diff options
Diffstat (limited to 'drivers/s390/crypto/ap_bus.c')
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 45 |
1 files changed, 39 insertions, 6 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 48ea0004a56d..cc30e4f07fff 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -116,7 +116,7 @@ static int user_set_domain; static struct bus_type ap_bus_type; /* Adapter interrupt definitions */ -static void ap_interrupt_handler(struct airq_struct *airq); +static void ap_interrupt_handler(struct airq_struct *airq, bool floating); static int ap_airq_flag; @@ -248,7 +248,8 @@ static inline int ap_test_config(unsigned int *field, unsigned int nr) static inline int ap_test_config_card_id(unsigned int id) { if (!ap_configuration) /* QCI not supported */ - return 1; + /* only ids 0...3F may be probed */ + return id < 0x40 ? 1 : 0; return ap_test_config(ap_configuration->apm, id); } @@ -392,7 +393,7 @@ static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused) * ap_interrupt_handler() - Schedule ap_tasklet on interrupt * @airq: pointer to adapter interrupt descriptor */ -static void ap_interrupt_handler(struct airq_struct *airq) +static void ap_interrupt_handler(struct airq_struct *airq, bool floating) { inc_irq_stat(IRQIO_APB); if (!ap_suspend_flag) @@ -809,11 +810,18 @@ 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; + /* prepare ap queue device removal */ if (is_queue_dev(dev)) - ap_queue_remove(to_ap_queue(dev)); + ap_queue_prepare_remove(to_ap_queue(dev)); + + /* driver's chance to clean up gracefully */ if (ap_drv->remove) ap_drv->remove(ap_dev); + /* now do the ap queue device remove */ + if (is_queue_dev(dev)) + ap_queue_remove(to_ap_queue(dev)); + /* Remove queue/card from list of active queues/cards */ spin_lock_bh(&ap_list_lock); if (is_card_dev(dev)) @@ -860,6 +868,16 @@ void ap_bus_force_rescan(void) EXPORT_SYMBOL(ap_bus_force_rescan); /* +* A config change has happened, force an ap bus rescan. +*/ +void ap_bus_cfg_chg(void) +{ + AP_DBF(DBF_INFO, "%s config change, forcing bus rescan\n", __func__); + + ap_bus_force_rescan(); +} + +/* * hex2bitmap() - parse hex mask string and set bitmap. * Valid strings are "0x012345678" with at least one valid hex number. * Rest of the bitmap to the right is padded with 0. No spaces allowed @@ -1335,6 +1353,16 @@ static int __match_queue_device_with_qid(struct device *dev, void *data) } /* + * Helper function to be used with bus_find_dev + * matches any queue device with given queue id + */ +static int __match_queue_device_with_queue_id(struct device *dev, void *data) +{ + return is_queue_dev(dev) + && AP_QID_QUEUE(to_ap_queue(dev)->qid) == (int)(long) data; +} + +/* * Helper function for ap_scan_bus(). * Does the scan bus job for the given adapter id. */ @@ -1434,8 +1462,13 @@ static void _ap_scan_bus_adapter(int id) borked = aq->state == AP_STATE_BORKED; spin_unlock_bh(&aq->lock); } - if (borked) /* Remove broken device */ + if (borked) { + /* Remove broken device */ + AP_DBF(DBF_DEBUG, + "removing broken queue=%02x.%04x\n", + id, dom); device_unregister(dev); + } put_device(dev); continue; } @@ -1505,7 +1538,7 @@ static void ap_scan_bus(struct work_struct *unused) struct device *dev = bus_find_device(&ap_bus_type, NULL, (void *)(long) ap_domain_index, - __match_queue_device_with_qid); + __match_queue_device_with_queue_id); if (dev) put_device(dev); else |