aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2012-06-22 02:36:30 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-07-20 03:58:54 -0400
commitf0bf750c2d25c3a2131ececbff63c7878e0e3765 (patch)
treeba967c5d28945e76bee78feb24ade328d5b0b3a6 /drivers/scsi
parenta494fd5bd98bb35d5a9a274fecb768e14ebf499c (diff)
[SCSI] libsas: trim sas_task of slow path infrastructure
The timer and the completion are only used for slow path tasks (smp, and lldd tmfs), yet we incur the allocation space and cpu setup time for every fast path task. Cc: Xiangliang Yu <yuxiangl@marvell.com> Acked-by: Jack Wang <jack_wang@usish.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-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
5 files changed, 64 insertions, 41 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)) {