aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2012-01-09 13:12:52 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-29 16:20:01 -0500
commit45c73b65194173e77030d5b95abe5b63a402d268 (patch)
tree46e08c5fb11805dac6aa2008a3501dfee58f75c8 /drivers/scsi/libsas
parent5a998328296cb16cb8b0307a402a0f2feab533c5 (diff)
[SCSI] libsas: pre-clean commands that won the eh vs completion race
When scrolling forward through the eh list (in a clear_q scenario) it is possible to encounter commands that won the completion vs eh race. Rather than sprinkle more "if (!task)" throughout the handler just make a pass through the list and delete the race winners before handling the rest. Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/libsas')
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 94ef76316c31..731c89250639 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -249,8 +249,8 @@ out_done:
249 249
250static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) 250static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
251{ 251{
252 struct sas_task *task = TO_SAS_TASK(cmd);
253 struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host); 252 struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host);
253 struct sas_task *task = TO_SAS_TASK(cmd);
254 254
255 /* At this point, we only get called following an actual abort 255 /* At this point, we only get called following an actual abort
256 * of the task, so we should be guaranteed not to be racing with 256 * of the task, so we should be guaranteed not to be racing with
@@ -267,9 +267,9 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
267 267
268static void sas_eh_defer_cmd(struct scsi_cmnd *cmd) 268static void sas_eh_defer_cmd(struct scsi_cmnd *cmd)
269{ 269{
270 struct sas_task *task = TO_SAS_TASK(cmd); 270 struct domain_device *dev = cmd_to_domain_dev(cmd);
271 struct domain_device *dev = task->dev;
272 struct sas_ha_struct *ha = dev->port->ha; 271 struct sas_ha_struct *ha = dev->port->ha;
272 struct sas_task *task = TO_SAS_TASK(cmd);
273 273
274 if (!dev_is_sata(dev)) { 274 if (!dev_is_sata(dev)) {
275 sas_eh_finish_cmd(cmd); 275 sas_eh_finish_cmd(cmd);
@@ -530,8 +530,9 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost,
530 struct sas_internal *i = to_sas_internal(shost->transportt); 530 struct sas_internal *i = to_sas_internal(shost->transportt);
531 unsigned long flags; 531 unsigned long flags;
532 struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); 532 struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
533 LIST_HEAD(done);
533 534
534Again: 535 /* clean out any commands that won the completion vs eh race */
535 list_for_each_entry_safe(cmd, n, work_q, eh_entry) { 536 list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
536 struct domain_device *dev = cmd_to_domain_dev(cmd); 537 struct domain_device *dev = cmd_to_domain_dev(cmd);
537 struct sas_task *task; 538 struct sas_task *task;
@@ -545,7 +546,12 @@ Again:
545 spin_unlock_irqrestore(&dev->done_lock, flags); 546 spin_unlock_irqrestore(&dev->done_lock, flags);
546 547
547 if (!task) 548 if (!task)
548 continue; 549 list_move_tail(&cmd->eh_entry, &done);
550 }
551
552 Again:
553 list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
554 struct sas_task *task = TO_SAS_TASK(cmd);
549 555
550 list_del_init(&cmd->eh_entry); 556 list_del_init(&cmd->eh_entry);
551 557
@@ -649,15 +655,16 @@ Again:
649 goto clear_q; 655 goto clear_q;
650 } 656 }
651 } 657 }
658 out:
659 list_splice_tail(&done, work_q);
652 list_splice_tail_init(&ha->eh_ata_q, work_q); 660 list_splice_tail_init(&ha->eh_ata_q, work_q);
653 return list_empty(work_q); 661 return list_empty(work_q);
654clear_q: 662
663 clear_q:
655 SAS_DPRINTK("--- Exit %s -- clear_q\n", __func__); 664 SAS_DPRINTK("--- Exit %s -- clear_q\n", __func__);
656 list_for_each_entry_safe(cmd, n, work_q, eh_entry) 665 list_for_each_entry_safe(cmd, n, work_q, eh_entry)
657 sas_eh_finish_cmd(cmd); 666 sas_eh_finish_cmd(cmd);
658 667 goto out;
659 list_splice_tail_init(&ha->eh_ata_q, work_q);
660 return list_empty(work_q);
661} 668}
662 669
663void sas_scsi_recover_host(struct Scsi_Host *shost) 670void sas_scsi_recover_host(struct Scsi_Host *shost)