diff options
Diffstat (limited to 'drivers/s390/crypto/ap_bus.c')
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 59 |
1 files changed, 39 insertions, 20 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 9be4596d8a08..6dee598979e7 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -668,10 +668,28 @@ static int ap_device_probe(struct device *dev) struct ap_driver *ap_drv = to_ap_drv(dev->driver); int rc; + /* Add queue/card to list of active queues/cards */ + spin_lock_bh(&ap_list_lock); + if (is_card_dev(dev)) + list_add(&to_ap_card(dev)->list, &ap_card_list); + else + list_add(&to_ap_queue(dev)->list, + &to_ap_queue(dev)->card->queues); + spin_unlock_bh(&ap_list_lock); + ap_dev->drv = ap_drv; rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV; - if (rc) + + if (rc) { + spin_lock_bh(&ap_list_lock); + if (is_card_dev(dev)) + list_del_init(&to_ap_card(dev)->list); + else + list_del_init(&to_ap_queue(dev)->list); + spin_unlock_bh(&ap_list_lock); ap_dev->drv = NULL; + } + return rc; } @@ -680,14 +698,17 @@ static int ap_device_remove(struct device *dev) struct ap_device *ap_dev = to_ap_dev(dev); struct ap_driver *ap_drv = ap_dev->drv; + if (ap_drv->remove) + ap_drv->remove(ap_dev); + + /* Remove queue/card from list of active queues/cards */ spin_lock_bh(&ap_list_lock); if (is_card_dev(dev)) list_del_init(&to_ap_card(dev)->list); else list_del_init(&to_ap_queue(dev)->list); spin_unlock_bh(&ap_list_lock); - if (ap_drv->remove) - ap_drv->remove(ap_dev); + return 0; } @@ -745,7 +766,7 @@ static ssize_t ap_domain_store(struct bus_type *bus, ap_domain_index = domain; spin_unlock_bh(&ap_domain_lock); - AP_DBF(DBF_DEBUG, "store new default domain=%d\n", domain); + AP_DBF(DBF_DEBUG, "stored new default domain=%d\n", domain); return count; } @@ -931,6 +952,7 @@ static int ap_select_domain(void) } if (best_domain >= 0){ ap_domain_index = best_domain; + AP_DBF(DBF_DEBUG, "new ap_domain_index=%d\n", ap_domain_index); spin_unlock_bh(&ap_domain_lock); return 0; } @@ -967,7 +989,7 @@ static void ap_scan_bus(struct work_struct *unused) ap_qid_t qid; int depth = 0, type = 0; unsigned int functions = 0; - int rc, id, dom, borked, domains; + int rc, id, dom, borked, domains, defdomdevs = 0; AP_DBF(DBF_DEBUG, "ap_scan_bus running\n"); @@ -1031,6 +1053,8 @@ static void ap_scan_bus(struct work_struct *unused) put_device(dev); if (!borked) { domains++; + if (dom == ap_domain_index) + defdomdevs++; continue; } } @@ -1056,10 +1080,6 @@ static void ap_scan_bus(struct work_struct *unused) } /* get it and thus adjust reference counter */ get_device(&ac->ap_dev.device); - /* Add card device to card list */ - spin_lock_bh(&ap_list_lock); - list_add(&ac->list, &ap_card_list); - spin_unlock_bh(&ap_list_lock); } /* now create the new queue device */ aq = ap_queue_create(qid, type); @@ -1070,10 +1090,6 @@ static void ap_scan_bus(struct work_struct *unused) aq->ap_dev.device.parent = &ac->ap_dev.device; dev_set_name(&aq->ap_dev.device, "%02x.%04x", id, dom); - /* Add queue device to card queue list */ - spin_lock_bh(&ap_list_lock); - list_add(&aq->list, &ac->queues); - spin_unlock_bh(&ap_list_lock); /* Start with a device reset */ spin_lock_bh(&aq->lock); ap_wait(ap_sm_event(aq, AP_EVENT_POLL)); @@ -1081,13 +1097,12 @@ static void ap_scan_bus(struct work_struct *unused) /* Register device */ rc = device_register(&aq->ap_dev.device); if (rc) { - spin_lock_bh(&ap_list_lock); - list_del_init(&aq->list); - spin_unlock_bh(&ap_list_lock); put_device(&aq->ap_dev.device); continue; } domains++; + if (dom == ap_domain_index) + defdomdevs++; } /* end domain loop */ if (ac) { /* remove card dev if there are no queue devices */ @@ -1096,6 +1111,11 @@ static void ap_scan_bus(struct work_struct *unused) put_device(&ac->ap_dev.device); } } /* end device loop */ + + if (defdomdevs < 1) + AP_DBF(DBF_INFO, "no queue device with default domain %d available\n", + ap_domain_index); + out: mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ); } @@ -1164,14 +1184,14 @@ int __init ap_module_init(void) ap_init_configuration(); if (ap_configuration) - max_domain_id = ap_max_domain_id ? : (AP_DOMAINS - 1); + max_domain_id = + ap_max_domain_id ? ap_max_domain_id : AP_DOMAINS - 1; else max_domain_id = 15; if (ap_domain_index < -1 || ap_domain_index > max_domain_id) { pr_warn("%d is not a valid cryptographic domain\n", ap_domain_index); - rc = -EINVAL; - goto out_free; + ap_domain_index = -1; } /* In resume callback we need to know if the user had set the domain. * If so, we can not just reset it. @@ -1244,7 +1264,6 @@ out: unregister_reset_call(&ap_reset_call); if (ap_using_interrupts()) unregister_adapter_interrupt(&ap_airq); -out_free: kfree(ap_configuration); return rc; } |