Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Dan Williams and committed by
James Bottomley
f0bf750c a494fd5b

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