aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libsas/sas_expander.c20
-rw-r--r--drivers/scsi/libsas/sas_init.c23
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c8
-rw-r--r--drivers/scsi/mvsas/mv_sas.c20
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c34
-rw-r--r--include/scsi/libsas.h14
6 files changed, 73 insertions, 46 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 879dbbe69799..efc6e72f09f3 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -51,14 +51,14 @@ static void smp_task_timedout(unsigned long _task)
51 task->task_state_flags |= SAS_TASK_STATE_ABORTED; 51 task->task_state_flags |= SAS_TASK_STATE_ABORTED;
52 spin_unlock_irqrestore(&task->task_state_lock, flags); 52 spin_unlock_irqrestore(&task->task_state_lock, flags);
53 53
54 complete(&task->completion); 54 complete(&task->slow_task->completion);
55} 55}
56 56
57static void smp_task_done(struct sas_task *task) 57static void smp_task_done(struct sas_task *task)
58{ 58{
59 if (!del_timer(&task->timer)) 59 if (!del_timer(&task->slow_task->timer))
60 return; 60 return;
61 complete(&task->completion); 61 complete(&task->slow_task->completion);
62} 62}
63 63
64/* Give it some long enough timeout. In seconds. */ 64/* Give it some long enough timeout. In seconds. */
@@ -79,7 +79,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
79 break; 79 break;
80 } 80 }
81 81
82 task = sas_alloc_task(GFP_KERNEL); 82 task = sas_alloc_slow_task(GFP_KERNEL);
83 if (!task) { 83 if (!task) {
84 res = -ENOMEM; 84 res = -ENOMEM;
85 break; 85 break;
@@ -91,20 +91,20 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
91 91
92 task->task_done = smp_task_done; 92 task->task_done = smp_task_done;
93 93
94 task->timer.data = (unsigned long) task; 94 task->slow_task->timer.data = (unsigned long) task;
95 task->timer.function = smp_task_timedout; 95 task->slow_task->timer.function = smp_task_timedout;
96 task->timer.expires = jiffies + SMP_TIMEOUT*HZ; 96 task->slow_task->timer.expires = jiffies + SMP_TIMEOUT*HZ;
97 add_timer(&task->timer); 97 add_timer(&task->slow_task->timer);
98 98
99 res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); 99 res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL);
100 100
101 if (res) { 101 if (res) {
102 del_timer(&task->timer); 102 del_timer(&task->slow_task->timer);
103 SAS_DPRINTK("executing SMP task failed:%d\n", res); 103 SAS_DPRINTK("executing SMP task failed:%d\n", res);
104 break; 104 break;
105 } 105 }
106 106
107 wait_for_completion(&task->completion); 107 wait_for_completion(&task->slow_task->completion);
108 res = -ECOMM; 108 res = -ECOMM;
109 if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { 109 if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
110 SAS_DPRINTK("smp task timed out or aborted\n"); 110 SAS_DPRINTK("smp task timed out or aborted\n");
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 1bbab3d94a20..014297c05880 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -48,18 +48,37 @@ struct sas_task *sas_alloc_task(gfp_t flags)
48 INIT_LIST_HEAD(&task->list); 48 INIT_LIST_HEAD(&task->list);
49 spin_lock_init(&task->task_state_lock); 49 spin_lock_init(&task->task_state_lock);
50 task->task_state_flags = SAS_TASK_STATE_PENDING; 50 task->task_state_flags = SAS_TASK_STATE_PENDING;
51 init_timer(&task->timer);
52 init_completion(&task->completion);
53 } 51 }
54 52
55 return task; 53 return task;
56} 54}
57EXPORT_SYMBOL_GPL(sas_alloc_task); 55EXPORT_SYMBOL_GPL(sas_alloc_task);
58 56
57struct sas_task *sas_alloc_slow_task(gfp_t flags)
58{
59 struct sas_task *task = sas_alloc_task(flags);
60 struct sas_task_slow *slow = kmalloc(sizeof(*slow), flags);
61
62 if (!task || !slow) {
63 if (task)
64 kmem_cache_free(sas_task_cache, task);
65 kfree(slow);
66 return NULL;
67 }
68
69 task->slow_task = slow;
70 init_timer(&slow->timer);
71 init_completion(&slow->completion);
72
73 return task;
74}
75EXPORT_SYMBOL_GPL(sas_alloc_slow_task);
76
59void sas_free_task(struct sas_task *task) 77void sas_free_task(struct sas_task *task)
60{ 78{
61 if (task) { 79 if (task) {
62 BUG_ON(!list_empty(&task->list)); 80 BUG_ON(!list_empty(&task->list));
81 kfree(task->slow_task);
63 kmem_cache_free(sas_task_cache, task); 82 kmem_cache_free(sas_task_cache, task);
64 } 83 }
65} 84}
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 676414859872..6e795a174a12 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -1134,9 +1134,13 @@ void sas_task_abort(struct sas_task *task)
1134 1134
1135 /* Escape for libsas internal commands */ 1135 /* Escape for libsas internal commands */
1136 if (!sc) { 1136 if (!sc) {
1137 if (!del_timer(&task->timer)) 1137 struct sas_task_slow *slow = task->slow_task;
1138
1139 if (!slow)
1140 return;
1141 if (!del_timer(&slow->timer))
1138 return; 1142 return;
1139 task->timer.function(task->timer.data); 1143 slow->timer.function(slow->timer.data);
1140 return; 1144 return;
1141 } 1145 }
1142 1146
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index fd3b2839843b..7d46c1ac1d52 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -1365,9 +1365,9 @@ void mvs_dev_gone(struct domain_device *dev)
1365 1365
1366static void mvs_task_done(struct sas_task *task) 1366static void mvs_task_done(struct sas_task *task)
1367{ 1367{
1368 if (!del_timer(&task->timer)) 1368 if (!del_timer(&task->slow_task->timer))
1369 return; 1369 return;
1370 complete(&task->completion); 1370 complete(&task->slow_task->completion);
1371} 1371}
1372 1372
1373static void mvs_tmf_timedout(unsigned long data) 1373static void mvs_tmf_timedout(unsigned long data)
@@ -1375,7 +1375,7 @@ static void mvs_tmf_timedout(unsigned long data)
1375 struct sas_task *task = (struct sas_task *)data; 1375 struct sas_task *task = (struct sas_task *)data;
1376 1376
1377 task->task_state_flags |= SAS_TASK_STATE_ABORTED; 1377 task->task_state_flags |= SAS_TASK_STATE_ABORTED;
1378 complete(&task->completion); 1378 complete(&task->slow_task->completion);
1379} 1379}
1380 1380
1381#define MVS_TASK_TIMEOUT 20 1381#define MVS_TASK_TIMEOUT 20
@@ -1386,7 +1386,7 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,
1386 struct sas_task *task = NULL; 1386 struct sas_task *task = NULL;
1387 1387
1388 for (retry = 0; retry < 3; retry++) { 1388 for (retry = 0; retry < 3; retry++) {
1389 task = sas_alloc_task(GFP_KERNEL); 1389 task = sas_alloc_slow_task(GFP_KERNEL);
1390 if (!task) 1390 if (!task)
1391 return -ENOMEM; 1391 return -ENOMEM;
1392 1392
@@ -1396,20 +1396,20 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,
1396 memcpy(&task->ssp_task, parameter, para_len); 1396 memcpy(&task->ssp_task, parameter, para_len);
1397 task->task_done = mvs_task_done; 1397 task->task_done = mvs_task_done;
1398 1398
1399 task->timer.data = (unsigned long) task; 1399 task->slow_task->timer.data = (unsigned long) task;
1400 task->timer.function = mvs_tmf_timedout; 1400 task->slow_task->timer.function = mvs_tmf_timedout;
1401 task->timer.expires = jiffies + MVS_TASK_TIMEOUT*HZ; 1401 task->slow_task->timer.expires = jiffies + MVS_TASK_TIMEOUT*HZ;
1402 add_timer(&task->timer); 1402 add_timer(&task->slow_task->timer);
1403 1403
1404 res = mvs_task_exec(task, 1, GFP_KERNEL, NULL, 1, tmf); 1404 res = mvs_task_exec(task, 1, GFP_KERNEL, NULL, 1, tmf);
1405 1405
1406 if (res) { 1406 if (res) {
1407 del_timer(&task->timer); 1407 del_timer(&task->slow_task->timer);
1408 mv_printk("executing internel task failed:%d\n", res); 1408 mv_printk("executing internel task failed:%d\n", res);
1409 goto ex_err; 1409 goto ex_err;
1410 } 1410 }
1411 1411
1412 wait_for_completion(&task->completion); 1412 wait_for_completion(&task->slow_task->completion);
1413 res = TMF_RESP_FUNC_FAILED; 1413 res = TMF_RESP_FUNC_FAILED;
1414 /* Even TMF timed out, return direct. */ 1414 /* Even TMF timed out, return direct. */
1415 if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { 1415 if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index fdbba57a74ae..b961112395d5 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -650,9 +650,9 @@ int pm8001_dev_found(struct domain_device *dev)
650 650
651static void pm8001_task_done(struct sas_task *task) 651static void pm8001_task_done(struct sas_task *task)
652{ 652{
653 if (!del_timer(&task->timer)) 653 if (!del_timer(&task->slow_task->timer))
654 return; 654 return;
655 complete(&task->completion); 655 complete(&task->slow_task->completion);
656} 656}
657 657
658static void pm8001_tmf_timedout(unsigned long data) 658static void pm8001_tmf_timedout(unsigned long data)
@@ -660,7 +660,7 @@ static void pm8001_tmf_timedout(unsigned long data)
660 struct sas_task *task = (struct sas_task *)data; 660 struct sas_task *task = (struct sas_task *)data;
661 661
662 task->task_state_flags |= SAS_TASK_STATE_ABORTED; 662 task->task_state_flags |= SAS_TASK_STATE_ABORTED;
663 complete(&task->completion); 663 complete(&task->slow_task->completion);
664} 664}
665 665
666#define PM8001_TASK_TIMEOUT 20 666#define PM8001_TASK_TIMEOUT 20
@@ -683,7 +683,7 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
683 struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); 683 struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev);
684 684
685 for (retry = 0; retry < 3; retry++) { 685 for (retry = 0; retry < 3; retry++) {
686 task = sas_alloc_task(GFP_KERNEL); 686 task = sas_alloc_slow_task(GFP_KERNEL);
687 if (!task) 687 if (!task)
688 return -ENOMEM; 688 return -ENOMEM;
689 689
@@ -691,21 +691,21 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
691 task->task_proto = dev->tproto; 691 task->task_proto = dev->tproto;
692 memcpy(&task->ssp_task, parameter, para_len); 692 memcpy(&task->ssp_task, parameter, para_len);
693 task->task_done = pm8001_task_done; 693 task->task_done = pm8001_task_done;
694 task->timer.data = (unsigned long)task; 694 task->slow_task->timer.data = (unsigned long)task;
695 task->timer.function = pm8001_tmf_timedout; 695 task->slow_task->timer.function = pm8001_tmf_timedout;
696 task->timer.expires = jiffies + PM8001_TASK_TIMEOUT*HZ; 696 task->slow_task->timer.expires = jiffies + PM8001_TASK_TIMEOUT*HZ;
697 add_timer(&task->timer); 697 add_timer(&task->slow_task->timer);
698 698
699 res = pm8001_task_exec(task, 1, GFP_KERNEL, 1, tmf); 699 res = pm8001_task_exec(task, 1, GFP_KERNEL, 1, tmf);
700 700
701 if (res) { 701 if (res) {
702 del_timer(&task->timer); 702 del_timer(&task->slow_task->timer);
703 PM8001_FAIL_DBG(pm8001_ha, 703 PM8001_FAIL_DBG(pm8001_ha,
704 pm8001_printk("Executing internal task " 704 pm8001_printk("Executing internal task "
705 "failed\n")); 705 "failed\n"));
706 goto ex_err; 706 goto ex_err;
707 } 707 }
708 wait_for_completion(&task->completion); 708 wait_for_completion(&task->slow_task->completion);
709 res = -TMF_RESP_FUNC_FAILED; 709 res = -TMF_RESP_FUNC_FAILED;
710 /* Even TMF timed out, return direct. */ 710 /* Even TMF timed out, return direct. */
711 if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { 711 if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
@@ -765,17 +765,17 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
765 struct sas_task *task = NULL; 765 struct sas_task *task = NULL;
766 766
767 for (retry = 0; retry < 3; retry++) { 767 for (retry = 0; retry < 3; retry++) {
768 task = sas_alloc_task(GFP_KERNEL); 768 task = sas_alloc_slow_task(GFP_KERNEL);
769 if (!task) 769 if (!task)
770 return -ENOMEM; 770 return -ENOMEM;
771 771
772 task->dev = dev; 772 task->dev = dev;
773 task->task_proto = dev->tproto; 773 task->task_proto = dev->tproto;
774 task->task_done = pm8001_task_done; 774 task->task_done = pm8001_task_done;
775 task->timer.data = (unsigned long)task; 775 task->slow_task->timer.data = (unsigned long)task;
776 task->timer.function = pm8001_tmf_timedout; 776 task->slow_task->timer.function = pm8001_tmf_timedout;
777 task->timer.expires = jiffies + PM8001_TASK_TIMEOUT * HZ; 777 task->slow_task->timer.expires = jiffies + PM8001_TASK_TIMEOUT * HZ;
778 add_timer(&task->timer); 778 add_timer(&task->slow_task->timer);
779 779
780 res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); 780 res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
781 if (res) 781 if (res)
@@ -789,13 +789,13 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
789 pm8001_dev, flag, task_tag, ccb_tag); 789 pm8001_dev, flag, task_tag, ccb_tag);
790 790
791 if (res) { 791 if (res) {
792 del_timer(&task->timer); 792 del_timer(&task->slow_task->timer);
793 PM8001_FAIL_DBG(pm8001_ha, 793 PM8001_FAIL_DBG(pm8001_ha,
794 pm8001_printk("Executing internal task " 794 pm8001_printk("Executing internal task "
795 "failed\n")); 795 "failed\n"));
796 goto ex_err; 796 goto ex_err;
797 } 797 }
798 wait_for_completion(&task->completion); 798 wait_for_completion(&task->slow_task->completion);
799 res = TMF_RESP_FUNC_FAILED; 799 res = TMF_RESP_FUNC_FAILED;
800 /* Even TMF timed out, return direct. */ 800 /* Even TMF timed out, return direct. */
801 if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { 801 if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 29a8cc7831af..ae33706afeb0 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -613,10 +613,6 @@ struct sas_task {
613 613
614 enum sas_protocol task_proto; 614 enum sas_protocol task_proto;
615 615
616 /* Used by the discovery code. */
617 struct timer_list timer;
618 struct completion completion;
619
620 union { 616 union {
621 struct sas_ata_task ata_task; 617 struct sas_ata_task ata_task;
622 struct sas_smp_task smp_task; 618 struct sas_smp_task smp_task;
@@ -633,8 +629,15 @@ struct sas_task {
633 629
634 void *lldd_task; /* for use by LLDDs */ 630 void *lldd_task; /* for use by LLDDs */
635 void *uldd_task; 631 void *uldd_task;
632 struct sas_task_slow *slow_task;
633};
636 634
637 struct work_struct abort_work; 635struct sas_task_slow {
636 /* standard/extra infrastructure for slow path commands (SMP and
637 * internal lldd commands
638 */
639 struct timer_list timer;
640 struct completion completion;
638}; 641};
639 642
640#define SAS_TASK_STATE_PENDING 1 643#define SAS_TASK_STATE_PENDING 1
@@ -644,6 +647,7 @@ struct sas_task {
644#define SAS_TASK_AT_INITIATOR 16 647#define SAS_TASK_AT_INITIATOR 16
645 648
646extern struct sas_task *sas_alloc_task(gfp_t flags); 649extern struct sas_task *sas_alloc_task(gfp_t flags);
650extern struct sas_task *sas_alloc_slow_task(gfp_t flags);
647extern void sas_free_task(struct sas_task *task); 651extern void sas_free_task(struct sas_task *task);
648 652
649struct sas_domain_function_template { 653struct sas_domain_function_template {