aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Dillow <dillowda@ornl.gov>2011-01-16 13:57:10 -0500
committerDavid Dillow <dillowda@ornl.gov>2011-03-15 19:37:23 -0400
commitc07d424d6118d528ef71b22b7424bfc359c307a5 (patch)
tree1d61da8aea0fa80c2c7bc13b03d15ddb470bcfa6 /drivers
parent8f26c9ff9cd0317ad867bce972f69e0c6c2cbe3c (diff)
IB/srp: add support for indirect tables that don't fit in SRP_CMD
This allows us to guarantee the ability to submit up to 8 MB requests based on the current value of SCSI_MAX_SG_CHAIN_SEGMENTS. While FMR will usually condense the requests into 8 SG entries, it is imperative that the target support external tables in case the FMR mapping fails or is not supported. We add a safety valve to allow targets without the needed support to reap the benefits of the large tables, but fail in a manner that lets the user know that the data didn't make it to the device. The user must add "allow_ext_sg=1" to the target parameters to indicate that the target has the needed support. If indirect_sg_entries is not specified in the modules options, then the sg_tablesize for the target will default to cmd_sg_entries unless overridden by the target options. Signed-off-by: David Dillow <dillowda@ornl.gov>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c117
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.h5
2 files changed, 110 insertions, 12 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 9ce129ab3beb..4ec7dddbbf49 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -61,6 +61,8 @@ MODULE_LICENSE("Dual BSD/GPL");
61 61
62static unsigned int srp_sg_tablesize; 62static unsigned int srp_sg_tablesize;
63static unsigned int cmd_sg_entries; 63static unsigned int cmd_sg_entries;
64static unsigned int indirect_sg_entries;
65static bool allow_ext_sg;
64static int topspin_workarounds = 1; 66static int topspin_workarounds = 1;
65 67
66module_param(srp_sg_tablesize, uint, 0444); 68module_param(srp_sg_tablesize, uint, 0444);
@@ -70,6 +72,14 @@ module_param(cmd_sg_entries, uint, 0444);
70MODULE_PARM_DESC(cmd_sg_entries, 72MODULE_PARM_DESC(cmd_sg_entries,
71 "Default number of gather/scatter entries in the SRP command (default is 12, max 255)"); 73 "Default number of gather/scatter entries in the SRP command (default is 12, max 255)");
72 74
75module_param(indirect_sg_entries, uint, 0444);
76MODULE_PARM_DESC(indirect_sg_entries,
77 "Default max number of gather/scatter entries (default is 12, max is " __stringify(SCSI_MAX_SG_CHAIN_SEGMENTS) ")");
78
79module_param(allow_ext_sg, bool, 0444);
80MODULE_PARM_DESC(allow_ext_sg,
81 "Default behavior when there are more than cmd_sg_entries S/G entries after mapping; fails the request when false (default false)");
82
73module_param(topspin_workarounds, int, 0444); 83module_param(topspin_workarounds, int, 0444);
74MODULE_PARM_DESC(topspin_workarounds, 84MODULE_PARM_DESC(topspin_workarounds,
75 "Enable workarounds for Topspin/Cisco SRP target bugs if != 0"); 85 "Enable workarounds for Topspin/Cisco SRP target bugs if != 0");
@@ -446,12 +456,19 @@ static bool srp_change_state(struct srp_target_port *target,
446 456
447static void srp_free_req_data(struct srp_target_port *target) 457static void srp_free_req_data(struct srp_target_port *target)
448{ 458{
459 struct ib_device *ibdev = target->srp_host->srp_dev->dev;
449 struct srp_request *req; 460 struct srp_request *req;
450 int i; 461 int i;
451 462
452 for (i = 0, req = target->req_ring; i < SRP_CMD_SQ_SIZE; ++i, ++req) { 463 for (i = 0, req = target->req_ring; i < SRP_CMD_SQ_SIZE; ++i, ++req) {
453 kfree(req->fmr_list); 464 kfree(req->fmr_list);
454 kfree(req->map_page); 465 kfree(req->map_page);
466 if (req->indirect_dma_addr) {
467 ib_dma_unmap_single(ibdev, req->indirect_dma_addr,
468 target->indirect_size,
469 DMA_TO_DEVICE);
470 }
471 kfree(req->indirect_desc);
455 } 472 }
456} 473}
457 474
@@ -790,7 +807,6 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
790 struct ib_device *ibdev; 807 struct ib_device *ibdev;
791 struct srp_map_state state; 808 struct srp_map_state state;
792 struct srp_indirect_buf *indirect_hdr; 809 struct srp_indirect_buf *indirect_hdr;
793 dma_addr_t indirect_addr;
794 u32 table_len; 810 u32 table_len;
795 u8 fmt; 811 u8 fmt;
796 812
@@ -841,8 +857,11 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
841 */ 857 */
842 indirect_hdr = (void *) cmd->add_data; 858 indirect_hdr = (void *) cmd->add_data;
843 859
860 ib_dma_sync_single_for_cpu(ibdev, req->indirect_dma_addr,
861 target->indirect_size, DMA_TO_DEVICE);
862
844 memset(&state, 0, sizeof(state)); 863 memset(&state, 0, sizeof(state));
845 state.desc = indirect_hdr->desc_list; 864 state.desc = req->indirect_desc;
846 state.pages = req->map_page; 865 state.pages = req->map_page;
847 state.next_fmr = req->fmr_list; 866 state.next_fmr = req->fmr_list;
848 867
@@ -872,7 +891,11 @@ backtrack:
872 if (use_fmr == SRP_MAP_ALLOW_FMR && srp_map_finish_fmr(&state, target)) 891 if (use_fmr == SRP_MAP_ALLOW_FMR && srp_map_finish_fmr(&state, target))
873 goto backtrack; 892 goto backtrack;
874 893
875 /* We've mapped the request, fill in the command buffer. 894 /* We've mapped the request, now pull as much of the indirect
895 * descriptor table as we can into the command buffer. If this
896 * target is not using an external indirect table, we are
897 * guaranteed to fit into the command, as the SCSI layer won't
898 * give us more S/G entries than we allow.
876 */ 899 */
877 req->nfmr = state.nfmr; 900 req->nfmr = state.nfmr;
878 if (state.ndesc == 1) { 901 if (state.ndesc == 1) {
@@ -881,27 +904,39 @@ backtrack:
881 */ 904 */
882 struct srp_direct_buf *buf = (void *) cmd->add_data; 905 struct srp_direct_buf *buf = (void *) cmd->add_data;
883 906
884 *buf = indirect_hdr->desc_list[0]; 907 *buf = req->indirect_desc[0];
885 goto map_complete; 908 goto map_complete;
886 } 909 }
887 910
911 if (unlikely(target->cmd_sg_cnt < state.ndesc &&
912 !target->allow_ext_sg)) {
913 shost_printk(KERN_ERR, target->scsi_host,
914 "Could not fit S/G list into SRP_CMD\n");
915 return -EIO;
916 }
917
918 count = min(state.ndesc, target->cmd_sg_cnt);
888 table_len = state.ndesc * sizeof (struct srp_direct_buf); 919 table_len = state.ndesc * sizeof (struct srp_direct_buf);
889 920
890 fmt = SRP_DATA_DESC_INDIRECT; 921 fmt = SRP_DATA_DESC_INDIRECT;
891 len = sizeof(struct srp_cmd) + sizeof (struct srp_indirect_buf); 922 len = sizeof(struct srp_cmd) + sizeof (struct srp_indirect_buf);
892 len += table_len; 923 len += count * sizeof (struct srp_direct_buf);
893 924
894 indirect_addr = req->cmd->dma + sizeof *cmd + sizeof *indirect_hdr; 925 memcpy(indirect_hdr->desc_list, req->indirect_desc,
926 count * sizeof (struct srp_direct_buf));
895 927
896 indirect_hdr->table_desc.va = cpu_to_be64(indirect_addr); 928 indirect_hdr->table_desc.va = cpu_to_be64(req->indirect_dma_addr);
897 indirect_hdr->table_desc.key = cpu_to_be32(target->rkey); 929 indirect_hdr->table_desc.key = cpu_to_be32(target->rkey);
898 indirect_hdr->table_desc.len = cpu_to_be32(table_len); 930 indirect_hdr->table_desc.len = cpu_to_be32(table_len);
899 indirect_hdr->len = cpu_to_be32(state.total_len); 931 indirect_hdr->len = cpu_to_be32(state.total_len);
900 932
901 if (scmnd->sc_data_direction == DMA_TO_DEVICE) 933 if (scmnd->sc_data_direction == DMA_TO_DEVICE)
902 cmd->data_out_desc_cnt = state.ndesc; 934 cmd->data_out_desc_cnt = count;
903 else 935 else
904 cmd->data_in_desc_cnt = state.ndesc; 936 cmd->data_in_desc_cnt = count;
937
938 ib_dma_sync_single_for_device(ibdev, req->indirect_dma_addr, table_len,
939 DMA_TO_DEVICE);
905 940
906map_complete: 941map_complete:
907 if (scmnd->sc_data_direction == DMA_TO_DEVICE) 942 if (scmnd->sc_data_direction == DMA_TO_DEVICE)
@@ -1759,6 +1794,14 @@ static ssize_t show_cmd_sg_entries(struct device *dev,
1759 return sprintf(buf, "%u\n", target->cmd_sg_cnt); 1794 return sprintf(buf, "%u\n", target->cmd_sg_cnt);
1760} 1795}
1761 1796
1797static ssize_t show_allow_ext_sg(struct device *dev,
1798 struct device_attribute *attr, char *buf)
1799{
1800 struct srp_target_port *target = host_to_target(class_to_shost(dev));
1801
1802 return sprintf(buf, "%s\n", target->allow_ext_sg ? "true" : "false");
1803}
1804
1762static DEVICE_ATTR(id_ext, S_IRUGO, show_id_ext, NULL); 1805static DEVICE_ATTR(id_ext, S_IRUGO, show_id_ext, NULL);
1763static DEVICE_ATTR(ioc_guid, S_IRUGO, show_ioc_guid, NULL); 1806static DEVICE_ATTR(ioc_guid, S_IRUGO, show_ioc_guid, NULL);
1764static DEVICE_ATTR(service_id, S_IRUGO, show_service_id, NULL); 1807static DEVICE_ATTR(service_id, S_IRUGO, show_service_id, NULL);
@@ -1770,6 +1813,7 @@ static DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim, NULL);
1770static DEVICE_ATTR(local_ib_port, S_IRUGO, show_local_ib_port, NULL); 1813static DEVICE_ATTR(local_ib_port, S_IRUGO, show_local_ib_port, NULL);
1771static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL); 1814static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
1772static DEVICE_ATTR(cmd_sg_entries, S_IRUGO, show_cmd_sg_entries, NULL); 1815static DEVICE_ATTR(cmd_sg_entries, S_IRUGO, show_cmd_sg_entries, NULL);
1816static DEVICE_ATTR(allow_ext_sg, S_IRUGO, show_allow_ext_sg, NULL);
1773 1817
1774static struct device_attribute *srp_host_attrs[] = { 1818static struct device_attribute *srp_host_attrs[] = {
1775 &dev_attr_id_ext, 1819 &dev_attr_id_ext,
@@ -1783,6 +1827,7 @@ static struct device_attribute *srp_host_attrs[] = {
1783 &dev_attr_local_ib_port, 1827 &dev_attr_local_ib_port,
1784 &dev_attr_local_ib_device, 1828 &dev_attr_local_ib_device,
1785 &dev_attr_cmd_sg_entries, 1829 &dev_attr_cmd_sg_entries,
1830 &dev_attr_allow_ext_sg,
1786 NULL 1831 NULL
1787}; 1832};
1788 1833
@@ -1868,6 +1913,8 @@ enum {
1868 SRP_OPT_IO_CLASS = 1 << 7, 1913 SRP_OPT_IO_CLASS = 1 << 7,
1869 SRP_OPT_INITIATOR_EXT = 1 << 8, 1914 SRP_OPT_INITIATOR_EXT = 1 << 8,
1870 SRP_OPT_CMD_SG_ENTRIES = 1 << 9, 1915 SRP_OPT_CMD_SG_ENTRIES = 1 << 9,
1916 SRP_OPT_ALLOW_EXT_SG = 1 << 10,
1917 SRP_OPT_SG_TABLESIZE = 1 << 11,
1871 SRP_OPT_ALL = (SRP_OPT_ID_EXT | 1918 SRP_OPT_ALL = (SRP_OPT_ID_EXT |
1872 SRP_OPT_IOC_GUID | 1919 SRP_OPT_IOC_GUID |
1873 SRP_OPT_DGID | 1920 SRP_OPT_DGID |
@@ -1886,6 +1933,8 @@ static const match_table_t srp_opt_tokens = {
1886 { SRP_OPT_IO_CLASS, "io_class=%x" }, 1933 { SRP_OPT_IO_CLASS, "io_class=%x" },
1887 { SRP_OPT_INITIATOR_EXT, "initiator_ext=%s" }, 1934 { SRP_OPT_INITIATOR_EXT, "initiator_ext=%s" },
1888 { SRP_OPT_CMD_SG_ENTRIES, "cmd_sg_entries=%u" }, 1935 { SRP_OPT_CMD_SG_ENTRIES, "cmd_sg_entries=%u" },
1936 { SRP_OPT_ALLOW_EXT_SG, "allow_ext_sg=%u" },
1937 { SRP_OPT_SG_TABLESIZE, "sg_tablesize=%u" },
1889 { SRP_OPT_ERR, NULL } 1938 { SRP_OPT_ERR, NULL }
1890}; 1939};
1891 1940
@@ -2021,6 +2070,23 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
2021 target->cmd_sg_cnt = token; 2070 target->cmd_sg_cnt = token;
2022 break; 2071 break;
2023 2072
2073 case SRP_OPT_ALLOW_EXT_SG:
2074 if (match_int(args, &token)) {
2075 printk(KERN_WARNING PFX "bad allow_ext_sg parameter '%s'\n", p);
2076 goto out;
2077 }
2078 target->allow_ext_sg = !!token;
2079 break;
2080
2081 case SRP_OPT_SG_TABLESIZE:
2082 if (match_int(args, &token) || token < 1 ||
2083 token > SCSI_MAX_SG_CHAIN_SEGMENTS) {
2084 printk(KERN_WARNING PFX "bad max sg_tablesize parameter '%s'\n", p);
2085 goto out;
2086 }
2087 target->sg_tablesize = token;
2088 break;
2089
2024 default: 2090 default:
2025 printk(KERN_WARNING PFX "unknown parameter or missing value " 2091 printk(KERN_WARNING PFX "unknown parameter or missing value "
2026 "'%s' in target creation request\n", p); 2092 "'%s' in target creation request\n", p);
@@ -2051,6 +2117,8 @@ static ssize_t srp_create_target(struct device *dev,
2051 container_of(dev, struct srp_host, dev); 2117 container_of(dev, struct srp_host, dev);
2052 struct Scsi_Host *target_host; 2118 struct Scsi_Host *target_host;
2053 struct srp_target_port *target; 2119 struct srp_target_port *target;
2120 struct ib_device *ibdev = host->srp_dev->dev;
2121 dma_addr_t dma_addr;
2054 int i, ret; 2122 int i, ret;
2055 2123
2056 target_host = scsi_host_alloc(&srp_template, 2124 target_host = scsi_host_alloc(&srp_template,
@@ -2070,12 +2138,22 @@ static ssize_t srp_create_target(struct device *dev,
2070 target->lkey = host->srp_dev->mr->lkey; 2138 target->lkey = host->srp_dev->mr->lkey;
2071 target->rkey = host->srp_dev->mr->rkey; 2139 target->rkey = host->srp_dev->mr->rkey;
2072 target->cmd_sg_cnt = cmd_sg_entries; 2140 target->cmd_sg_cnt = cmd_sg_entries;
2141 target->sg_tablesize = indirect_sg_entries ? : cmd_sg_entries;
2142 target->allow_ext_sg = allow_ext_sg;
2073 2143
2074 ret = srp_parse_options(buf, target); 2144 ret = srp_parse_options(buf, target);
2075 if (ret) 2145 if (ret)
2076 goto err; 2146 goto err;
2077 2147
2078 target_host->sg_tablesize = target->cmd_sg_cnt; 2148 if (!host->srp_dev->fmr_pool && !target->allow_ext_sg &&
2149 target->cmd_sg_cnt < target->sg_tablesize) {
2150 printk(KERN_WARNING PFX "No FMR pool and no external indirect descriptors, limiting sg_tablesize to cmd_sg_cnt\n");
2151 target->sg_tablesize = target->cmd_sg_cnt;
2152 }
2153
2154 target_host->sg_tablesize = target->sg_tablesize;
2155 target->indirect_size = target->sg_tablesize *
2156 sizeof (struct srp_direct_buf);
2079 target->max_iu_len = sizeof (struct srp_cmd) + 2157 target->max_iu_len = sizeof (struct srp_cmd) +
2080 sizeof (struct srp_indirect_buf) + 2158 sizeof (struct srp_indirect_buf) +
2081 target->cmd_sg_cnt * sizeof (struct srp_direct_buf); 2159 target->cmd_sg_cnt * sizeof (struct srp_direct_buf);
@@ -2090,14 +2168,22 @@ static ssize_t srp_create_target(struct device *dev,
2090 GFP_KERNEL); 2168 GFP_KERNEL);
2091 req->map_page = kmalloc(SRP_FMR_SIZE * sizeof (void *), 2169 req->map_page = kmalloc(SRP_FMR_SIZE * sizeof (void *),
2092 GFP_KERNEL); 2170 GFP_KERNEL);
2093 if (!req->fmr_list || !req->map_page) 2171 req->indirect_desc = kmalloc(target->indirect_size, GFP_KERNEL);
2172 if (!req->fmr_list || !req->map_page || !req->indirect_desc)
2094 goto err_free_mem; 2173 goto err_free_mem;
2095 2174
2175 dma_addr = ib_dma_map_single(ibdev, req->indirect_desc,
2176 target->indirect_size,
2177 DMA_TO_DEVICE);
2178 if (ib_dma_mapping_error(ibdev, dma_addr))
2179 goto err_free_mem;
2180
2181 req->indirect_dma_addr = dma_addr;
2096 req->index = i; 2182 req->index = i;
2097 list_add_tail(&req->list, &target->free_reqs); 2183 list_add_tail(&req->list, &target->free_reqs);
2098 } 2184 }
2099 2185
2100 ib_query_gid(host->srp_dev->dev, host->port, 0, &target->path.sgid); 2186 ib_query_gid(ibdev, host->port, 0, &target->path.sgid);
2101 2187
2102 shost_printk(KERN_DEBUG, target->scsi_host, PFX 2188 shost_printk(KERN_DEBUG, target->scsi_host, PFX
2103 "new target: id_ext %016llx ioc_guid %016llx pkey %04x " 2189 "new target: id_ext %016llx ioc_guid %016llx pkey %04x "
@@ -2377,6 +2463,13 @@ static int __init srp_init_module(void)
2377 cmd_sg_entries = 255; 2463 cmd_sg_entries = 255;
2378 } 2464 }
2379 2465
2466 if (!indirect_sg_entries)
2467 indirect_sg_entries = cmd_sg_entries;
2468 else if (indirect_sg_entries < cmd_sg_entries) {
2469 printk(KERN_WARNING PFX "Bumping up indirect_sg_entries to match cmd_sg_entries (%u)\n", cmd_sg_entries);
2470 indirect_sg_entries = cmd_sg_entries;
2471 }
2472
2380 ib_srp_transport_template = 2473 ib_srp_transport_template =
2381 srp_attach_transport(&ib_srp_transport_functions); 2474 srp_attach_transport(&ib_srp_transport_functions);
2382 if (!ib_srp_transport_template) 2475 if (!ib_srp_transport_template)
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index b43b5e7acbde..cf696218eeeb 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -117,6 +117,8 @@ struct srp_request {
117 struct srp_iu *cmd; 117 struct srp_iu *cmd;
118 struct ib_pool_fmr **fmr_list; 118 struct ib_pool_fmr **fmr_list;
119 u64 *map_page; 119 u64 *map_page;
120 struct srp_direct_buf *indirect_desc;
121 dma_addr_t indirect_dma_addr;
120 short nfmr; 122 short nfmr;
121 short index; 123 short index;
122}; 124};
@@ -137,6 +139,8 @@ struct srp_target_port {
137 enum srp_target_state state; 139 enum srp_target_state state;
138 unsigned int max_iu_len; 140 unsigned int max_iu_len;
139 unsigned int cmd_sg_cnt; 141 unsigned int cmd_sg_cnt;
142 unsigned int indirect_size;
143 bool allow_ext_sg;
140 144
141 /* Everything above this point is used in the hot path of 145 /* Everything above this point is used in the hot path of
142 * command processing. Try to keep them packed into cachelines. 146 * command processing. Try to keep them packed into cachelines.
@@ -151,6 +155,7 @@ struct srp_target_port {
151 struct Scsi_Host *scsi_host; 155 struct Scsi_Host *scsi_host;
152 char target_name[32]; 156 char target_name[32];
153 unsigned int scsi_id; 157 unsigned int scsi_id;
158 unsigned int sg_tablesize;
154 159
155 struct ib_sa_path_rec path; 160 struct ib_sa_path_rec path;
156 __be16 orig_dgid[8]; 161 __be16 orig_dgid[8];