diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-31 20:23:28 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-31 20:23:28 +0100 |
commit | 28bc6fb9596fe1e577d09fc17ee6e1bb051c6ba3 (patch) | |
tree | 6293b282a960720fc5008e3e5fa4d096d974b2f1 /drivers/scsi/libsas/sas_event.c | |
parent | Merge tag 'for-4.16/dm-changes' of git://git.kernel.org/pub/scm/linux/kernel/... (diff) | |
parent | scsi: qla2xxx: Fix logo flag for qlt_free_session_done() (diff) | |
download | linux-28bc6fb9596fe1e577d09fc17ee6e1bb051c6ba3.tar.xz linux-28bc6fb9596fe1e577d09fc17ee6e1bb051c6ba3.zip |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"This is mostly updates of the usual driver suspects: arcmsr,
scsi_debug, mpt3sas, lpfc, cxlflash, qla2xxx, aacraid, megaraid_sas,
hisi_sas.
We also have a rework of the libsas hotplug handling to make it more
robust, a slew of 32 bit time conversions and fixes, and a host of the
usual minor updates and style changes. The biggest potential for
regressions is the libsas hotplug changes, but so far they seem stable
under testing"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (313 commits)
scsi: qla2xxx: Fix logo flag for qlt_free_session_done()
scsi: arcmsr: avoid do_gettimeofday
scsi: core: Add VENDOR_SPECIFIC sense code definitions
scsi: qedi: Drop cqe response during connection recovery
scsi: fas216: fix sense buffer initialization
scsi: ibmvfc: Remove unneeded semicolons
scsi: hisi_sas: fix a bug in hisi_sas_dev_gone()
scsi: hisi_sas: directly attached disk LED feature for v2 hw
scsi: hisi_sas: devicetree: bindings: add LED feature for v2 hw
scsi: megaraid_sas: NVMe passthrough command support
scsi: megaraid: use ktime_get_real for firmware time
scsi: fnic: use 64-bit timestamps
scsi: qedf: Fix error return code in __qedf_probe()
scsi: devinfo: fix format of the device list
scsi: qla2xxx: Update driver version to 10.00.00.05-k
scsi: qla2xxx: Add XCB counters to debugfs
scsi: qla2xxx: Fix queue ID for async abort with Multiqueue
scsi: qla2xxx: Fix warning for code intentation in __qla24xx_handle_gpdb_event()
scsi: qla2xxx: Fix warning during port_name debug print
scsi: qla2xxx: Fix warning in qla2x00_async_iocb_timeout()
...
Diffstat (limited to 'drivers/scsi/libsas/sas_event.c')
-rw-r--r-- | drivers/scsi/libsas/sas_event.c | 86 |
1 files changed, 66 insertions, 20 deletions
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c index 0bb9eefc08c8..ae923eb6de95 100644 --- a/drivers/scsi/libsas/sas_event.c +++ b/drivers/scsi/libsas/sas_event.c @@ -29,7 +29,8 @@ int sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw) { - int rc = 0; + /* it's added to the defer_q when draining so return succeed */ + int rc = 1; if (!test_bit(SAS_HA_REGISTERED, &ha->state)) return 0; @@ -39,24 +40,20 @@ int sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw) if (list_empty(&sw->drain_node)) list_add_tail(&sw->drain_node, &ha->defer_q); } else - rc = scsi_queue_work(ha->core.shost, &sw->work); + rc = queue_work(ha->event_q, &sw->work); return rc; } -static int sas_queue_event(int event, unsigned long *pending, - struct sas_work *work, +static int sas_queue_event(int event, struct sas_work *work, struct sas_ha_struct *ha) { - int rc = 0; + unsigned long flags; + int rc; - if (!test_and_set_bit(event, pending)) { - unsigned long flags; - - spin_lock_irqsave(&ha->lock, flags); - rc = sas_queue_work(ha, work); - spin_unlock_irqrestore(&ha->lock, flags); - } + spin_lock_irqsave(&ha->lock, flags); + rc = sas_queue_work(ha, work); + spin_unlock_irqrestore(&ha->lock, flags); return rc; } @@ -64,21 +61,25 @@ static int sas_queue_event(int event, unsigned long *pending, void __sas_drain_work(struct sas_ha_struct *ha) { - struct workqueue_struct *wq = ha->core.shost->work_q; struct sas_work *sw, *_sw; + int ret; set_bit(SAS_HA_DRAINING, &ha->state); /* flush submitters */ spin_lock_irq(&ha->lock); spin_unlock_irq(&ha->lock); - drain_workqueue(wq); + drain_workqueue(ha->event_q); + drain_workqueue(ha->disco_q); spin_lock_irq(&ha->lock); clear_bit(SAS_HA_DRAINING, &ha->state); list_for_each_entry_safe(sw, _sw, &ha->defer_q, drain_node) { list_del_init(&sw->drain_node); - sas_queue_work(ha, sw); + ret = sas_queue_work(ha, sw); + if (ret != 1) + sas_free_event(to_asd_sas_event(&sw->work)); + } spin_unlock_irq(&ha->lock); } @@ -115,33 +116,78 @@ void sas_enable_revalidation(struct sas_ha_struct *ha) struct asd_sas_port *port = ha->sas_port[i]; const int ev = DISCE_REVALIDATE_DOMAIN; struct sas_discovery *d = &port->disc; + struct asd_sas_phy *sas_phy; if (!test_and_clear_bit(ev, &d->pending)) continue; - sas_queue_event(ev, &d->pending, &d->disc_work[ev].work, ha); + if (list_empty(&port->phy_list)) + continue; + + sas_phy = container_of(port->phy_list.next, struct asd_sas_phy, + port_phy_el); + ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); } mutex_unlock(&ha->disco_mutex); } + +static void sas_port_event_worker(struct work_struct *work) +{ + struct asd_sas_event *ev = to_asd_sas_event(work); + + sas_port_event_fns[ev->event](work); + sas_free_event(ev); +} + +static void sas_phy_event_worker(struct work_struct *work) +{ + struct asd_sas_event *ev = to_asd_sas_event(work); + + sas_phy_event_fns[ev->event](work); + sas_free_event(ev); +} + static int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event) { + struct asd_sas_event *ev; struct sas_ha_struct *ha = phy->ha; + int ret; BUG_ON(event >= PORT_NUM_EVENTS); - return sas_queue_event(event, &phy->port_events_pending, - &phy->port_events[event].work, ha); + ev = sas_alloc_event(phy); + if (!ev) + return -ENOMEM; + + INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event); + + ret = sas_queue_event(event, &ev->work, ha); + if (ret != 1) + sas_free_event(ev); + + return ret; } int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) { + struct asd_sas_event *ev; struct sas_ha_struct *ha = phy->ha; + int ret; BUG_ON(event >= PHY_NUM_EVENTS); - return sas_queue_event(event, &phy->phy_events_pending, - &phy->phy_events[event].work, ha); + ev = sas_alloc_event(phy); + if (!ev) + return -ENOMEM; + + INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event); + + ret = sas_queue_event(event, &ev->work, ha); + if (ret != 1) + sas_free_event(ev); + + return ret; } int sas_init_events(struct sas_ha_struct *sas_ha) |