aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Yan <yanaijie@huawei.com>2017-12-08 04:42:07 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2018-01-08 21:59:28 -0500
commit93bdbd06b1644ac15aa152e91faefed86cc04937 (patch)
tree4f71a02f4e6c671716f68b4f267f0728a0f2ceb3
parent8eea9dd84e450e5262643823691108f2a208a2ac (diff)
scsi: libsas: Use new workqueue to run sas event and disco event
Now all libsas works are queued to scsi host workqueue, include sas event work post by LLDD and sas discovery work, and a sas hotplug flow may be divided into several works, e.g libsas receive a PORTE_BYTES_DMAED event, currently we process it as following steps: sas_form_port --- run in work in shost workq sas_discover_domain --- run in another work in shost workq ... sas_probe_devices --- run in new work in shost workq We found during hot-add a device, libsas may need run several works in same workqueue to add device in system, the process is not atomic, it may interrupt by other sas event works, like PHYE_LOSS_OF_SIGNAL. This patch is preparation of execute libsas sas event in sync. We need to use different workqueue to run sas event and disco event. Otherwise the work will be blocked for waiting another chained work in the same workqueue. Signed-off-by: Yijing Wang <wangyijing@huawei.com> CC: John Garry <john.garry@huawei.com> CC: Johannes Thumshirn <jthumshirn@suse.de> CC: Ewan Milne <emilne@redhat.com> CC: Christoph Hellwig <hch@lst.de> CC: Tomas Henzl <thenzl@redhat.com> CC: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Jason Yan <yanaijie@huawei.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/libsas/sas_discover.c2
-rw-r--r--drivers/scsi/libsas/sas_event.c6
-rw-r--r--drivers/scsi/libsas/sas_init.c18
-rw-r--r--include/scsi/libsas.h3
4 files changed, 25 insertions, 4 deletions
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index 60de66252fa2..14f714d05767 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -534,7 +534,7 @@ static void sas_chain_work(struct sas_ha_struct *ha, struct sas_work *sw)
534 * workqueue, or known to be submitted from a context that is 534 * workqueue, or known to be submitted from a context that is
535 * not racing against draining 535 * not racing against draining
536 */ 536 */
537 scsi_queue_work(ha->core.shost, &sw->work); 537 queue_work(ha->disco_q, &sw->work);
538} 538}
539 539
540static void sas_chain_event(int event, unsigned long *pending, 540static void sas_chain_event(int event, unsigned long *pending,
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index 5d7254aa2dd2..8c82c007763d 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -40,7 +40,7 @@ int sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw)
40 if (list_empty(&sw->drain_node)) 40 if (list_empty(&sw->drain_node))
41 list_add_tail(&sw->drain_node, &ha->defer_q); 41 list_add_tail(&sw->drain_node, &ha->defer_q);
42 } else 42 } else
43 rc = scsi_queue_work(ha->core.shost, &sw->work); 43 rc = queue_work(ha->event_q, &sw->work);
44 44
45 return rc; 45 return rc;
46} 46}
@@ -61,7 +61,6 @@ static int sas_queue_event(int event, struct sas_work *work,
61 61
62void __sas_drain_work(struct sas_ha_struct *ha) 62void __sas_drain_work(struct sas_ha_struct *ha)
63{ 63{
64 struct workqueue_struct *wq = ha->core.shost->work_q;
65 struct sas_work *sw, *_sw; 64 struct sas_work *sw, *_sw;
66 int ret; 65 int ret;
67 66
@@ -70,7 +69,8 @@ void __sas_drain_work(struct sas_ha_struct *ha)
70 spin_lock_irq(&ha->lock); 69 spin_lock_irq(&ha->lock);
71 spin_unlock_irq(&ha->lock); 70 spin_unlock_irq(&ha->lock);
72 71
73 drain_workqueue(wq); 72 drain_workqueue(ha->event_q);
73 drain_workqueue(ha->disco_q);
74 74
75 spin_lock_irq(&ha->lock); 75 spin_lock_irq(&ha->lock);
76 clear_bit(SAS_HA_DRAINING, &ha->state); 76 clear_bit(SAS_HA_DRAINING, &ha->state);
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index afd928bf903e..c81a63b5dc71 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -110,6 +110,7 @@ void sas_hash_addr(u8 *hashed, const u8 *sas_addr)
110 110
111int sas_register_ha(struct sas_ha_struct *sas_ha) 111int sas_register_ha(struct sas_ha_struct *sas_ha)
112{ 112{
113 char name[64];
113 int error = 0; 114 int error = 0;
114 115
115 mutex_init(&sas_ha->disco_mutex); 116 mutex_init(&sas_ha->disco_mutex);
@@ -143,10 +144,24 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
143 goto Undo_ports; 144 goto Undo_ports;
144 } 145 }
145 146
147 error = -ENOMEM;
148 snprintf(name, sizeof(name), "%s_event_q", dev_name(sas_ha->dev));
149 sas_ha->event_q = create_singlethread_workqueue(name);
150 if (!sas_ha->event_q)
151 goto Undo_ports;
152
153 snprintf(name, sizeof(name), "%s_disco_q", dev_name(sas_ha->dev));
154 sas_ha->disco_q = create_singlethread_workqueue(name);
155 if (!sas_ha->disco_q)
156 goto Undo_event_q;
157
146 INIT_LIST_HEAD(&sas_ha->eh_done_q); 158 INIT_LIST_HEAD(&sas_ha->eh_done_q);
147 INIT_LIST_HEAD(&sas_ha->eh_ata_q); 159 INIT_LIST_HEAD(&sas_ha->eh_ata_q);
148 160
149 return 0; 161 return 0;
162
163Undo_event_q:
164 destroy_workqueue(sas_ha->event_q);
150Undo_ports: 165Undo_ports:
151 sas_unregister_ports(sas_ha); 166 sas_unregister_ports(sas_ha);
152Undo_phys: 167Undo_phys:
@@ -177,6 +192,9 @@ int sas_unregister_ha(struct sas_ha_struct *sas_ha)
177 __sas_drain_work(sas_ha); 192 __sas_drain_work(sas_ha);
178 mutex_unlock(&sas_ha->drain_mutex); 193 mutex_unlock(&sas_ha->drain_mutex);
179 194
195 destroy_workqueue(sas_ha->disco_q);
196 destroy_workqueue(sas_ha->event_q);
197
180 return 0; 198 return 0;
181} 199}
182 200
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 3769615d4ce9..6255bb5ed1e4 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -389,6 +389,9 @@ struct sas_ha_struct {
389 struct device *dev; /* should be set */ 389 struct device *dev; /* should be set */
390 struct module *lldd_module; /* should be set */ 390 struct module *lldd_module; /* should be set */
391 391
392 struct workqueue_struct *event_q;
393 struct workqueue_struct *disco_q;
394
392 u8 *sas_addr; /* must be set */ 395 u8 *sas_addr; /* must be set */
393 u8 hashed_sas_addr[HASHED_SAS_ADDR_SIZE]; 396 u8 hashed_sas_addr[HASHED_SAS_ADDR_SIZE];
394 397