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

[SCSI] mvsas: add support for Task collector mode and fixed relative bugs

1. Add support for Task collector mode.
2. Fixed relative collector mode bug:
- I/O failed when disks is on two ports
- system hang when hotplug disk
- system hang when unplug disk during run IO
3. Unlock ap->lock within .lldd_execute_task for direct mode to
improve performance

Signed-off-by: Xiangliang Yu <yuxiangl@marvell.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>

authored by

Xiangliang Yu and committed by
James Bottomley
0b15fb1f 82140283

+296 -154
+1
drivers/scsi/mvsas/Kconfig
··· 3 3 # 4 4 # Copyright 2007 Red Hat, Inc. 5 5 # Copyright 2008 Marvell. <kewei@marvell.com> 6 + # Copyright 2009-20011 Marvell. <yuxiangl@marvell.com> 6 7 # 7 8 # This file is licensed under GPLv2. 8 9 #
+1
drivers/scsi/mvsas/Makefile
··· 3 3 # 4 4 # Copyright 2007 Red Hat, Inc. 5 5 # Copyright 2008 Marvell. <kewei@marvell.com> 6 + # Copyright 2009-2011 Marvell. <yuxiangl@marvell.com> 6 7 # 7 8 # This file is licensed under GPLv2. 8 9 #
+1
drivers/scsi/mvsas/mv_64xx.c
··· 3 3 * 4 4 * Copyright 2007 Red Hat, Inc. 5 5 * Copyright 2008 Marvell. <kewei@marvell.com> 6 + * Copyright 2009-2011 Marvell. <yuxiangl@marvell.com> 6 7 * 7 8 * This file is licensed under GPLv2. 8 9 *
+1
drivers/scsi/mvsas/mv_64xx.h
··· 3 3 * 4 4 * Copyright 2007 Red Hat, Inc. 5 5 * Copyright 2008 Marvell. <kewei@marvell.com> 6 + * Copyright 2009-2011 Marvell. <yuxiangl@marvell.com> 6 7 * 7 8 * This file is licensed under GPLv2. 8 9 *
+1
drivers/scsi/mvsas/mv_94xx.c
··· 3 3 * 4 4 * Copyright 2007 Red Hat, Inc. 5 5 * Copyright 2008 Marvell. <kewei@marvell.com> 6 + * Copyright 2009-2011 Marvell. <yuxiangl@marvell.com> 6 7 * 7 8 * This file is licensed under GPLv2. 8 9 *
+1
drivers/scsi/mvsas/mv_94xx.h
··· 3 3 * 4 4 * Copyright 2007 Red Hat, Inc. 5 5 * Copyright 2008 Marvell. <kewei@marvell.com> 6 + * Copyright 2009-2011 Marvell. <yuxiangl@marvell.com> 6 7 * 7 8 * This file is licensed under GPLv2. 8 9 *
+1
drivers/scsi/mvsas/mv_chips.h
··· 3 3 * 4 4 * Copyright 2007 Red Hat, Inc. 5 5 * Copyright 2008 Marvell. <kewei@marvell.com> 6 + * Copyright 2009-2011 Marvell. <yuxiangl@marvell.com> 6 7 * 7 8 * This file is licensed under GPLv2. 8 9 *
+1
drivers/scsi/mvsas/mv_defs.h
··· 3 3 * 4 4 * Copyright 2007 Red Hat, Inc. 5 5 * Copyright 2008 Marvell. <kewei@marvell.com> 6 + * Copyright 2009-2011 Marvell. <yuxiangl@marvell.com> 6 7 * 7 8 * This file is licensed under GPLv2. 8 9 *
+29 -18
drivers/scsi/mvsas/mv_init.c
··· 3 3 * 4 4 * Copyright 2007 Red Hat, Inc. 5 5 * Copyright 2008 Marvell. <kewei@marvell.com> 6 + * Copyright 2009-2011 Marvell. <yuxiangl@marvell.com> 6 7 * 7 8 * This file is licensed under GPLv2. 8 9 * ··· 26 25 27 26 #include "mv_sas.h" 28 27 28 + static int lldd_max_execute_num = 1; 29 + module_param_named(collector, lldd_max_execute_num, int, S_IRUGO); 30 + MODULE_PARM_DESC(collector, "\n" 31 + "\tIf greater than one, tells the SAS Layer to run in Task Collector\n" 32 + "\tMode. If 1 or 0, tells the SAS Layer to run in Direct Mode.\n" 33 + "\tThe mvsas SAS LLDD supports both modes.\n" 34 + "\tDefault: 1 (Direct Mode).\n"); 35 + 29 36 static struct scsi_transport_template *mvs_stt; 37 + struct kmem_cache *mvs_task_list_cache; 30 38 static const struct mvs_chip_info mvs_chips[] = { 31 39 [chip_6320] = { 1, 2, 0x400, 17, 16, 9, &mvs_64xx_dispatch, }, 32 40 [chip_6440] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, }, ··· 119 109 120 110 static void mvs_free(struct mvs_info *mvi) 121 111 { 122 - int i; 123 112 struct mvs_wq *mwq; 124 113 int slot_nr; 125 114 ··· 130 121 else 131 122 slot_nr = MVS_SLOTS; 132 123 133 - for (i = 0; i < mvi->tags_num; i++) { 134 - struct mvs_slot_info *slot = &mvi->slot_info[i]; 135 - if (slot->buf) 136 - dma_free_coherent(mvi->dev, MVS_SLOT_BUF_SZ, 137 - slot->buf, slot->buf_dma); 138 - } 124 + if (mvi->dma_pool) 125 + pci_pool_destroy(mvi->dma_pool); 139 126 140 127 if (mvi->tx) 141 128 dma_free_coherent(mvi->dev, ··· 220 215 static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost) 221 216 { 222 217 int i = 0, slot_nr; 218 + char pool_name[32]; 223 219 224 220 if (mvi->flags & MVF_FLAG_SOC) 225 221 slot_nr = MVS_SOC_SLOTS; ··· 280 274 if (!mvi->bulk_buffer) 281 275 goto err_out; 282 276 #endif 283 - for (i = 0; i < slot_nr; i++) { 284 - struct mvs_slot_info *slot = &mvi->slot_info[i]; 285 - 286 - slot->buf = dma_alloc_coherent(mvi->dev, MVS_SLOT_BUF_SZ, 287 - &slot->buf_dma, GFP_KERNEL); 288 - if (!slot->buf) { 289 - printk(KERN_DEBUG"failed to allocate slot->buf.\n"); 277 + sprintf(pool_name, "%s%d", "mvs_dma_pool", mvi->id); 278 + mvi->dma_pool = pci_pool_create(pool_name, mvi->pdev, MVS_SLOT_BUF_SZ, 16, 0); 279 + if (!mvi->dma_pool) { 280 + printk(KERN_DEBUG "failed to create dma pool %s.\n", pool_name); 290 281 goto err_out; 291 - } 292 - memset(slot->buf, 0, MVS_SLOT_BUF_SZ); 293 - ++mvi->tags_num; 294 282 } 283 + mvi->tags_num = slot_nr; 284 + 295 285 /* Initialize tags */ 296 286 mvs_tag_init(mvi); 297 287 return 0; ··· 488 486 489 487 sha->num_phys = nr_core * chip_info->n_phy; 490 488 491 - sha->lldd_max_execute_num = 1; 489 + sha->lldd_max_execute_num = lldd_max_execute_num; 492 490 493 491 if (mvi->flags & MVF_FLAG_SOC) 494 492 can_queue = MVS_SOC_CAN_QUEUE; ··· 712 710 if (!mvs_stt) 713 711 return -ENOMEM; 714 712 713 + mvs_task_list_cache = kmem_cache_create("mvs_task_list", sizeof(struct mvs_task_list), 714 + 0, SLAB_HWCACHE_ALIGN, NULL); 715 + if (!mvs_task_list_cache) { 716 + rc = -ENOMEM; 717 + mv_printk("%s: mvs_task_list_cache alloc failed! \n", __func__); 718 + goto err_out; 719 + } 720 + 715 721 rc = pci_register_driver(&mvs_pci_driver); 716 722 717 723 if (rc) ··· 736 726 { 737 727 pci_unregister_driver(&mvs_pci_driver); 738 728 sas_release_transport(mvs_stt); 729 + kmem_cache_destroy(mvs_task_list_cache); 739 730 } 740 731 741 732 module_init(mvs_init);
+251 -136
drivers/scsi/mvsas/mv_sas.c
··· 3 3 * 4 4 * Copyright 2007 Red Hat, Inc. 5 5 * Copyright 2008 Marvell. <kewei@marvell.com> 6 + * Copyright 2009-2011 Marvell. <yuxiangl@marvell.com> 6 7 * 7 8 * This file is licensed under GPLv2. 8 9 * ··· 863 862 } 864 863 865 864 #define DEV_IS_GONE(mvi_dev) ((!mvi_dev || (mvi_dev->dev_type == NO_DEVICE))) 866 - static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags, 867 - struct completion *completion,int is_tmf, 868 - struct mvs_tmf_task *tmf) 865 + static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf, 866 + struct mvs_tmf_task *tmf, int *pass) 869 867 { 870 868 struct domain_device *dev = task->dev; 871 - struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; 872 - struct mvs_info *mvi = mvi_dev->mvi_info; 869 + struct mvs_device *mvi_dev = dev->lldd_dev; 873 870 struct mvs_task_exec_info tei; 874 - struct sas_task *t = task; 875 871 struct mvs_slot_info *slot; 876 - u32 tag = 0xdeadbeef, rc, n_elem = 0; 877 - u32 n = num, pass = 0; 878 - unsigned long flags = 0, flags_libsas = 0; 872 + u32 tag = 0xdeadbeef, n_elem = 0; 873 + int rc = 0; 879 874 880 875 if (!dev->port) { 881 - struct task_status_struct *tsm = &t->task_status; 876 + struct task_status_struct *tsm = &task->task_status; 882 877 883 878 tsm->resp = SAS_TASK_UNDELIVERED; 884 879 tsm->stat = SAS_PHY_DOWN; 880 + /* 881 + * libsas will use dev->port, should 882 + * not call task_done for sata 883 + */ 885 884 if (dev->dev_type != SATA_DEV) 886 - t->task_done(t); 887 - return 0; 885 + task->task_done(task); 886 + return rc; 888 887 } 889 888 890 - spin_lock_irqsave(&mvi->lock, flags); 891 - do { 892 - dev = t->dev; 893 - mvi_dev = dev->lldd_dev; 894 - if (DEV_IS_GONE(mvi_dev)) { 895 - if (mvi_dev) 896 - mv_dprintk("device %d not ready.\n", 897 - mvi_dev->device_id); 898 - else 899 - mv_dprintk("device %016llx not ready.\n", 900 - SAS_ADDR(dev->sas_addr)); 889 + if (DEV_IS_GONE(mvi_dev)) { 890 + if (mvi_dev) 891 + mv_dprintk("device %d not ready.\n", 892 + mvi_dev->device_id); 893 + else 894 + mv_dprintk("device %016llx not ready.\n", 895 + SAS_ADDR(dev->sas_addr)); 901 896 902 897 rc = SAS_PHY_DOWN; 903 - goto out_done; 904 - } 898 + return rc; 899 + } 900 + tei.port = dev->port->lldd_port; 901 + if (tei.port && !tei.port->port_attached && !tmf) { 902 + if (sas_protocol_ata(task->task_proto)) { 903 + struct task_status_struct *ts = &task->task_status; 904 + mv_dprintk("SATA/STP port %d does not attach" 905 + "device.\n", dev->port->id); 906 + ts->resp = SAS_TASK_COMPLETE; 907 + ts->stat = SAS_PHY_DOWN; 905 908 906 - if (dev->port->id >= mvi->chip->n_phy) 907 - tei.port = &mvi->port[dev->port->id - mvi->chip->n_phy]; 908 - else 909 - tei.port = &mvi->port[dev->port->id]; 909 + task->task_done(task); 910 910 911 - if (tei.port && !tei.port->port_attached) { 912 - if (sas_protocol_ata(t->task_proto)) { 913 - struct task_status_struct *ts = &t->task_status; 914 - 915 - mv_dprintk("port %d does not" 916 - "attached device.\n", dev->port->id); 917 - ts->stat = SAS_PROTO_RESPONSE; 918 - ts->stat = SAS_PHY_DOWN; 919 - spin_unlock_irqrestore(dev->sata_dev.ap->lock, 920 - flags_libsas); 921 - spin_unlock_irqrestore(&mvi->lock, flags); 922 - t->task_done(t); 923 - spin_lock_irqsave(&mvi->lock, flags); 924 - spin_lock_irqsave(dev->sata_dev.ap->lock, 925 - flags_libsas); 926 - if (n > 1) 927 - t = list_entry(t->list.next, 928 - struct sas_task, list); 929 - continue; 930 - } else { 931 - struct task_status_struct *ts = &t->task_status; 932 - ts->resp = SAS_TASK_UNDELIVERED; 933 - ts->stat = SAS_PHY_DOWN; 934 - t->task_done(t); 935 - if (n > 1) 936 - t = list_entry(t->list.next, 937 - struct sas_task, list); 938 - continue; 939 - } 940 - } 941 - 942 - if (!sas_protocol_ata(t->task_proto)) { 943 - if (t->num_scatter) { 944 - n_elem = dma_map_sg(mvi->dev, 945 - t->scatter, 946 - t->num_scatter, 947 - t->data_dir); 948 - if (!n_elem) { 949 - rc = -ENOMEM; 950 - goto err_out; 951 - } 952 - } 953 911 } else { 954 - n_elem = t->num_scatter; 912 + struct task_status_struct *ts = &task->task_status; 913 + mv_dprintk("SAS port %d does not attach" 914 + "device.\n", dev->port->id); 915 + ts->resp = SAS_TASK_UNDELIVERED; 916 + ts->stat = SAS_PHY_DOWN; 917 + task->task_done(task); 955 918 } 919 + return rc; 920 + } 956 921 957 - rc = mvs_tag_alloc(mvi, &tag); 958 - if (rc) 959 - goto err_out; 960 - 961 - slot = &mvi->slot_info[tag]; 962 - 963 - 964 - t->lldd_task = NULL; 965 - slot->n_elem = n_elem; 966 - slot->slot_tag = tag; 967 - memset(slot->buf, 0, MVS_SLOT_BUF_SZ); 968 - 969 - tei.task = t; 970 - tei.hdr = &mvi->slot[tag]; 971 - tei.tag = tag; 972 - tei.n_elem = n_elem; 973 - switch (t->task_proto) { 974 - case SAS_PROTOCOL_SMP: 975 - rc = mvs_task_prep_smp(mvi, &tei); 976 - break; 977 - case SAS_PROTOCOL_SSP: 978 - rc = mvs_task_prep_ssp(mvi, &tei, is_tmf, tmf); 979 - break; 980 - case SAS_PROTOCOL_SATA: 981 - case SAS_PROTOCOL_STP: 982 - case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: 983 - rc = mvs_task_prep_ata(mvi, &tei); 984 - break; 985 - default: 986 - dev_printk(KERN_ERR, mvi->dev, 987 - "unknown sas_task proto: 0x%x\n", 988 - t->task_proto); 989 - rc = -EINVAL; 990 - break; 922 + if (!sas_protocol_ata(task->task_proto)) { 923 + if (task->num_scatter) { 924 + n_elem = dma_map_sg(mvi->dev, 925 + task->scatter, 926 + task->num_scatter, 927 + task->data_dir); 928 + if (!n_elem) { 929 + rc = -ENOMEM; 930 + goto prep_out; 931 + } 991 932 } 933 + } else { 934 + n_elem = task->num_scatter; 935 + } 992 936 993 - if (rc) { 994 - mv_dprintk("rc is %x\n", rc); 995 - goto err_out_tag; 996 - } 997 - slot->task = t; 998 - slot->port = tei.port; 999 - t->lldd_task = slot; 1000 - list_add_tail(&slot->entry, &tei.port->list); 1001 - /* TODO: select normal or high priority */ 1002 - spin_lock(&t->task_state_lock); 1003 - t->task_state_flags |= SAS_TASK_AT_INITIATOR; 1004 - spin_unlock(&t->task_state_lock); 937 + rc = mvs_tag_alloc(mvi, &tag); 938 + if (rc) 939 + goto err_out; 1005 940 1006 - mvs_hba_memory_dump(mvi, tag, t->task_proto); 1007 - mvi_dev->running_req++; 1008 - ++pass; 1009 - mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); 1010 - if (n > 1) 1011 - t = list_entry(t->list.next, struct sas_task, list); 1012 - if (likely(pass)) 1013 - MVS_CHIP_DISP->start_delivery(mvi, (mvi->tx_prod - 1) & 1014 - (MVS_CHIP_SLOT_SZ - 1)); 941 + slot = &mvi->slot_info[tag]; 1015 942 1016 - } while (--n); 1017 - rc = 0; 1018 - goto out_done; 943 + task->lldd_task = NULL; 944 + slot->n_elem = n_elem; 945 + slot->slot_tag = tag; 1019 946 947 + slot->buf = pci_pool_alloc(mvi->dma_pool, GFP_ATOMIC, &slot->buf_dma); 948 + if (!slot->buf) 949 + goto err_out_tag; 950 + memset(slot->buf, 0, MVS_SLOT_BUF_SZ); 951 + 952 + tei.task = task; 953 + tei.hdr = &mvi->slot[tag]; 954 + tei.tag = tag; 955 + tei.n_elem = n_elem; 956 + switch (task->task_proto) { 957 + case SAS_PROTOCOL_SMP: 958 + rc = mvs_task_prep_smp(mvi, &tei); 959 + break; 960 + case SAS_PROTOCOL_SSP: 961 + rc = mvs_task_prep_ssp(mvi, &tei, is_tmf, tmf); 962 + break; 963 + case SAS_PROTOCOL_SATA: 964 + case SAS_PROTOCOL_STP: 965 + case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: 966 + rc = mvs_task_prep_ata(mvi, &tei); 967 + break; 968 + default: 969 + dev_printk(KERN_ERR, mvi->dev, 970 + "unknown sas_task proto: 0x%x\n", 971 + task->task_proto); 972 + rc = -EINVAL; 973 + break; 974 + } 975 + 976 + if (rc) { 977 + mv_dprintk("rc is %x\n", rc); 978 + goto err_out_slot_buf; 979 + } 980 + slot->task = task; 981 + slot->port = tei.port; 982 + task->lldd_task = slot; 983 + list_add_tail(&slot->entry, &tei.port->list); 984 + spin_lock(&task->task_state_lock); 985 + task->task_state_flags |= SAS_TASK_AT_INITIATOR; 986 + spin_unlock(&task->task_state_lock); 987 + 988 + mvs_hba_memory_dump(mvi, tag, task->task_proto); 989 + mvi_dev->running_req++; 990 + ++(*pass); 991 + mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); 992 + 993 + return rc; 994 + 995 + err_out_slot_buf: 996 + pci_pool_free(mvi->dma_pool, slot->buf, slot->buf_dma); 1020 997 err_out_tag: 1021 998 mvs_tag_free(mvi, tag); 1022 999 err_out: 1023 1000 1024 - dev_printk(KERN_ERR, mvi->dev, "mvsas exec failed[%d]!\n", rc); 1025 - if (!sas_protocol_ata(t->task_proto)) 1001 + dev_printk(KERN_ERR, mvi->dev, "mvsas prep failed[%d]!\n", rc); 1002 + if (!sas_protocol_ata(task->task_proto)) 1026 1003 if (n_elem) 1027 - dma_unmap_sg(mvi->dev, t->scatter, n_elem, 1028 - t->data_dir); 1029 - out_done: 1004 + dma_unmap_sg(mvi->dev, task->scatter, n_elem, 1005 + task->data_dir); 1006 + prep_out: 1007 + return rc; 1008 + } 1009 + 1010 + static struct mvs_task_list *mvs_task_alloc_list(int *num, gfp_t gfp_flags) 1011 + { 1012 + struct mvs_task_list *first = NULL; 1013 + 1014 + for (; *num > 0; --*num) { 1015 + struct mvs_task_list *mvs_list = kmem_cache_zalloc(mvs_task_list_cache, gfp_flags); 1016 + 1017 + if (!mvs_list) 1018 + break; 1019 + 1020 + INIT_LIST_HEAD(&mvs_list->list); 1021 + if (!first) 1022 + first = mvs_list; 1023 + else 1024 + list_add_tail(&mvs_list->list, &first->list); 1025 + 1026 + } 1027 + 1028 + return first; 1029 + } 1030 + 1031 + static inline void mvs_task_free_list(struct mvs_task_list *mvs_list) 1032 + { 1033 + LIST_HEAD(list); 1034 + struct list_head *pos, *a; 1035 + struct mvs_task_list *mlist = NULL; 1036 + 1037 + __list_add(&list, mvs_list->list.prev, &mvs_list->list); 1038 + 1039 + list_for_each_safe(pos, a, &list) { 1040 + list_del_init(pos); 1041 + mlist = list_entry(pos, struct mvs_task_list, list); 1042 + kmem_cache_free(mvs_task_list_cache, mlist); 1043 + } 1044 + } 1045 + 1046 + static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags, 1047 + struct completion *completion, int is_tmf, 1048 + struct mvs_tmf_task *tmf) 1049 + { 1050 + struct domain_device *dev = task->dev; 1051 + struct mvs_info *mvi = NULL; 1052 + u32 rc = 0; 1053 + u32 pass = 0; 1054 + unsigned long flags = 0; 1055 + 1056 + mvi = ((struct mvs_device *)task->dev->lldd_dev)->mvi_info; 1057 + 1058 + if ((dev->dev_type == SATA_DEV) && (dev->sata_dev.ap != NULL)) 1059 + spin_unlock_irq(dev->sata_dev.ap->lock); 1060 + 1061 + spin_lock_irqsave(&mvi->lock, flags); 1062 + rc = mvs_task_prep(task, mvi, is_tmf, tmf, &pass); 1063 + if (rc) 1064 + dev_printk(KERN_ERR, mvi->dev, "mvsas exec failed[%d]!\n", rc); 1065 + 1066 + if (likely(pass)) 1067 + MVS_CHIP_DISP->start_delivery(mvi, (mvi->tx_prod - 1) & 1068 + (MVS_CHIP_SLOT_SZ - 1)); 1030 1069 spin_unlock_irqrestore(&mvi->lock, flags); 1070 + 1071 + if ((dev->dev_type == SATA_DEV) && (dev->sata_dev.ap != NULL)) 1072 + spin_lock_irq(dev->sata_dev.ap->lock); 1073 + 1074 + return rc; 1075 + } 1076 + 1077 + static int mvs_collector_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags, 1078 + struct completion *completion, int is_tmf, 1079 + struct mvs_tmf_task *tmf) 1080 + { 1081 + struct domain_device *dev = task->dev; 1082 + struct mvs_prv_info *mpi = dev->port->ha->lldd_ha; 1083 + struct mvs_info *mvi = NULL; 1084 + struct sas_task *t = task; 1085 + struct mvs_task_list *mvs_list = NULL, *a; 1086 + LIST_HEAD(q); 1087 + int pass[2] = {0}; 1088 + u32 rc = 0; 1089 + u32 n = num; 1090 + unsigned long flags = 0; 1091 + 1092 + mvs_list = mvs_task_alloc_list(&n, gfp_flags); 1093 + if (n) { 1094 + printk(KERN_ERR "%s: mvs alloc list failed.\n", __func__); 1095 + rc = -ENOMEM; 1096 + goto free_list; 1097 + } 1098 + 1099 + __list_add(&q, mvs_list->list.prev, &mvs_list->list); 1100 + 1101 + list_for_each_entry(a, &q, list) { 1102 + a->task = t; 1103 + t = list_entry(t->list.next, struct sas_task, list); 1104 + } 1105 + 1106 + list_for_each_entry(a, &q , list) { 1107 + 1108 + t = a->task; 1109 + mvi = ((struct mvs_device *)t->dev->lldd_dev)->mvi_info; 1110 + 1111 + spin_lock_irqsave(&mvi->lock, flags); 1112 + rc = mvs_task_prep(t, mvi, is_tmf, tmf, &pass[mvi->id]); 1113 + if (rc) 1114 + dev_printk(KERN_ERR, mvi->dev, "mvsas exec failed[%d]!\n", rc); 1115 + spin_unlock_irqrestore(&mvi->lock, flags); 1116 + } 1117 + 1118 + if (likely(pass[0])) 1119 + MVS_CHIP_DISP->start_delivery(mpi->mvi[0], 1120 + (mpi->mvi[0]->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1)); 1121 + 1122 + if (likely(pass[1])) 1123 + MVS_CHIP_DISP->start_delivery(mpi->mvi[1], 1124 + (mpi->mvi[1]->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1)); 1125 + 1126 + list_del_init(&q); 1127 + 1128 + free_list: 1129 + if (mvs_list) 1130 + mvs_task_free_list(mvs_list); 1131 + 1031 1132 return rc; 1032 1133 } 1033 1134 1034 1135 int mvs_queue_command(struct sas_task *task, const int num, 1035 1136 gfp_t gfp_flags) 1036 1137 { 1037 - return mvs_task_exec(task, num, gfp_flags, NULL, 0, NULL); 1138 + struct mvs_device *mvi_dev = task->dev->lldd_dev; 1139 + struct sas_ha_struct *sas = mvi_dev->mvi_info->sas; 1140 + 1141 + if (sas->lldd_max_execute_num < 2) 1142 + return mvs_task_exec(task, num, gfp_flags, NULL, 0, NULL); 1143 + else 1144 + return mvs_collector_task_exec(task, num, gfp_flags, NULL, 0, NULL); 1038 1145 } 1039 1146 1040 1147 static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc) ··· 1175 1066 default: 1176 1067 /* do nothing */ 1177 1068 break; 1069 + } 1070 + 1071 + if (slot->buf) { 1072 + pci_pool_free(mvi->dma_pool, slot->buf, slot->buf_dma); 1073 + slot->buf = NULL; 1178 1074 } 1179 1075 list_del_init(&slot->entry); 1180 1076 task->lldd_task = NULL; ··· 1369 1255 spin_lock_irqsave(&mvi->lock, flags); 1370 1256 port->port_attached = 1; 1371 1257 phy->port = port; 1258 + sas_port->lldd_port = port; 1372 1259 if (phy->phy_type & PORT_TYPE_SAS) { 1373 1260 port->wide_port_phymap = sas_port->phy_mask; 1374 1261 mv_printk("set wide port phy map %x\n", sas_port->phy_mask);
+8
drivers/scsi/mvsas/mv_sas.h
··· 3 3 * 4 4 * Copyright 2007 Red Hat, Inc. 5 5 * Copyright 2008 Marvell. <kewei@marvell.com> 6 + * Copyright 2009-2011 Marvell. <yuxiangl@marvell.com> 6 7 * 7 8 * This file is licensed under GPLv2. 8 9 * ··· 68 67 extern struct mvs_info *tgt_mvi; 69 68 extern const struct mvs_dispatch mvs_64xx_dispatch; 70 69 extern const struct mvs_dispatch mvs_94xx_dispatch; 70 + extern struct kmem_cache *mvs_task_list_cache; 71 71 72 72 #define DEV_IS_EXPANDER(type) \ 73 73 ((type == EDGE_DEV) || (type == FANOUT_DEV)) ··· 343 341 dma_addr_t bulk_buffer_dma; 344 342 #define TRASH_BUCKET_SIZE 0x20000 345 343 #endif 344 + void *dma_pool; 346 345 struct mvs_slot_info slot_info[0]; 347 346 }; 348 347 ··· 368 365 struct mvs_port *port; 369 366 u32 tag; 370 367 int n_elem; 368 + }; 369 + 370 + struct mvs_task_list { 371 + struct sas_task *task; 372 + struct list_head list; 371 373 }; 372 374 373 375