aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/pm8001/pm8001_hwi.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-01-24 08:57:29 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-02-12 11:31:03 -0500
commit429305e4650c5d3395c21ca183455a3f3e3568af (patch)
tree22f80762c0a2d3dcca39bde7aec19e5401a3d292 /drivers/scsi/pm8001/pm8001_hwi.c
parenta684b8da35a429a246ec2a91e2742bdff5209709 (diff)
[SCSI] pm8001: simplify workqueue usage
pm8001 manages its own list of pending works and cancel them on device free. It is unnecessarily complex and has a race condition - the works are canceled but not synced, so the work could still be running during and after the data structures are freed. This patch simplifies workqueue usage. * A driver specific workqueue pm8001_wq is created to serve these work items. * To avoid confusion, the "queue" suffixes are dropped from work items and functions. * Delayed queueing was never used. pm8001_work now uses work_struct instead. * The driver no longer keeps track of pending works. All pm8001_works are queued to pm8001_wq and the workqueue is flushed as necessary. flush_scheduled_work() usage is removed during conversion. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Jack Wang <jack_wang@usish.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/pm8001/pm8001_hwi.c')
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c37
1 files changed, 17 insertions, 20 deletions
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index d8db0137c0c..18b6c55cd08 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1382,53 +1382,50 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
1382 return MPI_IO_STATUS_BUSY; 1382 return MPI_IO_STATUS_BUSY;
1383} 1383}
1384 1384
1385static void pm8001_work_queue(struct work_struct *work) 1385static void pm8001_work_fn(struct work_struct *work)
1386{ 1386{
1387 struct delayed_work *dw = container_of(work, struct delayed_work, work); 1387 struct pm8001_work *pw = container_of(work, struct pm8001_work, work);
1388 struct pm8001_wq *wq = container_of(dw, struct pm8001_wq, work_q);
1389 struct pm8001_device *pm8001_dev; 1388 struct pm8001_device *pm8001_dev;
1390 struct domain_device *dev; 1389 struct domain_device *dev;
1391 1390
1392 switch (wq->handler) { 1391 switch (pw->handler) {
1393 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: 1392 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
1394 pm8001_dev = wq->data; 1393 pm8001_dev = pw->data;
1395 dev = pm8001_dev->sas_device; 1394 dev = pm8001_dev->sas_device;
1396 pm8001_I_T_nexus_reset(dev); 1395 pm8001_I_T_nexus_reset(dev);
1397 break; 1396 break;
1398 case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY: 1397 case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
1399 pm8001_dev = wq->data; 1398 pm8001_dev = pw->data;
1400 dev = pm8001_dev->sas_device; 1399 dev = pm8001_dev->sas_device;
1401 pm8001_I_T_nexus_reset(dev); 1400 pm8001_I_T_nexus_reset(dev);
1402 break; 1401 break;
1403 case IO_DS_IN_ERROR: 1402 case IO_DS_IN_ERROR:
1404 pm8001_dev = wq->data; 1403 pm8001_dev = pw->data;
1405 dev = pm8001_dev->sas_device; 1404 dev = pm8001_dev->sas_device;
1406 pm8001_I_T_nexus_reset(dev); 1405 pm8001_I_T_nexus_reset(dev);
1407 break; 1406 break;
1408 case IO_DS_NON_OPERATIONAL: 1407 case IO_DS_NON_OPERATIONAL:
1409 pm8001_dev = wq->data; 1408 pm8001_dev = pw->data;
1410 dev = pm8001_dev->sas_device; 1409 dev = pm8001_dev->sas_device;
1411 pm8001_I_T_nexus_reset(dev); 1410 pm8001_I_T_nexus_reset(dev);
1412 break; 1411 break;
1413 } 1412 }
1414 list_del(&wq->entry); 1413 kfree(pw);
1415 kfree(wq);
1416} 1414}
1417 1415
1418static int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data, 1416static int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data,
1419 int handler) 1417 int handler)
1420{ 1418{
1421 struct pm8001_wq *wq; 1419 struct pm8001_work *pw;
1422 int ret = 0; 1420 int ret = 0;
1423 1421
1424 wq = kmalloc(sizeof(struct pm8001_wq), GFP_ATOMIC); 1422 pw = kmalloc(sizeof(struct pm8001_work), GFP_ATOMIC);
1425 if (wq) { 1423 if (pw) {
1426 wq->pm8001_ha = pm8001_ha; 1424 pw->pm8001_ha = pm8001_ha;
1427 wq->data = data; 1425 pw->data = data;
1428 wq->handler = handler; 1426 pw->handler = handler;
1429 INIT_DELAYED_WORK(&wq->work_q, pm8001_work_queue); 1427 INIT_WORK(&pw->work, pm8001_work_fn);
1430 list_add_tail(&wq->entry, &pm8001_ha->wq_list); 1428 queue_work(pm8001_wq, &pw->work);
1431 schedule_delayed_work(&wq->work_q, 0);
1432 } else 1429 } else
1433 ret = -ENOMEM; 1430 ret = -ENOMEM;
1434 1431