diff options
-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 | ||||
-rw-r--r-- | include/scsi/libsas.h | 14 |
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 | ||
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)) { |
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; | 635 | struct 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 | ||
646 | extern struct sas_task *sas_alloc_task(gfp_t flags); | 649 | extern struct sas_task *sas_alloc_task(gfp_t flags); |
650 | extern struct sas_task *sas_alloc_slow_task(gfp_t flags); | ||
647 | extern void sas_free_task(struct sas_task *task); | 651 | extern void sas_free_task(struct sas_task *task); |
648 | 652 | ||
649 | struct sas_domain_function_template { | 653 | struct sas_domain_function_template { |