diff options
author | Dan Williams <dan.j.williams@intel.com> | 2012-06-22 02:36:30 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-07-20 03:58:54 -0400 |
commit | f0bf750c2d25c3a2131ececbff63c7878e0e3765 (patch) | |
tree | ba967c5d28945e76bee78feb24ade328d5b0b3a6 /drivers/scsi | |
parent | a494fd5bd98bb35d5a9a274fecb768e14ebf499c (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.c | 20 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_init.c | 23 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 8 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_sas.c | 20 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.c | 34 |
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 | ||
57 | static void smp_task_done(struct sas_task *task) | 57 | static 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 | } |
57 | EXPORT_SYMBOL_GPL(sas_alloc_task); | 55 | EXPORT_SYMBOL_GPL(sas_alloc_task); |
58 | 56 | ||
57 | struct 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 | } | ||
75 | EXPORT_SYMBOL_GPL(sas_alloc_slow_task); | ||
76 | |||
59 | void sas_free_task(struct sas_task *task) | 77 | void 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 | ||
1366 | static void mvs_task_done(struct sas_task *task) | 1366 | static 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 | ||
1373 | static void mvs_tmf_timedout(unsigned long data) | 1373 | static 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 | ||
651 | static void pm8001_task_done(struct sas_task *task) | 651 | static 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 | ||
658 | static void pm8001_tmf_timedout(unsigned long data) | 658 | static 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)) { |