Skip to content

Commit

Permalink
scsi: libsas: Use new workqueue to run sas event and disco event
Browse files Browse the repository at this point in the history
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 <[email protected]>
CC: John Garry <[email protected]>
CC: Johannes Thumshirn <[email protected]>
CC: Ewan Milne <[email protected]>
CC: Christoph Hellwig <[email protected]>
CC: Tomas Henzl <[email protected]>
CC: Dan Williams <[email protected]>
Signed-off-by: Jason Yan <[email protected]>
Reviewed-by: Hannes Reinecke <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
  • Loading branch information
JasonYanHw authored and martinkpetersen committed Jan 9, 2018
1 parent 8eea9dd commit 93bdbd0
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 4 deletions.
2 changes: 1 addition & 1 deletion drivers/scsi/libsas/sas_discover.c
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ static void sas_chain_work(struct sas_ha_struct *ha, struct sas_work *sw)
* workqueue, or known to be submitted from a context that is
* not racing against draining
*/
scsi_queue_work(ha->core.shost, &sw->work);
queue_work(ha->disco_q, &sw->work);
}

static void sas_chain_event(int event, unsigned long *pending,
Expand Down
6 changes: 3 additions & 3 deletions drivers/scsi/libsas/sas_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ 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;
}
Expand All @@ -61,7 +61,6 @@ static int sas_queue_event(int event, struct sas_work *work,

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;

Expand All @@ -70,7 +69,8 @@ void __sas_drain_work(struct sas_ha_struct *ha)
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);
Expand Down
18 changes: 18 additions & 0 deletions drivers/scsi/libsas/sas_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ void sas_hash_addr(u8 *hashed, const u8 *sas_addr)

int sas_register_ha(struct sas_ha_struct *sas_ha)
{
char name[64];
int error = 0;

mutex_init(&sas_ha->disco_mutex);
Expand Down Expand Up @@ -143,10 +144,24 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
goto Undo_ports;
}

error = -ENOMEM;
snprintf(name, sizeof(name), "%s_event_q", dev_name(sas_ha->dev));
sas_ha->event_q = create_singlethread_workqueue(name);
if (!sas_ha->event_q)
goto Undo_ports;

snprintf(name, sizeof(name), "%s_disco_q", dev_name(sas_ha->dev));
sas_ha->disco_q = create_singlethread_workqueue(name);
if (!sas_ha->disco_q)
goto Undo_event_q;

INIT_LIST_HEAD(&sas_ha->eh_done_q);
INIT_LIST_HEAD(&sas_ha->eh_ata_q);

return 0;

Undo_event_q:
destroy_workqueue(sas_ha->event_q);
Undo_ports:
sas_unregister_ports(sas_ha);
Undo_phys:
Expand Down Expand Up @@ -177,6 +192,9 @@ int sas_unregister_ha(struct sas_ha_struct *sas_ha)
__sas_drain_work(sas_ha);
mutex_unlock(&sas_ha->drain_mutex);

destroy_workqueue(sas_ha->disco_q);
destroy_workqueue(sas_ha->event_q);

return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions include/scsi/libsas.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,9 @@ struct sas_ha_struct {
struct device *dev; /* should be set */
struct module *lldd_module; /* should be set */

struct workqueue_struct *event_q;
struct workqueue_struct *disco_q;

u8 *sas_addr; /* must be set */
u8 hashed_sas_addr[HASHED_SAS_ADDR_SIZE];

Expand Down

0 comments on commit 93bdbd0

Please sign in to comment.