aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_scsi_host.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libsas/sas_scsi_host.c')
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c290
1 files changed, 215 insertions, 75 deletions
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 22672d54aa27..897a5e2c55e4 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -34,6 +34,7 @@
34#include <scsi/scsi_transport_sas.h> 34#include <scsi/scsi_transport_sas.h>
35#include "../scsi_sas_internal.h" 35#include "../scsi_sas_internal.h"
36#include "../scsi_transport_api.h" 36#include "../scsi_transport_api.h"
37#include "../scsi_priv.h"
37 38
38#include <linux/err.h> 39#include <linux/err.h>
39#include <linux/blkdev.h> 40#include <linux/blkdev.h>
@@ -130,7 +131,7 @@ static enum task_attribute sas_scsi_get_task_attr(struct scsi_cmnd *cmd)
130 if (cmd->request && blk_rq_tagged(cmd->request)) { 131 if (cmd->request && blk_rq_tagged(cmd->request)) {
131 if (cmd->device->ordered_tags && 132 if (cmd->device->ordered_tags &&
132 (cmd->request->cmd_flags & REQ_HARDBARRIER)) 133 (cmd->request->cmd_flags & REQ_HARDBARRIER))
133 ta = TASK_ATTR_HOQ; 134 ta = TASK_ATTR_ORDERED;
134 } 135 }
135 return ta; 136 return ta;
136} 137}
@@ -281,6 +282,7 @@ enum task_disposition {
281 TASK_IS_ABORTED, 282 TASK_IS_ABORTED,
282 TASK_IS_AT_LU, 283 TASK_IS_AT_LU,
283 TASK_IS_NOT_AT_LU, 284 TASK_IS_NOT_AT_LU,
285 TASK_ABORT_FAILED,
284}; 286};
285 287
286static enum task_disposition sas_scsi_find_task(struct sas_task *task) 288static enum task_disposition sas_scsi_find_task(struct sas_task *task)
@@ -310,15 +312,6 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task)
310 spin_unlock_irqrestore(&core->task_queue_lock, flags); 312 spin_unlock_irqrestore(&core->task_queue_lock, flags);
311 } 313 }
312 314
313 spin_lock_irqsave(&task->task_state_lock, flags);
314 if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) {
315 spin_unlock_irqrestore(&task->task_state_lock, flags);
316 SAS_DPRINTK("%s: task 0x%p already aborted\n",
317 __FUNCTION__, task);
318 return TASK_IS_ABORTED;
319 }
320 spin_unlock_irqrestore(&task->task_state_lock, flags);
321
322 for (i = 0; i < 5; i++) { 315 for (i = 0; i < 5; i++) {
323 SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task); 316 SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task);
324 res = si->dft->lldd_abort_task(task); 317 res = si->dft->lldd_abort_task(task);
@@ -340,15 +333,21 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task)
340 SAS_DPRINTK("%s: querying task 0x%p\n", 333 SAS_DPRINTK("%s: querying task 0x%p\n",
341 __FUNCTION__, task); 334 __FUNCTION__, task);
342 res = si->dft->lldd_query_task(task); 335 res = si->dft->lldd_query_task(task);
343 if (res == TMF_RESP_FUNC_SUCC) { 336 switch (res) {
337 case TMF_RESP_FUNC_SUCC:
344 SAS_DPRINTK("%s: task 0x%p at LU\n", 338 SAS_DPRINTK("%s: task 0x%p at LU\n",
345 __FUNCTION__, task); 339 __FUNCTION__, task);
346 return TASK_IS_AT_LU; 340 return TASK_IS_AT_LU;
347 } else if (res == TMF_RESP_FUNC_COMPLETE) { 341 case TMF_RESP_FUNC_COMPLETE:
348 SAS_DPRINTK("%s: task 0x%p not at LU\n", 342 SAS_DPRINTK("%s: task 0x%p not at LU\n",
349 __FUNCTION__, task); 343 __FUNCTION__, task);
350 return TASK_IS_NOT_AT_LU; 344 return TASK_IS_NOT_AT_LU;
351 } 345 case TMF_RESP_FUNC_FAILED:
346 SAS_DPRINTK("%s: task 0x%p failed to abort\n",
347 __FUNCTION__, task);
348 return TASK_ABORT_FAILED;
349 }
350
352 } 351 }
353 } 352 }
354 return res; 353 return res;
@@ -398,35 +397,113 @@ static int sas_recover_I_T(struct domain_device *dev)
398 return res; 397 return res;
399} 398}
400 399
401void sas_scsi_recover_host(struct Scsi_Host *shost) 400/* Find the sas_phy that's attached to this device */
401struct sas_phy *find_local_sas_phy(struct domain_device *dev)
402{
403 struct domain_device *pdev = dev->parent;
404 struct ex_phy *exphy = NULL;
405 int i;
406
407 /* Directly attached device */
408 if (!pdev)
409 return dev->port->phy;
410
411 /* Otherwise look in the expander */
412 for (i = 0; i < pdev->ex_dev.num_phys; i++)
413 if (!memcmp(dev->sas_addr,
414 pdev->ex_dev.ex_phy[i].attached_sas_addr,
415 SAS_ADDR_SIZE)) {
416 exphy = &pdev->ex_dev.ex_phy[i];
417 break;
418 }
419
420 BUG_ON(!exphy);
421 return exphy->phy;
422}
423
424/* Attempt to send a LUN reset message to a device */
425int sas_eh_device_reset_handler(struct scsi_cmnd *cmd)
426{
427 struct domain_device *dev = cmd_to_domain_dev(cmd);
428 struct sas_internal *i =
429 to_sas_internal(dev->port->ha->core.shost->transportt);
430 struct scsi_lun lun;
431 int res;
432
433 int_to_scsilun(cmd->device->lun, &lun);
434
435 if (!i->dft->lldd_lu_reset)
436 return FAILED;
437
438 res = i->dft->lldd_lu_reset(dev, lun.scsi_lun);
439 if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE)
440 return SUCCESS;
441
442 return FAILED;
443}
444
445/* Attempt to send a phy (bus) reset */
446int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd)
447{
448 struct domain_device *dev = cmd_to_domain_dev(cmd);
449 struct sas_phy *phy = find_local_sas_phy(dev);
450 int res;
451
452 res = sas_phy_reset(phy, 1);
453 if (res)
454 SAS_DPRINTK("Bus reset of %s failed 0x%x\n",
455 phy->dev.kobj.k_name,
456 res);
457 if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE)
458 return SUCCESS;
459
460 return FAILED;
461}
462
463/* Try to reset a device */
464static int try_to_reset_cmd_device(struct Scsi_Host *shost,
465 struct scsi_cmnd *cmd)
466{
467 int res;
468
469 if (!shost->hostt->eh_device_reset_handler)
470 goto try_bus_reset;
471
472 res = shost->hostt->eh_device_reset_handler(cmd);
473 if (res == SUCCESS)
474 return res;
475
476try_bus_reset:
477 if (shost->hostt->eh_bus_reset_handler)
478 return shost->hostt->eh_bus_reset_handler(cmd);
479
480 return FAILED;
481}
482
483static int sas_eh_handle_sas_errors(struct Scsi_Host *shost,
484 struct list_head *work_q,
485 struct list_head *done_q)
402{ 486{
403 struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
404 unsigned long flags;
405 LIST_HEAD(error_q);
406 struct scsi_cmnd *cmd, *n; 487 struct scsi_cmnd *cmd, *n;
407 enum task_disposition res = TASK_IS_DONE; 488 enum task_disposition res = TASK_IS_DONE;
408 int tmf_resp; 489 int tmf_resp, need_reset;
409 struct sas_internal *i = to_sas_internal(shost->transportt); 490 struct sas_internal *i = to_sas_internal(shost->transportt);
491 unsigned long flags;
492 struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
410 493
411 spin_lock_irqsave(shost->host_lock, flags);
412 list_splice_init(&shost->eh_cmd_q, &error_q);
413 spin_unlock_irqrestore(shost->host_lock, flags);
414
415 SAS_DPRINTK("Enter %s\n", __FUNCTION__);
416
417 /* All tasks on this list were marked SAS_TASK_STATE_ABORTED
418 * by sas_scsi_timed_out() callback.
419 */
420Again: 494Again:
421 SAS_DPRINTK("going over list...\n"); 495 list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
422 list_for_each_entry_safe(cmd, n, &error_q, eh_entry) {
423 struct sas_task *task = TO_SAS_TASK(cmd); 496 struct sas_task *task = TO_SAS_TASK(cmd);
424 list_del_init(&cmd->eh_entry);
425 497
426 if (!task) { 498 if (!task)
427 SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__);
428 continue; 499 continue;
429 } 500
501 list_del_init(&cmd->eh_entry);
502
503 spin_lock_irqsave(&task->task_state_lock, flags);
504 need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET;
505 spin_unlock_irqrestore(&task->task_state_lock, flags);
506
430 SAS_DPRINTK("trying to find task 0x%p\n", task); 507 SAS_DPRINTK("trying to find task 0x%p\n", task);
431 res = sas_scsi_find_task(task); 508 res = sas_scsi_find_task(task);
432 509
@@ -437,11 +514,15 @@ Again:
437 SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, 514 SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__,
438 task); 515 task);
439 task->task_done(task); 516 task->task_done(task);
517 if (need_reset)
518 try_to_reset_cmd_device(shost, cmd);
440 continue; 519 continue;
441 case TASK_IS_ABORTED: 520 case TASK_IS_ABORTED:
442 SAS_DPRINTK("%s: task 0x%p is aborted\n", 521 SAS_DPRINTK("%s: task 0x%p is aborted\n",
443 __FUNCTION__, task); 522 __FUNCTION__, task);
444 task->task_done(task); 523 task->task_done(task);
524 if (need_reset)
525 try_to_reset_cmd_device(shost, cmd);
445 continue; 526 continue;
446 case TASK_IS_AT_LU: 527 case TASK_IS_AT_LU:
447 SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); 528 SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
@@ -452,11 +533,14 @@ Again:
452 SAS_ADDR(task->dev), 533 SAS_ADDR(task->dev),
453 cmd->device->lun); 534 cmd->device->lun);
454 task->task_done(task); 535 task->task_done(task);
455 sas_scsi_clear_queue_lu(&error_q, cmd); 536 if (need_reset)
537 try_to_reset_cmd_device(shost, cmd);
538 sas_scsi_clear_queue_lu(work_q, cmd);
456 goto Again; 539 goto Again;
457 } 540 }
458 /* fallthrough */ 541 /* fallthrough */
459 case TASK_IS_NOT_AT_LU: 542 case TASK_IS_NOT_AT_LU:
543 case TASK_ABORT_FAILED:
460 SAS_DPRINTK("task 0x%p is not at LU: I_T recover\n", 544 SAS_DPRINTK("task 0x%p is not at LU: I_T recover\n",
461 task); 545 task);
462 tmf_resp = sas_recover_I_T(task->dev); 546 tmf_resp = sas_recover_I_T(task->dev);
@@ -464,7 +548,9 @@ Again:
464 SAS_DPRINTK("I_T %016llx recovered\n", 548 SAS_DPRINTK("I_T %016llx recovered\n",
465 SAS_ADDR(task->dev->sas_addr)); 549 SAS_ADDR(task->dev->sas_addr));
466 task->task_done(task); 550 task->task_done(task);
467 sas_scsi_clear_queue_I_T(&error_q, task->dev); 551 if (need_reset)
552 try_to_reset_cmd_device(shost, cmd);
553 sas_scsi_clear_queue_I_T(work_q, task->dev);
468 goto Again; 554 goto Again;
469 } 555 }
470 /* Hammer time :-) */ 556 /* Hammer time :-) */
@@ -477,7 +563,9 @@ Again:
477 SAS_DPRINTK("clear nexus port:%d " 563 SAS_DPRINTK("clear nexus port:%d "
478 "succeeded\n", port->id); 564 "succeeded\n", port->id);
479 task->task_done(task); 565 task->task_done(task);
480 sas_scsi_clear_queue_port(&error_q, 566 if (need_reset)
567 try_to_reset_cmd_device(shost, cmd);
568 sas_scsi_clear_queue_port(work_q,
481 port); 569 port);
482 goto Again; 570 goto Again;
483 } 571 }
@@ -489,6 +577,8 @@ Again:
489 SAS_DPRINTK("clear nexus ha " 577 SAS_DPRINTK("clear nexus ha "
490 "succeeded\n"); 578 "succeeded\n");
491 task->task_done(task); 579 task->task_done(task);
580 if (need_reset)
581 try_to_reset_cmd_device(shost, cmd);
492 goto out; 582 goto out;
493 } 583 }
494 } 584 }
@@ -502,20 +592,54 @@ Again:
502 cmd->device->lun); 592 cmd->device->lun);
503 593
504 task->task_done(task); 594 task->task_done(task);
595 if (need_reset)
596 try_to_reset_cmd_device(shost, cmd);
505 goto clear_q; 597 goto clear_q;
506 } 598 }
507 } 599 }
508out: 600out:
509 scsi_eh_flush_done_q(&ha->eh_done_q); 601 return list_empty(work_q);
510 SAS_DPRINTK("--- Exit %s\n", __FUNCTION__);
511 return;
512clear_q: 602clear_q:
513 SAS_DPRINTK("--- Exit %s -- clear_q\n", __FUNCTION__); 603 SAS_DPRINTK("--- Exit %s -- clear_q\n", __FUNCTION__);
514 list_for_each_entry_safe(cmd, n, &error_q, eh_entry) { 604 list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
515 struct sas_task *task = TO_SAS_TASK(cmd); 605 struct sas_task *task = TO_SAS_TASK(cmd);
516 list_del_init(&cmd->eh_entry); 606 list_del_init(&cmd->eh_entry);
517 task->task_done(task); 607 task->task_done(task);
518 } 608 }
609 return list_empty(work_q);
610}
611
612void sas_scsi_recover_host(struct Scsi_Host *shost)
613{
614 struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
615 unsigned long flags;
616 LIST_HEAD(eh_work_q);
617
618 spin_lock_irqsave(shost->host_lock, flags);
619 list_splice_init(&shost->eh_cmd_q, &eh_work_q);
620 spin_unlock_irqrestore(shost->host_lock, flags);
621
622 SAS_DPRINTK("Enter %s\n", __FUNCTION__);
623 /*
624 * Deal with commands that still have SAS tasks (i.e. they didn't
625 * complete via the normal sas_task completion mechanism)
626 */
627 if (sas_eh_handle_sas_errors(shost, &eh_work_q, &ha->eh_done_q))
628 goto out;
629
630 /*
631 * Now deal with SCSI commands that completed ok but have a an error
632 * code (and hopefully sense data) attached. This is roughly what
633 * scsi_unjam_host does, but we skip scsi_eh_abort_cmds because any
634 * command we see here has no sas_task and is thus unknown to the HA.
635 */
636 if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q))
637 scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
638
639out:
640 scsi_eh_flush_done_q(&ha->eh_done_q);
641 SAS_DPRINTK("--- Exit %s\n", __FUNCTION__);
642 return;
519} 643}
520 644
521enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) 645enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
@@ -524,24 +648,30 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
524 unsigned long flags; 648 unsigned long flags;
525 649
526 if (!task) { 650 if (!task) {
527 SAS_DPRINTK("command 0x%p, task 0x%p, gone: EH_HANDLED\n", 651 cmd->timeout_per_command /= 2;
528 cmd, task); 652 SAS_DPRINTK("command 0x%p, task 0x%p, gone: %s\n",
529 return EH_HANDLED; 653 cmd, task, (cmd->timeout_per_command ?
654 "EH_RESET_TIMER" : "EH_NOT_HANDLED"));
655 if (!cmd->timeout_per_command)
656 return EH_NOT_HANDLED;
657 return EH_RESET_TIMER;
530 } 658 }
531 659
532 spin_lock_irqsave(&task->task_state_lock, flags); 660 spin_lock_irqsave(&task->task_state_lock, flags);
533 if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) { 661 BUG_ON(task->task_state_flags & SAS_TASK_STATE_ABORTED);
534 spin_unlock_irqrestore(&task->task_state_lock, flags);
535 SAS_DPRINTK("command 0x%p, task 0x%p, aborted by initiator: "
536 "EH_NOT_HANDLED\n", cmd, task);
537 return EH_NOT_HANDLED;
538 }
539 if (task->task_state_flags & SAS_TASK_STATE_DONE) { 662 if (task->task_state_flags & SAS_TASK_STATE_DONE) {
540 spin_unlock_irqrestore(&task->task_state_lock, flags); 663 spin_unlock_irqrestore(&task->task_state_lock, flags);
541 SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", 664 SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n",
542 cmd, task); 665 cmd, task);
543 return EH_HANDLED; 666 return EH_HANDLED;
544 } 667 }
668 if (!(task->task_state_flags & SAS_TASK_AT_INITIATOR)) {
669 spin_unlock_irqrestore(&task->task_state_lock, flags);
670 SAS_DPRINTK("command 0x%p, task 0x%p, not at initiator: "
671 "EH_RESET_TIMER\n",
672 cmd, task);
673 return EH_RESET_TIMER;
674 }
545 task->task_state_flags |= SAS_TASK_STATE_ABORTED; 675 task->task_state_flags |= SAS_TASK_STATE_ABORTED;
546 spin_unlock_irqrestore(&task->task_state_lock, flags); 676 spin_unlock_irqrestore(&task->task_state_lock, flags);
547 677
@@ -557,8 +687,9 @@ struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy)
557 struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); 687 struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
558 struct domain_device *found_dev = NULL; 688 struct domain_device *found_dev = NULL;
559 int i; 689 int i;
690 unsigned long flags;
560 691
561 spin_lock(&ha->phy_port_lock); 692 spin_lock_irqsave(&ha->phy_port_lock, flags);
562 for (i = 0; i < ha->num_phys; i++) { 693 for (i = 0; i < ha->num_phys; i++) {
563 struct asd_sas_port *port = ha->sas_port[i]; 694 struct asd_sas_port *port = ha->sas_port[i];
564 struct domain_device *dev; 695 struct domain_device *dev;
@@ -574,7 +705,7 @@ struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy)
574 spin_unlock(&port->dev_list_lock); 705 spin_unlock(&port->dev_list_lock);
575 } 706 }
576 found: 707 found:
577 spin_unlock(&ha->phy_port_lock); 708 spin_unlock_irqrestore(&ha->phy_port_lock, flags);
578 709
579 return found_dev; 710 return found_dev;
580} 711}
@@ -623,6 +754,8 @@ int sas_slave_configure(struct scsi_device *scsi_dev)
623 scsi_deactivate_tcq(scsi_dev, 1); 754 scsi_deactivate_tcq(scsi_dev, 1);
624 } 755 }
625 756
757 scsi_dev->allow_restart = 1;
758
626 return 0; 759 return 0;
627} 760}
628 761
@@ -799,46 +932,42 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha)
799 spin_unlock_irqrestore(&core->task_queue_lock, flags); 932 spin_unlock_irqrestore(&core->task_queue_lock, flags);
800} 933}
801 934
802static int do_sas_task_abort(struct sas_task *task) 935/*
936 * Call the LLDD task abort routine directly. This function is intended for
937 * use by upper layers that need to tell the LLDD to abort a task.
938 */
939int __sas_task_abort(struct sas_task *task)
803{ 940{
804 struct scsi_cmnd *sc = task->uldd_task;
805 struct sas_internal *si = 941 struct sas_internal *si =
806 to_sas_internal(task->dev->port->ha->core.shost->transportt); 942 to_sas_internal(task->dev->port->ha->core.shost->transportt);
807 unsigned long flags; 943 unsigned long flags;
808 int res; 944 int res;
809 945
810 spin_lock_irqsave(&task->task_state_lock, flags); 946 spin_lock_irqsave(&task->task_state_lock, flags);
811 if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { 947 if (task->task_state_flags & SAS_TASK_STATE_ABORTED ||
948 task->task_state_flags & SAS_TASK_STATE_DONE) {
812 spin_unlock_irqrestore(&task->task_state_lock, flags); 949 spin_unlock_irqrestore(&task->task_state_lock, flags);
813 SAS_DPRINTK("%s: Task %p already aborted.\n", __FUNCTION__, 950 SAS_DPRINTK("%s: Task %p already finished.\n", __FUNCTION__,
814 task); 951 task);
815 return 0; 952 return 0;
816 } 953 }
817 954 task->task_state_flags |= SAS_TASK_STATE_ABORTED;
818 task->task_state_flags |= SAS_TASK_INITIATOR_ABORTED;
819 if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
820 task->task_state_flags |= SAS_TASK_STATE_ABORTED;
821 spin_unlock_irqrestore(&task->task_state_lock, flags); 955 spin_unlock_irqrestore(&task->task_state_lock, flags);
822 956
823 if (!si->dft->lldd_abort_task) 957 if (!si->dft->lldd_abort_task)
824 return -ENODEV; 958 return -ENODEV;
825 959
826 res = si->dft->lldd_abort_task(task); 960 res = si->dft->lldd_abort_task(task);
961
962 spin_lock_irqsave(&task->task_state_lock, flags);
827 if ((task->task_state_flags & SAS_TASK_STATE_DONE) || 963 if ((task->task_state_flags & SAS_TASK_STATE_DONE) ||
828 (res == TMF_RESP_FUNC_COMPLETE)) 964 (res == TMF_RESP_FUNC_COMPLETE))
829 { 965 {
830 /* SMP commands don't have scsi_cmds(?) */ 966 spin_unlock_irqrestore(&task->task_state_lock, flags);
831 if (!sc) { 967 task->task_done(task);
832 task->task_done(task);
833 return 0;
834 }
835 scsi_req_abort_cmd(sc);
836 scsi_schedule_eh(sc->device->host);
837 return 0; 968 return 0;
838 } 969 }
839 970
840 spin_lock_irqsave(&task->task_state_lock, flags);
841 task->task_state_flags &= ~SAS_TASK_INITIATOR_ABORTED;
842 if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) 971 if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
843 task->task_state_flags &= ~SAS_TASK_STATE_ABORTED; 972 task->task_state_flags &= ~SAS_TASK_STATE_ABORTED;
844 spin_unlock_irqrestore(&task->task_state_lock, flags); 973 spin_unlock_irqrestore(&task->task_state_lock, flags);
@@ -846,17 +975,24 @@ static int do_sas_task_abort(struct sas_task *task)
846 return -EAGAIN; 975 return -EAGAIN;
847} 976}
848 977
849void sas_task_abort(struct work_struct *work) 978/*
979 * Tell an upper layer that it needs to initiate an abort for a given task.
980 * This should only ever be called by an LLDD.
981 */
982void sas_task_abort(struct sas_task *task)
850{ 983{
851 struct sas_task *task = 984 struct scsi_cmnd *sc = task->uldd_task;
852 container_of(work, struct sas_task, abort_work);
853 int i;
854 985
855 for (i = 0; i < 5; i++) 986 /* Escape for libsas internal commands */
856 if (!do_sas_task_abort(task)) 987 if (!sc) {
988 if (!del_timer(&task->timer))
857 return; 989 return;
990 task->timer.function(task->timer.data);
991 return;
992 }
858 993
859 SAS_DPRINTK("%s: Could not kill task!\n", __FUNCTION__); 994 scsi_req_abort_cmd(sc);
995 scsi_schedule_eh(sc->device->host);
860} 996}
861 997
862EXPORT_SYMBOL_GPL(sas_queuecommand); 998EXPORT_SYMBOL_GPL(sas_queuecommand);
@@ -866,5 +1002,9 @@ EXPORT_SYMBOL_GPL(sas_slave_destroy);
866EXPORT_SYMBOL_GPL(sas_change_queue_depth); 1002EXPORT_SYMBOL_GPL(sas_change_queue_depth);
867EXPORT_SYMBOL_GPL(sas_change_queue_type); 1003EXPORT_SYMBOL_GPL(sas_change_queue_type);
868EXPORT_SYMBOL_GPL(sas_bios_param); 1004EXPORT_SYMBOL_GPL(sas_bios_param);
1005EXPORT_SYMBOL_GPL(__sas_task_abort);
869EXPORT_SYMBOL_GPL(sas_task_abort); 1006EXPORT_SYMBOL_GPL(sas_task_abort);
870EXPORT_SYMBOL_GPL(sas_phy_reset); 1007EXPORT_SYMBOL_GPL(sas_phy_reset);
1008EXPORT_SYMBOL_GPL(sas_phy_enable);
1009EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler);
1010EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler);