diff options
| author | Jiri Kosina <jkosina@suse.cz> | 2015-09-01 09:35:24 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2015-09-01 09:35:24 -0400 |
| commit | 067e2601d3c076abbf45db91261f9065eaa879b2 (patch) | |
| tree | 86c8d4b913873dbd3b4ff23562a3a8597984b4df /drivers/infiniband | |
| parent | 3e097d1271ecdff2f251a54ddfc5eaa1f9821e96 (diff) | |
| parent | 931830aa5c251e0803523213428f777a48bde254 (diff) | |
Merge branch 'for-4.3/gembird' into for-linus
Diffstat (limited to 'drivers/infiniband')
104 files changed, 3806 insertions, 2091 deletions
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 38339d220d7f..746cdf56bc76 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c | |||
| @@ -457,8 +457,8 @@ static void resolve_cb(int status, struct sockaddr *src_addr, | |||
| 457 | complete(&((struct resolve_cb_context *)context)->comp); | 457 | complete(&((struct resolve_cb_context *)context)->comp); |
| 458 | } | 458 | } |
| 459 | 459 | ||
| 460 | int rdma_addr_find_dmac_by_grh(union ib_gid *sgid, union ib_gid *dgid, u8 *dmac, | 460 | int rdma_addr_find_dmac_by_grh(const union ib_gid *sgid, const union ib_gid *dgid, |
| 461 | u16 *vlan_id) | 461 | u8 *dmac, u16 *vlan_id) |
| 462 | { | 462 | { |
| 463 | int ret = 0; | 463 | int ret = 0; |
| 464 | struct rdma_dev_addr dev_addr; | 464 | struct rdma_dev_addr dev_addr; |
diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c index f6d29614cb01..0429040304fd 100644 --- a/drivers/infiniband/core/agent.c +++ b/drivers/infiniband/core/agent.c | |||
| @@ -54,7 +54,7 @@ static DEFINE_SPINLOCK(ib_agent_port_list_lock); | |||
| 54 | static LIST_HEAD(ib_agent_port_list); | 54 | static LIST_HEAD(ib_agent_port_list); |
| 55 | 55 | ||
| 56 | static struct ib_agent_port_private * | 56 | static struct ib_agent_port_private * |
| 57 | __ib_get_agent_port(struct ib_device *device, int port_num) | 57 | __ib_get_agent_port(const struct ib_device *device, int port_num) |
| 58 | { | 58 | { |
| 59 | struct ib_agent_port_private *entry; | 59 | struct ib_agent_port_private *entry; |
| 60 | 60 | ||
| @@ -67,7 +67,7 @@ __ib_get_agent_port(struct ib_device *device, int port_num) | |||
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static struct ib_agent_port_private * | 69 | static struct ib_agent_port_private * |
| 70 | ib_get_agent_port(struct ib_device *device, int port_num) | 70 | ib_get_agent_port(const struct ib_device *device, int port_num) |
| 71 | { | 71 | { |
| 72 | struct ib_agent_port_private *entry; | 72 | struct ib_agent_port_private *entry; |
| 73 | unsigned long flags; | 73 | unsigned long flags; |
| @@ -78,9 +78,9 @@ ib_get_agent_port(struct ib_device *device, int port_num) | |||
| 78 | return entry; | 78 | return entry; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | void agent_send_response(struct ib_mad *mad, struct ib_grh *grh, | 81 | void agent_send_response(const struct ib_mad_hdr *mad_hdr, const struct ib_grh *grh, |
| 82 | struct ib_wc *wc, struct ib_device *device, | 82 | const struct ib_wc *wc, const struct ib_device *device, |
| 83 | int port_num, int qpn) | 83 | int port_num, int qpn, size_t resp_mad_len, bool opa) |
| 84 | { | 84 | { |
| 85 | struct ib_agent_port_private *port_priv; | 85 | struct ib_agent_port_private *port_priv; |
| 86 | struct ib_mad_agent *agent; | 86 | struct ib_mad_agent *agent; |
| @@ -88,7 +88,7 @@ void agent_send_response(struct ib_mad *mad, struct ib_grh *grh, | |||
| 88 | struct ib_ah *ah; | 88 | struct ib_ah *ah; |
| 89 | struct ib_mad_send_wr_private *mad_send_wr; | 89 | struct ib_mad_send_wr_private *mad_send_wr; |
| 90 | 90 | ||
| 91 | if (device->node_type == RDMA_NODE_IB_SWITCH) | 91 | if (rdma_cap_ib_switch(device)) |
| 92 | port_priv = ib_get_agent_port(device, 0); | 92 | port_priv = ib_get_agent_port(device, 0); |
| 93 | else | 93 | else |
| 94 | port_priv = ib_get_agent_port(device, port_num); | 94 | port_priv = ib_get_agent_port(device, port_num); |
| @@ -106,18 +106,23 @@ void agent_send_response(struct ib_mad *mad, struct ib_grh *grh, | |||
| 106 | return; | 106 | return; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | if (opa && mad_hdr->base_version != OPA_MGMT_BASE_VERSION) | ||
| 110 | resp_mad_len = IB_MGMT_MAD_SIZE; | ||
| 111 | |||
| 109 | send_buf = ib_create_send_mad(agent, wc->src_qp, wc->pkey_index, 0, | 112 | send_buf = ib_create_send_mad(agent, wc->src_qp, wc->pkey_index, 0, |
| 110 | IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA, | 113 | IB_MGMT_MAD_HDR, |
| 111 | GFP_KERNEL); | 114 | resp_mad_len - IB_MGMT_MAD_HDR, |
| 115 | GFP_KERNEL, | ||
| 116 | mad_hdr->base_version); | ||
| 112 | if (IS_ERR(send_buf)) { | 117 | if (IS_ERR(send_buf)) { |
| 113 | dev_err(&device->dev, "ib_create_send_mad error\n"); | 118 | dev_err(&device->dev, "ib_create_send_mad error\n"); |
| 114 | goto err1; | 119 | goto err1; |
| 115 | } | 120 | } |
| 116 | 121 | ||
| 117 | memcpy(send_buf->mad, mad, sizeof *mad); | 122 | memcpy(send_buf->mad, mad_hdr, resp_mad_len); |
| 118 | send_buf->ah = ah; | 123 | send_buf->ah = ah; |
| 119 | 124 | ||
| 120 | if (device->node_type == RDMA_NODE_IB_SWITCH) { | 125 | if (rdma_cap_ib_switch(device)) { |
| 121 | mad_send_wr = container_of(send_buf, | 126 | mad_send_wr = container_of(send_buf, |
| 122 | struct ib_mad_send_wr_private, | 127 | struct ib_mad_send_wr_private, |
| 123 | send_buf); | 128 | send_buf); |
| @@ -156,7 +161,7 @@ int ib_agent_port_open(struct ib_device *device, int port_num) | |||
| 156 | goto error1; | 161 | goto error1; |
| 157 | } | 162 | } |
| 158 | 163 | ||
| 159 | if (rdma_port_get_link_layer(device, port_num) == IB_LINK_LAYER_INFINIBAND) { | 164 | if (rdma_cap_ib_smi(device, port_num)) { |
| 160 | /* Obtain send only MAD agent for SMI QP */ | 165 | /* Obtain send only MAD agent for SMI QP */ |
| 161 | port_priv->agent[0] = ib_register_mad_agent(device, port_num, | 166 | port_priv->agent[0] = ib_register_mad_agent(device, port_num, |
| 162 | IB_QPT_SMI, NULL, 0, | 167 | IB_QPT_SMI, NULL, 0, |
diff --git a/drivers/infiniband/core/agent.h b/drivers/infiniband/core/agent.h index 6669287009c2..65f92bedae44 100644 --- a/drivers/infiniband/core/agent.h +++ b/drivers/infiniband/core/agent.h | |||
| @@ -44,8 +44,8 @@ extern int ib_agent_port_open(struct ib_device *device, int port_num); | |||
| 44 | 44 | ||
| 45 | extern int ib_agent_port_close(struct ib_device *device, int port_num); | 45 | extern int ib_agent_port_close(struct ib_device *device, int port_num); |
| 46 | 46 | ||
| 47 | extern void agent_send_response(struct ib_mad *mad, struct ib_grh *grh, | 47 | extern void agent_send_response(const struct ib_mad_hdr *mad_hdr, const struct ib_grh *grh, |
| 48 | struct ib_wc *wc, struct ib_device *device, | 48 | const struct ib_wc *wc, const struct ib_device *device, |
| 49 | int port_num, int qpn); | 49 | int port_num, int qpn, size_t resp_mad_len, bool opa); |
| 50 | 50 | ||
| 51 | #endif /* __AGENT_H_ */ | 51 | #endif /* __AGENT_H_ */ |
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 80f6cf2449fb..871da832d016 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c | |||
| @@ -58,17 +58,6 @@ struct ib_update_work { | |||
| 58 | u8 port_num; | 58 | u8 port_num; |
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | static inline int start_port(struct ib_device *device) | ||
| 62 | { | ||
| 63 | return (device->node_type == RDMA_NODE_IB_SWITCH) ? 0 : 1; | ||
| 64 | } | ||
| 65 | |||
| 66 | static inline int end_port(struct ib_device *device) | ||
| 67 | { | ||
| 68 | return (device->node_type == RDMA_NODE_IB_SWITCH) ? | ||
| 69 | 0 : device->phys_port_cnt; | ||
| 70 | } | ||
| 71 | |||
| 72 | int ib_get_cached_gid(struct ib_device *device, | 61 | int ib_get_cached_gid(struct ib_device *device, |
| 73 | u8 port_num, | 62 | u8 port_num, |
| 74 | int index, | 63 | int index, |
| @@ -78,12 +67,12 @@ int ib_get_cached_gid(struct ib_device *device, | |||
| 78 | unsigned long flags; | 67 | unsigned long flags; |
| 79 | int ret = 0; | 68 | int ret = 0; |
| 80 | 69 | ||
| 81 | if (port_num < start_port(device) || port_num > end_port(device)) | 70 | if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device)) |
| 82 | return -EINVAL; | 71 | return -EINVAL; |
| 83 | 72 | ||
| 84 | read_lock_irqsave(&device->cache.lock, flags); | 73 | read_lock_irqsave(&device->cache.lock, flags); |
| 85 | 74 | ||
| 86 | cache = device->cache.gid_cache[port_num - start_port(device)]; | 75 | cache = device->cache.gid_cache[port_num - rdma_start_port(device)]; |
| 87 | 76 | ||
| 88 | if (index < 0 || index >= cache->table_len) | 77 | if (index < 0 || index >= cache->table_len) |
| 89 | ret = -EINVAL; | 78 | ret = -EINVAL; |
| @@ -96,10 +85,10 @@ int ib_get_cached_gid(struct ib_device *device, | |||
| 96 | } | 85 | } |
| 97 | EXPORT_SYMBOL(ib_get_cached_gid); | 86 | EXPORT_SYMBOL(ib_get_cached_gid); |
| 98 | 87 | ||
| 99 | int ib_find_cached_gid(struct ib_device *device, | 88 | int ib_find_cached_gid(struct ib_device *device, |
| 100 | union ib_gid *gid, | 89 | const union ib_gid *gid, |
| 101 | u8 *port_num, | 90 | u8 *port_num, |
| 102 | u16 *index) | 91 | u16 *index) |
| 103 | { | 92 | { |
| 104 | struct ib_gid_cache *cache; | 93 | struct ib_gid_cache *cache; |
| 105 | unsigned long flags; | 94 | unsigned long flags; |
| @@ -112,11 +101,11 @@ int ib_find_cached_gid(struct ib_device *device, | |||
| 112 | 101 | ||
| 113 | read_lock_irqsave(&device->cache.lock, flags); | 102 | read_lock_irqsave(&device->cache.lock, flags); |
| 114 | 103 | ||
| 115 | for (p = 0; p <= end_port(device) - start_port(device); ++p) { | 104 | for (p = 0; p <= rdma_end_port(device) - rdma_start_port(device); ++p) { |
| 116 | cache = device->cache.gid_cache[p]; | 105 | cache = device->cache.gid_cache[p]; |
| 117 | for (i = 0; i < cache->table_len; ++i) { | 106 | for (i = 0; i < cache->table_len; ++i) { |
| 118 | if (!memcmp(gid, &cache->table[i], sizeof *gid)) { | 107 | if (!memcmp(gid, &cache->table[i], sizeof *gid)) { |
| 119 | *port_num = p + start_port(device); | 108 | *port_num = p + rdma_start_port(device); |
| 120 | if (index) | 109 | if (index) |
| 121 | *index = i; | 110 | *index = i; |
| 122 | ret = 0; | 111 | ret = 0; |
| @@ -140,12 +129,12 @@ int ib_get_cached_pkey(struct ib_device *device, | |||
| 140 | unsigned long flags; | 129 | unsigned long flags; |
| 141 | int ret = 0; | 130 | int ret = 0; |
| 142 | 131 | ||
| 143 | if (port_num < start_port(device) || port_num > end_port(device)) | 132 | if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device)) |
| 144 | return -EINVAL; | 133 | return -EINVAL; |
| 145 | 134 | ||
| 146 | read_lock_irqsave(&device->cache.lock, flags); | 135 | read_lock_irqsave(&device->cache.lock, flags); |
| 147 | 136 | ||
| 148 | cache = device->cache.pkey_cache[port_num - start_port(device)]; | 137 | cache = device->cache.pkey_cache[port_num - rdma_start_port(device)]; |
| 149 | 138 | ||
| 150 | if (index < 0 || index >= cache->table_len) | 139 | if (index < 0 || index >= cache->table_len) |
| 151 | ret = -EINVAL; | 140 | ret = -EINVAL; |
| @@ -169,12 +158,12 @@ int ib_find_cached_pkey(struct ib_device *device, | |||
| 169 | int ret = -ENOENT; | 158 | int ret = -ENOENT; |
| 170 | int partial_ix = -1; | 159 | int partial_ix = -1; |
| 171 | 160 | ||
| 172 | if (port_num < start_port(device) || port_num > end_port(device)) | 161 | if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device)) |
| 173 | return -EINVAL; | 162 | return -EINVAL; |
| 174 | 163 | ||
| 175 | read_lock_irqsave(&device->cache.lock, flags); | 164 | read_lock_irqsave(&device->cache.lock, flags); |
| 176 | 165 | ||
| 177 | cache = device->cache.pkey_cache[port_num - start_port(device)]; | 166 | cache = device->cache.pkey_cache[port_num - rdma_start_port(device)]; |
| 178 | 167 | ||
| 179 | *index = -1; | 168 | *index = -1; |
| 180 | 169 | ||
| @@ -209,12 +198,12 @@ int ib_find_exact_cached_pkey(struct ib_device *device, | |||
| 209 | int i; | 198 | int i; |
| 210 | int ret = -ENOENT; | 199 | int ret = -ENOENT; |
| 211 | 200 | ||
| 212 | if (port_num < start_port(device) || port_num > end_port(device)) | 201 | if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device)) |
| 213 | return -EINVAL; | 202 | return -EINVAL; |
| 214 | 203 | ||
| 215 | read_lock_irqsave(&device->cache.lock, flags); | 204 | read_lock_irqsave(&device->cache.lock, flags); |
| 216 | 205 | ||
| 217 | cache = device->cache.pkey_cache[port_num - start_port(device)]; | 206 | cache = device->cache.pkey_cache[port_num - rdma_start_port(device)]; |
| 218 | 207 | ||
| 219 | *index = -1; | 208 | *index = -1; |
| 220 | 209 | ||
| @@ -238,11 +227,11 @@ int ib_get_cached_lmc(struct ib_device *device, | |||
| 238 | unsigned long flags; | 227 | unsigned long flags; |
| 239 | int ret = 0; | 228 | int ret = 0; |
| 240 | 229 | ||
| 241 | if (port_num < start_port(device) || port_num > end_port(device)) | 230 | if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device)) |
| 242 | return -EINVAL; | 231 | return -EINVAL; |
| 243 | 232 | ||
| 244 | read_lock_irqsave(&device->cache.lock, flags); | 233 | read_lock_irqsave(&device->cache.lock, flags); |
| 245 | *lmc = device->cache.lmc_cache[port_num - start_port(device)]; | 234 | *lmc = device->cache.lmc_cache[port_num - rdma_start_port(device)]; |
| 246 | read_unlock_irqrestore(&device->cache.lock, flags); | 235 | read_unlock_irqrestore(&device->cache.lock, flags); |
| 247 | 236 | ||
| 248 | return ret; | 237 | return ret; |
| @@ -303,13 +292,13 @@ static void ib_cache_update(struct ib_device *device, | |||
| 303 | 292 | ||
| 304 | write_lock_irq(&device->cache.lock); | 293 | write_lock_irq(&device->cache.lock); |
| 305 | 294 | ||
| 306 | old_pkey_cache = device->cache.pkey_cache[port - start_port(device)]; | 295 | old_pkey_cache = device->cache.pkey_cache[port - rdma_start_port(device)]; |
| 307 | old_gid_cache = device->cache.gid_cache [port - start_port(device)]; | 296 | old_gid_cache = device->cache.gid_cache [port - rdma_start_port(device)]; |
| 308 | 297 | ||
| 309 | device->cache.pkey_cache[port - start_port(device)] = pkey_cache; | 298 | device->cache.pkey_cache[port - rdma_start_port(device)] = pkey_cache; |
| 310 | device->cache.gid_cache [port - start_port(device)] = gid_cache; | 299 | device->cache.gid_cache [port - rdma_start_port(device)] = gid_cache; |
| 311 | 300 | ||
| 312 | device->cache.lmc_cache[port - start_port(device)] = tprops->lmc; | 301 | device->cache.lmc_cache[port - rdma_start_port(device)] = tprops->lmc; |
| 313 | 302 | ||
| 314 | write_unlock_irq(&device->cache.lock); | 303 | write_unlock_irq(&device->cache.lock); |
| 315 | 304 | ||
| @@ -363,14 +352,14 @@ static void ib_cache_setup_one(struct ib_device *device) | |||
| 363 | 352 | ||
| 364 | device->cache.pkey_cache = | 353 | device->cache.pkey_cache = |
| 365 | kmalloc(sizeof *device->cache.pkey_cache * | 354 | kmalloc(sizeof *device->cache.pkey_cache * |
| 366 | (end_port(device) - start_port(device) + 1), GFP_KERNEL); | 355 | (rdma_end_port(device) - rdma_start_port(device) + 1), GFP_KERNEL); |
| 367 | device->cache.gid_cache = | 356 | device->cache.gid_cache = |
| 368 | kmalloc(sizeof *device->cache.gid_cache * | 357 | kmalloc(sizeof *device->cache.gid_cache * |
| 369 | (end_port(device) - start_port(device) + 1), GFP_KERNEL); | 358 | (rdma_end_port(device) - rdma_start_port(device) + 1), GFP_KERNEL); |
| 370 | 359 | ||
| 371 | device->cache.lmc_cache = kmalloc(sizeof *device->cache.lmc_cache * | 360 | device->cache.lmc_cache = kmalloc(sizeof *device->cache.lmc_cache * |
| 372 | (end_port(device) - | 361 | (rdma_end_port(device) - |
| 373 | start_port(device) + 1), | 362 | rdma_start_port(device) + 1), |
| 374 | GFP_KERNEL); | 363 | GFP_KERNEL); |
| 375 | 364 | ||
| 376 | if (!device->cache.pkey_cache || !device->cache.gid_cache || | 365 | if (!device->cache.pkey_cache || !device->cache.gid_cache || |
| @@ -380,10 +369,10 @@ static void ib_cache_setup_one(struct ib_device *device) | |||
| 380 | goto err; | 369 | goto err; |
| 381 | } | 370 | } |
| 382 | 371 | ||
| 383 | for (p = 0; p <= end_port(device) - start_port(device); ++p) { | 372 | for (p = 0; p <= rdma_end_port(device) - rdma_start_port(device); ++p) { |
| 384 | device->cache.pkey_cache[p] = NULL; | 373 | device->cache.pkey_cache[p] = NULL; |
| 385 | device->cache.gid_cache [p] = NULL; | 374 | device->cache.gid_cache [p] = NULL; |
| 386 | ib_cache_update(device, p + start_port(device)); | 375 | ib_cache_update(device, p + rdma_start_port(device)); |
| 387 | } | 376 | } |
| 388 | 377 | ||
| 389 | INIT_IB_EVENT_HANDLER(&device->cache.event_handler, | 378 | INIT_IB_EVENT_HANDLER(&device->cache.event_handler, |
| @@ -394,7 +383,7 @@ static void ib_cache_setup_one(struct ib_device *device) | |||
| 394 | return; | 383 | return; |
| 395 | 384 | ||
| 396 | err_cache: | 385 | err_cache: |
| 397 | for (p = 0; p <= end_port(device) - start_port(device); ++p) { | 386 | for (p = 0; p <= rdma_end_port(device) - rdma_start_port(device); ++p) { |
| 398 | kfree(device->cache.pkey_cache[p]); | 387 | kfree(device->cache.pkey_cache[p]); |
| 399 | kfree(device->cache.gid_cache[p]); | 388 | kfree(device->cache.gid_cache[p]); |
| 400 | } | 389 | } |
| @@ -412,7 +401,7 @@ static void ib_cache_cleanup_one(struct ib_device *device) | |||
| 412 | ib_unregister_event_handler(&device->cache.event_handler); | 401 | ib_unregister_event_handler(&device->cache.event_handler); |
| 413 | flush_workqueue(ib_wq); | 402 | flush_workqueue(ib_wq); |
| 414 | 403 | ||
| 415 | for (p = 0; p <= end_port(device) - start_port(device); ++p) { | 404 | for (p = 0; p <= rdma_end_port(device) - rdma_start_port(device); ++p) { |
| 416 | kfree(device->cache.pkey_cache[p]); | 405 | kfree(device->cache.pkey_cache[p]); |
| 417 | kfree(device->cache.gid_cache[p]); | 406 | kfree(device->cache.gid_cache[p]); |
| 418 | } | 407 | } |
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 0271608a51c4..3a972ebf3c0d 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
| @@ -169,6 +169,7 @@ struct cm_device { | |||
| 169 | struct ib_device *ib_device; | 169 | struct ib_device *ib_device; |
| 170 | struct device *device; | 170 | struct device *device; |
| 171 | u8 ack_delay; | 171 | u8 ack_delay; |
| 172 | int going_down; | ||
| 172 | struct cm_port *port[0]; | 173 | struct cm_port *port[0]; |
| 173 | }; | 174 | }; |
| 174 | 175 | ||
| @@ -267,7 +268,8 @@ static int cm_alloc_msg(struct cm_id_private *cm_id_priv, | |||
| 267 | m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn, | 268 | m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn, |
| 268 | cm_id_priv->av.pkey_index, | 269 | cm_id_priv->av.pkey_index, |
| 269 | 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA, | 270 | 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA, |
| 270 | GFP_ATOMIC); | 271 | GFP_ATOMIC, |
| 272 | IB_MGMT_BASE_VERSION); | ||
| 271 | if (IS_ERR(m)) { | 273 | if (IS_ERR(m)) { |
| 272 | ib_destroy_ah(ah); | 274 | ib_destroy_ah(ah); |
| 273 | return PTR_ERR(m); | 275 | return PTR_ERR(m); |
| @@ -297,7 +299,8 @@ static int cm_alloc_response_msg(struct cm_port *port, | |||
| 297 | 299 | ||
| 298 | m = ib_create_send_mad(port->mad_agent, 1, mad_recv_wc->wc->pkey_index, | 300 | m = ib_create_send_mad(port->mad_agent, 1, mad_recv_wc->wc->pkey_index, |
| 299 | 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA, | 301 | 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA, |
| 300 | GFP_ATOMIC); | 302 | GFP_ATOMIC, |
| 303 | IB_MGMT_BASE_VERSION); | ||
| 301 | if (IS_ERR(m)) { | 304 | if (IS_ERR(m)) { |
| 302 | ib_destroy_ah(ah); | 305 | ib_destroy_ah(ah); |
| 303 | return PTR_ERR(m); | 306 | return PTR_ERR(m); |
| @@ -803,6 +806,11 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv) | |||
| 803 | { | 806 | { |
| 804 | int wait_time; | 807 | int wait_time; |
| 805 | unsigned long flags; | 808 | unsigned long flags; |
| 809 | struct cm_device *cm_dev; | ||
| 810 | |||
| 811 | cm_dev = ib_get_client_data(cm_id_priv->id.device, &cm_client); | ||
| 812 | if (!cm_dev) | ||
| 813 | return; | ||
| 806 | 814 | ||
| 807 | spin_lock_irqsave(&cm.lock, flags); | 815 | spin_lock_irqsave(&cm.lock, flags); |
| 808 | cm_cleanup_timewait(cm_id_priv->timewait_info); | 816 | cm_cleanup_timewait(cm_id_priv->timewait_info); |
| @@ -816,8 +824,14 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv) | |||
| 816 | */ | 824 | */ |
| 817 | cm_id_priv->id.state = IB_CM_TIMEWAIT; | 825 | cm_id_priv->id.state = IB_CM_TIMEWAIT; |
| 818 | wait_time = cm_convert_to_ms(cm_id_priv->av.timeout); | 826 | wait_time = cm_convert_to_ms(cm_id_priv->av.timeout); |
| 819 | queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work, | 827 | |
| 820 | msecs_to_jiffies(wait_time)); | 828 | /* Check if the device started its remove_one */ |
| 829 | spin_lock_irq(&cm.lock); | ||
| 830 | if (!cm_dev->going_down) | ||
| 831 | queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work, | ||
| 832 | msecs_to_jiffies(wait_time)); | ||
| 833 | spin_unlock_irq(&cm.lock); | ||
| 834 | |||
| 821 | cm_id_priv->timewait_info = NULL; | 835 | cm_id_priv->timewait_info = NULL; |
| 822 | } | 836 | } |
| 823 | 837 | ||
| @@ -3303,6 +3317,11 @@ static int cm_establish(struct ib_cm_id *cm_id) | |||
| 3303 | struct cm_work *work; | 3317 | struct cm_work *work; |
| 3304 | unsigned long flags; | 3318 | unsigned long flags; |
| 3305 | int ret = 0; | 3319 | int ret = 0; |
| 3320 | struct cm_device *cm_dev; | ||
| 3321 | |||
| 3322 | cm_dev = ib_get_client_data(cm_id->device, &cm_client); | ||
| 3323 | if (!cm_dev) | ||
| 3324 | return -ENODEV; | ||
| 3306 | 3325 | ||
| 3307 | work = kmalloc(sizeof *work, GFP_ATOMIC); | 3326 | work = kmalloc(sizeof *work, GFP_ATOMIC); |
| 3308 | if (!work) | 3327 | if (!work) |
| @@ -3341,7 +3360,17 @@ static int cm_establish(struct ib_cm_id *cm_id) | |||
| 3341 | work->remote_id = cm_id->remote_id; | 3360 | work->remote_id = cm_id->remote_id; |
| 3342 | work->mad_recv_wc = NULL; | 3361 | work->mad_recv_wc = NULL; |
| 3343 | work->cm_event.event = IB_CM_USER_ESTABLISHED; | 3362 | work->cm_event.event = IB_CM_USER_ESTABLISHED; |
| 3344 | queue_delayed_work(cm.wq, &work->work, 0); | 3363 | |
| 3364 | /* Check if the device started its remove_one */ | ||
| 3365 | spin_lock_irq(&cm.lock); | ||
| 3366 | if (!cm_dev->going_down) { | ||
| 3367 | queue_delayed_work(cm.wq, &work->work, 0); | ||
| 3368 | } else { | ||
| 3369 | kfree(work); | ||
| 3370 | ret = -ENODEV; | ||
| 3371 | } | ||
| 3372 | spin_unlock_irq(&cm.lock); | ||
| 3373 | |||
| 3345 | out: | 3374 | out: |
| 3346 | return ret; | 3375 | return ret; |
| 3347 | } | 3376 | } |
| @@ -3392,6 +3421,7 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent, | |||
| 3392 | enum ib_cm_event_type event; | 3421 | enum ib_cm_event_type event; |
| 3393 | u16 attr_id; | 3422 | u16 attr_id; |
| 3394 | int paths = 0; | 3423 | int paths = 0; |
| 3424 | int going_down = 0; | ||
| 3395 | 3425 | ||
| 3396 | switch (mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) { | 3426 | switch (mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) { |
| 3397 | case CM_REQ_ATTR_ID: | 3427 | case CM_REQ_ATTR_ID: |
| @@ -3450,7 +3480,19 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent, | |||
| 3450 | work->cm_event.event = event; | 3480 | work->cm_event.event = event; |
| 3451 | work->mad_recv_wc = mad_recv_wc; | 3481 | work->mad_recv_wc = mad_recv_wc; |
| 3452 | work->port = port; | 3482 | work->port = port; |
| 3453 | queue_delayed_work(cm.wq, &work->work, 0); | 3483 | |
| 3484 | /* Check if the device started its remove_one */ | ||
| 3485 | spin_lock_irq(&cm.lock); | ||
| 3486 | if (!port->cm_dev->going_down) | ||
| 3487 | queue_delayed_work(cm.wq, &work->work, 0); | ||
| 3488 | else | ||
| 3489 | going_down = 1; | ||
| 3490 | spin_unlock_irq(&cm.lock); | ||
| 3491 | |||
| 3492 | if (going_down) { | ||
| 3493 | kfree(work); | ||
| 3494 | ib_free_recv_mad(mad_recv_wc); | ||
| 3495 | } | ||
| 3454 | } | 3496 | } |
| 3455 | 3497 | ||
| 3456 | static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv, | 3498 | static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv, |
| @@ -3759,11 +3801,9 @@ static void cm_add_one(struct ib_device *ib_device) | |||
| 3759 | }; | 3801 | }; |
| 3760 | unsigned long flags; | 3802 | unsigned long flags; |
| 3761 | int ret; | 3803 | int ret; |
| 3804 | int count = 0; | ||
| 3762 | u8 i; | 3805 | u8 i; |
| 3763 | 3806 | ||
| 3764 | if (rdma_node_get_transport(ib_device->node_type) != RDMA_TRANSPORT_IB) | ||
| 3765 | return; | ||
| 3766 | |||
| 3767 | cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) * | 3807 | cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) * |
| 3768 | ib_device->phys_port_cnt, GFP_KERNEL); | 3808 | ib_device->phys_port_cnt, GFP_KERNEL); |
| 3769 | if (!cm_dev) | 3809 | if (!cm_dev) |
| @@ -3771,7 +3811,7 @@ static void cm_add_one(struct ib_device *ib_device) | |||
| 3771 | 3811 | ||
| 3772 | cm_dev->ib_device = ib_device; | 3812 | cm_dev->ib_device = ib_device; |
| 3773 | cm_get_ack_delay(cm_dev); | 3813 | cm_get_ack_delay(cm_dev); |
| 3774 | 3814 | cm_dev->going_down = 0; | |
| 3775 | cm_dev->device = device_create(&cm_class, &ib_device->dev, | 3815 | cm_dev->device = device_create(&cm_class, &ib_device->dev, |
| 3776 | MKDEV(0, 0), NULL, | 3816 | MKDEV(0, 0), NULL, |
| 3777 | "%s", ib_device->name); | 3817 | "%s", ib_device->name); |
| @@ -3782,6 +3822,9 @@ static void cm_add_one(struct ib_device *ib_device) | |||
| 3782 | 3822 | ||
| 3783 | set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); | 3823 | set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); |
| 3784 | for (i = 1; i <= ib_device->phys_port_cnt; i++) { | 3824 | for (i = 1; i <= ib_device->phys_port_cnt; i++) { |
| 3825 | if (!rdma_cap_ib_cm(ib_device, i)) | ||
| 3826 | continue; | ||
| 3827 | |||
| 3785 | port = kzalloc(sizeof *port, GFP_KERNEL); | 3828 | port = kzalloc(sizeof *port, GFP_KERNEL); |
| 3786 | if (!port) | 3829 | if (!port) |
| 3787 | goto error1; | 3830 | goto error1; |
| @@ -3808,7 +3851,13 @@ static void cm_add_one(struct ib_device *ib_device) | |||
| 3808 | ret = ib_modify_port(ib_device, i, 0, &port_modify); | 3851 | ret = ib_modify_port(ib_device, i, 0, &port_modify); |
| 3809 | if (ret) | 3852 | if (ret) |
| 3810 | goto error3; | 3853 | goto error3; |
| 3854 | |||
| 3855 | count++; | ||
| 3811 | } | 3856 | } |
| 3857 | |||
| 3858 | if (!count) | ||
| 3859 | goto free; | ||
| 3860 | |||
| 3812 | ib_set_client_data(ib_device, &cm_client, cm_dev); | 3861 | ib_set_client_data(ib_device, &cm_client, cm_dev); |
| 3813 | 3862 | ||
| 3814 | write_lock_irqsave(&cm.device_lock, flags); | 3863 | write_lock_irqsave(&cm.device_lock, flags); |
| @@ -3824,11 +3873,15 @@ error1: | |||
| 3824 | port_modify.set_port_cap_mask = 0; | 3873 | port_modify.set_port_cap_mask = 0; |
| 3825 | port_modify.clr_port_cap_mask = IB_PORT_CM_SUP; | 3874 | port_modify.clr_port_cap_mask = IB_PORT_CM_SUP; |
| 3826 | while (--i) { | 3875 | while (--i) { |
| 3876 | if (!rdma_cap_ib_cm(ib_device, i)) | ||
| 3877 | continue; | ||
| 3878 | |||
| 3827 | port = cm_dev->port[i-1]; | 3879 | port = cm_dev->port[i-1]; |
| 3828 | ib_modify_port(ib_device, port->port_num, 0, &port_modify); | 3880 | ib_modify_port(ib_device, port->port_num, 0, &port_modify); |
| 3829 | ib_unregister_mad_agent(port->mad_agent); | 3881 | ib_unregister_mad_agent(port->mad_agent); |
| 3830 | cm_remove_port_fs(port); | 3882 | cm_remove_port_fs(port); |
| 3831 | } | 3883 | } |
| 3884 | free: | ||
| 3832 | device_unregister(cm_dev->device); | 3885 | device_unregister(cm_dev->device); |
| 3833 | kfree(cm_dev); | 3886 | kfree(cm_dev); |
| 3834 | } | 3887 | } |
| @@ -3851,11 +3904,23 @@ static void cm_remove_one(struct ib_device *ib_device) | |||
| 3851 | list_del(&cm_dev->list); | 3904 | list_del(&cm_dev->list); |
| 3852 | write_unlock_irqrestore(&cm.device_lock, flags); | 3905 | write_unlock_irqrestore(&cm.device_lock, flags); |
| 3853 | 3906 | ||
| 3907 | spin_lock_irq(&cm.lock); | ||
| 3908 | cm_dev->going_down = 1; | ||
| 3909 | spin_unlock_irq(&cm.lock); | ||
| 3910 | |||
| 3854 | for (i = 1; i <= ib_device->phys_port_cnt; i++) { | 3911 | for (i = 1; i <= ib_device->phys_port_cnt; i++) { |
| 3912 | if (!rdma_cap_ib_cm(ib_device, i)) | ||
| 3913 | continue; | ||
| 3914 | |||
| 3855 | port = cm_dev->port[i-1]; | 3915 | port = cm_dev->port[i-1]; |
| 3856 | ib_modify_port(ib_device, port->port_num, 0, &port_modify); | 3916 | ib_modify_port(ib_device, port->port_num, 0, &port_modify); |
| 3857 | ib_unregister_mad_agent(port->mad_agent); | 3917 | /* |
| 3918 | * We flush the queue here after the going_down set, this | ||
| 3919 | * verify that no new works will be queued in the recv handler, | ||
| 3920 | * after that we can call the unregister_mad_agent | ||
| 3921 | */ | ||
| 3858 | flush_workqueue(cm.wq); | 3922 | flush_workqueue(cm.wq); |
| 3923 | ib_unregister_mad_agent(port->mad_agent); | ||
| 3859 | cm_remove_port_fs(port); | 3924 | cm_remove_port_fs(port); |
| 3860 | } | 3925 | } |
| 3861 | device_unregister(cm_dev->device); | 3926 | device_unregister(cm_dev->device); |
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 38ffe0981503..143ded2bbe7c 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
| @@ -65,6 +65,34 @@ MODULE_LICENSE("Dual BSD/GPL"); | |||
| 65 | #define CMA_CM_MRA_SETTING (IB_CM_MRA_FLAG_DELAY | 24) | 65 | #define CMA_CM_MRA_SETTING (IB_CM_MRA_FLAG_DELAY | 24) |
| 66 | #define CMA_IBOE_PACKET_LIFETIME 18 | 66 | #define CMA_IBOE_PACKET_LIFETIME 18 |
| 67 | 67 | ||
| 68 | static const char * const cma_events[] = { | ||
| 69 | [RDMA_CM_EVENT_ADDR_RESOLVED] = "address resolved", | ||
| 70 | [RDMA_CM_EVENT_ADDR_ERROR] = "address error", | ||
| 71 | [RDMA_CM_EVENT_ROUTE_RESOLVED] = "route resolved ", | ||
| 72 | [RDMA_CM_EVENT_ROUTE_ERROR] = "route error", | ||
| 73 | [RDMA_CM_EVENT_CONNECT_REQUEST] = "connect request", | ||
| 74 | [RDMA_CM_EVENT_CONNECT_RESPONSE] = "connect response", | ||
| 75 | [RDMA_CM_EVENT_CONNECT_ERROR] = "connect error", | ||
| 76 | [RDMA_CM_EVENT_UNREACHABLE] = "unreachable", | ||
| 77 | [RDMA_CM_EVENT_REJECTED] = "rejected", | ||
| 78 | [RDMA_CM_EVENT_ESTABLISHED] = "established", | ||
| 79 | [RDMA_CM_EVENT_DISCONNECTED] = "disconnected", | ||
| 80 | [RDMA_CM_EVENT_DEVICE_REMOVAL] = "device removal", | ||
| 81 | [RDMA_CM_EVENT_MULTICAST_JOIN] = "multicast join", | ||
| 82 | [RDMA_CM_EVENT_MULTICAST_ERROR] = "multicast error", | ||
| 83 | [RDMA_CM_EVENT_ADDR_CHANGE] = "address change", | ||
| 84 | [RDMA_CM_EVENT_TIMEWAIT_EXIT] = "timewait exit", | ||
| 85 | }; | ||
| 86 | |||
| 87 | const char *rdma_event_msg(enum rdma_cm_event_type event) | ||
| 88 | { | ||
| 89 | size_t index = event; | ||
| 90 | |||
| 91 | return (index < ARRAY_SIZE(cma_events) && cma_events[index]) ? | ||
| 92 | cma_events[index] : "unrecognized event"; | ||
| 93 | } | ||
| 94 | EXPORT_SYMBOL(rdma_event_msg); | ||
| 95 | |||
| 68 | static void cma_add_one(struct ib_device *device); | 96 | static void cma_add_one(struct ib_device *device); |
| 69 | static void cma_remove_one(struct ib_device *device); | 97 | static void cma_remove_one(struct ib_device *device); |
| 70 | 98 | ||
| @@ -349,18 +377,35 @@ static int cma_translate_addr(struct sockaddr *addr, struct rdma_dev_addr *dev_a | |||
| 349 | return ret; | 377 | return ret; |
| 350 | } | 378 | } |
| 351 | 379 | ||
| 380 | static inline int cma_validate_port(struct ib_device *device, u8 port, | ||
| 381 | union ib_gid *gid, int dev_type) | ||
| 382 | { | ||
| 383 | u8 found_port; | ||
| 384 | int ret = -ENODEV; | ||
| 385 | |||
| 386 | if ((dev_type == ARPHRD_INFINIBAND) && !rdma_protocol_ib(device, port)) | ||
| 387 | return ret; | ||
| 388 | |||
| 389 | if ((dev_type != ARPHRD_INFINIBAND) && rdma_protocol_ib(device, port)) | ||
| 390 | return ret; | ||
| 391 | |||
| 392 | ret = ib_find_cached_gid(device, gid, &found_port, NULL); | ||
| 393 | if (port != found_port) | ||
| 394 | return -ENODEV; | ||
| 395 | |||
| 396 | return ret; | ||
| 397 | } | ||
| 398 | |||
| 352 | static int cma_acquire_dev(struct rdma_id_private *id_priv, | 399 | static int cma_acquire_dev(struct rdma_id_private *id_priv, |
| 353 | struct rdma_id_private *listen_id_priv) | 400 | struct rdma_id_private *listen_id_priv) |
| 354 | { | 401 | { |
| 355 | struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr; | 402 | struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr; |
| 356 | struct cma_device *cma_dev; | 403 | struct cma_device *cma_dev; |
| 357 | union ib_gid gid, iboe_gid; | 404 | union ib_gid gid, iboe_gid, *gidp; |
| 358 | int ret = -ENODEV; | 405 | int ret = -ENODEV; |
| 359 | u8 port, found_port; | 406 | u8 port; |
| 360 | enum rdma_link_layer dev_ll = dev_addr->dev_type == ARPHRD_INFINIBAND ? | ||
| 361 | IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET; | ||
| 362 | 407 | ||
| 363 | if (dev_ll != IB_LINK_LAYER_INFINIBAND && | 408 | if (dev_addr->dev_type != ARPHRD_INFINIBAND && |
| 364 | id_priv->id.ps == RDMA_PS_IPOIB) | 409 | id_priv->id.ps == RDMA_PS_IPOIB) |
| 365 | return -EINVAL; | 410 | return -EINVAL; |
| 366 | 411 | ||
| @@ -370,41 +415,36 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv, | |||
| 370 | 415 | ||
| 371 | memcpy(&gid, dev_addr->src_dev_addr + | 416 | memcpy(&gid, dev_addr->src_dev_addr + |
| 372 | rdma_addr_gid_offset(dev_addr), sizeof gid); | 417 | rdma_addr_gid_offset(dev_addr), sizeof gid); |
| 373 | if (listen_id_priv && | 418 | |
| 374 | rdma_port_get_link_layer(listen_id_priv->id.device, | 419 | if (listen_id_priv) { |
| 375 | listen_id_priv->id.port_num) == dev_ll) { | ||
| 376 | cma_dev = listen_id_priv->cma_dev; | 420 | cma_dev = listen_id_priv->cma_dev; |
| 377 | port = listen_id_priv->id.port_num; | 421 | port = listen_id_priv->id.port_num; |
| 378 | if (rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB && | 422 | gidp = rdma_protocol_roce(cma_dev->device, port) ? |
| 379 | rdma_port_get_link_layer(cma_dev->device, port) == IB_LINK_LAYER_ETHERNET) | 423 | &iboe_gid : &gid; |
| 380 | ret = ib_find_cached_gid(cma_dev->device, &iboe_gid, | ||
| 381 | &found_port, NULL); | ||
| 382 | else | ||
| 383 | ret = ib_find_cached_gid(cma_dev->device, &gid, | ||
| 384 | &found_port, NULL); | ||
| 385 | 424 | ||
| 386 | if (!ret && (port == found_port)) { | 425 | ret = cma_validate_port(cma_dev->device, port, gidp, |
| 387 | id_priv->id.port_num = found_port; | 426 | dev_addr->dev_type); |
| 427 | if (!ret) { | ||
| 428 | id_priv->id.port_num = port; | ||
| 388 | goto out; | 429 | goto out; |
| 389 | } | 430 | } |
| 390 | } | 431 | } |
| 432 | |||
| 391 | list_for_each_entry(cma_dev, &dev_list, list) { | 433 | list_for_each_entry(cma_dev, &dev_list, list) { |
| 392 | for (port = 1; port <= cma_dev->device->phys_port_cnt; ++port) { | 434 | for (port = 1; port <= cma_dev->device->phys_port_cnt; ++port) { |
| 393 | if (listen_id_priv && | 435 | if (listen_id_priv && |
| 394 | listen_id_priv->cma_dev == cma_dev && | 436 | listen_id_priv->cma_dev == cma_dev && |
| 395 | listen_id_priv->id.port_num == port) | 437 | listen_id_priv->id.port_num == port) |
| 396 | continue; | 438 | continue; |
| 397 | if (rdma_port_get_link_layer(cma_dev->device, port) == dev_ll) { | 439 | |
| 398 | if (rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB && | 440 | gidp = rdma_protocol_roce(cma_dev->device, port) ? |
| 399 | rdma_port_get_link_layer(cma_dev->device, port) == IB_LINK_LAYER_ETHERNET) | 441 | &iboe_gid : &gid; |
| 400 | ret = ib_find_cached_gid(cma_dev->device, &iboe_gid, &found_port, NULL); | 442 | |
| 401 | else | 443 | ret = cma_validate_port(cma_dev->device, port, gidp, |
| 402 | ret = ib_find_cached_gid(cma_dev->device, &gid, &found_port, NULL); | 444 | dev_addr->dev_type); |
| 403 | 445 | if (!ret) { | |
| 404 | if (!ret && (port == found_port)) { | 446 | id_priv->id.port_num = port; |
| 405 | id_priv->id.port_num = found_port; | 447 | goto out; |
| 406 | goto out; | ||
| 407 | } | ||
| 408 | } | 448 | } |
| 409 | } | 449 | } |
| 410 | } | 450 | } |
| @@ -435,10 +475,10 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) | |||
| 435 | pkey = ntohs(addr->sib_pkey); | 475 | pkey = ntohs(addr->sib_pkey); |
| 436 | 476 | ||
| 437 | list_for_each_entry(cur_dev, &dev_list, list) { | 477 | list_for_each_entry(cur_dev, &dev_list, list) { |
| 438 | if (rdma_node_get_transport(cur_dev->device->node_type) != RDMA_TRANSPORT_IB) | ||
| 439 | continue; | ||
| 440 | |||
| 441 | for (p = 1; p <= cur_dev->device->phys_port_cnt; ++p) { | 478 | for (p = 1; p <= cur_dev->device->phys_port_cnt; ++p) { |
| 479 | if (!rdma_cap_af_ib(cur_dev->device, p)) | ||
| 480 | continue; | ||
| 481 | |||
| 442 | if (ib_find_cached_pkey(cur_dev->device, p, pkey, &index)) | 482 | if (ib_find_cached_pkey(cur_dev->device, p, pkey, &index)) |
| 443 | continue; | 483 | continue; |
| 444 | 484 | ||
| @@ -633,10 +673,9 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv, | |||
| 633 | if (ret) | 673 | if (ret) |
| 634 | goto out; | 674 | goto out; |
| 635 | 675 | ||
| 636 | if (rdma_node_get_transport(id_priv->cma_dev->device->node_type) | 676 | BUG_ON(id_priv->cma_dev->device != id_priv->id.device); |
| 637 | == RDMA_TRANSPORT_IB && | 677 | |
| 638 | rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num) | 678 | if (rdma_protocol_roce(id_priv->id.device, id_priv->id.port_num)) { |
| 639 | == IB_LINK_LAYER_ETHERNET) { | ||
| 640 | ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr.smac, NULL); | 679 | ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr.smac, NULL); |
| 641 | 680 | ||
| 642 | if (ret) | 681 | if (ret) |
| @@ -700,11 +739,10 @@ static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv, | |||
| 700 | int ret; | 739 | int ret; |
| 701 | u16 pkey; | 740 | u16 pkey; |
| 702 | 741 | ||
| 703 | if (rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num) == | 742 | if (rdma_cap_eth_ah(id_priv->id.device, id_priv->id.port_num)) |
| 704 | IB_LINK_LAYER_INFINIBAND) | ||
| 705 | pkey = ib_addr_get_pkey(dev_addr); | ||
| 706 | else | ||
| 707 | pkey = 0xffff; | 743 | pkey = 0xffff; |
| 744 | else | ||
| 745 | pkey = ib_addr_get_pkey(dev_addr); | ||
| 708 | 746 | ||
| 709 | ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num, | 747 | ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num, |
| 710 | pkey, &qp_attr->pkey_index); | 748 | pkey, &qp_attr->pkey_index); |
| @@ -735,8 +773,7 @@ int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr, | |||
| 735 | int ret = 0; | 773 | int ret = 0; |
| 736 | 774 | ||
| 737 | id_priv = container_of(id, struct rdma_id_private, id); | 775 | id_priv = container_of(id, struct rdma_id_private, id); |
| 738 | switch (rdma_node_get_transport(id_priv->id.device->node_type)) { | 776 | if (rdma_cap_ib_cm(id->device, id->port_num)) { |
| 739 | case RDMA_TRANSPORT_IB: | ||
| 740 | if (!id_priv->cm_id.ib || (id_priv->id.qp_type == IB_QPT_UD)) | 777 | if (!id_priv->cm_id.ib || (id_priv->id.qp_type == IB_QPT_UD)) |
| 741 | ret = cma_ib_init_qp_attr(id_priv, qp_attr, qp_attr_mask); | 778 | ret = cma_ib_init_qp_attr(id_priv, qp_attr, qp_attr_mask); |
| 742 | else | 779 | else |
| @@ -745,19 +782,15 @@ int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr, | |||
| 745 | 782 | ||
| 746 | if (qp_attr->qp_state == IB_QPS_RTR) | 783 | if (qp_attr->qp_state == IB_QPS_RTR) |
| 747 | qp_attr->rq_psn = id_priv->seq_num; | 784 | qp_attr->rq_psn = id_priv->seq_num; |
| 748 | break; | 785 | } else if (rdma_cap_iw_cm(id->device, id->port_num)) { |
| 749 | case RDMA_TRANSPORT_IWARP: | ||
| 750 | if (!id_priv->cm_id.iw) { | 786 | if (!id_priv->cm_id.iw) { |
| 751 | qp_attr->qp_access_flags = 0; | 787 | qp_attr->qp_access_flags = 0; |
| 752 | *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS; | 788 | *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS; |
| 753 | } else | 789 | } else |
| 754 | ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr, | 790 | ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr, |
| 755 | qp_attr_mask); | 791 | qp_attr_mask); |
| 756 | break; | 792 | } else |
| 757 | default: | ||
| 758 | ret = -ENOSYS; | 793 | ret = -ENOSYS; |
| 759 | break; | ||
| 760 | } | ||
| 761 | 794 | ||
| 762 | return ret; | 795 | return ret; |
| 763 | } | 796 | } |
| @@ -945,13 +978,9 @@ static inline int cma_user_data_offset(struct rdma_id_private *id_priv) | |||
| 945 | 978 | ||
| 946 | static void cma_cancel_route(struct rdma_id_private *id_priv) | 979 | static void cma_cancel_route(struct rdma_id_private *id_priv) |
| 947 | { | 980 | { |
| 948 | switch (rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num)) { | 981 | if (rdma_cap_ib_sa(id_priv->id.device, id_priv->id.port_num)) { |
| 949 | case IB_LINK_LAYER_INFINIBAND: | ||
| 950 | if (id_priv->query) | 982 | if (id_priv->query) |
| 951 | ib_sa_cancel_query(id_priv->query_id, id_priv->query); | 983 | ib_sa_cancel_query(id_priv->query_id, id_priv->query); |
| 952 | break; | ||
| 953 | default: | ||
| 954 | break; | ||
| 955 | } | 984 | } |
| 956 | } | 985 | } |
| 957 | 986 | ||
| @@ -1023,17 +1052,12 @@ static void cma_leave_mc_groups(struct rdma_id_private *id_priv) | |||
| 1023 | mc = container_of(id_priv->mc_list.next, | 1052 | mc = container_of(id_priv->mc_list.next, |
| 1024 | struct cma_multicast, list); | 1053 | struct cma_multicast, list); |
| 1025 | list_del(&mc->list); | 1054 | list_del(&mc->list); |
| 1026 | switch (rdma_port_get_link_layer(id_priv->cma_dev->device, id_priv->id.port_num)) { | 1055 | if (rdma_cap_ib_mcast(id_priv->cma_dev->device, |
| 1027 | case IB_LINK_LAYER_INFINIBAND: | 1056 | id_priv->id.port_num)) { |
| 1028 | ib_sa_free_multicast(mc->multicast.ib); | 1057 | ib_sa_free_multicast(mc->multicast.ib); |
| 1029 | kfree(mc); | 1058 | kfree(mc); |
| 1030 | break; | 1059 | } else |
| 1031 | case IB_LINK_LAYER_ETHERNET: | ||
| 1032 | kref_put(&mc->mcref, release_mc); | 1060 | kref_put(&mc->mcref, release_mc); |
| 1033 | break; | ||
| 1034 | default: | ||
| 1035 | break; | ||
| 1036 | } | ||
| 1037 | } | 1061 | } |
| 1038 | } | 1062 | } |
| 1039 | 1063 | ||
| @@ -1054,17 +1078,12 @@ void rdma_destroy_id(struct rdma_cm_id *id) | |||
| 1054 | mutex_unlock(&id_priv->handler_mutex); | 1078 | mutex_unlock(&id_priv->handler_mutex); |
| 1055 | 1079 | ||
| 1056 | if (id_priv->cma_dev) { | 1080 | if (id_priv->cma_dev) { |
| 1057 | switch (rdma_node_get_transport(id_priv->id.device->node_type)) { | 1081 | if (rdma_cap_ib_cm(id_priv->id.device, 1)) { |
| 1058 | case RDMA_TRANSPORT_IB: | ||
| 1059 | if (id_priv->cm_id.ib) | 1082 | if (id_priv->cm_id.ib) |
| 1060 | ib_destroy_cm_id(id_priv->cm_id.ib); | 1083 | ib_destroy_cm_id(id_priv->cm_id.ib); |
| 1061 | break; | 1084 | } else if (rdma_cap_iw_cm(id_priv->id.device, 1)) { |
| 1062 | case RDMA_TRANSPORT_IWARP: | ||
| 1063 | if (id_priv->cm_id.iw) | 1085 | if (id_priv->cm_id.iw) |
| 1064 | iw_destroy_cm_id(id_priv->cm_id.iw); | 1086 | iw_destroy_cm_id(id_priv->cm_id.iw); |
| 1065 | break; | ||
| 1066 | default: | ||
| 1067 | break; | ||
| 1068 | } | 1087 | } |
| 1069 | cma_leave_mc_groups(id_priv); | 1088 | cma_leave_mc_groups(id_priv); |
| 1070 | cma_release_dev(id_priv); | 1089 | cma_release_dev(id_priv); |
| @@ -1610,6 +1629,7 @@ static int cma_iw_listen(struct rdma_id_private *id_priv, int backlog) | |||
| 1610 | if (IS_ERR(id)) | 1629 | if (IS_ERR(id)) |
| 1611 | return PTR_ERR(id); | 1630 | return PTR_ERR(id); |
| 1612 | 1631 | ||
| 1632 | id->tos = id_priv->tos; | ||
| 1613 | id_priv->cm_id.iw = id; | 1633 | id_priv->cm_id.iw = id; |
| 1614 | 1634 | ||
| 1615 | memcpy(&id_priv->cm_id.iw->local_addr, cma_src_addr(id_priv), | 1635 | memcpy(&id_priv->cm_id.iw->local_addr, cma_src_addr(id_priv), |
| @@ -1642,8 +1662,7 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv, | |||
| 1642 | struct rdma_cm_id *id; | 1662 | struct rdma_cm_id *id; |
| 1643 | int ret; | 1663 | int ret; |
| 1644 | 1664 | ||
| 1645 | if (cma_family(id_priv) == AF_IB && | 1665 | if (cma_family(id_priv) == AF_IB && !rdma_cap_ib_cm(cma_dev->device, 1)) |
| 1646 | rdma_node_get_transport(cma_dev->device->node_type) != RDMA_TRANSPORT_IB) | ||
| 1647 | return; | 1666 | return; |
| 1648 | 1667 | ||
| 1649 | id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps, | 1668 | id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps, |
| @@ -1984,26 +2003,15 @@ int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms) | |||
| 1984 | return -EINVAL; | 2003 | return -EINVAL; |
| 1985 | 2004 | ||
| 1986 | atomic_inc(&id_priv->refcount); | 2005 | atomic_inc(&id_priv->refcount); |
| 1987 | switch (rdma_node_get_transport(id->device->node_type)) { | 2006 | if (rdma_cap_ib_sa(id->device, id->port_num)) |
| 1988 | case RDMA_TRANSPORT_IB: | 2007 | ret = cma_resolve_ib_route(id_priv, timeout_ms); |
| 1989 | switch (rdma_port_get_link_layer(id->device, id->port_num)) { | 2008 | else if (rdma_protocol_roce(id->device, id->port_num)) |
| 1990 | case IB_LINK_LAYER_INFINIBAND: | 2009 | ret = cma_resolve_iboe_route(id_priv); |
| 1991 | ret = cma_resolve_ib_route(id_priv, timeout_ms); | 2010 | else if (rdma_protocol_iwarp(id->device, id->port_num)) |
| 1992 | break; | ||
| 1993 | case IB_LINK_LAYER_ETHERNET: | ||
| 1994 | ret = cma_resolve_iboe_route(id_priv); | ||
| 1995 | break; | ||
| 1996 | default: | ||
| 1997 | ret = -ENOSYS; | ||
| 1998 | } | ||
| 1999 | break; | ||
| 2000 | case RDMA_TRANSPORT_IWARP: | ||
| 2001 | ret = cma_resolve_iw_route(id_priv, timeout_ms); | 2011 | ret = cma_resolve_iw_route(id_priv, timeout_ms); |
| 2002 | break; | 2012 | else |
| 2003 | default: | ||
| 2004 | ret = -ENOSYS; | 2013 | ret = -ENOSYS; |
| 2005 | break; | 2014 | |
| 2006 | } | ||
| 2007 | if (ret) | 2015 | if (ret) |
| 2008 | goto err; | 2016 | goto err; |
| 2009 | 2017 | ||
| @@ -2045,7 +2053,7 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv) | |||
| 2045 | mutex_lock(&lock); | 2053 | mutex_lock(&lock); |
| 2046 | list_for_each_entry(cur_dev, &dev_list, list) { | 2054 | list_for_each_entry(cur_dev, &dev_list, list) { |
| 2047 | if (cma_family(id_priv) == AF_IB && | 2055 | if (cma_family(id_priv) == AF_IB && |
| 2048 | rdma_node_get_transport(cur_dev->device->node_type) != RDMA_TRANSPORT_IB) | 2056 | !rdma_cap_ib_cm(cur_dev->device, 1)) |
| 2049 | continue; | 2057 | continue; |
| 2050 | 2058 | ||
| 2051 | if (!cma_dev) | 2059 | if (!cma_dev) |
| @@ -2077,7 +2085,7 @@ port_found: | |||
| 2077 | goto out; | 2085 | goto out; |
| 2078 | 2086 | ||
| 2079 | id_priv->id.route.addr.dev_addr.dev_type = | 2087 | id_priv->id.route.addr.dev_addr.dev_type = |
| 2080 | (rdma_port_get_link_layer(cma_dev->device, p) == IB_LINK_LAYER_INFINIBAND) ? | 2088 | (rdma_protocol_ib(cma_dev->device, p)) ? |
| 2081 | ARPHRD_INFINIBAND : ARPHRD_ETHER; | 2089 | ARPHRD_INFINIBAND : ARPHRD_ETHER; |
| 2082 | 2090 | ||
| 2083 | rdma_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid); | 2091 | rdma_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid); |
| @@ -2554,18 +2562,15 @@ int rdma_listen(struct rdma_cm_id *id, int backlog) | |||
| 2554 | 2562 | ||
| 2555 | id_priv->backlog = backlog; | 2563 | id_priv->backlog = backlog; |
| 2556 | if (id->device) { | 2564 | if (id->device) { |
| 2557 | switch (rdma_node_get_transport(id->device->node_type)) { | 2565 | if (rdma_cap_ib_cm(id->device, 1)) { |
| 2558 | case RDMA_TRANSPORT_IB: | ||
| 2559 | ret = cma_ib_listen(id_priv); | 2566 | ret = cma_ib_listen(id_priv); |
| 2560 | if (ret) | 2567 | if (ret) |
| 2561 | goto err; | 2568 | goto err; |
| 2562 | break; | 2569 | } else if (rdma_cap_iw_cm(id->device, 1)) { |
| 2563 | case RDMA_TRANSPORT_IWARP: | ||
| 2564 | ret = cma_iw_listen(id_priv, backlog); | 2570 | ret = cma_iw_listen(id_priv, backlog); |
| 2565 | if (ret) | 2571 | if (ret) |
| 2566 | goto err; | 2572 | goto err; |
| 2567 | break; | 2573 | } else { |
| 2568 | default: | ||
| 2569 | ret = -ENOSYS; | 2574 | ret = -ENOSYS; |
| 2570 | goto err; | 2575 | goto err; |
| 2571 | } | 2576 | } |
| @@ -2857,6 +2862,7 @@ static int cma_connect_iw(struct rdma_id_private *id_priv, | |||
| 2857 | if (IS_ERR(cm_id)) | 2862 | if (IS_ERR(cm_id)) |
| 2858 | return PTR_ERR(cm_id); | 2863 | return PTR_ERR(cm_id); |
| 2859 | 2864 | ||
| 2865 | cm_id->tos = id_priv->tos; | ||
| 2860 | id_priv->cm_id.iw = cm_id; | 2866 | id_priv->cm_id.iw = cm_id; |
| 2861 | 2867 | ||
| 2862 | memcpy(&cm_id->local_addr, cma_src_addr(id_priv), | 2868 | memcpy(&cm_id->local_addr, cma_src_addr(id_priv), |
| @@ -2901,20 +2907,15 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) | |||
| 2901 | id_priv->srq = conn_param->srq; | 2907 | id_priv->srq = conn_param->srq; |
| 2902 | } | 2908 | } |
| 2903 | 2909 | ||
| 2904 | switch (rdma_node_get_transport(id->device->node_type)) { | 2910 | if (rdma_cap_ib_cm(id->device, id->port_num)) { |
| 2905 | case RDMA_TRANSPORT_IB: | ||
| 2906 | if (id->qp_type == IB_QPT_UD) | 2911 | if (id->qp_type == IB_QPT_UD) |
| 2907 | ret = cma_resolve_ib_udp(id_priv, conn_param); | 2912 | ret = cma_resolve_ib_udp(id_priv, conn_param); |
| 2908 | else | 2913 | else |
| 2909 | ret = cma_connect_ib(id_priv, conn_param); | 2914 | ret = cma_connect_ib(id_priv, conn_param); |
| 2910 | break; | 2915 | } else if (rdma_cap_iw_cm(id->device, id->port_num)) |
| 2911 | case RDMA_TRANSPORT_IWARP: | ||
| 2912 | ret = cma_connect_iw(id_priv, conn_param); | 2916 | ret = cma_connect_iw(id_priv, conn_param); |
| 2913 | break; | 2917 | else |
| 2914 | default: | ||
| 2915 | ret = -ENOSYS; | 2918 | ret = -ENOSYS; |
| 2916 | break; | ||
| 2917 | } | ||
| 2918 | if (ret) | 2919 | if (ret) |
| 2919 | goto err; | 2920 | goto err; |
| 2920 | 2921 | ||
| @@ -3017,8 +3018,7 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) | |||
| 3017 | id_priv->srq = conn_param->srq; | 3018 | id_priv->srq = conn_param->srq; |
| 3018 | } | 3019 | } |
| 3019 | 3020 | ||
| 3020 | switch (rdma_node_get_transport(id->device->node_type)) { | 3021 | if (rdma_cap_ib_cm(id->device, id->port_num)) { |
| 3021 | case RDMA_TRANSPORT_IB: | ||
| 3022 | if (id->qp_type == IB_QPT_UD) { | 3022 | if (id->qp_type == IB_QPT_UD) { |
| 3023 | if (conn_param) | 3023 | if (conn_param) |
| 3024 | ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS, | 3024 | ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS, |
| @@ -3034,14 +3034,10 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) | |||
| 3034 | else | 3034 | else |
| 3035 | ret = cma_rep_recv(id_priv); | 3035 | ret = cma_rep_recv(id_priv); |
| 3036 | } | 3036 | } |
| 3037 | break; | 3037 | } else if (rdma_cap_iw_cm(id->device, id->port_num)) |
| 3038 | case RDMA_TRANSPORT_IWARP: | ||
| 3039 | ret = cma_accept_iw(id_priv, conn_param); | 3038 | ret = cma_accept_iw(id_priv, conn_param); |
| 3040 | break; | 3039 | else |
| 3041 | default: | ||
| 3042 | ret = -ENOSYS; | 3040 | ret = -ENOSYS; |
| 3043 | break; | ||
| 3044 | } | ||
| 3045 | 3041 | ||
| 3046 | if (ret) | 3042 | if (ret) |
| 3047 | goto reject; | 3043 | goto reject; |
| @@ -3085,8 +3081,7 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data, | |||
| 3085 | if (!id_priv->cm_id.ib) | 3081 | if (!id_priv->cm_id.ib) |
| 3086 | return -EINVAL; | 3082 | return -EINVAL; |
| 3087 | 3083 | ||
| 3088 | switch (rdma_node_get_transport(id->device->node_type)) { | 3084 | if (rdma_cap_ib_cm(id->device, id->port_num)) { |
| 3089 | case RDMA_TRANSPORT_IB: | ||
| 3090 | if (id->qp_type == IB_QPT_UD) | 3085 | if (id->qp_type == IB_QPT_UD) |
| 3091 | ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT, 0, | 3086 | ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT, 0, |
| 3092 | private_data, private_data_len); | 3087 | private_data, private_data_len); |
| @@ -3094,15 +3089,12 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data, | |||
| 3094 | ret = ib_send_cm_rej(id_priv->cm_id.ib, | 3089 | ret = ib_send_cm_rej(id_priv->cm_id.ib, |
| 3095 | IB_CM_REJ_CONSUMER_DEFINED, NULL, | 3090 | IB_CM_REJ_CONSUMER_DEFINED, NULL, |
| 3096 | 0, private_data, private_data_len); | 3091 | 0, private_data, private_data_len); |
| 3097 | break; | 3092 | } else if (rdma_cap_iw_cm(id->device, id->port_num)) { |
| 3098 | case RDMA_TRANSPORT_IWARP: | ||
| 3099 | ret = iw_cm_reject(id_priv->cm_id.iw, | 3093 | ret = iw_cm_reject(id_priv->cm_id.iw, |
| 3100 | private_data, private_data_len); | 3094 | private_data, private_data_len); |
| 3101 | break; | 3095 | } else |
| 3102 | default: | ||
| 3103 | ret = -ENOSYS; | 3096 | ret = -ENOSYS; |
| 3104 | break; | 3097 | |
| 3105 | } | ||
| 3106 | return ret; | 3098 | return ret; |
| 3107 | } | 3099 | } |
| 3108 | EXPORT_SYMBOL(rdma_reject); | 3100 | EXPORT_SYMBOL(rdma_reject); |
| @@ -3116,22 +3108,18 @@ int rdma_disconnect(struct rdma_cm_id *id) | |||
| 3116 | if (!id_priv->cm_id.ib) | 3108 | if (!id_priv->cm_id.ib) |
| 3117 | return -EINVAL; | 3109 | return -EINVAL; |
| 3118 | 3110 | ||
| 3119 | switch (rdma_node_get_transport(id->device->node_type)) { | 3111 | if (rdma_cap_ib_cm(id->device, id->port_num)) { |
| 3120 | case RDMA_TRANSPORT_IB: | ||
| 3121 | ret = cma_modify_qp_err(id_priv); | 3112 | ret = cma_modify_qp_err(id_priv); |
| 3122 | if (ret) | 3113 | if (ret) |
| 3123 | goto out; | 3114 | goto out; |
| 3124 | /* Initiate or respond to a disconnect. */ | 3115 | /* Initiate or respond to a disconnect. */ |
| 3125 | if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0)) | 3116 | if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0)) |
| 3126 | ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0); | 3117 | ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0); |
| 3127 | break; | 3118 | } else if (rdma_cap_iw_cm(id->device, id->port_num)) { |
| 3128 | case RDMA_TRANSPORT_IWARP: | ||
| 3129 | ret = iw_cm_disconnect(id_priv->cm_id.iw, 0); | 3119 | ret = iw_cm_disconnect(id_priv->cm_id.iw, 0); |
| 3130 | break; | 3120 | } else |
| 3131 | default: | ||
| 3132 | ret = -EINVAL; | 3121 | ret = -EINVAL; |
| 3133 | break; | 3122 | |
| 3134 | } | ||
| 3135 | out: | 3123 | out: |
| 3136 | return ret; | 3124 | return ret; |
| 3137 | } | 3125 | } |
| @@ -3377,24 +3365,13 @@ int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr, | |||
| 3377 | list_add(&mc->list, &id_priv->mc_list); | 3365 | list_add(&mc->list, &id_priv->mc_list); |
| 3378 | spin_unlock(&id_priv->lock); | 3366 | spin_unlock(&id_priv->lock); |
| 3379 | 3367 | ||
| 3380 | switch (rdma_node_get_transport(id->device->node_type)) { | 3368 | if (rdma_protocol_roce(id->device, id->port_num)) { |
| 3381 | case RDMA_TRANSPORT_IB: | 3369 | kref_init(&mc->mcref); |
| 3382 | switch (rdma_port_get_link_layer(id->device, id->port_num)) { | 3370 | ret = cma_iboe_join_multicast(id_priv, mc); |
| 3383 | case IB_LINK_LAYER_INFINIBAND: | 3371 | } else if (rdma_cap_ib_mcast(id->device, id->port_num)) |
| 3384 | ret = cma_join_ib_multicast(id_priv, mc); | 3372 | ret = cma_join_ib_multicast(id_priv, mc); |
| 3385 | break; | 3373 | else |
| 3386 | case IB_LINK_LAYER_ETHERNET: | ||
| 3387 | kref_init(&mc->mcref); | ||
| 3388 | ret = cma_iboe_join_multicast(id_priv, mc); | ||
| 3389 | break; | ||
| 3390 | default: | ||
| 3391 | ret = -EINVAL; | ||
| 3392 | } | ||
| 3393 | break; | ||
| 3394 | default: | ||
| 3395 | ret = -ENOSYS; | 3374 | ret = -ENOSYS; |
| 3396 | break; | ||
| 3397 | } | ||
| 3398 | 3375 | ||
| 3399 | if (ret) { | 3376 | if (ret) { |
| 3400 | spin_lock_irq(&id_priv->lock); | 3377 | spin_lock_irq(&id_priv->lock); |
| @@ -3422,19 +3399,15 @@ void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr) | |||
| 3422 | ib_detach_mcast(id->qp, | 3399 | ib_detach_mcast(id->qp, |
| 3423 | &mc->multicast.ib->rec.mgid, | 3400 | &mc->multicast.ib->rec.mgid, |
| 3424 | be16_to_cpu(mc->multicast.ib->rec.mlid)); | 3401 | be16_to_cpu(mc->multicast.ib->rec.mlid)); |
| 3425 | if (rdma_node_get_transport(id_priv->cma_dev->device->node_type) == RDMA_TRANSPORT_IB) { | 3402 | |
| 3426 | switch (rdma_port_get_link_layer(id->device, id->port_num)) { | 3403 | BUG_ON(id_priv->cma_dev->device != id->device); |
| 3427 | case IB_LINK_LAYER_INFINIBAND: | 3404 | |
| 3428 | ib_sa_free_multicast(mc->multicast.ib); | 3405 | if (rdma_cap_ib_mcast(id->device, id->port_num)) { |
| 3429 | kfree(mc); | 3406 | ib_sa_free_multicast(mc->multicast.ib); |
| 3430 | break; | 3407 | kfree(mc); |
| 3431 | case IB_LINK_LAYER_ETHERNET: | 3408 | } else if (rdma_protocol_roce(id->device, id->port_num)) |
| 3432 | kref_put(&mc->mcref, release_mc); | 3409 | kref_put(&mc->mcref, release_mc); |
| 3433 | break; | 3410 | |
| 3434 | default: | ||
| 3435 | break; | ||
| 3436 | } | ||
| 3437 | } | ||
| 3438 | return; | 3411 | return; |
| 3439 | } | 3412 | } |
| 3440 | } | 3413 | } |
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 18c1ece765f2..9567756ca4f9 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c | |||
| @@ -92,7 +92,8 @@ static int ib_device_check_mandatory(struct ib_device *device) | |||
| 92 | IB_MANDATORY_FUNC(poll_cq), | 92 | IB_MANDATORY_FUNC(poll_cq), |
| 93 | IB_MANDATORY_FUNC(req_notify_cq), | 93 | IB_MANDATORY_FUNC(req_notify_cq), |
| 94 | IB_MANDATORY_FUNC(get_dma_mr), | 94 | IB_MANDATORY_FUNC(get_dma_mr), |
| 95 | IB_MANDATORY_FUNC(dereg_mr) | 95 | IB_MANDATORY_FUNC(dereg_mr), |
| 96 | IB_MANDATORY_FUNC(get_port_immutable) | ||
| 96 | }; | 97 | }; |
| 97 | int i; | 98 | int i; |
| 98 | 99 | ||
| @@ -151,18 +152,6 @@ static int alloc_name(char *name) | |||
| 151 | return 0; | 152 | return 0; |
| 152 | } | 153 | } |
| 153 | 154 | ||
| 154 | static int start_port(struct ib_device *device) | ||
| 155 | { | ||
| 156 | return (device->node_type == RDMA_NODE_IB_SWITCH) ? 0 : 1; | ||
| 157 | } | ||
| 158 | |||
| 159 | |||
| 160 | static int end_port(struct ib_device *device) | ||
| 161 | { | ||
| 162 | return (device->node_type == RDMA_NODE_IB_SWITCH) ? | ||
| 163 | 0 : device->phys_port_cnt; | ||
| 164 | } | ||
| 165 | |||
| 166 | /** | 155 | /** |
| 167 | * ib_alloc_device - allocate an IB device struct | 156 | * ib_alloc_device - allocate an IB device struct |
| 168 | * @size:size of structure to allocate | 157 | * @size:size of structure to allocate |
| @@ -222,42 +211,49 @@ static int add_client_context(struct ib_device *device, struct ib_client *client | |||
| 222 | return 0; | 211 | return 0; |
| 223 | } | 212 | } |
| 224 | 213 | ||
| 225 | static int read_port_table_lengths(struct ib_device *device) | 214 | static int verify_immutable(const struct ib_device *dev, u8 port) |
| 226 | { | 215 | { |
| 227 | struct ib_port_attr *tprops = NULL; | 216 | return WARN_ON(!rdma_cap_ib_mad(dev, port) && |
| 228 | int num_ports, ret = -ENOMEM; | 217 | rdma_max_mad_size(dev, port) != 0); |
| 229 | u8 port_index; | 218 | } |
| 230 | |||
| 231 | tprops = kmalloc(sizeof *tprops, GFP_KERNEL); | ||
| 232 | if (!tprops) | ||
| 233 | goto out; | ||
| 234 | |||
| 235 | num_ports = end_port(device) - start_port(device) + 1; | ||
| 236 | 219 | ||
| 237 | device->pkey_tbl_len = kmalloc(sizeof *device->pkey_tbl_len * num_ports, | 220 | static int read_port_immutable(struct ib_device *device) |
| 238 | GFP_KERNEL); | 221 | { |
| 239 | device->gid_tbl_len = kmalloc(sizeof *device->gid_tbl_len * num_ports, | 222 | int ret = -ENOMEM; |
| 240 | GFP_KERNEL); | 223 | u8 start_port = rdma_start_port(device); |
| 241 | if (!device->pkey_tbl_len || !device->gid_tbl_len) | 224 | u8 end_port = rdma_end_port(device); |
| 225 | u8 port; | ||
| 226 | |||
| 227 | /** | ||
| 228 | * device->port_immutable is indexed directly by the port number to make | ||
| 229 | * access to this data as efficient as possible. | ||
| 230 | * | ||
| 231 | * Therefore port_immutable is declared as a 1 based array with | ||
| 232 | * potential empty slots at the beginning. | ||
| 233 | */ | ||
| 234 | device->port_immutable = kzalloc(sizeof(*device->port_immutable) | ||
| 235 | * (end_port + 1), | ||
| 236 | GFP_KERNEL); | ||
| 237 | if (!device->port_immutable) | ||
| 242 | goto err; | 238 | goto err; |
| 243 | 239 | ||
| 244 | for (port_index = 0; port_index < num_ports; ++port_index) { | 240 | for (port = start_port; port <= end_port; ++port) { |
| 245 | ret = ib_query_port(device, port_index + start_port(device), | 241 | ret = device->get_port_immutable(device, port, |
| 246 | tprops); | 242 | &device->port_immutable[port]); |
| 247 | if (ret) | 243 | if (ret) |
| 248 | goto err; | 244 | goto err; |
| 249 | device->pkey_tbl_len[port_index] = tprops->pkey_tbl_len; | 245 | |
| 250 | device->gid_tbl_len[port_index] = tprops->gid_tbl_len; | 246 | if (verify_immutable(device, port)) { |
| 247 | ret = -EINVAL; | ||
| 248 | goto err; | ||
| 249 | } | ||
| 251 | } | 250 | } |
| 252 | 251 | ||
| 253 | ret = 0; | 252 | ret = 0; |
| 254 | goto out; | 253 | goto out; |
| 255 | |||
| 256 | err: | 254 | err: |
| 257 | kfree(device->gid_tbl_len); | 255 | kfree(device->port_immutable); |
| 258 | kfree(device->pkey_tbl_len); | ||
| 259 | out: | 256 | out: |
| 260 | kfree(tprops); | ||
| 261 | return ret; | 257 | return ret; |
| 262 | } | 258 | } |
| 263 | 259 | ||
| @@ -294,9 +290,9 @@ int ib_register_device(struct ib_device *device, | |||
| 294 | spin_lock_init(&device->event_handler_lock); | 290 | spin_lock_init(&device->event_handler_lock); |
| 295 | spin_lock_init(&device->client_data_lock); | 291 | spin_lock_init(&device->client_data_lock); |
| 296 | 292 | ||
| 297 | ret = read_port_table_lengths(device); | 293 | ret = read_port_immutable(device); |
| 298 | if (ret) { | 294 | if (ret) { |
| 299 | printk(KERN_WARNING "Couldn't create table lengths cache for device %s\n", | 295 | printk(KERN_WARNING "Couldn't create per port immutable data %s\n", |
| 300 | device->name); | 296 | device->name); |
| 301 | goto out; | 297 | goto out; |
| 302 | } | 298 | } |
| @@ -305,8 +301,7 @@ int ib_register_device(struct ib_device *device, | |||
| 305 | if (ret) { | 301 | if (ret) { |
| 306 | printk(KERN_WARNING "Couldn't register device %s with driver model\n", | 302 | printk(KERN_WARNING "Couldn't register device %s with driver model\n", |
| 307 | device->name); | 303 | device->name); |
| 308 | kfree(device->gid_tbl_len); | 304 | kfree(device->port_immutable); |
| 309 | kfree(device->pkey_tbl_len); | ||
| 310 | goto out; | 305 | goto out; |
| 311 | } | 306 | } |
| 312 | 307 | ||
| @@ -348,9 +343,6 @@ void ib_unregister_device(struct ib_device *device) | |||
| 348 | 343 | ||
| 349 | list_del(&device->core_list); | 344 | list_del(&device->core_list); |
| 350 | 345 | ||
| 351 | kfree(device->gid_tbl_len); | ||
| 352 | kfree(device->pkey_tbl_len); | ||
| 353 | |||
| 354 | mutex_unlock(&device_mutex); | 346 | mutex_unlock(&device_mutex); |
| 355 | 347 | ||
| 356 | ib_device_unregister_sysfs(device); | 348 | ib_device_unregister_sysfs(device); |
| @@ -558,7 +550,11 @@ EXPORT_SYMBOL(ib_dispatch_event); | |||
| 558 | int ib_query_device(struct ib_device *device, | 550 | int ib_query_device(struct ib_device *device, |
| 559 | struct ib_device_attr *device_attr) | 551 | struct ib_device_attr *device_attr) |
| 560 | { | 552 | { |
| 561 | return device->query_device(device, device_attr); | 553 | struct ib_udata uhw = {.outlen = 0, .inlen = 0}; |
| 554 | |||
| 555 | memset(device_attr, 0, sizeof(*device_attr)); | ||
| 556 | |||
| 557 | return device->query_device(device, device_attr, &uhw); | ||
| 562 | } | 558 | } |
| 563 | EXPORT_SYMBOL(ib_query_device); | 559 | EXPORT_SYMBOL(ib_query_device); |
| 564 | 560 | ||
| @@ -575,7 +571,7 @@ int ib_query_port(struct ib_device *device, | |||
| 575 | u8 port_num, | 571 | u8 port_num, |
| 576 | struct ib_port_attr *port_attr) | 572 | struct ib_port_attr *port_attr) |
| 577 | { | 573 | { |
| 578 | if (port_num < start_port(device) || port_num > end_port(device)) | 574 | if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device)) |
| 579 | return -EINVAL; | 575 | return -EINVAL; |
| 580 | 576 | ||
| 581 | return device->query_port(device, port_num, port_attr); | 577 | return device->query_port(device, port_num, port_attr); |
| @@ -653,7 +649,7 @@ int ib_modify_port(struct ib_device *device, | |||
| 653 | if (!device->modify_port) | 649 | if (!device->modify_port) |
| 654 | return -ENOSYS; | 650 | return -ENOSYS; |
| 655 | 651 | ||
| 656 | if (port_num < start_port(device) || port_num > end_port(device)) | 652 | if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device)) |
| 657 | return -EINVAL; | 653 | return -EINVAL; |
| 658 | 654 | ||
| 659 | return device->modify_port(device, port_num, port_modify_mask, | 655 | return device->modify_port(device, port_num, port_modify_mask, |
| @@ -676,8 +672,8 @@ int ib_find_gid(struct ib_device *device, union ib_gid *gid, | |||
| 676 | union ib_gid tmp_gid; | 672 | union ib_gid tmp_gid; |
| 677 | int ret, port, i; | 673 | int ret, port, i; |
| 678 | 674 | ||
| 679 | for (port = start_port(device); port <= end_port(device); ++port) { | 675 | for (port = rdma_start_port(device); port <= rdma_end_port(device); ++port) { |
| 680 | for (i = 0; i < device->gid_tbl_len[port - start_port(device)]; ++i) { | 676 | for (i = 0; i < device->port_immutable[port].gid_tbl_len; ++i) { |
| 681 | ret = ib_query_gid(device, port, i, &tmp_gid); | 677 | ret = ib_query_gid(device, port, i, &tmp_gid); |
| 682 | if (ret) | 678 | if (ret) |
| 683 | return ret; | 679 | return ret; |
| @@ -709,7 +705,7 @@ int ib_find_pkey(struct ib_device *device, | |||
| 709 | u16 tmp_pkey; | 705 | u16 tmp_pkey; |
| 710 | int partial_ix = -1; | 706 | int partial_ix = -1; |
| 711 | 707 | ||
| 712 | for (i = 0; i < device->pkey_tbl_len[port_num - start_port(device)]; ++i) { | 708 | for (i = 0; i < device->port_immutable[port_num].pkey_tbl_len; ++i) { |
| 713 | ret = ib_query_pkey(device, port_num, i, &tmp_pkey); | 709 | ret = ib_query_pkey(device, port_num, i, &tmp_pkey); |
| 714 | if (ret) | 710 | if (ret) |
| 715 | return ret; | 711 | return ret; |
diff --git a/drivers/infiniband/core/iwpm_msg.c b/drivers/infiniband/core/iwpm_msg.c index e6ffa2e66c1a..22a3abee2a54 100644 --- a/drivers/infiniband/core/iwpm_msg.c +++ b/drivers/infiniband/core/iwpm_msg.c | |||
| @@ -67,7 +67,8 @@ int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client) | |||
| 67 | err_str = "Invalid port mapper client"; | 67 | err_str = "Invalid port mapper client"; |
| 68 | goto pid_query_error; | 68 | goto pid_query_error; |
| 69 | } | 69 | } |
| 70 | if (iwpm_registered_client(nl_client)) | 70 | if (iwpm_check_registration(nl_client, IWPM_REG_VALID) || |
| 71 | iwpm_user_pid == IWPM_PID_UNAVAILABLE) | ||
| 71 | return 0; | 72 | return 0; |
| 72 | skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REG_PID, &nlh, nl_client); | 73 | skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REG_PID, &nlh, nl_client); |
| 73 | if (!skb) { | 74 | if (!skb) { |
| @@ -106,7 +107,6 @@ int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client) | |||
| 106 | ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_IWPM, GFP_KERNEL); | 107 | ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_IWPM, GFP_KERNEL); |
| 107 | if (ret) { | 108 | if (ret) { |
| 108 | skb = NULL; /* skb is freed in the netlink send-op handling */ | 109 | skb = NULL; /* skb is freed in the netlink send-op handling */ |
| 109 | iwpm_set_registered(nl_client, 1); | ||
| 110 | iwpm_user_pid = IWPM_PID_UNAVAILABLE; | 110 | iwpm_user_pid = IWPM_PID_UNAVAILABLE; |
| 111 | err_str = "Unable to send a nlmsg"; | 111 | err_str = "Unable to send a nlmsg"; |
| 112 | goto pid_query_error; | 112 | goto pid_query_error; |
| @@ -144,12 +144,12 @@ int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client) | |||
| 144 | err_str = "Invalid port mapper client"; | 144 | err_str = "Invalid port mapper client"; |
| 145 | goto add_mapping_error; | 145 | goto add_mapping_error; |
| 146 | } | 146 | } |
| 147 | if (!iwpm_registered_client(nl_client)) { | 147 | if (!iwpm_valid_pid()) |
| 148 | return 0; | ||
| 149 | if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) { | ||
| 148 | err_str = "Unregistered port mapper client"; | 150 | err_str = "Unregistered port mapper client"; |
| 149 | goto add_mapping_error; | 151 | goto add_mapping_error; |
| 150 | } | 152 | } |
| 151 | if (!iwpm_valid_pid()) | ||
| 152 | return 0; | ||
| 153 | skb = iwpm_create_nlmsg(RDMA_NL_IWPM_ADD_MAPPING, &nlh, nl_client); | 153 | skb = iwpm_create_nlmsg(RDMA_NL_IWPM_ADD_MAPPING, &nlh, nl_client); |
| 154 | if (!skb) { | 154 | if (!skb) { |
| 155 | err_str = "Unable to create a nlmsg"; | 155 | err_str = "Unable to create a nlmsg"; |
| @@ -214,12 +214,12 @@ int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client) | |||
| 214 | err_str = "Invalid port mapper client"; | 214 | err_str = "Invalid port mapper client"; |
| 215 | goto query_mapping_error; | 215 | goto query_mapping_error; |
| 216 | } | 216 | } |
| 217 | if (!iwpm_registered_client(nl_client)) { | 217 | if (!iwpm_valid_pid()) |
| 218 | return 0; | ||
| 219 | if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) { | ||
| 218 | err_str = "Unregistered port mapper client"; | 220 | err_str = "Unregistered port mapper client"; |
| 219 | goto query_mapping_error; | 221 | goto query_mapping_error; |
| 220 | } | 222 | } |
| 221 | if (!iwpm_valid_pid()) | ||
| 222 | return 0; | ||
| 223 | ret = -ENOMEM; | 223 | ret = -ENOMEM; |
| 224 | skb = iwpm_create_nlmsg(RDMA_NL_IWPM_QUERY_MAPPING, &nlh, nl_client); | 224 | skb = iwpm_create_nlmsg(RDMA_NL_IWPM_QUERY_MAPPING, &nlh, nl_client); |
| 225 | if (!skb) { | 225 | if (!skb) { |
| @@ -288,12 +288,12 @@ int iwpm_remove_mapping(struct sockaddr_storage *local_addr, u8 nl_client) | |||
| 288 | err_str = "Invalid port mapper client"; | 288 | err_str = "Invalid port mapper client"; |
| 289 | goto remove_mapping_error; | 289 | goto remove_mapping_error; |
| 290 | } | 290 | } |
| 291 | if (!iwpm_registered_client(nl_client)) { | 291 | if (!iwpm_valid_pid()) |
| 292 | return 0; | ||
| 293 | if (iwpm_check_registration(nl_client, IWPM_REG_UNDEF)) { | ||
| 292 | err_str = "Unregistered port mapper client"; | 294 | err_str = "Unregistered port mapper client"; |
| 293 | goto remove_mapping_error; | 295 | goto remove_mapping_error; |
| 294 | } | 296 | } |
| 295 | if (!iwpm_valid_pid()) | ||
| 296 | return 0; | ||
| 297 | skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REMOVE_MAPPING, &nlh, nl_client); | 297 | skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REMOVE_MAPPING, &nlh, nl_client); |
| 298 | if (!skb) { | 298 | if (!skb) { |
| 299 | ret = -ENOMEM; | 299 | ret = -ENOMEM; |
| @@ -388,7 +388,7 @@ int iwpm_register_pid_cb(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 388 | pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n", | 388 | pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n", |
| 389 | __func__, iwpm_user_pid); | 389 | __func__, iwpm_user_pid); |
| 390 | if (iwpm_valid_client(nl_client)) | 390 | if (iwpm_valid_client(nl_client)) |
| 391 | iwpm_set_registered(nl_client, 1); | 391 | iwpm_set_registration(nl_client, IWPM_REG_VALID); |
| 392 | register_pid_response_exit: | 392 | register_pid_response_exit: |
| 393 | nlmsg_request->request_done = 1; | 393 | nlmsg_request->request_done = 1; |
| 394 | /* always for found nlmsg_request */ | 394 | /* always for found nlmsg_request */ |
| @@ -644,7 +644,6 @@ int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 644 | { | 644 | { |
| 645 | struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX]; | 645 | struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX]; |
| 646 | const char *msg_type = "Mapping Info response"; | 646 | const char *msg_type = "Mapping Info response"; |
| 647 | int iwpm_pid; | ||
| 648 | u8 nl_client; | 647 | u8 nl_client; |
| 649 | char *iwpm_name; | 648 | char *iwpm_name; |
| 650 | u16 iwpm_version; | 649 | u16 iwpm_version; |
| @@ -669,14 +668,14 @@ int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 669 | __func__, nl_client); | 668 | __func__, nl_client); |
| 670 | return ret; | 669 | return ret; |
| 671 | } | 670 | } |
| 672 | iwpm_set_registered(nl_client, 0); | 671 | iwpm_set_registration(nl_client, IWPM_REG_INCOMPL); |
| 673 | atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq); | 672 | atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq); |
| 673 | iwpm_user_pid = cb->nlh->nlmsg_pid; | ||
| 674 | if (!iwpm_mapinfo_available()) | 674 | if (!iwpm_mapinfo_available()) |
| 675 | return 0; | 675 | return 0; |
| 676 | iwpm_pid = cb->nlh->nlmsg_pid; | ||
| 677 | pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n", | 676 | pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n", |
| 678 | __func__, iwpm_pid); | 677 | __func__, iwpm_user_pid); |
| 679 | ret = iwpm_send_mapinfo(nl_client, iwpm_pid); | 678 | ret = iwpm_send_mapinfo(nl_client, iwpm_user_pid); |
| 680 | return ret; | 679 | return ret; |
| 681 | } | 680 | } |
| 682 | EXPORT_SYMBOL(iwpm_mapping_info_cb); | 681 | EXPORT_SYMBOL(iwpm_mapping_info_cb); |
diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c index a626795bf9c7..5fb089e91353 100644 --- a/drivers/infiniband/core/iwpm_util.c +++ b/drivers/infiniband/core/iwpm_util.c | |||
| @@ -78,6 +78,7 @@ init_exit: | |||
| 78 | mutex_unlock(&iwpm_admin_lock); | 78 | mutex_unlock(&iwpm_admin_lock); |
| 79 | if (!ret) { | 79 | if (!ret) { |
| 80 | iwpm_set_valid(nl_client, 1); | 80 | iwpm_set_valid(nl_client, 1); |
| 81 | iwpm_set_registration(nl_client, IWPM_REG_UNDEF); | ||
| 81 | pr_debug("%s: Mapinfo and reminfo tables are created\n", | 82 | pr_debug("%s: Mapinfo and reminfo tables are created\n", |
| 82 | __func__); | 83 | __func__); |
| 83 | } | 84 | } |
| @@ -106,6 +107,7 @@ int iwpm_exit(u8 nl_client) | |||
| 106 | } | 107 | } |
| 107 | mutex_unlock(&iwpm_admin_lock); | 108 | mutex_unlock(&iwpm_admin_lock); |
| 108 | iwpm_set_valid(nl_client, 0); | 109 | iwpm_set_valid(nl_client, 0); |
| 110 | iwpm_set_registration(nl_client, IWPM_REG_UNDEF); | ||
| 109 | return 0; | 111 | return 0; |
| 110 | } | 112 | } |
| 111 | EXPORT_SYMBOL(iwpm_exit); | 113 | EXPORT_SYMBOL(iwpm_exit); |
| @@ -397,17 +399,23 @@ void iwpm_set_valid(u8 nl_client, int valid) | |||
| 397 | } | 399 | } |
| 398 | 400 | ||
| 399 | /* valid client */ | 401 | /* valid client */ |
| 400 | int iwpm_registered_client(u8 nl_client) | 402 | u32 iwpm_get_registration(u8 nl_client) |
| 401 | { | 403 | { |
| 402 | return iwpm_admin.reg_list[nl_client]; | 404 | return iwpm_admin.reg_list[nl_client]; |
| 403 | } | 405 | } |
| 404 | 406 | ||
| 405 | /* valid client */ | 407 | /* valid client */ |
| 406 | void iwpm_set_registered(u8 nl_client, int reg) | 408 | void iwpm_set_registration(u8 nl_client, u32 reg) |
| 407 | { | 409 | { |
| 408 | iwpm_admin.reg_list[nl_client] = reg; | 410 | iwpm_admin.reg_list[nl_client] = reg; |
| 409 | } | 411 | } |
| 410 | 412 | ||
| 413 | /* valid client */ | ||
| 414 | u32 iwpm_check_registration(u8 nl_client, u32 reg) | ||
| 415 | { | ||
| 416 | return (iwpm_get_registration(nl_client) & reg); | ||
| 417 | } | ||
| 418 | |||
| 411 | int iwpm_compare_sockaddr(struct sockaddr_storage *a_sockaddr, | 419 | int iwpm_compare_sockaddr(struct sockaddr_storage *a_sockaddr, |
| 412 | struct sockaddr_storage *b_sockaddr) | 420 | struct sockaddr_storage *b_sockaddr) |
| 413 | { | 421 | { |
diff --git a/drivers/infiniband/core/iwpm_util.h b/drivers/infiniband/core/iwpm_util.h index ee2d9ff095be..b7b9e194ce81 100644 --- a/drivers/infiniband/core/iwpm_util.h +++ b/drivers/infiniband/core/iwpm_util.h | |||
| @@ -58,6 +58,10 @@ | |||
| 58 | #define IWPM_PID_UNDEFINED -1 | 58 | #define IWPM_PID_UNDEFINED -1 |
| 59 | #define IWPM_PID_UNAVAILABLE -2 | 59 | #define IWPM_PID_UNAVAILABLE -2 |
| 60 | 60 | ||
| 61 | #define IWPM_REG_UNDEF 0x01 | ||
| 62 | #define IWPM_REG_VALID 0x02 | ||
| 63 | #define IWPM_REG_INCOMPL 0x04 | ||
| 64 | |||
| 61 | struct iwpm_nlmsg_request { | 65 | struct iwpm_nlmsg_request { |
| 62 | struct list_head inprocess_list; | 66 | struct list_head inprocess_list; |
| 63 | __u32 nlmsg_seq; | 67 | __u32 nlmsg_seq; |
| @@ -88,7 +92,7 @@ struct iwpm_admin_data { | |||
| 88 | atomic_t refcount; | 92 | atomic_t refcount; |
| 89 | atomic_t nlmsg_seq; | 93 | atomic_t nlmsg_seq; |
| 90 | int client_list[RDMA_NL_NUM_CLIENTS]; | 94 | int client_list[RDMA_NL_NUM_CLIENTS]; |
| 91 | int reg_list[RDMA_NL_NUM_CLIENTS]; | 95 | u32 reg_list[RDMA_NL_NUM_CLIENTS]; |
| 92 | }; | 96 | }; |
| 93 | 97 | ||
| 94 | /** | 98 | /** |
| @@ -159,19 +163,31 @@ int iwpm_valid_client(u8 nl_client); | |||
| 159 | void iwpm_set_valid(u8 nl_client, int valid); | 163 | void iwpm_set_valid(u8 nl_client, int valid); |
| 160 | 164 | ||
| 161 | /** | 165 | /** |
| 162 | * iwpm_registered_client - Check if the port mapper client is registered | 166 | * iwpm_check_registration - Check if the client registration |
| 167 | * matches the given one | ||
| 163 | * @nl_client: The index of the netlink client | 168 | * @nl_client: The index of the netlink client |
| 169 | * @reg: The given registration type to compare with | ||
| 164 | * | 170 | * |
| 165 | * Call iwpm_register_pid() to register a client | 171 | * Call iwpm_register_pid() to register a client |
| 172 | * Returns true if the client registration matches reg, | ||
| 173 | * otherwise returns false | ||
| 174 | */ | ||
| 175 | u32 iwpm_check_registration(u8 nl_client, u32 reg); | ||
| 176 | |||
| 177 | /** | ||
| 178 | * iwpm_set_registration - Set the client registration | ||
| 179 | * @nl_client: The index of the netlink client | ||
| 180 | * @reg: Registration type to set | ||
| 166 | */ | 181 | */ |
| 167 | int iwpm_registered_client(u8 nl_client); | 182 | void iwpm_set_registration(u8 nl_client, u32 reg); |
| 168 | 183 | ||
| 169 | /** | 184 | /** |
| 170 | * iwpm_set_registered - Set the port mapper client to registered or not | 185 | * iwpm_get_registration |
| 171 | * @nl_client: The index of the netlink client | 186 | * @nl_client: The index of the netlink client |
| 172 | * @reg: 1 if registered or 0 if not | 187 | * |
| 188 | * Returns the client registration type | ||
| 173 | */ | 189 | */ |
| 174 | void iwpm_set_registered(u8 nl_client, int reg); | 190 | u32 iwpm_get_registration(u8 nl_client); |
| 175 | 191 | ||
| 176 | /** | 192 | /** |
| 177 | * iwpm_send_mapinfo - Send local and mapped IPv4/IPv6 address info of | 193 | * iwpm_send_mapinfo - Send local and mapped IPv4/IPv6 address info of |
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 74c30f4c557e..786fc51bf04b 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * Copyright (c) 2005 Intel Corporation. All rights reserved. | 3 | * Copyright (c) 2005 Intel Corporation. All rights reserved. |
| 4 | * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. | 4 | * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. |
| 5 | * Copyright (c) 2009 HNR Consulting. All rights reserved. | 5 | * Copyright (c) 2009 HNR Consulting. All rights reserved. |
| 6 | * Copyright (c) 2014 Intel Corporation. All rights reserved. | ||
| 6 | * | 7 | * |
| 7 | * This software is available to you under a choice of one of two | 8 | * This software is available to you under a choice of one of two |
| 8 | * licenses. You may choose to be licensed under the terms of the GNU | 9 | * licenses. You may choose to be licensed under the terms of the GNU |
| @@ -44,6 +45,7 @@ | |||
| 44 | #include "mad_priv.h" | 45 | #include "mad_priv.h" |
| 45 | #include "mad_rmpp.h" | 46 | #include "mad_rmpp.h" |
| 46 | #include "smi.h" | 47 | #include "smi.h" |
| 48 | #include "opa_smi.h" | ||
| 47 | #include "agent.h" | 49 | #include "agent.h" |
| 48 | 50 | ||
| 49 | MODULE_LICENSE("Dual BSD/GPL"); | 51 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -59,8 +61,6 @@ MODULE_PARM_DESC(send_queue_size, "Size of send queue in number of work requests | |||
| 59 | module_param_named(recv_queue_size, mad_recvq_size, int, 0444); | 61 | module_param_named(recv_queue_size, mad_recvq_size, int, 0444); |
| 60 | MODULE_PARM_DESC(recv_queue_size, "Size of receive queue in number of work requests"); | 62 | MODULE_PARM_DESC(recv_queue_size, "Size of receive queue in number of work requests"); |
| 61 | 63 | ||
| 62 | static struct kmem_cache *ib_mad_cache; | ||
| 63 | |||
| 64 | static struct list_head ib_mad_port_list; | 64 | static struct list_head ib_mad_port_list; |
| 65 | static u32 ib_mad_client_id = 0; | 65 | static u32 ib_mad_client_id = 0; |
| 66 | 66 | ||
| @@ -73,7 +73,7 @@ static int method_in_use(struct ib_mad_mgmt_method_table **method, | |||
| 73 | static void remove_mad_reg_req(struct ib_mad_agent_private *priv); | 73 | static void remove_mad_reg_req(struct ib_mad_agent_private *priv); |
| 74 | static struct ib_mad_agent_private *find_mad_agent( | 74 | static struct ib_mad_agent_private *find_mad_agent( |
| 75 | struct ib_mad_port_private *port_priv, | 75 | struct ib_mad_port_private *port_priv, |
| 76 | struct ib_mad *mad); | 76 | const struct ib_mad_hdr *mad); |
| 77 | static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, | 77 | static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, |
| 78 | struct ib_mad_private *mad); | 78 | struct ib_mad_private *mad); |
| 79 | static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv); | 79 | static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv); |
| @@ -179,12 +179,12 @@ static int is_vendor_method_in_use( | |||
| 179 | return 0; | 179 | return 0; |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | int ib_response_mad(struct ib_mad *mad) | 182 | int ib_response_mad(const struct ib_mad_hdr *hdr) |
| 183 | { | 183 | { |
| 184 | return ((mad->mad_hdr.method & IB_MGMT_METHOD_RESP) || | 184 | return ((hdr->method & IB_MGMT_METHOD_RESP) || |
| 185 | (mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS) || | 185 | (hdr->method == IB_MGMT_METHOD_TRAP_REPRESS) || |
| 186 | ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_BM) && | 186 | ((hdr->mgmt_class == IB_MGMT_CLASS_BM) && |
| 187 | (mad->mad_hdr.attr_mod & IB_BM_ATTR_MOD_RESP))); | 187 | (hdr->attr_mod & IB_BM_ATTR_MOD_RESP))); |
| 188 | } | 188 | } |
| 189 | EXPORT_SYMBOL(ib_response_mad); | 189 | EXPORT_SYMBOL(ib_response_mad); |
| 190 | 190 | ||
| @@ -717,6 +717,32 @@ static void build_smp_wc(struct ib_qp *qp, | |||
| 717 | wc->port_num = port_num; | 717 | wc->port_num = port_num; |
| 718 | } | 718 | } |
| 719 | 719 | ||
| 720 | static size_t mad_priv_size(const struct ib_mad_private *mp) | ||
| 721 | { | ||
| 722 | return sizeof(struct ib_mad_private) + mp->mad_size; | ||
| 723 | } | ||
| 724 | |||
| 725 | static struct ib_mad_private *alloc_mad_private(size_t mad_size, gfp_t flags) | ||
| 726 | { | ||
| 727 | size_t size = sizeof(struct ib_mad_private) + mad_size; | ||
| 728 | struct ib_mad_private *ret = kzalloc(size, flags); | ||
| 729 | |||
| 730 | if (ret) | ||
| 731 | ret->mad_size = mad_size; | ||
| 732 | |||
| 733 | return ret; | ||
| 734 | } | ||
| 735 | |||
| 736 | static size_t port_mad_size(const struct ib_mad_port_private *port_priv) | ||
| 737 | { | ||
| 738 | return rdma_max_mad_size(port_priv->device, port_priv->port_num); | ||
| 739 | } | ||
| 740 | |||
| 741 | static size_t mad_priv_dma_size(const struct ib_mad_private *mp) | ||
| 742 | { | ||
| 743 | return sizeof(struct ib_grh) + mp->mad_size; | ||
| 744 | } | ||
| 745 | |||
| 720 | /* | 746 | /* |
| 721 | * Return 0 if SMP is to be sent | 747 | * Return 0 if SMP is to be sent |
| 722 | * Return 1 if SMP was consumed locally (whether or not solicited) | 748 | * Return 1 if SMP was consumed locally (whether or not solicited) |
| @@ -727,6 +753,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, | |||
| 727 | { | 753 | { |
| 728 | int ret = 0; | 754 | int ret = 0; |
| 729 | struct ib_smp *smp = mad_send_wr->send_buf.mad; | 755 | struct ib_smp *smp = mad_send_wr->send_buf.mad; |
| 756 | struct opa_smp *opa_smp = (struct opa_smp *)smp; | ||
| 730 | unsigned long flags; | 757 | unsigned long flags; |
| 731 | struct ib_mad_local_private *local; | 758 | struct ib_mad_local_private *local; |
| 732 | struct ib_mad_private *mad_priv; | 759 | struct ib_mad_private *mad_priv; |
| @@ -736,8 +763,13 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, | |||
| 736 | u8 port_num; | 763 | u8 port_num; |
| 737 | struct ib_wc mad_wc; | 764 | struct ib_wc mad_wc; |
| 738 | struct ib_send_wr *send_wr = &mad_send_wr->send_wr; | 765 | struct ib_send_wr *send_wr = &mad_send_wr->send_wr; |
| 766 | size_t mad_size = port_mad_size(mad_agent_priv->qp_info->port_priv); | ||
| 767 | u16 out_mad_pkey_index = 0; | ||
| 768 | u16 drslid; | ||
| 769 | bool opa = rdma_cap_opa_mad(mad_agent_priv->qp_info->port_priv->device, | ||
| 770 | mad_agent_priv->qp_info->port_priv->port_num); | ||
| 739 | 771 | ||
| 740 | if (device->node_type == RDMA_NODE_IB_SWITCH && | 772 | if (rdma_cap_ib_switch(device) && |
| 741 | smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) | 773 | smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) |
| 742 | port_num = send_wr->wr.ud.port_num; | 774 | port_num = send_wr->wr.ud.port_num; |
| 743 | else | 775 | else |
| @@ -749,19 +781,49 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, | |||
| 749 | * If we are at the start of the LID routed part, don't update the | 781 | * If we are at the start of the LID routed part, don't update the |
| 750 | * hop_ptr or hop_cnt. See section 14.2.2, Vol 1 IB spec. | 782 | * hop_ptr or hop_cnt. See section 14.2.2, Vol 1 IB spec. |
| 751 | */ | 783 | */ |
| 752 | if ((ib_get_smp_direction(smp) ? smp->dr_dlid : smp->dr_slid) == | 784 | if (opa && smp->class_version == OPA_SMP_CLASS_VERSION) { |
| 753 | IB_LID_PERMISSIVE && | 785 | u32 opa_drslid; |
| 754 | smi_handle_dr_smp_send(smp, device->node_type, port_num) == | 786 | |
| 755 | IB_SMI_DISCARD) { | 787 | if ((opa_get_smp_direction(opa_smp) |
| 756 | ret = -EINVAL; | 788 | ? opa_smp->route.dr.dr_dlid : opa_smp->route.dr.dr_slid) == |
| 757 | dev_err(&device->dev, "Invalid directed route\n"); | 789 | OPA_LID_PERMISSIVE && |
| 758 | goto out; | 790 | opa_smi_handle_dr_smp_send(opa_smp, |
| 759 | } | 791 | rdma_cap_ib_switch(device), |
| 792 | port_num) == IB_SMI_DISCARD) { | ||
| 793 | ret = -EINVAL; | ||
| 794 | dev_err(&device->dev, "OPA Invalid directed route\n"); | ||
| 795 | goto out; | ||
| 796 | } | ||
| 797 | opa_drslid = be32_to_cpu(opa_smp->route.dr.dr_slid); | ||
| 798 | if (opa_drslid != be32_to_cpu(OPA_LID_PERMISSIVE) && | ||
| 799 | opa_drslid & 0xffff0000) { | ||
| 800 | ret = -EINVAL; | ||
| 801 | dev_err(&device->dev, "OPA Invalid dr_slid 0x%x\n", | ||
| 802 | opa_drslid); | ||
| 803 | goto out; | ||
| 804 | } | ||
| 805 | drslid = (u16)(opa_drslid & 0x0000ffff); | ||
| 760 | 806 | ||
| 761 | /* Check to post send on QP or process locally */ | 807 | /* Check to post send on QP or process locally */ |
| 762 | if (smi_check_local_smp(smp, device) == IB_SMI_DISCARD && | 808 | if (opa_smi_check_local_smp(opa_smp, device) == IB_SMI_DISCARD && |
| 763 | smi_check_local_returning_smp(smp, device) == IB_SMI_DISCARD) | 809 | opa_smi_check_local_returning_smp(opa_smp, device) == IB_SMI_DISCARD) |
| 764 | goto out; | 810 | goto out; |
| 811 | } else { | ||
| 812 | if ((ib_get_smp_direction(smp) ? smp->dr_dlid : smp->dr_slid) == | ||
| 813 | IB_LID_PERMISSIVE && | ||
| 814 | smi_handle_dr_smp_send(smp, rdma_cap_ib_switch(device), port_num) == | ||
| 815 | IB_SMI_DISCARD) { | ||
| 816 | ret = -EINVAL; | ||
| 817 | dev_err(&device->dev, "Invalid directed route\n"); | ||
| 818 | goto out; | ||
| 819 | } | ||
| 820 | drslid = be16_to_cpu(smp->dr_slid); | ||
| 821 | |||
| 822 | /* Check to post send on QP or process locally */ | ||
| 823 | if (smi_check_local_smp(smp, device) == IB_SMI_DISCARD && | ||
| 824 | smi_check_local_returning_smp(smp, device) == IB_SMI_DISCARD) | ||
| 825 | goto out; | ||
| 826 | } | ||
| 765 | 827 | ||
| 766 | local = kmalloc(sizeof *local, GFP_ATOMIC); | 828 | local = kmalloc(sizeof *local, GFP_ATOMIC); |
| 767 | if (!local) { | 829 | if (!local) { |
| @@ -771,7 +833,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, | |||
| 771 | } | 833 | } |
| 772 | local->mad_priv = NULL; | 834 | local->mad_priv = NULL; |
| 773 | local->recv_mad_agent = NULL; | 835 | local->recv_mad_agent = NULL; |
| 774 | mad_priv = kmem_cache_alloc(ib_mad_cache, GFP_ATOMIC); | 836 | mad_priv = alloc_mad_private(mad_size, GFP_ATOMIC); |
| 775 | if (!mad_priv) { | 837 | if (!mad_priv) { |
| 776 | ret = -ENOMEM; | 838 | ret = -ENOMEM; |
| 777 | dev_err(&device->dev, "No memory for local response MAD\n"); | 839 | dev_err(&device->dev, "No memory for local response MAD\n"); |
| @@ -780,18 +842,25 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, | |||
| 780 | } | 842 | } |
| 781 | 843 | ||
| 782 | build_smp_wc(mad_agent_priv->agent.qp, | 844 | build_smp_wc(mad_agent_priv->agent.qp, |
| 783 | send_wr->wr_id, be16_to_cpu(smp->dr_slid), | 845 | send_wr->wr_id, drslid, |
| 784 | send_wr->wr.ud.pkey_index, | 846 | send_wr->wr.ud.pkey_index, |
| 785 | send_wr->wr.ud.port_num, &mad_wc); | 847 | send_wr->wr.ud.port_num, &mad_wc); |
| 786 | 848 | ||
| 849 | if (opa && smp->base_version == OPA_MGMT_BASE_VERSION) { | ||
| 850 | mad_wc.byte_len = mad_send_wr->send_buf.hdr_len | ||
| 851 | + mad_send_wr->send_buf.data_len | ||
| 852 | + sizeof(struct ib_grh); | ||
| 853 | } | ||
| 854 | |||
| 787 | /* No GRH for DR SMP */ | 855 | /* No GRH for DR SMP */ |
| 788 | ret = device->process_mad(device, 0, port_num, &mad_wc, NULL, | 856 | ret = device->process_mad(device, 0, port_num, &mad_wc, NULL, |
| 789 | (struct ib_mad *)smp, | 857 | (const struct ib_mad_hdr *)smp, mad_size, |
| 790 | (struct ib_mad *)&mad_priv->mad); | 858 | (struct ib_mad_hdr *)mad_priv->mad, |
| 859 | &mad_size, &out_mad_pkey_index); | ||
| 791 | switch (ret) | 860 | switch (ret) |
| 792 | { | 861 | { |
| 793 | case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY: | 862 | case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY: |
| 794 | if (ib_response_mad(&mad_priv->mad.mad) && | 863 | if (ib_response_mad((const struct ib_mad_hdr *)mad_priv->mad) && |
| 795 | mad_agent_priv->agent.recv_handler) { | 864 | mad_agent_priv->agent.recv_handler) { |
| 796 | local->mad_priv = mad_priv; | 865 | local->mad_priv = mad_priv; |
| 797 | local->recv_mad_agent = mad_agent_priv; | 866 | local->recv_mad_agent = mad_agent_priv; |
| @@ -801,39 +870,43 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, | |||
| 801 | */ | 870 | */ |
| 802 | atomic_inc(&mad_agent_priv->refcount); | 871 | atomic_inc(&mad_agent_priv->refcount); |
| 803 | } else | 872 | } else |
| 804 | kmem_cache_free(ib_mad_cache, mad_priv); | 873 | kfree(mad_priv); |
| 805 | break; | 874 | break; |
| 806 | case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED: | 875 | case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED: |
| 807 | kmem_cache_free(ib_mad_cache, mad_priv); | 876 | kfree(mad_priv); |
| 808 | break; | 877 | break; |
| 809 | case IB_MAD_RESULT_SUCCESS: | 878 | case IB_MAD_RESULT_SUCCESS: |
| 810 | /* Treat like an incoming receive MAD */ | 879 | /* Treat like an incoming receive MAD */ |
| 811 | port_priv = ib_get_mad_port(mad_agent_priv->agent.device, | 880 | port_priv = ib_get_mad_port(mad_agent_priv->agent.device, |
| 812 | mad_agent_priv->agent.port_num); | 881 | mad_agent_priv->agent.port_num); |
| 813 | if (port_priv) { | 882 | if (port_priv) { |
| 814 | memcpy(&mad_priv->mad.mad, smp, sizeof(struct ib_mad)); | 883 | memcpy(mad_priv->mad, smp, mad_priv->mad_size); |
| 815 | recv_mad_agent = find_mad_agent(port_priv, | 884 | recv_mad_agent = find_mad_agent(port_priv, |
| 816 | &mad_priv->mad.mad); | 885 | (const struct ib_mad_hdr *)mad_priv->mad); |
| 817 | } | 886 | } |
| 818 | if (!port_priv || !recv_mad_agent) { | 887 | if (!port_priv || !recv_mad_agent) { |
| 819 | /* | 888 | /* |
| 820 | * No receiving agent so drop packet and | 889 | * No receiving agent so drop packet and |
| 821 | * generate send completion. | 890 | * generate send completion. |
| 822 | */ | 891 | */ |
| 823 | kmem_cache_free(ib_mad_cache, mad_priv); | 892 | kfree(mad_priv); |
| 824 | break; | 893 | break; |
| 825 | } | 894 | } |
| 826 | local->mad_priv = mad_priv; | 895 | local->mad_priv = mad_priv; |
| 827 | local->recv_mad_agent = recv_mad_agent; | 896 | local->recv_mad_agent = recv_mad_agent; |
| 828 | break; | 897 | break; |
| 829 | default: | 898 | default: |
| 830 | kmem_cache_free(ib_mad_cache, mad_priv); | 899 | kfree(mad_priv); |
| 831 | kfree(local); | 900 | kfree(local); |
| 832 | ret = -EINVAL; | 901 | ret = -EINVAL; |
| 833 | goto out; | 902 | goto out; |
| 834 | } | 903 | } |
| 835 | 904 | ||
| 836 | local->mad_send_wr = mad_send_wr; | 905 | local->mad_send_wr = mad_send_wr; |
| 906 | if (opa) { | ||
| 907 | local->mad_send_wr->send_wr.wr.ud.pkey_index = out_mad_pkey_index; | ||
| 908 | local->return_wc_byte_len = mad_size; | ||
| 909 | } | ||
| 837 | /* Reference MAD agent until send side of local completion handled */ | 910 | /* Reference MAD agent until send side of local completion handled */ |
| 838 | atomic_inc(&mad_agent_priv->refcount); | 911 | atomic_inc(&mad_agent_priv->refcount); |
| 839 | /* Queue local completion to local list */ | 912 | /* Queue local completion to local list */ |
| @@ -847,11 +920,11 @@ out: | |||
| 847 | return ret; | 920 | return ret; |
| 848 | } | 921 | } |
| 849 | 922 | ||
| 850 | static int get_pad_size(int hdr_len, int data_len) | 923 | static int get_pad_size(int hdr_len, int data_len, size_t mad_size) |
| 851 | { | 924 | { |
| 852 | int seg_size, pad; | 925 | int seg_size, pad; |
| 853 | 926 | ||
| 854 | seg_size = sizeof(struct ib_mad) - hdr_len; | 927 | seg_size = mad_size - hdr_len; |
| 855 | if (data_len && seg_size) { | 928 | if (data_len && seg_size) { |
| 856 | pad = seg_size - data_len % seg_size; | 929 | pad = seg_size - data_len % seg_size; |
| 857 | return pad == seg_size ? 0 : pad; | 930 | return pad == seg_size ? 0 : pad; |
| @@ -870,14 +943,15 @@ static void free_send_rmpp_list(struct ib_mad_send_wr_private *mad_send_wr) | |||
| 870 | } | 943 | } |
| 871 | 944 | ||
| 872 | static int alloc_send_rmpp_list(struct ib_mad_send_wr_private *send_wr, | 945 | static int alloc_send_rmpp_list(struct ib_mad_send_wr_private *send_wr, |
| 873 | gfp_t gfp_mask) | 946 | size_t mad_size, gfp_t gfp_mask) |
| 874 | { | 947 | { |
| 875 | struct ib_mad_send_buf *send_buf = &send_wr->send_buf; | 948 | struct ib_mad_send_buf *send_buf = &send_wr->send_buf; |
| 876 | struct ib_rmpp_mad *rmpp_mad = send_buf->mad; | 949 | struct ib_rmpp_mad *rmpp_mad = send_buf->mad; |
| 877 | struct ib_rmpp_segment *seg = NULL; | 950 | struct ib_rmpp_segment *seg = NULL; |
| 878 | int left, seg_size, pad; | 951 | int left, seg_size, pad; |
| 879 | 952 | ||
| 880 | send_buf->seg_size = sizeof (struct ib_mad) - send_buf->hdr_len; | 953 | send_buf->seg_size = mad_size - send_buf->hdr_len; |
| 954 | send_buf->seg_rmpp_size = mad_size - IB_MGMT_RMPP_HDR; | ||
| 881 | seg_size = send_buf->seg_size; | 955 | seg_size = send_buf->seg_size; |
| 882 | pad = send_wr->pad; | 956 | pad = send_wr->pad; |
| 883 | 957 | ||
| @@ -910,7 +984,7 @@ static int alloc_send_rmpp_list(struct ib_mad_send_wr_private *send_wr, | |||
| 910 | return 0; | 984 | return 0; |
| 911 | } | 985 | } |
| 912 | 986 | ||
| 913 | int ib_mad_kernel_rmpp_agent(struct ib_mad_agent *agent) | 987 | int ib_mad_kernel_rmpp_agent(const struct ib_mad_agent *agent) |
| 914 | { | 988 | { |
| 915 | return agent->rmpp_version && !(agent->flags & IB_MAD_USER_RMPP); | 989 | return agent->rmpp_version && !(agent->flags & IB_MAD_USER_RMPP); |
| 916 | } | 990 | } |
| @@ -920,26 +994,37 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, | |||
| 920 | u32 remote_qpn, u16 pkey_index, | 994 | u32 remote_qpn, u16 pkey_index, |
| 921 | int rmpp_active, | 995 | int rmpp_active, |
| 922 | int hdr_len, int data_len, | 996 | int hdr_len, int data_len, |
| 923 | gfp_t gfp_mask) | 997 | gfp_t gfp_mask, |
| 998 | u8 base_version) | ||
| 924 | { | 999 | { |
| 925 | struct ib_mad_agent_private *mad_agent_priv; | 1000 | struct ib_mad_agent_private *mad_agent_priv; |
| 926 | struct ib_mad_send_wr_private *mad_send_wr; | 1001 | struct ib_mad_send_wr_private *mad_send_wr; |
| 927 | int pad, message_size, ret, size; | 1002 | int pad, message_size, ret, size; |
| 928 | void *buf; | 1003 | void *buf; |
| 1004 | size_t mad_size; | ||
| 1005 | bool opa; | ||
| 929 | 1006 | ||
| 930 | mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private, | 1007 | mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private, |
| 931 | agent); | 1008 | agent); |
| 932 | pad = get_pad_size(hdr_len, data_len); | 1009 | |
| 1010 | opa = rdma_cap_opa_mad(mad_agent->device, mad_agent->port_num); | ||
| 1011 | |||
| 1012 | if (opa && base_version == OPA_MGMT_BASE_VERSION) | ||
| 1013 | mad_size = sizeof(struct opa_mad); | ||
| 1014 | else | ||
| 1015 | mad_size = sizeof(struct ib_mad); | ||
| 1016 | |||
| 1017 | pad = get_pad_size(hdr_len, data_len, mad_size); | ||
| 933 | message_size = hdr_len + data_len + pad; | 1018 | message_size = hdr_len + data_len + pad; |
| 934 | 1019 | ||
| 935 | if (ib_mad_kernel_rmpp_agent(mad_agent)) { | 1020 | if (ib_mad_kernel_rmpp_agent(mad_agent)) { |
| 936 | if (!rmpp_active && message_size > sizeof(struct ib_mad)) | 1021 | if (!rmpp_active && message_size > mad_size) |
| 937 | return ERR_PTR(-EINVAL); | 1022 | return ERR_PTR(-EINVAL); |
| 938 | } else | 1023 | } else |
| 939 | if (rmpp_active || message_size > sizeof(struct ib_mad)) | 1024 | if (rmpp_active || message_size > mad_size) |
| 940 | return ERR_PTR(-EINVAL); | 1025 | return ERR_PTR(-EINVAL); |
| 941 | 1026 | ||
| 942 | size = rmpp_active ? hdr_len : sizeof(struct ib_mad); | 1027 | size = rmpp_active ? hdr_len : mad_size; |
| 943 | buf = kzalloc(sizeof *mad_send_wr + size, gfp_mask); | 1028 | buf = kzalloc(sizeof *mad_send_wr + size, gfp_mask); |
| 944 | if (!buf) | 1029 | if (!buf) |
| 945 | return ERR_PTR(-ENOMEM); | 1030 | return ERR_PTR(-ENOMEM); |
| @@ -954,7 +1039,14 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, | |||
| 954 | mad_send_wr->mad_agent_priv = mad_agent_priv; | 1039 | mad_send_wr->mad_agent_priv = mad_agent_priv; |
| 955 | mad_send_wr->sg_list[0].length = hdr_len; | 1040 | mad_send_wr->sg_list[0].length = hdr_len; |
| 956 | mad_send_wr->sg_list[0].lkey = mad_agent->mr->lkey; | 1041 | mad_send_wr->sg_list[0].lkey = mad_agent->mr->lkey; |
| 957 | mad_send_wr->sg_list[1].length = sizeof(struct ib_mad) - hdr_len; | 1042 | |
| 1043 | /* OPA MADs don't have to be the full 2048 bytes */ | ||
| 1044 | if (opa && base_version == OPA_MGMT_BASE_VERSION && | ||
| 1045 | data_len < mad_size - hdr_len) | ||
| 1046 | mad_send_wr->sg_list[1].length = data_len; | ||
| 1047 | else | ||
| 1048 | mad_send_wr->sg_list[1].length = mad_size - hdr_len; | ||
| 1049 | |||
| 958 | mad_send_wr->sg_list[1].lkey = mad_agent->mr->lkey; | 1050 | mad_send_wr->sg_list[1].lkey = mad_agent->mr->lkey; |
| 959 | 1051 | ||
| 960 | mad_send_wr->send_wr.wr_id = (unsigned long) mad_send_wr; | 1052 | mad_send_wr->send_wr.wr_id = (unsigned long) mad_send_wr; |
| @@ -967,7 +1059,7 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, | |||
| 967 | mad_send_wr->send_wr.wr.ud.pkey_index = pkey_index; | 1059 | mad_send_wr->send_wr.wr.ud.pkey_index = pkey_index; |
| 968 | 1060 | ||
| 969 | if (rmpp_active) { | 1061 | if (rmpp_active) { |
| 970 | ret = alloc_send_rmpp_list(mad_send_wr, gfp_mask); | 1062 | ret = alloc_send_rmpp_list(mad_send_wr, mad_size, gfp_mask); |
| 971 | if (ret) { | 1063 | if (ret) { |
| 972 | kfree(buf); | 1064 | kfree(buf); |
| 973 | return ERR_PTR(ret); | 1065 | return ERR_PTR(ret); |
| @@ -1237,7 +1329,7 @@ void ib_free_recv_mad(struct ib_mad_recv_wc *mad_recv_wc) | |||
| 1237 | recv_wc); | 1329 | recv_wc); |
| 1238 | priv = container_of(mad_priv_hdr, struct ib_mad_private, | 1330 | priv = container_of(mad_priv_hdr, struct ib_mad_private, |
| 1239 | header); | 1331 | header); |
| 1240 | kmem_cache_free(ib_mad_cache, priv); | 1332 | kfree(priv); |
| 1241 | } | 1333 | } |
| 1242 | } | 1334 | } |
| 1243 | EXPORT_SYMBOL(ib_free_recv_mad); | 1335 | EXPORT_SYMBOL(ib_free_recv_mad); |
| @@ -1324,7 +1416,7 @@ static int check_vendor_class(struct ib_mad_mgmt_vendor_class *vendor_class) | |||
| 1324 | } | 1416 | } |
| 1325 | 1417 | ||
| 1326 | static int find_vendor_oui(struct ib_mad_mgmt_vendor_class *vendor_class, | 1418 | static int find_vendor_oui(struct ib_mad_mgmt_vendor_class *vendor_class, |
| 1327 | char *oui) | 1419 | const char *oui) |
| 1328 | { | 1420 | { |
| 1329 | int i; | 1421 | int i; |
| 1330 | 1422 | ||
| @@ -1622,13 +1714,13 @@ out: | |||
| 1622 | 1714 | ||
| 1623 | static struct ib_mad_agent_private * | 1715 | static struct ib_mad_agent_private * |
| 1624 | find_mad_agent(struct ib_mad_port_private *port_priv, | 1716 | find_mad_agent(struct ib_mad_port_private *port_priv, |
| 1625 | struct ib_mad *mad) | 1717 | const struct ib_mad_hdr *mad_hdr) |
| 1626 | { | 1718 | { |
| 1627 | struct ib_mad_agent_private *mad_agent = NULL; | 1719 | struct ib_mad_agent_private *mad_agent = NULL; |
| 1628 | unsigned long flags; | 1720 | unsigned long flags; |
| 1629 | 1721 | ||
| 1630 | spin_lock_irqsave(&port_priv->reg_lock, flags); | 1722 | spin_lock_irqsave(&port_priv->reg_lock, flags); |
| 1631 | if (ib_response_mad(mad)) { | 1723 | if (ib_response_mad(mad_hdr)) { |
| 1632 | u32 hi_tid; | 1724 | u32 hi_tid; |
| 1633 | struct ib_mad_agent_private *entry; | 1725 | struct ib_mad_agent_private *entry; |
| 1634 | 1726 | ||
| @@ -1636,7 +1728,7 @@ find_mad_agent(struct ib_mad_port_private *port_priv, | |||
| 1636 | * Routing is based on high 32 bits of transaction ID | 1728 | * Routing is based on high 32 bits of transaction ID |
| 1637 | * of MAD. | 1729 | * of MAD. |
| 1638 | */ | 1730 | */ |
| 1639 | hi_tid = be64_to_cpu(mad->mad_hdr.tid) >> 32; | 1731 | hi_tid = be64_to_cpu(mad_hdr->tid) >> 32; |
| 1640 | list_for_each_entry(entry, &port_priv->agent_list, agent_list) { | 1732 | list_for_each_entry(entry, &port_priv->agent_list, agent_list) { |
| 1641 | if (entry->agent.hi_tid == hi_tid) { | 1733 | if (entry->agent.hi_tid == hi_tid) { |
| 1642 | mad_agent = entry; | 1734 | mad_agent = entry; |
| @@ -1648,45 +1740,45 @@ find_mad_agent(struct ib_mad_port_private *port_priv, | |||
| 1648 | struct ib_mad_mgmt_method_table *method; | 1740 | struct ib_mad_mgmt_method_table *method; |
| 1649 | struct ib_mad_mgmt_vendor_class_table *vendor; | 1741 | struct ib_mad_mgmt_vendor_class_table *vendor; |
| 1650 | struct ib_mad_mgmt_vendor_class *vendor_class; | 1742 | struct ib_mad_mgmt_vendor_class *vendor_class; |
| 1651 | struct ib_vendor_mad *vendor_mad; | 1743 | const struct ib_vendor_mad *vendor_mad; |
| 1652 | int index; | 1744 | int index; |
| 1653 | 1745 | ||
| 1654 | /* | 1746 | /* |
| 1655 | * Routing is based on version, class, and method | 1747 | * Routing is based on version, class, and method |
| 1656 | * For "newer" vendor MADs, also based on OUI | 1748 | * For "newer" vendor MADs, also based on OUI |
| 1657 | */ | 1749 | */ |
| 1658 | if (mad->mad_hdr.class_version >= MAX_MGMT_VERSION) | 1750 | if (mad_hdr->class_version >= MAX_MGMT_VERSION) |
| 1659 | goto out; | 1751 | goto out; |
| 1660 | if (!is_vendor_class(mad->mad_hdr.mgmt_class)) { | 1752 | if (!is_vendor_class(mad_hdr->mgmt_class)) { |
| 1661 | class = port_priv->version[ | 1753 | class = port_priv->version[ |
| 1662 | mad->mad_hdr.class_version].class; | 1754 | mad_hdr->class_version].class; |
| 1663 | if (!class) | 1755 | if (!class) |
| 1664 | goto out; | 1756 | goto out; |
| 1665 | if (convert_mgmt_class(mad->mad_hdr.mgmt_class) >= | 1757 | if (convert_mgmt_class(mad_hdr->mgmt_class) >= |
| 1666 | IB_MGMT_MAX_METHODS) | 1758 | IB_MGMT_MAX_METHODS) |
| 1667 | goto out; | 1759 | goto out; |
| 1668 | method = class->method_table[convert_mgmt_class( | 1760 | method = class->method_table[convert_mgmt_class( |
| 1669 | mad->mad_hdr.mgmt_class)]; | 1761 | mad_hdr->mgmt_class)]; |
| 1670 | if (method) | 1762 | if (method) |
| 1671 | mad_agent = method->agent[mad->mad_hdr.method & | 1763 | mad_agent = method->agent[mad_hdr->method & |
| 1672 | ~IB_MGMT_METHOD_RESP]; | 1764 | ~IB_MGMT_METHOD_RESP]; |
| 1673 | } else { | 1765 | } else { |
| 1674 | vendor = port_priv->version[ | 1766 | vendor = port_priv->version[ |
| 1675 | mad->mad_hdr.class_version].vendor; | 1767 | mad_hdr->class_version].vendor; |
| 1676 | if (!vendor) | 1768 | if (!vendor) |
| 1677 | goto out; | 1769 | goto out; |
| 1678 | vendor_class = vendor->vendor_class[vendor_class_index( | 1770 | vendor_class = vendor->vendor_class[vendor_class_index( |
| 1679 | mad->mad_hdr.mgmt_class)]; | 1771 | mad_hdr->mgmt_class)]; |
| 1680 | if (!vendor_class) | 1772 | if (!vendor_class) |
| 1681 | goto out; | 1773 | goto out; |
| 1682 | /* Find matching OUI */ | 1774 | /* Find matching OUI */ |
| 1683 | vendor_mad = (struct ib_vendor_mad *)mad; | 1775 | vendor_mad = (const struct ib_vendor_mad *)mad_hdr; |
| 1684 | index = find_vendor_oui(vendor_class, vendor_mad->oui); | 1776 | index = find_vendor_oui(vendor_class, vendor_mad->oui); |
| 1685 | if (index == -1) | 1777 | if (index == -1) |
| 1686 | goto out; | 1778 | goto out; |
| 1687 | method = vendor_class->method_table[index]; | 1779 | method = vendor_class->method_table[index]; |
| 1688 | if (method) { | 1780 | if (method) { |
| 1689 | mad_agent = method->agent[mad->mad_hdr.method & | 1781 | mad_agent = method->agent[mad_hdr->method & |
| 1690 | ~IB_MGMT_METHOD_RESP]; | 1782 | ~IB_MGMT_METHOD_RESP]; |
| 1691 | } | 1783 | } |
| 1692 | } | 1784 | } |
| @@ -1708,20 +1800,24 @@ out: | |||
| 1708 | return mad_agent; | 1800 | return mad_agent; |
| 1709 | } | 1801 | } |
| 1710 | 1802 | ||
| 1711 | static int validate_mad(struct ib_mad *mad, u32 qp_num) | 1803 | static int validate_mad(const struct ib_mad_hdr *mad_hdr, |
| 1804 | const struct ib_mad_qp_info *qp_info, | ||
| 1805 | bool opa) | ||
| 1712 | { | 1806 | { |
| 1713 | int valid = 0; | 1807 | int valid = 0; |
| 1808 | u32 qp_num = qp_info->qp->qp_num; | ||
| 1714 | 1809 | ||
| 1715 | /* Make sure MAD base version is understood */ | 1810 | /* Make sure MAD base version is understood */ |
| 1716 | if (mad->mad_hdr.base_version != IB_MGMT_BASE_VERSION) { | 1811 | if (mad_hdr->base_version != IB_MGMT_BASE_VERSION && |
| 1717 | pr_err("MAD received with unsupported base version %d\n", | 1812 | (!opa || mad_hdr->base_version != OPA_MGMT_BASE_VERSION)) { |
| 1718 | mad->mad_hdr.base_version); | 1813 | pr_err("MAD received with unsupported base version %d %s\n", |
| 1814 | mad_hdr->base_version, opa ? "(opa)" : ""); | ||
| 1719 | goto out; | 1815 | goto out; |
| 1720 | } | 1816 | } |
| 1721 | 1817 | ||
| 1722 | /* Filter SMI packets sent to other than QP0 */ | 1818 | /* Filter SMI packets sent to other than QP0 */ |
| 1723 | if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED) || | 1819 | if ((mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED) || |
| 1724 | (mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)) { | 1820 | (mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)) { |
| 1725 | if (qp_num == 0) | 1821 | if (qp_num == 0) |
| 1726 | valid = 1; | 1822 | valid = 1; |
| 1727 | } else { | 1823 | } else { |
| @@ -1734,8 +1830,8 @@ out: | |||
| 1734 | return valid; | 1830 | return valid; |
| 1735 | } | 1831 | } |
| 1736 | 1832 | ||
| 1737 | static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv, | 1833 | static int is_rmpp_data_mad(const struct ib_mad_agent_private *mad_agent_priv, |
| 1738 | struct ib_mad_hdr *mad_hdr) | 1834 | const struct ib_mad_hdr *mad_hdr) |
| 1739 | { | 1835 | { |
| 1740 | struct ib_rmpp_mad *rmpp_mad; | 1836 | struct ib_rmpp_mad *rmpp_mad; |
| 1741 | 1837 | ||
| @@ -1747,16 +1843,16 @@ static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv, | |||
| 1747 | (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA); | 1843 | (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA); |
| 1748 | } | 1844 | } |
| 1749 | 1845 | ||
| 1750 | static inline int rcv_has_same_class(struct ib_mad_send_wr_private *wr, | 1846 | static inline int rcv_has_same_class(const struct ib_mad_send_wr_private *wr, |
| 1751 | struct ib_mad_recv_wc *rwc) | 1847 | const struct ib_mad_recv_wc *rwc) |
| 1752 | { | 1848 | { |
| 1753 | return ((struct ib_mad *)(wr->send_buf.mad))->mad_hdr.mgmt_class == | 1849 | return ((struct ib_mad_hdr *)(wr->send_buf.mad))->mgmt_class == |
| 1754 | rwc->recv_buf.mad->mad_hdr.mgmt_class; | 1850 | rwc->recv_buf.mad->mad_hdr.mgmt_class; |
| 1755 | } | 1851 | } |
| 1756 | 1852 | ||
| 1757 | static inline int rcv_has_same_gid(struct ib_mad_agent_private *mad_agent_priv, | 1853 | static inline int rcv_has_same_gid(const struct ib_mad_agent_private *mad_agent_priv, |
| 1758 | struct ib_mad_send_wr_private *wr, | 1854 | const struct ib_mad_send_wr_private *wr, |
| 1759 | struct ib_mad_recv_wc *rwc ) | 1855 | const struct ib_mad_recv_wc *rwc ) |
| 1760 | { | 1856 | { |
| 1761 | struct ib_ah_attr attr; | 1857 | struct ib_ah_attr attr; |
| 1762 | u8 send_resp, rcv_resp; | 1858 | u8 send_resp, rcv_resp; |
| @@ -1765,8 +1861,8 @@ static inline int rcv_has_same_gid(struct ib_mad_agent_private *mad_agent_priv, | |||
| 1765 | u8 port_num = mad_agent_priv->agent.port_num; | 1861 | u8 port_num = mad_agent_priv->agent.port_num; |
| 1766 | u8 lmc; | 1862 | u8 lmc; |
| 1767 | 1863 | ||
| 1768 | send_resp = ib_response_mad((struct ib_mad *)wr->send_buf.mad); | 1864 | send_resp = ib_response_mad((struct ib_mad_hdr *)wr->send_buf.mad); |
| 1769 | rcv_resp = ib_response_mad(rwc->recv_buf.mad); | 1865 | rcv_resp = ib_response_mad(&rwc->recv_buf.mad->mad_hdr); |
| 1770 | 1866 | ||
| 1771 | if (send_resp == rcv_resp) | 1867 | if (send_resp == rcv_resp) |
| 1772 | /* both requests, or both responses. GIDs different */ | 1868 | /* both requests, or both responses. GIDs different */ |
| @@ -1811,22 +1907,22 @@ static inline int is_direct(u8 class) | |||
| 1811 | } | 1907 | } |
| 1812 | 1908 | ||
| 1813 | struct ib_mad_send_wr_private* | 1909 | struct ib_mad_send_wr_private* |
| 1814 | ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, | 1910 | ib_find_send_mad(const struct ib_mad_agent_private *mad_agent_priv, |
| 1815 | struct ib_mad_recv_wc *wc) | 1911 | const struct ib_mad_recv_wc *wc) |
| 1816 | { | 1912 | { |
| 1817 | struct ib_mad_send_wr_private *wr; | 1913 | struct ib_mad_send_wr_private *wr; |
| 1818 | struct ib_mad *mad; | 1914 | const struct ib_mad_hdr *mad_hdr; |
| 1819 | 1915 | ||
| 1820 | mad = (struct ib_mad *)wc->recv_buf.mad; | 1916 | mad_hdr = &wc->recv_buf.mad->mad_hdr; |
| 1821 | 1917 | ||
| 1822 | list_for_each_entry(wr, &mad_agent_priv->wait_list, agent_list) { | 1918 | list_for_each_entry(wr, &mad_agent_priv->wait_list, agent_list) { |
| 1823 | if ((wr->tid == mad->mad_hdr.tid) && | 1919 | if ((wr->tid == mad_hdr->tid) && |
| 1824 | rcv_has_same_class(wr, wc) && | 1920 | rcv_has_same_class(wr, wc) && |
| 1825 | /* | 1921 | /* |
| 1826 | * Don't check GID for direct routed MADs. | 1922 | * Don't check GID for direct routed MADs. |
| 1827 | * These might have permissive LIDs. | 1923 | * These might have permissive LIDs. |
| 1828 | */ | 1924 | */ |
| 1829 | (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) || | 1925 | (is_direct(mad_hdr->mgmt_class) || |
| 1830 | rcv_has_same_gid(mad_agent_priv, wr, wc))) | 1926 | rcv_has_same_gid(mad_agent_priv, wr, wc))) |
| 1831 | return (wr->status == IB_WC_SUCCESS) ? wr : NULL; | 1927 | return (wr->status == IB_WC_SUCCESS) ? wr : NULL; |
| 1832 | } | 1928 | } |
| @@ -1836,15 +1932,15 @@ ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, | |||
| 1836 | * been notified that the send has completed | 1932 | * been notified that the send has completed |
| 1837 | */ | 1933 | */ |
| 1838 | list_for_each_entry(wr, &mad_agent_priv->send_list, agent_list) { | 1934 | list_for_each_entry(wr, &mad_agent_priv->send_list, agent_list) { |
| 1839 | if (is_data_mad(mad_agent_priv, wr->send_buf.mad) && | 1935 | if (is_rmpp_data_mad(mad_agent_priv, wr->send_buf.mad) && |
| 1840 | wr->tid == mad->mad_hdr.tid && | 1936 | wr->tid == mad_hdr->tid && |
| 1841 | wr->timeout && | 1937 | wr->timeout && |
| 1842 | rcv_has_same_class(wr, wc) && | 1938 | rcv_has_same_class(wr, wc) && |
| 1843 | /* | 1939 | /* |
| 1844 | * Don't check GID for direct routed MADs. | 1940 | * Don't check GID for direct routed MADs. |
| 1845 | * These might have permissive LIDs. | 1941 | * These might have permissive LIDs. |
| 1846 | */ | 1942 | */ |
| 1847 | (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) || | 1943 | (is_direct(mad_hdr->mgmt_class) || |
| 1848 | rcv_has_same_gid(mad_agent_priv, wr, wc))) | 1944 | rcv_has_same_gid(mad_agent_priv, wr, wc))) |
| 1849 | /* Verify request has not been canceled */ | 1945 | /* Verify request has not been canceled */ |
| 1850 | return (wr->status == IB_WC_SUCCESS) ? wr : NULL; | 1946 | return (wr->status == IB_WC_SUCCESS) ? wr : NULL; |
| @@ -1879,7 +1975,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, | |||
| 1879 | } | 1975 | } |
| 1880 | 1976 | ||
| 1881 | /* Complete corresponding request */ | 1977 | /* Complete corresponding request */ |
| 1882 | if (ib_response_mad(mad_recv_wc->recv_buf.mad)) { | 1978 | if (ib_response_mad(&mad_recv_wc->recv_buf.mad->mad_hdr)) { |
| 1883 | spin_lock_irqsave(&mad_agent_priv->lock, flags); | 1979 | spin_lock_irqsave(&mad_agent_priv->lock, flags); |
| 1884 | mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); | 1980 | mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); |
| 1885 | if (!mad_send_wr) { | 1981 | if (!mad_send_wr) { |
| @@ -1924,26 +2020,163 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, | |||
| 1924 | } | 2020 | } |
| 1925 | } | 2021 | } |
| 1926 | 2022 | ||
| 1927 | static bool generate_unmatched_resp(struct ib_mad_private *recv, | 2023 | static enum smi_action handle_ib_smi(const struct ib_mad_port_private *port_priv, |
| 1928 | struct ib_mad_private *response) | 2024 | const struct ib_mad_qp_info *qp_info, |
| 2025 | const struct ib_wc *wc, | ||
| 2026 | int port_num, | ||
| 2027 | struct ib_mad_private *recv, | ||
| 2028 | struct ib_mad_private *response) | ||
| 2029 | { | ||
| 2030 | enum smi_forward_action retsmi; | ||
| 2031 | struct ib_smp *smp = (struct ib_smp *)recv->mad; | ||
| 2032 | |||
| 2033 | if (smi_handle_dr_smp_recv(smp, | ||
| 2034 | rdma_cap_ib_switch(port_priv->device), | ||
| 2035 | port_num, | ||
| 2036 | port_priv->device->phys_port_cnt) == | ||
| 2037 | IB_SMI_DISCARD) | ||
| 2038 | return IB_SMI_DISCARD; | ||
| 2039 | |||
| 2040 | retsmi = smi_check_forward_dr_smp(smp); | ||
| 2041 | if (retsmi == IB_SMI_LOCAL) | ||
| 2042 | return IB_SMI_HANDLE; | ||
| 2043 | |||
| 2044 | if (retsmi == IB_SMI_SEND) { /* don't forward */ | ||
| 2045 | if (smi_handle_dr_smp_send(smp, | ||
| 2046 | rdma_cap_ib_switch(port_priv->device), | ||
| 2047 | port_num) == IB_SMI_DISCARD) | ||
| 2048 | return IB_SMI_DISCARD; | ||
| 2049 | |||
| 2050 | if (smi_check_local_smp(smp, port_priv->device) == IB_SMI_DISCARD) | ||
| 2051 | return IB_SMI_DISCARD; | ||
| 2052 | } else if (rdma_cap_ib_switch(port_priv->device)) { | ||
| 2053 | /* forward case for switches */ | ||
| 2054 | memcpy(response, recv, mad_priv_size(response)); | ||
| 2055 | response->header.recv_wc.wc = &response->header.wc; | ||
| 2056 | response->header.recv_wc.recv_buf.mad = (struct ib_mad *)response->mad; | ||
| 2057 | response->header.recv_wc.recv_buf.grh = &response->grh; | ||
| 2058 | |||
| 2059 | agent_send_response((const struct ib_mad_hdr *)response->mad, | ||
| 2060 | &response->grh, wc, | ||
| 2061 | port_priv->device, | ||
| 2062 | smi_get_fwd_port(smp), | ||
| 2063 | qp_info->qp->qp_num, | ||
| 2064 | response->mad_size, | ||
| 2065 | false); | ||
| 2066 | |||
| 2067 | return IB_SMI_DISCARD; | ||
| 2068 | } | ||
| 2069 | return IB_SMI_HANDLE; | ||
| 2070 | } | ||
| 2071 | |||
| 2072 | static bool generate_unmatched_resp(const struct ib_mad_private *recv, | ||
| 2073 | struct ib_mad_private *response, | ||
| 2074 | size_t *resp_len, bool opa) | ||
| 1929 | { | 2075 | { |
| 1930 | if (recv->mad.mad.mad_hdr.method == IB_MGMT_METHOD_GET || | 2076 | const struct ib_mad_hdr *recv_hdr = (const struct ib_mad_hdr *)recv->mad; |
| 1931 | recv->mad.mad.mad_hdr.method == IB_MGMT_METHOD_SET) { | 2077 | struct ib_mad_hdr *resp_hdr = (struct ib_mad_hdr *)response->mad; |
| 1932 | memcpy(response, recv, sizeof *response); | 2078 | |
| 2079 | if (recv_hdr->method == IB_MGMT_METHOD_GET || | ||
| 2080 | recv_hdr->method == IB_MGMT_METHOD_SET) { | ||
| 2081 | memcpy(response, recv, mad_priv_size(response)); | ||
| 1933 | response->header.recv_wc.wc = &response->header.wc; | 2082 | response->header.recv_wc.wc = &response->header.wc; |
| 1934 | response->header.recv_wc.recv_buf.mad = &response->mad.mad; | 2083 | response->header.recv_wc.recv_buf.mad = (struct ib_mad *)response->mad; |
| 1935 | response->header.recv_wc.recv_buf.grh = &response->grh; | 2084 | response->header.recv_wc.recv_buf.grh = &response->grh; |
| 1936 | response->mad.mad.mad_hdr.method = IB_MGMT_METHOD_GET_RESP; | 2085 | resp_hdr->method = IB_MGMT_METHOD_GET_RESP; |
| 1937 | response->mad.mad.mad_hdr.status = | 2086 | resp_hdr->status = cpu_to_be16(IB_MGMT_MAD_STATUS_UNSUPPORTED_METHOD_ATTRIB); |
| 1938 | cpu_to_be16(IB_MGMT_MAD_STATUS_UNSUPPORTED_METHOD_ATTRIB); | 2087 | if (recv_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) |
| 1939 | if (recv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) | 2088 | resp_hdr->status |= IB_SMP_DIRECTION; |
| 1940 | response->mad.mad.mad_hdr.status |= IB_SMP_DIRECTION; | 2089 | |
| 2090 | if (opa && recv_hdr->base_version == OPA_MGMT_BASE_VERSION) { | ||
| 2091 | if (recv_hdr->mgmt_class == | ||
| 2092 | IB_MGMT_CLASS_SUBN_LID_ROUTED || | ||
| 2093 | recv_hdr->mgmt_class == | ||
| 2094 | IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) | ||
| 2095 | *resp_len = opa_get_smp_header_size( | ||
| 2096 | (struct opa_smp *)recv->mad); | ||
| 2097 | else | ||
| 2098 | *resp_len = sizeof(struct ib_mad_hdr); | ||
| 2099 | } | ||
| 1941 | 2100 | ||
| 1942 | return true; | 2101 | return true; |
| 1943 | } else { | 2102 | } else { |
| 1944 | return false; | 2103 | return false; |
| 1945 | } | 2104 | } |
| 1946 | } | 2105 | } |
| 2106 | |||
| 2107 | static enum smi_action | ||
| 2108 | handle_opa_smi(struct ib_mad_port_private *port_priv, | ||
| 2109 | struct ib_mad_qp_info *qp_info, | ||
| 2110 | struct ib_wc *wc, | ||
| 2111 | int port_num, | ||
| 2112 | struct ib_mad_private *recv, | ||
| 2113 | struct ib_mad_private *response) | ||
| 2114 | { | ||
| 2115 | enum smi_forward_action retsmi; | ||
| 2116 | struct opa_smp *smp = (struct opa_smp *)recv->mad; | ||
| 2117 | |||
| 2118 | if (opa_smi_handle_dr_smp_recv(smp, | ||
| 2119 | rdma_cap_ib_switch(port_priv->device), | ||
| 2120 | port_num, | ||
| 2121 | port_priv->device->phys_port_cnt) == | ||
| 2122 | IB_SMI_DISCARD) | ||
| 2123 | return IB_SMI_DISCARD; | ||
| 2124 | |||
| 2125 | retsmi = opa_smi_check_forward_dr_smp(smp); | ||
| 2126 | if (retsmi == IB_SMI_LOCAL) | ||
| 2127 | return IB_SMI_HANDLE; | ||
| 2128 | |||
| 2129 | if (retsmi == IB_SMI_SEND) { /* don't forward */ | ||
| 2130 | if (opa_smi_handle_dr_smp_send(smp, | ||
| 2131 | rdma_cap_ib_switch(port_priv->device), | ||
| 2132 | port_num) == IB_SMI_DISCARD) | ||
| 2133 | return IB_SMI_DISCARD; | ||
| 2134 | |||
| 2135 | if (opa_smi_check_local_smp(smp, port_priv->device) == | ||
| 2136 | IB_SMI_DISCARD) | ||
| 2137 | return IB_SMI_DISCARD; | ||
| 2138 | |||
| 2139 | } else if (rdma_cap_ib_switch(port_priv->device)) { | ||
| 2140 | /* forward case for switches */ | ||
| 2141 | memcpy(response, recv, mad_priv_size(response)); | ||
| 2142 | response->header.recv_wc.wc = &response->header.wc; | ||
| 2143 | response->header.recv_wc.recv_buf.opa_mad = | ||
| 2144 | (struct opa_mad *)response->mad; | ||
| 2145 | response->header.recv_wc.recv_buf.grh = &response->grh; | ||
| 2146 | |||
| 2147 | agent_send_response((const struct ib_mad_hdr *)response->mad, | ||
| 2148 | &response->grh, wc, | ||
| 2149 | port_priv->device, | ||
| 2150 | opa_smi_get_fwd_port(smp), | ||
| 2151 | qp_info->qp->qp_num, | ||
| 2152 | recv->header.wc.byte_len, | ||
| 2153 | true); | ||
| 2154 | |||
| 2155 | return IB_SMI_DISCARD; | ||
| 2156 | } | ||
| 2157 | |||
| 2158 | return IB_SMI_HANDLE; | ||
| 2159 | } | ||
| 2160 | |||
| 2161 | static enum smi_action | ||
| 2162 | handle_smi(struct ib_mad_port_private *port_priv, | ||
| 2163 | struct ib_mad_qp_info *qp_info, | ||
| 2164 | struct ib_wc *wc, | ||
| 2165 | int port_num, | ||
| 2166 | struct ib_mad_private *recv, | ||
| 2167 | struct ib_mad_private *response, | ||
| 2168 | bool opa) | ||
| 2169 | { | ||
| 2170 | struct ib_mad_hdr *mad_hdr = (struct ib_mad_hdr *)recv->mad; | ||
| 2171 | |||
| 2172 | if (opa && mad_hdr->base_version == OPA_MGMT_BASE_VERSION && | ||
| 2173 | mad_hdr->class_version == OPA_SMI_CLASS_VERSION) | ||
| 2174 | return handle_opa_smi(port_priv, qp_info, wc, port_num, recv, | ||
| 2175 | response); | ||
| 2176 | |||
| 2177 | return handle_ib_smi(port_priv, qp_info, wc, port_num, recv, response); | ||
| 2178 | } | ||
| 2179 | |||
| 1947 | static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv, | 2180 | static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv, |
| 1948 | struct ib_wc *wc) | 2181 | struct ib_wc *wc) |
| 1949 | { | 2182 | { |
| @@ -1954,109 +2187,97 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv, | |||
| 1954 | struct ib_mad_agent_private *mad_agent; | 2187 | struct ib_mad_agent_private *mad_agent; |
| 1955 | int port_num; | 2188 | int port_num; |
| 1956 | int ret = IB_MAD_RESULT_SUCCESS; | 2189 | int ret = IB_MAD_RESULT_SUCCESS; |
| 2190 | size_t mad_size; | ||
| 2191 | u16 resp_mad_pkey_index = 0; | ||
| 2192 | bool opa; | ||
| 1957 | 2193 | ||
| 1958 | mad_list = (struct ib_mad_list_head *)(unsigned long)wc->wr_id; | 2194 | mad_list = (struct ib_mad_list_head *)(unsigned long)wc->wr_id; |
| 1959 | qp_info = mad_list->mad_queue->qp_info; | 2195 | qp_info = mad_list->mad_queue->qp_info; |
| 1960 | dequeue_mad(mad_list); | 2196 | dequeue_mad(mad_list); |
| 1961 | 2197 | ||
| 2198 | opa = rdma_cap_opa_mad(qp_info->port_priv->device, | ||
| 2199 | qp_info->port_priv->port_num); | ||
| 2200 | |||
| 1962 | mad_priv_hdr = container_of(mad_list, struct ib_mad_private_header, | 2201 | mad_priv_hdr = container_of(mad_list, struct ib_mad_private_header, |
| 1963 | mad_list); | 2202 | mad_list); |
| 1964 | recv = container_of(mad_priv_hdr, struct ib_mad_private, header); | 2203 | recv = container_of(mad_priv_hdr, struct ib_mad_private, header); |
| 1965 | ib_dma_unmap_single(port_priv->device, | 2204 | ib_dma_unmap_single(port_priv->device, |
| 1966 | recv->header.mapping, | 2205 | recv->header.mapping, |
| 1967 | sizeof(struct ib_mad_private) - | 2206 | mad_priv_dma_size(recv), |
| 1968 | sizeof(struct ib_mad_private_header), | ||
| 1969 | DMA_FROM_DEVICE); | 2207 | DMA_FROM_DEVICE); |
| 1970 | 2208 | ||
| 1971 | /* Setup MAD receive work completion from "normal" work completion */ | 2209 | /* Setup MAD receive work completion from "normal" work completion */ |
| 1972 | recv->header.wc = *wc; | 2210 | recv->header.wc = *wc; |
| 1973 | recv->header.recv_wc.wc = &recv->header.wc; | 2211 | recv->header.recv_wc.wc = &recv->header.wc; |
| 1974 | recv->header.recv_wc.mad_len = sizeof(struct ib_mad); | 2212 | |
| 1975 | recv->header.recv_wc.recv_buf.mad = &recv->mad.mad; | 2213 | if (opa && ((struct ib_mad_hdr *)(recv->mad))->base_version == OPA_MGMT_BASE_VERSION) { |
| 2214 | recv->header.recv_wc.mad_len = wc->byte_len - sizeof(struct ib_grh); | ||
| 2215 | recv->header.recv_wc.mad_seg_size = sizeof(struct opa_mad); | ||
| 2216 | } else { | ||
| 2217 | recv->header.recv_wc.mad_len = sizeof(struct ib_mad); | ||
| 2218 | recv->header.recv_wc.mad_seg_size = sizeof(struct ib_mad); | ||
| 2219 | } | ||
| 2220 | |||
| 2221 | recv->header.recv_wc.recv_buf.mad = (struct ib_mad *)recv->mad; | ||
| 1976 | recv->header.recv_wc.recv_buf.grh = &recv->grh; | 2222 | recv->header.recv_wc.recv_buf.grh = &recv->grh; |
| 1977 | 2223 | ||
| 1978 | if (atomic_read(&qp_info->snoop_count)) | 2224 | if (atomic_read(&qp_info->snoop_count)) |
| 1979 | snoop_recv(qp_info, &recv->header.recv_wc, IB_MAD_SNOOP_RECVS); | 2225 | snoop_recv(qp_info, &recv->header.recv_wc, IB_MAD_SNOOP_RECVS); |
| 1980 | 2226 | ||
| 1981 | /* Validate MAD */ | 2227 | /* Validate MAD */ |
| 1982 | if (!validate_mad(&recv->mad.mad, qp_info->qp->qp_num)) | 2228 | if (!validate_mad((const struct ib_mad_hdr *)recv->mad, qp_info, opa)) |
| 1983 | goto out; | 2229 | goto out; |
| 1984 | 2230 | ||
| 1985 | response = kmem_cache_alloc(ib_mad_cache, GFP_KERNEL); | 2231 | mad_size = recv->mad_size; |
| 2232 | response = alloc_mad_private(mad_size, GFP_KERNEL); | ||
| 1986 | if (!response) { | 2233 | if (!response) { |
| 1987 | dev_err(&port_priv->device->dev, | 2234 | dev_err(&port_priv->device->dev, |
| 1988 | "ib_mad_recv_done_handler no memory for response buffer\n"); | 2235 | "ib_mad_recv_done_handler no memory for response buffer\n"); |
| 1989 | goto out; | 2236 | goto out; |
| 1990 | } | 2237 | } |
| 1991 | 2238 | ||
| 1992 | if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH) | 2239 | if (rdma_cap_ib_switch(port_priv->device)) |
| 1993 | port_num = wc->port_num; | 2240 | port_num = wc->port_num; |
| 1994 | else | 2241 | else |
| 1995 | port_num = port_priv->port_num; | 2242 | port_num = port_priv->port_num; |
| 1996 | 2243 | ||
| 1997 | if (recv->mad.mad.mad_hdr.mgmt_class == | 2244 | if (((struct ib_mad_hdr *)recv->mad)->mgmt_class == |
| 1998 | IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) { | 2245 | IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) { |
| 1999 | enum smi_forward_action retsmi; | 2246 | if (handle_smi(port_priv, qp_info, wc, port_num, recv, |
| 2000 | 2247 | response, opa) | |
| 2001 | if (smi_handle_dr_smp_recv(&recv->mad.smp, | 2248 | == IB_SMI_DISCARD) |
| 2002 | port_priv->device->node_type, | ||
| 2003 | port_num, | ||
| 2004 | port_priv->device->phys_port_cnt) == | ||
| 2005 | IB_SMI_DISCARD) | ||
| 2006 | goto out; | ||
| 2007 | |||
| 2008 | retsmi = smi_check_forward_dr_smp(&recv->mad.smp); | ||
| 2009 | if (retsmi == IB_SMI_LOCAL) | ||
| 2010 | goto local; | ||
| 2011 | |||
| 2012 | if (retsmi == IB_SMI_SEND) { /* don't forward */ | ||
| 2013 | if (smi_handle_dr_smp_send(&recv->mad.smp, | ||
| 2014 | port_priv->device->node_type, | ||
| 2015 | port_num) == IB_SMI_DISCARD) | ||
| 2016 | goto out; | ||
| 2017 | |||
| 2018 | if (smi_check_local_smp(&recv->mad.smp, port_priv->device) == IB_SMI_DISCARD) | ||
| 2019 | goto out; | ||
| 2020 | } else if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH) { | ||
| 2021 | /* forward case for switches */ | ||
| 2022 | memcpy(response, recv, sizeof(*response)); | ||
| 2023 | response->header.recv_wc.wc = &response->header.wc; | ||
| 2024 | response->header.recv_wc.recv_buf.mad = &response->mad.mad; | ||
| 2025 | response->header.recv_wc.recv_buf.grh = &response->grh; | ||
| 2026 | |||
| 2027 | agent_send_response(&response->mad.mad, | ||
| 2028 | &response->grh, wc, | ||
| 2029 | port_priv->device, | ||
| 2030 | smi_get_fwd_port(&recv->mad.smp), | ||
| 2031 | qp_info->qp->qp_num); | ||
| 2032 | |||
| 2033 | goto out; | 2249 | goto out; |
| 2034 | } | ||
| 2035 | } | 2250 | } |
| 2036 | 2251 | ||
| 2037 | local: | ||
| 2038 | /* Give driver "right of first refusal" on incoming MAD */ | 2252 | /* Give driver "right of first refusal" on incoming MAD */ |
| 2039 | if (port_priv->device->process_mad) { | 2253 | if (port_priv->device->process_mad) { |
| 2040 | ret = port_priv->device->process_mad(port_priv->device, 0, | 2254 | ret = port_priv->device->process_mad(port_priv->device, 0, |
| 2041 | port_priv->port_num, | 2255 | port_priv->port_num, |
| 2042 | wc, &recv->grh, | 2256 | wc, &recv->grh, |
| 2043 | &recv->mad.mad, | 2257 | (const struct ib_mad_hdr *)recv->mad, |
| 2044 | &response->mad.mad); | 2258 | recv->mad_size, |
| 2259 | (struct ib_mad_hdr *)response->mad, | ||
| 2260 | &mad_size, &resp_mad_pkey_index); | ||
| 2261 | |||
| 2262 | if (opa) | ||
| 2263 | wc->pkey_index = resp_mad_pkey_index; | ||
| 2264 | |||
| 2045 | if (ret & IB_MAD_RESULT_SUCCESS) { | 2265 | if (ret & IB_MAD_RESULT_SUCCESS) { |
| 2046 | if (ret & IB_MAD_RESULT_CONSUMED) | 2266 | if (ret & IB_MAD_RESULT_CONSUMED) |
| 2047 | goto out; | 2267 | goto out; |
| 2048 | if (ret & IB_MAD_RESULT_REPLY) { | 2268 | if (ret & IB_MAD_RESULT_REPLY) { |
| 2049 | agent_send_response(&response->mad.mad, | 2269 | agent_send_response((const struct ib_mad_hdr *)response->mad, |
| 2050 | &recv->grh, wc, | 2270 | &recv->grh, wc, |
| 2051 | port_priv->device, | 2271 | port_priv->device, |
| 2052 | port_num, | 2272 | port_num, |
| 2053 | qp_info->qp->qp_num); | 2273 | qp_info->qp->qp_num, |
| 2274 | mad_size, opa); | ||
| 2054 | goto out; | 2275 | goto out; |
| 2055 | } | 2276 | } |
| 2056 | } | 2277 | } |
| 2057 | } | 2278 | } |
| 2058 | 2279 | ||
| 2059 | mad_agent = find_mad_agent(port_priv, &recv->mad.mad); | 2280 | mad_agent = find_mad_agent(port_priv, (const struct ib_mad_hdr *)recv->mad); |
| 2060 | if (mad_agent) { | 2281 | if (mad_agent) { |
| 2061 | ib_mad_complete_recv(mad_agent, &recv->header.recv_wc); | 2282 | ib_mad_complete_recv(mad_agent, &recv->header.recv_wc); |
| 2062 | /* | 2283 | /* |
| @@ -2065,17 +2286,17 @@ local: | |||
| 2065 | */ | 2286 | */ |
| 2066 | recv = NULL; | 2287 | recv = NULL; |
| 2067 | } else if ((ret & IB_MAD_RESULT_SUCCESS) && | 2288 | } else if ((ret & IB_MAD_RESULT_SUCCESS) && |
| 2068 | generate_unmatched_resp(recv, response)) { | 2289 | generate_unmatched_resp(recv, response, &mad_size, opa)) { |
| 2069 | agent_send_response(&response->mad.mad, &recv->grh, wc, | 2290 | agent_send_response((const struct ib_mad_hdr *)response->mad, &recv->grh, wc, |
| 2070 | port_priv->device, port_num, qp_info->qp->qp_num); | 2291 | port_priv->device, port_num, |
| 2292 | qp_info->qp->qp_num, mad_size, opa); | ||
| 2071 | } | 2293 | } |
| 2072 | 2294 | ||
| 2073 | out: | 2295 | out: |
| 2074 | /* Post another receive request for this QP */ | 2296 | /* Post another receive request for this QP */ |
| 2075 | if (response) { | 2297 | if (response) { |
| 2076 | ib_mad_post_receive_mads(qp_info, response); | 2298 | ib_mad_post_receive_mads(qp_info, response); |
| 2077 | if (recv) | 2299 | kfree(recv); |
| 2078 | kmem_cache_free(ib_mad_cache, recv); | ||
| 2079 | } else | 2300 | } else |
| 2080 | ib_mad_post_receive_mads(qp_info, recv); | 2301 | ib_mad_post_receive_mads(qp_info, recv); |
| 2081 | } | 2302 | } |
| @@ -2411,7 +2632,8 @@ find_send_wr(struct ib_mad_agent_private *mad_agent_priv, | |||
| 2411 | 2632 | ||
| 2412 | list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list, | 2633 | list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list, |
| 2413 | agent_list) { | 2634 | agent_list) { |
| 2414 | if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) && | 2635 | if (is_rmpp_data_mad(mad_agent_priv, |
| 2636 | mad_send_wr->send_buf.mad) && | ||
| 2415 | &mad_send_wr->send_buf == send_buf) | 2637 | &mad_send_wr->send_buf == send_buf) |
| 2416 | return mad_send_wr; | 2638 | return mad_send_wr; |
| 2417 | } | 2639 | } |
| @@ -2468,10 +2690,14 @@ static void local_completions(struct work_struct *work) | |||
| 2468 | int free_mad; | 2690 | int free_mad; |
| 2469 | struct ib_wc wc; | 2691 | struct ib_wc wc; |
| 2470 | struct ib_mad_send_wc mad_send_wc; | 2692 | struct ib_mad_send_wc mad_send_wc; |
| 2693 | bool opa; | ||
| 2471 | 2694 | ||
| 2472 | mad_agent_priv = | 2695 | mad_agent_priv = |
| 2473 | container_of(work, struct ib_mad_agent_private, local_work); | 2696 | container_of(work, struct ib_mad_agent_private, local_work); |
| 2474 | 2697 | ||
| 2698 | opa = rdma_cap_opa_mad(mad_agent_priv->qp_info->port_priv->device, | ||
| 2699 | mad_agent_priv->qp_info->port_priv->port_num); | ||
| 2700 | |||
| 2475 | spin_lock_irqsave(&mad_agent_priv->lock, flags); | 2701 | spin_lock_irqsave(&mad_agent_priv->lock, flags); |
| 2476 | while (!list_empty(&mad_agent_priv->local_list)) { | 2702 | while (!list_empty(&mad_agent_priv->local_list)) { |
| 2477 | local = list_entry(mad_agent_priv->local_list.next, | 2703 | local = list_entry(mad_agent_priv->local_list.next, |
| @@ -2481,6 +2707,7 @@ static void local_completions(struct work_struct *work) | |||
| 2481 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); | 2707 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); |
| 2482 | free_mad = 0; | 2708 | free_mad = 0; |
| 2483 | if (local->mad_priv) { | 2709 | if (local->mad_priv) { |
| 2710 | u8 base_version; | ||
| 2484 | recv_mad_agent = local->recv_mad_agent; | 2711 | recv_mad_agent = local->recv_mad_agent; |
| 2485 | if (!recv_mad_agent) { | 2712 | if (!recv_mad_agent) { |
| 2486 | dev_err(&mad_agent_priv->agent.device->dev, | 2713 | dev_err(&mad_agent_priv->agent.device->dev, |
| @@ -2496,17 +2723,26 @@ static void local_completions(struct work_struct *work) | |||
| 2496 | build_smp_wc(recv_mad_agent->agent.qp, | 2723 | build_smp_wc(recv_mad_agent->agent.qp, |
| 2497 | (unsigned long) local->mad_send_wr, | 2724 | (unsigned long) local->mad_send_wr, |
| 2498 | be16_to_cpu(IB_LID_PERMISSIVE), | 2725 | be16_to_cpu(IB_LID_PERMISSIVE), |
| 2499 | 0, recv_mad_agent->agent.port_num, &wc); | 2726 | local->mad_send_wr->send_wr.wr.ud.pkey_index, |
| 2727 | recv_mad_agent->agent.port_num, &wc); | ||
| 2500 | 2728 | ||
| 2501 | local->mad_priv->header.recv_wc.wc = &wc; | 2729 | local->mad_priv->header.recv_wc.wc = &wc; |
| 2502 | local->mad_priv->header.recv_wc.mad_len = | 2730 | |
| 2503 | sizeof(struct ib_mad); | 2731 | base_version = ((struct ib_mad_hdr *)(local->mad_priv->mad))->base_version; |
| 2732 | if (opa && base_version == OPA_MGMT_BASE_VERSION) { | ||
| 2733 | local->mad_priv->header.recv_wc.mad_len = local->return_wc_byte_len; | ||
| 2734 | local->mad_priv->header.recv_wc.mad_seg_size = sizeof(struct opa_mad); | ||
| 2735 | } else { | ||
| 2736 | local->mad_priv->header.recv_wc.mad_len = sizeof(struct ib_mad); | ||
| 2737 | local->mad_priv->header.recv_wc.mad_seg_size = sizeof(struct ib_mad); | ||
| 2738 | } | ||
| 2739 | |||
| 2504 | INIT_LIST_HEAD(&local->mad_priv->header.recv_wc.rmpp_list); | 2740 | INIT_LIST_HEAD(&local->mad_priv->header.recv_wc.rmpp_list); |
| 2505 | list_add(&local->mad_priv->header.recv_wc.recv_buf.list, | 2741 | list_add(&local->mad_priv->header.recv_wc.recv_buf.list, |
| 2506 | &local->mad_priv->header.recv_wc.rmpp_list); | 2742 | &local->mad_priv->header.recv_wc.rmpp_list); |
| 2507 | local->mad_priv->header.recv_wc.recv_buf.grh = NULL; | 2743 | local->mad_priv->header.recv_wc.recv_buf.grh = NULL; |
| 2508 | local->mad_priv->header.recv_wc.recv_buf.mad = | 2744 | local->mad_priv->header.recv_wc.recv_buf.mad = |
| 2509 | &local->mad_priv->mad.mad; | 2745 | (struct ib_mad *)local->mad_priv->mad; |
| 2510 | if (atomic_read(&recv_mad_agent->qp_info->snoop_count)) | 2746 | if (atomic_read(&recv_mad_agent->qp_info->snoop_count)) |
| 2511 | snoop_recv(recv_mad_agent->qp_info, | 2747 | snoop_recv(recv_mad_agent->qp_info, |
| 2512 | &local->mad_priv->header.recv_wc, | 2748 | &local->mad_priv->header.recv_wc, |
| @@ -2534,7 +2770,7 @@ local_send_completion: | |||
| 2534 | spin_lock_irqsave(&mad_agent_priv->lock, flags); | 2770 | spin_lock_irqsave(&mad_agent_priv->lock, flags); |
| 2535 | atomic_dec(&mad_agent_priv->refcount); | 2771 | atomic_dec(&mad_agent_priv->refcount); |
| 2536 | if (free_mad) | 2772 | if (free_mad) |
| 2537 | kmem_cache_free(ib_mad_cache, local->mad_priv); | 2773 | kfree(local->mad_priv); |
| 2538 | kfree(local); | 2774 | kfree(local); |
| 2539 | } | 2775 | } |
| 2540 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); | 2776 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); |
| @@ -2649,7 +2885,6 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, | |||
| 2649 | struct ib_mad_queue *recv_queue = &qp_info->recv_queue; | 2885 | struct ib_mad_queue *recv_queue = &qp_info->recv_queue; |
| 2650 | 2886 | ||
| 2651 | /* Initialize common scatter list fields */ | 2887 | /* Initialize common scatter list fields */ |
| 2652 | sg_list.length = sizeof *mad_priv - sizeof mad_priv->header; | ||
| 2653 | sg_list.lkey = (*qp_info->port_priv->mr).lkey; | 2888 | sg_list.lkey = (*qp_info->port_priv->mr).lkey; |
| 2654 | 2889 | ||
| 2655 | /* Initialize common receive WR fields */ | 2890 | /* Initialize common receive WR fields */ |
| @@ -2663,7 +2898,8 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, | |||
| 2663 | mad_priv = mad; | 2898 | mad_priv = mad; |
| 2664 | mad = NULL; | 2899 | mad = NULL; |
| 2665 | } else { | 2900 | } else { |
| 2666 | mad_priv = kmem_cache_alloc(ib_mad_cache, GFP_KERNEL); | 2901 | mad_priv = alloc_mad_private(port_mad_size(qp_info->port_priv), |
| 2902 | GFP_ATOMIC); | ||
| 2667 | if (!mad_priv) { | 2903 | if (!mad_priv) { |
| 2668 | dev_err(&qp_info->port_priv->device->dev, | 2904 | dev_err(&qp_info->port_priv->device->dev, |
| 2669 | "No memory for receive buffer\n"); | 2905 | "No memory for receive buffer\n"); |
| @@ -2671,10 +2907,10 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, | |||
| 2671 | break; | 2907 | break; |
| 2672 | } | 2908 | } |
| 2673 | } | 2909 | } |
| 2910 | sg_list.length = mad_priv_dma_size(mad_priv); | ||
| 2674 | sg_list.addr = ib_dma_map_single(qp_info->port_priv->device, | 2911 | sg_list.addr = ib_dma_map_single(qp_info->port_priv->device, |
| 2675 | &mad_priv->grh, | 2912 | &mad_priv->grh, |
| 2676 | sizeof *mad_priv - | 2913 | mad_priv_dma_size(mad_priv), |
| 2677 | sizeof mad_priv->header, | ||
| 2678 | DMA_FROM_DEVICE); | 2914 | DMA_FROM_DEVICE); |
| 2679 | if (unlikely(ib_dma_mapping_error(qp_info->port_priv->device, | 2915 | if (unlikely(ib_dma_mapping_error(qp_info->port_priv->device, |
| 2680 | sg_list.addr))) { | 2916 | sg_list.addr))) { |
| @@ -2698,10 +2934,9 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, | |||
| 2698 | spin_unlock_irqrestore(&recv_queue->lock, flags); | 2934 | spin_unlock_irqrestore(&recv_queue->lock, flags); |
| 2699 | ib_dma_unmap_single(qp_info->port_priv->device, | 2935 | ib_dma_unmap_single(qp_info->port_priv->device, |
| 2700 | mad_priv->header.mapping, | 2936 | mad_priv->header.mapping, |
| 2701 | sizeof *mad_priv - | 2937 | mad_priv_dma_size(mad_priv), |
| 2702 | sizeof mad_priv->header, | ||
| 2703 | DMA_FROM_DEVICE); | 2938 | DMA_FROM_DEVICE); |
| 2704 | kmem_cache_free(ib_mad_cache, mad_priv); | 2939 | kfree(mad_priv); |
| 2705 | dev_err(&qp_info->port_priv->device->dev, | 2940 | dev_err(&qp_info->port_priv->device->dev, |
| 2706 | "ib_post_recv failed: %d\n", ret); | 2941 | "ib_post_recv failed: %d\n", ret); |
| 2707 | break; | 2942 | break; |
| @@ -2738,10 +2973,9 @@ static void cleanup_recv_queue(struct ib_mad_qp_info *qp_info) | |||
| 2738 | 2973 | ||
| 2739 | ib_dma_unmap_single(qp_info->port_priv->device, | 2974 | ib_dma_unmap_single(qp_info->port_priv->device, |
| 2740 | recv->header.mapping, | 2975 | recv->header.mapping, |
| 2741 | sizeof(struct ib_mad_private) - | 2976 | mad_priv_dma_size(recv), |
| 2742 | sizeof(struct ib_mad_private_header), | ||
| 2743 | DMA_FROM_DEVICE); | 2977 | DMA_FROM_DEVICE); |
| 2744 | kmem_cache_free(ib_mad_cache, recv); | 2978 | kfree(recv); |
| 2745 | } | 2979 | } |
| 2746 | 2980 | ||
| 2747 | qp_info->recv_queue.count = 0; | 2981 | qp_info->recv_queue.count = 0; |
| @@ -2922,6 +3156,14 @@ static int ib_mad_port_open(struct ib_device *device, | |||
| 2922 | unsigned long flags; | 3156 | unsigned long flags; |
| 2923 | char name[sizeof "ib_mad123"]; | 3157 | char name[sizeof "ib_mad123"]; |
| 2924 | int has_smi; | 3158 | int has_smi; |
| 3159 | struct ib_cq_init_attr cq_attr = {}; | ||
| 3160 | |||
| 3161 | if (WARN_ON(rdma_max_mad_size(device, port_num) < IB_MGMT_MAD_SIZE)) | ||
| 3162 | return -EFAULT; | ||
| 3163 | |||
| 3164 | if (WARN_ON(rdma_cap_opa_mad(device, port_num) && | ||
| 3165 | rdma_max_mad_size(device, port_num) < OPA_MGMT_MAD_SIZE)) | ||
| 3166 | return -EFAULT; | ||
| 2925 | 3167 | ||
| 2926 | /* Create new device info */ | 3168 | /* Create new device info */ |
| 2927 | port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL); | 3169 | port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL); |
| @@ -2938,13 +3180,14 @@ static int ib_mad_port_open(struct ib_device *device, | |||
| 2938 | init_mad_qp(port_priv, &port_priv->qp_info[1]); | 3180 | init_mad_qp(port_priv, &port_priv->qp_info[1]); |
| 2939 | 3181 | ||
| 2940 | cq_size = mad_sendq_size + mad_recvq_size; | 3182 | cq_size = mad_sendq_size + mad_recvq_size; |
| 2941 | has_smi = rdma_port_get_link_layer(device, port_num) == IB_LINK_LAYER_INFINIBAND; | 3183 | has_smi = rdma_cap_ib_smi(device, port_num); |
| 2942 | if (has_smi) | 3184 | if (has_smi) |
| 2943 | cq_size *= 2; | 3185 | cq_size *= 2; |
| 2944 | 3186 | ||
| 3187 | cq_attr.cqe = cq_size; | ||
| 2945 | port_priv->cq = ib_create_cq(port_priv->device, | 3188 | port_priv->cq = ib_create_cq(port_priv->device, |
| 2946 | ib_mad_thread_completion_handler, | 3189 | ib_mad_thread_completion_handler, |
| 2947 | NULL, port_priv, cq_size, 0); | 3190 | NULL, port_priv, &cq_attr); |
| 2948 | if (IS_ERR(port_priv->cq)) { | 3191 | if (IS_ERR(port_priv->cq)) { |
| 2949 | dev_err(&device->dev, "Couldn't create ib_mad CQ\n"); | 3192 | dev_err(&device->dev, "Couldn't create ib_mad CQ\n"); |
| 2950 | ret = PTR_ERR(port_priv->cq); | 3193 | ret = PTR_ERR(port_priv->cq); |
| @@ -3055,20 +3298,14 @@ static int ib_mad_port_close(struct ib_device *device, int port_num) | |||
| 3055 | 3298 | ||
| 3056 | static void ib_mad_init_device(struct ib_device *device) | 3299 | static void ib_mad_init_device(struct ib_device *device) |
| 3057 | { | 3300 | { |
| 3058 | int start, end, i; | 3301 | int start, i; |
| 3059 | 3302 | ||
| 3060 | if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) | 3303 | start = rdma_start_port(device); |
| 3061 | return; | ||
| 3062 | 3304 | ||
| 3063 | if (device->node_type == RDMA_NODE_IB_SWITCH) { | 3305 | for (i = start; i <= rdma_end_port(device); i++) { |
| 3064 | start = 0; | 3306 | if (!rdma_cap_ib_mad(device, i)) |
| 3065 | end = 0; | 3307 | continue; |
| 3066 | } else { | ||
| 3067 | start = 1; | ||
| 3068 | end = device->phys_port_cnt; | ||
| 3069 | } | ||
| 3070 | 3308 | ||
| 3071 | for (i = start; i <= end; i++) { | ||
| 3072 | if (ib_mad_port_open(device, i)) { | 3309 | if (ib_mad_port_open(device, i)) { |
| 3073 | dev_err(&device->dev, "Couldn't open port %d\n", i); | 3310 | dev_err(&device->dev, "Couldn't open port %d\n", i); |
| 3074 | goto error; | 3311 | goto error; |
| @@ -3086,40 +3323,31 @@ error_agent: | |||
| 3086 | dev_err(&device->dev, "Couldn't close port %d\n", i); | 3323 | dev_err(&device->dev, "Couldn't close port %d\n", i); |
| 3087 | 3324 | ||
| 3088 | error: | 3325 | error: |
| 3089 | i--; | 3326 | while (--i >= start) { |
| 3327 | if (!rdma_cap_ib_mad(device, i)) | ||
| 3328 | continue; | ||
| 3090 | 3329 | ||
| 3091 | while (i >= start) { | ||
| 3092 | if (ib_agent_port_close(device, i)) | 3330 | if (ib_agent_port_close(device, i)) |
| 3093 | dev_err(&device->dev, | 3331 | dev_err(&device->dev, |
| 3094 | "Couldn't close port %d for agents\n", i); | 3332 | "Couldn't close port %d for agents\n", i); |
| 3095 | if (ib_mad_port_close(device, i)) | 3333 | if (ib_mad_port_close(device, i)) |
| 3096 | dev_err(&device->dev, "Couldn't close port %d\n", i); | 3334 | dev_err(&device->dev, "Couldn't close port %d\n", i); |
| 3097 | i--; | ||
| 3098 | } | 3335 | } |
| 3099 | } | 3336 | } |
| 3100 | 3337 | ||
| 3101 | static void ib_mad_remove_device(struct ib_device *device) | 3338 | static void ib_mad_remove_device(struct ib_device *device) |
| 3102 | { | 3339 | { |
| 3103 | int i, num_ports, cur_port; | 3340 | int i; |
| 3104 | 3341 | ||
| 3105 | if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) | 3342 | for (i = rdma_start_port(device); i <= rdma_end_port(device); i++) { |
| 3106 | return; | 3343 | if (!rdma_cap_ib_mad(device, i)) |
| 3344 | continue; | ||
| 3107 | 3345 | ||
| 3108 | if (device->node_type == RDMA_NODE_IB_SWITCH) { | 3346 | if (ib_agent_port_close(device, i)) |
| 3109 | num_ports = 1; | ||
| 3110 | cur_port = 0; | ||
| 3111 | } else { | ||
| 3112 | num_ports = device->phys_port_cnt; | ||
| 3113 | cur_port = 1; | ||
| 3114 | } | ||
| 3115 | for (i = 0; i < num_ports; i++, cur_port++) { | ||
| 3116 | if (ib_agent_port_close(device, cur_port)) | ||
| 3117 | dev_err(&device->dev, | 3347 | dev_err(&device->dev, |
| 3118 | "Couldn't close port %d for agents\n", | 3348 | "Couldn't close port %d for agents\n", i); |
| 3119 | cur_port); | 3349 | if (ib_mad_port_close(device, i)) |
| 3120 | if (ib_mad_port_close(device, cur_port)) | 3350 | dev_err(&device->dev, "Couldn't close port %d\n", i); |
| 3121 | dev_err(&device->dev, "Couldn't close port %d\n", | ||
| 3122 | cur_port); | ||
| 3123 | } | 3351 | } |
| 3124 | } | 3352 | } |
| 3125 | 3353 | ||
| @@ -3131,45 +3359,25 @@ static struct ib_client mad_client = { | |||
| 3131 | 3359 | ||
| 3132 | static int __init ib_mad_init_module(void) | 3360 | static int __init ib_mad_init_module(void) |
| 3133 | { | 3361 | { |
| 3134 | int ret; | ||
| 3135 | |||
| 3136 | mad_recvq_size = min(mad_recvq_size, IB_MAD_QP_MAX_SIZE); | 3362 | mad_recvq_size = min(mad_recvq_size, IB_MAD_QP_MAX_SIZE); |
| 3137 | mad_recvq_size = max(mad_recvq_size, IB_MAD_QP_MIN_SIZE); | 3363 | mad_recvq_size = max(mad_recvq_size, IB_MAD_QP_MIN_SIZE); |
| 3138 | 3364 | ||
| 3139 | mad_sendq_size = min(mad_sendq_size, IB_MAD_QP_MAX_SIZE); | 3365 | mad_sendq_size = min(mad_sendq_size, IB_MAD_QP_MAX_SIZE); |
| 3140 | mad_sendq_size = max(mad_sendq_size, IB_MAD_QP_MIN_SIZE); | 3366 | mad_sendq_size = max(mad_sendq_size, IB_MAD_QP_MIN_SIZE); |
| 3141 | 3367 | ||
| 3142 | ib_mad_cache = kmem_cache_create("ib_mad", | ||
| 3143 | sizeof(struct ib_mad_private), | ||
| 3144 | 0, | ||
| 3145 | SLAB_HWCACHE_ALIGN, | ||
| 3146 | NULL); | ||
| 3147 | if (!ib_mad_cache) { | ||
| 3148 | pr_err("Couldn't create ib_mad cache\n"); | ||
| 3149 | ret = -ENOMEM; | ||
| 3150 | goto error1; | ||
| 3151 | } | ||
| 3152 | |||
| 3153 | INIT_LIST_HEAD(&ib_mad_port_list); | 3368 | INIT_LIST_HEAD(&ib_mad_port_list); |
| 3154 | 3369 | ||
| 3155 | if (ib_register_client(&mad_client)) { | 3370 | if (ib_register_client(&mad_client)) { |
| 3156 | pr_err("Couldn't register ib_mad client\n"); | 3371 | pr_err("Couldn't register ib_mad client\n"); |
| 3157 | ret = -EINVAL; | 3372 | return -EINVAL; |
| 3158 | goto error2; | ||
| 3159 | } | 3373 | } |
| 3160 | 3374 | ||
| 3161 | return 0; | 3375 | return 0; |
| 3162 | |||
| 3163 | error2: | ||
| 3164 | kmem_cache_destroy(ib_mad_cache); | ||
| 3165 | error1: | ||
| 3166 | return ret; | ||
| 3167 | } | 3376 | } |
| 3168 | 3377 | ||
| 3169 | static void __exit ib_mad_cleanup_module(void) | 3378 | static void __exit ib_mad_cleanup_module(void) |
| 3170 | { | 3379 | { |
| 3171 | ib_unregister_client(&mad_client); | 3380 | ib_unregister_client(&mad_client); |
| 3172 | kmem_cache_destroy(ib_mad_cache); | ||
| 3173 | } | 3381 | } |
| 3174 | 3382 | ||
| 3175 | module_init(ib_mad_init_module); | 3383 | module_init(ib_mad_init_module); |
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index d1a0b0ee9444..5be89f98928f 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <linux/workqueue.h> | 41 | #include <linux/workqueue.h> |
| 42 | #include <rdma/ib_mad.h> | 42 | #include <rdma/ib_mad.h> |
| 43 | #include <rdma/ib_smi.h> | 43 | #include <rdma/ib_smi.h> |
| 44 | #include <rdma/opa_smi.h> | ||
| 44 | 45 | ||
| 45 | #define IB_MAD_QPS_CORE 2 /* Always QP0 and QP1 as a minimum */ | 46 | #define IB_MAD_QPS_CORE 2 /* Always QP0 and QP1 as a minimum */ |
| 46 | 47 | ||
| @@ -56,7 +57,7 @@ | |||
| 56 | 57 | ||
| 57 | /* Registration table sizes */ | 58 | /* Registration table sizes */ |
| 58 | #define MAX_MGMT_CLASS 80 | 59 | #define MAX_MGMT_CLASS 80 |
| 59 | #define MAX_MGMT_VERSION 8 | 60 | #define MAX_MGMT_VERSION 0x83 |
| 60 | #define MAX_MGMT_OUI 8 | 61 | #define MAX_MGMT_OUI 8 |
| 61 | #define MAX_MGMT_VENDOR_RANGE2 (IB_MGMT_CLASS_VENDOR_RANGE2_END - \ | 62 | #define MAX_MGMT_VENDOR_RANGE2 (IB_MGMT_CLASS_VENDOR_RANGE2_END - \ |
| 62 | IB_MGMT_CLASS_VENDOR_RANGE2_START + 1) | 63 | IB_MGMT_CLASS_VENDOR_RANGE2_START + 1) |
| @@ -75,12 +76,9 @@ struct ib_mad_private_header { | |||
| 75 | 76 | ||
| 76 | struct ib_mad_private { | 77 | struct ib_mad_private { |
| 77 | struct ib_mad_private_header header; | 78 | struct ib_mad_private_header header; |
| 79 | size_t mad_size; | ||
| 78 | struct ib_grh grh; | 80 | struct ib_grh grh; |
| 79 | union { | 81 | u8 mad[0]; |
| 80 | struct ib_mad mad; | ||
| 81 | struct ib_rmpp_mad rmpp_mad; | ||
| 82 | struct ib_smp smp; | ||
| 83 | } mad; | ||
| 84 | } __attribute__ ((packed)); | 82 | } __attribute__ ((packed)); |
| 85 | 83 | ||
| 86 | struct ib_rmpp_segment { | 84 | struct ib_rmpp_segment { |
| @@ -150,6 +148,7 @@ struct ib_mad_local_private { | |||
| 150 | struct ib_mad_private *mad_priv; | 148 | struct ib_mad_private *mad_priv; |
| 151 | struct ib_mad_agent_private *recv_mad_agent; | 149 | struct ib_mad_agent_private *recv_mad_agent; |
| 152 | struct ib_mad_send_wr_private *mad_send_wr; | 150 | struct ib_mad_send_wr_private *mad_send_wr; |
| 151 | size_t return_wc_byte_len; | ||
| 153 | }; | 152 | }; |
| 154 | 153 | ||
| 155 | struct ib_mad_mgmt_method_table { | 154 | struct ib_mad_mgmt_method_table { |
| @@ -213,8 +212,8 @@ struct ib_mad_port_private { | |||
| 213 | int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr); | 212 | int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr); |
| 214 | 213 | ||
| 215 | struct ib_mad_send_wr_private * | 214 | struct ib_mad_send_wr_private * |
| 216 | ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, | 215 | ib_find_send_mad(const struct ib_mad_agent_private *mad_agent_priv, |
| 217 | struct ib_mad_recv_wc *mad_recv_wc); | 216 | const struct ib_mad_recv_wc *mad_recv_wc); |
| 218 | 217 | ||
| 219 | void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr, | 218 | void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr, |
| 220 | struct ib_mad_send_wc *mad_send_wc); | 219 | struct ib_mad_send_wc *mad_send_wc); |
diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index f37878c9c06e..382941b46e43 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2005 Intel Inc. All rights reserved. | 2 | * Copyright (c) 2005 Intel Inc. All rights reserved. |
| 3 | * Copyright (c) 2005-2006 Voltaire, Inc. All rights reserved. | 3 | * Copyright (c) 2005-2006 Voltaire, Inc. All rights reserved. |
| 4 | * Copyright (c) 2014 Intel Corporation. All rights reserved. | ||
| 4 | * | 5 | * |
| 5 | * This software is available to you under a choice of one of two | 6 | * This software is available to you under a choice of one of two |
| 6 | * licenses. You may choose to be licensed under the terms of the GNU | 7 | * licenses. You may choose to be licensed under the terms of the GNU |
| @@ -67,6 +68,7 @@ struct mad_rmpp_recv { | |||
| 67 | u8 mgmt_class; | 68 | u8 mgmt_class; |
| 68 | u8 class_version; | 69 | u8 class_version; |
| 69 | u8 method; | 70 | u8 method; |
| 71 | u8 base_version; | ||
| 70 | }; | 72 | }; |
| 71 | 73 | ||
| 72 | static inline void deref_rmpp_recv(struct mad_rmpp_recv *rmpp_recv) | 74 | static inline void deref_rmpp_recv(struct mad_rmpp_recv *rmpp_recv) |
| @@ -139,7 +141,8 @@ static void ack_recv(struct mad_rmpp_recv *rmpp_recv, | |||
| 139 | hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); | 141 | hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); |
| 140 | msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp, | 142 | msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp, |
| 141 | recv_wc->wc->pkey_index, 1, hdr_len, | 143 | recv_wc->wc->pkey_index, 1, hdr_len, |
| 142 | 0, GFP_KERNEL); | 144 | 0, GFP_KERNEL, |
| 145 | IB_MGMT_BASE_VERSION); | ||
| 143 | if (IS_ERR(msg)) | 146 | if (IS_ERR(msg)) |
| 144 | return; | 147 | return; |
| 145 | 148 | ||
| @@ -165,7 +168,8 @@ static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent, | |||
| 165 | hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); | 168 | hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); |
| 166 | msg = ib_create_send_mad(agent, recv_wc->wc->src_qp, | 169 | msg = ib_create_send_mad(agent, recv_wc->wc->src_qp, |
| 167 | recv_wc->wc->pkey_index, 1, | 170 | recv_wc->wc->pkey_index, 1, |
| 168 | hdr_len, 0, GFP_KERNEL); | 171 | hdr_len, 0, GFP_KERNEL, |
| 172 | IB_MGMT_BASE_VERSION); | ||
| 169 | if (IS_ERR(msg)) | 173 | if (IS_ERR(msg)) |
| 170 | ib_destroy_ah(ah); | 174 | ib_destroy_ah(ah); |
| 171 | else { | 175 | else { |
| @@ -316,6 +320,7 @@ create_rmpp_recv(struct ib_mad_agent_private *agent, | |||
| 316 | rmpp_recv->mgmt_class = mad_hdr->mgmt_class; | 320 | rmpp_recv->mgmt_class = mad_hdr->mgmt_class; |
| 317 | rmpp_recv->class_version = mad_hdr->class_version; | 321 | rmpp_recv->class_version = mad_hdr->class_version; |
| 318 | rmpp_recv->method = mad_hdr->method; | 322 | rmpp_recv->method = mad_hdr->method; |
| 323 | rmpp_recv->base_version = mad_hdr->base_version; | ||
| 319 | return rmpp_recv; | 324 | return rmpp_recv; |
| 320 | 325 | ||
| 321 | error: kfree(rmpp_recv); | 326 | error: kfree(rmpp_recv); |
| @@ -431,14 +436,23 @@ static inline int get_mad_len(struct mad_rmpp_recv *rmpp_recv) | |||
| 431 | { | 436 | { |
| 432 | struct ib_rmpp_mad *rmpp_mad; | 437 | struct ib_rmpp_mad *rmpp_mad; |
| 433 | int hdr_size, data_size, pad; | 438 | int hdr_size, data_size, pad; |
| 439 | bool opa = rdma_cap_opa_mad(rmpp_recv->agent->qp_info->port_priv->device, | ||
| 440 | rmpp_recv->agent->qp_info->port_priv->port_num); | ||
| 434 | 441 | ||
| 435 | rmpp_mad = (struct ib_rmpp_mad *)rmpp_recv->cur_seg_buf->mad; | 442 | rmpp_mad = (struct ib_rmpp_mad *)rmpp_recv->cur_seg_buf->mad; |
| 436 | 443 | ||
| 437 | hdr_size = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class); | 444 | hdr_size = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class); |
| 438 | data_size = sizeof(struct ib_rmpp_mad) - hdr_size; | 445 | if (opa && rmpp_recv->base_version == OPA_MGMT_BASE_VERSION) { |
| 439 | pad = IB_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); | 446 | data_size = sizeof(struct opa_rmpp_mad) - hdr_size; |
| 440 | if (pad > IB_MGMT_RMPP_DATA || pad < 0) | 447 | pad = OPA_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); |
| 441 | pad = 0; | 448 | if (pad > OPA_MGMT_RMPP_DATA || pad < 0) |
| 449 | pad = 0; | ||
| 450 | } else { | ||
| 451 | data_size = sizeof(struct ib_rmpp_mad) - hdr_size; | ||
| 452 | pad = IB_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); | ||
| 453 | if (pad > IB_MGMT_RMPP_DATA || pad < 0) | ||
| 454 | pad = 0; | ||
| 455 | } | ||
| 442 | 456 | ||
| 443 | return hdr_size + rmpp_recv->seg_num * data_size - pad; | 457 | return hdr_size + rmpp_recv->seg_num * data_size - pad; |
| 444 | } | 458 | } |
| @@ -570,13 +584,14 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) | |||
| 570 | 584 | ||
| 571 | if (mad_send_wr->seg_num == 1) { | 585 | if (mad_send_wr->seg_num == 1) { |
| 572 | rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST; | 586 | rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST; |
| 573 | paylen = mad_send_wr->send_buf.seg_count * IB_MGMT_RMPP_DATA - | 587 | paylen = (mad_send_wr->send_buf.seg_count * |
| 574 | mad_send_wr->pad; | 588 | mad_send_wr->send_buf.seg_rmpp_size) - |
| 589 | mad_send_wr->pad; | ||
| 575 | } | 590 | } |
| 576 | 591 | ||
| 577 | if (mad_send_wr->seg_num == mad_send_wr->send_buf.seg_count) { | 592 | if (mad_send_wr->seg_num == mad_send_wr->send_buf.seg_count) { |
| 578 | rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST; | 593 | rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST; |
| 579 | paylen = IB_MGMT_RMPP_DATA - mad_send_wr->pad; | 594 | paylen = mad_send_wr->send_buf.seg_rmpp_size - mad_send_wr->pad; |
| 580 | } | 595 | } |
| 581 | rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen); | 596 | rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen); |
| 582 | 597 | ||
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c index fa17b552ff78..2cb865c7ce7a 100644 --- a/drivers/infiniband/core/multicast.c +++ b/drivers/infiniband/core/multicast.c | |||
| @@ -780,8 +780,7 @@ static void mcast_event_handler(struct ib_event_handler *handler, | |||
| 780 | int index; | 780 | int index; |
| 781 | 781 | ||
| 782 | dev = container_of(handler, struct mcast_device, event_handler); | 782 | dev = container_of(handler, struct mcast_device, event_handler); |
| 783 | if (rdma_port_get_link_layer(dev->device, event->element.port_num) != | 783 | if (!rdma_cap_ib_mcast(dev->device, event->element.port_num)) |
| 784 | IB_LINK_LAYER_INFINIBAND) | ||
| 785 | return; | 784 | return; |
| 786 | 785 | ||
| 787 | index = event->element.port_num - dev->start_port; | 786 | index = event->element.port_num - dev->start_port; |
| @@ -808,24 +807,16 @@ static void mcast_add_one(struct ib_device *device) | |||
| 808 | int i; | 807 | int i; |
| 809 | int count = 0; | 808 | int count = 0; |
| 810 | 809 | ||
| 811 | if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) | ||
| 812 | return; | ||
| 813 | |||
| 814 | dev = kmalloc(sizeof *dev + device->phys_port_cnt * sizeof *port, | 810 | dev = kmalloc(sizeof *dev + device->phys_port_cnt * sizeof *port, |
| 815 | GFP_KERNEL); | 811 | GFP_KERNEL); |
| 816 | if (!dev) | 812 | if (!dev) |
| 817 | return; | 813 | return; |
| 818 | 814 | ||
| 819 | if (device->node_type == RDMA_NODE_IB_SWITCH) | 815 | dev->start_port = rdma_start_port(device); |
| 820 | dev->start_port = dev->end_port = 0; | 816 | dev->end_port = rdma_end_port(device); |
| 821 | else { | ||
| 822 | dev->start_port = 1; | ||
| 823 | dev->end_port = device->phys_port_cnt; | ||
| 824 | } | ||
| 825 | 817 | ||
| 826 | for (i = 0; i <= dev->end_port - dev->start_port; i++) { | 818 | for (i = 0; i <= dev->end_port - dev->start_port; i++) { |
| 827 | if (rdma_port_get_link_layer(device, dev->start_port + i) != | 819 | if (!rdma_cap_ib_mcast(device, dev->start_port + i)) |
| 828 | IB_LINK_LAYER_INFINIBAND) | ||
| 829 | continue; | 820 | continue; |
| 830 | port = &dev->port[i]; | 821 | port = &dev->port[i]; |
| 831 | port->dev = dev; | 822 | port->dev = dev; |
| @@ -863,8 +854,7 @@ static void mcast_remove_one(struct ib_device *device) | |||
| 863 | flush_workqueue(mcast_wq); | 854 | flush_workqueue(mcast_wq); |
| 864 | 855 | ||
| 865 | for (i = 0; i <= dev->end_port - dev->start_port; i++) { | 856 | for (i = 0; i <= dev->end_port - dev->start_port; i++) { |
| 866 | if (rdma_port_get_link_layer(device, dev->start_port + i) == | 857 | if (rdma_cap_ib_mcast(device, dev->start_port + i)) { |
| 867 | IB_LINK_LAYER_INFINIBAND) { | ||
| 868 | port = &dev->port[i]; | 858 | port = &dev->port[i]; |
| 869 | deref_port(port); | 859 | deref_port(port); |
| 870 | wait_for_completion(&port->comp); | 860 | wait_for_completion(&port->comp); |
diff --git a/drivers/infiniband/core/opa_smi.h b/drivers/infiniband/core/opa_smi.h new file mode 100644 index 000000000000..3bfab3505a29 --- /dev/null +++ b/drivers/infiniband/core/opa_smi.h | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * This software is available to you under a choice of one of two | ||
| 5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
| 6 | * General Public License (GPL) Version 2, available from the file | ||
| 7 | * COPYING in the main directory of this source tree, or the | ||
| 8 | * OpenIB.org BSD license below: | ||
| 9 | * | ||
| 10 | * Redistribution and use in source and binary forms, with or | ||
| 11 | * without modification, are permitted provided that the following | ||
| 12 | * conditions are met: | ||
| 13 | * | ||
| 14 | * - Redistributions of source code must retain the above | ||
| 15 | * copyright notice, this list of conditions and the following | ||
| 16 | * disclaimer. | ||
| 17 | * | ||
| 18 | * - Redistributions in binary form must reproduce the above | ||
| 19 | * copyright notice, this list of conditions and the following | ||
| 20 | * disclaimer in the documentation and/or other materials | ||
| 21 | * provided with the distribution. | ||
| 22 | * | ||
| 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
| 27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
| 28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 30 | * SOFTWARE. | ||
| 31 | * | ||
| 32 | */ | ||
| 33 | |||
| 34 | #ifndef __OPA_SMI_H_ | ||
| 35 | #define __OPA_SMI_H_ | ||
| 36 | |||
| 37 | #include <rdma/ib_smi.h> | ||
| 38 | #include <rdma/opa_smi.h> | ||
| 39 | |||
| 40 | #include "smi.h" | ||
| 41 | |||
| 42 | enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, bool is_switch, | ||
| 43 | int port_num, int phys_port_cnt); | ||
| 44 | int opa_smi_get_fwd_port(struct opa_smp *smp); | ||
| 45 | extern enum smi_forward_action opa_smi_check_forward_dr_smp(struct opa_smp *smp); | ||
| 46 | extern enum smi_action opa_smi_handle_dr_smp_send(struct opa_smp *smp, | ||
| 47 | bool is_switch, int port_num); | ||
| 48 | |||
| 49 | /* | ||
| 50 | * Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM | ||
| 51 | * via process_mad | ||
| 52 | */ | ||
| 53 | static inline enum smi_action opa_smi_check_local_smp(struct opa_smp *smp, | ||
| 54 | struct ib_device *device) | ||
| 55 | { | ||
| 56 | /* C14-9:3 -- We're at the end of the DR segment of path */ | ||
| 57 | /* C14-9:4 -- Hop Pointer = Hop Count + 1 -> give to SMA/SM */ | ||
| 58 | return (device->process_mad && | ||
| 59 | !opa_get_smp_direction(smp) && | ||
| 60 | (smp->hop_ptr == smp->hop_cnt + 1)) ? | ||
| 61 | IB_SMI_HANDLE : IB_SMI_DISCARD; | ||
| 62 | } | ||
| 63 | |||
| 64 | /* | ||
| 65 | * Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM | ||
| 66 | * via process_mad | ||
| 67 | */ | ||
| 68 | static inline enum smi_action opa_smi_check_local_returning_smp(struct opa_smp *smp, | ||
| 69 | struct ib_device *device) | ||
| 70 | { | ||
| 71 | /* C14-13:3 -- We're at the end of the DR segment of path */ | ||
| 72 | /* C14-13:4 -- Hop Pointer == 0 -> give to SM */ | ||
| 73 | return (device->process_mad && | ||
| 74 | opa_get_smp_direction(smp) && | ||
| 75 | !smp->hop_ptr) ? IB_SMI_HANDLE : IB_SMI_DISCARD; | ||
| 76 | } | ||
| 77 | |||
| 78 | #endif /* __OPA_SMI_H_ */ | ||
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index c38f030f0dc9..ca919f429666 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c | |||
| @@ -450,7 +450,7 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event | |||
| 450 | struct ib_sa_port *port = | 450 | struct ib_sa_port *port = |
| 451 | &sa_dev->port[event->element.port_num - sa_dev->start_port]; | 451 | &sa_dev->port[event->element.port_num - sa_dev->start_port]; |
| 452 | 452 | ||
| 453 | if (rdma_port_get_link_layer(handler->device, port->port_num) != IB_LINK_LAYER_INFINIBAND) | 453 | if (!rdma_cap_ib_sa(handler->device, port->port_num)) |
| 454 | return; | 454 | return; |
| 455 | 455 | ||
| 456 | spin_lock_irqsave(&port->ah_lock, flags); | 456 | spin_lock_irqsave(&port->ah_lock, flags); |
| @@ -540,7 +540,7 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num, | |||
| 540 | ah_attr->port_num = port_num; | 540 | ah_attr->port_num = port_num; |
| 541 | ah_attr->static_rate = rec->rate; | 541 | ah_attr->static_rate = rec->rate; |
| 542 | 542 | ||
| 543 | force_grh = rdma_port_get_link_layer(device, port_num) == IB_LINK_LAYER_ETHERNET; | 543 | force_grh = rdma_cap_eth_ah(device, port_num); |
| 544 | 544 | ||
| 545 | if (rec->hop_limit > 1 || force_grh) { | 545 | if (rec->hop_limit > 1 || force_grh) { |
| 546 | ah_attr->ah_flags = IB_AH_GRH; | 546 | ah_attr->ah_flags = IB_AH_GRH; |
| @@ -583,7 +583,8 @@ static int alloc_mad(struct ib_sa_query *query, gfp_t gfp_mask) | |||
| 583 | query->mad_buf = ib_create_send_mad(query->port->agent, 1, | 583 | query->mad_buf = ib_create_send_mad(query->port->agent, 1, |
| 584 | query->sm_ah->pkey_index, | 584 | query->sm_ah->pkey_index, |
| 585 | 0, IB_MGMT_SA_HDR, IB_MGMT_SA_DATA, | 585 | 0, IB_MGMT_SA_HDR, IB_MGMT_SA_DATA, |
| 586 | gfp_mask); | 586 | gfp_mask, |
| 587 | IB_MGMT_BASE_VERSION); | ||
| 587 | if (IS_ERR(query->mad_buf)) { | 588 | if (IS_ERR(query->mad_buf)) { |
| 588 | kref_put(&query->sm_ah->ref, free_sm_ah); | 589 | kref_put(&query->sm_ah->ref, free_sm_ah); |
| 589 | return -ENOMEM; | 590 | return -ENOMEM; |
| @@ -1153,16 +1154,10 @@ static void ib_sa_add_one(struct ib_device *device) | |||
| 1153 | { | 1154 | { |
| 1154 | struct ib_sa_device *sa_dev; | 1155 | struct ib_sa_device *sa_dev; |
| 1155 | int s, e, i; | 1156 | int s, e, i; |
| 1157 | int count = 0; | ||
| 1156 | 1158 | ||
| 1157 | if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) | 1159 | s = rdma_start_port(device); |
| 1158 | return; | 1160 | e = rdma_end_port(device); |
| 1159 | |||
| 1160 | if (device->node_type == RDMA_NODE_IB_SWITCH) | ||
| 1161 | s = e = 0; | ||
| 1162 | else { | ||
| 1163 | s = 1; | ||
| 1164 | e = device->phys_port_cnt; | ||
| 1165 | } | ||
| 1166 | 1161 | ||
| 1167 | sa_dev = kzalloc(sizeof *sa_dev + | 1162 | sa_dev = kzalloc(sizeof *sa_dev + |
| 1168 | (e - s + 1) * sizeof (struct ib_sa_port), | 1163 | (e - s + 1) * sizeof (struct ib_sa_port), |
| @@ -1175,7 +1170,7 @@ static void ib_sa_add_one(struct ib_device *device) | |||
| 1175 | 1170 | ||
| 1176 | for (i = 0; i <= e - s; ++i) { | 1171 | for (i = 0; i <= e - s; ++i) { |
| 1177 | spin_lock_init(&sa_dev->port[i].ah_lock); | 1172 | spin_lock_init(&sa_dev->port[i].ah_lock); |
| 1178 | if (rdma_port_get_link_layer(device, i + 1) != IB_LINK_LAYER_INFINIBAND) | 1173 | if (!rdma_cap_ib_sa(device, i + 1)) |
| 1179 | continue; | 1174 | continue; |
| 1180 | 1175 | ||
| 1181 | sa_dev->port[i].sm_ah = NULL; | 1176 | sa_dev->port[i].sm_ah = NULL; |
| @@ -1189,8 +1184,13 @@ static void ib_sa_add_one(struct ib_device *device) | |||
| 1189 | goto err; | 1184 | goto err; |
| 1190 | 1185 | ||
| 1191 | INIT_WORK(&sa_dev->port[i].update_task, update_sm_ah); | 1186 | INIT_WORK(&sa_dev->port[i].update_task, update_sm_ah); |
| 1187 | |||
| 1188 | count++; | ||
| 1192 | } | 1189 | } |
| 1193 | 1190 | ||
| 1191 | if (!count) | ||
| 1192 | goto free; | ||
| 1193 | |||
| 1194 | ib_set_client_data(device, &sa_client, sa_dev); | 1194 | ib_set_client_data(device, &sa_client, sa_dev); |
| 1195 | 1195 | ||
| 1196 | /* | 1196 | /* |
| @@ -1204,19 +1204,20 @@ static void ib_sa_add_one(struct ib_device *device) | |||
| 1204 | if (ib_register_event_handler(&sa_dev->event_handler)) | 1204 | if (ib_register_event_handler(&sa_dev->event_handler)) |
| 1205 | goto err; | 1205 | goto err; |
| 1206 | 1206 | ||
| 1207 | for (i = 0; i <= e - s; ++i) | 1207 | for (i = 0; i <= e - s; ++i) { |
| 1208 | if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND) | 1208 | if (rdma_cap_ib_sa(device, i + 1)) |
| 1209 | update_sm_ah(&sa_dev->port[i].update_task); | 1209 | update_sm_ah(&sa_dev->port[i].update_task); |
| 1210 | } | ||
| 1210 | 1211 | ||
| 1211 | return; | 1212 | return; |
| 1212 | 1213 | ||
| 1213 | err: | 1214 | err: |
| 1214 | while (--i >= 0) | 1215 | while (--i >= 0) { |
| 1215 | if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND) | 1216 | if (rdma_cap_ib_sa(device, i + 1)) |
| 1216 | ib_unregister_mad_agent(sa_dev->port[i].agent); | 1217 | ib_unregister_mad_agent(sa_dev->port[i].agent); |
| 1217 | 1218 | } | |
| 1219 | free: | ||
| 1218 | kfree(sa_dev); | 1220 | kfree(sa_dev); |
| 1219 | |||
| 1220 | return; | 1221 | return; |
| 1221 | } | 1222 | } |
| 1222 | 1223 | ||
| @@ -1233,7 +1234,7 @@ static void ib_sa_remove_one(struct ib_device *device) | |||
| 1233 | flush_workqueue(ib_wq); | 1234 | flush_workqueue(ib_wq); |
| 1234 | 1235 | ||
| 1235 | for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) { | 1236 | for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) { |
| 1236 | if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND) { | 1237 | if (rdma_cap_ib_sa(device, i + 1)) { |
| 1237 | ib_unregister_mad_agent(sa_dev->port[i].agent); | 1238 | ib_unregister_mad_agent(sa_dev->port[i].agent); |
| 1238 | if (sa_dev->port[i].sm_ah) | 1239 | if (sa_dev->port[i].sm_ah) |
| 1239 | kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah); | 1240 | kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah); |
diff --git a/drivers/infiniband/core/smi.c b/drivers/infiniband/core/smi.c index 5855e4405d9b..f19b23817c2b 100644 --- a/drivers/infiniband/core/smi.c +++ b/drivers/infiniband/core/smi.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved. | 5 | * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved. |
| 6 | * Copyright (c) 2004-2007 Voltaire Corporation. All rights reserved. | 6 | * Copyright (c) 2004-2007 Voltaire Corporation. All rights reserved. |
| 7 | * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. | 7 | * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. |
| 8 | * Copyright (c) 2014 Intel Corporation. All rights reserved. | ||
| 8 | * | 9 | * |
| 9 | * This software is available to you under a choice of one of two | 10 | * This software is available to you under a choice of one of two |
| 10 | * licenses. You may choose to be licensed under the terms of the GNU | 11 | * licenses. You may choose to be licensed under the terms of the GNU |
| @@ -38,85 +39,82 @@ | |||
| 38 | 39 | ||
| 39 | #include <rdma/ib_smi.h> | 40 | #include <rdma/ib_smi.h> |
| 40 | #include "smi.h" | 41 | #include "smi.h" |
| 41 | 42 | #include "opa_smi.h" | |
| 42 | /* | 43 | |
| 43 | * Fixup a directed route SMP for sending | 44 | static enum smi_action __smi_handle_dr_smp_send(bool is_switch, int port_num, |
| 44 | * Return 0 if the SMP should be discarded | 45 | u8 *hop_ptr, u8 hop_cnt, |
| 45 | */ | 46 | const u8 *initial_path, |
| 46 | enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp, | 47 | const u8 *return_path, |
| 47 | u8 node_type, int port_num) | 48 | u8 direction, |
| 49 | bool dr_dlid_is_permissive, | ||
| 50 | bool dr_slid_is_permissive) | ||
| 48 | { | 51 | { |
| 49 | u8 hop_ptr, hop_cnt; | ||
| 50 | |||
| 51 | hop_ptr = smp->hop_ptr; | ||
| 52 | hop_cnt = smp->hop_cnt; | ||
| 53 | |||
| 54 | /* See section 14.2.2.2, Vol 1 IB spec */ | 52 | /* See section 14.2.2.2, Vol 1 IB spec */ |
| 55 | /* C14-6 -- valid hop_cnt values are from 0 to 63 */ | 53 | /* C14-6 -- valid hop_cnt values are from 0 to 63 */ |
| 56 | if (hop_cnt >= IB_SMP_MAX_PATH_HOPS) | 54 | if (hop_cnt >= IB_SMP_MAX_PATH_HOPS) |
| 57 | return IB_SMI_DISCARD; | 55 | return IB_SMI_DISCARD; |
| 58 | 56 | ||
| 59 | if (!ib_get_smp_direction(smp)) { | 57 | if (!direction) { |
| 60 | /* C14-9:1 */ | 58 | /* C14-9:1 */ |
| 61 | if (hop_cnt && hop_ptr == 0) { | 59 | if (hop_cnt && *hop_ptr == 0) { |
| 62 | smp->hop_ptr++; | 60 | (*hop_ptr)++; |
| 63 | return (smp->initial_path[smp->hop_ptr] == | 61 | return (initial_path[*hop_ptr] == |
| 64 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); | 62 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
| 65 | } | 63 | } |
| 66 | 64 | ||
| 67 | /* C14-9:2 */ | 65 | /* C14-9:2 */ |
| 68 | if (hop_ptr && hop_ptr < hop_cnt) { | 66 | if (*hop_ptr && *hop_ptr < hop_cnt) { |
| 69 | if (node_type != RDMA_NODE_IB_SWITCH) | 67 | if (!is_switch) |
| 70 | return IB_SMI_DISCARD; | 68 | return IB_SMI_DISCARD; |
| 71 | 69 | ||
| 72 | /* smp->return_path set when received */ | 70 | /* return_path set when received */ |
| 73 | smp->hop_ptr++; | 71 | (*hop_ptr)++; |
| 74 | return (smp->initial_path[smp->hop_ptr] == | 72 | return (initial_path[*hop_ptr] == |
| 75 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); | 73 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
| 76 | } | 74 | } |
| 77 | 75 | ||
| 78 | /* C14-9:3 -- We're at the end of the DR segment of path */ | 76 | /* C14-9:3 -- We're at the end of the DR segment of path */ |
| 79 | if (hop_ptr == hop_cnt) { | 77 | if (*hop_ptr == hop_cnt) { |
| 80 | /* smp->return_path set when received */ | 78 | /* return_path set when received */ |
| 81 | smp->hop_ptr++; | 79 | (*hop_ptr)++; |
| 82 | return (node_type == RDMA_NODE_IB_SWITCH || | 80 | return (is_switch || |
| 83 | smp->dr_dlid == IB_LID_PERMISSIVE ? | 81 | dr_dlid_is_permissive ? |
| 84 | IB_SMI_HANDLE : IB_SMI_DISCARD); | 82 | IB_SMI_HANDLE : IB_SMI_DISCARD); |
| 85 | } | 83 | } |
| 86 | 84 | ||
| 87 | /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ | 85 | /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ |
| 88 | /* C14-9:5 -- Fail unreasonable hop pointer */ | 86 | /* C14-9:5 -- Fail unreasonable hop pointer */ |
| 89 | return (hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD); | 87 | return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
| 90 | 88 | ||
| 91 | } else { | 89 | } else { |
| 92 | /* C14-13:1 */ | 90 | /* C14-13:1 */ |
| 93 | if (hop_cnt && hop_ptr == hop_cnt + 1) { | 91 | if (hop_cnt && *hop_ptr == hop_cnt + 1) { |
| 94 | smp->hop_ptr--; | 92 | (*hop_ptr)--; |
| 95 | return (smp->return_path[smp->hop_ptr] == | 93 | return (return_path[*hop_ptr] == |
| 96 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); | 94 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
| 97 | } | 95 | } |
| 98 | 96 | ||
| 99 | /* C14-13:2 */ | 97 | /* C14-13:2 */ |
| 100 | if (2 <= hop_ptr && hop_ptr <= hop_cnt) { | 98 | if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) { |
| 101 | if (node_type != RDMA_NODE_IB_SWITCH) | 99 | if (!is_switch) |
| 102 | return IB_SMI_DISCARD; | 100 | return IB_SMI_DISCARD; |
| 103 | 101 | ||
| 104 | smp->hop_ptr--; | 102 | (*hop_ptr)--; |
| 105 | return (smp->return_path[smp->hop_ptr] == | 103 | return (return_path[*hop_ptr] == |
| 106 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); | 104 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
| 107 | } | 105 | } |
| 108 | 106 | ||
| 109 | /* C14-13:3 -- at the end of the DR segment of path */ | 107 | /* C14-13:3 -- at the end of the DR segment of path */ |
| 110 | if (hop_ptr == 1) { | 108 | if (*hop_ptr == 1) { |
| 111 | smp->hop_ptr--; | 109 | (*hop_ptr)--; |
| 112 | /* C14-13:3 -- SMPs destined for SM shouldn't be here */ | 110 | /* C14-13:3 -- SMPs destined for SM shouldn't be here */ |
| 113 | return (node_type == RDMA_NODE_IB_SWITCH || | 111 | return (is_switch || |
| 114 | smp->dr_slid == IB_LID_PERMISSIVE ? | 112 | dr_slid_is_permissive ? |
| 115 | IB_SMI_HANDLE : IB_SMI_DISCARD); | 113 | IB_SMI_HANDLE : IB_SMI_DISCARD); |
| 116 | } | 114 | } |
| 117 | 115 | ||
| 118 | /* C14-13:4 -- hop_ptr = 0 -> should have gone to SM */ | 116 | /* C14-13:4 -- hop_ptr = 0 -> should have gone to SM */ |
| 119 | if (hop_ptr == 0) | 117 | if (*hop_ptr == 0) |
| 120 | return IB_SMI_HANDLE; | 118 | return IB_SMI_HANDLE; |
| 121 | 119 | ||
| 122 | /* C14-13:5 -- Check for unreasonable hop pointer */ | 120 | /* C14-13:5 -- Check for unreasonable hop pointer */ |
| @@ -125,105 +123,163 @@ enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp, | |||
| 125 | } | 123 | } |
| 126 | 124 | ||
| 127 | /* | 125 | /* |
| 128 | * Adjust information for a received SMP | 126 | * Fixup a directed route SMP for sending |
| 129 | * Return 0 if the SMP should be dropped | 127 | * Return IB_SMI_DISCARD if the SMP should be discarded |
| 130 | */ | 128 | */ |
| 131 | enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type, | 129 | enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp, |
| 132 | int port_num, int phys_port_cnt) | 130 | bool is_switch, int port_num) |
| 133 | { | 131 | { |
| 134 | u8 hop_ptr, hop_cnt; | 132 | return __smi_handle_dr_smp_send(is_switch, port_num, |
| 133 | &smp->hop_ptr, smp->hop_cnt, | ||
| 134 | smp->initial_path, | ||
| 135 | smp->return_path, | ||
| 136 | ib_get_smp_direction(smp), | ||
| 137 | smp->dr_dlid == IB_LID_PERMISSIVE, | ||
| 138 | smp->dr_slid == IB_LID_PERMISSIVE); | ||
| 139 | } | ||
| 135 | 140 | ||
| 136 | hop_ptr = smp->hop_ptr; | 141 | enum smi_action opa_smi_handle_dr_smp_send(struct opa_smp *smp, |
| 137 | hop_cnt = smp->hop_cnt; | 142 | bool is_switch, int port_num) |
| 143 | { | ||
| 144 | return __smi_handle_dr_smp_send(is_switch, port_num, | ||
| 145 | &smp->hop_ptr, smp->hop_cnt, | ||
| 146 | smp->route.dr.initial_path, | ||
| 147 | smp->route.dr.return_path, | ||
| 148 | opa_get_smp_direction(smp), | ||
| 149 | smp->route.dr.dr_dlid == | ||
| 150 | OPA_LID_PERMISSIVE, | ||
| 151 | smp->route.dr.dr_slid == | ||
| 152 | OPA_LID_PERMISSIVE); | ||
| 153 | } | ||
| 138 | 154 | ||
| 155 | static enum smi_action __smi_handle_dr_smp_recv(bool is_switch, int port_num, | ||
| 156 | int phys_port_cnt, | ||
| 157 | u8 *hop_ptr, u8 hop_cnt, | ||
| 158 | const u8 *initial_path, | ||
| 159 | u8 *return_path, | ||
| 160 | u8 direction, | ||
| 161 | bool dr_dlid_is_permissive, | ||
| 162 | bool dr_slid_is_permissive) | ||
| 163 | { | ||
| 139 | /* See section 14.2.2.2, Vol 1 IB spec */ | 164 | /* See section 14.2.2.2, Vol 1 IB spec */ |
| 140 | /* C14-6 -- valid hop_cnt values are from 0 to 63 */ | 165 | /* C14-6 -- valid hop_cnt values are from 0 to 63 */ |
| 141 | if (hop_cnt >= IB_SMP_MAX_PATH_HOPS) | 166 | if (hop_cnt >= IB_SMP_MAX_PATH_HOPS) |
| 142 | return IB_SMI_DISCARD; | 167 | return IB_SMI_DISCARD; |
| 143 | 168 | ||
| 144 | if (!ib_get_smp_direction(smp)) { | 169 | if (!direction) { |
| 145 | /* C14-9:1 -- sender should have incremented hop_ptr */ | 170 | /* C14-9:1 -- sender should have incremented hop_ptr */ |
| 146 | if (hop_cnt && hop_ptr == 0) | 171 | if (hop_cnt && *hop_ptr == 0) |
| 147 | return IB_SMI_DISCARD; | 172 | return IB_SMI_DISCARD; |
| 148 | 173 | ||
| 149 | /* C14-9:2 -- intermediate hop */ | 174 | /* C14-9:2 -- intermediate hop */ |
| 150 | if (hop_ptr && hop_ptr < hop_cnt) { | 175 | if (*hop_ptr && *hop_ptr < hop_cnt) { |
| 151 | if (node_type != RDMA_NODE_IB_SWITCH) | 176 | if (!is_switch) |
| 152 | return IB_SMI_DISCARD; | 177 | return IB_SMI_DISCARD; |
| 153 | 178 | ||
| 154 | smp->return_path[hop_ptr] = port_num; | 179 | return_path[*hop_ptr] = port_num; |
| 155 | /* smp->hop_ptr updated when sending */ | 180 | /* hop_ptr updated when sending */ |
| 156 | return (smp->initial_path[hop_ptr+1] <= phys_port_cnt ? | 181 | return (initial_path[*hop_ptr+1] <= phys_port_cnt ? |
| 157 | IB_SMI_HANDLE : IB_SMI_DISCARD); | 182 | IB_SMI_HANDLE : IB_SMI_DISCARD); |
| 158 | } | 183 | } |
| 159 | 184 | ||
| 160 | /* C14-9:3 -- We're at the end of the DR segment of path */ | 185 | /* C14-9:3 -- We're at the end of the DR segment of path */ |
| 161 | if (hop_ptr == hop_cnt) { | 186 | if (*hop_ptr == hop_cnt) { |
| 162 | if (hop_cnt) | 187 | if (hop_cnt) |
| 163 | smp->return_path[hop_ptr] = port_num; | 188 | return_path[*hop_ptr] = port_num; |
| 164 | /* smp->hop_ptr updated when sending */ | 189 | /* hop_ptr updated when sending */ |
| 165 | 190 | ||
| 166 | return (node_type == RDMA_NODE_IB_SWITCH || | 191 | return (is_switch || |
| 167 | smp->dr_dlid == IB_LID_PERMISSIVE ? | 192 | dr_dlid_is_permissive ? |
| 168 | IB_SMI_HANDLE : IB_SMI_DISCARD); | 193 | IB_SMI_HANDLE : IB_SMI_DISCARD); |
| 169 | } | 194 | } |
| 170 | 195 | ||
| 171 | /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ | 196 | /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ |
| 172 | /* C14-9:5 -- fail unreasonable hop pointer */ | 197 | /* C14-9:5 -- fail unreasonable hop pointer */ |
| 173 | return (hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD); | 198 | return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
| 174 | 199 | ||
| 175 | } else { | 200 | } else { |
| 176 | 201 | ||
| 177 | /* C14-13:1 */ | 202 | /* C14-13:1 */ |
| 178 | if (hop_cnt && hop_ptr == hop_cnt + 1) { | 203 | if (hop_cnt && *hop_ptr == hop_cnt + 1) { |
| 179 | smp->hop_ptr--; | 204 | (*hop_ptr)--; |
| 180 | return (smp->return_path[smp->hop_ptr] == | 205 | return (return_path[*hop_ptr] == |
| 181 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); | 206 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
| 182 | } | 207 | } |
| 183 | 208 | ||
| 184 | /* C14-13:2 */ | 209 | /* C14-13:2 */ |
| 185 | if (2 <= hop_ptr && hop_ptr <= hop_cnt) { | 210 | if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) { |
| 186 | if (node_type != RDMA_NODE_IB_SWITCH) | 211 | if (!is_switch) |
| 187 | return IB_SMI_DISCARD; | 212 | return IB_SMI_DISCARD; |
| 188 | 213 | ||
| 189 | /* smp->hop_ptr updated when sending */ | 214 | /* hop_ptr updated when sending */ |
| 190 | return (smp->return_path[hop_ptr-1] <= phys_port_cnt ? | 215 | return (return_path[*hop_ptr-1] <= phys_port_cnt ? |
| 191 | IB_SMI_HANDLE : IB_SMI_DISCARD); | 216 | IB_SMI_HANDLE : IB_SMI_DISCARD); |
| 192 | } | 217 | } |
| 193 | 218 | ||
| 194 | /* C14-13:3 -- We're at the end of the DR segment of path */ | 219 | /* C14-13:3 -- We're at the end of the DR segment of path */ |
| 195 | if (hop_ptr == 1) { | 220 | if (*hop_ptr == 1) { |
| 196 | if (smp->dr_slid == IB_LID_PERMISSIVE) { | 221 | if (dr_slid_is_permissive) { |
| 197 | /* giving SMP to SM - update hop_ptr */ | 222 | /* giving SMP to SM - update hop_ptr */ |
| 198 | smp->hop_ptr--; | 223 | (*hop_ptr)--; |
| 199 | return IB_SMI_HANDLE; | 224 | return IB_SMI_HANDLE; |
| 200 | } | 225 | } |
| 201 | /* smp->hop_ptr updated when sending */ | 226 | /* hop_ptr updated when sending */ |
| 202 | return (node_type == RDMA_NODE_IB_SWITCH ? | 227 | return (is_switch ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
| 203 | IB_SMI_HANDLE : IB_SMI_DISCARD); | ||
| 204 | } | 228 | } |
| 205 | 229 | ||
| 206 | /* C14-13:4 -- hop_ptr = 0 -> give to SM */ | 230 | /* C14-13:4 -- hop_ptr = 0 -> give to SM */ |
| 207 | /* C14-13:5 -- Check for unreasonable hop pointer */ | 231 | /* C14-13:5 -- Check for unreasonable hop pointer */ |
| 208 | return (hop_ptr == 0 ? IB_SMI_HANDLE : IB_SMI_DISCARD); | 232 | return (*hop_ptr == 0 ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
| 209 | } | 233 | } |
| 210 | } | 234 | } |
| 211 | 235 | ||
| 212 | enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp) | 236 | /* |
| 237 | * Adjust information for a received SMP | ||
| 238 | * Return IB_SMI_DISCARD if the SMP should be dropped | ||
| 239 | */ | ||
| 240 | enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, bool is_switch, | ||
| 241 | int port_num, int phys_port_cnt) | ||
| 213 | { | 242 | { |
| 214 | u8 hop_ptr, hop_cnt; | 243 | return __smi_handle_dr_smp_recv(is_switch, port_num, phys_port_cnt, |
| 244 | &smp->hop_ptr, smp->hop_cnt, | ||
| 245 | smp->initial_path, | ||
| 246 | smp->return_path, | ||
| 247 | ib_get_smp_direction(smp), | ||
| 248 | smp->dr_dlid == IB_LID_PERMISSIVE, | ||
| 249 | smp->dr_slid == IB_LID_PERMISSIVE); | ||
| 250 | } | ||
| 215 | 251 | ||
| 216 | hop_ptr = smp->hop_ptr; | 252 | /* |
| 217 | hop_cnt = smp->hop_cnt; | 253 | * Adjust information for a received SMP |
| 254 | * Return IB_SMI_DISCARD if the SMP should be dropped | ||
| 255 | */ | ||
| 256 | enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, bool is_switch, | ||
| 257 | int port_num, int phys_port_cnt) | ||
| 258 | { | ||
| 259 | return __smi_handle_dr_smp_recv(is_switch, port_num, phys_port_cnt, | ||
| 260 | &smp->hop_ptr, smp->hop_cnt, | ||
| 261 | smp->route.dr.initial_path, | ||
| 262 | smp->route.dr.return_path, | ||
| 263 | opa_get_smp_direction(smp), | ||
| 264 | smp->route.dr.dr_dlid == | ||
| 265 | OPA_LID_PERMISSIVE, | ||
| 266 | smp->route.dr.dr_slid == | ||
| 267 | OPA_LID_PERMISSIVE); | ||
| 268 | } | ||
| 218 | 269 | ||
| 219 | if (!ib_get_smp_direction(smp)) { | 270 | static enum smi_forward_action __smi_check_forward_dr_smp(u8 hop_ptr, u8 hop_cnt, |
| 271 | u8 direction, | ||
| 272 | bool dr_dlid_is_permissive, | ||
| 273 | bool dr_slid_is_permissive) | ||
| 274 | { | ||
| 275 | if (!direction) { | ||
| 220 | /* C14-9:2 -- intermediate hop */ | 276 | /* C14-9:2 -- intermediate hop */ |
| 221 | if (hop_ptr && hop_ptr < hop_cnt) | 277 | if (hop_ptr && hop_ptr < hop_cnt) |
| 222 | return IB_SMI_FORWARD; | 278 | return IB_SMI_FORWARD; |
| 223 | 279 | ||
| 224 | /* C14-9:3 -- at the end of the DR segment of path */ | 280 | /* C14-9:3 -- at the end of the DR segment of path */ |
| 225 | if (hop_ptr == hop_cnt) | 281 | if (hop_ptr == hop_cnt) |
| 226 | return (smp->dr_dlid == IB_LID_PERMISSIVE ? | 282 | return (dr_dlid_is_permissive ? |
| 227 | IB_SMI_SEND : IB_SMI_LOCAL); | 283 | IB_SMI_SEND : IB_SMI_LOCAL); |
| 228 | 284 | ||
| 229 | /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ | 285 | /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ |
| @@ -236,10 +292,29 @@ enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp) | |||
| 236 | 292 | ||
| 237 | /* C14-13:3 -- at the end of the DR segment of path */ | 293 | /* C14-13:3 -- at the end of the DR segment of path */ |
| 238 | if (hop_ptr == 1) | 294 | if (hop_ptr == 1) |
| 239 | return (smp->dr_slid != IB_LID_PERMISSIVE ? | 295 | return (!dr_slid_is_permissive ? |
| 240 | IB_SMI_SEND : IB_SMI_LOCAL); | 296 | IB_SMI_SEND : IB_SMI_LOCAL); |
| 241 | } | 297 | } |
| 242 | return IB_SMI_LOCAL; | 298 | return IB_SMI_LOCAL; |
| 299 | |||
| 300 | } | ||
| 301 | |||
| 302 | enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp) | ||
| 303 | { | ||
| 304 | return __smi_check_forward_dr_smp(smp->hop_ptr, smp->hop_cnt, | ||
| 305 | ib_get_smp_direction(smp), | ||
| 306 | smp->dr_dlid == IB_LID_PERMISSIVE, | ||
| 307 | smp->dr_slid == IB_LID_PERMISSIVE); | ||
| 308 | } | ||
| 309 | |||
| 310 | enum smi_forward_action opa_smi_check_forward_dr_smp(struct opa_smp *smp) | ||
| 311 | { | ||
| 312 | return __smi_check_forward_dr_smp(smp->hop_ptr, smp->hop_cnt, | ||
| 313 | opa_get_smp_direction(smp), | ||
| 314 | smp->route.dr.dr_dlid == | ||
| 315 | OPA_LID_PERMISSIVE, | ||
| 316 | smp->route.dr.dr_slid == | ||
| 317 | OPA_LID_PERMISSIVE); | ||
| 243 | } | 318 | } |
| 244 | 319 | ||
| 245 | /* | 320 | /* |
| @@ -251,3 +326,13 @@ int smi_get_fwd_port(struct ib_smp *smp) | |||
| 251 | return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] : | 326 | return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] : |
| 252 | smp->return_path[smp->hop_ptr-1]); | 327 | smp->return_path[smp->hop_ptr-1]); |
| 253 | } | 328 | } |
| 329 | |||
| 330 | /* | ||
| 331 | * Return the forwarding port number from initial_path for outgoing SMP and | ||
| 332 | * from return_path for returning SMP | ||
| 333 | */ | ||
| 334 | int opa_smi_get_fwd_port(struct opa_smp *smp) | ||
| 335 | { | ||
| 336 | return !opa_get_smp_direction(smp) ? smp->route.dr.initial_path[smp->hop_ptr+1] : | ||
| 337 | smp->route.dr.return_path[smp->hop_ptr-1]; | ||
| 338 | } | ||
diff --git a/drivers/infiniband/core/smi.h b/drivers/infiniband/core/smi.h index aff96bac49b4..33c91c8a16e9 100644 --- a/drivers/infiniband/core/smi.h +++ b/drivers/infiniband/core/smi.h | |||
| @@ -51,12 +51,12 @@ enum smi_forward_action { | |||
| 51 | IB_SMI_FORWARD /* SMP should be forwarded (for switches only) */ | 51 | IB_SMI_FORWARD /* SMP should be forwarded (for switches only) */ |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type, | 54 | enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, bool is_switch, |
| 55 | int port_num, int phys_port_cnt); | 55 | int port_num, int phys_port_cnt); |
| 56 | int smi_get_fwd_port(struct ib_smp *smp); | 56 | int smi_get_fwd_port(struct ib_smp *smp); |
| 57 | extern enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp); | 57 | extern enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp); |
| 58 | extern enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp, | 58 | extern enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp, |
| 59 | u8 node_type, int port_num); | 59 | bool is_switch, int port_num); |
| 60 | 60 | ||
| 61 | /* | 61 | /* |
| 62 | * Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM | 62 | * Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM |
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index cbd0383f622e..0b84a9cdfe5b 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c | |||
| @@ -326,6 +326,8 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr, | |||
| 326 | int width = (tab_attr->index >> 16) & 0xff; | 326 | int width = (tab_attr->index >> 16) & 0xff; |
| 327 | struct ib_mad *in_mad = NULL; | 327 | struct ib_mad *in_mad = NULL; |
| 328 | struct ib_mad *out_mad = NULL; | 328 | struct ib_mad *out_mad = NULL; |
| 329 | size_t mad_size = sizeof(*out_mad); | ||
| 330 | u16 out_mad_pkey_index = 0; | ||
| 329 | ssize_t ret; | 331 | ssize_t ret; |
| 330 | 332 | ||
| 331 | if (!p->ibdev->process_mad) | 333 | if (!p->ibdev->process_mad) |
| @@ -347,7 +349,10 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr, | |||
| 347 | in_mad->data[41] = p->port_num; /* PortSelect field */ | 349 | in_mad->data[41] = p->port_num; /* PortSelect field */ |
| 348 | 350 | ||
| 349 | if ((p->ibdev->process_mad(p->ibdev, IB_MAD_IGNORE_MKEY, | 351 | if ((p->ibdev->process_mad(p->ibdev, IB_MAD_IGNORE_MKEY, |
| 350 | p->port_num, NULL, NULL, in_mad, out_mad) & | 352 | p->port_num, NULL, NULL, |
| 353 | (const struct ib_mad_hdr *)in_mad, mad_size, | ||
| 354 | (struct ib_mad_hdr *)out_mad, &mad_size, | ||
| 355 | &out_mad_pkey_index) & | ||
| 351 | (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) != | 356 | (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) != |
| 352 | (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) { | 357 | (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) { |
| 353 | ret = -EINVAL; | 358 | ret = -EINVAL; |
| @@ -456,6 +461,7 @@ static void ib_device_release(struct device *device) | |||
| 456 | { | 461 | { |
| 457 | struct ib_device *dev = container_of(device, struct ib_device, dev); | 462 | struct ib_device *dev = container_of(device, struct ib_device, dev); |
| 458 | 463 | ||
| 464 | kfree(dev->port_immutable); | ||
| 459 | kfree(dev); | 465 | kfree(dev); |
| 460 | } | 466 | } |
| 461 | 467 | ||
| @@ -864,7 +870,7 @@ int ib_device_register_sysfs(struct ib_device *device, | |||
| 864 | goto err_put; | 870 | goto err_put; |
| 865 | } | 871 | } |
| 866 | 872 | ||
| 867 | if (device->node_type == RDMA_NODE_IB_SWITCH) { | 873 | if (rdma_cap_ib_switch(device)) { |
| 868 | ret = add_port(device, 0, port_callback); | 874 | ret = add_port(device, 0, port_callback); |
| 869 | if (ret) | 875 | if (ret) |
| 870 | goto err_put; | 876 | goto err_put; |
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index f2f63933e8a9..009481073644 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c | |||
| @@ -1193,6 +1193,7 @@ static int ib_ucm_close(struct inode *inode, struct file *filp) | |||
| 1193 | return 0; | 1193 | return 0; |
| 1194 | } | 1194 | } |
| 1195 | 1195 | ||
| 1196 | static DECLARE_BITMAP(overflow_map, IB_UCM_MAX_DEVICES); | ||
| 1196 | static void ib_ucm_release_dev(struct device *dev) | 1197 | static void ib_ucm_release_dev(struct device *dev) |
| 1197 | { | 1198 | { |
| 1198 | struct ib_ucm_device *ucm_dev; | 1199 | struct ib_ucm_device *ucm_dev; |
| @@ -1202,7 +1203,7 @@ static void ib_ucm_release_dev(struct device *dev) | |||
| 1202 | if (ucm_dev->devnum < IB_UCM_MAX_DEVICES) | 1203 | if (ucm_dev->devnum < IB_UCM_MAX_DEVICES) |
| 1203 | clear_bit(ucm_dev->devnum, dev_map); | 1204 | clear_bit(ucm_dev->devnum, dev_map); |
| 1204 | else | 1205 | else |
| 1205 | clear_bit(ucm_dev->devnum - IB_UCM_MAX_DEVICES, dev_map); | 1206 | clear_bit(ucm_dev->devnum - IB_UCM_MAX_DEVICES, overflow_map); |
| 1206 | kfree(ucm_dev); | 1207 | kfree(ucm_dev); |
| 1207 | } | 1208 | } |
| 1208 | 1209 | ||
| @@ -1226,7 +1227,6 @@ static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr, | |||
| 1226 | static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); | 1227 | static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); |
| 1227 | 1228 | ||
| 1228 | static dev_t overflow_maj; | 1229 | static dev_t overflow_maj; |
| 1229 | static DECLARE_BITMAP(overflow_map, IB_UCM_MAX_DEVICES); | ||
| 1230 | static int find_overflow_devnum(void) | 1230 | static int find_overflow_devnum(void) |
| 1231 | { | 1231 | { |
| 1232 | int ret; | 1232 | int ret; |
| @@ -1253,8 +1253,7 @@ static void ib_ucm_add_one(struct ib_device *device) | |||
| 1253 | dev_t base; | 1253 | dev_t base; |
| 1254 | struct ib_ucm_device *ucm_dev; | 1254 | struct ib_ucm_device *ucm_dev; |
| 1255 | 1255 | ||
| 1256 | if (!device->alloc_ucontext || | 1256 | if (!device->alloc_ucontext || !rdma_cap_ib_cm(device, 1)) |
| 1257 | rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) | ||
| 1258 | return; | 1257 | return; |
| 1259 | 1258 | ||
| 1260 | ucm_dev = kzalloc(sizeof *ucm_dev, GFP_KERNEL); | 1259 | ucm_dev = kzalloc(sizeof *ucm_dev, GFP_KERNEL); |
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 45d67e9228d7..29b21213ea75 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c | |||
| @@ -722,26 +722,13 @@ static ssize_t ucma_query_route(struct ucma_file *file, | |||
| 722 | 722 | ||
| 723 | resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid; | 723 | resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid; |
| 724 | resp.port_num = ctx->cm_id->port_num; | 724 | resp.port_num = ctx->cm_id->port_num; |
| 725 | switch (rdma_node_get_transport(ctx->cm_id->device->node_type)) { | 725 | |
| 726 | case RDMA_TRANSPORT_IB: | 726 | if (rdma_cap_ib_sa(ctx->cm_id->device, ctx->cm_id->port_num)) |
| 727 | switch (rdma_port_get_link_layer(ctx->cm_id->device, | 727 | ucma_copy_ib_route(&resp, &ctx->cm_id->route); |
| 728 | ctx->cm_id->port_num)) { | 728 | else if (rdma_protocol_roce(ctx->cm_id->device, ctx->cm_id->port_num)) |
| 729 | case IB_LINK_LAYER_INFINIBAND: | 729 | ucma_copy_iboe_route(&resp, &ctx->cm_id->route); |
| 730 | ucma_copy_ib_route(&resp, &ctx->cm_id->route); | 730 | else if (rdma_protocol_iwarp(ctx->cm_id->device, ctx->cm_id->port_num)) |
| 731 | break; | ||
| 732 | case IB_LINK_LAYER_ETHERNET: | ||
| 733 | ucma_copy_iboe_route(&resp, &ctx->cm_id->route); | ||
| 734 | break; | ||
| 735 | default: | ||
| 736 | break; | ||
| 737 | } | ||
| 738 | break; | ||
| 739 | case RDMA_TRANSPORT_IWARP: | ||
| 740 | ucma_copy_iw_route(&resp, &ctx->cm_id->route); | 731 | ucma_copy_iw_route(&resp, &ctx->cm_id->route); |
| 741 | break; | ||
| 742 | default: | ||
| 743 | break; | ||
| 744 | } | ||
| 745 | 732 | ||
| 746 | out: | 733 | out: |
| 747 | if (copy_to_user((void __user *)(unsigned long)cmd.response, | 734 | if (copy_to_user((void __user *)(unsigned long)cmd.response, |
| @@ -1367,10 +1354,10 @@ static void ucma_lock_files(struct ucma_file *file1, struct ucma_file *file2) | |||
| 1367 | /* Acquire mutex's based on pointer comparison to prevent deadlock. */ | 1354 | /* Acquire mutex's based on pointer comparison to prevent deadlock. */ |
| 1368 | if (file1 < file2) { | 1355 | if (file1 < file2) { |
| 1369 | mutex_lock(&file1->mut); | 1356 | mutex_lock(&file1->mut); |
| 1370 | mutex_lock(&file2->mut); | 1357 | mutex_lock_nested(&file2->mut, SINGLE_DEPTH_NESTING); |
| 1371 | } else { | 1358 | } else { |
| 1372 | mutex_lock(&file2->mut); | 1359 | mutex_lock(&file2->mut); |
| 1373 | mutex_lock(&file1->mut); | 1360 | mutex_lock_nested(&file1->mut, SINGLE_DEPTH_NESTING); |
| 1374 | } | 1361 | } |
| 1375 | } | 1362 | } |
| 1376 | 1363 | ||
| @@ -1629,6 +1616,7 @@ static void __exit ucma_cleanup(void) | |||
| 1629 | device_remove_file(ucma_misc.this_device, &dev_attr_abi_version); | 1616 | device_remove_file(ucma_misc.this_device, &dev_attr_abi_version); |
| 1630 | misc_deregister(&ucma_misc); | 1617 | misc_deregister(&ucma_misc); |
| 1631 | idr_destroy(&ctx_idr); | 1618 | idr_destroy(&ctx_idr); |
| 1619 | idr_destroy(&multicast_idr); | ||
| 1632 | } | 1620 | } |
| 1633 | 1621 | ||
| 1634 | module_init(ucma_init); | 1622 | module_init(ucma_init); |
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 928cdd20e2d1..35567fffaa4e 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c | |||
| @@ -99,7 +99,6 @@ struct ib_umad_port { | |||
| 99 | }; | 99 | }; |
| 100 | 100 | ||
| 101 | struct ib_umad_device { | 101 | struct ib_umad_device { |
| 102 | int start_port, end_port; | ||
| 103 | struct kobject kobj; | 102 | struct kobject kobj; |
| 104 | struct ib_umad_port port[0]; | 103 | struct ib_umad_port port[0]; |
| 105 | }; | 104 | }; |
| @@ -263,20 +262,23 @@ static ssize_t copy_recv_mad(struct ib_umad_file *file, char __user *buf, | |||
| 263 | { | 262 | { |
| 264 | struct ib_mad_recv_buf *recv_buf; | 263 | struct ib_mad_recv_buf *recv_buf; |
| 265 | int left, seg_payload, offset, max_seg_payload; | 264 | int left, seg_payload, offset, max_seg_payload; |
| 265 | size_t seg_size; | ||
| 266 | 266 | ||
| 267 | /* We need enough room to copy the first (or only) MAD segment. */ | ||
| 268 | recv_buf = &packet->recv_wc->recv_buf; | 267 | recv_buf = &packet->recv_wc->recv_buf; |
| 269 | if ((packet->length <= sizeof (*recv_buf->mad) && | 268 | seg_size = packet->recv_wc->mad_seg_size; |
| 269 | |||
| 270 | /* We need enough room to copy the first (or only) MAD segment. */ | ||
| 271 | if ((packet->length <= seg_size && | ||
| 270 | count < hdr_size(file) + packet->length) || | 272 | count < hdr_size(file) + packet->length) || |
| 271 | (packet->length > sizeof (*recv_buf->mad) && | 273 | (packet->length > seg_size && |
| 272 | count < hdr_size(file) + sizeof (*recv_buf->mad))) | 274 | count < hdr_size(file) + seg_size)) |
| 273 | return -EINVAL; | 275 | return -EINVAL; |
| 274 | 276 | ||
| 275 | if (copy_to_user(buf, &packet->mad, hdr_size(file))) | 277 | if (copy_to_user(buf, &packet->mad, hdr_size(file))) |
| 276 | return -EFAULT; | 278 | return -EFAULT; |
| 277 | 279 | ||
| 278 | buf += hdr_size(file); | 280 | buf += hdr_size(file); |
| 279 | seg_payload = min_t(int, packet->length, sizeof (*recv_buf->mad)); | 281 | seg_payload = min_t(int, packet->length, seg_size); |
| 280 | if (copy_to_user(buf, recv_buf->mad, seg_payload)) | 282 | if (copy_to_user(buf, recv_buf->mad, seg_payload)) |
| 281 | return -EFAULT; | 283 | return -EFAULT; |
| 282 | 284 | ||
| @@ -293,7 +295,7 @@ static ssize_t copy_recv_mad(struct ib_umad_file *file, char __user *buf, | |||
| 293 | return -ENOSPC; | 295 | return -ENOSPC; |
| 294 | } | 296 | } |
| 295 | offset = ib_get_mad_data_offset(recv_buf->mad->mad_hdr.mgmt_class); | 297 | offset = ib_get_mad_data_offset(recv_buf->mad->mad_hdr.mgmt_class); |
| 296 | max_seg_payload = sizeof (struct ib_mad) - offset; | 298 | max_seg_payload = seg_size - offset; |
| 297 | 299 | ||
| 298 | for (left = packet->length - seg_payload, buf += seg_payload; | 300 | for (left = packet->length - seg_payload, buf += seg_payload; |
| 299 | left; left -= seg_payload, buf += seg_payload) { | 301 | left; left -= seg_payload, buf += seg_payload) { |
| @@ -426,11 +428,11 @@ static int is_duplicate(struct ib_umad_file *file, | |||
| 426 | * the same TID, reject the second as a duplicate. This is more | 428 | * the same TID, reject the second as a duplicate. This is more |
| 427 | * restrictive than required by the spec. | 429 | * restrictive than required by the spec. |
| 428 | */ | 430 | */ |
| 429 | if (!ib_response_mad((struct ib_mad *) hdr)) { | 431 | if (!ib_response_mad(hdr)) { |
| 430 | if (!ib_response_mad((struct ib_mad *) sent_hdr)) | 432 | if (!ib_response_mad(sent_hdr)) |
| 431 | return 1; | 433 | return 1; |
| 432 | continue; | 434 | continue; |
| 433 | } else if (!ib_response_mad((struct ib_mad *) sent_hdr)) | 435 | } else if (!ib_response_mad(sent_hdr)) |
| 434 | continue; | 436 | continue; |
| 435 | 437 | ||
| 436 | if (same_destination(&packet->mad.hdr, &sent_packet->mad.hdr)) | 438 | if (same_destination(&packet->mad.hdr, &sent_packet->mad.hdr)) |
| @@ -451,6 +453,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, | |||
| 451 | struct ib_rmpp_mad *rmpp_mad; | 453 | struct ib_rmpp_mad *rmpp_mad; |
| 452 | __be64 *tid; | 454 | __be64 *tid; |
| 453 | int ret, data_len, hdr_len, copy_offset, rmpp_active; | 455 | int ret, data_len, hdr_len, copy_offset, rmpp_active; |
| 456 | u8 base_version; | ||
| 454 | 457 | ||
| 455 | if (count < hdr_size(file) + IB_MGMT_RMPP_HDR) | 458 | if (count < hdr_size(file) + IB_MGMT_RMPP_HDR) |
| 456 | return -EINVAL; | 459 | return -EINVAL; |
| @@ -517,11 +520,13 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, | |||
| 517 | rmpp_active = 0; | 520 | rmpp_active = 0; |
| 518 | } | 521 | } |
| 519 | 522 | ||
| 523 | base_version = ((struct ib_mad_hdr *)&packet->mad.data)->base_version; | ||
| 520 | data_len = count - hdr_size(file) - hdr_len; | 524 | data_len = count - hdr_size(file) - hdr_len; |
| 521 | packet->msg = ib_create_send_mad(agent, | 525 | packet->msg = ib_create_send_mad(agent, |
| 522 | be32_to_cpu(packet->mad.hdr.qpn), | 526 | be32_to_cpu(packet->mad.hdr.qpn), |
| 523 | packet->mad.hdr.pkey_index, rmpp_active, | 527 | packet->mad.hdr.pkey_index, rmpp_active, |
| 524 | hdr_len, data_len, GFP_KERNEL); | 528 | hdr_len, data_len, GFP_KERNEL, |
| 529 | base_version); | ||
| 525 | if (IS_ERR(packet->msg)) { | 530 | if (IS_ERR(packet->msg)) { |
| 526 | ret = PTR_ERR(packet->msg); | 531 | ret = PTR_ERR(packet->msg); |
| 527 | goto err_ah; | 532 | goto err_ah; |
| @@ -1273,16 +1278,10 @@ static void ib_umad_add_one(struct ib_device *device) | |||
| 1273 | { | 1278 | { |
| 1274 | struct ib_umad_device *umad_dev; | 1279 | struct ib_umad_device *umad_dev; |
| 1275 | int s, e, i; | 1280 | int s, e, i; |
| 1281 | int count = 0; | ||
| 1276 | 1282 | ||
| 1277 | if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) | 1283 | s = rdma_start_port(device); |
| 1278 | return; | 1284 | e = rdma_end_port(device); |
| 1279 | |||
| 1280 | if (device->node_type == RDMA_NODE_IB_SWITCH) | ||
| 1281 | s = e = 0; | ||
| 1282 | else { | ||
| 1283 | s = 1; | ||
| 1284 | e = device->phys_port_cnt; | ||
| 1285 | } | ||
| 1286 | 1285 | ||
| 1287 | umad_dev = kzalloc(sizeof *umad_dev + | 1286 | umad_dev = kzalloc(sizeof *umad_dev + |
| 1288 | (e - s + 1) * sizeof (struct ib_umad_port), | 1287 | (e - s + 1) * sizeof (struct ib_umad_port), |
| @@ -1292,25 +1291,34 @@ static void ib_umad_add_one(struct ib_device *device) | |||
| 1292 | 1291 | ||
| 1293 | kobject_init(&umad_dev->kobj, &ib_umad_dev_ktype); | 1292 | kobject_init(&umad_dev->kobj, &ib_umad_dev_ktype); |
| 1294 | 1293 | ||
| 1295 | umad_dev->start_port = s; | ||
| 1296 | umad_dev->end_port = e; | ||
| 1297 | |||
| 1298 | for (i = s; i <= e; ++i) { | 1294 | for (i = s; i <= e; ++i) { |
| 1295 | if (!rdma_cap_ib_mad(device, i)) | ||
| 1296 | continue; | ||
| 1297 | |||
| 1299 | umad_dev->port[i - s].umad_dev = umad_dev; | 1298 | umad_dev->port[i - s].umad_dev = umad_dev; |
| 1300 | 1299 | ||
| 1301 | if (ib_umad_init_port(device, i, umad_dev, | 1300 | if (ib_umad_init_port(device, i, umad_dev, |
| 1302 | &umad_dev->port[i - s])) | 1301 | &umad_dev->port[i - s])) |
| 1303 | goto err; | 1302 | goto err; |
| 1303 | |||
| 1304 | count++; | ||
| 1304 | } | 1305 | } |
| 1305 | 1306 | ||
| 1307 | if (!count) | ||
| 1308 | goto free; | ||
| 1309 | |||
| 1306 | ib_set_client_data(device, &umad_client, umad_dev); | 1310 | ib_set_client_data(device, &umad_client, umad_dev); |
| 1307 | 1311 | ||
| 1308 | return; | 1312 | return; |
| 1309 | 1313 | ||
| 1310 | err: | 1314 | err: |
| 1311 | while (--i >= s) | 1315 | while (--i >= s) { |
| 1312 | ib_umad_kill_port(&umad_dev->port[i - s]); | 1316 | if (!rdma_cap_ib_mad(device, i)) |
| 1317 | continue; | ||
| 1313 | 1318 | ||
| 1319 | ib_umad_kill_port(&umad_dev->port[i - s]); | ||
| 1320 | } | ||
| 1321 | free: | ||
| 1314 | kobject_put(&umad_dev->kobj); | 1322 | kobject_put(&umad_dev->kobj); |
| 1315 | } | 1323 | } |
| 1316 | 1324 | ||
| @@ -1322,8 +1330,10 @@ static void ib_umad_remove_one(struct ib_device *device) | |||
| 1322 | if (!umad_dev) | 1330 | if (!umad_dev) |
| 1323 | return; | 1331 | return; |
| 1324 | 1332 | ||
| 1325 | for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i) | 1333 | for (i = 0; i <= rdma_end_port(device) - rdma_start_port(device); ++i) { |
| 1326 | ib_umad_kill_port(&umad_dev->port[i]); | 1334 | if (rdma_cap_ib_mad(device, i + rdma_start_port(device))) |
| 1335 | ib_umad_kill_port(&umad_dev->port[i]); | ||
| 1336 | } | ||
| 1327 | 1337 | ||
| 1328 | kobject_put(&umad_dev->kobj); | 1338 | kobject_put(&umad_dev->kobj); |
| 1329 | } | 1339 | } |
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index b716b0815644..ba365b6d1e8d 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h | |||
| @@ -259,5 +259,6 @@ IB_UVERBS_DECLARE_CMD(close_xrcd); | |||
| 259 | IB_UVERBS_DECLARE_EX_CMD(create_flow); | 259 | IB_UVERBS_DECLARE_EX_CMD(create_flow); |
| 260 | IB_UVERBS_DECLARE_EX_CMD(destroy_flow); | 260 | IB_UVERBS_DECLARE_EX_CMD(destroy_flow); |
| 261 | IB_UVERBS_DECLARE_EX_CMD(query_device); | 261 | IB_UVERBS_DECLARE_EX_CMD(query_device); |
| 262 | IB_UVERBS_DECLARE_EX_CMD(create_cq); | ||
| 262 | 263 | ||
| 263 | #endif /* UVERBS_H */ | 264 | #endif /* UVERBS_H */ |
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index a9f048990dfc..bbb02ffe87df 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
| @@ -1330,40 +1330,37 @@ ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file, | |||
| 1330 | return in_len; | 1330 | return in_len; |
| 1331 | } | 1331 | } |
| 1332 | 1332 | ||
| 1333 | ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, | 1333 | static struct ib_ucq_object *create_cq(struct ib_uverbs_file *file, |
| 1334 | const char __user *buf, int in_len, | 1334 | struct ib_udata *ucore, |
| 1335 | int out_len) | 1335 | struct ib_udata *uhw, |
| 1336 | struct ib_uverbs_ex_create_cq *cmd, | ||
| 1337 | size_t cmd_sz, | ||
| 1338 | int (*cb)(struct ib_uverbs_file *file, | ||
| 1339 | struct ib_ucq_object *obj, | ||
| 1340 | struct ib_uverbs_ex_create_cq_resp *resp, | ||
| 1341 | struct ib_udata *udata, | ||
| 1342 | void *context), | ||
| 1343 | void *context) | ||
| 1336 | { | 1344 | { |
| 1337 | struct ib_uverbs_create_cq cmd; | ||
| 1338 | struct ib_uverbs_create_cq_resp resp; | ||
| 1339 | struct ib_udata udata; | ||
| 1340 | struct ib_ucq_object *obj; | 1345 | struct ib_ucq_object *obj; |
| 1341 | struct ib_uverbs_event_file *ev_file = NULL; | 1346 | struct ib_uverbs_event_file *ev_file = NULL; |
| 1342 | struct ib_cq *cq; | 1347 | struct ib_cq *cq; |
| 1343 | int ret; | 1348 | int ret; |
| 1349 | struct ib_uverbs_ex_create_cq_resp resp; | ||
| 1350 | struct ib_cq_init_attr attr = {}; | ||
| 1344 | 1351 | ||
| 1345 | if (out_len < sizeof resp) | 1352 | if (cmd->comp_vector >= file->device->num_comp_vectors) |
| 1346 | return -ENOSPC; | 1353 | return ERR_PTR(-EINVAL); |
| 1347 | |||
| 1348 | if (copy_from_user(&cmd, buf, sizeof cmd)) | ||
| 1349 | return -EFAULT; | ||
| 1350 | |||
| 1351 | INIT_UDATA(&udata, buf + sizeof cmd, | ||
| 1352 | (unsigned long) cmd.response + sizeof resp, | ||
| 1353 | in_len - sizeof cmd, out_len - sizeof resp); | ||
| 1354 | |||
| 1355 | if (cmd.comp_vector >= file->device->num_comp_vectors) | ||
| 1356 | return -EINVAL; | ||
| 1357 | 1354 | ||
| 1358 | obj = kmalloc(sizeof *obj, GFP_KERNEL); | 1355 | obj = kmalloc(sizeof *obj, GFP_KERNEL); |
| 1359 | if (!obj) | 1356 | if (!obj) |
| 1360 | return -ENOMEM; | 1357 | return ERR_PTR(-ENOMEM); |
| 1361 | 1358 | ||
| 1362 | init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &cq_lock_class); | 1359 | init_uobj(&obj->uobject, cmd->user_handle, file->ucontext, &cq_lock_class); |
| 1363 | down_write(&obj->uobject.mutex); | 1360 | down_write(&obj->uobject.mutex); |
| 1364 | 1361 | ||
| 1365 | if (cmd.comp_channel >= 0) { | 1362 | if (cmd->comp_channel >= 0) { |
| 1366 | ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel); | 1363 | ev_file = ib_uverbs_lookup_comp_file(cmd->comp_channel); |
| 1367 | if (!ev_file) { | 1364 | if (!ev_file) { |
| 1368 | ret = -EINVAL; | 1365 | ret = -EINVAL; |
| 1369 | goto err; | 1366 | goto err; |
| @@ -1376,9 +1373,14 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, | |||
| 1376 | INIT_LIST_HEAD(&obj->comp_list); | 1373 | INIT_LIST_HEAD(&obj->comp_list); |
| 1377 | INIT_LIST_HEAD(&obj->async_list); | 1374 | INIT_LIST_HEAD(&obj->async_list); |
| 1378 | 1375 | ||
| 1379 | cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe, | 1376 | attr.cqe = cmd->cqe; |
| 1380 | cmd.comp_vector, | 1377 | attr.comp_vector = cmd->comp_vector; |
| 1381 | file->ucontext, &udata); | 1378 | |
| 1379 | if (cmd_sz > offsetof(typeof(*cmd), flags) + sizeof(cmd->flags)) | ||
| 1380 | attr.flags = cmd->flags; | ||
| 1381 | |||
| 1382 | cq = file->device->ib_dev->create_cq(file->device->ib_dev, &attr, | ||
| 1383 | file->ucontext, uhw); | ||
| 1382 | if (IS_ERR(cq)) { | 1384 | if (IS_ERR(cq)) { |
| 1383 | ret = PTR_ERR(cq); | 1385 | ret = PTR_ERR(cq); |
| 1384 | goto err_file; | 1386 | goto err_file; |
| @@ -1397,14 +1399,15 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, | |||
| 1397 | goto err_free; | 1399 | goto err_free; |
| 1398 | 1400 | ||
| 1399 | memset(&resp, 0, sizeof resp); | 1401 | memset(&resp, 0, sizeof resp); |
| 1400 | resp.cq_handle = obj->uobject.id; | 1402 | resp.base.cq_handle = obj->uobject.id; |
| 1401 | resp.cqe = cq->cqe; | 1403 | resp.base.cqe = cq->cqe; |
| 1402 | 1404 | ||
| 1403 | if (copy_to_user((void __user *) (unsigned long) cmd.response, | 1405 | resp.response_length = offsetof(typeof(resp), response_length) + |
| 1404 | &resp, sizeof resp)) { | 1406 | sizeof(resp.response_length); |
| 1405 | ret = -EFAULT; | 1407 | |
| 1406 | goto err_copy; | 1408 | ret = cb(file, obj, &resp, ucore, context); |
| 1407 | } | 1409 | if (ret) |
| 1410 | goto err_cb; | ||
| 1408 | 1411 | ||
| 1409 | mutex_lock(&file->mutex); | 1412 | mutex_lock(&file->mutex); |
| 1410 | list_add_tail(&obj->uobject.list, &file->ucontext->cq_list); | 1413 | list_add_tail(&obj->uobject.list, &file->ucontext->cq_list); |
| @@ -1414,9 +1417,9 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, | |||
| 1414 | 1417 | ||
| 1415 | up_write(&obj->uobject.mutex); | 1418 | up_write(&obj->uobject.mutex); |
| 1416 | 1419 | ||
| 1417 | return in_len; | 1420 | return obj; |
| 1418 | 1421 | ||
| 1419 | err_copy: | 1422 | err_cb: |
| 1420 | idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject); | 1423 | idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject); |
| 1421 | 1424 | ||
| 1422 | err_free: | 1425 | err_free: |
| @@ -1428,7 +1431,106 @@ err_file: | |||
| 1428 | 1431 | ||
| 1429 | err: | 1432 | err: |
| 1430 | put_uobj_write(&obj->uobject); | 1433 | put_uobj_write(&obj->uobject); |
| 1431 | return ret; | 1434 | |
| 1435 | return ERR_PTR(ret); | ||
| 1436 | } | ||
| 1437 | |||
| 1438 | static int ib_uverbs_create_cq_cb(struct ib_uverbs_file *file, | ||
| 1439 | struct ib_ucq_object *obj, | ||
| 1440 | struct ib_uverbs_ex_create_cq_resp *resp, | ||
| 1441 | struct ib_udata *ucore, void *context) | ||
| 1442 | { | ||
| 1443 | if (ib_copy_to_udata(ucore, &resp->base, sizeof(resp->base))) | ||
| 1444 | return -EFAULT; | ||
| 1445 | |||
| 1446 | return 0; | ||
| 1447 | } | ||
| 1448 | |||
| 1449 | ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, | ||
| 1450 | const char __user *buf, int in_len, | ||
| 1451 | int out_len) | ||
| 1452 | { | ||
| 1453 | struct ib_uverbs_create_cq cmd; | ||
| 1454 | struct ib_uverbs_ex_create_cq cmd_ex; | ||
| 1455 | struct ib_uverbs_create_cq_resp resp; | ||
| 1456 | struct ib_udata ucore; | ||
| 1457 | struct ib_udata uhw; | ||
| 1458 | struct ib_ucq_object *obj; | ||
| 1459 | |||
| 1460 | if (out_len < sizeof(resp)) | ||
| 1461 | return -ENOSPC; | ||
| 1462 | |||
| 1463 | if (copy_from_user(&cmd, buf, sizeof(cmd))) | ||
| 1464 | return -EFAULT; | ||
| 1465 | |||
| 1466 | INIT_UDATA(&ucore, buf, cmd.response, sizeof(cmd), sizeof(resp)); | ||
| 1467 | |||
| 1468 | INIT_UDATA(&uhw, buf + sizeof(cmd), | ||
| 1469 | (unsigned long)cmd.response + sizeof(resp), | ||
| 1470 | in_len - sizeof(cmd), out_len - sizeof(resp)); | ||
| 1471 | |||
| 1472 | memset(&cmd_ex, 0, sizeof(cmd_ex)); | ||
| 1473 | cmd_ex.user_handle = cmd.user_handle; | ||
| 1474 | cmd_ex.cqe = cmd.cqe; | ||
| 1475 | cmd_ex.comp_vector = cmd.comp_vector; | ||
| 1476 | cmd_ex.comp_channel = cmd.comp_channel; | ||
| 1477 | |||
| 1478 | obj = create_cq(file, &ucore, &uhw, &cmd_ex, | ||
| 1479 | offsetof(typeof(cmd_ex), comp_channel) + | ||
| 1480 | sizeof(cmd.comp_channel), ib_uverbs_create_cq_cb, | ||
| 1481 | NULL); | ||
| 1482 | |||
| 1483 | if (IS_ERR(obj)) | ||
| 1484 | return PTR_ERR(obj); | ||
| 1485 | |||
| 1486 | return in_len; | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | static int ib_uverbs_ex_create_cq_cb(struct ib_uverbs_file *file, | ||
| 1490 | struct ib_ucq_object *obj, | ||
| 1491 | struct ib_uverbs_ex_create_cq_resp *resp, | ||
| 1492 | struct ib_udata *ucore, void *context) | ||
| 1493 | { | ||
| 1494 | if (ib_copy_to_udata(ucore, resp, resp->response_length)) | ||
| 1495 | return -EFAULT; | ||
| 1496 | |||
| 1497 | return 0; | ||
| 1498 | } | ||
| 1499 | |||
| 1500 | int ib_uverbs_ex_create_cq(struct ib_uverbs_file *file, | ||
| 1501 | struct ib_udata *ucore, | ||
| 1502 | struct ib_udata *uhw) | ||
| 1503 | { | ||
| 1504 | struct ib_uverbs_ex_create_cq_resp resp; | ||
| 1505 | struct ib_uverbs_ex_create_cq cmd; | ||
| 1506 | struct ib_ucq_object *obj; | ||
| 1507 | int err; | ||
| 1508 | |||
| 1509 | if (ucore->inlen < sizeof(cmd)) | ||
| 1510 | return -EINVAL; | ||
| 1511 | |||
| 1512 | err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd)); | ||
| 1513 | if (err) | ||
| 1514 | return err; | ||
| 1515 | |||
| 1516 | if (cmd.comp_mask) | ||
| 1517 | return -EINVAL; | ||
| 1518 | |||
| 1519 | if (cmd.reserved) | ||
| 1520 | return -EINVAL; | ||
| 1521 | |||
| 1522 | if (ucore->outlen < (offsetof(typeof(resp), response_length) + | ||
| 1523 | sizeof(resp.response_length))) | ||
| 1524 | return -ENOSPC; | ||
| 1525 | |||
| 1526 | obj = create_cq(file, ucore, uhw, &cmd, | ||
| 1527 | min(ucore->inlen, sizeof(cmd)), | ||
| 1528 | ib_uverbs_ex_create_cq_cb, NULL); | ||
| 1529 | |||
| 1530 | if (IS_ERR(obj)) | ||
| 1531 | return PTR_ERR(obj); | ||
| 1532 | |||
| 1533 | return 0; | ||
| 1432 | } | 1534 | } |
| 1433 | 1535 | ||
| 1434 | ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file, | 1536 | ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file, |
| @@ -3324,7 +3426,9 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file, | |||
| 3324 | if (ucore->outlen < resp.response_length) | 3426 | if (ucore->outlen < resp.response_length) |
| 3325 | return -ENOSPC; | 3427 | return -ENOSPC; |
| 3326 | 3428 | ||
| 3327 | err = device->query_device(device, &attr); | 3429 | memset(&attr, 0, sizeof(attr)); |
| 3430 | |||
| 3431 | err = device->query_device(device, &attr, uhw); | ||
| 3328 | if (err) | 3432 | if (err) |
| 3329 | return err; | 3433 | return err; |
| 3330 | 3434 | ||
| @@ -3348,6 +3452,18 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file, | |||
| 3348 | #endif | 3452 | #endif |
| 3349 | resp.response_length += sizeof(resp.odp_caps); | 3453 | resp.response_length += sizeof(resp.odp_caps); |
| 3350 | 3454 | ||
| 3455 | if (ucore->outlen < resp.response_length + sizeof(resp.timestamp_mask)) | ||
| 3456 | goto end; | ||
| 3457 | |||
| 3458 | resp.timestamp_mask = attr.timestamp_mask; | ||
| 3459 | resp.response_length += sizeof(resp.timestamp_mask); | ||
| 3460 | |||
| 3461 | if (ucore->outlen < resp.response_length + sizeof(resp.hca_core_clock)) | ||
| 3462 | goto end; | ||
| 3463 | |||
| 3464 | resp.hca_core_clock = attr.hca_core_clock; | ||
| 3465 | resp.response_length += sizeof(resp.hca_core_clock); | ||
| 3466 | |||
| 3351 | end: | 3467 | end: |
| 3352 | err = ib_copy_to_udata(ucore, &resp, resp.response_length); | 3468 | err = ib_copy_to_udata(ucore, &resp, resp.response_length); |
| 3353 | if (err) | 3469 | if (err) |
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 88cce9bb72fe..f6eef2da7097 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
| @@ -124,6 +124,7 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file, | |||
| 124 | [IB_USER_VERBS_EX_CMD_CREATE_FLOW] = ib_uverbs_ex_create_flow, | 124 | [IB_USER_VERBS_EX_CMD_CREATE_FLOW] = ib_uverbs_ex_create_flow, |
| 125 | [IB_USER_VERBS_EX_CMD_DESTROY_FLOW] = ib_uverbs_ex_destroy_flow, | 125 | [IB_USER_VERBS_EX_CMD_DESTROY_FLOW] = ib_uverbs_ex_destroy_flow, |
| 126 | [IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device, | 126 | [IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device, |
| 127 | [IB_USER_VERBS_EX_CMD_CREATE_CQ] = ib_uverbs_ex_create_cq, | ||
| 127 | }; | 128 | }; |
| 128 | 129 | ||
| 129 | static void ib_uverbs_add_one(struct ib_device *device); | 130 | static void ib_uverbs_add_one(struct ib_device *device); |
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index f93eb8da7b5a..bac3fb406a74 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c | |||
| @@ -48,6 +48,71 @@ | |||
| 48 | 48 | ||
| 49 | #include "core_priv.h" | 49 | #include "core_priv.h" |
| 50 | 50 | ||
| 51 | static const char * const ib_events[] = { | ||
| 52 | [IB_EVENT_CQ_ERR] = "CQ error", | ||
| 53 | [IB_EVENT_QP_FATAL] = "QP fatal error", | ||
| 54 | [IB_EVENT_QP_REQ_ERR] = "QP request error", | ||
| 55 | [IB_EVENT_QP_ACCESS_ERR] = "QP access error", | ||
| 56 | [IB_EVENT_COMM_EST] = "communication established", | ||
| 57 | [IB_EVENT_SQ_DRAINED] = "send queue drained", | ||
| 58 | [IB_EVENT_PATH_MIG] = "path migration successful", | ||
| 59 | [IB_EVENT_PATH_MIG_ERR] = "path migration error", | ||
| 60 | [IB_EVENT_DEVICE_FATAL] = "device fatal error", | ||
| 61 | [IB_EVENT_PORT_ACTIVE] = "port active", | ||
| 62 | [IB_EVENT_PORT_ERR] = "port error", | ||
| 63 | [IB_EVENT_LID_CHANGE] = "LID change", | ||
| 64 | [IB_EVENT_PKEY_CHANGE] = "P_key change", | ||
| 65 | [IB_EVENT_SM_CHANGE] = "SM change", | ||
| 66 | [IB_EVENT_SRQ_ERR] = "SRQ error", | ||
| 67 | [IB_EVENT_SRQ_LIMIT_REACHED] = "SRQ limit reached", | ||
| 68 | [IB_EVENT_QP_LAST_WQE_REACHED] = "last WQE reached", | ||
| 69 | [IB_EVENT_CLIENT_REREGISTER] = "client reregister", | ||
| 70 | [IB_EVENT_GID_CHANGE] = "GID changed", | ||
| 71 | }; | ||
| 72 | |||
| 73 | const char *ib_event_msg(enum ib_event_type event) | ||
| 74 | { | ||
| 75 | size_t index = event; | ||
| 76 | |||
| 77 | return (index < ARRAY_SIZE(ib_events) && ib_events[index]) ? | ||
| 78 | ib_events[index] : "unrecognized event"; | ||
| 79 | } | ||
| 80 | EXPORT_SYMBOL(ib_event_msg); | ||
| 81 | |||
| 82 | static const char * const wc_statuses[] = { | ||
| 83 | [IB_WC_SUCCESS] = "success", | ||
| 84 | [IB_WC_LOC_LEN_ERR] = "local length error", | ||
| 85 | [IB_WC_LOC_QP_OP_ERR] = "local QP operation error", | ||
| 86 | [IB_WC_LOC_EEC_OP_ERR] = "local EE context operation error", | ||
| 87 | [IB_WC_LOC_PROT_ERR] = "local protection error", | ||
| 88 | [IB_WC_WR_FLUSH_ERR] = "WR flushed", | ||
| 89 | [IB_WC_MW_BIND_ERR] = "memory management operation error", | ||
| 90 | [IB_WC_BAD_RESP_ERR] = "bad response error", | ||
| 91 | [IB_WC_LOC_ACCESS_ERR] = "local access error", | ||
| 92 | [IB_WC_REM_INV_REQ_ERR] = "invalid request error", | ||
| 93 | [IB_WC_REM_ACCESS_ERR] = "remote access error", | ||
| 94 | [IB_WC_REM_OP_ERR] = "remote operation error", | ||
| 95 | [IB_WC_RETRY_EXC_ERR] = "transport retry counter exceeded", | ||
| 96 | [IB_WC_RNR_RETRY_EXC_ERR] = "RNR retry counter exceeded", | ||
| 97 | [IB_WC_LOC_RDD_VIOL_ERR] = "local RDD violation error", | ||
| 98 | [IB_WC_REM_INV_RD_REQ_ERR] = "remote invalid RD request", | ||
| 99 | [IB_WC_REM_ABORT_ERR] = "operation aborted", | ||
| 100 | [IB_WC_INV_EECN_ERR] = "invalid EE context number", | ||
| 101 | [IB_WC_INV_EEC_STATE_ERR] = "invalid EE context state", | ||
| 102 | [IB_WC_FATAL_ERR] = "fatal error", | ||
| 103 | [IB_WC_RESP_TIMEOUT_ERR] = "response timeout error", | ||
| 104 | [IB_WC_GENERAL_ERR] = "general error", | ||
| 105 | }; | ||
| 106 | |||
| 107 | const char *ib_wc_status_msg(enum ib_wc_status status) | ||
| 108 | { | ||
| 109 | size_t index = status; | ||
| 110 | |||
| 111 | return (index < ARRAY_SIZE(wc_statuses) && wc_statuses[index]) ? | ||
| 112 | wc_statuses[index] : "unrecognized status"; | ||
| 113 | } | ||
| 114 | EXPORT_SYMBOL(ib_wc_status_msg); | ||
| 115 | |||
| 51 | __attribute_const__ int ib_rate_to_mult(enum ib_rate rate) | 116 | __attribute_const__ int ib_rate_to_mult(enum ib_rate rate) |
| 52 | { | 117 | { |
| 53 | switch (rate) { | 118 | switch (rate) { |
| @@ -192,17 +257,16 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) | |||
| 192 | } | 257 | } |
| 193 | EXPORT_SYMBOL(ib_create_ah); | 258 | EXPORT_SYMBOL(ib_create_ah); |
| 194 | 259 | ||
| 195 | int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc, | 260 | int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, |
| 196 | struct ib_grh *grh, struct ib_ah_attr *ah_attr) | 261 | const struct ib_wc *wc, const struct ib_grh *grh, |
| 262 | struct ib_ah_attr *ah_attr) | ||
| 197 | { | 263 | { |
| 198 | u32 flow_class; | 264 | u32 flow_class; |
| 199 | u16 gid_index; | 265 | u16 gid_index; |
| 200 | int ret; | 266 | int ret; |
| 201 | int is_eth = (rdma_port_get_link_layer(device, port_num) == | ||
| 202 | IB_LINK_LAYER_ETHERNET); | ||
| 203 | 267 | ||
| 204 | memset(ah_attr, 0, sizeof *ah_attr); | 268 | memset(ah_attr, 0, sizeof *ah_attr); |
| 205 | if (is_eth) { | 269 | if (rdma_cap_eth_ah(device, port_num)) { |
| 206 | if (!(wc->wc_flags & IB_WC_GRH)) | 270 | if (!(wc->wc_flags & IB_WC_GRH)) |
| 207 | return -EPROTOTYPE; | 271 | return -EPROTOTYPE; |
| 208 | 272 | ||
| @@ -244,8 +308,8 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc, | |||
| 244 | } | 308 | } |
| 245 | EXPORT_SYMBOL(ib_init_ah_from_wc); | 309 | EXPORT_SYMBOL(ib_init_ah_from_wc); |
| 246 | 310 | ||
| 247 | struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc, | 311 | struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, const struct ib_wc *wc, |
| 248 | struct ib_grh *grh, u8 port_num) | 312 | const struct ib_grh *grh, u8 port_num) |
| 249 | { | 313 | { |
| 250 | struct ib_ah_attr ah_attr; | 314 | struct ib_ah_attr ah_attr; |
| 251 | int ret; | 315 | int ret; |
| @@ -871,7 +935,7 @@ int ib_resolve_eth_l2_attrs(struct ib_qp *qp, | |||
| 871 | union ib_gid sgid; | 935 | union ib_gid sgid; |
| 872 | 936 | ||
| 873 | if ((*qp_attr_mask & IB_QP_AV) && | 937 | if ((*qp_attr_mask & IB_QP_AV) && |
| 874 | (rdma_port_get_link_layer(qp->device, qp_attr->ah_attr.port_num) == IB_LINK_LAYER_ETHERNET)) { | 938 | (rdma_cap_eth_ah(qp->device, qp_attr->ah_attr.port_num))) { |
| 875 | ret = ib_query_gid(qp->device, qp_attr->ah_attr.port_num, | 939 | ret = ib_query_gid(qp->device, qp_attr->ah_attr.port_num, |
| 876 | qp_attr->ah_attr.grh.sgid_index, &sgid); | 940 | qp_attr->ah_attr.grh.sgid_index, &sgid); |
| 877 | if (ret) | 941 | if (ret) |
| @@ -1012,11 +1076,12 @@ EXPORT_SYMBOL(ib_destroy_qp); | |||
| 1012 | struct ib_cq *ib_create_cq(struct ib_device *device, | 1076 | struct ib_cq *ib_create_cq(struct ib_device *device, |
| 1013 | ib_comp_handler comp_handler, | 1077 | ib_comp_handler comp_handler, |
| 1014 | void (*event_handler)(struct ib_event *, void *), | 1078 | void (*event_handler)(struct ib_event *, void *), |
| 1015 | void *cq_context, int cqe, int comp_vector) | 1079 | void *cq_context, |
| 1080 | const struct ib_cq_init_attr *cq_attr) | ||
| 1016 | { | 1081 | { |
| 1017 | struct ib_cq *cq; | 1082 | struct ib_cq *cq; |
| 1018 | 1083 | ||
| 1019 | cq = device->create_cq(device, cqe, comp_vector, NULL, NULL); | 1084 | cq = device->create_cq(device, cq_attr, NULL, NULL); |
| 1020 | 1085 | ||
| 1021 | if (!IS_ERR(cq)) { | 1086 | if (!IS_ERR(cq)) { |
| 1022 | cq->device = device; | 1087 | cq->device = device; |
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c index bdf3507810cb..25c3f0085563 100644 --- a/drivers/infiniband/hw/amso1100/c2_provider.c +++ b/drivers/infiniband/hw/amso1100/c2_provider.c | |||
| @@ -63,13 +63,16 @@ | |||
| 63 | #include "c2_provider.h" | 63 | #include "c2_provider.h" |
| 64 | #include "c2_user.h" | 64 | #include "c2_user.h" |
| 65 | 65 | ||
| 66 | static int c2_query_device(struct ib_device *ibdev, | 66 | static int c2_query_device(struct ib_device *ibdev, struct ib_device_attr *props, |
| 67 | struct ib_device_attr *props) | 67 | struct ib_udata *uhw) |
| 68 | { | 68 | { |
| 69 | struct c2_dev *c2dev = to_c2dev(ibdev); | 69 | struct c2_dev *c2dev = to_c2dev(ibdev); |
| 70 | 70 | ||
| 71 | pr_debug("%s:%u\n", __func__, __LINE__); | 71 | pr_debug("%s:%u\n", __func__, __LINE__); |
| 72 | 72 | ||
| 73 | if (uhw->inlen || uhw->outlen) | ||
| 74 | return -EINVAL; | ||
| 75 | |||
| 73 | *props = c2dev->props; | 76 | *props = c2dev->props; |
| 74 | return 0; | 77 | return 0; |
| 75 | } | 78 | } |
| @@ -286,13 +289,18 @@ static int c2_destroy_qp(struct ib_qp *ib_qp) | |||
| 286 | return 0; | 289 | return 0; |
| 287 | } | 290 | } |
| 288 | 291 | ||
| 289 | static struct ib_cq *c2_create_cq(struct ib_device *ibdev, int entries, int vector, | 292 | static struct ib_cq *c2_create_cq(struct ib_device *ibdev, |
| 293 | const struct ib_cq_init_attr *attr, | ||
| 290 | struct ib_ucontext *context, | 294 | struct ib_ucontext *context, |
| 291 | struct ib_udata *udata) | 295 | struct ib_udata *udata) |
| 292 | { | 296 | { |
| 297 | int entries = attr->cqe; | ||
| 293 | struct c2_cq *cq; | 298 | struct c2_cq *cq; |
| 294 | int err; | 299 | int err; |
| 295 | 300 | ||
| 301 | if (attr->flags) | ||
| 302 | return ERR_PTR(-EINVAL); | ||
| 303 | |||
| 296 | cq = kmalloc(sizeof(*cq), GFP_KERNEL); | 304 | cq = kmalloc(sizeof(*cq), GFP_KERNEL); |
| 297 | if (!cq) { | 305 | if (!cq) { |
| 298 | pr_debug("%s: Unable to allocate CQ\n", __func__); | 306 | pr_debug("%s: Unable to allocate CQ\n", __func__); |
| @@ -582,9 +590,13 @@ static int c2_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
| 582 | static int c2_process_mad(struct ib_device *ibdev, | 590 | static int c2_process_mad(struct ib_device *ibdev, |
| 583 | int mad_flags, | 591 | int mad_flags, |
| 584 | u8 port_num, | 592 | u8 port_num, |
| 585 | struct ib_wc *in_wc, | 593 | const struct ib_wc *in_wc, |
| 586 | struct ib_grh *in_grh, | 594 | const struct ib_grh *in_grh, |
| 587 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 595 | const struct ib_mad_hdr *in_mad, |
| 596 | size_t in_mad_size, | ||
| 597 | struct ib_mad_hdr *out_mad, | ||
| 598 | size_t *out_mad_size, | ||
| 599 | u16 *out_mad_pkey_index) | ||
| 588 | { | 600 | { |
| 589 | pr_debug("%s:%u\n", __func__, __LINE__); | 601 | pr_debug("%s:%u\n", __func__, __LINE__); |
| 590 | return -ENOSYS; | 602 | return -ENOSYS; |
| @@ -757,6 +769,23 @@ static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev) | |||
| 757 | return netdev; | 769 | return netdev; |
| 758 | } | 770 | } |
| 759 | 771 | ||
| 772 | static int c2_port_immutable(struct ib_device *ibdev, u8 port_num, | ||
| 773 | struct ib_port_immutable *immutable) | ||
| 774 | { | ||
| 775 | struct ib_port_attr attr; | ||
| 776 | int err; | ||
| 777 | |||
| 778 | err = c2_query_port(ibdev, port_num, &attr); | ||
| 779 | if (err) | ||
| 780 | return err; | ||
| 781 | |||
| 782 | immutable->pkey_tbl_len = attr.pkey_tbl_len; | ||
| 783 | immutable->gid_tbl_len = attr.gid_tbl_len; | ||
| 784 | immutable->core_cap_flags = RDMA_CORE_PORT_IWARP; | ||
| 785 | |||
| 786 | return 0; | ||
| 787 | } | ||
| 788 | |||
| 760 | int c2_register_device(struct c2_dev *dev) | 789 | int c2_register_device(struct c2_dev *dev) |
| 761 | { | 790 | { |
| 762 | int ret = -ENOMEM; | 791 | int ret = -ENOMEM; |
| @@ -820,6 +849,7 @@ int c2_register_device(struct c2_dev *dev) | |||
| 820 | dev->ibdev.reg_phys_mr = c2_reg_phys_mr; | 849 | dev->ibdev.reg_phys_mr = c2_reg_phys_mr; |
| 821 | dev->ibdev.reg_user_mr = c2_reg_user_mr; | 850 | dev->ibdev.reg_user_mr = c2_reg_user_mr; |
| 822 | dev->ibdev.dereg_mr = c2_dereg_mr; | 851 | dev->ibdev.dereg_mr = c2_dereg_mr; |
| 852 | dev->ibdev.get_port_immutable = c2_port_immutable; | ||
| 823 | 853 | ||
| 824 | dev->ibdev.alloc_fmr = NULL; | 854 | dev->ibdev.alloc_fmr = NULL; |
| 825 | dev->ibdev.unmap_fmr = NULL; | 855 | dev->ibdev.unmap_fmr = NULL; |
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index 811b24a539c0..bbbe0184e592 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c | |||
| @@ -85,9 +85,13 @@ static int iwch_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
| 85 | static int iwch_process_mad(struct ib_device *ibdev, | 85 | static int iwch_process_mad(struct ib_device *ibdev, |
| 86 | int mad_flags, | 86 | int mad_flags, |
| 87 | u8 port_num, | 87 | u8 port_num, |
| 88 | struct ib_wc *in_wc, | 88 | const struct ib_wc *in_wc, |
| 89 | struct ib_grh *in_grh, | 89 | const struct ib_grh *in_grh, |
| 90 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 90 | const struct ib_mad_hdr *in_mad, |
| 91 | size_t in_mad_size, | ||
| 92 | struct ib_mad_hdr *out_mad, | ||
| 93 | size_t *out_mad_size, | ||
| 94 | u16 *out_mad_pkey_index) | ||
| 91 | { | 95 | { |
| 92 | return -ENOSYS; | 96 | return -ENOSYS; |
| 93 | } | 97 | } |
| @@ -138,10 +142,12 @@ static int iwch_destroy_cq(struct ib_cq *ib_cq) | |||
| 138 | return 0; | 142 | return 0; |
| 139 | } | 143 | } |
| 140 | 144 | ||
| 141 | static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int vector, | 145 | static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, |
| 142 | struct ib_ucontext *ib_context, | 146 | const struct ib_cq_init_attr *attr, |
| 143 | struct ib_udata *udata) | 147 | struct ib_ucontext *ib_context, |
| 148 | struct ib_udata *udata) | ||
| 144 | { | 149 | { |
| 150 | int entries = attr->cqe; | ||
| 145 | struct iwch_dev *rhp; | 151 | struct iwch_dev *rhp; |
| 146 | struct iwch_cq *chp; | 152 | struct iwch_cq *chp; |
| 147 | struct iwch_create_cq_resp uresp; | 153 | struct iwch_create_cq_resp uresp; |
| @@ -151,6 +157,9 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve | |||
| 151 | size_t resplen; | 157 | size_t resplen; |
| 152 | 158 | ||
| 153 | PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries); | 159 | PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries); |
| 160 | if (attr->flags) | ||
| 161 | return ERR_PTR(-EINVAL); | ||
| 162 | |||
| 154 | rhp = to_iwch_dev(ibdev); | 163 | rhp = to_iwch_dev(ibdev); |
| 155 | chp = kzalloc(sizeof(*chp), GFP_KERNEL); | 164 | chp = kzalloc(sizeof(*chp), GFP_KERNEL); |
| 156 | if (!chp) | 165 | if (!chp) |
| @@ -727,6 +736,10 @@ static struct ib_mr *iwch_get_dma_mr(struct ib_pd *pd, int acc) | |||
| 727 | /* | 736 | /* |
| 728 | * T3 only supports 32 bits of size. | 737 | * T3 only supports 32 bits of size. |
| 729 | */ | 738 | */ |
| 739 | if (sizeof(phys_addr_t) > 4) { | ||
| 740 | pr_warn_once(MOD "Cannot support dma_mrs on this platform.\n"); | ||
| 741 | return ERR_PTR(-ENOTSUPP); | ||
| 742 | } | ||
| 730 | bl.size = 0xffffffff; | 743 | bl.size = 0xffffffff; |
| 731 | bl.addr = 0; | 744 | bl.addr = 0; |
| 732 | kva = 0; | 745 | kva = 0; |
| @@ -1145,13 +1158,17 @@ static u64 fw_vers_string_to_u64(struct iwch_dev *iwch_dev) | |||
| 1145 | (fw_mic & 0xffff); | 1158 | (fw_mic & 0xffff); |
| 1146 | } | 1159 | } |
| 1147 | 1160 | ||
| 1148 | static int iwch_query_device(struct ib_device *ibdev, | 1161 | static int iwch_query_device(struct ib_device *ibdev, struct ib_device_attr *props, |
| 1149 | struct ib_device_attr *props) | 1162 | struct ib_udata *uhw) |
| 1150 | { | 1163 | { |
| 1151 | 1164 | ||
| 1152 | struct iwch_dev *dev; | 1165 | struct iwch_dev *dev; |
| 1166 | |||
| 1153 | PDBG("%s ibdev %p\n", __func__, ibdev); | 1167 | PDBG("%s ibdev %p\n", __func__, ibdev); |
| 1154 | 1168 | ||
| 1169 | if (uhw->inlen || uhw->outlen) | ||
| 1170 | return -EINVAL; | ||
| 1171 | |||
| 1155 | dev = to_iwch_dev(ibdev); | 1172 | dev = to_iwch_dev(ibdev); |
| 1156 | memset(props, 0, sizeof *props); | 1173 | memset(props, 0, sizeof *props); |
| 1157 | memcpy(&props->sys_image_guid, dev->rdev.t3cdev_p->lldev->dev_addr, 6); | 1174 | memcpy(&props->sys_image_guid, dev->rdev.t3cdev_p->lldev->dev_addr, 6); |
| @@ -1343,6 +1360,23 @@ static struct device_attribute *iwch_class_attributes[] = { | |||
| 1343 | &dev_attr_board_id, | 1360 | &dev_attr_board_id, |
| 1344 | }; | 1361 | }; |
| 1345 | 1362 | ||
| 1363 | static int iwch_port_immutable(struct ib_device *ibdev, u8 port_num, | ||
| 1364 | struct ib_port_immutable *immutable) | ||
| 1365 | { | ||
| 1366 | struct ib_port_attr attr; | ||
| 1367 | int err; | ||
| 1368 | |||
| 1369 | err = iwch_query_port(ibdev, port_num, &attr); | ||
| 1370 | if (err) | ||
| 1371 | return err; | ||
| 1372 | |||
| 1373 | immutable->pkey_tbl_len = attr.pkey_tbl_len; | ||
| 1374 | immutable->gid_tbl_len = attr.gid_tbl_len; | ||
| 1375 | immutable->core_cap_flags = RDMA_CORE_PORT_IWARP; | ||
| 1376 | |||
| 1377 | return 0; | ||
| 1378 | } | ||
| 1379 | |||
| 1346 | int iwch_register_device(struct iwch_dev *dev) | 1380 | int iwch_register_device(struct iwch_dev *dev) |
| 1347 | { | 1381 | { |
| 1348 | int ret; | 1382 | int ret; |
| @@ -1420,6 +1454,7 @@ int iwch_register_device(struct iwch_dev *dev) | |||
| 1420 | dev->ibdev.post_recv = iwch_post_receive; | 1454 | dev->ibdev.post_recv = iwch_post_receive; |
| 1421 | dev->ibdev.get_protocol_stats = iwch_get_mib; | 1455 | dev->ibdev.get_protocol_stats = iwch_get_mib; |
| 1422 | dev->ibdev.uverbs_abi_ver = IWCH_UVERBS_ABI_VERSION; | 1456 | dev->ibdev.uverbs_abi_ver = IWCH_UVERBS_ABI_VERSION; |
| 1457 | dev->ibdev.get_port_immutable = iwch_port_immutable; | ||
| 1423 | 1458 | ||
| 1424 | dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL); | 1459 | dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL); |
| 1425 | if (!dev->ibdev.iwcm) | 1460 | if (!dev->ibdev.iwcm) |
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c index 68ddb3710215..c7aab48f07cd 100644 --- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c | |||
| @@ -156,19 +156,17 @@ static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq, | |||
| 156 | goto err4; | 156 | goto err4; |
| 157 | 157 | ||
| 158 | cq->gen = 1; | 158 | cq->gen = 1; |
| 159 | cq->gts = rdev->lldi.gts_reg; | ||
| 159 | cq->rdev = rdev; | 160 | cq->rdev = rdev; |
| 160 | if (user) { | ||
| 161 | u32 off = (cq->cqid << rdev->cqshift) & PAGE_MASK; | ||
| 162 | 161 | ||
| 163 | cq->ugts = (u64)rdev->bar2_pa + off; | 162 | cq->bar2_va = c4iw_bar2_addrs(rdev, cq->cqid, T4_BAR2_QTYPE_INGRESS, |
| 164 | } else if (is_t4(rdev->lldi.adapter_type)) { | 163 | &cq->bar2_qid, |
| 165 | cq->gts = rdev->lldi.gts_reg; | 164 | user ? &cq->bar2_pa : NULL); |
| 166 | cq->qid_mask = -1U; | 165 | if (user && !cq->bar2_va) { |
| 167 | } else { | 166 | pr_warn(MOD "%s: cqid %u not in BAR2 range.\n", |
| 168 | u32 off = ((cq->cqid << rdev->cqshift) & PAGE_MASK) + 12; | 167 | pci_name(rdev->lldi.pdev), cq->cqid); |
| 169 | 168 | ret = -EINVAL; | |
| 170 | cq->gts = rdev->bar2_kva + off; | 169 | goto err4; |
| 171 | cq->qid_mask = rdev->qpmask; | ||
| 172 | } | 170 | } |
| 173 | return 0; | 171 | return 0; |
| 174 | err4: | 172 | err4: |
| @@ -866,10 +864,13 @@ int c4iw_destroy_cq(struct ib_cq *ib_cq) | |||
| 866 | return 0; | 864 | return 0; |
| 867 | } | 865 | } |
| 868 | 866 | ||
| 869 | struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries, | 867 | struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, |
| 870 | int vector, struct ib_ucontext *ib_context, | 868 | const struct ib_cq_init_attr *attr, |
| 869 | struct ib_ucontext *ib_context, | ||
| 871 | struct ib_udata *udata) | 870 | struct ib_udata *udata) |
| 872 | { | 871 | { |
| 872 | int entries = attr->cqe; | ||
| 873 | int vector = attr->comp_vector; | ||
| 873 | struct c4iw_dev *rhp; | 874 | struct c4iw_dev *rhp; |
| 874 | struct c4iw_cq *chp; | 875 | struct c4iw_cq *chp; |
| 875 | struct c4iw_create_cq_resp uresp; | 876 | struct c4iw_create_cq_resp uresp; |
| @@ -879,6 +880,8 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries, | |||
| 879 | struct c4iw_mm_entry *mm, *mm2; | 880 | struct c4iw_mm_entry *mm, *mm2; |
| 880 | 881 | ||
| 881 | PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries); | 882 | PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries); |
| 883 | if (attr->flags) | ||
| 884 | return ERR_PTR(-EINVAL); | ||
| 882 | 885 | ||
| 883 | rhp = to_c4iw_dev(ibdev); | 886 | rhp = to_c4iw_dev(ibdev); |
| 884 | 887 | ||
| @@ -971,7 +974,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries, | |||
| 971 | insert_mmap(ucontext, mm); | 974 | insert_mmap(ucontext, mm); |
| 972 | 975 | ||
| 973 | mm2->key = uresp.gts_key; | 976 | mm2->key = uresp.gts_key; |
| 974 | mm2->addr = chp->cq.ugts; | 977 | mm2->addr = chp->cq.bar2_pa; |
| 975 | mm2->len = PAGE_SIZE; | 978 | mm2->len = PAGE_SIZE; |
| 976 | insert_mmap(ucontext, mm2); | 979 | insert_mmap(ucontext, mm2); |
| 977 | } | 980 | } |
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c index 7e895d714b19..1a297391b54c 100644 --- a/drivers/infiniband/hw/cxgb4/device.c +++ b/drivers/infiniband/hw/cxgb4/device.c | |||
| @@ -795,13 +795,7 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev) | |||
| 795 | goto err1; | 795 | goto err1; |
| 796 | } | 796 | } |
| 797 | 797 | ||
| 798 | /* | ||
| 799 | * qpshift is the number of bits to shift the qpid left in order | ||
| 800 | * to get the correct address of the doorbell for that qp. | ||
| 801 | */ | ||
| 802 | rdev->qpshift = PAGE_SHIFT - ilog2(rdev->lldi.udb_density); | ||
| 803 | rdev->qpmask = rdev->lldi.udb_density - 1; | 798 | rdev->qpmask = rdev->lldi.udb_density - 1; |
| 804 | rdev->cqshift = PAGE_SHIFT - ilog2(rdev->lldi.ucq_density); | ||
| 805 | rdev->cqmask = rdev->lldi.ucq_density - 1; | 799 | rdev->cqmask = rdev->lldi.ucq_density - 1; |
| 806 | PDBG("%s dev %s stag start 0x%0x size 0x%0x num stags %d " | 800 | PDBG("%s dev %s stag start 0x%0x size 0x%0x num stags %d " |
| 807 | "pbl start 0x%0x size 0x%0x rq start 0x%0x size 0x%0x " | 801 | "pbl start 0x%0x size 0x%0x rq start 0x%0x size 0x%0x " |
| @@ -815,14 +809,12 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev) | |||
| 815 | rdev->lldi.vr->qp.size, | 809 | rdev->lldi.vr->qp.size, |
| 816 | rdev->lldi.vr->cq.start, | 810 | rdev->lldi.vr->cq.start, |
| 817 | rdev->lldi.vr->cq.size); | 811 | rdev->lldi.vr->cq.size); |
| 818 | PDBG("udb len 0x%x udb base %p db_reg %p gts_reg %p qpshift %lu " | 812 | PDBG("udb len 0x%x udb base %p db_reg %p gts_reg %p " |
| 819 | "qpmask 0x%x cqshift %lu cqmask 0x%x\n", | 813 | "qpmask 0x%x cqmask 0x%x\n", |
| 820 | (unsigned)pci_resource_len(rdev->lldi.pdev, 2), | 814 | (unsigned)pci_resource_len(rdev->lldi.pdev, 2), |
| 821 | (void *)pci_resource_start(rdev->lldi.pdev, 2), | 815 | (void *)pci_resource_start(rdev->lldi.pdev, 2), |
| 822 | rdev->lldi.db_reg, | 816 | rdev->lldi.db_reg, rdev->lldi.gts_reg, |
| 823 | rdev->lldi.gts_reg, | 817 | rdev->qpmask, rdev->cqmask); |
| 824 | rdev->qpshift, rdev->qpmask, | ||
| 825 | rdev->cqshift, rdev->cqmask); | ||
| 826 | 818 | ||
| 827 | if (c4iw_num_stags(rdev) == 0) { | 819 | if (c4iw_num_stags(rdev) == 0) { |
| 828 | err = -EINVAL; | 820 | err = -EINVAL; |
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index 97bb5550a6cf..cc77844fada3 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h | |||
| @@ -165,9 +165,7 @@ struct wr_log_entry { | |||
| 165 | 165 | ||
| 166 | struct c4iw_rdev { | 166 | struct c4iw_rdev { |
| 167 | struct c4iw_resource resource; | 167 | struct c4iw_resource resource; |
| 168 | unsigned long qpshift; | ||
| 169 | u32 qpmask; | 168 | u32 qpmask; |
| 170 | unsigned long cqshift; | ||
| 171 | u32 cqmask; | 169 | u32 cqmask; |
| 172 | struct c4iw_dev_ucontext uctx; | 170 | struct c4iw_dev_ucontext uctx; |
| 173 | struct gen_pool *pbl_pool; | 171 | struct gen_pool *pbl_pool; |
| @@ -992,10 +990,10 @@ int c4iw_reregister_phys_mem(struct ib_mr *mr, | |||
| 992 | int acc, u64 *iova_start); | 990 | int acc, u64 *iova_start); |
| 993 | int c4iw_dereg_mr(struct ib_mr *ib_mr); | 991 | int c4iw_dereg_mr(struct ib_mr *ib_mr); |
| 994 | int c4iw_destroy_cq(struct ib_cq *ib_cq); | 992 | int c4iw_destroy_cq(struct ib_cq *ib_cq); |
| 995 | struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries, | 993 | struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, |
| 996 | int vector, | 994 | const struct ib_cq_init_attr *attr, |
| 997 | struct ib_ucontext *ib_context, | 995 | struct ib_ucontext *ib_context, |
| 998 | struct ib_udata *udata); | 996 | struct ib_udata *udata); |
| 999 | int c4iw_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata); | 997 | int c4iw_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata); |
| 1000 | int c4iw_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags); | 998 | int c4iw_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags); |
| 1001 | int c4iw_destroy_qp(struct ib_qp *ib_qp); | 999 | int c4iw_destroy_qp(struct ib_qp *ib_qp); |
| @@ -1032,6 +1030,9 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe); | |||
| 1032 | 1030 | ||
| 1033 | extern struct cxgb4_client t4c_client; | 1031 | extern struct cxgb4_client t4c_client; |
| 1034 | extern c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS]; | 1032 | extern c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS]; |
| 1033 | void __iomem *c4iw_bar2_addrs(struct c4iw_rdev *rdev, unsigned int qid, | ||
| 1034 | enum cxgb4_bar2_qtype qtype, | ||
| 1035 | unsigned int *pbar2_qid, u64 *pbar2_pa); | ||
| 1035 | extern void c4iw_log_wr_stats(struct t4_wq *wq, struct t4_cqe *cqe); | 1036 | extern void c4iw_log_wr_stats(struct t4_wq *wq, struct t4_cqe *cqe); |
| 1036 | extern int c4iw_wr_log; | 1037 | extern int c4iw_wr_log; |
| 1037 | extern int db_fc_threshold; | 1038 | extern int db_fc_threshold; |
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c index 66bd6a2ad83b..6eee3d385541 100644 --- a/drivers/infiniband/hw/cxgb4/provider.c +++ b/drivers/infiniband/hw/cxgb4/provider.c | |||
| @@ -80,9 +80,13 @@ static int c4iw_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | static int c4iw_process_mad(struct ib_device *ibdev, int mad_flags, | 82 | static int c4iw_process_mad(struct ib_device *ibdev, int mad_flags, |
| 83 | u8 port_num, struct ib_wc *in_wc, | 83 | u8 port_num, const struct ib_wc *in_wc, |
| 84 | struct ib_grh *in_grh, struct ib_mad *in_mad, | 84 | const struct ib_grh *in_grh, |
| 85 | struct ib_mad *out_mad) | 85 | const struct ib_mad_hdr *in_mad, |
| 86 | size_t in_mad_size, | ||
| 87 | struct ib_mad_hdr *out_mad, | ||
| 88 | size_t *out_mad_size, | ||
| 89 | u16 *out_mad_pkey_index) | ||
| 86 | { | 90 | { |
| 87 | return -ENOSYS; | 91 | return -ENOSYS; |
| 88 | } | 92 | } |
| @@ -301,13 +305,17 @@ static int c4iw_query_gid(struct ib_device *ibdev, u8 port, int index, | |||
| 301 | return 0; | 305 | return 0; |
| 302 | } | 306 | } |
| 303 | 307 | ||
| 304 | static int c4iw_query_device(struct ib_device *ibdev, | 308 | static int c4iw_query_device(struct ib_device *ibdev, struct ib_device_attr *props, |
| 305 | struct ib_device_attr *props) | 309 | struct ib_udata *uhw) |
| 306 | { | 310 | { |
| 307 | 311 | ||
| 308 | struct c4iw_dev *dev; | 312 | struct c4iw_dev *dev; |
| 313 | |||
| 309 | PDBG("%s ibdev %p\n", __func__, ibdev); | 314 | PDBG("%s ibdev %p\n", __func__, ibdev); |
| 310 | 315 | ||
| 316 | if (uhw->inlen || uhw->outlen) | ||
| 317 | return -EINVAL; | ||
| 318 | |||
| 311 | dev = to_c4iw_dev(ibdev); | 319 | dev = to_c4iw_dev(ibdev); |
| 312 | memset(props, 0, sizeof *props); | 320 | memset(props, 0, sizeof *props); |
| 313 | memcpy(&props->sys_image_guid, dev->rdev.lldi.ports[0]->dev_addr, 6); | 321 | memcpy(&props->sys_image_guid, dev->rdev.lldi.ports[0]->dev_addr, 6); |
| @@ -445,10 +453,10 @@ static int c4iw_get_mib(struct ib_device *ibdev, | |||
| 445 | 453 | ||
| 446 | cxgb4_get_tcp_stats(c4iw_dev->rdev.lldi.pdev, &v4, &v6); | 454 | cxgb4_get_tcp_stats(c4iw_dev->rdev.lldi.pdev, &v4, &v6); |
| 447 | memset(stats, 0, sizeof *stats); | 455 | memset(stats, 0, sizeof *stats); |
| 448 | stats->iw.tcpInSegs = v4.tcpInSegs + v6.tcpInSegs; | 456 | stats->iw.tcpInSegs = v4.tcp_in_segs + v6.tcp_in_segs; |
| 449 | stats->iw.tcpOutSegs = v4.tcpOutSegs + v6.tcpOutSegs; | 457 | stats->iw.tcpOutSegs = v4.tcp_out_segs + v6.tcp_out_segs; |
| 450 | stats->iw.tcpRetransSegs = v4.tcpRetransSegs + v6.tcpRetransSegs; | 458 | stats->iw.tcpRetransSegs = v4.tcp_retrans_segs + v6.tcp_retrans_segs; |
| 451 | stats->iw.tcpOutRsts = v4.tcpOutRsts + v6.tcpOutSegs; | 459 | stats->iw.tcpOutRsts = v4.tcp_out_rsts + v6.tcp_out_rsts; |
| 452 | 460 | ||
| 453 | return 0; | 461 | return 0; |
| 454 | } | 462 | } |
| @@ -465,6 +473,23 @@ static struct device_attribute *c4iw_class_attributes[] = { | |||
| 465 | &dev_attr_board_id, | 473 | &dev_attr_board_id, |
| 466 | }; | 474 | }; |
| 467 | 475 | ||
| 476 | static int c4iw_port_immutable(struct ib_device *ibdev, u8 port_num, | ||
| 477 | struct ib_port_immutable *immutable) | ||
| 478 | { | ||
| 479 | struct ib_port_attr attr; | ||
| 480 | int err; | ||
| 481 | |||
| 482 | err = c4iw_query_port(ibdev, port_num, &attr); | ||
| 483 | if (err) | ||
| 484 | return err; | ||
| 485 | |||
| 486 | immutable->pkey_tbl_len = attr.pkey_tbl_len; | ||
| 487 | immutable->gid_tbl_len = attr.gid_tbl_len; | ||
| 488 | immutable->core_cap_flags = RDMA_CORE_PORT_IWARP; | ||
| 489 | |||
| 490 | return 0; | ||
| 491 | } | ||
| 492 | |||
| 468 | int c4iw_register_device(struct c4iw_dev *dev) | 493 | int c4iw_register_device(struct c4iw_dev *dev) |
| 469 | { | 494 | { |
| 470 | int ret; | 495 | int ret; |
| @@ -542,6 +567,7 @@ int c4iw_register_device(struct c4iw_dev *dev) | |||
| 542 | dev->ibdev.post_recv = c4iw_post_receive; | 567 | dev->ibdev.post_recv = c4iw_post_receive; |
| 543 | dev->ibdev.get_protocol_stats = c4iw_get_mib; | 568 | dev->ibdev.get_protocol_stats = c4iw_get_mib; |
| 544 | dev->ibdev.uverbs_abi_ver = C4IW_UVERBS_ABI_VERSION; | 569 | dev->ibdev.uverbs_abi_ver = C4IW_UVERBS_ABI_VERSION; |
| 570 | dev->ibdev.get_port_immutable = c4iw_port_immutable; | ||
| 545 | 571 | ||
| 546 | dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL); | 572 | dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL); |
| 547 | if (!dev->ibdev.iwcm) | 573 | if (!dev->ibdev.iwcm) |
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 389ced335bc5..6517e1208ccb 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c | |||
| @@ -165,6 +165,29 @@ static int destroy_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, | |||
| 165 | return 0; | 165 | return 0; |
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | /* | ||
| 169 | * Determine the BAR2 virtual address and qid. If pbar2_pa is not NULL, | ||
| 170 | * then this is a user mapping so compute the page-aligned physical address | ||
| 171 | * for mapping. | ||
| 172 | */ | ||
| 173 | void __iomem *c4iw_bar2_addrs(struct c4iw_rdev *rdev, unsigned int qid, | ||
| 174 | enum cxgb4_bar2_qtype qtype, | ||
| 175 | unsigned int *pbar2_qid, u64 *pbar2_pa) | ||
| 176 | { | ||
| 177 | u64 bar2_qoffset; | ||
| 178 | int ret; | ||
| 179 | |||
| 180 | ret = cxgb4_bar2_sge_qregs(rdev->lldi.ports[0], qid, qtype, | ||
| 181 | pbar2_pa ? 1 : 0, | ||
| 182 | &bar2_qoffset, pbar2_qid); | ||
| 183 | if (ret) | ||
| 184 | return NULL; | ||
| 185 | |||
| 186 | if (pbar2_pa) | ||
| 187 | *pbar2_pa = (rdev->bar2_pa + bar2_qoffset) & PAGE_MASK; | ||
| 188 | return rdev->bar2_kva + bar2_qoffset; | ||
| 189 | } | ||
| 190 | |||
| 168 | static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, | 191 | static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, |
| 169 | struct t4_cq *rcq, struct t4_cq *scq, | 192 | struct t4_cq *rcq, struct t4_cq *scq, |
| 170 | struct c4iw_dev_ucontext *uctx) | 193 | struct c4iw_dev_ucontext *uctx) |
| @@ -236,25 +259,23 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, | |||
| 236 | dma_unmap_addr_set(&wq->rq, mapping, wq->rq.dma_addr); | 259 | dma_unmap_addr_set(&wq->rq, mapping, wq->rq.dma_addr); |
| 237 | 260 | ||
| 238 | wq->db = rdev->lldi.db_reg; | 261 | wq->db = rdev->lldi.db_reg; |
| 239 | wq->gts = rdev->lldi.gts_reg; | ||
| 240 | if (user || is_t5(rdev->lldi.adapter_type)) { | ||
| 241 | u32 off; | ||
| 242 | 262 | ||
| 243 | off = (wq->sq.qid << rdev->qpshift) & PAGE_MASK; | 263 | wq->sq.bar2_va = c4iw_bar2_addrs(rdev, wq->sq.qid, T4_BAR2_QTYPE_EGRESS, |
| 244 | if (user) { | 264 | &wq->sq.bar2_qid, |
| 245 | wq->sq.udb = (u64 __iomem *)(rdev->bar2_pa + off); | 265 | user ? &wq->sq.bar2_pa : NULL); |
| 246 | } else { | 266 | wq->rq.bar2_va = c4iw_bar2_addrs(rdev, wq->rq.qid, T4_BAR2_QTYPE_EGRESS, |
| 247 | off += 128 * (wq->sq.qid & rdev->qpmask) + 8; | 267 | &wq->rq.bar2_qid, |
| 248 | wq->sq.udb = (u64 __iomem *)(rdev->bar2_kva + off); | 268 | user ? &wq->rq.bar2_pa : NULL); |
| 249 | } | 269 | |
| 250 | off = (wq->rq.qid << rdev->qpshift) & PAGE_MASK; | 270 | /* |
| 251 | if (user) { | 271 | * User mode must have bar2 access. |
| 252 | wq->rq.udb = (u64 __iomem *)(rdev->bar2_pa + off); | 272 | */ |
| 253 | } else { | 273 | if (user && (!wq->sq.bar2_va || !wq->rq.bar2_va)) { |
| 254 | off += 128 * (wq->rq.qid & rdev->qpmask) + 8; | 274 | pr_warn(MOD "%s: sqid %u or rqid %u not in BAR2 range.\n", |
| 255 | wq->rq.udb = (u64 __iomem *)(rdev->bar2_kva + off); | 275 | pci_name(rdev->lldi.pdev), wq->sq.qid, wq->rq.qid); |
| 256 | } | 276 | goto free_dma; |
| 257 | } | 277 | } |
| 278 | |||
| 258 | wq->rdev = rdev; | 279 | wq->rdev = rdev; |
| 259 | wq->rq.msn = 1; | 280 | wq->rq.msn = 1; |
| 260 | 281 | ||
| @@ -336,10 +357,9 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, | |||
| 336 | if (ret) | 357 | if (ret) |
| 337 | goto free_dma; | 358 | goto free_dma; |
| 338 | 359 | ||
| 339 | PDBG("%s sqid 0x%x rqid 0x%x kdb 0x%p squdb 0x%lx rqudb 0x%lx\n", | 360 | PDBG("%s sqid 0x%x rqid 0x%x kdb 0x%p sq_bar2_addr %p rq_bar2_addr %p\n", |
| 340 | __func__, wq->sq.qid, wq->rq.qid, wq->db, | 361 | __func__, wq->sq.qid, wq->rq.qid, wq->db, |
| 341 | (__force unsigned long) wq->sq.udb, | 362 | wq->sq.bar2_va, wq->rq.bar2_va); |
| 342 | (__force unsigned long) wq->rq.udb); | ||
| 343 | 363 | ||
| 344 | return 0; | 364 | return 0; |
| 345 | free_dma: | 365 | free_dma: |
| @@ -1766,11 +1786,11 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, | |||
| 1766 | mm2->len = PAGE_ALIGN(qhp->wq.rq.memsize); | 1786 | mm2->len = PAGE_ALIGN(qhp->wq.rq.memsize); |
| 1767 | insert_mmap(ucontext, mm2); | 1787 | insert_mmap(ucontext, mm2); |
| 1768 | mm3->key = uresp.sq_db_gts_key; | 1788 | mm3->key = uresp.sq_db_gts_key; |
| 1769 | mm3->addr = (__force unsigned long)qhp->wq.sq.udb; | 1789 | mm3->addr = (__force unsigned long)qhp->wq.sq.bar2_pa; |
| 1770 | mm3->len = PAGE_SIZE; | 1790 | mm3->len = PAGE_SIZE; |
| 1771 | insert_mmap(ucontext, mm3); | 1791 | insert_mmap(ucontext, mm3); |
| 1772 | mm4->key = uresp.rq_db_gts_key; | 1792 | mm4->key = uresp.rq_db_gts_key; |
| 1773 | mm4->addr = (__force unsigned long)qhp->wq.rq.udb; | 1793 | mm4->addr = (__force unsigned long)qhp->wq.rq.bar2_pa; |
| 1774 | mm4->len = PAGE_SIZE; | 1794 | mm4->len = PAGE_SIZE; |
| 1775 | insert_mmap(ucontext, mm4); | 1795 | insert_mmap(ucontext, mm4); |
| 1776 | if (mm5) { | 1796 | if (mm5) { |
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h index 7f2a6c244d25..274a7ab13bef 100644 --- a/drivers/infiniband/hw/cxgb4/t4.h +++ b/drivers/infiniband/hw/cxgb4/t4.h | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | 33 | ||
| 34 | #include "t4_hw.h" | 34 | #include "t4_hw.h" |
| 35 | #include "t4_regs.h" | 35 | #include "t4_regs.h" |
| 36 | #include "t4_values.h" | ||
| 36 | #include "t4_msg.h" | 37 | #include "t4_msg.h" |
| 37 | #include "t4fw_ri_api.h" | 38 | #include "t4fw_ri_api.h" |
| 38 | 39 | ||
| @@ -290,8 +291,10 @@ struct t4_sq { | |||
| 290 | unsigned long phys_addr; | 291 | unsigned long phys_addr; |
| 291 | struct t4_swsqe *sw_sq; | 292 | struct t4_swsqe *sw_sq; |
| 292 | struct t4_swsqe *oldest_read; | 293 | struct t4_swsqe *oldest_read; |
| 293 | u64 __iomem *udb; | 294 | void __iomem *bar2_va; |
| 295 | u64 bar2_pa; | ||
| 294 | size_t memsize; | 296 | size_t memsize; |
| 297 | u32 bar2_qid; | ||
| 295 | u32 qid; | 298 | u32 qid; |
| 296 | u16 in_use; | 299 | u16 in_use; |
| 297 | u16 size; | 300 | u16 size; |
| @@ -314,8 +317,10 @@ struct t4_rq { | |||
| 314 | dma_addr_t dma_addr; | 317 | dma_addr_t dma_addr; |
| 315 | DEFINE_DMA_UNMAP_ADDR(mapping); | 318 | DEFINE_DMA_UNMAP_ADDR(mapping); |
| 316 | struct t4_swrqe *sw_rq; | 319 | struct t4_swrqe *sw_rq; |
| 317 | u64 __iomem *udb; | 320 | void __iomem *bar2_va; |
| 321 | u64 bar2_pa; | ||
| 318 | size_t memsize; | 322 | size_t memsize; |
| 323 | u32 bar2_qid; | ||
| 319 | u32 qid; | 324 | u32 qid; |
| 320 | u32 msn; | 325 | u32 msn; |
| 321 | u32 rqt_hwaddr; | 326 | u32 rqt_hwaddr; |
| @@ -332,7 +337,6 @@ struct t4_wq { | |||
| 332 | struct t4_sq sq; | 337 | struct t4_sq sq; |
| 333 | struct t4_rq rq; | 338 | struct t4_rq rq; |
| 334 | void __iomem *db; | 339 | void __iomem *db; |
| 335 | void __iomem *gts; | ||
| 336 | struct c4iw_rdev *rdev; | 340 | struct c4iw_rdev *rdev; |
| 337 | int flushed; | 341 | int flushed; |
| 338 | }; | 342 | }; |
| @@ -457,15 +461,18 @@ static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc, u8 t5, | |||
| 457 | 461 | ||
| 458 | /* Flush host queue memory writes. */ | 462 | /* Flush host queue memory writes. */ |
| 459 | wmb(); | 463 | wmb(); |
| 460 | if (t5) { | 464 | if (wq->sq.bar2_va) { |
| 461 | if (inc == 1 && wqe) { | 465 | if (inc == 1 && wq->sq.bar2_qid == 0 && wqe) { |
| 462 | PDBG("%s: WC wq->sq.pidx = %d\n", | 466 | PDBG("%s: WC wq->sq.pidx = %d\n", |
| 463 | __func__, wq->sq.pidx); | 467 | __func__, wq->sq.pidx); |
| 464 | pio_copy(wq->sq.udb + 7, (void *)wqe); | 468 | pio_copy((u64 __iomem *) |
| 469 | (wq->sq.bar2_va + SGE_UDB_WCDOORBELL), | ||
| 470 | (u64 *)wqe); | ||
| 465 | } else { | 471 | } else { |
| 466 | PDBG("%s: DB wq->sq.pidx = %d\n", | 472 | PDBG("%s: DB wq->sq.pidx = %d\n", |
| 467 | __func__, wq->sq.pidx); | 473 | __func__, wq->sq.pidx); |
| 468 | writel(PIDX_T5_V(inc), wq->sq.udb); | 474 | writel(PIDX_T5_V(inc) | QID_V(wq->sq.bar2_qid), |
| 475 | wq->sq.bar2_va + SGE_UDB_KDOORBELL); | ||
| 469 | } | 476 | } |
| 470 | 477 | ||
| 471 | /* Flush user doorbell area writes. */ | 478 | /* Flush user doorbell area writes. */ |
| @@ -481,15 +488,18 @@ static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc, u8 t5, | |||
| 481 | 488 | ||
| 482 | /* Flush host queue memory writes. */ | 489 | /* Flush host queue memory writes. */ |
| 483 | wmb(); | 490 | wmb(); |
| 484 | if (t5) { | 491 | if (wq->rq.bar2_va) { |
| 485 | if (inc == 1 && wqe) { | 492 | if (inc == 1 && wq->rq.bar2_qid == 0 && wqe) { |
| 486 | PDBG("%s: WC wq->rq.pidx = %d\n", | 493 | PDBG("%s: WC wq->rq.pidx = %d\n", |
| 487 | __func__, wq->rq.pidx); | 494 | __func__, wq->rq.pidx); |
| 488 | pio_copy(wq->rq.udb + 7, (void *)wqe); | 495 | pio_copy((u64 __iomem *) |
| 496 | (wq->rq.bar2_va + SGE_UDB_WCDOORBELL), | ||
| 497 | (void *)wqe); | ||
| 489 | } else { | 498 | } else { |
| 490 | PDBG("%s: DB wq->rq.pidx = %d\n", | 499 | PDBG("%s: DB wq->rq.pidx = %d\n", |
| 491 | __func__, wq->rq.pidx); | 500 | __func__, wq->rq.pidx); |
| 492 | writel(PIDX_T5_V(inc), wq->rq.udb); | 501 | writel(PIDX_T5_V(inc) | QID_V(wq->rq.bar2_qid), |
| 502 | wq->rq.bar2_va + SGE_UDB_KDOORBELL); | ||
| 493 | } | 503 | } |
| 494 | 504 | ||
| 495 | /* Flush user doorbell area writes. */ | 505 | /* Flush user doorbell area writes. */ |
| @@ -534,8 +544,10 @@ struct t4_cq { | |||
| 534 | DEFINE_DMA_UNMAP_ADDR(mapping); | 544 | DEFINE_DMA_UNMAP_ADDR(mapping); |
| 535 | struct t4_cqe *sw_queue; | 545 | struct t4_cqe *sw_queue; |
| 536 | void __iomem *gts; | 546 | void __iomem *gts; |
| 547 | void __iomem *bar2_va; | ||
| 548 | u64 bar2_pa; | ||
| 549 | u32 bar2_qid; | ||
| 537 | struct c4iw_rdev *rdev; | 550 | struct c4iw_rdev *rdev; |
| 538 | u64 ugts; | ||
| 539 | size_t memsize; | 551 | size_t memsize; |
| 540 | __be64 bits_type_ts; | 552 | __be64 bits_type_ts; |
| 541 | u32 cqid; | 553 | u32 cqid; |
| @@ -552,6 +564,15 @@ struct t4_cq { | |||
| 552 | unsigned long flags; | 564 | unsigned long flags; |
| 553 | }; | 565 | }; |
| 554 | 566 | ||
| 567 | static inline void write_gts(struct t4_cq *cq, u32 val) | ||
| 568 | { | ||
| 569 | if (cq->bar2_va) | ||
| 570 | writel(val | INGRESSQID_V(cq->bar2_qid), | ||
| 571 | cq->bar2_va + SGE_UDB_GTS); | ||
| 572 | else | ||
| 573 | writel(val | INGRESSQID_V(cq->cqid), cq->gts); | ||
| 574 | } | ||
| 575 | |||
| 555 | static inline int t4_clear_cq_armed(struct t4_cq *cq) | 576 | static inline int t4_clear_cq_armed(struct t4_cq *cq) |
| 556 | { | 577 | { |
| 557 | return test_and_clear_bit(CQ_ARMED, &cq->flags); | 578 | return test_and_clear_bit(CQ_ARMED, &cq->flags); |
| @@ -563,14 +584,12 @@ static inline int t4_arm_cq(struct t4_cq *cq, int se) | |||
| 563 | 584 | ||
| 564 | set_bit(CQ_ARMED, &cq->flags); | 585 | set_bit(CQ_ARMED, &cq->flags); |
| 565 | while (cq->cidx_inc > CIDXINC_M) { | 586 | while (cq->cidx_inc > CIDXINC_M) { |
| 566 | val = SEINTARM_V(0) | CIDXINC_V(CIDXINC_M) | TIMERREG_V(7) | | 587 | val = SEINTARM_V(0) | CIDXINC_V(CIDXINC_M) | TIMERREG_V(7); |
| 567 | INGRESSQID_V(cq->cqid & cq->qid_mask); | 588 | write_gts(cq, val); |
| 568 | writel(val, cq->gts); | ||
| 569 | cq->cidx_inc -= CIDXINC_M; | 589 | cq->cidx_inc -= CIDXINC_M; |
| 570 | } | 590 | } |
| 571 | val = SEINTARM_V(se) | CIDXINC_V(cq->cidx_inc) | TIMERREG_V(6) | | 591 | val = SEINTARM_V(se) | CIDXINC_V(cq->cidx_inc) | TIMERREG_V(6); |
| 572 | INGRESSQID_V(cq->cqid & cq->qid_mask); | 592 | write_gts(cq, val); |
| 573 | writel(val, cq->gts); | ||
| 574 | cq->cidx_inc = 0; | 593 | cq->cidx_inc = 0; |
| 575 | return 0; | 594 | return 0; |
| 576 | } | 595 | } |
| @@ -601,9 +620,8 @@ static inline void t4_hwcq_consume(struct t4_cq *cq) | |||
| 601 | if (++cq->cidx_inc == (cq->size >> 4) || cq->cidx_inc == CIDXINC_M) { | 620 | if (++cq->cidx_inc == (cq->size >> 4) || cq->cidx_inc == CIDXINC_M) { |
| 602 | u32 val; | 621 | u32 val; |
| 603 | 622 | ||
| 604 | val = SEINTARM_V(0) | CIDXINC_V(cq->cidx_inc) | TIMERREG_V(7) | | 623 | val = SEINTARM_V(0) | CIDXINC_V(cq->cidx_inc) | TIMERREG_V(7); |
| 605 | INGRESSQID_V(cq->cqid & cq->qid_mask); | 624 | write_gts(cq, val); |
| 606 | writel(val, cq->gts); | ||
| 607 | cq->cidx_inc = 0; | 625 | cq->cidx_inc = 0; |
| 608 | } | 626 | } |
| 609 | if (++cq->cidx == cq->size) { | 627 | if (++cq->cidx == cq->size) { |
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c index 8cc837537768..9b68b175069b 100644 --- a/drivers/infiniband/hw/ehca/ehca_cq.c +++ b/drivers/infiniband/hw/ehca/ehca_cq.c | |||
| @@ -113,10 +113,12 @@ struct ehca_qp *ehca_cq_get_qp(struct ehca_cq *cq, int real_qp_num) | |||
| 113 | return ret; | 113 | return ret; |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector, | 116 | struct ib_cq *ehca_create_cq(struct ib_device *device, |
| 117 | const struct ib_cq_init_attr *attr, | ||
| 117 | struct ib_ucontext *context, | 118 | struct ib_ucontext *context, |
| 118 | struct ib_udata *udata) | 119 | struct ib_udata *udata) |
| 119 | { | 120 | { |
| 121 | int cqe = attr->cqe; | ||
| 120 | static const u32 additional_cqe = 20; | 122 | static const u32 additional_cqe = 20; |
| 121 | struct ib_cq *cq; | 123 | struct ib_cq *cq; |
| 122 | struct ehca_cq *my_cq; | 124 | struct ehca_cq *my_cq; |
| @@ -131,6 +133,9 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector, | |||
| 131 | int ipz_rc, i; | 133 | int ipz_rc, i; |
| 132 | unsigned long flags; | 134 | unsigned long flags; |
| 133 | 135 | ||
| 136 | if (attr->flags) | ||
| 137 | return ERR_PTR(-EINVAL); | ||
| 138 | |||
| 134 | if (cqe >= 0xFFFFFFFF - 64 - additional_cqe) | 139 | if (cqe >= 0xFFFFFFFF - 64 - additional_cqe) |
| 135 | return ERR_PTR(-EINVAL); | 140 | return ERR_PTR(-EINVAL); |
| 136 | 141 | ||
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c index 9ed4d2588304..e8b1bb65797a 100644 --- a/drivers/infiniband/hw/ehca/ehca_hca.c +++ b/drivers/infiniband/hw/ehca/ehca_hca.c | |||
| @@ -50,7 +50,8 @@ static unsigned int limit_uint(unsigned int value) | |||
| 50 | return min_t(unsigned int, value, INT_MAX); | 50 | return min_t(unsigned int, value, INT_MAX); |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) | 53 | int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props, |
| 54 | struct ib_udata *uhw) | ||
| 54 | { | 55 | { |
| 55 | int i, ret = 0; | 56 | int i, ret = 0; |
| 56 | struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, | 57 | struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, |
| @@ -71,6 +72,9 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) | |||
| 71 | IB_DEVICE_PORT_ACTIVE_EVENT, HCA_CAP_PORT_ACTIVE_EVENT, | 72 | IB_DEVICE_PORT_ACTIVE_EVENT, HCA_CAP_PORT_ACTIVE_EVENT, |
| 72 | }; | 73 | }; |
| 73 | 74 | ||
| 75 | if (uhw->inlen || uhw->outlen) | ||
| 76 | return -EINVAL; | ||
| 77 | |||
| 74 | rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); | 78 | rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); |
| 75 | if (!rblock) { | 79 | if (!rblock) { |
| 76 | ehca_err(&shca->ib_device, "Can't allocate rblock memory."); | 80 | ehca_err(&shca->ib_device, "Can't allocate rblock memory."); |
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h index 22f79afa7fc1..80e6a3d5df3e 100644 --- a/drivers/infiniband/hw/ehca/ehca_iverbs.h +++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h | |||
| @@ -44,11 +44,15 @@ | |||
| 44 | 44 | ||
| 45 | #include "ehca_classes.h" | 45 | #include "ehca_classes.h" |
| 46 | 46 | ||
| 47 | int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props); | 47 | int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props, |
| 48 | struct ib_udata *uhw); | ||
| 48 | 49 | ||
| 49 | int ehca_query_port(struct ib_device *ibdev, u8 port, | 50 | int ehca_query_port(struct ib_device *ibdev, u8 port, |
| 50 | struct ib_port_attr *props); | 51 | struct ib_port_attr *props); |
| 51 | 52 | ||
| 53 | enum rdma_protocol_type | ||
| 54 | ehca_query_protocol(struct ib_device *device, u8 port_num); | ||
| 55 | |||
| 52 | int ehca_query_sma_attr(struct ehca_shca *shca, u8 port, | 56 | int ehca_query_sma_attr(struct ehca_shca *shca, u8 port, |
| 53 | struct ehca_sma_attr *attr); | 57 | struct ehca_sma_attr *attr); |
| 54 | 58 | ||
| @@ -126,7 +130,8 @@ int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq); | |||
| 126 | void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq); | 130 | void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq); |
| 127 | 131 | ||
| 128 | 132 | ||
| 129 | struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector, | 133 | struct ib_cq *ehca_create_cq(struct ib_device *device, |
| 134 | const struct ib_cq_init_attr *attr, | ||
| 130 | struct ib_ucontext *context, | 135 | struct ib_ucontext *context, |
| 131 | struct ib_udata *udata); | 136 | struct ib_udata *udata); |
| 132 | 137 | ||
| @@ -188,9 +193,10 @@ int ehca_dealloc_ucontext(struct ib_ucontext *context); | |||
| 188 | int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); | 193 | int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); |
| 189 | 194 | ||
| 190 | int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | 195 | int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, |
| 191 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 196 | const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 192 | struct ib_mad *in_mad, | 197 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 193 | struct ib_mad *out_mad); | 198 | struct ib_mad_hdr *out, size_t *out_mad_size, |
| 199 | u16 *out_mad_pkey_index); | ||
| 194 | 200 | ||
| 195 | void ehca_poll_eqs(unsigned long data); | 201 | void ehca_poll_eqs(unsigned long data); |
| 196 | 202 | ||
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index cd8d290a09fc..8246418cd4e0 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |||
| @@ -46,6 +46,7 @@ | |||
| 46 | 46 | ||
| 47 | #include <linux/notifier.h> | 47 | #include <linux/notifier.h> |
| 48 | #include <linux/memory.h> | 48 | #include <linux/memory.h> |
| 49 | #include <rdma/ib_mad.h> | ||
| 49 | #include "ehca_classes.h" | 50 | #include "ehca_classes.h" |
| 50 | #include "ehca_iverbs.h" | 51 | #include "ehca_iverbs.h" |
| 51 | #include "ehca_mrmw.h" | 52 | #include "ehca_mrmw.h" |
| @@ -431,6 +432,24 @@ init_node_guid1: | |||
| 431 | return ret; | 432 | return ret; |
| 432 | } | 433 | } |
| 433 | 434 | ||
| 435 | static int ehca_port_immutable(struct ib_device *ibdev, u8 port_num, | ||
| 436 | struct ib_port_immutable *immutable) | ||
| 437 | { | ||
| 438 | struct ib_port_attr attr; | ||
| 439 | int err; | ||
| 440 | |||
| 441 | err = ehca_query_port(ibdev, port_num, &attr); | ||
| 442 | if (err) | ||
| 443 | return err; | ||
| 444 | |||
| 445 | immutable->pkey_tbl_len = attr.pkey_tbl_len; | ||
| 446 | immutable->gid_tbl_len = attr.gid_tbl_len; | ||
| 447 | immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB; | ||
| 448 | immutable->max_mad_size = IB_MGMT_MAD_SIZE; | ||
| 449 | |||
| 450 | return 0; | ||
| 451 | } | ||
| 452 | |||
| 434 | static int ehca_init_device(struct ehca_shca *shca) | 453 | static int ehca_init_device(struct ehca_shca *shca) |
| 435 | { | 454 | { |
| 436 | int ret; | 455 | int ret; |
| @@ -510,6 +529,7 @@ static int ehca_init_device(struct ehca_shca *shca) | |||
| 510 | shca->ib_device.process_mad = ehca_process_mad; | 529 | shca->ib_device.process_mad = ehca_process_mad; |
| 511 | shca->ib_device.mmap = ehca_mmap; | 530 | shca->ib_device.mmap = ehca_mmap; |
| 512 | shca->ib_device.dma_ops = &ehca_dma_mapping_ops; | 531 | shca->ib_device.dma_ops = &ehca_dma_mapping_ops; |
| 532 | shca->ib_device.get_port_immutable = ehca_port_immutable; | ||
| 513 | 533 | ||
| 514 | if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) { | 534 | if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) { |
| 515 | shca->ib_device.uverbs_cmd_mask |= | 535 | shca->ib_device.uverbs_cmd_mask |= |
| @@ -534,6 +554,7 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 port) | |||
| 534 | struct ib_cq *ibcq; | 554 | struct ib_cq *ibcq; |
| 535 | struct ib_qp *ibqp; | 555 | struct ib_qp *ibqp; |
| 536 | struct ib_qp_init_attr qp_init_attr; | 556 | struct ib_qp_init_attr qp_init_attr; |
| 557 | struct ib_cq_init_attr cq_attr = {}; | ||
| 537 | int ret; | 558 | int ret; |
| 538 | 559 | ||
| 539 | if (sport->ibcq_aqp1) { | 560 | if (sport->ibcq_aqp1) { |
| @@ -541,7 +562,9 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 port) | |||
| 541 | return -EPERM; | 562 | return -EPERM; |
| 542 | } | 563 | } |
| 543 | 564 | ||
| 544 | ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void *)(-1), 10, 0); | 565 | cq_attr.cqe = 10; |
| 566 | ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void *)(-1), | ||
| 567 | &cq_attr); | ||
| 545 | if (IS_ERR(ibcq)) { | 568 | if (IS_ERR(ibcq)) { |
| 546 | ehca_err(&shca->ib_device, "Cannot create AQP1 CQ."); | 569 | ehca_err(&shca->ib_device, "Cannot create AQP1 CQ."); |
| 547 | return PTR_ERR(ibcq); | 570 | return PTR_ERR(ibcq); |
diff --git a/drivers/infiniband/hw/ehca/ehca_sqp.c b/drivers/infiniband/hw/ehca/ehca_sqp.c index dba8f9f8b996..376b031c2c7f 100644 --- a/drivers/infiniband/hw/ehca/ehca_sqp.c +++ b/drivers/infiniband/hw/ehca/ehca_sqp.c | |||
| @@ -140,10 +140,10 @@ struct vertcfl { | |||
| 140 | } __attribute__ ((packed)); | 140 | } __attribute__ ((packed)); |
| 141 | 141 | ||
| 142 | static int ehca_process_perf(struct ib_device *ibdev, u8 port_num, | 142 | static int ehca_process_perf(struct ib_device *ibdev, u8 port_num, |
| 143 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 143 | const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 144 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 144 | const struct ib_mad *in_mad, struct ib_mad *out_mad) |
| 145 | { | 145 | { |
| 146 | struct ib_perf *in_perf = (struct ib_perf *)in_mad; | 146 | const struct ib_perf *in_perf = (const struct ib_perf *)in_mad; |
| 147 | struct ib_perf *out_perf = (struct ib_perf *)out_mad; | 147 | struct ib_perf *out_perf = (struct ib_perf *)out_mad; |
| 148 | struct ib_class_port_info *poi = | 148 | struct ib_class_port_info *poi = |
| 149 | (struct ib_class_port_info *)out_perf->data; | 149 | (struct ib_class_port_info *)out_perf->data; |
| @@ -187,8 +187,8 @@ static int ehca_process_perf(struct ib_device *ibdev, u8 port_num, | |||
| 187 | 187 | ||
| 188 | /* if request was globally routed, copy route info */ | 188 | /* if request was globally routed, copy route info */ |
| 189 | if (in_grh) { | 189 | if (in_grh) { |
| 190 | struct vertcfl *vertcfl = | 190 | const struct vertcfl *vertcfl = |
| 191 | (struct vertcfl *)&in_grh->version_tclass_flow; | 191 | (const struct vertcfl *)&in_grh->version_tclass_flow; |
| 192 | memcpy(poi->redirect_gid, in_grh->dgid.raw, | 192 | memcpy(poi->redirect_gid, in_grh->dgid.raw, |
| 193 | sizeof(poi->redirect_gid)); | 193 | sizeof(poi->redirect_gid)); |
| 194 | tcslfl->tc = vertcfl->tc; | 194 | tcslfl->tc = vertcfl->tc; |
| @@ -217,10 +217,18 @@ perf_reply: | |||
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | 219 | int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, |
| 220 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 220 | const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 221 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 221 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 222 | struct ib_mad_hdr *out, size_t *out_mad_size, | ||
| 223 | u16 *out_mad_pkey_index) | ||
| 222 | { | 224 | { |
| 223 | int ret; | 225 | int ret; |
| 226 | const struct ib_mad *in_mad = (const struct ib_mad *)in; | ||
| 227 | struct ib_mad *out_mad = (struct ib_mad *)out; | ||
| 228 | |||
| 229 | if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || | ||
| 230 | *out_mad_size != sizeof(*out_mad))) | ||
| 231 | return IB_MAD_RESULT_FAILURE; | ||
| 224 | 232 | ||
| 225 | if (!port_num || port_num > ibdev->phys_port_cnt || !in_wc) | 233 | if (!port_num || port_num > ibdev->phys_port_cnt || !in_wc) |
| 226 | return IB_MAD_RESULT_FAILURE; | 234 | return IB_MAD_RESULT_FAILURE; |
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.c b/drivers/infiniband/hw/ehca/ipz_pt_fn.c index 8d594517cd29..7ffc748cb973 100644 --- a/drivers/infiniband/hw/ehca/ipz_pt_fn.c +++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.c | |||
| @@ -245,10 +245,7 @@ int ipz_queue_ctor(struct ehca_pd *pd, struct ipz_queue *queue, | |||
| 245 | ipz_queue_ctor_exit0: | 245 | ipz_queue_ctor_exit0: |
| 246 | ehca_gen_err("Couldn't alloc pages queue=%p " | 246 | ehca_gen_err("Couldn't alloc pages queue=%p " |
| 247 | "nr_of_pages=%x", queue, nr_of_pages); | 247 | "nr_of_pages=%x", queue, nr_of_pages); |
| 248 | if (is_vmalloc_addr(queue->queue_pages)) | 248 | kvfree(queue->queue_pages); |
| 249 | vfree(queue->queue_pages); | ||
| 250 | else | ||
| 251 | kfree(queue->queue_pages); | ||
| 252 | 249 | ||
| 253 | return 0; | 250 | return 0; |
| 254 | } | 251 | } |
| @@ -270,10 +267,7 @@ int ipz_queue_dtor(struct ehca_pd *pd, struct ipz_queue *queue) | |||
| 270 | free_page((unsigned long)queue->queue_pages[i]); | 267 | free_page((unsigned long)queue->queue_pages[i]); |
| 271 | } | 268 | } |
| 272 | 269 | ||
| 273 | if (is_vmalloc_addr(queue->queue_pages)) | 270 | kvfree(queue->queue_pages); |
| 274 | vfree(queue->queue_pages); | ||
| 275 | else | ||
| 276 | kfree(queue->queue_pages); | ||
| 277 | 271 | ||
| 278 | return 1; | 272 | return 1; |
| 279 | } | 273 | } |
diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c index 0416c6c0e126..e9dd9112e718 100644 --- a/drivers/infiniband/hw/ipath/ipath_cq.c +++ b/drivers/infiniband/hw/ipath/ipath_cq.c | |||
| @@ -188,7 +188,7 @@ static void send_complete(unsigned long data) | |||
| 188 | /** | 188 | /** |
| 189 | * ipath_create_cq - create a completion queue | 189 | * ipath_create_cq - create a completion queue |
| 190 | * @ibdev: the device this completion queue is attached to | 190 | * @ibdev: the device this completion queue is attached to |
| 191 | * @entries: the minimum size of the completion queue | 191 | * @attr: creation attributes |
| 192 | * @context: unused by the InfiniPath driver | 192 | * @context: unused by the InfiniPath driver |
| 193 | * @udata: unused by the InfiniPath driver | 193 | * @udata: unused by the InfiniPath driver |
| 194 | * | 194 | * |
| @@ -197,16 +197,21 @@ static void send_complete(unsigned long data) | |||
| 197 | * | 197 | * |
| 198 | * Called by ib_create_cq() in the generic verbs code. | 198 | * Called by ib_create_cq() in the generic verbs code. |
| 199 | */ | 199 | */ |
| 200 | struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries, int comp_vector, | 200 | struct ib_cq *ipath_create_cq(struct ib_device *ibdev, |
| 201 | const struct ib_cq_init_attr *attr, | ||
| 201 | struct ib_ucontext *context, | 202 | struct ib_ucontext *context, |
| 202 | struct ib_udata *udata) | 203 | struct ib_udata *udata) |
| 203 | { | 204 | { |
| 205 | int entries = attr->cqe; | ||
| 204 | struct ipath_ibdev *dev = to_idev(ibdev); | 206 | struct ipath_ibdev *dev = to_idev(ibdev); |
| 205 | struct ipath_cq *cq; | 207 | struct ipath_cq *cq; |
| 206 | struct ipath_cq_wc *wc; | 208 | struct ipath_cq_wc *wc; |
| 207 | struct ib_cq *ret; | 209 | struct ib_cq *ret; |
| 208 | u32 sz; | 210 | u32 sz; |
| 209 | 211 | ||
| 212 | if (attr->flags) | ||
| 213 | return ERR_PTR(-EINVAL); | ||
| 214 | |||
| 210 | if (entries < 1 || entries > ib_ipath_max_cqes) { | 215 | if (entries < 1 || entries > ib_ipath_max_cqes) { |
| 211 | ret = ERR_PTR(-EINVAL); | 216 | ret = ERR_PTR(-EINVAL); |
| 212 | goto done; | 217 | goto done; |
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 2d7e503d13cb..871dbe56216a 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
| @@ -31,6 +31,8 @@ | |||
| 31 | * SOFTWARE. | 31 | * SOFTWARE. |
| 32 | */ | 32 | */ |
| 33 | 33 | ||
| 34 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 35 | |||
| 34 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
| 35 | #include <linux/spinlock.h> | 37 | #include <linux/spinlock.h> |
| 36 | #include <linux/idr.h> | 38 | #include <linux/idr.h> |
| @@ -399,8 +401,8 @@ static int ipath_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 399 | u32 bar0 = 0, bar1 = 0; | 401 | u32 bar0 = 0, bar1 = 0; |
| 400 | 402 | ||
| 401 | #ifdef CONFIG_X86_64 | 403 | #ifdef CONFIG_X86_64 |
| 402 | if (WARN(pat_enabled(), | 404 | if (pat_enabled()) { |
| 403 | "ipath needs PAT disabled, boot with nopat kernel parameter\n")) { | 405 | pr_warn("ipath needs PAT disabled, boot with nopat kernel parameter\n"); |
| 404 | ret = -ENODEV; | 406 | ret = -ENODEV; |
| 405 | goto bail; | 407 | goto bail; |
| 406 | } | 408 | } |
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index 1ca8e32a9592..25422a3a7238 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c | |||
| @@ -277,7 +277,7 @@ static int remove_file(struct dentry *parent, char *name) | |||
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | spin_lock(&tmp->d_lock); | 279 | spin_lock(&tmp->d_lock); |
| 280 | if (!d_unhashed(tmp) && d_really_is_positive(tmp)) { | 280 | if (simple_positive(tmp)) { |
| 281 | dget_dlock(tmp); | 281 | dget_dlock(tmp); |
| 282 | __d_drop(tmp); | 282 | __d_drop(tmp); |
| 283 | spin_unlock(&tmp->d_lock); | 283 | spin_unlock(&tmp->d_lock); |
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c index e890e5ba0e01..ad3a926ab3c5 100644 --- a/drivers/infiniband/hw/ipath/ipath_mad.c +++ b/drivers/infiniband/hw/ipath/ipath_mad.c | |||
| @@ -1257,7 +1257,7 @@ static int recv_pma_set_portcounters_ext(struct ib_pma_mad *pmp, | |||
| 1257 | } | 1257 | } |
| 1258 | 1258 | ||
| 1259 | static int process_subn(struct ib_device *ibdev, int mad_flags, | 1259 | static int process_subn(struct ib_device *ibdev, int mad_flags, |
| 1260 | u8 port_num, struct ib_mad *in_mad, | 1260 | u8 port_num, const struct ib_mad *in_mad, |
| 1261 | struct ib_mad *out_mad) | 1261 | struct ib_mad *out_mad) |
| 1262 | { | 1262 | { |
| 1263 | struct ib_smp *smp = (struct ib_smp *)out_mad; | 1263 | struct ib_smp *smp = (struct ib_smp *)out_mad; |
| @@ -1389,7 +1389,7 @@ bail: | |||
| 1389 | } | 1389 | } |
| 1390 | 1390 | ||
| 1391 | static int process_perf(struct ib_device *ibdev, u8 port_num, | 1391 | static int process_perf(struct ib_device *ibdev, u8 port_num, |
| 1392 | struct ib_mad *in_mad, | 1392 | const struct ib_mad *in_mad, |
| 1393 | struct ib_mad *out_mad) | 1393 | struct ib_mad *out_mad) |
| 1394 | { | 1394 | { |
| 1395 | struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad; | 1395 | struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad; |
| @@ -1490,10 +1490,18 @@ bail: | |||
| 1490 | * This is called by the ib_mad module. | 1490 | * This is called by the ib_mad module. |
| 1491 | */ | 1491 | */ |
| 1492 | int ipath_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | 1492 | int ipath_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, |
| 1493 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 1493 | const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 1494 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 1494 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 1495 | struct ib_mad_hdr *out, size_t *out_mad_size, | ||
| 1496 | u16 *out_mad_pkey_index) | ||
| 1495 | { | 1497 | { |
| 1496 | int ret; | 1498 | int ret; |
| 1499 | const struct ib_mad *in_mad = (const struct ib_mad *)in; | ||
| 1500 | struct ib_mad *out_mad = (struct ib_mad *)out; | ||
| 1501 | |||
| 1502 | if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || | ||
| 1503 | *out_mad_size != sizeof(*out_mad))) | ||
| 1504 | return IB_MAD_RESULT_FAILURE; | ||
| 1497 | 1505 | ||
| 1498 | switch (in_mad->mad_hdr.mgmt_class) { | 1506 | switch (in_mad->mad_hdr.mgmt_class) { |
| 1499 | case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: | 1507 | case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index 44ea9390417c..30ba49c4a98c 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c | |||
| @@ -1495,11 +1495,14 @@ bail: | |||
| 1495 | return 0; | 1495 | return 0; |
| 1496 | } | 1496 | } |
| 1497 | 1497 | ||
| 1498 | static int ipath_query_device(struct ib_device *ibdev, | 1498 | static int ipath_query_device(struct ib_device *ibdev, struct ib_device_attr *props, |
| 1499 | struct ib_device_attr *props) | 1499 | struct ib_udata *uhw) |
| 1500 | { | 1500 | { |
| 1501 | struct ipath_ibdev *dev = to_idev(ibdev); | 1501 | struct ipath_ibdev *dev = to_idev(ibdev); |
| 1502 | 1502 | ||
| 1503 | if (uhw->inlen || uhw->outlen) | ||
| 1504 | return -EINVAL; | ||
| 1505 | |||
| 1503 | memset(props, 0, sizeof(*props)); | 1506 | memset(props, 0, sizeof(*props)); |
| 1504 | 1507 | ||
| 1505 | props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR | | 1508 | props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR | |
| @@ -1980,6 +1983,24 @@ static int disable_timer(struct ipath_devdata *dd) | |||
| 1980 | return 0; | 1983 | return 0; |
| 1981 | } | 1984 | } |
| 1982 | 1985 | ||
| 1986 | static int ipath_port_immutable(struct ib_device *ibdev, u8 port_num, | ||
| 1987 | struct ib_port_immutable *immutable) | ||
| 1988 | { | ||
| 1989 | struct ib_port_attr attr; | ||
| 1990 | int err; | ||
| 1991 | |||
| 1992 | err = ipath_query_port(ibdev, port_num, &attr); | ||
| 1993 | if (err) | ||
| 1994 | return err; | ||
| 1995 | |||
| 1996 | immutable->pkey_tbl_len = attr.pkey_tbl_len; | ||
| 1997 | immutable->gid_tbl_len = attr.gid_tbl_len; | ||
| 1998 | immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB; | ||
| 1999 | immutable->max_mad_size = IB_MGMT_MAD_SIZE; | ||
| 2000 | |||
| 2001 | return 0; | ||
| 2002 | } | ||
| 2003 | |||
| 1983 | /** | 2004 | /** |
| 1984 | * ipath_register_ib_device - register our device with the infiniband core | 2005 | * ipath_register_ib_device - register our device with the infiniband core |
| 1985 | * @dd: the device data structure | 2006 | * @dd: the device data structure |
| @@ -2023,9 +2044,9 @@ int ipath_register_ib_device(struct ipath_devdata *dd) | |||
| 2023 | 2044 | ||
| 2024 | spin_lock_init(&idev->qp_table.lock); | 2045 | spin_lock_init(&idev->qp_table.lock); |
| 2025 | spin_lock_init(&idev->lk_table.lock); | 2046 | spin_lock_init(&idev->lk_table.lock); |
| 2026 | idev->sm_lid = __constant_be16_to_cpu(IB_LID_PERMISSIVE); | 2047 | idev->sm_lid = be16_to_cpu(IB_LID_PERMISSIVE); |
| 2027 | /* Set the prefix to the default value (see ch. 4.1.1) */ | 2048 | /* Set the prefix to the default value (see ch. 4.1.1) */ |
| 2028 | idev->gid_prefix = __constant_cpu_to_be64(0xfe80000000000000ULL); | 2049 | idev->gid_prefix = cpu_to_be64(0xfe80000000000000ULL); |
| 2029 | 2050 | ||
| 2030 | ret = ipath_init_qp_table(idev, ib_ipath_qp_table_size); | 2051 | ret = ipath_init_qp_table(idev, ib_ipath_qp_table_size); |
| 2031 | if (ret) | 2052 | if (ret) |
| @@ -2179,6 +2200,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd) | |||
| 2179 | dev->process_mad = ipath_process_mad; | 2200 | dev->process_mad = ipath_process_mad; |
| 2180 | dev->mmap = ipath_mmap; | 2201 | dev->mmap = ipath_mmap; |
| 2181 | dev->dma_ops = &ipath_dma_mapping_ops; | 2202 | dev->dma_ops = &ipath_dma_mapping_ops; |
| 2203 | dev->get_port_immutable = ipath_port_immutable; | ||
| 2182 | 2204 | ||
| 2183 | snprintf(dev->node_desc, sizeof(dev->node_desc), | 2205 | snprintf(dev->node_desc, sizeof(dev->node_desc), |
| 2184 | IPATH_IDSTR " %s", init_utsname()->nodename); | 2206 | IPATH_IDSTR " %s", init_utsname()->nodename); |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h index ae6cff4abffc..ec167e545e15 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.h +++ b/drivers/infiniband/hw/ipath/ipath_verbs.h | |||
| @@ -701,9 +701,11 @@ static inline void ipath_schedule_send(struct ipath_qp *qp) | |||
| 701 | int ipath_process_mad(struct ib_device *ibdev, | 701 | int ipath_process_mad(struct ib_device *ibdev, |
| 702 | int mad_flags, | 702 | int mad_flags, |
| 703 | u8 port_num, | 703 | u8 port_num, |
| 704 | struct ib_wc *in_wc, | 704 | const struct ib_wc *in_wc, |
| 705 | struct ib_grh *in_grh, | 705 | const struct ib_grh *in_grh, |
| 706 | struct ib_mad *in_mad, struct ib_mad *out_mad); | 706 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 707 | struct ib_mad_hdr *out, size_t *out_mad_size, | ||
| 708 | u16 *out_mad_pkey_index); | ||
| 707 | 709 | ||
| 708 | /* | 710 | /* |
| 709 | * Compare the lower 24 bits of the two values. | 711 | * Compare the lower 24 bits of the two values. |
| @@ -807,7 +809,8 @@ void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig); | |||
| 807 | 809 | ||
| 808 | int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry); | 810 | int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry); |
| 809 | 811 | ||
| 810 | struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries, int comp_vector, | 812 | struct ib_cq *ipath_create_cq(struct ib_device *ibdev, |
| 813 | const struct ib_cq_init_attr *attr, | ||
| 811 | struct ib_ucontext *context, | 814 | struct ib_ucontext *context, |
| 812 | struct ib_udata *udata); | 815 | struct ib_udata *udata); |
| 813 | 816 | ||
diff --git a/drivers/infiniband/hw/mlx4/alias_GUID.c b/drivers/infiniband/hw/mlx4/alias_GUID.c index 0f00204d2ece..21cb41a60fe8 100644 --- a/drivers/infiniband/hw/mlx4/alias_GUID.c +++ b/drivers/infiniband/hw/mlx4/alias_GUID.c | |||
| @@ -189,7 +189,7 @@ void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev, | |||
| 189 | { | 189 | { |
| 190 | int i; | 190 | int i; |
| 191 | u64 guid_indexes; | 191 | u64 guid_indexes; |
| 192 | int slave_id; | 192 | int slave_id, slave_port; |
| 193 | enum slave_port_state new_state; | 193 | enum slave_port_state new_state; |
| 194 | enum slave_port_state prev_state; | 194 | enum slave_port_state prev_state; |
| 195 | __be64 tmp_cur_ag, form_cache_ag; | 195 | __be64 tmp_cur_ag, form_cache_ag; |
| @@ -217,6 +217,11 @@ void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev, | |||
| 217 | slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ; | 217 | slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ; |
| 218 | if (slave_id >= dev->dev->persist->num_vfs + 1) | 218 | if (slave_id >= dev->dev->persist->num_vfs + 1) |
| 219 | return; | 219 | return; |
| 220 | |||
| 221 | slave_port = mlx4_phys_to_slave_port(dev->dev, slave_id, port_num); | ||
| 222 | if (slave_port < 0) /* this port isn't available for the VF */ | ||
| 223 | continue; | ||
| 224 | |||
| 220 | tmp_cur_ag = *(__be64 *)&p_data[i * GUID_REC_SIZE]; | 225 | tmp_cur_ag = *(__be64 *)&p_data[i * GUID_REC_SIZE]; |
| 221 | form_cache_ag = get_cached_alias_guid(dev, port_num, | 226 | form_cache_ag = get_cached_alias_guid(dev, port_num, |
| 222 | (NUM_ALIAS_GUID_IN_REC * block_num) + i); | 227 | (NUM_ALIAS_GUID_IN_REC * block_num) + i); |
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c index 0176caa5792c..36eb3d012b6d 100644 --- a/drivers/infiniband/hw/mlx4/cq.c +++ b/drivers/infiniband/hw/mlx4/cq.c | |||
| @@ -166,10 +166,14 @@ err_buf: | |||
| 166 | return err; | 166 | return err; |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector, | 169 | #define CQ_CREATE_FLAGS_SUPPORTED IB_CQ_FLAGS_TIMESTAMP_COMPLETION |
| 170 | struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, | ||
| 171 | const struct ib_cq_init_attr *attr, | ||
| 170 | struct ib_ucontext *context, | 172 | struct ib_ucontext *context, |
| 171 | struct ib_udata *udata) | 173 | struct ib_udata *udata) |
| 172 | { | 174 | { |
| 175 | int entries = attr->cqe; | ||
| 176 | int vector = attr->comp_vector; | ||
| 173 | struct mlx4_ib_dev *dev = to_mdev(ibdev); | 177 | struct mlx4_ib_dev *dev = to_mdev(ibdev); |
| 174 | struct mlx4_ib_cq *cq; | 178 | struct mlx4_ib_cq *cq; |
| 175 | struct mlx4_uar *uar; | 179 | struct mlx4_uar *uar; |
| @@ -178,6 +182,9 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector | |||
| 178 | if (entries < 1 || entries > dev->dev->caps.max_cqes) | 182 | if (entries < 1 || entries > dev->dev->caps.max_cqes) |
| 179 | return ERR_PTR(-EINVAL); | 183 | return ERR_PTR(-EINVAL); |
| 180 | 184 | ||
| 185 | if (attr->flags & ~CQ_CREATE_FLAGS_SUPPORTED) | ||
| 186 | return ERR_PTR(-EINVAL); | ||
| 187 | |||
| 181 | cq = kmalloc(sizeof *cq, GFP_KERNEL); | 188 | cq = kmalloc(sizeof *cq, GFP_KERNEL); |
| 182 | if (!cq) | 189 | if (!cq) |
| 183 | return ERR_PTR(-ENOMEM); | 190 | return ERR_PTR(-ENOMEM); |
| @@ -188,6 +195,7 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector | |||
| 188 | spin_lock_init(&cq->lock); | 195 | spin_lock_init(&cq->lock); |
| 189 | cq->resize_buf = NULL; | 196 | cq->resize_buf = NULL; |
| 190 | cq->resize_umem = NULL; | 197 | cq->resize_umem = NULL; |
| 198 | cq->create_flags = attr->flags; | ||
| 191 | INIT_LIST_HEAD(&cq->send_qp_list); | 199 | INIT_LIST_HEAD(&cq->send_qp_list); |
| 192 | INIT_LIST_HEAD(&cq->recv_qp_list); | 200 | INIT_LIST_HEAD(&cq->recv_qp_list); |
| 193 | 201 | ||
| @@ -231,7 +239,8 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector | |||
| 231 | vector = dev->eq_table[vector % ibdev->num_comp_vectors]; | 239 | vector = dev->eq_table[vector % ibdev->num_comp_vectors]; |
| 232 | 240 | ||
| 233 | err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar, | 241 | err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar, |
| 234 | cq->db.dma, &cq->mcq, vector, 0, 0); | 242 | cq->db.dma, &cq->mcq, vector, 0, |
| 243 | !!(cq->create_flags & IB_CQ_FLAGS_TIMESTAMP_COMPLETION)); | ||
| 235 | if (err) | 244 | if (err) |
| 236 | goto err_dbmap; | 245 | goto err_dbmap; |
| 237 | 246 | ||
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 9cd2b002d7ae..68b3dfa922bf 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c | |||
| @@ -64,14 +64,6 @@ enum { | |||
| 64 | #define GUID_TBL_BLK_NUM_ENTRIES 8 | 64 | #define GUID_TBL_BLK_NUM_ENTRIES 8 |
| 65 | #define GUID_TBL_BLK_SIZE (GUID_TBL_ENTRY_SIZE * GUID_TBL_BLK_NUM_ENTRIES) | 65 | #define GUID_TBL_BLK_SIZE (GUID_TBL_ENTRY_SIZE * GUID_TBL_BLK_NUM_ENTRIES) |
| 66 | 66 | ||
| 67 | /* Counters should be saturate once they reach their maximum value */ | ||
| 68 | #define ASSIGN_32BIT_COUNTER(counter, value) do {\ | ||
| 69 | if ((value) > U32_MAX) \ | ||
| 70 | counter = cpu_to_be32(U32_MAX); \ | ||
| 71 | else \ | ||
| 72 | counter = cpu_to_be32(value); \ | ||
| 73 | } while (0) | ||
| 74 | |||
| 75 | struct mlx4_mad_rcv_buf { | 67 | struct mlx4_mad_rcv_buf { |
| 76 | struct ib_grh grh; | 68 | struct ib_grh grh; |
| 77 | u8 payload[256]; | 69 | u8 payload[256]; |
| @@ -111,8 +103,9 @@ __be64 mlx4_ib_get_new_demux_tid(struct mlx4_ib_demux_ctx *ctx) | |||
| 111 | } | 103 | } |
| 112 | 104 | ||
| 113 | int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int mad_ifc_flags, | 105 | int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int mad_ifc_flags, |
| 114 | int port, struct ib_wc *in_wc, struct ib_grh *in_grh, | 106 | int port, const struct ib_wc *in_wc, |
| 115 | void *in_mad, void *response_mad) | 107 | const struct ib_grh *in_grh, |
| 108 | const void *in_mad, void *response_mad) | ||
| 116 | { | 109 | { |
| 117 | struct mlx4_cmd_mailbox *inmailbox, *outmailbox; | 110 | struct mlx4_cmd_mailbox *inmailbox, *outmailbox; |
| 118 | void *inbox; | 111 | void *inbox; |
| @@ -220,7 +213,7 @@ static void update_sm_ah(struct mlx4_ib_dev *dev, u8 port_num, u16 lid, u8 sl) | |||
| 220 | * Snoop SM MADs for port info, GUID info, and P_Key table sets, so we can | 213 | * Snoop SM MADs for port info, GUID info, and P_Key table sets, so we can |
| 221 | * synthesize LID change, Client-Rereg, GID change, and P_Key change events. | 214 | * synthesize LID change, Client-Rereg, GID change, and P_Key change events. |
| 222 | */ | 215 | */ |
| 223 | static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad, | 216 | static void smp_snoop(struct ib_device *ibdev, u8 port_num, const struct ib_mad *mad, |
| 224 | u16 prev_lid) | 217 | u16 prev_lid) |
| 225 | { | 218 | { |
| 226 | struct ib_port_info *pinfo; | 219 | struct ib_port_info *pinfo; |
| @@ -356,7 +349,7 @@ static void node_desc_override(struct ib_device *dev, | |||
| 356 | } | 349 | } |
| 357 | } | 350 | } |
| 358 | 351 | ||
| 359 | static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *mad) | 352 | static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, const struct ib_mad *mad) |
| 360 | { | 353 | { |
| 361 | int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED; | 354 | int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED; |
| 362 | struct ib_mad_send_buf *send_buf; | 355 | struct ib_mad_send_buf *send_buf; |
| @@ -366,7 +359,8 @@ static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *ma | |||
| 366 | 359 | ||
| 367 | if (agent) { | 360 | if (agent) { |
| 368 | send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR, | 361 | send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR, |
| 369 | IB_MGMT_MAD_DATA, GFP_ATOMIC); | 362 | IB_MGMT_MAD_DATA, GFP_ATOMIC, |
| 363 | IB_MGMT_BASE_VERSION); | ||
| 370 | if (IS_ERR(send_buf)) | 364 | if (IS_ERR(send_buf)) |
| 371 | return; | 365 | return; |
| 372 | /* | 366 | /* |
| @@ -722,8 +716,8 @@ static int mlx4_ib_demux_mad(struct ib_device *ibdev, u8 port, | |||
| 722 | } | 716 | } |
| 723 | 717 | ||
| 724 | static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | 718 | static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, |
| 725 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 719 | const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 726 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 720 | const struct ib_mad *in_mad, struct ib_mad *out_mad) |
| 727 | { | 721 | { |
| 728 | u16 slid, prev_lid = 0; | 722 | u16 slid, prev_lid = 0; |
| 729 | int err; | 723 | int err; |
| @@ -825,34 +819,28 @@ static void edit_counter(struct mlx4_counter *cnt, | |||
| 825 | } | 819 | } |
| 826 | 820 | ||
| 827 | static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | 821 | static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, |
| 828 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 822 | const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 829 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 823 | const struct ib_mad *in_mad, struct ib_mad *out_mad) |
| 830 | { | 824 | { |
| 831 | struct mlx4_cmd_mailbox *mailbox; | 825 | struct mlx4_counter counter_stats; |
| 832 | struct mlx4_ib_dev *dev = to_mdev(ibdev); | 826 | struct mlx4_ib_dev *dev = to_mdev(ibdev); |
| 833 | int err; | 827 | int err; |
| 834 | u32 inmod = dev->counters[port_num - 1] & 0xffff; | ||
| 835 | u8 mode; | ||
| 836 | 828 | ||
| 837 | if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_PERF_MGMT) | 829 | if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_PERF_MGMT) |
| 838 | return -EINVAL; | 830 | return -EINVAL; |
| 839 | 831 | ||
| 840 | mailbox = mlx4_alloc_cmd_mailbox(dev->dev); | 832 | memset(&counter_stats, 0, sizeof(counter_stats)); |
| 841 | if (IS_ERR(mailbox)) | 833 | err = mlx4_get_counter_stats(dev->dev, |
| 842 | return IB_MAD_RESULT_FAILURE; | 834 | dev->counters[port_num - 1].index, |
| 843 | 835 | &counter_stats, 0); | |
| 844 | err = mlx4_cmd_box(dev->dev, 0, mailbox->dma, inmod, 0, | ||
| 845 | MLX4_CMD_QUERY_IF_STAT, MLX4_CMD_TIME_CLASS_C, | ||
| 846 | MLX4_CMD_WRAPPED); | ||
| 847 | if (err) | 836 | if (err) |
| 848 | err = IB_MAD_RESULT_FAILURE; | 837 | err = IB_MAD_RESULT_FAILURE; |
| 849 | else { | 838 | else { |
| 850 | memset(out_mad->data, 0, sizeof out_mad->data); | 839 | memset(out_mad->data, 0, sizeof out_mad->data); |
| 851 | mode = ((struct mlx4_counter *)mailbox->buf)->counter_mode; | 840 | switch (counter_stats.counter_mode & 0xf) { |
| 852 | switch (mode & 0xf) { | ||
| 853 | case 0: | 841 | case 0: |
| 854 | edit_counter(mailbox->buf, | 842 | edit_counter(&counter_stats, |
| 855 | (void *)(out_mad->data + 40)); | 843 | (void *)(out_mad->data + 40)); |
| 856 | err = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; | 844 | err = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; |
| 857 | break; | 845 | break; |
| 858 | default: | 846 | default: |
| @@ -860,25 +848,43 @@ static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | |||
| 860 | } | 848 | } |
| 861 | } | 849 | } |
| 862 | 850 | ||
| 863 | mlx4_free_cmd_mailbox(dev->dev, mailbox); | ||
| 864 | |||
| 865 | return err; | 851 | return err; |
| 866 | } | 852 | } |
| 867 | 853 | ||
| 868 | int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | 854 | int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, |
| 869 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 855 | const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 870 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 856 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 857 | struct ib_mad_hdr *out, size_t *out_mad_size, | ||
| 858 | u16 *out_mad_pkey_index) | ||
| 871 | { | 859 | { |
| 872 | switch (rdma_port_get_link_layer(ibdev, port_num)) { | 860 | struct mlx4_ib_dev *dev = to_mdev(ibdev); |
| 873 | case IB_LINK_LAYER_INFINIBAND: | 861 | const struct ib_mad *in_mad = (const struct ib_mad *)in; |
| 862 | struct ib_mad *out_mad = (struct ib_mad *)out; | ||
| 863 | enum rdma_link_layer link = rdma_port_get_link_layer(ibdev, port_num); | ||
| 864 | |||
| 865 | if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || | ||
| 866 | *out_mad_size != sizeof(*out_mad))) | ||
| 867 | return IB_MAD_RESULT_FAILURE; | ||
| 868 | |||
| 869 | /* iboe_process_mad() which uses the HCA flow-counters to implement IB PMA | ||
| 870 | * queries, should be called only by VFs and for that specific purpose | ||
| 871 | */ | ||
| 872 | if (link == IB_LINK_LAYER_INFINIBAND) { | ||
| 873 | if (mlx4_is_slave(dev->dev) && | ||
| 874 | in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT && | ||
| 875 | in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS) | ||
| 876 | return iboe_process_mad(ibdev, mad_flags, port_num, in_wc, | ||
| 877 | in_grh, in_mad, out_mad); | ||
| 878 | |||
| 874 | return ib_process_mad(ibdev, mad_flags, port_num, in_wc, | 879 | return ib_process_mad(ibdev, mad_flags, port_num, in_wc, |
| 875 | in_grh, in_mad, out_mad); | 880 | in_grh, in_mad, out_mad); |
| 876 | case IB_LINK_LAYER_ETHERNET: | ||
| 877 | return iboe_process_mad(ibdev, mad_flags, port_num, in_wc, | ||
| 878 | in_grh, in_mad, out_mad); | ||
| 879 | default: | ||
| 880 | return -EINVAL; | ||
| 881 | } | 881 | } |
| 882 | |||
| 883 | if (link == IB_LINK_LAYER_ETHERNET) | ||
| 884 | return iboe_process_mad(ibdev, mad_flags, port_num, in_wc, | ||
| 885 | in_grh, in_mad, out_mad); | ||
| 886 | |||
| 887 | return -EINVAL; | ||
| 882 | } | 888 | } |
| 883 | 889 | ||
| 884 | static void send_handler(struct ib_mad_agent *agent, | 890 | static void send_handler(struct ib_mad_agent *agent, |
| @@ -1365,14 +1371,17 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc | |||
| 1365 | * stadard address handle by decoding the tunnelled mlx4_ah fields */ | 1371 | * stadard address handle by decoding the tunnelled mlx4_ah fields */ |
| 1366 | memcpy(&ah.av, &tunnel->hdr.av, sizeof (struct mlx4_av)); | 1372 | memcpy(&ah.av, &tunnel->hdr.av, sizeof (struct mlx4_av)); |
| 1367 | ah.ibah.device = ctx->ib_dev; | 1373 | ah.ibah.device = ctx->ib_dev; |
| 1374 | |||
| 1375 | port = be32_to_cpu(ah.av.ib.port_pd) >> 24; | ||
| 1376 | port = mlx4_slave_convert_port(dev->dev, slave, port); | ||
| 1377 | if (port < 0) | ||
| 1378 | return; | ||
| 1379 | ah.av.ib.port_pd = cpu_to_be32(port << 24 | (be32_to_cpu(ah.av.ib.port_pd) & 0xffffff)); | ||
| 1380 | |||
| 1368 | mlx4_ib_query_ah(&ah.ibah, &ah_attr); | 1381 | mlx4_ib_query_ah(&ah.ibah, &ah_attr); |
| 1369 | if (ah_attr.ah_flags & IB_AH_GRH) | 1382 | if (ah_attr.ah_flags & IB_AH_GRH) |
| 1370 | fill_in_real_sgid_index(dev, slave, ctx->port, &ah_attr); | 1383 | fill_in_real_sgid_index(dev, slave, ctx->port, &ah_attr); |
| 1371 | 1384 | ||
| 1372 | port = mlx4_slave_convert_port(dev->dev, slave, ah_attr.port_num); | ||
| 1373 | if (port < 0) | ||
| 1374 | return; | ||
| 1375 | ah_attr.port_num = port; | ||
| 1376 | memcpy(ah_attr.dmac, tunnel->hdr.mac, 6); | 1385 | memcpy(ah_attr.dmac, tunnel->hdr.mac, 6); |
| 1377 | ah_attr.vlan_id = be16_to_cpu(tunnel->hdr.vlan); | 1386 | ah_attr.vlan_id = be16_to_cpu(tunnel->hdr.vlan); |
| 1378 | /* if slave have default vlan use it */ | 1387 | /* if slave have default vlan use it */ |
| @@ -1773,6 +1782,7 @@ static int create_pv_resources(struct ib_device *ibdev, int slave, int port, | |||
| 1773 | int create_tun, struct mlx4_ib_demux_pv_ctx *ctx) | 1782 | int create_tun, struct mlx4_ib_demux_pv_ctx *ctx) |
| 1774 | { | 1783 | { |
| 1775 | int ret, cq_size; | 1784 | int ret, cq_size; |
| 1785 | struct ib_cq_init_attr cq_attr = {}; | ||
| 1776 | 1786 | ||
| 1777 | if (ctx->state != DEMUX_PV_STATE_DOWN) | 1787 | if (ctx->state != DEMUX_PV_STATE_DOWN) |
| 1778 | return -EEXIST; | 1788 | return -EEXIST; |
| @@ -1801,8 +1811,9 @@ static int create_pv_resources(struct ib_device *ibdev, int slave, int port, | |||
| 1801 | if (ctx->has_smi) | 1811 | if (ctx->has_smi) |
| 1802 | cq_size *= 2; | 1812 | cq_size *= 2; |
| 1803 | 1813 | ||
| 1814 | cq_attr.cqe = cq_size; | ||
| 1804 | ctx->cq = ib_create_cq(ctx->ib_dev, mlx4_ib_tunnel_comp_handler, | 1815 | ctx->cq = ib_create_cq(ctx->ib_dev, mlx4_ib_tunnel_comp_handler, |
| 1805 | NULL, ctx, cq_size, 0); | 1816 | NULL, ctx, &cq_attr); |
| 1806 | if (IS_ERR(ctx->cq)) { | 1817 | if (IS_ERR(ctx->cq)) { |
| 1807 | ret = PTR_ERR(ctx->cq); | 1818 | ret = PTR_ERR(ctx->cq); |
| 1808 | pr_err("Couldn't create tunnel CQ (%d)\n", ret); | 1819 | pr_err("Couldn't create tunnel CQ (%d)\n", ret); |
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index cc64400d41ac..8be6db816460 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
| @@ -132,14 +132,35 @@ static int num_ib_ports(struct mlx4_dev *dev) | |||
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | static int mlx4_ib_query_device(struct ib_device *ibdev, | 134 | static int mlx4_ib_query_device(struct ib_device *ibdev, |
| 135 | struct ib_device_attr *props) | 135 | struct ib_device_attr *props, |
| 136 | struct ib_udata *uhw) | ||
| 136 | { | 137 | { |
| 137 | struct mlx4_ib_dev *dev = to_mdev(ibdev); | 138 | struct mlx4_ib_dev *dev = to_mdev(ibdev); |
| 138 | struct ib_smp *in_mad = NULL; | 139 | struct ib_smp *in_mad = NULL; |
| 139 | struct ib_smp *out_mad = NULL; | 140 | struct ib_smp *out_mad = NULL; |
| 140 | int err = -ENOMEM; | 141 | int err = -ENOMEM; |
| 141 | int have_ib_ports; | 142 | int have_ib_ports; |
| 143 | struct mlx4_uverbs_ex_query_device cmd; | ||
| 144 | struct mlx4_uverbs_ex_query_device_resp resp = {.comp_mask = 0}; | ||
| 145 | struct mlx4_clock_params clock_params; | ||
| 142 | 146 | ||
| 147 | if (uhw->inlen) { | ||
| 148 | if (uhw->inlen < sizeof(cmd)) | ||
| 149 | return -EINVAL; | ||
| 150 | |||
| 151 | err = ib_copy_from_udata(&cmd, uhw, sizeof(cmd)); | ||
| 152 | if (err) | ||
| 153 | return err; | ||
| 154 | |||
| 155 | if (cmd.comp_mask) | ||
| 156 | return -EINVAL; | ||
| 157 | |||
| 158 | if (cmd.reserved) | ||
| 159 | return -EINVAL; | ||
| 160 | } | ||
| 161 | |||
| 162 | resp.response_length = offsetof(typeof(resp), response_length) + | ||
| 163 | sizeof(resp.response_length); | ||
| 143 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); | 164 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
| 144 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | 165 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); |
| 145 | if (!in_mad || !out_mad) | 166 | if (!in_mad || !out_mad) |
| @@ -229,7 +250,25 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, | |||
| 229 | props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * | 250 | props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * |
| 230 | props->max_mcast_grp; | 251 | props->max_mcast_grp; |
| 231 | props->max_map_per_fmr = dev->dev->caps.max_fmr_maps; | 252 | props->max_map_per_fmr = dev->dev->caps.max_fmr_maps; |
| 253 | props->hca_core_clock = dev->dev->caps.hca_core_clock * 1000UL; | ||
| 254 | props->timestamp_mask = 0xFFFFFFFFFFFFULL; | ||
| 232 | 255 | ||
| 256 | if (!mlx4_is_slave(dev->dev)) | ||
| 257 | err = mlx4_get_internal_clock_params(dev->dev, &clock_params); | ||
| 258 | |||
| 259 | if (uhw->outlen >= resp.response_length + sizeof(resp.hca_core_clock_offset)) { | ||
| 260 | resp.response_length += sizeof(resp.hca_core_clock_offset); | ||
| 261 | if (!err && !mlx4_is_slave(dev->dev)) { | ||
| 262 | resp.comp_mask |= QUERY_DEVICE_RESP_MASK_TIMESTAMP; | ||
| 263 | resp.hca_core_clock_offset = clock_params.offset % PAGE_SIZE; | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | if (uhw->outlen) { | ||
| 268 | err = ib_copy_to_udata(uhw, &resp, resp.response_length); | ||
| 269 | if (err) | ||
| 270 | goto out; | ||
| 271 | } | ||
| 233 | out: | 272 | out: |
| 234 | kfree(in_mad); | 273 | kfree(in_mad); |
| 235 | kfree(out_mad); | 274 | kfree(out_mad); |
| @@ -712,8 +751,24 @@ static int mlx4_ib_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) | |||
| 712 | dev->dev->caps.num_uars, | 751 | dev->dev->caps.num_uars, |
| 713 | PAGE_SIZE, vma->vm_page_prot)) | 752 | PAGE_SIZE, vma->vm_page_prot)) |
| 714 | return -EAGAIN; | 753 | return -EAGAIN; |
| 715 | } else | 754 | } else if (vma->vm_pgoff == 3) { |
| 755 | struct mlx4_clock_params params; | ||
| 756 | int ret = mlx4_get_internal_clock_params(dev->dev, ¶ms); | ||
| 757 | |||
| 758 | if (ret) | ||
| 759 | return ret; | ||
| 760 | |||
| 761 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
| 762 | if (io_remap_pfn_range(vma, vma->vm_start, | ||
| 763 | (pci_resource_start(dev->dev->persist->pdev, | ||
| 764 | params.bar) + | ||
| 765 | params.offset) | ||
| 766 | >> PAGE_SHIFT, | ||
| 767 | PAGE_SIZE, vma->vm_page_prot)) | ||
| 768 | return -EAGAIN; | ||
| 769 | } else { | ||
| 716 | return -EINVAL; | 770 | return -EINVAL; |
| 771 | } | ||
| 717 | 772 | ||
| 718 | return 0; | 773 | return 0; |
| 719 | } | 774 | } |
| @@ -758,6 +813,7 @@ static struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev, | |||
| 758 | struct ib_udata *udata) | 813 | struct ib_udata *udata) |
| 759 | { | 814 | { |
| 760 | struct mlx4_ib_xrcd *xrcd; | 815 | struct mlx4_ib_xrcd *xrcd; |
| 816 | struct ib_cq_init_attr cq_attr = {}; | ||
| 761 | int err; | 817 | int err; |
| 762 | 818 | ||
| 763 | if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)) | 819 | if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)) |
| @@ -777,7 +833,8 @@ static struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev, | |||
| 777 | goto err2; | 833 | goto err2; |
| 778 | } | 834 | } |
| 779 | 835 | ||
| 780 | xrcd->cq = ib_create_cq(ibdev, NULL, NULL, xrcd, 1, 0); | 836 | cq_attr.cqe = 1; |
| 837 | xrcd->cq = ib_create_cq(ibdev, NULL, NULL, xrcd, &cq_attr); | ||
| 781 | if (IS_ERR(xrcd->cq)) { | 838 | if (IS_ERR(xrcd->cq)) { |
| 782 | err = PTR_ERR(xrcd->cq); | 839 | err = PTR_ERR(xrcd->cq); |
| 783 | goto err3; | 840 | goto err3; |
| @@ -1090,7 +1147,7 @@ static int __mlx4_ib_create_flow(struct ib_qp *qp, struct ib_flow_attr *flow_att | |||
| 1090 | 1147 | ||
| 1091 | ret = mlx4_cmd_imm(mdev->dev, mailbox->dma, reg_id, size >> 2, 0, | 1148 | ret = mlx4_cmd_imm(mdev->dev, mailbox->dma, reg_id, size >> 2, 0, |
| 1092 | MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, | 1149 | MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, |
| 1093 | MLX4_CMD_NATIVE); | 1150 | MLX4_CMD_WRAPPED); |
| 1094 | if (ret == -ENOMEM) | 1151 | if (ret == -ENOMEM) |
| 1095 | pr_err("mcg table is full. Fail to register network rule.\n"); | 1152 | pr_err("mcg table is full. Fail to register network rule.\n"); |
| 1096 | else if (ret == -ENXIO) | 1153 | else if (ret == -ENXIO) |
| @@ -1107,7 +1164,7 @@ static int __mlx4_ib_destroy_flow(struct mlx4_dev *dev, u64 reg_id) | |||
| 1107 | int err; | 1164 | int err; |
| 1108 | err = mlx4_cmd(dev, reg_id, 0, 0, | 1165 | err = mlx4_cmd(dev, reg_id, 0, 0, |
| 1109 | MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, | 1166 | MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, |
| 1110 | MLX4_CMD_NATIVE); | 1167 | MLX4_CMD_WRAPPED); |
| 1111 | if (err) | 1168 | if (err) |
| 1112 | pr_err("Fail to detach network rule. registration id = 0x%llx\n", | 1169 | pr_err("Fail to detach network rule. registration id = 0x%llx\n", |
| 1113 | reg_id); | 1170 | reg_id); |
| @@ -1185,7 +1242,6 @@ static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp, | |||
| 1185 | &mflow->reg_id[i].id); | 1242 | &mflow->reg_id[i].id); |
| 1186 | if (err) | 1243 | if (err) |
| 1187 | goto err_create_flow; | 1244 | goto err_create_flow; |
| 1188 | i++; | ||
| 1189 | if (is_bonded) { | 1245 | if (is_bonded) { |
| 1190 | /* Application always sees one port so the mirror rule | 1246 | /* Application always sees one port so the mirror rule |
| 1191 | * must be on port #2 | 1247 | * must be on port #2 |
| @@ -1200,6 +1256,7 @@ static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp, | |||
| 1200 | j++; | 1256 | j++; |
| 1201 | } | 1257 | } |
| 1202 | 1258 | ||
| 1259 | i++; | ||
| 1203 | } | 1260 | } |
| 1204 | 1261 | ||
| 1205 | if (i < ARRAY_SIZE(type) && flow_attr->type == IB_FLOW_ATTR_NORMAL) { | 1262 | if (i < ARRAY_SIZE(type) && flow_attr->type == IB_FLOW_ATTR_NORMAL) { |
| @@ -1207,7 +1264,7 @@ static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp, | |||
| 1207 | &mflow->reg_id[i].id); | 1264 | &mflow->reg_id[i].id); |
| 1208 | if (err) | 1265 | if (err) |
| 1209 | goto err_create_flow; | 1266 | goto err_create_flow; |
| 1210 | i++; | 1267 | |
| 1211 | if (is_bonded) { | 1268 | if (is_bonded) { |
| 1212 | flow_attr->port = 2; | 1269 | flow_attr->port = 2; |
| 1213 | err = mlx4_ib_tunnel_steer_add(qp, flow_attr, | 1270 | err = mlx4_ib_tunnel_steer_add(qp, flow_attr, |
| @@ -1218,6 +1275,7 @@ static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp, | |||
| 1218 | j++; | 1275 | j++; |
| 1219 | } | 1276 | } |
| 1220 | /* function to create mirror rule */ | 1277 | /* function to create mirror rule */ |
| 1278 | i++; | ||
| 1221 | } | 1279 | } |
| 1222 | 1280 | ||
| 1223 | return &mflow->ibflow; | 1281 | return &mflow->ibflow; |
| @@ -2041,77 +2099,75 @@ static void init_pkeys(struct mlx4_ib_dev *ibdev) | |||
| 2041 | 2099 | ||
| 2042 | static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev) | 2100 | static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev) |
| 2043 | { | 2101 | { |
| 2044 | char name[80]; | 2102 | int i, j, eq = 0, total_eqs = 0; |
| 2045 | int eq_per_port = 0; | ||
| 2046 | int added_eqs = 0; | ||
| 2047 | int total_eqs = 0; | ||
| 2048 | int i, j, eq; | ||
| 2049 | 2103 | ||
| 2050 | /* Legacy mode or comp_pool is not large enough */ | 2104 | ibdev->eq_table = kcalloc(dev->caps.num_comp_vectors, |
| 2051 | if (dev->caps.comp_pool == 0 || | 2105 | sizeof(ibdev->eq_table[0]), GFP_KERNEL); |
| 2052 | dev->caps.num_ports > dev->caps.comp_pool) | ||
| 2053 | return; | ||
| 2054 | |||
| 2055 | eq_per_port = dev->caps.comp_pool / dev->caps.num_ports; | ||
| 2056 | |||
| 2057 | /* Init eq table */ | ||
| 2058 | added_eqs = 0; | ||
| 2059 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) | ||
| 2060 | added_eqs += eq_per_port; | ||
| 2061 | |||
| 2062 | total_eqs = dev->caps.num_comp_vectors + added_eqs; | ||
| 2063 | |||
| 2064 | ibdev->eq_table = kzalloc(total_eqs * sizeof(int), GFP_KERNEL); | ||
| 2065 | if (!ibdev->eq_table) | 2106 | if (!ibdev->eq_table) |
| 2066 | return; | 2107 | return; |
| 2067 | 2108 | ||
| 2068 | ibdev->eq_added = added_eqs; | 2109 | for (i = 1; i <= dev->caps.num_ports; i++) { |
| 2069 | 2110 | for (j = 0; j < mlx4_get_eqs_per_port(dev, i); | |
| 2070 | eq = 0; | 2111 | j++, total_eqs++) { |
| 2071 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) { | 2112 | if (i > 1 && mlx4_is_eq_shared(dev, total_eqs)) |
| 2072 | for (j = 0; j < eq_per_port; j++) { | 2113 | continue; |
| 2073 | snprintf(name, sizeof(name), "mlx4-ib-%d-%d@%s", | 2114 | ibdev->eq_table[eq] = total_eqs; |
| 2074 | i, j, dev->persist->pdev->bus->name); | 2115 | if (!mlx4_assign_eq(dev, i, |
| 2075 | /* Set IRQ for specific name (per ring) */ | 2116 | &ibdev->eq_table[eq])) |
| 2076 | if (mlx4_assign_eq(dev, name, NULL, | 2117 | eq++; |
| 2077 | &ibdev->eq_table[eq])) { | 2118 | else |
| 2078 | /* Use legacy (same as mlx4_en driver) */ | 2119 | ibdev->eq_table[eq] = -1; |
| 2079 | pr_warn("Can't allocate EQ %d; reverting to legacy\n", eq); | ||
| 2080 | ibdev->eq_table[eq] = | ||
| 2081 | (eq % dev->caps.num_comp_vectors); | ||
| 2082 | } | ||
| 2083 | eq++; | ||
| 2084 | } | 2120 | } |
| 2085 | } | 2121 | } |
| 2086 | 2122 | ||
| 2087 | /* Fill the reset of the vector with legacy EQ */ | 2123 | for (i = eq; i < dev->caps.num_comp_vectors; |
| 2088 | for (i = 0, eq = added_eqs; i < dev->caps.num_comp_vectors; i++) | 2124 | ibdev->eq_table[i++] = -1) |
| 2089 | ibdev->eq_table[eq++] = i; | 2125 | ; |
| 2090 | 2126 | ||
| 2091 | /* Advertise the new number of EQs to clients */ | 2127 | /* Advertise the new number of EQs to clients */ |
| 2092 | ibdev->ib_dev.num_comp_vectors = total_eqs; | 2128 | ibdev->ib_dev.num_comp_vectors = eq; |
| 2093 | } | 2129 | } |
| 2094 | 2130 | ||
| 2095 | static void mlx4_ib_free_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev) | 2131 | static void mlx4_ib_free_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev) |
| 2096 | { | 2132 | { |
| 2097 | int i; | 2133 | int i; |
| 2134 | int total_eqs = ibdev->ib_dev.num_comp_vectors; | ||
| 2098 | 2135 | ||
| 2099 | /* no additional eqs were added */ | 2136 | /* no eqs were allocated */ |
| 2100 | if (!ibdev->eq_table) | 2137 | if (!ibdev->eq_table) |
| 2101 | return; | 2138 | return; |
| 2102 | 2139 | ||
| 2103 | /* Reset the advertised EQ number */ | 2140 | /* Reset the advertised EQ number */ |
| 2104 | ibdev->ib_dev.num_comp_vectors = dev->caps.num_comp_vectors; | 2141 | ibdev->ib_dev.num_comp_vectors = 0; |
| 2105 | 2142 | ||
| 2106 | /* Free only the added eqs */ | 2143 | for (i = 0; i < total_eqs; i++) |
| 2107 | for (i = 0; i < ibdev->eq_added; i++) { | ||
| 2108 | /* Don't free legacy eqs if used */ | ||
| 2109 | if (ibdev->eq_table[i] <= dev->caps.num_comp_vectors) | ||
| 2110 | continue; | ||
| 2111 | mlx4_release_eq(dev, ibdev->eq_table[i]); | 2144 | mlx4_release_eq(dev, ibdev->eq_table[i]); |
| 2112 | } | ||
| 2113 | 2145 | ||
| 2114 | kfree(ibdev->eq_table); | 2146 | kfree(ibdev->eq_table); |
| 2147 | ibdev->eq_table = NULL; | ||
| 2148 | } | ||
| 2149 | |||
| 2150 | static int mlx4_port_immutable(struct ib_device *ibdev, u8 port_num, | ||
| 2151 | struct ib_port_immutable *immutable) | ||
| 2152 | { | ||
| 2153 | struct ib_port_attr attr; | ||
| 2154 | int err; | ||
| 2155 | |||
| 2156 | err = mlx4_ib_query_port(ibdev, port_num, &attr); | ||
| 2157 | if (err) | ||
| 2158 | return err; | ||
| 2159 | |||
| 2160 | immutable->pkey_tbl_len = attr.pkey_tbl_len; | ||
| 2161 | immutable->gid_tbl_len = attr.gid_tbl_len; | ||
| 2162 | |||
| 2163 | if (mlx4_ib_port_link_layer(ibdev, port_num) == IB_LINK_LAYER_INFINIBAND) | ||
| 2164 | immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB; | ||
| 2165 | else | ||
| 2166 | immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE; | ||
| 2167 | |||
| 2168 | immutable->max_mad_size = IB_MGMT_MAD_SIZE; | ||
| 2169 | |||
| 2170 | return 0; | ||
| 2115 | } | 2171 | } |
| 2116 | 2172 | ||
| 2117 | static void *mlx4_ib_add(struct mlx4_dev *dev) | 2173 | static void *mlx4_ib_add(struct mlx4_dev *dev) |
| @@ -2123,6 +2179,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) | |||
| 2123 | struct mlx4_ib_iboe *iboe; | 2179 | struct mlx4_ib_iboe *iboe; |
| 2124 | int ib_num_ports = 0; | 2180 | int ib_num_ports = 0; |
| 2125 | int num_req_counters; | 2181 | int num_req_counters; |
| 2182 | int allocated; | ||
| 2183 | u32 counter_index; | ||
| 2126 | 2184 | ||
| 2127 | pr_info_once("%s", mlx4_ib_version); | 2185 | pr_info_once("%s", mlx4_ib_version); |
| 2128 | 2186 | ||
| @@ -2241,6 +2299,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) | |||
| 2241 | ibdev->ib_dev.attach_mcast = mlx4_ib_mcg_attach; | 2299 | ibdev->ib_dev.attach_mcast = mlx4_ib_mcg_attach; |
| 2242 | ibdev->ib_dev.detach_mcast = mlx4_ib_mcg_detach; | 2300 | ibdev->ib_dev.detach_mcast = mlx4_ib_mcg_detach; |
| 2243 | ibdev->ib_dev.process_mad = mlx4_ib_process_mad; | 2301 | ibdev->ib_dev.process_mad = mlx4_ib_process_mad; |
| 2302 | ibdev->ib_dev.get_port_immutable = mlx4_port_immutable; | ||
| 2244 | 2303 | ||
| 2245 | if (!mlx4_is_slave(ibdev->dev)) { | 2304 | if (!mlx4_is_slave(ibdev->dev)) { |
| 2246 | ibdev->ib_dev.alloc_fmr = mlx4_ib_fmr_alloc; | 2305 | ibdev->ib_dev.alloc_fmr = mlx4_ib_fmr_alloc; |
| @@ -2278,6 +2337,10 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) | |||
| 2278 | (1ull << IB_USER_VERBS_EX_CMD_DESTROY_FLOW); | 2337 | (1ull << IB_USER_VERBS_EX_CMD_DESTROY_FLOW); |
| 2279 | } | 2338 | } |
| 2280 | 2339 | ||
| 2340 | ibdev->ib_dev.uverbs_ex_cmd_mask |= | ||
| 2341 | (1ull << IB_USER_VERBS_EX_CMD_QUERY_DEVICE) | | ||
| 2342 | (1ull << IB_USER_VERBS_EX_CMD_CREATE_CQ); | ||
| 2343 | |||
| 2281 | mlx4_ib_alloc_eqs(dev, ibdev); | 2344 | mlx4_ib_alloc_eqs(dev, ibdev); |
| 2282 | 2345 | ||
| 2283 | spin_lock_init(&iboe->lock); | 2346 | spin_lock_init(&iboe->lock); |
| @@ -2288,19 +2351,31 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) | |||
| 2288 | num_req_counters = mlx4_is_bonded(dev) ? 1 : ibdev->num_ports; | 2351 | num_req_counters = mlx4_is_bonded(dev) ? 1 : ibdev->num_ports; |
| 2289 | for (i = 0; i < num_req_counters; ++i) { | 2352 | for (i = 0; i < num_req_counters; ++i) { |
| 2290 | mutex_init(&ibdev->qp1_proxy_lock[i]); | 2353 | mutex_init(&ibdev->qp1_proxy_lock[i]); |
| 2354 | allocated = 0; | ||
| 2291 | if (mlx4_ib_port_link_layer(&ibdev->ib_dev, i + 1) == | 2355 | if (mlx4_ib_port_link_layer(&ibdev->ib_dev, i + 1) == |
| 2292 | IB_LINK_LAYER_ETHERNET) { | 2356 | IB_LINK_LAYER_ETHERNET) { |
| 2293 | err = mlx4_counter_alloc(ibdev->dev, &ibdev->counters[i]); | 2357 | err = mlx4_counter_alloc(ibdev->dev, &counter_index); |
| 2358 | /* if failed to allocate a new counter, use default */ | ||
| 2294 | if (err) | 2359 | if (err) |
| 2295 | ibdev->counters[i] = -1; | 2360 | counter_index = |
| 2296 | } else { | 2361 | mlx4_get_default_counter_index(dev, |
| 2297 | ibdev->counters[i] = -1; | 2362 | i + 1); |
| 2363 | else | ||
| 2364 | allocated = 1; | ||
| 2365 | } else { /* IB_LINK_LAYER_INFINIBAND use the default counter */ | ||
| 2366 | counter_index = mlx4_get_default_counter_index(dev, | ||
| 2367 | i + 1); | ||
| 2298 | } | 2368 | } |
| 2369 | ibdev->counters[i].index = counter_index; | ||
| 2370 | ibdev->counters[i].allocated = allocated; | ||
| 2371 | pr_info("counter index %d for port %d allocated %d\n", | ||
| 2372 | counter_index, i + 1, allocated); | ||
| 2299 | } | 2373 | } |
| 2300 | if (mlx4_is_bonded(dev)) | 2374 | if (mlx4_is_bonded(dev)) |
| 2301 | for (i = 1; i < ibdev->num_ports ; ++i) | 2375 | for (i = 1; i < ibdev->num_ports ; ++i) { |
| 2302 | ibdev->counters[i] = ibdev->counters[0]; | 2376 | ibdev->counters[i].index = ibdev->counters[0].index; |
| 2303 | 2377 | ibdev->counters[i].allocated = 0; | |
| 2378 | } | ||
| 2304 | 2379 | ||
| 2305 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) | 2380 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) |
| 2306 | ib_num_ports++; | 2381 | ib_num_ports++; |
| @@ -2440,10 +2515,12 @@ err_steer_qp_release: | |||
| 2440 | mlx4_qp_release_range(dev, ibdev->steer_qpn_base, | 2515 | mlx4_qp_release_range(dev, ibdev->steer_qpn_base, |
| 2441 | ibdev->steer_qpn_count); | 2516 | ibdev->steer_qpn_count); |
| 2442 | err_counter: | 2517 | err_counter: |
| 2443 | for (; i; --i) | 2518 | for (i = 0; i < ibdev->num_ports; ++i) { |
| 2444 | if (ibdev->counters[i - 1] != -1) | 2519 | if (ibdev->counters[i].index != -1 && |
| 2445 | mlx4_counter_free(ibdev->dev, ibdev->counters[i - 1]); | 2520 | ibdev->counters[i].allocated) |
| 2446 | 2521 | mlx4_counter_free(ibdev->dev, | |
| 2522 | ibdev->counters[i].index); | ||
| 2523 | } | ||
| 2447 | err_map: | 2524 | err_map: |
| 2448 | iounmap(ibdev->uar_map); | 2525 | iounmap(ibdev->uar_map); |
| 2449 | 2526 | ||
| @@ -2560,8 +2637,9 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) | |||
| 2560 | 2637 | ||
| 2561 | iounmap(ibdev->uar_map); | 2638 | iounmap(ibdev->uar_map); |
| 2562 | for (p = 0; p < ibdev->num_ports; ++p) | 2639 | for (p = 0; p < ibdev->num_ports; ++p) |
| 2563 | if (ibdev->counters[p] != -1) | 2640 | if (ibdev->counters[p].index != -1 && |
| 2564 | mlx4_counter_free(ibdev->dev, ibdev->counters[p]); | 2641 | ibdev->counters[p].allocated) |
| 2642 | mlx4_counter_free(ibdev->dev, ibdev->counters[p].index); | ||
| 2565 | mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB) | 2643 | mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB) |
| 2566 | mlx4_CLOSE_PORT(dev, p); | 2644 | mlx4_CLOSE_PORT(dev, p); |
| 2567 | 2645 | ||
| @@ -2592,31 +2670,33 @@ static void do_slave_init(struct mlx4_ib_dev *ibdev, int slave, int do_init) | |||
| 2592 | dm = kcalloc(ports, sizeof(*dm), GFP_ATOMIC); | 2670 | dm = kcalloc(ports, sizeof(*dm), GFP_ATOMIC); |
| 2593 | if (!dm) { | 2671 | if (!dm) { |
| 2594 | pr_err("failed to allocate memory for tunneling qp update\n"); | 2672 | pr_err("failed to allocate memory for tunneling qp update\n"); |
| 2595 | goto out; | 2673 | return; |
| 2596 | } | 2674 | } |
| 2597 | 2675 | ||
| 2598 | for (i = 0; i < ports; i++) { | 2676 | for (i = 0; i < ports; i++) { |
| 2599 | dm[i] = kmalloc(sizeof (struct mlx4_ib_demux_work), GFP_ATOMIC); | 2677 | dm[i] = kmalloc(sizeof (struct mlx4_ib_demux_work), GFP_ATOMIC); |
| 2600 | if (!dm[i]) { | 2678 | if (!dm[i]) { |
| 2601 | pr_err("failed to allocate memory for tunneling qp update work struct\n"); | 2679 | pr_err("failed to allocate memory for tunneling qp update work struct\n"); |
| 2602 | for (i = 0; i < dev->caps.num_ports; i++) { | 2680 | while (--i >= 0) |
| 2603 | if (dm[i]) | 2681 | kfree(dm[i]); |
| 2604 | kfree(dm[i]); | ||
| 2605 | } | ||
| 2606 | goto out; | 2682 | goto out; |
| 2607 | } | 2683 | } |
| 2608 | } | ||
| 2609 | /* initialize or tear down tunnel QPs for the slave */ | ||
| 2610 | for (i = 0; i < ports; i++) { | ||
| 2611 | INIT_WORK(&dm[i]->work, mlx4_ib_tunnels_update_work); | 2684 | INIT_WORK(&dm[i]->work, mlx4_ib_tunnels_update_work); |
| 2612 | dm[i]->port = first_port + i + 1; | 2685 | dm[i]->port = first_port + i + 1; |
| 2613 | dm[i]->slave = slave; | 2686 | dm[i]->slave = slave; |
| 2614 | dm[i]->do_init = do_init; | 2687 | dm[i]->do_init = do_init; |
| 2615 | dm[i]->dev = ibdev; | 2688 | dm[i]->dev = ibdev; |
| 2616 | spin_lock_irqsave(&ibdev->sriov.going_down_lock, flags); | 2689 | } |
| 2617 | if (!ibdev->sriov.is_going_down) | 2690 | /* initialize or tear down tunnel QPs for the slave */ |
| 2691 | spin_lock_irqsave(&ibdev->sriov.going_down_lock, flags); | ||
| 2692 | if (!ibdev->sriov.is_going_down) { | ||
| 2693 | for (i = 0; i < ports; i++) | ||
| 2618 | queue_work(ibdev->sriov.demux[i].ud_wq, &dm[i]->work); | 2694 | queue_work(ibdev->sriov.demux[i].ud_wq, &dm[i]->work); |
| 2619 | spin_unlock_irqrestore(&ibdev->sriov.going_down_lock, flags); | 2695 | spin_unlock_irqrestore(&ibdev->sriov.going_down_lock, flags); |
| 2696 | } else { | ||
| 2697 | spin_unlock_irqrestore(&ibdev->sriov.going_down_lock, flags); | ||
| 2698 | for (i = 0; i < ports; i++) | ||
| 2699 | kfree(dm[i]); | ||
| 2620 | } | 2700 | } |
| 2621 | out: | 2701 | out: |
| 2622 | kfree(dm); | 2702 | kfree(dm); |
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index fce3934372a1..334387f63358 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h | |||
| @@ -110,6 +110,7 @@ struct mlx4_ib_cq { | |||
| 110 | struct mutex resize_mutex; | 110 | struct mutex resize_mutex; |
| 111 | struct ib_umem *umem; | 111 | struct ib_umem *umem; |
| 112 | struct ib_umem *resize_umem; | 112 | struct ib_umem *resize_umem; |
| 113 | int create_flags; | ||
| 113 | /* List of qps that it serves.*/ | 114 | /* List of qps that it serves.*/ |
| 114 | struct list_head send_qp_list; | 115 | struct list_head send_qp_list; |
| 115 | struct list_head recv_qp_list; | 116 | struct list_head recv_qp_list; |
| @@ -503,6 +504,11 @@ struct mlx4_ib_iov_port { | |||
| 503 | struct mlx4_ib_iov_sysfs_attr mcg_dentry; | 504 | struct mlx4_ib_iov_sysfs_attr mcg_dentry; |
| 504 | }; | 505 | }; |
| 505 | 506 | ||
| 507 | struct counter_index { | ||
| 508 | u32 index; | ||
| 509 | u8 allocated; | ||
| 510 | }; | ||
| 511 | |||
| 506 | struct mlx4_ib_dev { | 512 | struct mlx4_ib_dev { |
| 507 | struct ib_device ib_dev; | 513 | struct ib_device ib_dev; |
| 508 | struct mlx4_dev *dev; | 514 | struct mlx4_dev *dev; |
| @@ -521,9 +527,8 @@ struct mlx4_ib_dev { | |||
| 521 | struct mutex cap_mask_mutex; | 527 | struct mutex cap_mask_mutex; |
| 522 | bool ib_active; | 528 | bool ib_active; |
| 523 | struct mlx4_ib_iboe iboe; | 529 | struct mlx4_ib_iboe iboe; |
| 524 | int counters[MLX4_MAX_PORTS]; | 530 | struct counter_index counters[MLX4_MAX_PORTS]; |
| 525 | int *eq_table; | 531 | int *eq_table; |
| 526 | int eq_added; | ||
| 527 | struct kobject *iov_parent; | 532 | struct kobject *iov_parent; |
| 528 | struct kobject *ports_parent; | 533 | struct kobject *ports_parent; |
| 529 | struct kobject *dev_ports_parent[MLX4_MFUNC_MAX]; | 534 | struct kobject *dev_ports_parent[MLX4_MFUNC_MAX]; |
| @@ -555,6 +560,21 @@ struct mlx4_ib_qp_tunnel_init_attr { | |||
| 555 | u8 port; | 560 | u8 port; |
| 556 | }; | 561 | }; |
| 557 | 562 | ||
| 563 | struct mlx4_uverbs_ex_query_device { | ||
| 564 | __u32 comp_mask; | ||
| 565 | __u32 reserved; | ||
| 566 | }; | ||
| 567 | |||
| 568 | enum query_device_resp_mask { | ||
| 569 | QUERY_DEVICE_RESP_MASK_TIMESTAMP = 1UL << 0, | ||
| 570 | }; | ||
| 571 | |||
| 572 | struct mlx4_uverbs_ex_query_device_resp { | ||
| 573 | __u32 comp_mask; | ||
| 574 | __u32 response_length; | ||
| 575 | __u64 hca_core_clock_offset; | ||
| 576 | }; | ||
| 577 | |||
| 558 | static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev) | 578 | static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev) |
| 559 | { | 579 | { |
| 560 | return container_of(ibdev, struct mlx4_ib_dev, ib_dev); | 580 | return container_of(ibdev, struct mlx4_ib_dev, ib_dev); |
| @@ -668,7 +688,8 @@ void mlx4_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list); | |||
| 668 | 688 | ||
| 669 | int mlx4_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period); | 689 | int mlx4_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period); |
| 670 | int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata); | 690 | int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata); |
| 671 | struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector, | 691 | struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, |
| 692 | const struct ib_cq_init_attr *attr, | ||
| 672 | struct ib_ucontext *context, | 693 | struct ib_ucontext *context, |
| 673 | struct ib_udata *udata); | 694 | struct ib_udata *udata); |
| 674 | int mlx4_ib_destroy_cq(struct ib_cq *cq); | 695 | int mlx4_ib_destroy_cq(struct ib_cq *cq); |
| @@ -706,11 +727,13 @@ int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr, | |||
| 706 | struct ib_recv_wr **bad_wr); | 727 | struct ib_recv_wr **bad_wr); |
| 707 | 728 | ||
| 708 | int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int mad_ifc_flags, | 729 | int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int mad_ifc_flags, |
| 709 | int port, struct ib_wc *in_wc, struct ib_grh *in_grh, | 730 | int port, const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 710 | void *in_mad, void *response_mad); | 731 | const void *in_mad, void *response_mad); |
| 711 | int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | 732 | int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, |
| 712 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 733 | const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 713 | struct ib_mad *in_mad, struct ib_mad *out_mad); | 734 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 735 | struct ib_mad_hdr *out, size_t *out_mad_size, | ||
| 736 | u16 *out_mad_pkey_index); | ||
| 714 | int mlx4_ib_mad_init(struct mlx4_ib_dev *dev); | 737 | int mlx4_ib_mad_init(struct mlx4_ib_dev *dev); |
| 715 | void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev); | 738 | void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev); |
| 716 | 739 | ||
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 02fc91c68027..c5a3a5f0de41 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c | |||
| @@ -1539,12 +1539,13 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, | |||
| 1539 | } | 1539 | } |
| 1540 | 1540 | ||
| 1541 | if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) { | 1541 | if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) { |
| 1542 | if (dev->counters[qp->port - 1] != -1) { | 1542 | if (dev->counters[qp->port - 1].index != -1) { |
| 1543 | context->pri_path.counter_index = | 1543 | context->pri_path.counter_index = |
| 1544 | dev->counters[qp->port - 1]; | 1544 | dev->counters[qp->port - 1].index; |
| 1545 | optpar |= MLX4_QP_OPTPAR_COUNTER_INDEX; | 1545 | optpar |= MLX4_QP_OPTPAR_COUNTER_INDEX; |
| 1546 | } else | 1546 | } else |
| 1547 | context->pri_path.counter_index = 0xff; | 1547 | context->pri_path.counter_index = |
| 1548 | MLX4_SINK_COUNTER_INDEX(dev->dev); | ||
| 1548 | 1549 | ||
| 1549 | if (qp->flags & MLX4_IB_QP_NETIF) { | 1550 | if (qp->flags & MLX4_IB_QP_NETIF) { |
| 1550 | mlx4_ib_steer_qp_reg(dev, qp, 1); | 1551 | mlx4_ib_steer_qp_reg(dev, qp, 1); |
diff --git a/drivers/infiniband/hw/mlx5/Kconfig b/drivers/infiniband/hw/mlx5/Kconfig index 10df386c6344..bce263b92821 100644 --- a/drivers/infiniband/hw/mlx5/Kconfig +++ b/drivers/infiniband/hw/mlx5/Kconfig | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | config MLX5_INFINIBAND | 1 | config MLX5_INFINIBAND |
| 2 | tristate "Mellanox Connect-IB HCA support" | 2 | tristate "Mellanox Connect-IB HCA support" |
| 3 | depends on NETDEVICES && ETHERNET && PCI | 3 | depends on NETDEVICES && ETHERNET && PCI && MLX5_CORE |
| 4 | select NET_VENDOR_MELLANOX | ||
| 5 | select MLX5_CORE | ||
| 6 | ---help--- | 4 | ---help--- |
| 7 | This driver provides low-level InfiniBand support for | 5 | This driver provides low-level InfiniBand support for |
| 8 | Mellanox Connect-IB PCI Express host channel adapters (HCAs). | 6 | Mellanox Connect-IB PCI Express host channel adapters (HCAs). |
diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c index 2ee6b1051975..5c9eeea62805 100644 --- a/drivers/infiniband/hw/mlx5/cq.c +++ b/drivers/infiniband/hw/mlx5/cq.c | |||
| @@ -590,8 +590,7 @@ static int alloc_cq_buf(struct mlx5_ib_dev *dev, struct mlx5_ib_cq_buf *buf, | |||
| 590 | { | 590 | { |
| 591 | int err; | 591 | int err; |
| 592 | 592 | ||
| 593 | err = mlx5_buf_alloc(dev->mdev, nent * cqe_size, | 593 | err = mlx5_buf_alloc(dev->mdev, nent * cqe_size, &buf->buf); |
| 594 | PAGE_SIZE * 2, &buf->buf); | ||
| 595 | if (err) | 594 | if (err) |
| 596 | return err; | 595 | return err; |
| 597 | 596 | ||
| @@ -736,10 +735,13 @@ static void destroy_cq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *cq) | |||
| 736 | mlx5_db_free(dev->mdev, &cq->db); | 735 | mlx5_db_free(dev->mdev, &cq->db); |
| 737 | } | 736 | } |
| 738 | 737 | ||
| 739 | struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, int entries, | 738 | struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, |
| 740 | int vector, struct ib_ucontext *context, | 739 | const struct ib_cq_init_attr *attr, |
| 740 | struct ib_ucontext *context, | ||
| 741 | struct ib_udata *udata) | 741 | struct ib_udata *udata) |
| 742 | { | 742 | { |
| 743 | int entries = attr->cqe; | ||
| 744 | int vector = attr->comp_vector; | ||
| 743 | struct mlx5_create_cq_mbox_in *cqb = NULL; | 745 | struct mlx5_create_cq_mbox_in *cqb = NULL; |
| 744 | struct mlx5_ib_dev *dev = to_mdev(ibdev); | 746 | struct mlx5_ib_dev *dev = to_mdev(ibdev); |
| 745 | struct mlx5_ib_cq *cq; | 747 | struct mlx5_ib_cq *cq; |
| @@ -750,11 +752,14 @@ struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, int entries, | |||
| 750 | int eqn; | 752 | int eqn; |
| 751 | int err; | 753 | int err; |
| 752 | 754 | ||
| 755 | if (attr->flags) | ||
| 756 | return ERR_PTR(-EINVAL); | ||
| 757 | |||
| 753 | if (entries < 0) | 758 | if (entries < 0) |
| 754 | return ERR_PTR(-EINVAL); | 759 | return ERR_PTR(-EINVAL); |
| 755 | 760 | ||
| 756 | entries = roundup_pow_of_two(entries + 1); | 761 | entries = roundup_pow_of_two(entries + 1); |
| 757 | if (entries > dev->mdev->caps.gen.max_cqes) | 762 | if (entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz))) |
| 758 | return ERR_PTR(-EINVAL); | 763 | return ERR_PTR(-EINVAL); |
| 759 | 764 | ||
| 760 | cq = kzalloc(sizeof(*cq), GFP_KERNEL); | 765 | cq = kzalloc(sizeof(*cq), GFP_KERNEL); |
| @@ -921,7 +926,7 @@ int mlx5_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period) | |||
| 921 | int err; | 926 | int err; |
| 922 | u32 fsel; | 927 | u32 fsel; |
| 923 | 928 | ||
| 924 | if (!(dev->mdev->caps.gen.flags & MLX5_DEV_CAP_FLAG_CQ_MODER)) | 929 | if (!MLX5_CAP_GEN(dev->mdev, cq_moderation)) |
| 925 | return -ENOSYS; | 930 | return -ENOSYS; |
| 926 | 931 | ||
| 927 | in = kzalloc(sizeof(*in), GFP_KERNEL); | 932 | in = kzalloc(sizeof(*in), GFP_KERNEL); |
| @@ -1076,7 +1081,7 @@ int mlx5_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata) | |||
| 1076 | int uninitialized_var(cqe_size); | 1081 | int uninitialized_var(cqe_size); |
| 1077 | unsigned long flags; | 1082 | unsigned long flags; |
| 1078 | 1083 | ||
| 1079 | if (!(dev->mdev->caps.gen.flags & MLX5_DEV_CAP_FLAG_RESIZE_CQ)) { | 1084 | if (!MLX5_CAP_GEN(dev->mdev, cq_resize)) { |
| 1080 | pr_info("Firmware does not support resize CQ\n"); | 1085 | pr_info("Firmware does not support resize CQ\n"); |
| 1081 | return -ENOSYS; | 1086 | return -ENOSYS; |
| 1082 | } | 1087 | } |
| @@ -1085,7 +1090,7 @@ int mlx5_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata) | |||
| 1085 | return -EINVAL; | 1090 | return -EINVAL; |
| 1086 | 1091 | ||
| 1087 | entries = roundup_pow_of_two(entries + 1); | 1092 | entries = roundup_pow_of_two(entries + 1); |
| 1088 | if (entries > dev->mdev->caps.gen.max_cqes + 1) | 1093 | if (entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz)) + 1) |
| 1089 | return -EINVAL; | 1094 | return -EINVAL; |
| 1090 | 1095 | ||
| 1091 | if (entries == ibcq->cqe + 1) | 1096 | if (entries == ibcq->cqe + 1) |
diff --git a/drivers/infiniband/hw/mlx5/mad.c b/drivers/infiniband/hw/mlx5/mad.c index 9cf9a37bb5ff..b84d13a487cc 100644 --- a/drivers/infiniband/hw/mlx5/mad.c +++ b/drivers/infiniband/hw/mlx5/mad.c | |||
| @@ -41,8 +41,8 @@ enum { | |||
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, | 43 | int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, |
| 44 | u8 port, struct ib_wc *in_wc, struct ib_grh *in_grh, | 44 | u8 port, const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 45 | void *in_mad, void *response_mad) | 45 | const void *in_mad, void *response_mad) |
| 46 | { | 46 | { |
| 47 | u8 op_modifier = 0; | 47 | u8 op_modifier = 0; |
| 48 | 48 | ||
| @@ -58,11 +58,19 @@ int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, | |||
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | 60 | int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, |
| 61 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 61 | const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 62 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 62 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 63 | struct ib_mad_hdr *out, size_t *out_mad_size, | ||
| 64 | u16 *out_mad_pkey_index) | ||
| 63 | { | 65 | { |
| 64 | u16 slid; | 66 | u16 slid; |
| 65 | int err; | 67 | int err; |
| 68 | const struct ib_mad *in_mad = (const struct ib_mad *)in; | ||
| 69 | struct ib_mad *out_mad = (struct ib_mad *)out; | ||
| 70 | |||
| 71 | if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || | ||
| 72 | *out_mad_size != sizeof(*out_mad))) | ||
| 73 | return IB_MAD_RESULT_FAILURE; | ||
| 66 | 74 | ||
| 67 | slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); | 75 | slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); |
| 68 | 76 | ||
| @@ -129,7 +137,7 @@ int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, u8 port) | |||
| 129 | 137 | ||
| 130 | packet_error = be16_to_cpu(out_mad->status); | 138 | packet_error = be16_to_cpu(out_mad->status); |
| 131 | 139 | ||
| 132 | dev->mdev->caps.gen.ext_port_cap[port - 1] = (!err && !packet_error) ? | 140 | dev->mdev->port_caps[port - 1].ext_port_cap = (!err && !packet_error) ? |
| 133 | MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO : 0; | 141 | MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO : 0; |
| 134 | 142 | ||
| 135 | out: | 143 | out: |
| @@ -137,3 +145,300 @@ out: | |||
| 137 | kfree(out_mad); | 145 | kfree(out_mad); |
| 138 | return err; | 146 | return err; |
| 139 | } | 147 | } |
| 148 | |||
| 149 | int mlx5_query_mad_ifc_smp_attr_node_info(struct ib_device *ibdev, | ||
| 150 | struct ib_smp *out_mad) | ||
| 151 | { | ||
| 152 | struct ib_smp *in_mad = NULL; | ||
| 153 | int err = -ENOMEM; | ||
| 154 | |||
| 155 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | ||
| 156 | if (!in_mad) | ||
| 157 | return -ENOMEM; | ||
| 158 | |||
| 159 | init_query_mad(in_mad); | ||
| 160 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; | ||
| 161 | |||
| 162 | err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad, | ||
| 163 | out_mad); | ||
| 164 | |||
| 165 | kfree(in_mad); | ||
| 166 | return err; | ||
| 167 | } | ||
| 168 | |||
| 169 | int mlx5_query_mad_ifc_system_image_guid(struct ib_device *ibdev, | ||
| 170 | __be64 *sys_image_guid) | ||
| 171 | { | ||
| 172 | struct ib_smp *out_mad = NULL; | ||
| 173 | int err = -ENOMEM; | ||
| 174 | |||
| 175 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
| 176 | if (!out_mad) | ||
| 177 | return -ENOMEM; | ||
| 178 | |||
| 179 | err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad); | ||
| 180 | if (err) | ||
| 181 | goto out; | ||
| 182 | |||
| 183 | memcpy(sys_image_guid, out_mad->data + 4, 8); | ||
| 184 | |||
| 185 | out: | ||
| 186 | kfree(out_mad); | ||
| 187 | |||
| 188 | return err; | ||
| 189 | } | ||
| 190 | |||
| 191 | int mlx5_query_mad_ifc_max_pkeys(struct ib_device *ibdev, | ||
| 192 | u16 *max_pkeys) | ||
| 193 | { | ||
| 194 | struct ib_smp *out_mad = NULL; | ||
| 195 | int err = -ENOMEM; | ||
| 196 | |||
| 197 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
| 198 | if (!out_mad) | ||
| 199 | return -ENOMEM; | ||
| 200 | |||
| 201 | err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad); | ||
| 202 | if (err) | ||
| 203 | goto out; | ||
| 204 | |||
| 205 | *max_pkeys = be16_to_cpup((__be16 *)(out_mad->data + 28)); | ||
| 206 | |||
| 207 | out: | ||
| 208 | kfree(out_mad); | ||
| 209 | |||
| 210 | return err; | ||
| 211 | } | ||
| 212 | |||
| 213 | int mlx5_query_mad_ifc_vendor_id(struct ib_device *ibdev, | ||
| 214 | u32 *vendor_id) | ||
| 215 | { | ||
| 216 | struct ib_smp *out_mad = NULL; | ||
| 217 | int err = -ENOMEM; | ||
| 218 | |||
| 219 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
| 220 | if (!out_mad) | ||
| 221 | return -ENOMEM; | ||
| 222 | |||
| 223 | err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad); | ||
| 224 | if (err) | ||
| 225 | goto out; | ||
| 226 | |||
| 227 | *vendor_id = be32_to_cpup((__be32 *)(out_mad->data + 36)) & 0xffff; | ||
| 228 | |||
| 229 | out: | ||
| 230 | kfree(out_mad); | ||
| 231 | |||
| 232 | return err; | ||
| 233 | } | ||
| 234 | |||
| 235 | int mlx5_query_mad_ifc_node_desc(struct mlx5_ib_dev *dev, char *node_desc) | ||
| 236 | { | ||
| 237 | struct ib_smp *in_mad = NULL; | ||
| 238 | struct ib_smp *out_mad = NULL; | ||
| 239 | int err = -ENOMEM; | ||
| 240 | |||
| 241 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | ||
| 242 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
| 243 | if (!in_mad || !out_mad) | ||
| 244 | goto out; | ||
| 245 | |||
| 246 | init_query_mad(in_mad); | ||
| 247 | in_mad->attr_id = IB_SMP_ATTR_NODE_DESC; | ||
| 248 | |||
| 249 | err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); | ||
| 250 | if (err) | ||
| 251 | goto out; | ||
| 252 | |||
| 253 | memcpy(node_desc, out_mad->data, 64); | ||
| 254 | out: | ||
| 255 | kfree(in_mad); | ||
| 256 | kfree(out_mad); | ||
| 257 | return err; | ||
| 258 | } | ||
| 259 | |||
| 260 | int mlx5_query_mad_ifc_node_guid(struct mlx5_ib_dev *dev, __be64 *node_guid) | ||
| 261 | { | ||
| 262 | struct ib_smp *in_mad = NULL; | ||
| 263 | struct ib_smp *out_mad = NULL; | ||
| 264 | int err = -ENOMEM; | ||
| 265 | |||
| 266 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | ||
| 267 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
| 268 | if (!in_mad || !out_mad) | ||
| 269 | goto out; | ||
| 270 | |||
| 271 | init_query_mad(in_mad); | ||
| 272 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; | ||
| 273 | |||
| 274 | err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); | ||
| 275 | if (err) | ||
| 276 | goto out; | ||
| 277 | |||
| 278 | memcpy(node_guid, out_mad->data + 12, 8); | ||
| 279 | out: | ||
| 280 | kfree(in_mad); | ||
| 281 | kfree(out_mad); | ||
| 282 | return err; | ||
| 283 | } | ||
| 284 | |||
| 285 | int mlx5_query_mad_ifc_pkey(struct ib_device *ibdev, u8 port, u16 index, | ||
| 286 | u16 *pkey) | ||
| 287 | { | ||
| 288 | struct ib_smp *in_mad = NULL; | ||
| 289 | struct ib_smp *out_mad = NULL; | ||
| 290 | int err = -ENOMEM; | ||
| 291 | |||
| 292 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | ||
| 293 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
| 294 | if (!in_mad || !out_mad) | ||
| 295 | goto out; | ||
| 296 | |||
| 297 | init_query_mad(in_mad); | ||
| 298 | in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; | ||
| 299 | in_mad->attr_mod = cpu_to_be32(index / 32); | ||
| 300 | |||
| 301 | err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, | ||
| 302 | out_mad); | ||
| 303 | if (err) | ||
| 304 | goto out; | ||
| 305 | |||
| 306 | *pkey = be16_to_cpu(((__be16 *)out_mad->data)[index % 32]); | ||
| 307 | |||
| 308 | out: | ||
| 309 | kfree(in_mad); | ||
| 310 | kfree(out_mad); | ||
| 311 | return err; | ||
| 312 | } | ||
| 313 | |||
| 314 | int mlx5_query_mad_ifc_gids(struct ib_device *ibdev, u8 port, int index, | ||
| 315 | union ib_gid *gid) | ||
| 316 | { | ||
| 317 | struct ib_smp *in_mad = NULL; | ||
| 318 | struct ib_smp *out_mad = NULL; | ||
| 319 | int err = -ENOMEM; | ||
| 320 | |||
| 321 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | ||
| 322 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
| 323 | if (!in_mad || !out_mad) | ||
| 324 | goto out; | ||
| 325 | |||
| 326 | init_query_mad(in_mad); | ||
| 327 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; | ||
| 328 | in_mad->attr_mod = cpu_to_be32(port); | ||
| 329 | |||
| 330 | err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, | ||
| 331 | out_mad); | ||
| 332 | if (err) | ||
| 333 | goto out; | ||
| 334 | |||
| 335 | memcpy(gid->raw, out_mad->data + 8, 8); | ||
| 336 | |||
| 337 | init_query_mad(in_mad); | ||
| 338 | in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; | ||
| 339 | in_mad->attr_mod = cpu_to_be32(index / 8); | ||
| 340 | |||
| 341 | err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, | ||
| 342 | out_mad); | ||
| 343 | if (err) | ||
| 344 | goto out; | ||
| 345 | |||
| 346 | memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8); | ||
| 347 | |||
| 348 | out: | ||
| 349 | kfree(in_mad); | ||
| 350 | kfree(out_mad); | ||
| 351 | return err; | ||
| 352 | } | ||
| 353 | |||
| 354 | int mlx5_query_mad_ifc_port(struct ib_device *ibdev, u8 port, | ||
| 355 | struct ib_port_attr *props) | ||
| 356 | { | ||
| 357 | struct mlx5_ib_dev *dev = to_mdev(ibdev); | ||
| 358 | struct mlx5_core_dev *mdev = dev->mdev; | ||
| 359 | struct ib_smp *in_mad = NULL; | ||
| 360 | struct ib_smp *out_mad = NULL; | ||
| 361 | int ext_active_speed; | ||
| 362 | int err = -ENOMEM; | ||
| 363 | |||
| 364 | if (port < 1 || port > MLX5_CAP_GEN(mdev, num_ports)) { | ||
| 365 | mlx5_ib_warn(dev, "invalid port number %d\n", port); | ||
| 366 | return -EINVAL; | ||
| 367 | } | ||
| 368 | |||
| 369 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | ||
| 370 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
| 371 | if (!in_mad || !out_mad) | ||
| 372 | goto out; | ||
| 373 | |||
| 374 | memset(props, 0, sizeof(*props)); | ||
| 375 | |||
| 376 | init_query_mad(in_mad); | ||
| 377 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; | ||
| 378 | in_mad->attr_mod = cpu_to_be32(port); | ||
| 379 | |||
| 380 | err = mlx5_MAD_IFC(dev, 1, 1, port, NULL, NULL, in_mad, out_mad); | ||
| 381 | if (err) { | ||
| 382 | mlx5_ib_warn(dev, "err %d\n", err); | ||
| 383 | goto out; | ||
| 384 | } | ||
| 385 | |||
| 386 | props->lid = be16_to_cpup((__be16 *)(out_mad->data + 16)); | ||
| 387 | props->lmc = out_mad->data[34] & 0x7; | ||
| 388 | props->sm_lid = be16_to_cpup((__be16 *)(out_mad->data + 18)); | ||
| 389 | props->sm_sl = out_mad->data[36] & 0xf; | ||
| 390 | props->state = out_mad->data[32] & 0xf; | ||
| 391 | props->phys_state = out_mad->data[33] >> 4; | ||
| 392 | props->port_cap_flags = be32_to_cpup((__be32 *)(out_mad->data + 20)); | ||
| 393 | props->gid_tbl_len = out_mad->data[50]; | ||
| 394 | props->max_msg_sz = 1 << MLX5_CAP_GEN(mdev, log_max_msg); | ||
| 395 | props->pkey_tbl_len = mdev->port_caps[port - 1].pkey_table_len; | ||
| 396 | props->bad_pkey_cntr = be16_to_cpup((__be16 *)(out_mad->data + 46)); | ||
| 397 | props->qkey_viol_cntr = be16_to_cpup((__be16 *)(out_mad->data + 48)); | ||
| 398 | props->active_width = out_mad->data[31] & 0xf; | ||
| 399 | props->active_speed = out_mad->data[35] >> 4; | ||
| 400 | props->max_mtu = out_mad->data[41] & 0xf; | ||
| 401 | props->active_mtu = out_mad->data[36] >> 4; | ||
| 402 | props->subnet_timeout = out_mad->data[51] & 0x1f; | ||
| 403 | props->max_vl_num = out_mad->data[37] >> 4; | ||
| 404 | props->init_type_reply = out_mad->data[41] >> 4; | ||
| 405 | |||
| 406 | /* Check if extended speeds (EDR/FDR/...) are supported */ | ||
| 407 | if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) { | ||
| 408 | ext_active_speed = out_mad->data[62] >> 4; | ||
| 409 | |||
| 410 | switch (ext_active_speed) { | ||
| 411 | case 1: | ||
| 412 | props->active_speed = 16; /* FDR */ | ||
| 413 | break; | ||
| 414 | case 2: | ||
| 415 | props->active_speed = 32; /* EDR */ | ||
| 416 | break; | ||
| 417 | } | ||
| 418 | } | ||
| 419 | |||
| 420 | /* If reported active speed is QDR, check if is FDR-10 */ | ||
| 421 | if (props->active_speed == 4) { | ||
| 422 | if (mdev->port_caps[port - 1].ext_port_cap & | ||
| 423 | MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) { | ||
| 424 | init_query_mad(in_mad); | ||
| 425 | in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO; | ||
| 426 | in_mad->attr_mod = cpu_to_be32(port); | ||
| 427 | |||
| 428 | err = mlx5_MAD_IFC(dev, 1, 1, port, | ||
| 429 | NULL, NULL, in_mad, out_mad); | ||
| 430 | if (err) | ||
| 431 | goto out; | ||
| 432 | |||
| 433 | /* Checking LinkSpeedActive for FDR-10 */ | ||
| 434 | if (out_mad->data[15] & 0x1) | ||
| 435 | props->active_speed = 8; | ||
| 436 | } | ||
| 437 | } | ||
| 438 | |||
| 439 | out: | ||
| 440 | kfree(in_mad); | ||
| 441 | kfree(out_mad); | ||
| 442 | |||
| 443 | return err; | ||
| 444 | } | ||
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 57c9809e8b87..085c24b4b603 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include <linux/io-mapping.h> | 40 | #include <linux/io-mapping.h> |
| 41 | #include <linux/sched.h> | 41 | #include <linux/sched.h> |
| 42 | #include <rdma/ib_user_verbs.h> | 42 | #include <rdma/ib_user_verbs.h> |
| 43 | #include <linux/mlx5/vport.h> | ||
| 43 | #include <rdma/ib_smi.h> | 44 | #include <rdma/ib_smi.h> |
| 44 | #include <rdma/ib_umem.h> | 45 | #include <rdma/ib_umem.h> |
| 45 | #include "user.h" | 46 | #include "user.h" |
| @@ -62,32 +63,172 @@ static char mlx5_version[] = | |||
| 62 | DRIVER_NAME ": Mellanox Connect-IB Infiniband driver v" | 63 | DRIVER_NAME ": Mellanox Connect-IB Infiniband driver v" |
| 63 | DRIVER_VERSION " (" DRIVER_RELDATE ")\n"; | 64 | DRIVER_VERSION " (" DRIVER_RELDATE ")\n"; |
| 64 | 65 | ||
| 66 | static enum rdma_link_layer | ||
| 67 | mlx5_ib_port_link_layer(struct ib_device *device) | ||
| 68 | { | ||
| 69 | struct mlx5_ib_dev *dev = to_mdev(device); | ||
| 70 | |||
| 71 | switch (MLX5_CAP_GEN(dev->mdev, port_type)) { | ||
| 72 | case MLX5_CAP_PORT_TYPE_IB: | ||
| 73 | return IB_LINK_LAYER_INFINIBAND; | ||
| 74 | case MLX5_CAP_PORT_TYPE_ETH: | ||
| 75 | return IB_LINK_LAYER_ETHERNET; | ||
| 76 | default: | ||
| 77 | return IB_LINK_LAYER_UNSPECIFIED; | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | static int mlx5_use_mad_ifc(struct mlx5_ib_dev *dev) | ||
| 82 | { | ||
| 83 | return !dev->mdev->issi; | ||
| 84 | } | ||
| 85 | |||
| 86 | enum { | ||
| 87 | MLX5_VPORT_ACCESS_METHOD_MAD, | ||
| 88 | MLX5_VPORT_ACCESS_METHOD_HCA, | ||
| 89 | MLX5_VPORT_ACCESS_METHOD_NIC, | ||
| 90 | }; | ||
| 91 | |||
| 92 | static int mlx5_get_vport_access_method(struct ib_device *ibdev) | ||
| 93 | { | ||
| 94 | if (mlx5_use_mad_ifc(to_mdev(ibdev))) | ||
| 95 | return MLX5_VPORT_ACCESS_METHOD_MAD; | ||
| 96 | |||
| 97 | if (mlx5_ib_port_link_layer(ibdev) == | ||
| 98 | IB_LINK_LAYER_ETHERNET) | ||
| 99 | return MLX5_VPORT_ACCESS_METHOD_NIC; | ||
| 100 | |||
| 101 | return MLX5_VPORT_ACCESS_METHOD_HCA; | ||
| 102 | } | ||
| 103 | |||
| 104 | static int mlx5_query_system_image_guid(struct ib_device *ibdev, | ||
| 105 | __be64 *sys_image_guid) | ||
| 106 | { | ||
| 107 | struct mlx5_ib_dev *dev = to_mdev(ibdev); | ||
| 108 | struct mlx5_core_dev *mdev = dev->mdev; | ||
| 109 | u64 tmp; | ||
| 110 | int err; | ||
| 111 | |||
| 112 | switch (mlx5_get_vport_access_method(ibdev)) { | ||
| 113 | case MLX5_VPORT_ACCESS_METHOD_MAD: | ||
| 114 | return mlx5_query_mad_ifc_system_image_guid(ibdev, | ||
| 115 | sys_image_guid); | ||
| 116 | |||
| 117 | case MLX5_VPORT_ACCESS_METHOD_HCA: | ||
| 118 | err = mlx5_query_hca_vport_system_image_guid(mdev, &tmp); | ||
| 119 | if (!err) | ||
| 120 | *sys_image_guid = cpu_to_be64(tmp); | ||
| 121 | return err; | ||
| 122 | |||
| 123 | default: | ||
| 124 | return -EINVAL; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | static int mlx5_query_max_pkeys(struct ib_device *ibdev, | ||
| 129 | u16 *max_pkeys) | ||
| 130 | { | ||
| 131 | struct mlx5_ib_dev *dev = to_mdev(ibdev); | ||
| 132 | struct mlx5_core_dev *mdev = dev->mdev; | ||
| 133 | |||
| 134 | switch (mlx5_get_vport_access_method(ibdev)) { | ||
| 135 | case MLX5_VPORT_ACCESS_METHOD_MAD: | ||
| 136 | return mlx5_query_mad_ifc_max_pkeys(ibdev, max_pkeys); | ||
| 137 | |||
| 138 | case MLX5_VPORT_ACCESS_METHOD_HCA: | ||
| 139 | case MLX5_VPORT_ACCESS_METHOD_NIC: | ||
| 140 | *max_pkeys = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(mdev, | ||
| 141 | pkey_table_size)); | ||
| 142 | return 0; | ||
| 143 | |||
| 144 | default: | ||
| 145 | return -EINVAL; | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | static int mlx5_query_vendor_id(struct ib_device *ibdev, | ||
| 150 | u32 *vendor_id) | ||
| 151 | { | ||
| 152 | struct mlx5_ib_dev *dev = to_mdev(ibdev); | ||
| 153 | |||
| 154 | switch (mlx5_get_vport_access_method(ibdev)) { | ||
| 155 | case MLX5_VPORT_ACCESS_METHOD_MAD: | ||
| 156 | return mlx5_query_mad_ifc_vendor_id(ibdev, vendor_id); | ||
| 157 | |||
| 158 | case MLX5_VPORT_ACCESS_METHOD_HCA: | ||
| 159 | case MLX5_VPORT_ACCESS_METHOD_NIC: | ||
| 160 | return mlx5_core_query_vendor_id(dev->mdev, vendor_id); | ||
| 161 | |||
| 162 | default: | ||
| 163 | return -EINVAL; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | static int mlx5_query_node_guid(struct mlx5_ib_dev *dev, | ||
| 168 | __be64 *node_guid) | ||
| 169 | { | ||
| 170 | u64 tmp; | ||
| 171 | int err; | ||
| 172 | |||
| 173 | switch (mlx5_get_vport_access_method(&dev->ib_dev)) { | ||
| 174 | case MLX5_VPORT_ACCESS_METHOD_MAD: | ||
| 175 | return mlx5_query_mad_ifc_node_guid(dev, node_guid); | ||
| 176 | |||
| 177 | case MLX5_VPORT_ACCESS_METHOD_HCA: | ||
| 178 | err = mlx5_query_hca_vport_node_guid(dev->mdev, &tmp); | ||
| 179 | if (!err) | ||
| 180 | *node_guid = cpu_to_be64(tmp); | ||
| 181 | return err; | ||
| 182 | |||
| 183 | default: | ||
| 184 | return -EINVAL; | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | struct mlx5_reg_node_desc { | ||
| 189 | u8 desc[64]; | ||
| 190 | }; | ||
| 191 | |||
| 192 | static int mlx5_query_node_desc(struct mlx5_ib_dev *dev, char *node_desc) | ||
| 193 | { | ||
| 194 | struct mlx5_reg_node_desc in; | ||
| 195 | |||
| 196 | if (mlx5_use_mad_ifc(dev)) | ||
| 197 | return mlx5_query_mad_ifc_node_desc(dev, node_desc); | ||
| 198 | |||
| 199 | memset(&in, 0, sizeof(in)); | ||
| 200 | |||
| 201 | return mlx5_core_access_reg(dev->mdev, &in, sizeof(in), node_desc, | ||
| 202 | sizeof(struct mlx5_reg_node_desc), | ||
| 203 | MLX5_REG_NODE_DESC, 0, 0); | ||
| 204 | } | ||
| 205 | |||
| 65 | static int mlx5_ib_query_device(struct ib_device *ibdev, | 206 | static int mlx5_ib_query_device(struct ib_device *ibdev, |
| 66 | struct ib_device_attr *props) | 207 | struct ib_device_attr *props, |
| 208 | struct ib_udata *uhw) | ||
| 67 | { | 209 | { |
| 68 | struct mlx5_ib_dev *dev = to_mdev(ibdev); | 210 | struct mlx5_ib_dev *dev = to_mdev(ibdev); |
| 69 | struct ib_smp *in_mad = NULL; | 211 | struct mlx5_core_dev *mdev = dev->mdev; |
| 70 | struct ib_smp *out_mad = NULL; | ||
| 71 | struct mlx5_general_caps *gen; | ||
| 72 | int err = -ENOMEM; | 212 | int err = -ENOMEM; |
| 73 | int max_rq_sg; | 213 | int max_rq_sg; |
| 74 | int max_sq_sg; | 214 | int max_sq_sg; |
| 75 | u64 flags; | ||
| 76 | 215 | ||
| 77 | gen = &dev->mdev->caps.gen; | 216 | if (uhw->inlen || uhw->outlen) |
| 78 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | 217 | return -EINVAL; |
| 79 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
| 80 | if (!in_mad || !out_mad) | ||
| 81 | goto out; | ||
| 82 | 218 | ||
| 83 | init_query_mad(in_mad); | 219 | memset(props, 0, sizeof(*props)); |
| 84 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; | 220 | err = mlx5_query_system_image_guid(ibdev, |
| 221 | &props->sys_image_guid); | ||
| 222 | if (err) | ||
| 223 | return err; | ||
| 85 | 224 | ||
| 86 | err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad, out_mad); | 225 | err = mlx5_query_max_pkeys(ibdev, &props->max_pkeys); |
| 87 | if (err) | 226 | if (err) |
| 88 | goto out; | 227 | return err; |
| 89 | 228 | ||
| 90 | memset(props, 0, sizeof(*props)); | 229 | err = mlx5_query_vendor_id(ibdev, &props->vendor_id); |
| 230 | if (err) | ||
| 231 | return err; | ||
| 91 | 232 | ||
| 92 | props->fw_ver = ((u64)fw_rev_maj(dev->mdev) << 32) | | 233 | props->fw_ver = ((u64)fw_rev_maj(dev->mdev) << 32) | |
| 93 | (fw_rev_min(dev->mdev) << 16) | | 234 | (fw_rev_min(dev->mdev) << 16) | |
| @@ -96,18 +237,18 @@ static int mlx5_ib_query_device(struct ib_device *ibdev, | |||
| 96 | IB_DEVICE_PORT_ACTIVE_EVENT | | 237 | IB_DEVICE_PORT_ACTIVE_EVENT | |
| 97 | IB_DEVICE_SYS_IMAGE_GUID | | 238 | IB_DEVICE_SYS_IMAGE_GUID | |
| 98 | IB_DEVICE_RC_RNR_NAK_GEN; | 239 | IB_DEVICE_RC_RNR_NAK_GEN; |
| 99 | flags = gen->flags; | 240 | |
| 100 | if (flags & MLX5_DEV_CAP_FLAG_BAD_PKEY_CNTR) | 241 | if (MLX5_CAP_GEN(mdev, pkv)) |
| 101 | props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR; | 242 | props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR; |
| 102 | if (flags & MLX5_DEV_CAP_FLAG_BAD_QKEY_CNTR) | 243 | if (MLX5_CAP_GEN(mdev, qkv)) |
| 103 | props->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR; | 244 | props->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR; |
| 104 | if (flags & MLX5_DEV_CAP_FLAG_APM) | 245 | if (MLX5_CAP_GEN(mdev, apm)) |
| 105 | props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG; | 246 | props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG; |
| 106 | props->device_cap_flags |= IB_DEVICE_LOCAL_DMA_LKEY; | 247 | props->device_cap_flags |= IB_DEVICE_LOCAL_DMA_LKEY; |
| 107 | if (flags & MLX5_DEV_CAP_FLAG_XRC) | 248 | if (MLX5_CAP_GEN(mdev, xrc)) |
| 108 | props->device_cap_flags |= IB_DEVICE_XRC; | 249 | props->device_cap_flags |= IB_DEVICE_XRC; |
| 109 | props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS; | 250 | props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS; |
| 110 | if (flags & MLX5_DEV_CAP_FLAG_SIG_HAND_OVER) { | 251 | if (MLX5_CAP_GEN(mdev, sho)) { |
| 111 | props->device_cap_flags |= IB_DEVICE_SIGNATURE_HANDOVER; | 252 | props->device_cap_flags |= IB_DEVICE_SIGNATURE_HANDOVER; |
| 112 | /* At this stage no support for signature handover */ | 253 | /* At this stage no support for signature handover */ |
| 113 | props->sig_prot_cap = IB_PROT_T10DIF_TYPE_1 | | 254 | props->sig_prot_cap = IB_PROT_T10DIF_TYPE_1 | |
| @@ -116,221 +257,270 @@ static int mlx5_ib_query_device(struct ib_device *ibdev, | |||
| 116 | props->sig_guard_cap = IB_GUARD_T10DIF_CRC | | 257 | props->sig_guard_cap = IB_GUARD_T10DIF_CRC | |
| 117 | IB_GUARD_T10DIF_CSUM; | 258 | IB_GUARD_T10DIF_CSUM; |
| 118 | } | 259 | } |
| 119 | if (flags & MLX5_DEV_CAP_FLAG_BLOCK_MCAST) | 260 | if (MLX5_CAP_GEN(mdev, block_lb_mc)) |
| 120 | props->device_cap_flags |= IB_DEVICE_BLOCK_MULTICAST_LOOPBACK; | 261 | props->device_cap_flags |= IB_DEVICE_BLOCK_MULTICAST_LOOPBACK; |
| 121 | 262 | ||
| 122 | props->vendor_id = be32_to_cpup((__be32 *)(out_mad->data + 36)) & | 263 | props->vendor_part_id = mdev->pdev->device; |
| 123 | 0xffffff; | 264 | props->hw_ver = mdev->pdev->revision; |
| 124 | props->vendor_part_id = be16_to_cpup((__be16 *)(out_mad->data + 30)); | ||
| 125 | props->hw_ver = be32_to_cpup((__be32 *)(out_mad->data + 32)); | ||
| 126 | memcpy(&props->sys_image_guid, out_mad->data + 4, 8); | ||
| 127 | 265 | ||
| 128 | props->max_mr_size = ~0ull; | 266 | props->max_mr_size = ~0ull; |
| 129 | props->page_size_cap = gen->min_page_sz; | 267 | props->page_size_cap = 1ull << MLX5_CAP_GEN(mdev, log_pg_sz); |
| 130 | props->max_qp = 1 << gen->log_max_qp; | 268 | props->max_qp = 1 << MLX5_CAP_GEN(mdev, log_max_qp); |
| 131 | props->max_qp_wr = gen->max_wqes; | 269 | props->max_qp_wr = 1 << MLX5_CAP_GEN(mdev, log_max_qp_sz); |
| 132 | max_rq_sg = gen->max_rq_desc_sz / sizeof(struct mlx5_wqe_data_seg); | 270 | max_rq_sg = MLX5_CAP_GEN(mdev, max_wqe_sz_rq) / |
| 133 | max_sq_sg = (gen->max_sq_desc_sz - sizeof(struct mlx5_wqe_ctrl_seg)) / | 271 | sizeof(struct mlx5_wqe_data_seg); |
| 134 | sizeof(struct mlx5_wqe_data_seg); | 272 | max_sq_sg = (MLX5_CAP_GEN(mdev, max_wqe_sz_sq) - |
| 273 | sizeof(struct mlx5_wqe_ctrl_seg)) / | ||
| 274 | sizeof(struct mlx5_wqe_data_seg); | ||
| 135 | props->max_sge = min(max_rq_sg, max_sq_sg); | 275 | props->max_sge = min(max_rq_sg, max_sq_sg); |
| 136 | props->max_cq = 1 << gen->log_max_cq; | 276 | props->max_cq = 1 << MLX5_CAP_GEN(mdev, log_max_cq); |
| 137 | props->max_cqe = gen->max_cqes - 1; | 277 | props->max_cqe = (1 << MLX5_CAP_GEN(mdev, log_max_eq_sz)) - 1; |
| 138 | props->max_mr = 1 << gen->log_max_mkey; | 278 | props->max_mr = 1 << MLX5_CAP_GEN(mdev, log_max_mkey); |
| 139 | props->max_pd = 1 << gen->log_max_pd; | 279 | props->max_pd = 1 << MLX5_CAP_GEN(mdev, log_max_pd); |
| 140 | props->max_qp_rd_atom = 1 << gen->log_max_ra_req_qp; | 280 | props->max_qp_rd_atom = 1 << MLX5_CAP_GEN(mdev, log_max_ra_req_qp); |
| 141 | props->max_qp_init_rd_atom = 1 << gen->log_max_ra_res_qp; | 281 | props->max_qp_init_rd_atom = 1 << MLX5_CAP_GEN(mdev, log_max_ra_res_qp); |
| 142 | props->max_srq = 1 << gen->log_max_srq; | 282 | props->max_srq = 1 << MLX5_CAP_GEN(mdev, log_max_srq); |
| 143 | props->max_srq_wr = gen->max_srq_wqes - 1; | 283 | props->max_srq_wr = (1 << MLX5_CAP_GEN(mdev, log_max_srq_sz)) - 1; |
| 144 | props->local_ca_ack_delay = gen->local_ca_ack_delay; | 284 | props->local_ca_ack_delay = MLX5_CAP_GEN(mdev, local_ca_ack_delay); |
| 145 | props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp; | 285 | props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp; |
| 146 | props->max_srq_sge = max_rq_sg - 1; | 286 | props->max_srq_sge = max_rq_sg - 1; |
| 147 | props->max_fast_reg_page_list_len = (unsigned int)-1; | 287 | props->max_fast_reg_page_list_len = (unsigned int)-1; |
| 148 | props->local_ca_ack_delay = gen->local_ca_ack_delay; | ||
| 149 | props->atomic_cap = IB_ATOMIC_NONE; | 288 | props->atomic_cap = IB_ATOMIC_NONE; |
| 150 | props->masked_atomic_cap = IB_ATOMIC_NONE; | 289 | props->masked_atomic_cap = IB_ATOMIC_NONE; |
| 151 | props->max_pkeys = be16_to_cpup((__be16 *)(out_mad->data + 28)); | 290 | props->max_mcast_grp = 1 << MLX5_CAP_GEN(mdev, log_max_mcg); |
| 152 | props->max_mcast_grp = 1 << gen->log_max_mcg; | 291 | props->max_mcast_qp_attach = MLX5_CAP_GEN(mdev, max_qp_mcg); |
| 153 | props->max_mcast_qp_attach = gen->max_qp_mcg; | ||
| 154 | props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * | 292 | props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * |
| 155 | props->max_mcast_grp; | 293 | props->max_mcast_grp; |
| 156 | props->max_map_per_fmr = INT_MAX; /* no limit in ConnectIB */ | 294 | props->max_map_per_fmr = INT_MAX; /* no limit in ConnectIB */ |
| 157 | 295 | ||
| 158 | #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING | 296 | #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING |
| 159 | if (dev->mdev->caps.gen.flags & MLX5_DEV_CAP_FLAG_ON_DMND_PG) | 297 | if (MLX5_CAP_GEN(mdev, pg)) |
| 160 | props->device_cap_flags |= IB_DEVICE_ON_DEMAND_PAGING; | 298 | props->device_cap_flags |= IB_DEVICE_ON_DEMAND_PAGING; |
| 161 | props->odp_caps = dev->odp_caps; | 299 | props->odp_caps = dev->odp_caps; |
| 162 | #endif | 300 | #endif |
| 163 | 301 | ||
| 164 | out: | 302 | return 0; |
| 165 | kfree(in_mad); | ||
| 166 | kfree(out_mad); | ||
| 167 | |||
| 168 | return err; | ||
| 169 | } | 303 | } |
| 170 | 304 | ||
| 171 | int mlx5_ib_query_port(struct ib_device *ibdev, u8 port, | 305 | enum mlx5_ib_width { |
| 172 | struct ib_port_attr *props) | 306 | MLX5_IB_WIDTH_1X = 1 << 0, |
| 307 | MLX5_IB_WIDTH_2X = 1 << 1, | ||
| 308 | MLX5_IB_WIDTH_4X = 1 << 2, | ||
| 309 | MLX5_IB_WIDTH_8X = 1 << 3, | ||
| 310 | MLX5_IB_WIDTH_12X = 1 << 4 | ||
| 311 | }; | ||
| 312 | |||
| 313 | static int translate_active_width(struct ib_device *ibdev, u8 active_width, | ||
| 314 | u8 *ib_width) | ||
| 173 | { | 315 | { |
| 174 | struct mlx5_ib_dev *dev = to_mdev(ibdev); | 316 | struct mlx5_ib_dev *dev = to_mdev(ibdev); |
| 175 | struct ib_smp *in_mad = NULL; | 317 | int err = 0; |
| 176 | struct ib_smp *out_mad = NULL; | 318 | |
| 177 | struct mlx5_general_caps *gen; | 319 | if (active_width & MLX5_IB_WIDTH_1X) { |
| 178 | int ext_active_speed; | 320 | *ib_width = IB_WIDTH_1X; |
| 179 | int err = -ENOMEM; | 321 | } else if (active_width & MLX5_IB_WIDTH_2X) { |
| 180 | 322 | mlx5_ib_dbg(dev, "active_width %d is not supported by IB spec\n", | |
| 181 | gen = &dev->mdev->caps.gen; | 323 | (int)active_width); |
| 182 | if (port < 1 || port > gen->num_ports) { | 324 | err = -EINVAL; |
| 183 | mlx5_ib_warn(dev, "invalid port number %d\n", port); | 325 | } else if (active_width & MLX5_IB_WIDTH_4X) { |
| 184 | return -EINVAL; | 326 | *ib_width = IB_WIDTH_4X; |
| 327 | } else if (active_width & MLX5_IB_WIDTH_8X) { | ||
| 328 | *ib_width = IB_WIDTH_8X; | ||
| 329 | } else if (active_width & MLX5_IB_WIDTH_12X) { | ||
| 330 | *ib_width = IB_WIDTH_12X; | ||
| 331 | } else { | ||
| 332 | mlx5_ib_dbg(dev, "Invalid active_width %d\n", | ||
| 333 | (int)active_width); | ||
| 334 | err = -EINVAL; | ||
| 185 | } | 335 | } |
| 186 | 336 | ||
| 187 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | 337 | return err; |
| 188 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | 338 | } |
| 189 | if (!in_mad || !out_mad) | ||
| 190 | goto out; | ||
| 191 | |||
| 192 | memset(props, 0, sizeof(*props)); | ||
| 193 | |||
| 194 | init_query_mad(in_mad); | ||
| 195 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; | ||
| 196 | in_mad->attr_mod = cpu_to_be32(port); | ||
| 197 | 339 | ||
| 198 | err = mlx5_MAD_IFC(dev, 1, 1, port, NULL, NULL, in_mad, out_mad); | 340 | static int mlx5_mtu_to_ib_mtu(int mtu) |
| 199 | if (err) { | 341 | { |
| 200 | mlx5_ib_warn(dev, "err %d\n", err); | 342 | switch (mtu) { |
| 201 | goto out; | 343 | case 256: return 1; |
| 344 | case 512: return 2; | ||
| 345 | case 1024: return 3; | ||
| 346 | case 2048: return 4; | ||
| 347 | case 4096: return 5; | ||
| 348 | default: | ||
| 349 | pr_warn("invalid mtu\n"); | ||
| 350 | return -1; | ||
| 202 | } | 351 | } |
| 352 | } | ||
| 203 | 353 | ||
| 354 | enum ib_max_vl_num { | ||
| 355 | __IB_MAX_VL_0 = 1, | ||
| 356 | __IB_MAX_VL_0_1 = 2, | ||
| 357 | __IB_MAX_VL_0_3 = 3, | ||
| 358 | __IB_MAX_VL_0_7 = 4, | ||
| 359 | __IB_MAX_VL_0_14 = 5, | ||
| 360 | }; | ||
| 204 | 361 | ||
| 205 | props->lid = be16_to_cpup((__be16 *)(out_mad->data + 16)); | 362 | enum mlx5_vl_hw_cap { |
| 206 | props->lmc = out_mad->data[34] & 0x7; | 363 | MLX5_VL_HW_0 = 1, |
| 207 | props->sm_lid = be16_to_cpup((__be16 *)(out_mad->data + 18)); | 364 | MLX5_VL_HW_0_1 = 2, |
| 208 | props->sm_sl = out_mad->data[36] & 0xf; | 365 | MLX5_VL_HW_0_2 = 3, |
| 209 | props->state = out_mad->data[32] & 0xf; | 366 | MLX5_VL_HW_0_3 = 4, |
| 210 | props->phys_state = out_mad->data[33] >> 4; | 367 | MLX5_VL_HW_0_4 = 5, |
| 211 | props->port_cap_flags = be32_to_cpup((__be32 *)(out_mad->data + 20)); | 368 | MLX5_VL_HW_0_5 = 6, |
| 212 | props->gid_tbl_len = out_mad->data[50]; | 369 | MLX5_VL_HW_0_6 = 7, |
| 213 | props->max_msg_sz = 1 << gen->log_max_msg; | 370 | MLX5_VL_HW_0_7 = 8, |
| 214 | props->pkey_tbl_len = gen->port[port - 1].pkey_table_len; | 371 | MLX5_VL_HW_0_14 = 15 |
| 215 | props->bad_pkey_cntr = be16_to_cpup((__be16 *)(out_mad->data + 46)); | 372 | }; |
| 216 | props->qkey_viol_cntr = be16_to_cpup((__be16 *)(out_mad->data + 48)); | ||
| 217 | props->active_width = out_mad->data[31] & 0xf; | ||
| 218 | props->active_speed = out_mad->data[35] >> 4; | ||
| 219 | props->max_mtu = out_mad->data[41] & 0xf; | ||
| 220 | props->active_mtu = out_mad->data[36] >> 4; | ||
| 221 | props->subnet_timeout = out_mad->data[51] & 0x1f; | ||
| 222 | props->max_vl_num = out_mad->data[37] >> 4; | ||
| 223 | props->init_type_reply = out_mad->data[41] >> 4; | ||
| 224 | |||
| 225 | /* Check if extended speeds (EDR/FDR/...) are supported */ | ||
| 226 | if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) { | ||
| 227 | ext_active_speed = out_mad->data[62] >> 4; | ||
| 228 | |||
| 229 | switch (ext_active_speed) { | ||
| 230 | case 1: | ||
| 231 | props->active_speed = 16; /* FDR */ | ||
| 232 | break; | ||
| 233 | case 2: | ||
| 234 | props->active_speed = 32; /* EDR */ | ||
| 235 | break; | ||
| 236 | } | ||
| 237 | } | ||
| 238 | 373 | ||
| 239 | /* If reported active speed is QDR, check if is FDR-10 */ | 374 | static int translate_max_vl_num(struct ib_device *ibdev, u8 vl_hw_cap, |
| 240 | if (props->active_speed == 4) { | 375 | u8 *max_vl_num) |
| 241 | if (gen->ext_port_cap[port - 1] & | 376 | { |
| 242 | MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) { | 377 | switch (vl_hw_cap) { |
| 243 | init_query_mad(in_mad); | 378 | case MLX5_VL_HW_0: |
| 244 | in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO; | 379 | *max_vl_num = __IB_MAX_VL_0; |
| 245 | in_mad->attr_mod = cpu_to_be32(port); | 380 | break; |
| 246 | 381 | case MLX5_VL_HW_0_1: | |
| 247 | err = mlx5_MAD_IFC(dev, 1, 1, port, | 382 | *max_vl_num = __IB_MAX_VL_0_1; |
| 248 | NULL, NULL, in_mad, out_mad); | 383 | break; |
| 249 | if (err) | 384 | case MLX5_VL_HW_0_3: |
| 250 | goto out; | 385 | *max_vl_num = __IB_MAX_VL_0_3; |
| 251 | 386 | break; | |
| 252 | /* Checking LinkSpeedActive for FDR-10 */ | 387 | case MLX5_VL_HW_0_7: |
| 253 | if (out_mad->data[15] & 0x1) | 388 | *max_vl_num = __IB_MAX_VL_0_7; |
| 254 | props->active_speed = 8; | 389 | break; |
| 255 | } | 390 | case MLX5_VL_HW_0_14: |
| 256 | } | 391 | *max_vl_num = __IB_MAX_VL_0_14; |
| 392 | break; | ||
| 257 | 393 | ||
| 258 | out: | 394 | default: |
| 259 | kfree(in_mad); | 395 | return -EINVAL; |
| 260 | kfree(out_mad); | 396 | } |
| 261 | 397 | ||
| 262 | return err; | 398 | return 0; |
| 263 | } | 399 | } |
| 264 | 400 | ||
| 265 | static int mlx5_ib_query_gid(struct ib_device *ibdev, u8 port, int index, | 401 | static int mlx5_query_hca_port(struct ib_device *ibdev, u8 port, |
| 266 | union ib_gid *gid) | 402 | struct ib_port_attr *props) |
| 267 | { | 403 | { |
| 268 | struct ib_smp *in_mad = NULL; | 404 | struct mlx5_ib_dev *dev = to_mdev(ibdev); |
| 269 | struct ib_smp *out_mad = NULL; | 405 | struct mlx5_core_dev *mdev = dev->mdev; |
| 270 | int err = -ENOMEM; | 406 | struct mlx5_hca_vport_context *rep; |
| 407 | int max_mtu; | ||
| 408 | int oper_mtu; | ||
| 409 | int err; | ||
| 410 | u8 ib_link_width_oper; | ||
| 411 | u8 vl_hw_cap; | ||
| 271 | 412 | ||
| 272 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | 413 | rep = kzalloc(sizeof(*rep), GFP_KERNEL); |
| 273 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | 414 | if (!rep) { |
| 274 | if (!in_mad || !out_mad) | 415 | err = -ENOMEM; |
| 275 | goto out; | 416 | goto out; |
| 417 | } | ||
| 276 | 418 | ||
| 277 | init_query_mad(in_mad); | 419 | memset(props, 0, sizeof(*props)); |
| 278 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; | ||
| 279 | in_mad->attr_mod = cpu_to_be32(port); | ||
| 280 | 420 | ||
| 281 | err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); | 421 | err = mlx5_query_hca_vport_context(mdev, 0, port, 0, rep); |
| 282 | if (err) | 422 | if (err) |
| 283 | goto out; | 423 | goto out; |
| 284 | 424 | ||
| 285 | memcpy(gid->raw, out_mad->data + 8, 8); | 425 | props->lid = rep->lid; |
| 286 | 426 | props->lmc = rep->lmc; | |
| 287 | init_query_mad(in_mad); | 427 | props->sm_lid = rep->sm_lid; |
| 288 | in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; | 428 | props->sm_sl = rep->sm_sl; |
| 289 | in_mad->attr_mod = cpu_to_be32(index / 8); | 429 | props->state = rep->vport_state; |
| 430 | props->phys_state = rep->port_physical_state; | ||
| 431 | props->port_cap_flags = rep->cap_mask1; | ||
| 432 | props->gid_tbl_len = mlx5_get_gid_table_len(MLX5_CAP_GEN(mdev, gid_table_size)); | ||
| 433 | props->max_msg_sz = 1 << MLX5_CAP_GEN(mdev, log_max_msg); | ||
| 434 | props->pkey_tbl_len = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(mdev, pkey_table_size)); | ||
| 435 | props->bad_pkey_cntr = rep->pkey_violation_counter; | ||
| 436 | props->qkey_viol_cntr = rep->qkey_violation_counter; | ||
| 437 | props->subnet_timeout = rep->subnet_timeout; | ||
| 438 | props->init_type_reply = rep->init_type_reply; | ||
| 439 | |||
| 440 | err = mlx5_query_port_link_width_oper(mdev, &ib_link_width_oper, port); | ||
| 441 | if (err) | ||
| 442 | goto out; | ||
| 290 | 443 | ||
| 291 | err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); | 444 | err = translate_active_width(ibdev, ib_link_width_oper, |
| 445 | &props->active_width); | ||
| 446 | if (err) | ||
| 447 | goto out; | ||
| 448 | err = mlx5_query_port_proto_oper(mdev, &props->active_speed, MLX5_PTYS_IB, | ||
| 449 | port); | ||
| 292 | if (err) | 450 | if (err) |
| 293 | goto out; | 451 | goto out; |
| 294 | 452 | ||
| 295 | memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8); | 453 | mlx5_query_port_max_mtu(mdev, &max_mtu, port); |
| 454 | |||
| 455 | props->max_mtu = mlx5_mtu_to_ib_mtu(max_mtu); | ||
| 456 | |||
| 457 | mlx5_query_port_oper_mtu(mdev, &oper_mtu, port); | ||
| 458 | |||
| 459 | props->active_mtu = mlx5_mtu_to_ib_mtu(oper_mtu); | ||
| 296 | 460 | ||
| 461 | err = mlx5_query_port_vl_hw_cap(mdev, &vl_hw_cap, port); | ||
| 462 | if (err) | ||
| 463 | goto out; | ||
| 464 | |||
| 465 | err = translate_max_vl_num(ibdev, vl_hw_cap, | ||
| 466 | &props->max_vl_num); | ||
| 297 | out: | 467 | out: |
| 298 | kfree(in_mad); | 468 | kfree(rep); |
| 299 | kfree(out_mad); | ||
| 300 | return err; | 469 | return err; |
| 301 | } | 470 | } |
| 302 | 471 | ||
| 303 | static int mlx5_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, | 472 | int mlx5_ib_query_port(struct ib_device *ibdev, u8 port, |
| 304 | u16 *pkey) | 473 | struct ib_port_attr *props) |
| 305 | { | 474 | { |
| 306 | struct ib_smp *in_mad = NULL; | 475 | switch (mlx5_get_vport_access_method(ibdev)) { |
| 307 | struct ib_smp *out_mad = NULL; | 476 | case MLX5_VPORT_ACCESS_METHOD_MAD: |
| 308 | int err = -ENOMEM; | 477 | return mlx5_query_mad_ifc_port(ibdev, port, props); |
| 309 | 478 | ||
| 310 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | 479 | case MLX5_VPORT_ACCESS_METHOD_HCA: |
| 311 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | 480 | return mlx5_query_hca_port(ibdev, port, props); |
| 312 | if (!in_mad || !out_mad) | ||
| 313 | goto out; | ||
| 314 | 481 | ||
| 315 | init_query_mad(in_mad); | 482 | default: |
| 316 | in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; | 483 | return -EINVAL; |
| 317 | in_mad->attr_mod = cpu_to_be32(index / 32); | 484 | } |
| 485 | } | ||
| 318 | 486 | ||
| 319 | err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); | 487 | static int mlx5_ib_query_gid(struct ib_device *ibdev, u8 port, int index, |
| 320 | if (err) | 488 | union ib_gid *gid) |
| 321 | goto out; | 489 | { |
| 490 | struct mlx5_ib_dev *dev = to_mdev(ibdev); | ||
| 491 | struct mlx5_core_dev *mdev = dev->mdev; | ||
| 322 | 492 | ||
| 323 | *pkey = be16_to_cpu(((__be16 *)out_mad->data)[index % 32]); | 493 | switch (mlx5_get_vport_access_method(ibdev)) { |
| 494 | case MLX5_VPORT_ACCESS_METHOD_MAD: | ||
| 495 | return mlx5_query_mad_ifc_gids(ibdev, port, index, gid); | ||
| 496 | |||
| 497 | case MLX5_VPORT_ACCESS_METHOD_HCA: | ||
| 498 | return mlx5_query_hca_vport_gid(mdev, 0, port, 0, index, gid); | ||
| 499 | |||
| 500 | default: | ||
| 501 | return -EINVAL; | ||
| 502 | } | ||
| 324 | 503 | ||
| 325 | out: | ||
| 326 | kfree(in_mad); | ||
| 327 | kfree(out_mad); | ||
| 328 | return err; | ||
| 329 | } | 504 | } |
| 330 | 505 | ||
| 331 | struct mlx5_reg_node_desc { | 506 | static int mlx5_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, |
| 332 | u8 desc[64]; | 507 | u16 *pkey) |
| 333 | }; | 508 | { |
| 509 | struct mlx5_ib_dev *dev = to_mdev(ibdev); | ||
| 510 | struct mlx5_core_dev *mdev = dev->mdev; | ||
| 511 | |||
| 512 | switch (mlx5_get_vport_access_method(ibdev)) { | ||
| 513 | case MLX5_VPORT_ACCESS_METHOD_MAD: | ||
| 514 | return mlx5_query_mad_ifc_pkey(ibdev, port, index, pkey); | ||
| 515 | |||
| 516 | case MLX5_VPORT_ACCESS_METHOD_HCA: | ||
| 517 | case MLX5_VPORT_ACCESS_METHOD_NIC: | ||
| 518 | return mlx5_query_hca_vport_pkey(mdev, 0, port, 0, index, | ||
| 519 | pkey); | ||
| 520 | default: | ||
| 521 | return -EINVAL; | ||
| 522 | } | ||
| 523 | } | ||
| 334 | 524 | ||
| 335 | static int mlx5_ib_modify_device(struct ib_device *ibdev, int mask, | 525 | static int mlx5_ib_modify_device(struct ib_device *ibdev, int mask, |
| 336 | struct ib_device_modify *props) | 526 | struct ib_device_modify *props) |
| @@ -392,7 +582,6 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev, | |||
| 392 | struct mlx5_ib_alloc_ucontext_req_v2 req; | 582 | struct mlx5_ib_alloc_ucontext_req_v2 req; |
| 393 | struct mlx5_ib_alloc_ucontext_resp resp; | 583 | struct mlx5_ib_alloc_ucontext_resp resp; |
| 394 | struct mlx5_ib_ucontext *context; | 584 | struct mlx5_ib_ucontext *context; |
| 395 | struct mlx5_general_caps *gen; | ||
| 396 | struct mlx5_uuar_info *uuari; | 585 | struct mlx5_uuar_info *uuari; |
| 397 | struct mlx5_uar *uars; | 586 | struct mlx5_uar *uars; |
| 398 | int gross_uuars; | 587 | int gross_uuars; |
| @@ -403,7 +592,6 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev, | |||
| 403 | int i; | 592 | int i; |
| 404 | size_t reqlen; | 593 | size_t reqlen; |
| 405 | 594 | ||
| 406 | gen = &dev->mdev->caps.gen; | ||
| 407 | if (!dev->ib_active) | 595 | if (!dev->ib_active) |
| 408 | return ERR_PTR(-EAGAIN); | 596 | return ERR_PTR(-EAGAIN); |
| 409 | 597 | ||
| @@ -436,14 +624,14 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev, | |||
| 436 | 624 | ||
| 437 | num_uars = req.total_num_uuars / MLX5_NON_FP_BF_REGS_PER_PAGE; | 625 | num_uars = req.total_num_uuars / MLX5_NON_FP_BF_REGS_PER_PAGE; |
| 438 | gross_uuars = num_uars * MLX5_BF_REGS_PER_PAGE; | 626 | gross_uuars = num_uars * MLX5_BF_REGS_PER_PAGE; |
| 439 | resp.qp_tab_size = 1 << gen->log_max_qp; | 627 | resp.qp_tab_size = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp); |
| 440 | resp.bf_reg_size = gen->bf_reg_size; | 628 | resp.bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev, log_bf_reg_size); |
| 441 | resp.cache_line_size = L1_CACHE_BYTES; | 629 | resp.cache_line_size = L1_CACHE_BYTES; |
| 442 | resp.max_sq_desc_sz = gen->max_sq_desc_sz; | 630 | resp.max_sq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq); |
| 443 | resp.max_rq_desc_sz = gen->max_rq_desc_sz; | 631 | resp.max_rq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq); |
| 444 | resp.max_send_wqebb = gen->max_wqes; | 632 | resp.max_send_wqebb = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz); |
| 445 | resp.max_recv_wr = gen->max_wqes; | 633 | resp.max_recv_wr = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz); |
| 446 | resp.max_srq_recv_wr = gen->max_srq_wqes; | 634 | resp.max_srq_recv_wr = 1 << MLX5_CAP_GEN(dev->mdev, log_max_srq_sz); |
| 447 | 635 | ||
| 448 | context = kzalloc(sizeof(*context), GFP_KERNEL); | 636 | context = kzalloc(sizeof(*context), GFP_KERNEL); |
| 449 | if (!context) | 637 | if (!context) |
| @@ -493,7 +681,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev, | |||
| 493 | mutex_init(&context->db_page_mutex); | 681 | mutex_init(&context->db_page_mutex); |
| 494 | 682 | ||
| 495 | resp.tot_uuars = req.total_num_uuars; | 683 | resp.tot_uuars = req.total_num_uuars; |
| 496 | resp.num_ports = gen->num_ports; | 684 | resp.num_ports = MLX5_CAP_GEN(dev->mdev, num_ports); |
| 497 | err = ib_copy_to_udata(udata, &resp, | 685 | err = ib_copy_to_udata(udata, &resp, |
| 498 | sizeof(resp) - sizeof(resp.reserved)); | 686 | sizeof(resp) - sizeof(resp.reserved)); |
| 499 | if (err) | 687 | if (err) |
| @@ -731,37 +919,15 @@ static int mlx5_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
| 731 | 919 | ||
| 732 | static int init_node_data(struct mlx5_ib_dev *dev) | 920 | static int init_node_data(struct mlx5_ib_dev *dev) |
| 733 | { | 921 | { |
| 734 | struct ib_smp *in_mad = NULL; | 922 | int err; |
| 735 | struct ib_smp *out_mad = NULL; | ||
| 736 | int err = -ENOMEM; | ||
| 737 | |||
| 738 | in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); | ||
| 739 | out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); | ||
| 740 | if (!in_mad || !out_mad) | ||
| 741 | goto out; | ||
| 742 | |||
| 743 | init_query_mad(in_mad); | ||
| 744 | in_mad->attr_id = IB_SMP_ATTR_NODE_DESC; | ||
| 745 | |||
| 746 | err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); | ||
| 747 | if (err) | ||
| 748 | goto out; | ||
| 749 | |||
| 750 | memcpy(dev->ib_dev.node_desc, out_mad->data, 64); | ||
| 751 | |||
| 752 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; | ||
| 753 | 923 | ||
| 754 | err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); | 924 | err = mlx5_query_node_desc(dev, dev->ib_dev.node_desc); |
| 755 | if (err) | 925 | if (err) |
| 756 | goto out; | 926 | return err; |
| 757 | 927 | ||
| 758 | dev->mdev->rev_id = be32_to_cpup((__be32 *)(out_mad->data + 32)); | 928 | dev->mdev->rev_id = dev->mdev->pdev->revision; |
| 759 | memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8); | ||
| 760 | 929 | ||
| 761 | out: | 930 | return mlx5_query_node_guid(dev, &dev->ib_dev.node_guid); |
| 762 | kfree(in_mad); | ||
| 763 | kfree(out_mad); | ||
| 764 | return err; | ||
| 765 | } | 931 | } |
| 766 | 932 | ||
| 767 | static ssize_t show_fw_pages(struct device *device, struct device_attribute *attr, | 933 | static ssize_t show_fw_pages(struct device *device, struct device_attribute *attr, |
| @@ -895,11 +1061,9 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context, | |||
| 895 | 1061 | ||
| 896 | static void get_ext_port_caps(struct mlx5_ib_dev *dev) | 1062 | static void get_ext_port_caps(struct mlx5_ib_dev *dev) |
| 897 | { | 1063 | { |
| 898 | struct mlx5_general_caps *gen; | ||
| 899 | int port; | 1064 | int port; |
| 900 | 1065 | ||
| 901 | gen = &dev->mdev->caps.gen; | 1066 | for (port = 1; port <= MLX5_CAP_GEN(dev->mdev, num_ports); port++) |
| 902 | for (port = 1; port <= gen->num_ports; port++) | ||
| 903 | mlx5_query_ext_port_caps(dev, port); | 1067 | mlx5_query_ext_port_caps(dev, port); |
| 904 | } | 1068 | } |
| 905 | 1069 | ||
| @@ -907,11 +1071,10 @@ static int get_port_caps(struct mlx5_ib_dev *dev) | |||
| 907 | { | 1071 | { |
| 908 | struct ib_device_attr *dprops = NULL; | 1072 | struct ib_device_attr *dprops = NULL; |
| 909 | struct ib_port_attr *pprops = NULL; | 1073 | struct ib_port_attr *pprops = NULL; |
| 910 | struct mlx5_general_caps *gen; | ||
| 911 | int err = -ENOMEM; | 1074 | int err = -ENOMEM; |
| 912 | int port; | 1075 | int port; |
| 1076 | struct ib_udata uhw = {.inlen = 0, .outlen = 0}; | ||
| 913 | 1077 | ||
| 914 | gen = &dev->mdev->caps.gen; | ||
| 915 | pprops = kmalloc(sizeof(*pprops), GFP_KERNEL); | 1078 | pprops = kmalloc(sizeof(*pprops), GFP_KERNEL); |
| 916 | if (!pprops) | 1079 | if (!pprops) |
| 917 | goto out; | 1080 | goto out; |
| @@ -920,20 +1083,23 @@ static int get_port_caps(struct mlx5_ib_dev *dev) | |||
| 920 | if (!dprops) | 1083 | if (!dprops) |
| 921 | goto out; | 1084 | goto out; |
| 922 | 1085 | ||
| 923 | err = mlx5_ib_query_device(&dev->ib_dev, dprops); | 1086 | err = mlx5_ib_query_device(&dev->ib_dev, dprops, &uhw); |
| 924 | if (err) { | 1087 | if (err) { |
| 925 | mlx5_ib_warn(dev, "query_device failed %d\n", err); | 1088 | mlx5_ib_warn(dev, "query_device failed %d\n", err); |
| 926 | goto out; | 1089 | goto out; |
| 927 | } | 1090 | } |
| 928 | 1091 | ||
| 929 | for (port = 1; port <= gen->num_ports; port++) { | 1092 | for (port = 1; port <= MLX5_CAP_GEN(dev->mdev, num_ports); port++) { |
| 930 | err = mlx5_ib_query_port(&dev->ib_dev, port, pprops); | 1093 | err = mlx5_ib_query_port(&dev->ib_dev, port, pprops); |
| 931 | if (err) { | 1094 | if (err) { |
| 932 | mlx5_ib_warn(dev, "query_port %d failed %d\n", port, err); | 1095 | mlx5_ib_warn(dev, "query_port %d failed %d\n", |
| 1096 | port, err); | ||
| 933 | break; | 1097 | break; |
| 934 | } | 1098 | } |
| 935 | gen->port[port - 1].pkey_table_len = dprops->max_pkeys; | 1099 | dev->mdev->port_caps[port - 1].pkey_table_len = |
| 936 | gen->port[port - 1].gid_table_len = pprops->gid_tbl_len; | 1100 | dprops->max_pkeys; |
| 1101 | dev->mdev->port_caps[port - 1].gid_table_len = | ||
| 1102 | pprops->gid_tbl_len; | ||
| 937 | mlx5_ib_dbg(dev, "pkey_table_len %d, gid_table_len %d\n", | 1103 | mlx5_ib_dbg(dev, "pkey_table_len %d, gid_table_len %d\n", |
| 938 | dprops->max_pkeys, pprops->gid_tbl_len); | 1104 | dprops->max_pkeys, pprops->gid_tbl_len); |
| 939 | } | 1105 | } |
| @@ -971,6 +1137,7 @@ static int create_umr_res(struct mlx5_ib_dev *dev) | |||
| 971 | struct ib_cq *cq; | 1137 | struct ib_cq *cq; |
| 972 | struct ib_qp *qp; | 1138 | struct ib_qp *qp; |
| 973 | struct ib_mr *mr; | 1139 | struct ib_mr *mr; |
| 1140 | struct ib_cq_init_attr cq_attr = {}; | ||
| 974 | int ret; | 1141 | int ret; |
| 975 | 1142 | ||
| 976 | attr = kzalloc(sizeof(*attr), GFP_KERNEL); | 1143 | attr = kzalloc(sizeof(*attr), GFP_KERNEL); |
| @@ -994,8 +1161,9 @@ static int create_umr_res(struct mlx5_ib_dev *dev) | |||
| 994 | goto error_1; | 1161 | goto error_1; |
| 995 | } | 1162 | } |
| 996 | 1163 | ||
| 997 | cq = ib_create_cq(&dev->ib_dev, mlx5_umr_cq_handler, NULL, NULL, 128, | 1164 | cq_attr.cqe = 128; |
| 998 | 0); | 1165 | cq = ib_create_cq(&dev->ib_dev, mlx5_umr_cq_handler, NULL, NULL, |
| 1166 | &cq_attr); | ||
| 999 | if (IS_ERR(cq)) { | 1167 | if (IS_ERR(cq)) { |
| 1000 | mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n"); | 1168 | mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n"); |
| 1001 | ret = PTR_ERR(cq); | 1169 | ret = PTR_ERR(cq); |
| @@ -1087,6 +1255,7 @@ static int create_dev_resources(struct mlx5_ib_resources *devr) | |||
| 1087 | { | 1255 | { |
| 1088 | struct ib_srq_init_attr attr; | 1256 | struct ib_srq_init_attr attr; |
| 1089 | struct mlx5_ib_dev *dev; | 1257 | struct mlx5_ib_dev *dev; |
| 1258 | struct ib_cq_init_attr cq_attr = {.cqe = 1}; | ||
| 1090 | int ret = 0; | 1259 | int ret = 0; |
| 1091 | 1260 | ||
| 1092 | dev = container_of(devr, struct mlx5_ib_dev, devr); | 1261 | dev = container_of(devr, struct mlx5_ib_dev, devr); |
| @@ -1100,7 +1269,7 @@ static int create_dev_resources(struct mlx5_ib_resources *devr) | |||
| 1100 | devr->p0->uobject = NULL; | 1269 | devr->p0->uobject = NULL; |
| 1101 | atomic_set(&devr->p0->usecnt, 0); | 1270 | atomic_set(&devr->p0->usecnt, 0); |
| 1102 | 1271 | ||
| 1103 | devr->c0 = mlx5_ib_create_cq(&dev->ib_dev, 1, 0, NULL, NULL); | 1272 | devr->c0 = mlx5_ib_create_cq(&dev->ib_dev, &cq_attr, NULL, NULL); |
| 1104 | if (IS_ERR(devr->c0)) { | 1273 | if (IS_ERR(devr->c0)) { |
| 1105 | ret = PTR_ERR(devr->c0); | 1274 | ret = PTR_ERR(devr->c0); |
| 1106 | goto error1; | 1275 | goto error1; |
| @@ -1159,8 +1328,29 @@ static int create_dev_resources(struct mlx5_ib_resources *devr) | |||
| 1159 | atomic_inc(&devr->p0->usecnt); | 1328 | atomic_inc(&devr->p0->usecnt); |
| 1160 | atomic_set(&devr->s0->usecnt, 0); | 1329 | atomic_set(&devr->s0->usecnt, 0); |
| 1161 | 1330 | ||
| 1331 | memset(&attr, 0, sizeof(attr)); | ||
| 1332 | attr.attr.max_sge = 1; | ||
| 1333 | attr.attr.max_wr = 1; | ||
| 1334 | attr.srq_type = IB_SRQT_BASIC; | ||
| 1335 | devr->s1 = mlx5_ib_create_srq(devr->p0, &attr, NULL); | ||
| 1336 | if (IS_ERR(devr->s1)) { | ||
| 1337 | ret = PTR_ERR(devr->s1); | ||
| 1338 | goto error5; | ||
| 1339 | } | ||
| 1340 | devr->s1->device = &dev->ib_dev; | ||
| 1341 | devr->s1->pd = devr->p0; | ||
| 1342 | devr->s1->uobject = NULL; | ||
| 1343 | devr->s1->event_handler = NULL; | ||
| 1344 | devr->s1->srq_context = NULL; | ||
| 1345 | devr->s1->srq_type = IB_SRQT_BASIC; | ||
| 1346 | devr->s1->ext.xrc.cq = devr->c0; | ||
| 1347 | atomic_inc(&devr->p0->usecnt); | ||
| 1348 | atomic_set(&devr->s0->usecnt, 0); | ||
| 1349 | |||
| 1162 | return 0; | 1350 | return 0; |
| 1163 | 1351 | ||
| 1352 | error5: | ||
| 1353 | mlx5_ib_destroy_srq(devr->s0); | ||
| 1164 | error4: | 1354 | error4: |
| 1165 | mlx5_ib_dealloc_xrcd(devr->x1); | 1355 | mlx5_ib_dealloc_xrcd(devr->x1); |
| 1166 | error3: | 1356 | error3: |
| @@ -1175,6 +1365,7 @@ error0: | |||
| 1175 | 1365 | ||
| 1176 | static void destroy_dev_resources(struct mlx5_ib_resources *devr) | 1366 | static void destroy_dev_resources(struct mlx5_ib_resources *devr) |
| 1177 | { | 1367 | { |
| 1368 | mlx5_ib_destroy_srq(devr->s1); | ||
| 1178 | mlx5_ib_destroy_srq(devr->s0); | 1369 | mlx5_ib_destroy_srq(devr->s0); |
| 1179 | mlx5_ib_dealloc_xrcd(devr->x0); | 1370 | mlx5_ib_dealloc_xrcd(devr->x0); |
| 1180 | mlx5_ib_dealloc_xrcd(devr->x1); | 1371 | mlx5_ib_dealloc_xrcd(devr->x1); |
| @@ -1182,12 +1373,34 @@ static void destroy_dev_resources(struct mlx5_ib_resources *devr) | |||
| 1182 | mlx5_ib_dealloc_pd(devr->p0); | 1373 | mlx5_ib_dealloc_pd(devr->p0); |
| 1183 | } | 1374 | } |
| 1184 | 1375 | ||
| 1376 | static int mlx5_port_immutable(struct ib_device *ibdev, u8 port_num, | ||
| 1377 | struct ib_port_immutable *immutable) | ||
| 1378 | { | ||
| 1379 | struct ib_port_attr attr; | ||
| 1380 | int err; | ||
| 1381 | |||
| 1382 | err = mlx5_ib_query_port(ibdev, port_num, &attr); | ||
| 1383 | if (err) | ||
| 1384 | return err; | ||
| 1385 | |||
| 1386 | immutable->pkey_tbl_len = attr.pkey_tbl_len; | ||
| 1387 | immutable->gid_tbl_len = attr.gid_tbl_len; | ||
| 1388 | immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB; | ||
| 1389 | immutable->max_mad_size = IB_MGMT_MAD_SIZE; | ||
| 1390 | |||
| 1391 | return 0; | ||
| 1392 | } | ||
| 1393 | |||
| 1185 | static void *mlx5_ib_add(struct mlx5_core_dev *mdev) | 1394 | static void *mlx5_ib_add(struct mlx5_core_dev *mdev) |
| 1186 | { | 1395 | { |
| 1187 | struct mlx5_ib_dev *dev; | 1396 | struct mlx5_ib_dev *dev; |
| 1188 | int err; | 1397 | int err; |
| 1189 | int i; | 1398 | int i; |
| 1190 | 1399 | ||
| 1400 | /* don't create IB instance over Eth ports, no RoCE yet! */ | ||
| 1401 | if (MLX5_CAP_GEN(mdev, port_type) == MLX5_CAP_PORT_TYPE_ETH) | ||
| 1402 | return NULL; | ||
| 1403 | |||
| 1191 | printk_once(KERN_INFO "%s", mlx5_version); | 1404 | printk_once(KERN_INFO "%s", mlx5_version); |
| 1192 | 1405 | ||
| 1193 | dev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*dev)); | 1406 | dev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*dev)); |
| @@ -1200,15 +1413,16 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev) | |||
| 1200 | if (err) | 1413 | if (err) |
| 1201 | goto err_dealloc; | 1414 | goto err_dealloc; |
| 1202 | 1415 | ||
| 1203 | get_ext_port_caps(dev); | 1416 | if (mlx5_use_mad_ifc(dev)) |
| 1417 | get_ext_port_caps(dev); | ||
| 1204 | 1418 | ||
| 1205 | MLX5_INIT_DOORBELL_LOCK(&dev->uar_lock); | 1419 | MLX5_INIT_DOORBELL_LOCK(&dev->uar_lock); |
| 1206 | 1420 | ||
| 1207 | strlcpy(dev->ib_dev.name, "mlx5_%d", IB_DEVICE_NAME_MAX); | 1421 | strlcpy(dev->ib_dev.name, "mlx5_%d", IB_DEVICE_NAME_MAX); |
| 1208 | dev->ib_dev.owner = THIS_MODULE; | 1422 | dev->ib_dev.owner = THIS_MODULE; |
| 1209 | dev->ib_dev.node_type = RDMA_NODE_IB_CA; | 1423 | dev->ib_dev.node_type = RDMA_NODE_IB_CA; |
| 1210 | dev->ib_dev.local_dma_lkey = mdev->caps.gen.reserved_lkey; | 1424 | dev->ib_dev.local_dma_lkey = 0 /* not supported for now */; |
| 1211 | dev->num_ports = mdev->caps.gen.num_ports; | 1425 | dev->num_ports = MLX5_CAP_GEN(mdev, num_ports); |
| 1212 | dev->ib_dev.phys_port_cnt = dev->num_ports; | 1426 | dev->ib_dev.phys_port_cnt = dev->num_ports; |
| 1213 | dev->ib_dev.num_comp_vectors = | 1427 | dev->ib_dev.num_comp_vectors = |
| 1214 | dev->mdev->priv.eq_table.num_comp_vectors; | 1428 | dev->mdev->priv.eq_table.num_comp_vectors; |
| @@ -1285,10 +1499,11 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev) | |||
| 1285 | dev->ib_dev.alloc_fast_reg_page_list = mlx5_ib_alloc_fast_reg_page_list; | 1499 | dev->ib_dev.alloc_fast_reg_page_list = mlx5_ib_alloc_fast_reg_page_list; |
| 1286 | dev->ib_dev.free_fast_reg_page_list = mlx5_ib_free_fast_reg_page_list; | 1500 | dev->ib_dev.free_fast_reg_page_list = mlx5_ib_free_fast_reg_page_list; |
| 1287 | dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status; | 1501 | dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status; |
| 1502 | dev->ib_dev.get_port_immutable = mlx5_port_immutable; | ||
| 1288 | 1503 | ||
| 1289 | mlx5_ib_internal_query_odp_caps(dev); | 1504 | mlx5_ib_internal_fill_odp_caps(dev); |
| 1290 | 1505 | ||
| 1291 | if (mdev->caps.gen.flags & MLX5_DEV_CAP_FLAG_XRC) { | 1506 | if (MLX5_CAP_GEN(mdev, xrc)) { |
| 1292 | dev->ib_dev.alloc_xrcd = mlx5_ib_alloc_xrcd; | 1507 | dev->ib_dev.alloc_xrcd = mlx5_ib_alloc_xrcd; |
| 1293 | dev->ib_dev.dealloc_xrcd = mlx5_ib_dealloc_xrcd; | 1508 | dev->ib_dev.dealloc_xrcd = mlx5_ib_dealloc_xrcd; |
| 1294 | dev->ib_dev.uverbs_cmd_mask |= | 1509 | dev->ib_dev.uverbs_cmd_mask |= |
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index dff1cfcdf476..7cae09836481 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h | |||
| @@ -415,6 +415,7 @@ struct mlx5_ib_resources { | |||
| 415 | struct ib_xrcd *x1; | 415 | struct ib_xrcd *x1; |
| 416 | struct ib_pd *p0; | 416 | struct ib_pd *p0; |
| 417 | struct ib_srq *s0; | 417 | struct ib_srq *s0; |
| 418 | struct ib_srq *s1; | ||
| 418 | }; | 419 | }; |
| 419 | 420 | ||
| 420 | struct mlx5_ib_dev { | 421 | struct mlx5_ib_dev { |
| @@ -525,8 +526,8 @@ void __mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq) | |||
| 525 | void mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq); | 526 | void mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq); |
| 526 | void mlx5_ib_free_srq_wqe(struct mlx5_ib_srq *srq, int wqe_index); | 527 | void mlx5_ib_free_srq_wqe(struct mlx5_ib_srq *srq, int wqe_index); |
| 527 | int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, | 528 | int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, |
| 528 | u8 port, struct ib_wc *in_wc, struct ib_grh *in_grh, | 529 | u8 port, const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 529 | void *in_mad, void *response_mad); | 530 | const void *in_mad, void *response_mad); |
| 530 | struct ib_ah *create_ib_ah(struct ib_ah_attr *ah_attr, | 531 | struct ib_ah *create_ib_ah(struct ib_ah_attr *ah_attr, |
| 531 | struct mlx5_ib_ah *ah); | 532 | struct mlx5_ib_ah *ah); |
| 532 | struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr); | 533 | struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr); |
| @@ -556,8 +557,9 @@ int mlx5_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr, | |||
| 556 | void *mlx5_get_send_wqe(struct mlx5_ib_qp *qp, int n); | 557 | void *mlx5_get_send_wqe(struct mlx5_ib_qp *qp, int n); |
| 557 | int mlx5_ib_read_user_wqe(struct mlx5_ib_qp *qp, int send, int wqe_index, | 558 | int mlx5_ib_read_user_wqe(struct mlx5_ib_qp *qp, int send, int wqe_index, |
| 558 | void *buffer, u32 length); | 559 | void *buffer, u32 length); |
| 559 | struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, int entries, | 560 | struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, |
| 560 | int vector, struct ib_ucontext *context, | 561 | const struct ib_cq_init_attr *attr, |
| 562 | struct ib_ucontext *context, | ||
| 561 | struct ib_udata *udata); | 563 | struct ib_udata *udata); |
| 562 | int mlx5_ib_destroy_cq(struct ib_cq *cq); | 564 | int mlx5_ib_destroy_cq(struct ib_cq *cq); |
| 563 | int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc); | 565 | int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc); |
| @@ -586,14 +588,32 @@ int mlx5_ib_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, | |||
| 586 | int mlx5_ib_unmap_fmr(struct list_head *fmr_list); | 588 | int mlx5_ib_unmap_fmr(struct list_head *fmr_list); |
| 587 | int mlx5_ib_fmr_dealloc(struct ib_fmr *ibfmr); | 589 | int mlx5_ib_fmr_dealloc(struct ib_fmr *ibfmr); |
| 588 | int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | 590 | int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, |
| 589 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 591 | const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 590 | struct ib_mad *in_mad, struct ib_mad *out_mad); | 592 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 593 | struct ib_mad_hdr *out, size_t *out_mad_size, | ||
| 594 | u16 *out_mad_pkey_index); | ||
| 591 | struct ib_xrcd *mlx5_ib_alloc_xrcd(struct ib_device *ibdev, | 595 | struct ib_xrcd *mlx5_ib_alloc_xrcd(struct ib_device *ibdev, |
| 592 | struct ib_ucontext *context, | 596 | struct ib_ucontext *context, |
| 593 | struct ib_udata *udata); | 597 | struct ib_udata *udata); |
| 594 | int mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd); | 598 | int mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd); |
| 595 | int mlx5_ib_get_buf_offset(u64 addr, int page_shift, u32 *offset); | 599 | int mlx5_ib_get_buf_offset(u64 addr, int page_shift, u32 *offset); |
| 596 | int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, u8 port); | 600 | int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, u8 port); |
| 601 | int mlx5_query_mad_ifc_smp_attr_node_info(struct ib_device *ibdev, | ||
| 602 | struct ib_smp *out_mad); | ||
| 603 | int mlx5_query_mad_ifc_system_image_guid(struct ib_device *ibdev, | ||
| 604 | __be64 *sys_image_guid); | ||
| 605 | int mlx5_query_mad_ifc_max_pkeys(struct ib_device *ibdev, | ||
| 606 | u16 *max_pkeys); | ||
| 607 | int mlx5_query_mad_ifc_vendor_id(struct ib_device *ibdev, | ||
| 608 | u32 *vendor_id); | ||
| 609 | int mlx5_query_mad_ifc_node_desc(struct mlx5_ib_dev *dev, char *node_desc); | ||
| 610 | int mlx5_query_mad_ifc_node_guid(struct mlx5_ib_dev *dev, __be64 *node_guid); | ||
| 611 | int mlx5_query_mad_ifc_pkey(struct ib_device *ibdev, u8 port, u16 index, | ||
| 612 | u16 *pkey); | ||
| 613 | int mlx5_query_mad_ifc_gids(struct ib_device *ibdev, u8 port, int index, | ||
| 614 | union ib_gid *gid); | ||
| 615 | int mlx5_query_mad_ifc_port(struct ib_device *ibdev, u8 port, | ||
| 616 | struct ib_port_attr *props); | ||
| 597 | int mlx5_ib_query_port(struct ib_device *ibdev, u8 port, | 617 | int mlx5_ib_query_port(struct ib_device *ibdev, u8 port, |
| 598 | struct ib_port_attr *props); | 618 | struct ib_port_attr *props); |
| 599 | int mlx5_ib_init_fmr(struct mlx5_ib_dev *dev); | 619 | int mlx5_ib_init_fmr(struct mlx5_ib_dev *dev); |
| @@ -617,7 +637,7 @@ int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask, | |||
| 617 | #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING | 637 | #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING |
| 618 | extern struct workqueue_struct *mlx5_ib_page_fault_wq; | 638 | extern struct workqueue_struct *mlx5_ib_page_fault_wq; |
| 619 | 639 | ||
| 620 | int mlx5_ib_internal_query_odp_caps(struct mlx5_ib_dev *dev); | 640 | void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev); |
| 621 | void mlx5_ib_mr_pfault_handler(struct mlx5_ib_qp *qp, | 641 | void mlx5_ib_mr_pfault_handler(struct mlx5_ib_qp *qp, |
| 622 | struct mlx5_ib_pfault *pfault); | 642 | struct mlx5_ib_pfault *pfault); |
| 623 | void mlx5_ib_odp_create_qp(struct mlx5_ib_qp *qp); | 643 | void mlx5_ib_odp_create_qp(struct mlx5_ib_qp *qp); |
| @@ -631,9 +651,9 @@ void mlx5_ib_invalidate_range(struct ib_umem *umem, unsigned long start, | |||
| 631 | unsigned long end); | 651 | unsigned long end); |
| 632 | 652 | ||
| 633 | #else /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */ | 653 | #else /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */ |
| 634 | static inline int mlx5_ib_internal_query_odp_caps(struct mlx5_ib_dev *dev) | 654 | static inline void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev) |
| 635 | { | 655 | { |
| 636 | return 0; | 656 | return; |
| 637 | } | 657 | } |
| 638 | 658 | ||
| 639 | static inline void mlx5_ib_odp_create_qp(struct mlx5_ib_qp *qp) {} | 659 | static inline void mlx5_ib_odp_create_qp(struct mlx5_ib_qp *qp) {} |
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c index 71c593583864..bc9a0de897cb 100644 --- a/drivers/infiniband/hw/mlx5/mr.c +++ b/drivers/infiniband/hw/mlx5/mr.c | |||
| @@ -975,8 +975,7 @@ static struct mlx5_ib_mr *reg_create(struct ib_pd *pd, u64 virt_addr, | |||
| 975 | struct mlx5_ib_mr *mr; | 975 | struct mlx5_ib_mr *mr; |
| 976 | int inlen; | 976 | int inlen; |
| 977 | int err; | 977 | int err; |
| 978 | bool pg_cap = !!(dev->mdev->caps.gen.flags & | 978 | bool pg_cap = !!(MLX5_CAP_GEN(dev->mdev, pg)); |
| 979 | MLX5_DEV_CAP_FLAG_ON_DMND_PG); | ||
| 980 | 979 | ||
| 981 | mr = kzalloc(sizeof(*mr), GFP_KERNEL); | 980 | mr = kzalloc(sizeof(*mr), GFP_KERNEL); |
| 982 | if (!mr) | 981 | if (!mr) |
diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c index 5099db08afd2..aa8391e75385 100644 --- a/drivers/infiniband/hw/mlx5/odp.c +++ b/drivers/infiniband/hw/mlx5/odp.c | |||
| @@ -109,40 +109,33 @@ void mlx5_ib_invalidate_range(struct ib_umem *umem, unsigned long start, | |||
| 109 | ib_umem_odp_unmap_dma_pages(umem, start, end); | 109 | ib_umem_odp_unmap_dma_pages(umem, start, end); |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | #define COPY_ODP_BIT_MLX_TO_IB(reg, ib_caps, field_name, bit_name) do { \ | 112 | void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev) |
| 113 | if (be32_to_cpu(reg.field_name) & MLX5_ODP_SUPPORT_##bit_name) \ | ||
| 114 | ib_caps->field_name |= IB_ODP_SUPPORT_##bit_name; \ | ||
| 115 | } while (0) | ||
| 116 | |||
| 117 | int mlx5_ib_internal_query_odp_caps(struct mlx5_ib_dev *dev) | ||
| 118 | { | 113 | { |
| 119 | int err; | ||
| 120 | struct mlx5_odp_caps hw_caps; | ||
| 121 | struct ib_odp_caps *caps = &dev->odp_caps; | 114 | struct ib_odp_caps *caps = &dev->odp_caps; |
| 122 | 115 | ||
| 123 | memset(caps, 0, sizeof(*caps)); | 116 | memset(caps, 0, sizeof(*caps)); |
| 124 | 117 | ||
| 125 | if (!(dev->mdev->caps.gen.flags & MLX5_DEV_CAP_FLAG_ON_DMND_PG)) | 118 | if (!MLX5_CAP_GEN(dev->mdev, pg)) |
| 126 | return 0; | 119 | return; |
| 127 | |||
| 128 | err = mlx5_query_odp_caps(dev->mdev, &hw_caps); | ||
| 129 | if (err) | ||
| 130 | goto out; | ||
| 131 | 120 | ||
| 132 | caps->general_caps = IB_ODP_SUPPORT; | 121 | caps->general_caps = IB_ODP_SUPPORT; |
| 133 | COPY_ODP_BIT_MLX_TO_IB(hw_caps, caps, per_transport_caps.ud_odp_caps, | 122 | |
| 134 | SEND); | 123 | if (MLX5_CAP_ODP(dev->mdev, ud_odp_caps.send)) |
| 135 | COPY_ODP_BIT_MLX_TO_IB(hw_caps, caps, per_transport_caps.rc_odp_caps, | 124 | caps->per_transport_caps.ud_odp_caps |= IB_ODP_SUPPORT_SEND; |
| 136 | SEND); | 125 | |
| 137 | COPY_ODP_BIT_MLX_TO_IB(hw_caps, caps, per_transport_caps.rc_odp_caps, | 126 | if (MLX5_CAP_ODP(dev->mdev, rc_odp_caps.send)) |
| 138 | RECV); | 127 | caps->per_transport_caps.rc_odp_caps |= IB_ODP_SUPPORT_SEND; |
| 139 | COPY_ODP_BIT_MLX_TO_IB(hw_caps, caps, per_transport_caps.rc_odp_caps, | 128 | |
| 140 | WRITE); | 129 | if (MLX5_CAP_ODP(dev->mdev, rc_odp_caps.receive)) |
| 141 | COPY_ODP_BIT_MLX_TO_IB(hw_caps, caps, per_transport_caps.rc_odp_caps, | 130 | caps->per_transport_caps.rc_odp_caps |= IB_ODP_SUPPORT_RECV; |
| 142 | READ); | 131 | |
| 143 | 132 | if (MLX5_CAP_ODP(dev->mdev, rc_odp_caps.write)) | |
| 144 | out: | 133 | caps->per_transport_caps.rc_odp_caps |= IB_ODP_SUPPORT_WRITE; |
| 145 | return err; | 134 | |
| 135 | if (MLX5_CAP_ODP(dev->mdev, rc_odp_caps.read)) | ||
| 136 | caps->per_transport_caps.rc_odp_caps |= IB_ODP_SUPPORT_READ; | ||
| 137 | |||
| 138 | return; | ||
| 146 | } | 139 | } |
| 147 | 140 | ||
| 148 | static struct mlx5_ib_mr *mlx5_ib_odp_find_mr_lkey(struct mlx5_ib_dev *dev, | 141 | static struct mlx5_ib_mr *mlx5_ib_odp_find_mr_lkey(struct mlx5_ib_dev *dev, |
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index d35f62d4f4c5..203c8a45e095 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c | |||
| @@ -220,13 +220,11 @@ static void mlx5_ib_qp_event(struct mlx5_core_qp *qp, int type) | |||
| 220 | static int set_rq_size(struct mlx5_ib_dev *dev, struct ib_qp_cap *cap, | 220 | static int set_rq_size(struct mlx5_ib_dev *dev, struct ib_qp_cap *cap, |
| 221 | int has_rq, struct mlx5_ib_qp *qp, struct mlx5_ib_create_qp *ucmd) | 221 | int has_rq, struct mlx5_ib_qp *qp, struct mlx5_ib_create_qp *ucmd) |
| 222 | { | 222 | { |
| 223 | struct mlx5_general_caps *gen; | ||
| 224 | int wqe_size; | 223 | int wqe_size; |
| 225 | int wq_size; | 224 | int wq_size; |
| 226 | 225 | ||
| 227 | gen = &dev->mdev->caps.gen; | ||
| 228 | /* Sanity check RQ size before proceeding */ | 226 | /* Sanity check RQ size before proceeding */ |
| 229 | if (cap->max_recv_wr > gen->max_wqes) | 227 | if (cap->max_recv_wr > (1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz))) |
| 230 | return -EINVAL; | 228 | return -EINVAL; |
| 231 | 229 | ||
| 232 | if (!has_rq) { | 230 | if (!has_rq) { |
| @@ -246,10 +244,11 @@ static int set_rq_size(struct mlx5_ib_dev *dev, struct ib_qp_cap *cap, | |||
| 246 | wq_size = roundup_pow_of_two(cap->max_recv_wr) * wqe_size; | 244 | wq_size = roundup_pow_of_two(cap->max_recv_wr) * wqe_size; |
| 247 | wq_size = max_t(int, wq_size, MLX5_SEND_WQE_BB); | 245 | wq_size = max_t(int, wq_size, MLX5_SEND_WQE_BB); |
| 248 | qp->rq.wqe_cnt = wq_size / wqe_size; | 246 | qp->rq.wqe_cnt = wq_size / wqe_size; |
| 249 | if (wqe_size > gen->max_rq_desc_sz) { | 247 | if (wqe_size > MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq)) { |
| 250 | mlx5_ib_dbg(dev, "wqe_size %d, max %d\n", | 248 | mlx5_ib_dbg(dev, "wqe_size %d, max %d\n", |
| 251 | wqe_size, | 249 | wqe_size, |
| 252 | gen->max_rq_desc_sz); | 250 | MLX5_CAP_GEN(dev->mdev, |
| 251 | max_wqe_sz_rq)); | ||
| 253 | return -EINVAL; | 252 | return -EINVAL; |
| 254 | } | 253 | } |
| 255 | qp->rq.wqe_shift = ilog2(wqe_size); | 254 | qp->rq.wqe_shift = ilog2(wqe_size); |
| @@ -330,11 +329,9 @@ static int calc_send_wqe(struct ib_qp_init_attr *attr) | |||
| 330 | static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr, | 329 | static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr, |
| 331 | struct mlx5_ib_qp *qp) | 330 | struct mlx5_ib_qp *qp) |
| 332 | { | 331 | { |
| 333 | struct mlx5_general_caps *gen; | ||
| 334 | int wqe_size; | 332 | int wqe_size; |
| 335 | int wq_size; | 333 | int wq_size; |
| 336 | 334 | ||
| 337 | gen = &dev->mdev->caps.gen; | ||
| 338 | if (!attr->cap.max_send_wr) | 335 | if (!attr->cap.max_send_wr) |
| 339 | return 0; | 336 | return 0; |
| 340 | 337 | ||
| @@ -343,9 +340,9 @@ static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr, | |||
| 343 | if (wqe_size < 0) | 340 | if (wqe_size < 0) |
| 344 | return wqe_size; | 341 | return wqe_size; |
| 345 | 342 | ||
| 346 | if (wqe_size > gen->max_sq_desc_sz) { | 343 | if (wqe_size > MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq)) { |
| 347 | mlx5_ib_dbg(dev, "wqe_size(%d) > max_sq_desc_sz(%d)\n", | 344 | mlx5_ib_dbg(dev, "wqe_size(%d) > max_sq_desc_sz(%d)\n", |
| 348 | wqe_size, gen->max_sq_desc_sz); | 345 | wqe_size, MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq)); |
| 349 | return -EINVAL; | 346 | return -EINVAL; |
| 350 | } | 347 | } |
| 351 | 348 | ||
| @@ -358,9 +355,10 @@ static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr, | |||
| 358 | 355 | ||
| 359 | wq_size = roundup_pow_of_two(attr->cap.max_send_wr * wqe_size); | 356 | wq_size = roundup_pow_of_two(attr->cap.max_send_wr * wqe_size); |
| 360 | qp->sq.wqe_cnt = wq_size / MLX5_SEND_WQE_BB; | 357 | qp->sq.wqe_cnt = wq_size / MLX5_SEND_WQE_BB; |
| 361 | if (qp->sq.wqe_cnt > gen->max_wqes) { | 358 | if (qp->sq.wqe_cnt > (1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz))) { |
| 362 | mlx5_ib_dbg(dev, "wqe count(%d) exceeds limits(%d)\n", | 359 | mlx5_ib_dbg(dev, "wqe count(%d) exceeds limits(%d)\n", |
| 363 | qp->sq.wqe_cnt, gen->max_wqes); | 360 | qp->sq.wqe_cnt, |
| 361 | 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz)); | ||
| 364 | return -ENOMEM; | 362 | return -ENOMEM; |
| 365 | } | 363 | } |
| 366 | qp->sq.wqe_shift = ilog2(MLX5_SEND_WQE_BB); | 364 | qp->sq.wqe_shift = ilog2(MLX5_SEND_WQE_BB); |
| @@ -375,13 +373,11 @@ static int set_user_buf_size(struct mlx5_ib_dev *dev, | |||
| 375 | struct mlx5_ib_qp *qp, | 373 | struct mlx5_ib_qp *qp, |
| 376 | struct mlx5_ib_create_qp *ucmd) | 374 | struct mlx5_ib_create_qp *ucmd) |
| 377 | { | 375 | { |
| 378 | struct mlx5_general_caps *gen; | ||
| 379 | int desc_sz = 1 << qp->sq.wqe_shift; | 376 | int desc_sz = 1 << qp->sq.wqe_shift; |
| 380 | 377 | ||
| 381 | gen = &dev->mdev->caps.gen; | 378 | if (desc_sz > MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq)) { |
| 382 | if (desc_sz > gen->max_sq_desc_sz) { | ||
| 383 | mlx5_ib_warn(dev, "desc_sz %d, max_sq_desc_sz %d\n", | 379 | mlx5_ib_warn(dev, "desc_sz %d, max_sq_desc_sz %d\n", |
| 384 | desc_sz, gen->max_sq_desc_sz); | 380 | desc_sz, MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq)); |
| 385 | return -EINVAL; | 381 | return -EINVAL; |
| 386 | } | 382 | } |
| 387 | 383 | ||
| @@ -393,9 +389,10 @@ static int set_user_buf_size(struct mlx5_ib_dev *dev, | |||
| 393 | 389 | ||
| 394 | qp->sq.wqe_cnt = ucmd->sq_wqe_count; | 390 | qp->sq.wqe_cnt = ucmd->sq_wqe_count; |
| 395 | 391 | ||
| 396 | if (qp->sq.wqe_cnt > gen->max_wqes) { | 392 | if (qp->sq.wqe_cnt > (1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz))) { |
| 397 | mlx5_ib_warn(dev, "wqe_cnt %d, max_wqes %d\n", | 393 | mlx5_ib_warn(dev, "wqe_cnt %d, max_wqes %d\n", |
| 398 | qp->sq.wqe_cnt, gen->max_wqes); | 394 | qp->sq.wqe_cnt, |
| 395 | 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz)); | ||
| 399 | return -EINVAL; | 396 | return -EINVAL; |
| 400 | } | 397 | } |
| 401 | 398 | ||
| @@ -768,7 +765,7 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev, | |||
| 768 | qp->sq.offset = qp->rq.wqe_cnt << qp->rq.wqe_shift; | 765 | qp->sq.offset = qp->rq.wqe_cnt << qp->rq.wqe_shift; |
| 769 | qp->buf_size = err + (qp->rq.wqe_cnt << qp->rq.wqe_shift); | 766 | qp->buf_size = err + (qp->rq.wqe_cnt << qp->rq.wqe_shift); |
| 770 | 767 | ||
| 771 | err = mlx5_buf_alloc(dev->mdev, qp->buf_size, PAGE_SIZE * 2, &qp->buf); | 768 | err = mlx5_buf_alloc(dev->mdev, qp->buf_size, &qp->buf); |
| 772 | if (err) { | 769 | if (err) { |
| 773 | mlx5_ib_dbg(dev, "err %d\n", err); | 770 | mlx5_ib_dbg(dev, "err %d\n", err); |
| 774 | goto err_uuar; | 771 | goto err_uuar; |
| @@ -866,22 +863,21 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, | |||
| 866 | struct ib_udata *udata, struct mlx5_ib_qp *qp) | 863 | struct ib_udata *udata, struct mlx5_ib_qp *qp) |
| 867 | { | 864 | { |
| 868 | struct mlx5_ib_resources *devr = &dev->devr; | 865 | struct mlx5_ib_resources *devr = &dev->devr; |
| 866 | struct mlx5_core_dev *mdev = dev->mdev; | ||
| 869 | struct mlx5_ib_create_qp_resp resp; | 867 | struct mlx5_ib_create_qp_resp resp; |
| 870 | struct mlx5_create_qp_mbox_in *in; | 868 | struct mlx5_create_qp_mbox_in *in; |
| 871 | struct mlx5_general_caps *gen; | ||
| 872 | struct mlx5_ib_create_qp ucmd; | 869 | struct mlx5_ib_create_qp ucmd; |
| 873 | int inlen = sizeof(*in); | 870 | int inlen = sizeof(*in); |
| 874 | int err; | 871 | int err; |
| 875 | 872 | ||
| 876 | mlx5_ib_odp_create_qp(qp); | 873 | mlx5_ib_odp_create_qp(qp); |
| 877 | 874 | ||
| 878 | gen = &dev->mdev->caps.gen; | ||
| 879 | mutex_init(&qp->mutex); | 875 | mutex_init(&qp->mutex); |
| 880 | spin_lock_init(&qp->sq.lock); | 876 | spin_lock_init(&qp->sq.lock); |
| 881 | spin_lock_init(&qp->rq.lock); | 877 | spin_lock_init(&qp->rq.lock); |
| 882 | 878 | ||
| 883 | if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) { | 879 | if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) { |
| 884 | if (!(gen->flags & MLX5_DEV_CAP_FLAG_BLOCK_MCAST)) { | 880 | if (!MLX5_CAP_GEN(mdev, block_lb_mc)) { |
| 885 | mlx5_ib_dbg(dev, "block multicast loopback isn't supported\n"); | 881 | mlx5_ib_dbg(dev, "block multicast loopback isn't supported\n"); |
| 886 | return -EINVAL; | 882 | return -EINVAL; |
| 887 | } else { | 883 | } else { |
| @@ -914,15 +910,17 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, | |||
| 914 | 910 | ||
| 915 | if (pd) { | 911 | if (pd) { |
| 916 | if (pd->uobject) { | 912 | if (pd->uobject) { |
| 913 | __u32 max_wqes = | ||
| 914 | 1 << MLX5_CAP_GEN(mdev, log_max_qp_sz); | ||
| 917 | mlx5_ib_dbg(dev, "requested sq_wqe_count (%d)\n", ucmd.sq_wqe_count); | 915 | mlx5_ib_dbg(dev, "requested sq_wqe_count (%d)\n", ucmd.sq_wqe_count); |
| 918 | if (ucmd.rq_wqe_shift != qp->rq.wqe_shift || | 916 | if (ucmd.rq_wqe_shift != qp->rq.wqe_shift || |
| 919 | ucmd.rq_wqe_count != qp->rq.wqe_cnt) { | 917 | ucmd.rq_wqe_count != qp->rq.wqe_cnt) { |
| 920 | mlx5_ib_dbg(dev, "invalid rq params\n"); | 918 | mlx5_ib_dbg(dev, "invalid rq params\n"); |
| 921 | return -EINVAL; | 919 | return -EINVAL; |
| 922 | } | 920 | } |
| 923 | if (ucmd.sq_wqe_count > gen->max_wqes) { | 921 | if (ucmd.sq_wqe_count > max_wqes) { |
| 924 | mlx5_ib_dbg(dev, "requested sq_wqe_count (%d) > max allowed (%d)\n", | 922 | mlx5_ib_dbg(dev, "requested sq_wqe_count (%d) > max allowed (%d)\n", |
| 925 | ucmd.sq_wqe_count, gen->max_wqes); | 923 | ucmd.sq_wqe_count, max_wqes); |
| 926 | return -EINVAL; | 924 | return -EINVAL; |
| 927 | } | 925 | } |
| 928 | err = create_user_qp(dev, pd, qp, udata, &in, &resp, &inlen); | 926 | err = create_user_qp(dev, pd, qp, udata, &in, &resp, &inlen); |
| @@ -1014,7 +1012,8 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, | |||
| 1014 | in->ctx.rq_type_srqn |= cpu_to_be32(to_msrq(init_attr->srq)->msrq.srqn); | 1012 | in->ctx.rq_type_srqn |= cpu_to_be32(to_msrq(init_attr->srq)->msrq.srqn); |
| 1015 | } else { | 1013 | } else { |
| 1016 | in->ctx.xrcd = cpu_to_be32(to_mxrcd(devr->x1)->xrcdn); | 1014 | in->ctx.xrcd = cpu_to_be32(to_mxrcd(devr->x1)->xrcdn); |
| 1017 | in->ctx.rq_type_srqn |= cpu_to_be32(to_msrq(devr->s0)->msrq.srqn); | 1015 | in->ctx.rq_type_srqn |= |
| 1016 | cpu_to_be32(to_msrq(devr->s1)->msrq.srqn); | ||
| 1018 | } | 1017 | } |
| 1019 | } | 1018 | } |
| 1020 | 1019 | ||
| @@ -1226,7 +1225,6 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, | |||
| 1226 | struct ib_qp_init_attr *init_attr, | 1225 | struct ib_qp_init_attr *init_attr, |
| 1227 | struct ib_udata *udata) | 1226 | struct ib_udata *udata) |
| 1228 | { | 1227 | { |
| 1229 | struct mlx5_general_caps *gen; | ||
| 1230 | struct mlx5_ib_dev *dev; | 1228 | struct mlx5_ib_dev *dev; |
| 1231 | struct mlx5_ib_qp *qp; | 1229 | struct mlx5_ib_qp *qp; |
| 1232 | u16 xrcdn = 0; | 1230 | u16 xrcdn = 0; |
| @@ -1244,12 +1242,11 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, | |||
| 1244 | } | 1242 | } |
| 1245 | dev = to_mdev(to_mxrcd(init_attr->xrcd)->ibxrcd.device); | 1243 | dev = to_mdev(to_mxrcd(init_attr->xrcd)->ibxrcd.device); |
| 1246 | } | 1244 | } |
| 1247 | gen = &dev->mdev->caps.gen; | ||
| 1248 | 1245 | ||
| 1249 | switch (init_attr->qp_type) { | 1246 | switch (init_attr->qp_type) { |
| 1250 | case IB_QPT_XRC_TGT: | 1247 | case IB_QPT_XRC_TGT: |
| 1251 | case IB_QPT_XRC_INI: | 1248 | case IB_QPT_XRC_INI: |
| 1252 | if (!(gen->flags & MLX5_DEV_CAP_FLAG_XRC)) { | 1249 | if (!MLX5_CAP_GEN(dev->mdev, xrc)) { |
| 1253 | mlx5_ib_dbg(dev, "XRC not supported\n"); | 1250 | mlx5_ib_dbg(dev, "XRC not supported\n"); |
| 1254 | return ERR_PTR(-ENOSYS); | 1251 | return ERR_PTR(-ENOSYS); |
| 1255 | } | 1252 | } |
| @@ -1356,9 +1353,6 @@ enum { | |||
| 1356 | 1353 | ||
| 1357 | static int ib_rate_to_mlx5(struct mlx5_ib_dev *dev, u8 rate) | 1354 | static int ib_rate_to_mlx5(struct mlx5_ib_dev *dev, u8 rate) |
| 1358 | { | 1355 | { |
| 1359 | struct mlx5_general_caps *gen; | ||
| 1360 | |||
| 1361 | gen = &dev->mdev->caps.gen; | ||
| 1362 | if (rate == IB_RATE_PORT_CURRENT) { | 1356 | if (rate == IB_RATE_PORT_CURRENT) { |
| 1363 | return 0; | 1357 | return 0; |
| 1364 | } else if (rate < IB_RATE_2_5_GBPS || rate > IB_RATE_300_GBPS) { | 1358 | } else if (rate < IB_RATE_2_5_GBPS || rate > IB_RATE_300_GBPS) { |
| @@ -1366,7 +1360,7 @@ static int ib_rate_to_mlx5(struct mlx5_ib_dev *dev, u8 rate) | |||
| 1366 | } else { | 1360 | } else { |
| 1367 | while (rate != IB_RATE_2_5_GBPS && | 1361 | while (rate != IB_RATE_2_5_GBPS && |
| 1368 | !(1 << (rate + MLX5_STAT_RATE_OFFSET) & | 1362 | !(1 << (rate + MLX5_STAT_RATE_OFFSET) & |
| 1369 | gen->stat_rate_support)) | 1363 | MLX5_CAP_GEN(dev->mdev, stat_rate_support))) |
| 1370 | --rate; | 1364 | --rate; |
| 1371 | } | 1365 | } |
| 1372 | 1366 | ||
| @@ -1377,10 +1371,8 @@ static int mlx5_set_path(struct mlx5_ib_dev *dev, const struct ib_ah_attr *ah, | |||
| 1377 | struct mlx5_qp_path *path, u8 port, int attr_mask, | 1371 | struct mlx5_qp_path *path, u8 port, int attr_mask, |
| 1378 | u32 path_flags, const struct ib_qp_attr *attr) | 1372 | u32 path_flags, const struct ib_qp_attr *attr) |
| 1379 | { | 1373 | { |
| 1380 | struct mlx5_general_caps *gen; | ||
| 1381 | int err; | 1374 | int err; |
| 1382 | 1375 | ||
| 1383 | gen = &dev->mdev->caps.gen; | ||
| 1384 | path->fl = (path_flags & MLX5_PATH_FLAG_FL) ? 0x80 : 0; | 1376 | path->fl = (path_flags & MLX5_PATH_FLAG_FL) ? 0x80 : 0; |
| 1385 | path->free_ar = (path_flags & MLX5_PATH_FLAG_FREE_AR) ? 0x80 : 0; | 1377 | path->free_ar = (path_flags & MLX5_PATH_FLAG_FREE_AR) ? 0x80 : 0; |
| 1386 | 1378 | ||
| @@ -1391,9 +1383,11 @@ static int mlx5_set_path(struct mlx5_ib_dev *dev, const struct ib_ah_attr *ah, | |||
| 1391 | path->rlid = cpu_to_be16(ah->dlid); | 1383 | path->rlid = cpu_to_be16(ah->dlid); |
| 1392 | 1384 | ||
| 1393 | if (ah->ah_flags & IB_AH_GRH) { | 1385 | if (ah->ah_flags & IB_AH_GRH) { |
| 1394 | if (ah->grh.sgid_index >= gen->port[port - 1].gid_table_len) { | 1386 | if (ah->grh.sgid_index >= |
| 1387 | dev->mdev->port_caps[port - 1].gid_table_len) { | ||
| 1395 | pr_err("sgid_index (%u) too large. max is %d\n", | 1388 | pr_err("sgid_index (%u) too large. max is %d\n", |
| 1396 | ah->grh.sgid_index, gen->port[port - 1].gid_table_len); | 1389 | ah->grh.sgid_index, |
| 1390 | dev->mdev->port_caps[port - 1].gid_table_len); | ||
| 1397 | return -EINVAL; | 1391 | return -EINVAL; |
| 1398 | } | 1392 | } |
| 1399 | path->grh_mlid |= 1 << 7; | 1393 | path->grh_mlid |= 1 << 7; |
| @@ -1570,7 +1564,6 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp, | |||
| 1570 | struct mlx5_ib_qp *qp = to_mqp(ibqp); | 1564 | struct mlx5_ib_qp *qp = to_mqp(ibqp); |
| 1571 | struct mlx5_ib_cq *send_cq, *recv_cq; | 1565 | struct mlx5_ib_cq *send_cq, *recv_cq; |
| 1572 | struct mlx5_qp_context *context; | 1566 | struct mlx5_qp_context *context; |
| 1573 | struct mlx5_general_caps *gen; | ||
| 1574 | struct mlx5_modify_qp_mbox_in *in; | 1567 | struct mlx5_modify_qp_mbox_in *in; |
| 1575 | struct mlx5_ib_pd *pd; | 1568 | struct mlx5_ib_pd *pd; |
| 1576 | enum mlx5_qp_state mlx5_cur, mlx5_new; | 1569 | enum mlx5_qp_state mlx5_cur, mlx5_new; |
| @@ -1579,7 +1572,6 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp, | |||
| 1579 | int mlx5_st; | 1572 | int mlx5_st; |
| 1580 | int err; | 1573 | int err; |
| 1581 | 1574 | ||
| 1582 | gen = &dev->mdev->caps.gen; | ||
| 1583 | in = kzalloc(sizeof(*in), GFP_KERNEL); | 1575 | in = kzalloc(sizeof(*in), GFP_KERNEL); |
| 1584 | if (!in) | 1576 | if (!in) |
| 1585 | return -ENOMEM; | 1577 | return -ENOMEM; |
| @@ -1619,7 +1611,8 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp, | |||
| 1619 | err = -EINVAL; | 1611 | err = -EINVAL; |
| 1620 | goto out; | 1612 | goto out; |
| 1621 | } | 1613 | } |
| 1622 | context->mtu_msgmax = (attr->path_mtu << 5) | gen->log_max_msg; | 1614 | context->mtu_msgmax = (attr->path_mtu << 5) | |
| 1615 | (u8)MLX5_CAP_GEN(dev->mdev, log_max_msg); | ||
| 1623 | } | 1616 | } |
| 1624 | 1617 | ||
| 1625 | if (attr_mask & IB_QP_DEST_QPN) | 1618 | if (attr_mask & IB_QP_DEST_QPN) |
| @@ -1777,11 +1770,9 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
| 1777 | struct mlx5_ib_dev *dev = to_mdev(ibqp->device); | 1770 | struct mlx5_ib_dev *dev = to_mdev(ibqp->device); |
| 1778 | struct mlx5_ib_qp *qp = to_mqp(ibqp); | 1771 | struct mlx5_ib_qp *qp = to_mqp(ibqp); |
| 1779 | enum ib_qp_state cur_state, new_state; | 1772 | enum ib_qp_state cur_state, new_state; |
| 1780 | struct mlx5_general_caps *gen; | ||
| 1781 | int err = -EINVAL; | 1773 | int err = -EINVAL; |
| 1782 | int port; | 1774 | int port; |
| 1783 | 1775 | ||
| 1784 | gen = &dev->mdev->caps.gen; | ||
| 1785 | mutex_lock(&qp->mutex); | 1776 | mutex_lock(&qp->mutex); |
| 1786 | 1777 | ||
| 1787 | cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state; | 1778 | cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state; |
| @@ -1793,21 +1784,25 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
| 1793 | goto out; | 1784 | goto out; |
| 1794 | 1785 | ||
| 1795 | if ((attr_mask & IB_QP_PORT) && | 1786 | if ((attr_mask & IB_QP_PORT) && |
| 1796 | (attr->port_num == 0 || attr->port_num > gen->num_ports)) | 1787 | (attr->port_num == 0 || |
| 1788 | attr->port_num > MLX5_CAP_GEN(dev->mdev, num_ports))) | ||
| 1797 | goto out; | 1789 | goto out; |
| 1798 | 1790 | ||
| 1799 | if (attr_mask & IB_QP_PKEY_INDEX) { | 1791 | if (attr_mask & IB_QP_PKEY_INDEX) { |
| 1800 | port = attr_mask & IB_QP_PORT ? attr->port_num : qp->port; | 1792 | port = attr_mask & IB_QP_PORT ? attr->port_num : qp->port; |
| 1801 | if (attr->pkey_index >= gen->port[port - 1].pkey_table_len) | 1793 | if (attr->pkey_index >= |
| 1794 | dev->mdev->port_caps[port - 1].pkey_table_len) | ||
| 1802 | goto out; | 1795 | goto out; |
| 1803 | } | 1796 | } |
| 1804 | 1797 | ||
| 1805 | if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && | 1798 | if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && |
| 1806 | attr->max_rd_atomic > (1 << gen->log_max_ra_res_qp)) | 1799 | attr->max_rd_atomic > |
| 1800 | (1 << MLX5_CAP_GEN(dev->mdev, log_max_ra_res_qp))) | ||
| 1807 | goto out; | 1801 | goto out; |
| 1808 | 1802 | ||
| 1809 | if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && | 1803 | if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && |
| 1810 | attr->max_dest_rd_atomic > (1 << gen->log_max_ra_req_qp)) | 1804 | attr->max_dest_rd_atomic > |
| 1805 | (1 << MLX5_CAP_GEN(dev->mdev, log_max_ra_req_qp))) | ||
| 1811 | goto out; | 1806 | goto out; |
| 1812 | 1807 | ||
| 1813 | if (cur_state == new_state && cur_state == IB_QPS_RESET) { | 1808 | if (cur_state == new_state && cur_state == IB_QPS_RESET) { |
| @@ -3009,7 +3004,7 @@ static void to_ib_ah_attr(struct mlx5_ib_dev *ibdev, struct ib_ah_attr *ib_ah_at | |||
| 3009 | ib_ah_attr->port_num = path->port; | 3004 | ib_ah_attr->port_num = path->port; |
| 3010 | 3005 | ||
| 3011 | if (ib_ah_attr->port_num == 0 || | 3006 | if (ib_ah_attr->port_num == 0 || |
| 3012 | ib_ah_attr->port_num > dev->caps.gen.num_ports) | 3007 | ib_ah_attr->port_num > MLX5_CAP_GEN(dev, num_ports)) |
| 3013 | return; | 3008 | return; |
| 3014 | 3009 | ||
| 3015 | ib_ah_attr->sl = path->sl & 0xf; | 3010 | ib_ah_attr->sl = path->sl & 0xf; |
| @@ -3135,12 +3130,10 @@ struct ib_xrcd *mlx5_ib_alloc_xrcd(struct ib_device *ibdev, | |||
| 3135 | struct ib_udata *udata) | 3130 | struct ib_udata *udata) |
| 3136 | { | 3131 | { |
| 3137 | struct mlx5_ib_dev *dev = to_mdev(ibdev); | 3132 | struct mlx5_ib_dev *dev = to_mdev(ibdev); |
| 3138 | struct mlx5_general_caps *gen; | ||
| 3139 | struct mlx5_ib_xrcd *xrcd; | 3133 | struct mlx5_ib_xrcd *xrcd; |
| 3140 | int err; | 3134 | int err; |
| 3141 | 3135 | ||
| 3142 | gen = &dev->mdev->caps.gen; | 3136 | if (!MLX5_CAP_GEN(dev->mdev, xrc)) |
| 3143 | if (!(gen->flags & MLX5_DEV_CAP_FLAG_XRC)) | ||
| 3144 | return ERR_PTR(-ENOSYS); | 3137 | return ERR_PTR(-ENOSYS); |
| 3145 | 3138 | ||
| 3146 | xrcd = kmalloc(sizeof(*xrcd), GFP_KERNEL); | 3139 | xrcd = kmalloc(sizeof(*xrcd), GFP_KERNEL); |
diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c index 02d77a29764d..e008505e96e9 100644 --- a/drivers/infiniband/hw/mlx5/srq.c +++ b/drivers/infiniband/hw/mlx5/srq.c | |||
| @@ -165,7 +165,7 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq, | |||
| 165 | return err; | 165 | return err; |
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | if (mlx5_buf_alloc(dev->mdev, buf_size, PAGE_SIZE * 2, &srq->buf)) { | 168 | if (mlx5_buf_alloc(dev->mdev, buf_size, &srq->buf)) { |
| 169 | mlx5_ib_dbg(dev, "buf alloc failed\n"); | 169 | mlx5_ib_dbg(dev, "buf alloc failed\n"); |
| 170 | err = -ENOMEM; | 170 | err = -ENOMEM; |
| 171 | goto err_db; | 171 | goto err_db; |
| @@ -236,7 +236,6 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd, | |||
| 236 | struct ib_udata *udata) | 236 | struct ib_udata *udata) |
| 237 | { | 237 | { |
| 238 | struct mlx5_ib_dev *dev = to_mdev(pd->device); | 238 | struct mlx5_ib_dev *dev = to_mdev(pd->device); |
| 239 | struct mlx5_general_caps *gen; | ||
| 240 | struct mlx5_ib_srq *srq; | 239 | struct mlx5_ib_srq *srq; |
| 241 | int desc_size; | 240 | int desc_size; |
| 242 | int buf_size; | 241 | int buf_size; |
| @@ -245,13 +244,13 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd, | |||
| 245 | int uninitialized_var(inlen); | 244 | int uninitialized_var(inlen); |
| 246 | int is_xrc; | 245 | int is_xrc; |
| 247 | u32 flgs, xrcdn; | 246 | u32 flgs, xrcdn; |
| 247 | __u32 max_srq_wqes = 1 << MLX5_CAP_GEN(dev->mdev, log_max_srq_sz); | ||
| 248 | 248 | ||
| 249 | gen = &dev->mdev->caps.gen; | ||
| 250 | /* Sanity check SRQ size before proceeding */ | 249 | /* Sanity check SRQ size before proceeding */ |
| 251 | if (init_attr->attr.max_wr >= gen->max_srq_wqes) { | 250 | if (init_attr->attr.max_wr >= max_srq_wqes) { |
| 252 | mlx5_ib_dbg(dev, "max_wr %d, cap %d\n", | 251 | mlx5_ib_dbg(dev, "max_wr %d, cap %d\n", |
| 253 | init_attr->attr.max_wr, | 252 | init_attr->attr.max_wr, |
| 254 | gen->max_srq_wqes); | 253 | max_srq_wqes); |
| 255 | return ERR_PTR(-EINVAL); | 254 | return ERR_PTR(-EINVAL); |
| 256 | } | 255 | } |
| 257 | 256 | ||
| @@ -303,7 +302,7 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd, | |||
| 303 | 302 | ||
| 304 | in->ctx.pd = cpu_to_be32(to_mpd(pd)->pdn); | 303 | in->ctx.pd = cpu_to_be32(to_mpd(pd)->pdn); |
| 305 | in->ctx.db_record = cpu_to_be64(srq->db.dma); | 304 | in->ctx.db_record = cpu_to_be64(srq->db.dma); |
| 306 | err = mlx5_core_create_srq(dev->mdev, &srq->msrq, in, inlen); | 305 | err = mlx5_core_create_srq(dev->mdev, &srq->msrq, in, inlen, is_xrc); |
| 307 | kvfree(in); | 306 | kvfree(in); |
| 308 | if (err) { | 307 | if (err) { |
| 309 | mlx5_ib_dbg(dev, "create SRQ failed, err %d\n", err); | 308 | mlx5_ib_dbg(dev, "create SRQ failed, err %d\n", err); |
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 9d3e5c1ac60e..c7f49bbb0c72 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c | |||
| @@ -1858,8 +1858,8 @@ int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn) | |||
| 1858 | } | 1858 | } |
| 1859 | 1859 | ||
| 1860 | int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, | 1860 | int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, |
| 1861 | int port, struct ib_wc *in_wc, struct ib_grh *in_grh, | 1861 | int port, const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 1862 | void *in_mad, void *response_mad) | 1862 | const void *in_mad, void *response_mad) |
| 1863 | { | 1863 | { |
| 1864 | struct mthca_mailbox *inmailbox, *outmailbox; | 1864 | struct mthca_mailbox *inmailbox, *outmailbox; |
| 1865 | void *inbox; | 1865 | void *inbox; |
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h index f952244c54de..d2e5b194b938 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.h +++ b/drivers/infiniband/hw/mthca/mthca_cmd.h | |||
| @@ -312,8 +312,8 @@ int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee, | |||
| 312 | struct mthca_mailbox *mailbox); | 312 | struct mthca_mailbox *mailbox); |
| 313 | int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn); | 313 | int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn); |
| 314 | int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, | 314 | int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, |
| 315 | int port, struct ib_wc *in_wc, struct ib_grh *in_grh, | 315 | int port, const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 316 | void *in_mad, void *response_mad); | 316 | const void *in_mad, void *response_mad); |
| 317 | int mthca_READ_MGM(struct mthca_dev *dev, int index, | 317 | int mthca_READ_MGM(struct mthca_dev *dev, int index, |
| 318 | struct mthca_mailbox *mailbox); | 318 | struct mthca_mailbox *mailbox); |
| 319 | int mthca_WRITE_MGM(struct mthca_dev *dev, int index, | 319 | int mthca_WRITE_MGM(struct mthca_dev *dev, int index, |
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index 7e6a6d64ad4e..4393a022867b 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h | |||
| @@ -576,10 +576,11 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); | |||
| 576 | int mthca_process_mad(struct ib_device *ibdev, | 576 | int mthca_process_mad(struct ib_device *ibdev, |
| 577 | int mad_flags, | 577 | int mad_flags, |
| 578 | u8 port_num, | 578 | u8 port_num, |
| 579 | struct ib_wc *in_wc, | 579 | const struct ib_wc *in_wc, |
| 580 | struct ib_grh *in_grh, | 580 | const struct ib_grh *in_grh, |
| 581 | struct ib_mad *in_mad, | 581 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 582 | struct ib_mad *out_mad); | 582 | struct ib_mad_hdr *out, size_t *out_mad_size, |
| 583 | u16 *out_mad_pkey_index); | ||
| 583 | int mthca_create_agents(struct mthca_dev *dev); | 584 | int mthca_create_agents(struct mthca_dev *dev); |
| 584 | void mthca_free_agents(struct mthca_dev *dev); | 585 | void mthca_free_agents(struct mthca_dev *dev); |
| 585 | 586 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c index 8881fa376e06..7c3f2fb44ba5 100644 --- a/drivers/infiniband/hw/mthca/mthca_mad.c +++ b/drivers/infiniband/hw/mthca/mthca_mad.c | |||
| @@ -104,7 +104,7 @@ static void update_sm_ah(struct mthca_dev *dev, | |||
| 104 | */ | 104 | */ |
| 105 | static void smp_snoop(struct ib_device *ibdev, | 105 | static void smp_snoop(struct ib_device *ibdev, |
| 106 | u8 port_num, | 106 | u8 port_num, |
| 107 | struct ib_mad *mad, | 107 | const struct ib_mad *mad, |
| 108 | u16 prev_lid) | 108 | u16 prev_lid) |
| 109 | { | 109 | { |
| 110 | struct ib_event event; | 110 | struct ib_event event; |
| @@ -160,7 +160,7 @@ static void node_desc_override(struct ib_device *dev, | |||
| 160 | 160 | ||
| 161 | static void forward_trap(struct mthca_dev *dev, | 161 | static void forward_trap(struct mthca_dev *dev, |
| 162 | u8 port_num, | 162 | u8 port_num, |
| 163 | struct ib_mad *mad) | 163 | const struct ib_mad *mad) |
| 164 | { | 164 | { |
| 165 | int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED; | 165 | int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED; |
| 166 | struct ib_mad_send_buf *send_buf; | 166 | struct ib_mad_send_buf *send_buf; |
| @@ -170,7 +170,8 @@ static void forward_trap(struct mthca_dev *dev, | |||
| 170 | 170 | ||
| 171 | if (agent) { | 171 | if (agent) { |
| 172 | send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR, | 172 | send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR, |
| 173 | IB_MGMT_MAD_DATA, GFP_ATOMIC); | 173 | IB_MGMT_MAD_DATA, GFP_ATOMIC, |
| 174 | IB_MGMT_BASE_VERSION); | ||
| 174 | if (IS_ERR(send_buf)) | 175 | if (IS_ERR(send_buf)) |
| 175 | return; | 176 | return; |
| 176 | /* | 177 | /* |
| @@ -195,15 +196,22 @@ static void forward_trap(struct mthca_dev *dev, | |||
| 195 | int mthca_process_mad(struct ib_device *ibdev, | 196 | int mthca_process_mad(struct ib_device *ibdev, |
| 196 | int mad_flags, | 197 | int mad_flags, |
| 197 | u8 port_num, | 198 | u8 port_num, |
| 198 | struct ib_wc *in_wc, | 199 | const struct ib_wc *in_wc, |
| 199 | struct ib_grh *in_grh, | 200 | const struct ib_grh *in_grh, |
| 200 | struct ib_mad *in_mad, | 201 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 201 | struct ib_mad *out_mad) | 202 | struct ib_mad_hdr *out, size_t *out_mad_size, |
| 203 | u16 *out_mad_pkey_index) | ||
| 202 | { | 204 | { |
| 203 | int err; | 205 | int err; |
| 204 | u16 slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); | 206 | u16 slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); |
| 205 | u16 prev_lid = 0; | 207 | u16 prev_lid = 0; |
| 206 | struct ib_port_attr pattr; | 208 | struct ib_port_attr pattr; |
| 209 | const struct ib_mad *in_mad = (const struct ib_mad *)in; | ||
| 210 | struct ib_mad *out_mad = (struct ib_mad *)out; | ||
| 211 | |||
| 212 | if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || | ||
| 213 | *out_mad_size != sizeof(*out_mad))) | ||
| 214 | return IB_MAD_RESULT_FAILURE; | ||
| 207 | 215 | ||
| 208 | /* Forward locally generated traps to the SM */ | 216 | /* Forward locally generated traps to the SM */ |
| 209 | if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP && | 217 | if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP && |
diff --git a/drivers/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c index 8edb28a9a0e7..15d064479ef6 100644 --- a/drivers/infiniband/hw/mthca/mthca_profile.c +++ b/drivers/infiniband/hw/mthca/mthca_profile.c | |||
| @@ -77,7 +77,6 @@ s64 mthca_make_profile(struct mthca_dev *dev, | |||
| 77 | u64 mem_base, mem_avail; | 77 | u64 mem_base, mem_avail; |
| 78 | s64 total_size = 0; | 78 | s64 total_size = 0; |
| 79 | struct mthca_resource *profile; | 79 | struct mthca_resource *profile; |
| 80 | struct mthca_resource tmp; | ||
| 81 | int i, j; | 80 | int i, j; |
| 82 | 81 | ||
| 83 | profile = kzalloc(MTHCA_RES_NUM * sizeof *profile, GFP_KERNEL); | 82 | profile = kzalloc(MTHCA_RES_NUM * sizeof *profile, GFP_KERNEL); |
| @@ -136,11 +135,8 @@ s64 mthca_make_profile(struct mthca_dev *dev, | |||
| 136 | */ | 135 | */ |
| 137 | for (i = MTHCA_RES_NUM; i > 0; --i) | 136 | for (i = MTHCA_RES_NUM; i > 0; --i) |
| 138 | for (j = 1; j < i; ++j) { | 137 | for (j = 1; j < i; ++j) { |
| 139 | if (profile[j].size > profile[j - 1].size) { | 138 | if (profile[j].size > profile[j - 1].size) |
| 140 | tmp = profile[j]; | 139 | swap(profile[j], profile[j - 1]); |
| 141 | profile[j] = profile[j - 1]; | ||
| 142 | profile[j - 1] = tmp; | ||
| 143 | } | ||
| 144 | } | 140 | } |
| 145 | 141 | ||
| 146 | for (i = 0; i < MTHCA_RES_NUM; ++i) { | 142 | for (i = 0; i < MTHCA_RES_NUM; ++i) { |
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 415f8e1a54db..93ae51dcf2ff 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c | |||
| @@ -57,14 +57,17 @@ static void init_query_mad(struct ib_smp *mad) | |||
| 57 | mad->method = IB_MGMT_METHOD_GET; | 57 | mad->method = IB_MGMT_METHOD_GET; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | static int mthca_query_device(struct ib_device *ibdev, | 60 | static int mthca_query_device(struct ib_device *ibdev, struct ib_device_attr *props, |
| 61 | struct ib_device_attr *props) | 61 | struct ib_udata *uhw) |
| 62 | { | 62 | { |
| 63 | struct ib_smp *in_mad = NULL; | 63 | struct ib_smp *in_mad = NULL; |
| 64 | struct ib_smp *out_mad = NULL; | 64 | struct ib_smp *out_mad = NULL; |
| 65 | int err = -ENOMEM; | 65 | int err = -ENOMEM; |
| 66 | struct mthca_dev *mdev = to_mdev(ibdev); | 66 | struct mthca_dev *mdev = to_mdev(ibdev); |
| 67 | 67 | ||
| 68 | if (uhw->inlen || uhw->outlen) | ||
| 69 | return -EINVAL; | ||
| 70 | |||
| 68 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); | 71 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
| 69 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | 72 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); |
| 70 | if (!in_mad || !out_mad) | 73 | if (!in_mad || !out_mad) |
| @@ -641,16 +644,20 @@ static int mthca_destroy_qp(struct ib_qp *qp) | |||
| 641 | return 0; | 644 | return 0; |
| 642 | } | 645 | } |
| 643 | 646 | ||
| 644 | static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries, | 647 | static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, |
| 645 | int comp_vector, | 648 | const struct ib_cq_init_attr *attr, |
| 646 | struct ib_ucontext *context, | 649 | struct ib_ucontext *context, |
| 647 | struct ib_udata *udata) | 650 | struct ib_udata *udata) |
| 648 | { | 651 | { |
| 652 | int entries = attr->cqe; | ||
| 649 | struct mthca_create_cq ucmd; | 653 | struct mthca_create_cq ucmd; |
| 650 | struct mthca_cq *cq; | 654 | struct mthca_cq *cq; |
| 651 | int nent; | 655 | int nent; |
| 652 | int err; | 656 | int err; |
| 653 | 657 | ||
| 658 | if (attr->flags) | ||
| 659 | return ERR_PTR(-EINVAL); | ||
| 660 | |||
| 654 | if (entries < 1 || entries > to_mdev(ibdev)->limits.max_cqes) | 661 | if (entries < 1 || entries > to_mdev(ibdev)->limits.max_cqes) |
| 655 | return ERR_PTR(-EINVAL); | 662 | return ERR_PTR(-EINVAL); |
| 656 | 663 | ||
| @@ -1244,6 +1251,24 @@ out: | |||
| 1244 | return err; | 1251 | return err; |
| 1245 | } | 1252 | } |
| 1246 | 1253 | ||
| 1254 | static int mthca_port_immutable(struct ib_device *ibdev, u8 port_num, | ||
| 1255 | struct ib_port_immutable *immutable) | ||
| 1256 | { | ||
| 1257 | struct ib_port_attr attr; | ||
| 1258 | int err; | ||
| 1259 | |||
| 1260 | err = mthca_query_port(ibdev, port_num, &attr); | ||
| 1261 | if (err) | ||
| 1262 | return err; | ||
| 1263 | |||
| 1264 | immutable->pkey_tbl_len = attr.pkey_tbl_len; | ||
| 1265 | immutable->gid_tbl_len = attr.gid_tbl_len; | ||
| 1266 | immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB; | ||
| 1267 | immutable->max_mad_size = IB_MGMT_MAD_SIZE; | ||
| 1268 | |||
| 1269 | return 0; | ||
| 1270 | } | ||
| 1271 | |||
| 1247 | int mthca_register_device(struct mthca_dev *dev) | 1272 | int mthca_register_device(struct mthca_dev *dev) |
| 1248 | { | 1273 | { |
| 1249 | int ret; | 1274 | int ret; |
| @@ -1323,6 +1348,7 @@ int mthca_register_device(struct mthca_dev *dev) | |||
| 1323 | dev->ib_dev.reg_phys_mr = mthca_reg_phys_mr; | 1348 | dev->ib_dev.reg_phys_mr = mthca_reg_phys_mr; |
| 1324 | dev->ib_dev.reg_user_mr = mthca_reg_user_mr; | 1349 | dev->ib_dev.reg_user_mr = mthca_reg_user_mr; |
| 1325 | dev->ib_dev.dereg_mr = mthca_dereg_mr; | 1350 | dev->ib_dev.dereg_mr = mthca_dereg_mr; |
| 1351 | dev->ib_dev.get_port_immutable = mthca_port_immutable; | ||
| 1326 | 1352 | ||
| 1327 | if (dev->mthca_flags & MTHCA_FLAG_FMR) { | 1353 | if (dev->mthca_flags & MTHCA_FLAG_FMR) { |
| 1328 | dev->ib_dev.alloc_fmr = mthca_alloc_fmr; | 1354 | dev->ib_dev.alloc_fmr = mthca_alloc_fmr; |
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 72b43417cbe3..8a3ad170d790 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c | |||
| @@ -1520,8 +1520,9 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi | |||
| 1520 | int rc = arpindex; | 1520 | int rc = arpindex; |
| 1521 | struct net_device *netdev; | 1521 | struct net_device *netdev; |
| 1522 | struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter; | 1522 | struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter; |
| 1523 | __be32 dst_ipaddr = htonl(dst_ip); | ||
| 1523 | 1524 | ||
| 1524 | rt = ip_route_output(&init_net, htonl(dst_ip), 0, 0, 0); | 1525 | rt = ip_route_output(&init_net, dst_ipaddr, nesvnic->local_ipaddr, 0, 0); |
| 1525 | if (IS_ERR(rt)) { | 1526 | if (IS_ERR(rt)) { |
| 1526 | printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n", | 1527 | printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n", |
| 1527 | __func__, dst_ip); | 1528 | __func__, dst_ip); |
| @@ -1533,7 +1534,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi | |||
| 1533 | else | 1534 | else |
| 1534 | netdev = nesvnic->netdev; | 1535 | netdev = nesvnic->netdev; |
| 1535 | 1536 | ||
| 1536 | neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, netdev); | 1537 | neigh = dst_neigh_lookup(&rt->dst, &dst_ipaddr); |
| 1537 | 1538 | ||
| 1538 | rcu_read_lock(); | 1539 | rcu_read_lock(); |
| 1539 | if (neigh) { | 1540 | if (neigh) { |
| @@ -1616,6 +1617,8 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, | |||
| 1616 | &cm_node->loc_addr, cm_node->loc_port, | 1617 | &cm_node->loc_addr, cm_node->loc_port, |
| 1617 | &cm_node->rem_addr, cm_node->rem_port); | 1618 | &cm_node->rem_addr, cm_node->rem_port); |
| 1618 | cm_node->listener = listener; | 1619 | cm_node->listener = listener; |
| 1620 | if (listener) | ||
| 1621 | cm_node->tos = listener->tos; | ||
| 1619 | cm_node->netdev = nesvnic->netdev; | 1622 | cm_node->netdev = nesvnic->netdev; |
| 1620 | cm_node->cm_id = cm_info->cm_id; | 1623 | cm_node->cm_id = cm_info->cm_id; |
| 1621 | memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN); | 1624 | memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN); |
| @@ -2938,6 +2941,9 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod | |||
| 2938 | 2941 | ||
| 2939 | nesqp->nesqp_context->misc2 |= cpu_to_le32(64 << NES_QPCONTEXT_MISC2_TTL_SHIFT); | 2942 | nesqp->nesqp_context->misc2 |= cpu_to_le32(64 << NES_QPCONTEXT_MISC2_TTL_SHIFT); |
| 2940 | 2943 | ||
| 2944 | nesqp->nesqp_context->misc2 |= cpu_to_le32( | ||
| 2945 | cm_node->tos << NES_QPCONTEXT_MISC2_TOS_SHIFT); | ||
| 2946 | |||
| 2941 | nesqp->nesqp_context->mss |= cpu_to_le32(((u32)cm_node->tcp_cntxt.mss) << 16); | 2947 | nesqp->nesqp_context->mss |= cpu_to_le32(((u32)cm_node->tcp_cntxt.mss) << 16); |
| 2942 | 2948 | ||
| 2943 | nesqp->nesqp_context->tcp_state_flow_label |= cpu_to_le32( | 2949 | nesqp->nesqp_context->tcp_state_flow_label |= cpu_to_le32( |
| @@ -3612,6 +3618,7 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
| 3612 | cm_node->ord_size = 1; | 3618 | cm_node->ord_size = 1; |
| 3613 | 3619 | ||
| 3614 | cm_node->apbvt_set = apbvt_set; | 3620 | cm_node->apbvt_set = apbvt_set; |
| 3621 | cm_node->tos = cm_id->tos; | ||
| 3615 | nesqp->cm_node = cm_node; | 3622 | nesqp->cm_node = cm_node; |
| 3616 | cm_node->nesqp = nesqp; | 3623 | cm_node->nesqp = nesqp; |
| 3617 | nes_add_ref(&nesqp->ibqp); | 3624 | nes_add_ref(&nesqp->ibqp); |
| @@ -3666,6 +3673,7 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog) | |||
| 3666 | } | 3673 | } |
| 3667 | 3674 | ||
| 3668 | cm_id->provider_data = cm_node; | 3675 | cm_id->provider_data = cm_node; |
| 3676 | cm_node->tos = cm_id->tos; | ||
| 3669 | 3677 | ||
| 3670 | if (!cm_node->reused_node) { | 3678 | if (!cm_node->reused_node) { |
| 3671 | if (nes_create_mapinfo(&cm_info)) | 3679 | if (nes_create_mapinfo(&cm_info)) |
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h index f522cf639789..32a6420c2940 100644 --- a/drivers/infiniband/hw/nes/nes_cm.h +++ b/drivers/infiniband/hw/nes/nes_cm.h | |||
| @@ -303,6 +303,7 @@ struct nes_cm_listener { | |||
| 303 | int backlog; | 303 | int backlog; |
| 304 | enum nes_cm_listener_state listener_state; | 304 | enum nes_cm_listener_state listener_state; |
| 305 | u32 reused_node; | 305 | u32 reused_node; |
| 306 | u8 tos; | ||
| 306 | }; | 307 | }; |
| 307 | 308 | ||
| 308 | /* per connection node and node state information */ | 309 | /* per connection node and node state information */ |
| @@ -352,6 +353,7 @@ struct nes_cm_node { | |||
| 352 | struct list_head reset_entry; | 353 | struct list_head reset_entry; |
| 353 | struct nes_qp *nesqp; | 354 | struct nes_qp *nesqp; |
| 354 | atomic_t passive_state; | 355 | atomic_t passive_state; |
| 356 | u8 tos; | ||
| 355 | }; | 357 | }; |
| 356 | 358 | ||
| 357 | /* structure for client or CM to fill when making CM api calls. */ | 359 | /* structure for client or CM to fill when making CM api calls. */ |
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 02120d340d50..4713dd7ed764 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c | |||
| @@ -3861,7 +3861,7 @@ void nes_manage_arp_cache(struct net_device *netdev, unsigned char *mac_addr, | |||
| 3861 | (((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) | | 3861 | (((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) | |
| 3862 | (((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]); | 3862 | (((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]); |
| 3863 | cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = cpu_to_le32( | 3863 | cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = cpu_to_le32( |
| 3864 | (((u32)mac_addr[0]) << 16) | (u32)mac_addr[1]); | 3864 | (((u32)mac_addr[0]) << 8) | (u32)mac_addr[1]); |
| 3865 | } else { | 3865 | } else { |
| 3866 | cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = 0; | 3866 | cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = 0; |
| 3867 | cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = 0; | 3867 | cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = 0; |
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index c0d0296e7a00..fbc43e5f717b 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c | |||
| @@ -512,12 +512,16 @@ static void nes_free_fast_reg_page_list(struct ib_fast_reg_page_list *pifrpl) | |||
| 512 | /** | 512 | /** |
| 513 | * nes_query_device | 513 | * nes_query_device |
| 514 | */ | 514 | */ |
| 515 | static int nes_query_device(struct ib_device *ibdev, struct ib_device_attr *props) | 515 | static int nes_query_device(struct ib_device *ibdev, struct ib_device_attr *props, |
| 516 | struct ib_udata *uhw) | ||
| 516 | { | 517 | { |
| 517 | struct nes_vnic *nesvnic = to_nesvnic(ibdev); | 518 | struct nes_vnic *nesvnic = to_nesvnic(ibdev); |
| 518 | struct nes_device *nesdev = nesvnic->nesdev; | 519 | struct nes_device *nesdev = nesvnic->nesdev; |
| 519 | struct nes_ib_device *nesibdev = nesvnic->nesibdev; | 520 | struct nes_ib_device *nesibdev = nesvnic->nesibdev; |
| 520 | 521 | ||
| 522 | if (uhw->inlen || uhw->outlen) | ||
| 523 | return -EINVAL; | ||
| 524 | |||
| 521 | memset(props, 0, sizeof(*props)); | 525 | memset(props, 0, sizeof(*props)); |
| 522 | memcpy(&props->sys_image_guid, nesvnic->netdev->dev_addr, 6); | 526 | memcpy(&props->sys_image_guid, nesvnic->netdev->dev_addr, 6); |
| 523 | 527 | ||
| @@ -606,7 +610,6 @@ static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr | |||
| 606 | return 0; | 610 | return 0; |
| 607 | } | 611 | } |
| 608 | 612 | ||
| 609 | |||
| 610 | /** | 613 | /** |
| 611 | * nes_query_pkey | 614 | * nes_query_pkey |
| 612 | */ | 615 | */ |
| @@ -1527,10 +1530,12 @@ static int nes_destroy_qp(struct ib_qp *ibqp) | |||
| 1527 | /** | 1530 | /** |
| 1528 | * nes_create_cq | 1531 | * nes_create_cq |
| 1529 | */ | 1532 | */ |
| 1530 | static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, | 1533 | static struct ib_cq *nes_create_cq(struct ib_device *ibdev, |
| 1531 | int comp_vector, | 1534 | const struct ib_cq_init_attr *attr, |
| 1532 | struct ib_ucontext *context, struct ib_udata *udata) | 1535 | struct ib_ucontext *context, |
| 1536 | struct ib_udata *udata) | ||
| 1533 | { | 1537 | { |
| 1538 | int entries = attr->cqe; | ||
| 1534 | u64 u64temp; | 1539 | u64 u64temp; |
| 1535 | struct nes_vnic *nesvnic = to_nesvnic(ibdev); | 1540 | struct nes_vnic *nesvnic = to_nesvnic(ibdev); |
| 1536 | struct nes_device *nesdev = nesvnic->nesdev; | 1541 | struct nes_device *nesdev = nesvnic->nesdev; |
| @@ -1550,6 +1555,9 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, | |||
| 1550 | unsigned long flags; | 1555 | unsigned long flags; |
| 1551 | int ret; | 1556 | int ret; |
| 1552 | 1557 | ||
| 1558 | if (attr->flags) | ||
| 1559 | return ERR_PTR(-EINVAL); | ||
| 1560 | |||
| 1553 | if (entries > nesadapter->max_cqe) | 1561 | if (entries > nesadapter->max_cqe) |
| 1554 | return ERR_PTR(-EINVAL); | 1562 | return ERR_PTR(-EINVAL); |
| 1555 | 1563 | ||
| @@ -3222,8 +3230,10 @@ static int nes_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
| 3222 | * nes_process_mad | 3230 | * nes_process_mad |
| 3223 | */ | 3231 | */ |
| 3224 | static int nes_process_mad(struct ib_device *ibdev, int mad_flags, | 3232 | static int nes_process_mad(struct ib_device *ibdev, int mad_flags, |
| 3225 | u8 port_num, struct ib_wc *in_wc, struct ib_grh *in_grh, | 3233 | u8 port_num, const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 3226 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 3234 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 3235 | struct ib_mad_hdr *out, size_t *out_mad_size, | ||
| 3236 | u16 *out_mad_pkey_index) | ||
| 3227 | { | 3237 | { |
| 3228 | nes_debug(NES_DBG_INIT, "\n"); | 3238 | nes_debug(NES_DBG_INIT, "\n"); |
| 3229 | return -ENOSYS; | 3239 | return -ENOSYS; |
| @@ -3828,6 +3838,22 @@ static int nes_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags notify_ | |||
| 3828 | return 0; | 3838 | return 0; |
| 3829 | } | 3839 | } |
| 3830 | 3840 | ||
| 3841 | static int nes_port_immutable(struct ib_device *ibdev, u8 port_num, | ||
| 3842 | struct ib_port_immutable *immutable) | ||
| 3843 | { | ||
| 3844 | struct ib_port_attr attr; | ||
| 3845 | int err; | ||
| 3846 | |||
| 3847 | err = nes_query_port(ibdev, port_num, &attr); | ||
| 3848 | if (err) | ||
| 3849 | return err; | ||
| 3850 | |||
| 3851 | immutable->pkey_tbl_len = attr.pkey_tbl_len; | ||
| 3852 | immutable->gid_tbl_len = attr.gid_tbl_len; | ||
| 3853 | immutable->core_cap_flags = RDMA_CORE_PORT_IWARP; | ||
| 3854 | |||
| 3855 | return 0; | ||
| 3856 | } | ||
| 3831 | 3857 | ||
| 3832 | /** | 3858 | /** |
| 3833 | * nes_init_ofa_device | 3859 | * nes_init_ofa_device |
| @@ -3928,6 +3954,7 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev) | |||
| 3928 | nesibdev->ibdev.iwcm->reject = nes_reject; | 3954 | nesibdev->ibdev.iwcm->reject = nes_reject; |
| 3929 | nesibdev->ibdev.iwcm->create_listen = nes_create_listen; | 3955 | nesibdev->ibdev.iwcm->create_listen = nes_create_listen; |
| 3930 | nesibdev->ibdev.iwcm->destroy_listen = nes_destroy_listen; | 3956 | nesibdev->ibdev.iwcm->destroy_listen = nes_destroy_listen; |
| 3957 | nesibdev->ibdev.get_port_immutable = nes_port_immutable; | ||
| 3931 | 3958 | ||
| 3932 | return nesibdev; | 3959 | return nesibdev; |
| 3933 | } | 3960 | } |
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h index b396344fae16..6a36338593cd 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma.h | |||
| @@ -1,21 +1,36 @@ | |||
| 1 | /******************************************************************* | 1 | /* This file is part of the Emulex RoCE Device Driver for |
| 2 | * This file is part of the Emulex RoCE Device Driver for * | 2 | * RoCE (RDMA over Converged Ethernet) adapters. |
| 3 | * RoCE (RDMA over Converged Ethernet) adapters. * | 3 | * Copyright (C) 2012-2015 Emulex. All rights reserved. |
| 4 | * Copyright (C) 2008-2012 Emulex. All rights reserved. * | 4 | * EMULEX and SLI are trademarks of Emulex. |
| 5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * www.emulex.com |
| 6 | * www.emulex.com * | 6 | * |
| 7 | * * | 7 | * This software is available to you under a choice of one of two licenses. |
| 8 | * This program is free software; you can redistribute it and/or * | 8 | * You may choose to be licensed under the terms of the GNU General Public |
| 9 | * modify it under the terms of version 2 of the GNU General * | 9 | * License (GPL) Version 2, available from the file COPYING in the main |
| 10 | * Public License as published by the Free Software Foundation. * | 10 | * directory of this source tree, or the BSD license below: |
| 11 | * This program is distributed in the hope that it will be useful. * | 11 | * |
| 12 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | 12 | * Redistribution and use in source and binary forms, with or without |
| 13 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | 13 | * modification, are permitted provided that the following conditions |
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | 14 | * are met: |
| 15 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | 15 | * |
| 16 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | 16 | * - Redistributions of source code must retain the above copyright notice, |
| 17 | * more details, a copy of which can be found in the file COPYING * | 17 | * this list of conditions and the following disclaimer. |
| 18 | * included with this package. * | 18 | * |
| 19 | * - Redistributions in binary form must reproduce the above copyright | ||
| 20 | * notice, this list of conditions and the following disclaimer in | ||
| 21 | * the documentation and/or other materials provided with the distribution. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE | ||
| 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
| 30 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
| 31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
| 32 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
| 33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 19 | * | 34 | * |
| 20 | * Contact Information: | 35 | * Contact Information: |
| 21 | * linux-drivers@emulex.com | 36 | * linux-drivers@emulex.com |
| @@ -23,7 +38,7 @@ | |||
| 23 | * Emulex | 38 | * Emulex |
| 24 | * 3333 Susan Street | 39 | * 3333 Susan Street |
| 25 | * Costa Mesa, CA 92626 | 40 | * Costa Mesa, CA 92626 |
| 26 | *******************************************************************/ | 41 | */ |
| 27 | 42 | ||
| 28 | #ifndef __OCRDMA_H__ | 43 | #ifndef __OCRDMA_H__ |
| 29 | #define __OCRDMA_H__ | 44 | #define __OCRDMA_H__ |
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_abi.h b/drivers/infiniband/hw/ocrdma/ocrdma_abi.h index 1554cca5712a..430b1350fe96 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_abi.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_abi.h | |||
| @@ -1,21 +1,36 @@ | |||
| 1 | /******************************************************************* | 1 | /* This file is part of the Emulex RoCE Device Driver for |
| 2 | * This file is part of the Emulex RoCE Device Driver for * | 2 | * RoCE (RDMA over Converged Ethernet) adapters. |
| 3 | * RoCE (RDMA over Converged Ethernet) adapters. * | 3 | * Copyright (C) 2012-2015 Emulex. All rights reserved. |
| 4 | * Copyright (C) 2008-2012 Emulex. All rights reserved. * | 4 | * EMULEX and SLI are trademarks of Emulex. |
| 5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * www.emulex.com |
| 6 | * www.emulex.com * | 6 | * |
| 7 | * * | 7 | * This software is available to you under a choice of one of two licenses. |
| 8 | * This program is free software; you can redistribute it and/or * | 8 | * You may choose to be licensed under the terms of the GNU General Public |
| 9 | * modify it under the terms of version 2 of the GNU General * | 9 | * License (GPL) Version 2, available from the file COPYING in the main |
| 10 | * Public License as published by the Free Software Foundation. * | 10 | * directory of this source tree, or the BSD license below: |
| 11 | * This program is distributed in the hope that it will be useful. * | 11 | * |
| 12 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | 12 | * Redistribution and use in source and binary forms, with or without |
| 13 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | 13 | * modification, are permitted provided that the following conditions |
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | 14 | * are met: |
| 15 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | 15 | * |
| 16 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | 16 | * - Redistributions of source code must retain the above copyright notice, |
| 17 | * more details, a copy of which can be found in the file COPYING * | 17 | * this list of conditions and the following disclaimer. |
| 18 | * included with this package. * | 18 | * |
| 19 | * - Redistributions in binary form must reproduce the above copyright | ||
| 20 | * notice, this list of conditions and the following disclaimer in | ||
| 21 | * the documentation and/or other materials provided with the distribution. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE | ||
| 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
| 30 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
| 31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
| 32 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
| 33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 19 | * | 34 | * |
| 20 | * Contact Information: | 35 | * Contact Information: |
| 21 | * linux-drivers@emulex.com | 36 | * linux-drivers@emulex.com |
| @@ -23,7 +38,7 @@ | |||
| 23 | * Emulex | 38 | * Emulex |
| 24 | * 3333 Susan Street | 39 | * 3333 Susan Street |
| 25 | * Costa Mesa, CA 92626 | 40 | * Costa Mesa, CA 92626 |
| 26 | *******************************************************************/ | 41 | */ |
| 27 | 42 | ||
| 28 | #ifndef __OCRDMA_ABI_H__ | 43 | #ifndef __OCRDMA_ABI_H__ |
| 29 | #define __OCRDMA_ABI_H__ | 44 | #define __OCRDMA_ABI_H__ |
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c index f5a5ea836dbd..44766fee1f4e 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c | |||
| @@ -1,21 +1,36 @@ | |||
| 1 | /******************************************************************* | 1 | /* This file is part of the Emulex RoCE Device Driver for |
| 2 | * This file is part of the Emulex RoCE Device Driver for * | 2 | * RoCE (RDMA over Converged Ethernet) adapters. |
| 3 | * RoCE (RDMA over Converged Ethernet) adapters. * | 3 | * Copyright (C) 2012-2015 Emulex. All rights reserved. |
| 4 | * Copyright (C) 2008-2012 Emulex. All rights reserved. * | 4 | * EMULEX and SLI are trademarks of Emulex. |
| 5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * www.emulex.com |
| 6 | * www.emulex.com * | 6 | * |
| 7 | * * | 7 | * This software is available to you under a choice of one of two licenses. |
| 8 | * This program is free software; you can redistribute it and/or * | 8 | * You may choose to be licensed under the terms of the GNU General Public |
| 9 | * modify it under the terms of version 2 of the GNU General * | 9 | * License (GPL) Version 2, available from the file COPYING in the main |
| 10 | * Public License as published by the Free Software Foundation. * | 10 | * directory of this source tree, or the BSD license below: |
| 11 | * This program is distributed in the hope that it will be useful. * | 11 | * |
| 12 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | 12 | * Redistribution and use in source and binary forms, with or without |
| 13 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | 13 | * modification, are permitted provided that the following conditions |
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | 14 | * are met: |
| 15 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | 15 | * |
| 16 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | 16 | * - Redistributions of source code must retain the above copyright notice, |
| 17 | * more details, a copy of which can be found in the file COPYING * | 17 | * this list of conditions and the following disclaimer. |
| 18 | * included with this package. * | 18 | * |
| 19 | * - Redistributions in binary form must reproduce the above copyright | ||
| 20 | * notice, this list of conditions and the following disclaimer in | ||
| 21 | * the documentation and/or other materials provided with the distribution. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE | ||
| 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
| 30 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
| 31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
| 32 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
| 33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 19 | * | 34 | * |
| 20 | * Contact Information: | 35 | * Contact Information: |
| 21 | * linux-drivers@emulex.com | 36 | * linux-drivers@emulex.com |
| @@ -23,7 +38,7 @@ | |||
| 23 | * Emulex | 38 | * Emulex |
| 24 | * 3333 Susan Street | 39 | * 3333 Susan Street |
| 25 | * Costa Mesa, CA 92626 | 40 | * Costa Mesa, CA 92626 |
| 26 | *******************************************************************/ | 41 | */ |
| 27 | 42 | ||
| 28 | #include <net/neighbour.h> | 43 | #include <net/neighbour.h> |
| 29 | #include <net/netevent.h> | 44 | #include <net/netevent.h> |
| @@ -204,12 +219,20 @@ int ocrdma_modify_ah(struct ib_ah *ibah, struct ib_ah_attr *attr) | |||
| 204 | int ocrdma_process_mad(struct ib_device *ibdev, | 219 | int ocrdma_process_mad(struct ib_device *ibdev, |
| 205 | int process_mad_flags, | 220 | int process_mad_flags, |
| 206 | u8 port_num, | 221 | u8 port_num, |
| 207 | struct ib_wc *in_wc, | 222 | const struct ib_wc *in_wc, |
| 208 | struct ib_grh *in_grh, | 223 | const struct ib_grh *in_grh, |
| 209 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 224 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 225 | struct ib_mad_hdr *out, size_t *out_mad_size, | ||
| 226 | u16 *out_mad_pkey_index) | ||
| 210 | { | 227 | { |
| 211 | int status; | 228 | int status; |
| 212 | struct ocrdma_dev *dev; | 229 | struct ocrdma_dev *dev; |
| 230 | const struct ib_mad *in_mad = (const struct ib_mad *)in; | ||
| 231 | struct ib_mad *out_mad = (struct ib_mad *)out; | ||
| 232 | |||
| 233 | if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || | ||
| 234 | *out_mad_size != sizeof(*out_mad))) | ||
| 235 | return IB_MAD_RESULT_FAILURE; | ||
| 213 | 236 | ||
| 214 | switch (in_mad->mad_hdr.mgmt_class) { | 237 | switch (in_mad->mad_hdr.mgmt_class) { |
| 215 | case IB_MGMT_CLASS_PERF_MGMT: | 238 | case IB_MGMT_CLASS_PERF_MGMT: |
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.h b/drivers/infiniband/hw/ocrdma/ocrdma_ah.h index 726a87cf22dc..04a30ae67473 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.h | |||
| @@ -1,21 +1,36 @@ | |||
| 1 | /******************************************************************* | 1 | /* This file is part of the Emulex RoCE Device Driver for |
| 2 | * This file is part of the Emulex RoCE Device Driver for * | 2 | * RoCE (RDMA over Converged Ethernet) adapters. |
| 3 | * RoCE (RDMA over Converged Ethernet) adapters. * | 3 | * Copyright (C) 2012-2015 Emulex. All rights reserved. |
| 4 | * Copyright (C) 2008-2012 Emulex. All rights reserved. * | 4 | * EMULEX and SLI are trademarks of Emulex. |
| 5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * www.emulex.com |
| 6 | * www.emulex.com * | 6 | * |
| 7 | * * | 7 | * This software is available to you under a choice of one of two licenses. |
| 8 | * This program is free software; you can redistribute it and/or * | 8 | * You may choose to be licensed under the terms of the GNU General Public |
| 9 | * modify it under the terms of version 2 of the GNU General * | 9 | * License (GPL) Version 2, available from the file COPYING in the main |
| 10 | * Public License as published by the Free Software Foundation. * | 10 | * directory of this source tree, or the BSD license below: |
| 11 | * This program is distributed in the hope that it will be useful. * | 11 | * |
| 12 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | 12 | * Redistribution and use in source and binary forms, with or without |
| 13 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | 13 | * modification, are permitted provided that the following conditions |
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | 14 | * are met: |
| 15 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | 15 | * |
| 16 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | 16 | * - Redistributions of source code must retain the above copyright notice, |
| 17 | * more details, a copy of which can be found in the file COPYING * | 17 | * this list of conditions and the following disclaimer. |
| 18 | * included with this package. * | 18 | * |
| 19 | * - Redistributions in binary form must reproduce the above copyright | ||
| 20 | * notice, this list of conditions and the following disclaimer in | ||
| 21 | * the documentation and/or other materials provided with the distribution. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE | ||
| 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
| 30 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
| 31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
| 32 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
| 33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 19 | * | 34 | * |
| 20 | * Contact Information: | 35 | * Contact Information: |
| 21 | * linux-drivers@emulex.com | 36 | * linux-drivers@emulex.com |
| @@ -23,7 +38,7 @@ | |||
| 23 | * Emulex | 38 | * Emulex |
| 24 | * 3333 Susan Street | 39 | * 3333 Susan Street |
| 25 | * Costa Mesa, CA 92626 | 40 | * Costa Mesa, CA 92626 |
| 26 | *******************************************************************/ | 41 | */ |
| 27 | 42 | ||
| 28 | #ifndef __OCRDMA_AH_H__ | 43 | #ifndef __OCRDMA_AH_H__ |
| 29 | #define __OCRDMA_AH_H__ | 44 | #define __OCRDMA_AH_H__ |
| @@ -42,7 +57,9 @@ int ocrdma_modify_ah(struct ib_ah *, struct ib_ah_attr *); | |||
| 42 | int ocrdma_process_mad(struct ib_device *, | 57 | int ocrdma_process_mad(struct ib_device *, |
| 43 | int process_mad_flags, | 58 | int process_mad_flags, |
| 44 | u8 port_num, | 59 | u8 port_num, |
| 45 | struct ib_wc *in_wc, | 60 | const struct ib_wc *in_wc, |
| 46 | struct ib_grh *in_grh, | 61 | const struct ib_grh *in_grh, |
| 47 | struct ib_mad *in_mad, struct ib_mad *out_mad); | 62 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 63 | struct ib_mad_hdr *out, size_t *out_mad_size, | ||
| 64 | u16 *out_mad_pkey_index); | ||
| 48 | #endif /* __OCRDMA_AH_H__ */ | 65 | #endif /* __OCRDMA_AH_H__ */ |
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c index 47615ff33bc6..aab391a15db4 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c | |||
| @@ -1,21 +1,36 @@ | |||
| 1 | /******************************************************************* | 1 | /* This file is part of the Emulex RoCE Device Driver for |
| 2 | * This file is part of the Emulex RoCE Device Driver for * | 2 | * RoCE (RDMA over Converged Ethernet) adapters. |
| 3 | * RoCE (RDMA over Converged Ethernet) CNA Adapters. * | 3 | * Copyright (C) 2012-2015 Emulex. All rights reserved. |
| 4 | * Copyright (C) 2008-2012 Emulex. All rights reserved. * | 4 | * EMULEX and SLI are trademarks of Emulex. |
| 5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * www.emulex.com |
| 6 | * www.emulex.com * | 6 | * |
| 7 | * * | 7 | * This software is available to you under a choice of one of two licenses. |
| 8 | * This program is free software; you can redistribute it and/or * | 8 | * You may choose to be licensed under the terms of the GNU General Public |
| 9 | * modify it under the terms of version 2 of the GNU General * | 9 | * License (GPL) Version 2, available from the file COPYING in the main |
| 10 | * Public License as published by the Free Software Foundation. * | 10 | * directory of this source tree, or the BSD license below: |
| 11 | * This program is distributed in the hope that it will be useful. * | 11 | * |
| 12 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | 12 | * Redistribution and use in source and binary forms, with or without |
| 13 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | 13 | * modification, are permitted provided that the following conditions |
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | 14 | * are met: |
| 15 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | 15 | * |
| 16 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | 16 | * - Redistributions of source code must retain the above copyright notice, |
| 17 | * more details, a copy of which can be found in the file COPYING * | 17 | * this list of conditions and the following disclaimer. |
| 18 | * included with this package. * | 18 | * |
| 19 | * - Redistributions in binary form must reproduce the above copyright | ||
| 20 | * notice, this list of conditions and the following disclaimer in | ||
| 21 | * the documentation and/or other materials provided with the distribution. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE | ||
| 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
| 30 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
| 31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
| 32 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
| 33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 19 | * | 34 | * |
| 20 | * Contact Information: | 35 | * Contact Information: |
| 21 | * linux-drivers@emulex.com | 36 | * linux-drivers@emulex.com |
| @@ -23,7 +38,7 @@ | |||
| 23 | * Emulex | 38 | * Emulex |
| 24 | * 3333 Susan Street | 39 | * 3333 Susan Street |
| 25 | * Costa Mesa, CA 92626 | 40 | * Costa Mesa, CA 92626 |
| 26 | *******************************************************************/ | 41 | */ |
| 27 | 42 | ||
| 28 | #include <linux/sched.h> | 43 | #include <linux/sched.h> |
| 29 | #include <linux/interrupt.h> | 44 | #include <linux/interrupt.h> |
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.h b/drivers/infiniband/hw/ocrdma/ocrdma_hw.h index e905972fceb7..7ed885c1851e 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.h | |||
| @@ -1,21 +1,36 @@ | |||
| 1 | /******************************************************************* | 1 | /* This file is part of the Emulex RoCE Device Driver for |
| 2 | * This file is part of the Emulex RoCE Device Driver for * | 2 | * RoCE (RDMA over Converged Ethernet) adapters. |
| 3 | * RoCE (RDMA over Converged Ethernet) CNA Adapters. * | 3 | * Copyright (C) 2012-2015 Emulex. All rights reserved. |
| 4 | * Copyright (C) 2008-2012 Emulex. All rights reserved. * | 4 | * EMULEX and SLI are trademarks of Emulex. |
| 5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * www.emulex.com |
| 6 | * www.emulex.com * | 6 | * |
| 7 | * * | 7 | * This software is available to you under a choice of one of two licenses. |
| 8 | * This program is free software; you can redistribute it and/or * | 8 | * You may choose to be licensed under the terms of the GNU General Public |
| 9 | * modify it under the terms of version 2 of the GNU General * | 9 | * License (GPL) Version 2, available from the file COPYING in the main |
| 10 | * Public License as published by the Free Software Foundation. * | 10 | * directory of this source tree, or the BSD license below: |
| 11 | * This program is distributed in the hope that it will be useful. * | 11 | * |
| 12 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | 12 | * Redistribution and use in source and binary forms, with or without |
| 13 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | 13 | * modification, are permitted provided that the following conditions |
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | 14 | * are met: |
| 15 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | 15 | * |
| 16 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | 16 | * - Redistributions of source code must retain the above copyright notice, |
| 17 | * more details, a copy of which can be found in the file COPYING * | 17 | * this list of conditions and the following disclaimer. |
| 18 | * included with this package. * | 18 | * |
| 19 | * - Redistributions in binary form must reproduce the above copyright | ||
| 20 | * notice, this list of conditions and the following disclaimer in | ||
| 21 | * the documentation and/or other materials provided with the distribution. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE | ||
| 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
| 30 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
| 31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
| 32 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
| 33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 19 | * | 34 | * |
| 20 | * Contact Information: | 35 | * Contact Information: |
| 21 | * linux-drivers@emulex.com | 36 | * linux-drivers@emulex.com |
| @@ -23,7 +38,7 @@ | |||
| 23 | * Emulex | 38 | * Emulex |
| 24 | * 3333 Susan Street | 39 | * 3333 Susan Street |
| 25 | * Costa Mesa, CA 92626 | 40 | * Costa Mesa, CA 92626 |
| 26 | *******************************************************************/ | 41 | */ |
| 27 | 42 | ||
| 28 | #ifndef __OCRDMA_HW_H__ | 43 | #ifndef __OCRDMA_HW_H__ |
| 29 | #define __OCRDMA_HW_H__ | 44 | #define __OCRDMA_HW_H__ |
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c index 7a2b59aca004..b119a3413a15 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c | |||
| @@ -1,21 +1,36 @@ | |||
| 1 | /******************************************************************* | 1 | /* This file is part of the Emulex RoCE Device Driver for |
| 2 | * This file is part of the Emulex RoCE Device Driver for * | 2 | * RoCE (RDMA over Converged Ethernet) adapters. |
| 3 | * RoCE (RDMA over Converged Ethernet) adapters. * | 3 | * Copyright (C) 2012-2015 Emulex. All rights reserved. |
| 4 | * Copyright (C) 2008-2012 Emulex. All rights reserved. * | 4 | * EMULEX and SLI are trademarks of Emulex. |
| 5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * www.emulex.com |
| 6 | * www.emulex.com * | 6 | * |
| 7 | * * | 7 | * This software is available to you under a choice of one of two licenses. |
| 8 | * This program is free software; you can redistribute it and/or * | 8 | * You may choose to be licensed under the terms of the GNU General Public |
| 9 | * modify it under the terms of version 2 of the GNU General * | 9 | * License (GPL) Version 2, available from the file COPYING in the main |
| 10 | * Public License as published by the Free Software Foundation. * | 10 | * directory of this source tree, or the BSD license below: |
| 11 | * This program is distributed in the hope that it will be useful. * | 11 | * |
| 12 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | 12 | * Redistribution and use in source and binary forms, with or without |
| 13 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | 13 | * modification, are permitted provided that the following conditions |
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | 14 | * are met: |
| 15 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | 15 | * |
| 16 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | 16 | * - Redistributions of source code must retain the above copyright notice, |
| 17 | * more details, a copy of which can be found in the file COPYING * | 17 | * this list of conditions and the following disclaimer. |
| 18 | * included with this package. * | 18 | * |
| 19 | * - Redistributions in binary form must reproduce the above copyright | ||
| 20 | * notice, this list of conditions and the following disclaimer in | ||
| 21 | * the documentation and/or other materials provided with the distribution. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE | ||
| 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
| 30 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
| 31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
| 32 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
| 33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 19 | * | 34 | * |
| 20 | * Contact Information: | 35 | * Contact Information: |
| 21 | * linux-drivers@emulex.com | 36 | * linux-drivers@emulex.com |
| @@ -23,13 +38,14 @@ | |||
| 23 | * Emulex | 38 | * Emulex |
| 24 | * 3333 Susan Street | 39 | * 3333 Susan Street |
| 25 | * Costa Mesa, CA 92626 | 40 | * Costa Mesa, CA 92626 |
| 26 | *******************************************************************/ | 41 | */ |
| 27 | 42 | ||
| 28 | #include <linux/module.h> | 43 | #include <linux/module.h> |
| 29 | #include <linux/idr.h> | 44 | #include <linux/idr.h> |
| 30 | #include <rdma/ib_verbs.h> | 45 | #include <rdma/ib_verbs.h> |
| 31 | #include <rdma/ib_user_verbs.h> | 46 | #include <rdma/ib_user_verbs.h> |
| 32 | #include <rdma/ib_addr.h> | 47 | #include <rdma/ib_addr.h> |
| 48 | #include <rdma/ib_mad.h> | ||
| 33 | 49 | ||
| 34 | #include <linux/netdevice.h> | 50 | #include <linux/netdevice.h> |
| 35 | #include <net/addrconf.h> | 51 | #include <net/addrconf.h> |
| @@ -45,7 +61,7 @@ | |||
| 45 | MODULE_VERSION(OCRDMA_ROCE_DRV_VERSION); | 61 | MODULE_VERSION(OCRDMA_ROCE_DRV_VERSION); |
| 46 | MODULE_DESCRIPTION(OCRDMA_ROCE_DRV_DESC " " OCRDMA_ROCE_DRV_VERSION); | 62 | MODULE_DESCRIPTION(OCRDMA_ROCE_DRV_DESC " " OCRDMA_ROCE_DRV_VERSION); |
| 47 | MODULE_AUTHOR("Emulex Corporation"); | 63 | MODULE_AUTHOR("Emulex Corporation"); |
| 48 | MODULE_LICENSE("GPL"); | 64 | MODULE_LICENSE("Dual BSD/GPL"); |
| 49 | 65 | ||
| 50 | static LIST_HEAD(ocrdma_dev_list); | 66 | static LIST_HEAD(ocrdma_dev_list); |
| 51 | static DEFINE_SPINLOCK(ocrdma_devlist_lock); | 67 | static DEFINE_SPINLOCK(ocrdma_devlist_lock); |
| @@ -202,6 +218,24 @@ static enum rdma_link_layer ocrdma_link_layer(struct ib_device *device, | |||
| 202 | return IB_LINK_LAYER_ETHERNET; | 218 | return IB_LINK_LAYER_ETHERNET; |
| 203 | } | 219 | } |
| 204 | 220 | ||
| 221 | static int ocrdma_port_immutable(struct ib_device *ibdev, u8 port_num, | ||
| 222 | struct ib_port_immutable *immutable) | ||
| 223 | { | ||
| 224 | struct ib_port_attr attr; | ||
| 225 | int err; | ||
| 226 | |||
| 227 | err = ocrdma_query_port(ibdev, port_num, &attr); | ||
| 228 | if (err) | ||
| 229 | return err; | ||
| 230 | |||
| 231 | immutable->pkey_tbl_len = attr.pkey_tbl_len; | ||
| 232 | immutable->gid_tbl_len = attr.gid_tbl_len; | ||
| 233 | immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE; | ||
| 234 | immutable->max_mad_size = IB_MGMT_MAD_SIZE; | ||
| 235 | |||
| 236 | return 0; | ||
| 237 | } | ||
| 238 | |||
| 205 | static int ocrdma_register_device(struct ocrdma_dev *dev) | 239 | static int ocrdma_register_device(struct ocrdma_dev *dev) |
| 206 | { | 240 | { |
| 207 | strlcpy(dev->ibdev.name, "ocrdma%d", IB_DEVICE_NAME_MAX); | 241 | strlcpy(dev->ibdev.name, "ocrdma%d", IB_DEVICE_NAME_MAX); |
| @@ -286,6 +320,7 @@ static int ocrdma_register_device(struct ocrdma_dev *dev) | |||
| 286 | dev->ibdev.dma_device = &dev->nic_info.pdev->dev; | 320 | dev->ibdev.dma_device = &dev->nic_info.pdev->dev; |
| 287 | 321 | ||
| 288 | dev->ibdev.process_mad = ocrdma_process_mad; | 322 | dev->ibdev.process_mad = ocrdma_process_mad; |
| 323 | dev->ibdev.get_port_immutable = ocrdma_port_immutable; | ||
| 289 | 324 | ||
| 290 | if (ocrdma_get_asic_type(dev) == OCRDMA_ASIC_GEN_SKH_R) { | 325 | if (ocrdma_get_asic_type(dev) == OCRDMA_ASIC_GEN_SKH_R) { |
| 291 | dev->ibdev.uverbs_cmd_mask |= | 326 | dev->ibdev.uverbs_cmd_mask |= |
| @@ -676,6 +711,7 @@ static void __exit ocrdma_exit_module(void) | |||
| 676 | ocrdma_unregister_inet6addr_notifier(); | 711 | ocrdma_unregister_inet6addr_notifier(); |
| 677 | ocrdma_unregister_inetaddr_notifier(); | 712 | ocrdma_unregister_inetaddr_notifier(); |
| 678 | ocrdma_rem_debugfs(); | 713 | ocrdma_rem_debugfs(); |
| 714 | idr_destroy(&ocrdma_dev_id); | ||
| 679 | } | 715 | } |
| 680 | 716 | ||
| 681 | module_init(ocrdma_init_module); | 717 | module_init(ocrdma_init_module); |
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h index 02ad0aee99af..80006b24aa11 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h | |||
| @@ -1,21 +1,36 @@ | |||
| 1 | /******************************************************************* | 1 | /* This file is part of the Emulex RoCE Device Driver for |
| 2 | * This file is part of the Emulex RoCE Device Driver for * | 2 | * RoCE (RDMA over Converged Ethernet) adapters. |
| 3 | * RoCE (RDMA over Converged Ethernet) adapters. * | 3 | * Copyright (C) 2012-2015 Emulex. All rights reserved. |
| 4 | * Copyright (C) 2008-2012 Emulex. All rights reserved. * | 4 | * EMULEX and SLI are trademarks of Emulex. |
| 5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * www.emulex.com |
| 6 | * www.emulex.com * | 6 | * |
| 7 | * * | 7 | * This software is available to you under a choice of one of two licenses. |
| 8 | * This program is free software; you can redistribute it and/or * | 8 | * You may choose to be licensed under the terms of the GNU General Public |
| 9 | * modify it under the terms of version 2 of the GNU General * | 9 | * License (GPL) Version 2, available from the file COPYING in the main |
| 10 | * Public License as published by the Free Software Foundation. * | 10 | * directory of this source tree, or the BSD license below: |
| 11 | * This program is distributed in the hope that it will be useful. * | 11 | * |
| 12 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | 12 | * Redistribution and use in source and binary forms, with or without |
| 13 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | 13 | * modification, are permitted provided that the following conditions |
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | 14 | * are met: |
| 15 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | 15 | * |
| 16 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | 16 | * - Redistributions of source code must retain the above copyright notice, |
| 17 | * more details, a copy of which can be found in the file COPYING * | 17 | * this list of conditions and the following disclaimer. |
| 18 | * included with this package. * | 18 | * |
| 19 | * - Redistributions in binary form must reproduce the above copyright | ||
| 20 | * notice, this list of conditions and the following disclaimer in | ||
| 21 | * the documentation and/or other materials provided with the distribution. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE | ||
| 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
| 30 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
| 31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
| 32 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
| 33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 19 | * | 34 | * |
| 20 | * Contact Information: | 35 | * Contact Information: |
| 21 | * linux-drivers@emulex.com | 36 | * linux-drivers@emulex.com |
| @@ -23,7 +38,7 @@ | |||
| 23 | * Emulex | 38 | * Emulex |
| 24 | * 3333 Susan Street | 39 | * 3333 Susan Street |
| 25 | * Costa Mesa, CA 92626 | 40 | * Costa Mesa, CA 92626 |
| 26 | *******************************************************************/ | 41 | */ |
| 27 | 42 | ||
| 28 | #ifndef __OCRDMA_SLI_H__ | 43 | #ifndef __OCRDMA_SLI_H__ |
| 29 | #define __OCRDMA_SLI_H__ | 44 | #define __OCRDMA_SLI_H__ |
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c index 48d7ef51aa0c..69334e214571 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c | |||
| @@ -1,21 +1,36 @@ | |||
| 1 | /******************************************************************* | 1 | /* This file is part of the Emulex RoCE Device Driver for |
| 2 | * This file is part of the Emulex RoCE Device Driver for * | 2 | * RoCE (RDMA over Converged Ethernet) adapters. |
| 3 | * RoCE (RDMA over Converged Ethernet) adapters. * | 3 | * Copyright (C) 2012-2015 Emulex. All rights reserved. |
| 4 | * Copyright (C) 2008-2014 Emulex. All rights reserved. * | 4 | * EMULEX and SLI are trademarks of Emulex. |
| 5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * www.emulex.com |
| 6 | * www.emulex.com * | 6 | * |
| 7 | * * | 7 | * This software is available to you under a choice of one of two licenses. |
| 8 | * This program is free software; you can redistribute it and/or * | 8 | * You may choose to be licensed under the terms of the GNU General Public |
| 9 | * modify it under the terms of version 2 of the GNU General * | 9 | * License (GPL) Version 2, available from the file COPYING in the main |
| 10 | * Public License as published by the Free Software Foundation. * | 10 | * directory of this source tree, or the BSD license below: |
| 11 | * This program is distributed in the hope that it will be useful. * | 11 | * |
| 12 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | 12 | * Redistribution and use in source and binary forms, with or without |
| 13 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | 13 | * modification, are permitted provided that the following conditions |
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | 14 | * are met: |
| 15 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | 15 | * |
| 16 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | 16 | * - Redistributions of source code must retain the above copyright notice, |
| 17 | * more details, a copy of which can be found in the file COPYING * | 17 | * this list of conditions and the following disclaimer. |
| 18 | * included with this package. * | 18 | * |
| 19 | * - Redistributions in binary form must reproduce the above copyright | ||
| 20 | * notice, this list of conditions and the following disclaimer in | ||
| 21 | * the documentation and/or other materials provided with the distribution. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE | ||
| 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
| 30 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
| 31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
| 32 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
| 33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 19 | * | 34 | * |
| 20 | * Contact Information: | 35 | * Contact Information: |
| 21 | * linux-drivers@emulex.com | 36 | * linux-drivers@emulex.com |
| @@ -23,7 +38,7 @@ | |||
| 23 | * Emulex | 38 | * Emulex |
| 24 | * 3333 Susan Street | 39 | * 3333 Susan Street |
| 25 | * Costa Mesa, CA 92626 | 40 | * Costa Mesa, CA 92626 |
| 26 | *******************************************************************/ | 41 | */ |
| 27 | 42 | ||
| 28 | #include <rdma/ib_addr.h> | 43 | #include <rdma/ib_addr.h> |
| 29 | #include <rdma/ib_pma.h> | 44 | #include <rdma/ib_pma.h> |
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_stats.h b/drivers/infiniband/hw/ocrdma/ocrdma_stats.h index 091edd68a8a3..c9e58d04c7b8 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_stats.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_stats.h | |||
| @@ -1,21 +1,36 @@ | |||
| 1 | /******************************************************************* | 1 | /* This file is part of the Emulex RoCE Device Driver for |
| 2 | * This file is part of the Emulex RoCE Device Driver for * | 2 | * RoCE (RDMA over Converged Ethernet) adapters. |
| 3 | * RoCE (RDMA over Converged Ethernet) adapters. * | 3 | * Copyright (C) 2012-2015 Emulex. All rights reserved. |
| 4 | * Copyright (C) 2008-2014 Emulex. All rights reserved. * | 4 | * EMULEX and SLI are trademarks of Emulex. |
| 5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * www.emulex.com |
| 6 | * www.emulex.com * | 6 | * |
| 7 | * * | 7 | * This software is available to you under a choice of one of two licenses. |
| 8 | * This program is free software; you can redistribute it and/or * | 8 | * You may choose to be licensed under the terms of the GNU General Public |
| 9 | * modify it under the terms of version 2 of the GNU General * | 9 | * License (GPL) Version 2, available from the file COPYING in the main |
| 10 | * Public License as published by the Free Software Foundation. * | 10 | * directory of this source tree, or the BSD license below: |
| 11 | * This program is distributed in the hope that it will be useful. * | 11 | * |
| 12 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | 12 | * Redistribution and use in source and binary forms, with or without |
| 13 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | 13 | * modification, are permitted provided that the following conditions |
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | 14 | * are met: |
| 15 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | 15 | * |
| 16 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | 16 | * - Redistributions of source code must retain the above copyright notice, |
| 17 | * more details, a copy of which can be found in the file COPYING * | 17 | * this list of conditions and the following disclaimer. |
| 18 | * included with this package. * | 18 | * |
| 19 | * - Redistributions in binary form must reproduce the above copyright | ||
| 20 | * notice, this list of conditions and the following disclaimer in | ||
| 21 | * the documentation and/or other materials provided with the distribution. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE | ||
| 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
| 30 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
| 31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
| 32 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
| 33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 19 | * | 34 | * |
| 20 | * Contact Information: | 35 | * Contact Information: |
| 21 | * linux-drivers@emulex.com | 36 | * linux-drivers@emulex.com |
| @@ -23,7 +38,7 @@ | |||
| 23 | * Emulex | 38 | * Emulex |
| 24 | * 3333 Susan Street | 39 | * 3333 Susan Street |
| 25 | * Costa Mesa, CA 92626 | 40 | * Costa Mesa, CA 92626 |
| 26 | *******************************************************************/ | 41 | */ |
| 27 | 42 | ||
| 28 | #ifndef __OCRDMA_STATS_H__ | 43 | #ifndef __OCRDMA_STATS_H__ |
| 29 | #define __OCRDMA_STATS_H__ | 44 | #define __OCRDMA_STATS_H__ |
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index 9dcb66077d6c..bc84cd462ecf 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | |||
| @@ -1,21 +1,36 @@ | |||
| 1 | /******************************************************************* | 1 | /* This file is part of the Emulex RoCE Device Driver for |
| 2 | * This file is part of the Emulex RoCE Device Driver for * | 2 | * RoCE (RDMA over Converged Ethernet) adapters. |
| 3 | * RoCE (RDMA over Converged Ethernet) adapters. * | 3 | * Copyright (C) 2012-2015 Emulex. All rights reserved. |
| 4 | * Copyright (C) 2008-2012 Emulex. All rights reserved. * | 4 | * EMULEX and SLI are trademarks of Emulex. |
| 5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * www.emulex.com |
| 6 | * www.emulex.com * | 6 | * |
| 7 | * * | 7 | * This software is available to you under a choice of one of two licenses. |
| 8 | * This program is free software; you can redistribute it and/or * | 8 | * You may choose to be licensed under the terms of the GNU General Public |
| 9 | * modify it under the terms of version 2 of the GNU General * | 9 | * License (GPL) Version 2, available from the file COPYING in the main |
| 10 | * Public License as published by the Free Software Foundation. * | 10 | * directory of this source tree, or the BSD license below: |
| 11 | * This program is distributed in the hope that it will be useful. * | 11 | * |
| 12 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | 12 | * Redistribution and use in source and binary forms, with or without |
| 13 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | 13 | * modification, are permitted provided that the following conditions |
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | 14 | * are met: |
| 15 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | 15 | * |
| 16 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | 16 | * - Redistributions of source code must retain the above copyright notice, |
| 17 | * more details, a copy of which can be found in the file COPYING * | 17 | * this list of conditions and the following disclaimer. |
| 18 | * included with this package. * | 18 | * |
| 19 | * - Redistributions in binary form must reproduce the above copyright | ||
| 20 | * notice, this list of conditions and the following disclaimer in | ||
| 21 | * the documentation and/or other materials provided with the distribution. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE | ||
| 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
| 30 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
| 31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
| 32 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
| 33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 19 | * | 34 | * |
| 20 | * Contact Information: | 35 | * Contact Information: |
| 21 | * linux-drivers@emulex.com | 36 | * linux-drivers@emulex.com |
| @@ -23,7 +38,7 @@ | |||
| 23 | * Emulex | 38 | * Emulex |
| 24 | * 3333 Susan Street | 39 | * 3333 Susan Street |
| 25 | * Costa Mesa, CA 92626 | 40 | * Costa Mesa, CA 92626 |
| 26 | *******************************************************************/ | 41 | */ |
| 27 | 42 | ||
| 28 | #include <linux/dma-mapping.h> | 43 | #include <linux/dma-mapping.h> |
| 29 | #include <rdma/ib_verbs.h> | 44 | #include <rdma/ib_verbs.h> |
| @@ -61,10 +76,14 @@ int ocrdma_query_gid(struct ib_device *ibdev, u8 port, | |||
| 61 | return 0; | 76 | return 0; |
| 62 | } | 77 | } |
| 63 | 78 | ||
| 64 | int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr) | 79 | int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr, |
| 80 | struct ib_udata *uhw) | ||
| 65 | { | 81 | { |
| 66 | struct ocrdma_dev *dev = get_ocrdma_dev(ibdev); | 82 | struct ocrdma_dev *dev = get_ocrdma_dev(ibdev); |
| 67 | 83 | ||
| 84 | if (uhw->inlen || uhw->outlen) | ||
| 85 | return -EINVAL; | ||
| 86 | |||
| 68 | memset(attr, 0, sizeof *attr); | 87 | memset(attr, 0, sizeof *attr); |
| 69 | memcpy(&attr->fw_ver, &dev->attr.fw_ver[0], | 88 | memcpy(&attr->fw_ver, &dev->attr.fw_ver[0], |
| 70 | min(sizeof(dev->attr.fw_ver), sizeof(attr->fw_ver))); | 89 | min(sizeof(dev->attr.fw_ver), sizeof(attr->fw_ver))); |
| @@ -375,7 +394,12 @@ static struct ocrdma_pd *_ocrdma_alloc_pd(struct ocrdma_dev *dev, | |||
| 375 | 394 | ||
| 376 | if (dev->pd_mgr->pd_prealloc_valid) { | 395 | if (dev->pd_mgr->pd_prealloc_valid) { |
| 377 | status = ocrdma_get_pd_num(dev, pd); | 396 | status = ocrdma_get_pd_num(dev, pd); |
| 378 | return (status == 0) ? pd : ERR_PTR(status); | 397 | if (status == 0) { |
| 398 | return pd; | ||
| 399 | } else { | ||
| 400 | kfree(pd); | ||
| 401 | return ERR_PTR(status); | ||
| 402 | } | ||
| 379 | } | 403 | } |
| 380 | 404 | ||
| 381 | retry: | 405 | retry: |
| @@ -679,7 +703,6 @@ err: | |||
| 679 | ocrdma_release_ucontext_pd(uctx); | 703 | ocrdma_release_ucontext_pd(uctx); |
| 680 | } else { | 704 | } else { |
| 681 | status = _ocrdma_dealloc_pd(dev, pd); | 705 | status = _ocrdma_dealloc_pd(dev, pd); |
| 682 | kfree(pd); | ||
| 683 | } | 706 | } |
| 684 | exit: | 707 | exit: |
| 685 | return ERR_PTR(status); | 708 | return ERR_PTR(status); |
| @@ -1000,10 +1023,12 @@ err: | |||
| 1000 | return status; | 1023 | return status; |
| 1001 | } | 1024 | } |
| 1002 | 1025 | ||
| 1003 | struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev, int entries, int vector, | 1026 | struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev, |
| 1027 | const struct ib_cq_init_attr *attr, | ||
| 1004 | struct ib_ucontext *ib_ctx, | 1028 | struct ib_ucontext *ib_ctx, |
| 1005 | struct ib_udata *udata) | 1029 | struct ib_udata *udata) |
| 1006 | { | 1030 | { |
| 1031 | int entries = attr->cqe; | ||
| 1007 | struct ocrdma_cq *cq; | 1032 | struct ocrdma_cq *cq; |
| 1008 | struct ocrdma_dev *dev = get_ocrdma_dev(ibdev); | 1033 | struct ocrdma_dev *dev = get_ocrdma_dev(ibdev); |
| 1009 | struct ocrdma_ucontext *uctx = NULL; | 1034 | struct ocrdma_ucontext *uctx = NULL; |
| @@ -1011,6 +1036,9 @@ struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev, int entries, int vector, | |||
| 1011 | int status; | 1036 | int status; |
| 1012 | struct ocrdma_create_cq_ureq ureq; | 1037 | struct ocrdma_create_cq_ureq ureq; |
| 1013 | 1038 | ||
| 1039 | if (attr->flags) | ||
| 1040 | return ERR_PTR(-EINVAL); | ||
| 1041 | |||
| 1014 | if (udata) { | 1042 | if (udata) { |
| 1015 | if (ib_copy_from_udata(&ureq, udata, sizeof(ureq))) | 1043 | if (ib_copy_from_udata(&ureq, udata, sizeof(ureq))) |
| 1016 | return ERR_PTR(-EFAULT); | 1044 | return ERR_PTR(-EFAULT); |
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h index b8f7853fd36c..eaccb2d3cb9f 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h | |||
| @@ -1,21 +1,36 @@ | |||
| 1 | /******************************************************************* | 1 | /* This file is part of the Emulex RoCE Device Driver for |
| 2 | * This file is part of the Emulex RoCE Device Driver for * | 2 | * RoCE (RDMA over Converged Ethernet) adapters. |
| 3 | * RoCE (RDMA over Converged Ethernet) adapters. * | 3 | * Copyright (C) 2012-2015 Emulex. All rights reserved. |
| 4 | * Copyright (C) 2008-2012 Emulex. All rights reserved. * | 4 | * EMULEX and SLI are trademarks of Emulex. |
| 5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * www.emulex.com |
| 6 | * www.emulex.com * | 6 | * |
| 7 | * * | 7 | * This software is available to you under a choice of one of two licenses. |
| 8 | * This program is free software; you can redistribute it and/or * | 8 | * You may choose to be licensed under the terms of the GNU General Public |
| 9 | * modify it under the terms of version 2 of the GNU General * | 9 | * License (GPL) Version 2, available from the file COPYING in the main |
| 10 | * Public License as published by the Free Software Foundation. * | 10 | * directory of this source tree, or the BSD license below: |
| 11 | * This program is distributed in the hope that it will be useful. * | 11 | * |
| 12 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | 12 | * Redistribution and use in source and binary forms, with or without |
| 13 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | 13 | * modification, are permitted provided that the following conditions |
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | 14 | * are met: |
| 15 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | 15 | * |
| 16 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | 16 | * - Redistributions of source code must retain the above copyright notice, |
| 17 | * more details, a copy of which can be found in the file COPYING * | 17 | * this list of conditions and the following disclaimer. |
| 18 | * included with this package. * | 18 | * |
| 19 | * - Redistributions in binary form must reproduce the above copyright | ||
| 20 | * notice, this list of conditions and the following disclaimer in | ||
| 21 | * the documentation and/or other materials provided with the distribution. | ||
| 22 | * | ||
| 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE | ||
| 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
| 30 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
| 31 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
| 32 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
| 33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 19 | * | 34 | * |
| 20 | * Contact Information: | 35 | * Contact Information: |
| 21 | * linux-drivers@emulex.com | 36 | * linux-drivers@emulex.com |
| @@ -23,7 +38,7 @@ | |||
| 23 | * Emulex | 38 | * Emulex |
| 24 | * 3333 Susan Street | 39 | * 3333 Susan Street |
| 25 | * Costa Mesa, CA 92626 | 40 | * Costa Mesa, CA 92626 |
| 26 | *******************************************************************/ | 41 | */ |
| 27 | 42 | ||
| 28 | #ifndef __OCRDMA_VERBS_H__ | 43 | #ifndef __OCRDMA_VERBS_H__ |
| 29 | #define __OCRDMA_VERBS_H__ | 44 | #define __OCRDMA_VERBS_H__ |
| @@ -36,11 +51,15 @@ int ocrdma_post_recv(struct ib_qp *, struct ib_recv_wr *, | |||
| 36 | int ocrdma_poll_cq(struct ib_cq *, int num_entries, struct ib_wc *wc); | 51 | int ocrdma_poll_cq(struct ib_cq *, int num_entries, struct ib_wc *wc); |
| 37 | int ocrdma_arm_cq(struct ib_cq *, enum ib_cq_notify_flags flags); | 52 | int ocrdma_arm_cq(struct ib_cq *, enum ib_cq_notify_flags flags); |
| 38 | 53 | ||
| 39 | int ocrdma_query_device(struct ib_device *, struct ib_device_attr *props); | 54 | int ocrdma_query_device(struct ib_device *, struct ib_device_attr *props, |
| 55 | struct ib_udata *uhw); | ||
| 40 | int ocrdma_query_port(struct ib_device *, u8 port, struct ib_port_attr *props); | 56 | int ocrdma_query_port(struct ib_device *, u8 port, struct ib_port_attr *props); |
| 41 | int ocrdma_modify_port(struct ib_device *, u8 port, int mask, | 57 | int ocrdma_modify_port(struct ib_device *, u8 port, int mask, |
| 42 | struct ib_port_modify *props); | 58 | struct ib_port_modify *props); |
| 43 | 59 | ||
| 60 | enum rdma_protocol_type | ||
| 61 | ocrdma_query_protocol(struct ib_device *device, u8 port_num); | ||
| 62 | |||
| 44 | void ocrdma_get_guid(struct ocrdma_dev *, u8 *guid); | 63 | void ocrdma_get_guid(struct ocrdma_dev *, u8 *guid); |
| 45 | int ocrdma_query_gid(struct ib_device *, u8 port, | 64 | int ocrdma_query_gid(struct ib_device *, u8 port, |
| 46 | int index, union ib_gid *gid); | 65 | int index, union ib_gid *gid); |
| @@ -56,8 +75,10 @@ struct ib_pd *ocrdma_alloc_pd(struct ib_device *, | |||
| 56 | struct ib_ucontext *, struct ib_udata *); | 75 | struct ib_ucontext *, struct ib_udata *); |
| 57 | int ocrdma_dealloc_pd(struct ib_pd *pd); | 76 | int ocrdma_dealloc_pd(struct ib_pd *pd); |
| 58 | 77 | ||
| 59 | struct ib_cq *ocrdma_create_cq(struct ib_device *, int entries, int vector, | 78 | struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev, |
| 60 | struct ib_ucontext *, struct ib_udata *); | 79 | const struct ib_cq_init_attr *attr, |
| 80 | struct ib_ucontext *ib_ctx, | ||
| 81 | struct ib_udata *udata); | ||
| 61 | int ocrdma_resize_cq(struct ib_cq *, int cqe, struct ib_udata *); | 82 | int ocrdma_resize_cq(struct ib_cq *, int cqe, struct ib_udata *); |
| 62 | int ocrdma_destroy_cq(struct ib_cq *); | 83 | int ocrdma_destroy_cq(struct ib_cq *); |
| 63 | 84 | ||
diff --git a/drivers/infiniband/hw/qib/qib_cq.c b/drivers/infiniband/hw/qib/qib_cq.c index ab4e11cfab15..2b45d0b02300 100644 --- a/drivers/infiniband/hw/qib/qib_cq.c +++ b/drivers/infiniband/hw/qib/qib_cq.c | |||
| @@ -203,7 +203,7 @@ static void send_complete(struct kthread_work *work) | |||
| 203 | /** | 203 | /** |
| 204 | * qib_create_cq - create a completion queue | 204 | * qib_create_cq - create a completion queue |
| 205 | * @ibdev: the device this completion queue is attached to | 205 | * @ibdev: the device this completion queue is attached to |
| 206 | * @entries: the minimum size of the completion queue | 206 | * @attr: creation attributes |
| 207 | * @context: unused by the QLogic_IB driver | 207 | * @context: unused by the QLogic_IB driver |
| 208 | * @udata: user data for libibverbs.so | 208 | * @udata: user data for libibverbs.so |
| 209 | * | 209 | * |
| @@ -212,16 +212,21 @@ static void send_complete(struct kthread_work *work) | |||
| 212 | * | 212 | * |
| 213 | * Called by ib_create_cq() in the generic verbs code. | 213 | * Called by ib_create_cq() in the generic verbs code. |
| 214 | */ | 214 | */ |
| 215 | struct ib_cq *qib_create_cq(struct ib_device *ibdev, int entries, | 215 | struct ib_cq *qib_create_cq(struct ib_device *ibdev, |
| 216 | int comp_vector, struct ib_ucontext *context, | 216 | const struct ib_cq_init_attr *attr, |
| 217 | struct ib_ucontext *context, | ||
| 217 | struct ib_udata *udata) | 218 | struct ib_udata *udata) |
| 218 | { | 219 | { |
| 220 | int entries = attr->cqe; | ||
| 219 | struct qib_ibdev *dev = to_idev(ibdev); | 221 | struct qib_ibdev *dev = to_idev(ibdev); |
| 220 | struct qib_cq *cq; | 222 | struct qib_cq *cq; |
| 221 | struct qib_cq_wc *wc; | 223 | struct qib_cq_wc *wc; |
| 222 | struct ib_cq *ret; | 224 | struct ib_cq *ret; |
| 223 | u32 sz; | 225 | u32 sz; |
| 224 | 226 | ||
| 227 | if (attr->flags) | ||
| 228 | return ERR_PTR(-EINVAL); | ||
| 229 | |||
| 225 | if (entries < 1 || entries > ib_qib_max_cqes) { | 230 | if (entries < 1 || entries > ib_qib_max_cqes) { |
| 226 | ret = ERR_PTR(-EINVAL); | 231 | ret = ERR_PTR(-EINVAL); |
| 227 | goto done; | 232 | goto done; |
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c index bdd5d3857203..13ef22bd9459 100644 --- a/drivers/infiniband/hw/qib/qib_fs.c +++ b/drivers/infiniband/hw/qib/qib_fs.c | |||
| @@ -455,7 +455,7 @@ static int remove_file(struct dentry *parent, char *name) | |||
| 455 | } | 455 | } |
| 456 | 456 | ||
| 457 | spin_lock(&tmp->d_lock); | 457 | spin_lock(&tmp->d_lock); |
| 458 | if (!d_unhashed(tmp) && d_really_is_positive(tmp)) { | 458 | if (simple_positive(tmp)) { |
| 459 | __d_drop(tmp); | 459 | __d_drop(tmp); |
| 460 | spin_unlock(&tmp->d_lock); | 460 | spin_unlock(&tmp->d_lock); |
| 461 | simple_unlink(d_inode(parent), tmp); | 461 | simple_unlink(d_inode(parent), tmp); |
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index f32b4628e991..6c8ff10101c0 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c | |||
| @@ -5502,7 +5502,8 @@ static void try_7322_ipg(struct qib_pportdata *ppd) | |||
| 5502 | goto retry; | 5502 | goto retry; |
| 5503 | 5503 | ||
| 5504 | send_buf = ib_create_send_mad(agent, 0, 0, 0, IB_MGMT_MAD_HDR, | 5504 | send_buf = ib_create_send_mad(agent, 0, 0, 0, IB_MGMT_MAD_HDR, |
| 5505 | IB_MGMT_MAD_DATA, GFP_ATOMIC); | 5505 | IB_MGMT_MAD_DATA, GFP_ATOMIC, |
| 5506 | IB_MGMT_BASE_VERSION); | ||
| 5506 | if (IS_ERR(send_buf)) | 5507 | if (IS_ERR(send_buf)) |
| 5507 | goto retry; | 5508 | goto retry; |
| 5508 | 5509 | ||
diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c index 395f4046dba2..9625e7c438e5 100644 --- a/drivers/infiniband/hw/qib/qib_mad.c +++ b/drivers/infiniband/hw/qib/qib_mad.c | |||
| @@ -83,7 +83,8 @@ static void qib_send_trap(struct qib_ibport *ibp, void *data, unsigned len) | |||
| 83 | return; | 83 | return; |
| 84 | 84 | ||
| 85 | send_buf = ib_create_send_mad(agent, 0, 0, 0, IB_MGMT_MAD_HDR, | 85 | send_buf = ib_create_send_mad(agent, 0, 0, 0, IB_MGMT_MAD_HDR, |
| 86 | IB_MGMT_MAD_DATA, GFP_ATOMIC); | 86 | IB_MGMT_MAD_DATA, GFP_ATOMIC, |
| 87 | IB_MGMT_BASE_VERSION); | ||
| 87 | if (IS_ERR(send_buf)) | 88 | if (IS_ERR(send_buf)) |
| 88 | return; | 89 | return; |
| 89 | 90 | ||
| @@ -1854,7 +1855,7 @@ static int pma_set_portcounters_ext(struct ib_pma_mad *pmp, | |||
| 1854 | } | 1855 | } |
| 1855 | 1856 | ||
| 1856 | static int process_subn(struct ib_device *ibdev, int mad_flags, | 1857 | static int process_subn(struct ib_device *ibdev, int mad_flags, |
| 1857 | u8 port, struct ib_mad *in_mad, | 1858 | u8 port, const struct ib_mad *in_mad, |
| 1858 | struct ib_mad *out_mad) | 1859 | struct ib_mad *out_mad) |
| 1859 | { | 1860 | { |
| 1860 | struct ib_smp *smp = (struct ib_smp *)out_mad; | 1861 | struct ib_smp *smp = (struct ib_smp *)out_mad; |
| @@ -2006,7 +2007,7 @@ bail: | |||
| 2006 | } | 2007 | } |
| 2007 | 2008 | ||
| 2008 | static int process_perf(struct ib_device *ibdev, u8 port, | 2009 | static int process_perf(struct ib_device *ibdev, u8 port, |
| 2009 | struct ib_mad *in_mad, | 2010 | const struct ib_mad *in_mad, |
| 2010 | struct ib_mad *out_mad) | 2011 | struct ib_mad *out_mad) |
| 2011 | { | 2012 | { |
| 2012 | struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad; | 2013 | struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad; |
| @@ -2299,7 +2300,7 @@ static int check_cc_key(struct qib_ibport *ibp, | |||
| 2299 | } | 2300 | } |
| 2300 | 2301 | ||
| 2301 | static int process_cc(struct ib_device *ibdev, int mad_flags, | 2302 | static int process_cc(struct ib_device *ibdev, int mad_flags, |
| 2302 | u8 port, struct ib_mad *in_mad, | 2303 | u8 port, const struct ib_mad *in_mad, |
| 2303 | struct ib_mad *out_mad) | 2304 | struct ib_mad *out_mad) |
| 2304 | { | 2305 | { |
| 2305 | struct ib_cc_mad *ccp = (struct ib_cc_mad *)out_mad; | 2306 | struct ib_cc_mad *ccp = (struct ib_cc_mad *)out_mad; |
| @@ -2400,12 +2401,20 @@ bail: | |||
| 2400 | * This is called by the ib_mad module. | 2401 | * This is called by the ib_mad module. |
| 2401 | */ | 2402 | */ |
| 2402 | int qib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port, | 2403 | int qib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port, |
| 2403 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 2404 | const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 2404 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 2405 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 2406 | struct ib_mad_hdr *out, size_t *out_mad_size, | ||
| 2407 | u16 *out_mad_pkey_index) | ||
| 2405 | { | 2408 | { |
| 2406 | int ret; | 2409 | int ret; |
| 2407 | struct qib_ibport *ibp = to_iport(ibdev, port); | 2410 | struct qib_ibport *ibp = to_iport(ibdev, port); |
| 2408 | struct qib_pportdata *ppd = ppd_from_ibp(ibp); | 2411 | struct qib_pportdata *ppd = ppd_from_ibp(ibp); |
| 2412 | const struct ib_mad *in_mad = (const struct ib_mad *)in; | ||
| 2413 | struct ib_mad *out_mad = (struct ib_mad *)out; | ||
| 2414 | |||
| 2415 | if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || | ||
| 2416 | *out_mad_size != sizeof(*out_mad))) | ||
| 2417 | return IB_MAD_RESULT_FAILURE; | ||
| 2409 | 2418 | ||
| 2410 | switch (in_mad->mad_hdr.mgmt_class) { | 2419 | switch (in_mad->mad_hdr.mgmt_class) { |
| 2411 | case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: | 2420 | case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: |
diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c index 4a3599890ea5..a05d1a372208 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.c +++ b/drivers/infiniband/hw/qib/qib_verbs.c | |||
| @@ -1550,12 +1550,14 @@ full: | |||
| 1550 | } | 1550 | } |
| 1551 | } | 1551 | } |
| 1552 | 1552 | ||
| 1553 | static int qib_query_device(struct ib_device *ibdev, | 1553 | static int qib_query_device(struct ib_device *ibdev, struct ib_device_attr *props, |
| 1554 | struct ib_device_attr *props) | 1554 | struct ib_udata *uhw) |
| 1555 | { | 1555 | { |
| 1556 | struct qib_devdata *dd = dd_from_ibdev(ibdev); | 1556 | struct qib_devdata *dd = dd_from_ibdev(ibdev); |
| 1557 | struct qib_ibdev *dev = to_idev(ibdev); | 1557 | struct qib_ibdev *dev = to_idev(ibdev); |
| 1558 | 1558 | ||
| 1559 | if (uhw->inlen || uhw->outlen) | ||
| 1560 | return -EINVAL; | ||
| 1559 | memset(props, 0, sizeof(*props)); | 1561 | memset(props, 0, sizeof(*props)); |
| 1560 | 1562 | ||
| 1561 | props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR | | 1563 | props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR | |
| @@ -2040,6 +2042,24 @@ static void init_ibport(struct qib_pportdata *ppd) | |||
| 2040 | RCU_INIT_POINTER(ibp->qp1, NULL); | 2042 | RCU_INIT_POINTER(ibp->qp1, NULL); |
| 2041 | } | 2043 | } |
| 2042 | 2044 | ||
| 2045 | static int qib_port_immutable(struct ib_device *ibdev, u8 port_num, | ||
| 2046 | struct ib_port_immutable *immutable) | ||
| 2047 | { | ||
| 2048 | struct ib_port_attr attr; | ||
| 2049 | int err; | ||
| 2050 | |||
| 2051 | err = qib_query_port(ibdev, port_num, &attr); | ||
| 2052 | if (err) | ||
| 2053 | return err; | ||
| 2054 | |||
| 2055 | immutable->pkey_tbl_len = attr.pkey_tbl_len; | ||
| 2056 | immutable->gid_tbl_len = attr.gid_tbl_len; | ||
| 2057 | immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB; | ||
| 2058 | immutable->max_mad_size = IB_MGMT_MAD_SIZE; | ||
| 2059 | |||
| 2060 | return 0; | ||
| 2061 | } | ||
| 2062 | |||
| 2043 | /** | 2063 | /** |
| 2044 | * qib_register_ib_device - register our device with the infiniband core | 2064 | * qib_register_ib_device - register our device with the infiniband core |
| 2045 | * @dd: the device data structure | 2065 | * @dd: the device data structure |
| @@ -2227,6 +2247,7 @@ int qib_register_ib_device(struct qib_devdata *dd) | |||
| 2227 | ibdev->process_mad = qib_process_mad; | 2247 | ibdev->process_mad = qib_process_mad; |
| 2228 | ibdev->mmap = qib_mmap; | 2248 | ibdev->mmap = qib_mmap; |
| 2229 | ibdev->dma_ops = &qib_dma_mapping_ops; | 2249 | ibdev->dma_ops = &qib_dma_mapping_ops; |
| 2250 | ibdev->get_port_immutable = qib_port_immutable; | ||
| 2230 | 2251 | ||
| 2231 | snprintf(ibdev->node_desc, sizeof(ibdev->node_desc), | 2252 | snprintf(ibdev->node_desc, sizeof(ibdev->node_desc), |
| 2232 | "Intel Infiniband HCA %s", init_utsname()->nodename); | 2253 | "Intel Infiniband HCA %s", init_utsname()->nodename); |
diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h index bfc8948fdd35..1635572752ce 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.h +++ b/drivers/infiniband/hw/qib/qib_verbs.h | |||
| @@ -872,8 +872,10 @@ void qib_cap_mask_chg(struct qib_ibport *ibp); | |||
| 872 | void qib_sys_guid_chg(struct qib_ibport *ibp); | 872 | void qib_sys_guid_chg(struct qib_ibport *ibp); |
| 873 | void qib_node_desc_chg(struct qib_ibport *ibp); | 873 | void qib_node_desc_chg(struct qib_ibport *ibp); |
| 874 | int qib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | 874 | int qib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, |
| 875 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 875 | const struct ib_wc *in_wc, const struct ib_grh *in_grh, |
| 876 | struct ib_mad *in_mad, struct ib_mad *out_mad); | 876 | const struct ib_mad_hdr *in, size_t in_mad_size, |
| 877 | struct ib_mad_hdr *out, size_t *out_mad_size, | ||
| 878 | u16 *out_mad_pkey_index); | ||
| 877 | int qib_create_agents(struct qib_ibdev *dev); | 879 | int qib_create_agents(struct qib_ibdev *dev); |
| 878 | void qib_free_agents(struct qib_ibdev *dev); | 880 | void qib_free_agents(struct qib_ibdev *dev); |
| 879 | 881 | ||
| @@ -1007,8 +1009,9 @@ void qib_cq_enter(struct qib_cq *cq, struct ib_wc *entry, int sig); | |||
| 1007 | 1009 | ||
| 1008 | int qib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry); | 1010 | int qib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry); |
| 1009 | 1011 | ||
| 1010 | struct ib_cq *qib_create_cq(struct ib_device *ibdev, int entries, | 1012 | struct ib_cq *qib_create_cq(struct ib_device *ibdev, |
| 1011 | int comp_vector, struct ib_ucontext *context, | 1013 | const struct ib_cq_init_attr *attr, |
| 1014 | struct ib_ucontext *context, | ||
| 1012 | struct ib_udata *udata); | 1015 | struct ib_udata *udata); |
| 1013 | 1016 | ||
| 1014 | int qib_destroy_cq(struct ib_cq *ibcq); | 1017 | int qib_destroy_cq(struct ib_cq *ibcq); |
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_main.c b/drivers/infiniband/hw/usnic/usnic_ib_main.c index 0d0f98695d53..34c49b8105fe 100644 --- a/drivers/infiniband/hw/usnic/usnic_ib_main.c +++ b/drivers/infiniband/hw/usnic/usnic_ib_main.c | |||
| @@ -300,6 +300,22 @@ static struct notifier_block usnic_ib_inetaddr_notifier = { | |||
| 300 | }; | 300 | }; |
| 301 | /* End of inet section*/ | 301 | /* End of inet section*/ |
| 302 | 302 | ||
| 303 | static int usnic_port_immutable(struct ib_device *ibdev, u8 port_num, | ||
| 304 | struct ib_port_immutable *immutable) | ||
| 305 | { | ||
| 306 | struct ib_port_attr attr; | ||
| 307 | int err; | ||
| 308 | |||
| 309 | err = usnic_ib_query_port(ibdev, port_num, &attr); | ||
| 310 | if (err) | ||
| 311 | return err; | ||
| 312 | |||
| 313 | immutable->pkey_tbl_len = attr.pkey_tbl_len; | ||
| 314 | immutable->gid_tbl_len = attr.gid_tbl_len; | ||
| 315 | |||
| 316 | return 0; | ||
| 317 | } | ||
| 318 | |||
| 303 | /* Start of PF discovery section */ | 319 | /* Start of PF discovery section */ |
| 304 | static void *usnic_ib_device_add(struct pci_dev *dev) | 320 | static void *usnic_ib_device_add(struct pci_dev *dev) |
| 305 | { | 321 | { |
| @@ -383,6 +399,7 @@ static void *usnic_ib_device_add(struct pci_dev *dev) | |||
| 383 | us_ibdev->ib_dev.poll_cq = usnic_ib_poll_cq; | 399 | us_ibdev->ib_dev.poll_cq = usnic_ib_poll_cq; |
| 384 | us_ibdev->ib_dev.req_notify_cq = usnic_ib_req_notify_cq; | 400 | us_ibdev->ib_dev.req_notify_cq = usnic_ib_req_notify_cq; |
| 385 | us_ibdev->ib_dev.get_dma_mr = usnic_ib_get_dma_mr; | 401 | us_ibdev->ib_dev.get_dma_mr = usnic_ib_get_dma_mr; |
| 402 | us_ibdev->ib_dev.get_port_immutable = usnic_port_immutable; | ||
| 386 | 403 | ||
| 387 | 404 | ||
| 388 | if (ib_register_device(&us_ibdev->ib_dev, NULL)) | 405 | if (ib_register_device(&us_ibdev->ib_dev, NULL)) |
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c index 53bd6a2d9cdb..7df43827cb29 100644 --- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c +++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c | |||
| @@ -248,7 +248,8 @@ enum rdma_link_layer usnic_ib_port_link_layer(struct ib_device *device, | |||
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | int usnic_ib_query_device(struct ib_device *ibdev, | 250 | int usnic_ib_query_device(struct ib_device *ibdev, |
| 251 | struct ib_device_attr *props) | 251 | struct ib_device_attr *props, |
| 252 | struct ib_udata *uhw) | ||
| 252 | { | 253 | { |
| 253 | struct usnic_ib_dev *us_ibdev = to_usdev(ibdev); | 254 | struct usnic_ib_dev *us_ibdev = to_usdev(ibdev); |
| 254 | union ib_gid gid; | 255 | union ib_gid gid; |
| @@ -257,6 +258,9 @@ int usnic_ib_query_device(struct ib_device *ibdev, | |||
| 257 | int qp_per_vf; | 258 | int qp_per_vf; |
| 258 | 259 | ||
| 259 | usnic_dbg("\n"); | 260 | usnic_dbg("\n"); |
| 261 | if (uhw->inlen || uhw->outlen) | ||
| 262 | return -EINVAL; | ||
| 263 | |||
| 260 | mutex_lock(&us_ibdev->usdev_lock); | 264 | mutex_lock(&us_ibdev->usdev_lock); |
| 261 | us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info); | 265 | us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info); |
| 262 | us_ibdev->netdev->ethtool_ops->get_settings(us_ibdev->netdev, &cmd); | 266 | us_ibdev->netdev->ethtool_ops->get_settings(us_ibdev->netdev, &cmd); |
| @@ -570,13 +574,17 @@ int usnic_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
| 570 | return status; | 574 | return status; |
| 571 | } | 575 | } |
| 572 | 576 | ||
| 573 | struct ib_cq *usnic_ib_create_cq(struct ib_device *ibdev, int entries, | 577 | struct ib_cq *usnic_ib_create_cq(struct ib_device *ibdev, |
| 574 | int vector, struct ib_ucontext *context, | 578 | const struct ib_cq_init_attr *attr, |
| 575 | struct ib_udata *udata) | 579 | struct ib_ucontext *context, |
| 580 | struct ib_udata *udata) | ||
| 576 | { | 581 | { |
| 577 | struct ib_cq *cq; | 582 | struct ib_cq *cq; |
| 578 | 583 | ||
| 579 | usnic_dbg("\n"); | 584 | usnic_dbg("\n"); |
| 585 | if (attr->flags) | ||
| 586 | return ERR_PTR(-EINVAL); | ||
| 587 | |||
| 580 | cq = kzalloc(sizeof(*cq), GFP_KERNEL); | 588 | cq = kzalloc(sizeof(*cq), GFP_KERNEL); |
| 581 | if (!cq) | 589 | if (!cq) |
| 582 | return ERR_PTR(-EBUSY); | 590 | return ERR_PTR(-EBUSY); |
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h index bb864f5aed70..0bd04efa16f3 100644 --- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h +++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h | |||
| @@ -24,9 +24,12 @@ | |||
| 24 | enum rdma_link_layer usnic_ib_port_link_layer(struct ib_device *device, | 24 | enum rdma_link_layer usnic_ib_port_link_layer(struct ib_device *device, |
| 25 | u8 port_num); | 25 | u8 port_num); |
| 26 | int usnic_ib_query_device(struct ib_device *ibdev, | 26 | int usnic_ib_query_device(struct ib_device *ibdev, |
| 27 | struct ib_device_attr *props); | 27 | struct ib_device_attr *props, |
| 28 | struct ib_udata *uhw); | ||
| 28 | int usnic_ib_query_port(struct ib_device *ibdev, u8 port, | 29 | int usnic_ib_query_port(struct ib_device *ibdev, u8 port, |
| 29 | struct ib_port_attr *props); | 30 | struct ib_port_attr *props); |
| 31 | enum rdma_protocol_type | ||
| 32 | usnic_ib_query_protocol(struct ib_device *device, u8 port_num); | ||
| 30 | int usnic_ib_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr, | 33 | int usnic_ib_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr, |
| 31 | int qp_attr_mask, | 34 | int qp_attr_mask, |
| 32 | struct ib_qp_init_attr *qp_init_attr); | 35 | struct ib_qp_init_attr *qp_init_attr); |
| @@ -44,9 +47,10 @@ struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd, | |||
| 44 | int usnic_ib_destroy_qp(struct ib_qp *qp); | 47 | int usnic_ib_destroy_qp(struct ib_qp *qp); |
| 45 | int usnic_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | 48 | int usnic_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, |
| 46 | int attr_mask, struct ib_udata *udata); | 49 | int attr_mask, struct ib_udata *udata); |
| 47 | struct ib_cq *usnic_ib_create_cq(struct ib_device *ibdev, int entries, | 50 | struct ib_cq *usnic_ib_create_cq(struct ib_device *ibdev, |
| 48 | int vector, struct ib_ucontext *context, | 51 | const struct ib_cq_init_attr *attr, |
| 49 | struct ib_udata *udata); | 52 | struct ib_ucontext *context, |
| 53 | struct ib_udata *udata); | ||
| 50 | int usnic_ib_destroy_cq(struct ib_cq *cq); | 54 | int usnic_ib_destroy_cq(struct ib_cq *cq); |
| 51 | struct ib_mr *usnic_ib_reg_mr(struct ib_pd *pd, u64 start, u64 length, | 55 | struct ib_mr *usnic_ib_reg_mr(struct ib_pd *pd, u64 start, u64 length, |
| 52 | u64 virt_addr, int access_flags, | 56 | u64 virt_addr, int access_flags, |
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom.c b/drivers/infiniband/hw/usnic/usnic_uiom.c index 417de1f32960..cb2337f0532b 100644 --- a/drivers/infiniband/hw/usnic/usnic_uiom.c +++ b/drivers/infiniband/hw/usnic/usnic_uiom.c | |||
| @@ -472,11 +472,10 @@ struct usnic_uiom_pd *usnic_uiom_alloc_pd(void) | |||
| 472 | return ERR_PTR(-ENOMEM); | 472 | return ERR_PTR(-ENOMEM); |
| 473 | 473 | ||
| 474 | pd->domain = domain = iommu_domain_alloc(&pci_bus_type); | 474 | pd->domain = domain = iommu_domain_alloc(&pci_bus_type); |
| 475 | if (IS_ERR_OR_NULL(domain)) { | 475 | if (!domain) { |
| 476 | usnic_err("Failed to allocate IOMMU domain with err %ld\n", | 476 | usnic_err("Failed to allocate IOMMU domain"); |
| 477 | PTR_ERR(pd->domain)); | ||
| 478 | kfree(pd); | 477 | kfree(pd); |
| 479 | return ERR_PTR(domain ? PTR_ERR(domain) : -ENOMEM); | 478 | return ERR_PTR(-ENOMEM); |
| 480 | } | 479 | } |
| 481 | 480 | ||
| 482 | iommu_set_fault_handler(pd->domain, usnic_uiom_dma_fault, NULL); | 481 | iommu_set_fault_handler(pd->domain, usnic_uiom_dma_fault, NULL); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index bd94b0a6e9e5..79859c4d43c9 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
| @@ -239,7 +239,7 @@ struct ipoib_cm_tx { | |||
| 239 | struct net_device *dev; | 239 | struct net_device *dev; |
| 240 | struct ipoib_neigh *neigh; | 240 | struct ipoib_neigh *neigh; |
| 241 | struct ipoib_path *path; | 241 | struct ipoib_path *path; |
| 242 | struct ipoib_cm_tx_buf *tx_ring; | 242 | struct ipoib_tx_buf *tx_ring; |
| 243 | unsigned tx_head; | 243 | unsigned tx_head; |
| 244 | unsigned tx_tail; | 244 | unsigned tx_tail; |
| 245 | unsigned long flags; | 245 | unsigned long flags; |
| @@ -504,6 +504,33 @@ int ipoib_mcast_stop_thread(struct net_device *dev); | |||
| 504 | void ipoib_mcast_dev_down(struct net_device *dev); | 504 | void ipoib_mcast_dev_down(struct net_device *dev); |
| 505 | void ipoib_mcast_dev_flush(struct net_device *dev); | 505 | void ipoib_mcast_dev_flush(struct net_device *dev); |
| 506 | 506 | ||
| 507 | int ipoib_dma_map_tx(struct ib_device *ca, struct ipoib_tx_buf *tx_req); | ||
| 508 | void ipoib_dma_unmap_tx(struct ipoib_dev_priv *priv, | ||
| 509 | struct ipoib_tx_buf *tx_req); | ||
| 510 | |||
| 511 | static inline void ipoib_build_sge(struct ipoib_dev_priv *priv, | ||
| 512 | struct ipoib_tx_buf *tx_req) | ||
| 513 | { | ||
| 514 | int i, off; | ||
| 515 | struct sk_buff *skb = tx_req->skb; | ||
| 516 | skb_frag_t *frags = skb_shinfo(skb)->frags; | ||
| 517 | int nr_frags = skb_shinfo(skb)->nr_frags; | ||
| 518 | u64 *mapping = tx_req->mapping; | ||
| 519 | |||
| 520 | if (skb_headlen(skb)) { | ||
| 521 | priv->tx_sge[0].addr = mapping[0]; | ||
| 522 | priv->tx_sge[0].length = skb_headlen(skb); | ||
| 523 | off = 1; | ||
| 524 | } else | ||
| 525 | off = 0; | ||
| 526 | |||
| 527 | for (i = 0; i < nr_frags; ++i) { | ||
| 528 | priv->tx_sge[i + off].addr = mapping[i + off]; | ||
| 529 | priv->tx_sge[i + off].length = skb_frag_size(&frags[i]); | ||
| 530 | } | ||
| 531 | priv->tx_wr.num_sge = nr_frags + off; | ||
| 532 | } | ||
| 533 | |||
| 507 | #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG | 534 | #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG |
| 508 | struct ipoib_mcast_iter *ipoib_mcast_iter_init(struct net_device *dev); | 535 | struct ipoib_mcast_iter *ipoib_mcast_iter_init(struct net_device *dev); |
| 509 | int ipoib_mcast_iter_next(struct ipoib_mcast_iter *iter); | 536 | int ipoib_mcast_iter_next(struct ipoib_mcast_iter *iter); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index cf32a778e7d0..ee39be6ccfb0 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c | |||
| @@ -694,14 +694,12 @@ repost: | |||
| 694 | static inline int post_send(struct ipoib_dev_priv *priv, | 694 | static inline int post_send(struct ipoib_dev_priv *priv, |
| 695 | struct ipoib_cm_tx *tx, | 695 | struct ipoib_cm_tx *tx, |
| 696 | unsigned int wr_id, | 696 | unsigned int wr_id, |
| 697 | u64 addr, int len) | 697 | struct ipoib_tx_buf *tx_req) |
| 698 | { | 698 | { |
| 699 | struct ib_send_wr *bad_wr; | 699 | struct ib_send_wr *bad_wr; |
| 700 | 700 | ||
| 701 | priv->tx_sge[0].addr = addr; | 701 | ipoib_build_sge(priv, tx_req); |
| 702 | priv->tx_sge[0].length = len; | ||
| 703 | 702 | ||
| 704 | priv->tx_wr.num_sge = 1; | ||
| 705 | priv->tx_wr.wr_id = wr_id | IPOIB_OP_CM; | 703 | priv->tx_wr.wr_id = wr_id | IPOIB_OP_CM; |
| 706 | 704 | ||
| 707 | return ib_post_send(tx->qp, &priv->tx_wr, &bad_wr); | 705 | return ib_post_send(tx->qp, &priv->tx_wr, &bad_wr); |
| @@ -710,8 +708,7 @@ static inline int post_send(struct ipoib_dev_priv *priv, | |||
| 710 | void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_tx *tx) | 708 | void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_tx *tx) |
| 711 | { | 709 | { |
| 712 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 710 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 713 | struct ipoib_cm_tx_buf *tx_req; | 711 | struct ipoib_tx_buf *tx_req; |
| 714 | u64 addr; | ||
| 715 | int rc; | 712 | int rc; |
| 716 | 713 | ||
| 717 | if (unlikely(skb->len > tx->mtu)) { | 714 | if (unlikely(skb->len > tx->mtu)) { |
| @@ -735,24 +732,21 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ | |||
| 735 | */ | 732 | */ |
| 736 | tx_req = &tx->tx_ring[tx->tx_head & (ipoib_sendq_size - 1)]; | 733 | tx_req = &tx->tx_ring[tx->tx_head & (ipoib_sendq_size - 1)]; |
| 737 | tx_req->skb = skb; | 734 | tx_req->skb = skb; |
| 738 | addr = ib_dma_map_single(priv->ca, skb->data, skb->len, DMA_TO_DEVICE); | 735 | |
| 739 | if (unlikely(ib_dma_mapping_error(priv->ca, addr))) { | 736 | if (unlikely(ipoib_dma_map_tx(priv->ca, tx_req))) { |
| 740 | ++dev->stats.tx_errors; | 737 | ++dev->stats.tx_errors; |
| 741 | dev_kfree_skb_any(skb); | 738 | dev_kfree_skb_any(skb); |
| 742 | return; | 739 | return; |
| 743 | } | 740 | } |
| 744 | 741 | ||
| 745 | tx_req->mapping = addr; | ||
| 746 | |||
| 747 | skb_orphan(skb); | 742 | skb_orphan(skb); |
| 748 | skb_dst_drop(skb); | 743 | skb_dst_drop(skb); |
| 749 | 744 | ||
| 750 | rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1), | 745 | rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1), tx_req); |
| 751 | addr, skb->len); | ||
| 752 | if (unlikely(rc)) { | 746 | if (unlikely(rc)) { |
| 753 | ipoib_warn(priv, "post_send failed, error %d\n", rc); | 747 | ipoib_warn(priv, "post_send failed, error %d\n", rc); |
| 754 | ++dev->stats.tx_errors; | 748 | ++dev->stats.tx_errors; |
| 755 | ib_dma_unmap_single(priv->ca, addr, skb->len, DMA_TO_DEVICE); | 749 | ipoib_dma_unmap_tx(priv, tx_req); |
| 756 | dev_kfree_skb_any(skb); | 750 | dev_kfree_skb_any(skb); |
| 757 | } else { | 751 | } else { |
| 758 | dev->trans_start = jiffies; | 752 | dev->trans_start = jiffies; |
| @@ -777,7 +771,7 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) | |||
| 777 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 771 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 778 | struct ipoib_cm_tx *tx = wc->qp->qp_context; | 772 | struct ipoib_cm_tx *tx = wc->qp->qp_context; |
| 779 | unsigned int wr_id = wc->wr_id & ~IPOIB_OP_CM; | 773 | unsigned int wr_id = wc->wr_id & ~IPOIB_OP_CM; |
| 780 | struct ipoib_cm_tx_buf *tx_req; | 774 | struct ipoib_tx_buf *tx_req; |
| 781 | unsigned long flags; | 775 | unsigned long flags; |
| 782 | 776 | ||
| 783 | ipoib_dbg_data(priv, "cm send completion: id %d, status: %d\n", | 777 | ipoib_dbg_data(priv, "cm send completion: id %d, status: %d\n", |
| @@ -791,7 +785,7 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) | |||
| 791 | 785 | ||
| 792 | tx_req = &tx->tx_ring[wr_id]; | 786 | tx_req = &tx->tx_ring[wr_id]; |
| 793 | 787 | ||
| 794 | ib_dma_unmap_single(priv->ca, tx_req->mapping, tx_req->skb->len, DMA_TO_DEVICE); | 788 | ipoib_dma_unmap_tx(priv, tx_req); |
| 795 | 789 | ||
| 796 | /* FIXME: is this right? Shouldn't we only increment on success? */ | 790 | /* FIXME: is this right? Shouldn't we only increment on success? */ |
| 797 | ++dev->stats.tx_packets; | 791 | ++dev->stats.tx_packets; |
| @@ -1036,6 +1030,9 @@ static struct ib_qp *ipoib_cm_create_tx_qp(struct net_device *dev, struct ipoib_ | |||
| 1036 | 1030 | ||
| 1037 | struct ib_qp *tx_qp; | 1031 | struct ib_qp *tx_qp; |
| 1038 | 1032 | ||
| 1033 | if (dev->features & NETIF_F_SG) | ||
| 1034 | attr.cap.max_send_sge = MAX_SKB_FRAGS + 1; | ||
| 1035 | |||
| 1039 | tx_qp = ib_create_qp(priv->pd, &attr); | 1036 | tx_qp = ib_create_qp(priv->pd, &attr); |
| 1040 | if (PTR_ERR(tx_qp) == -EINVAL) { | 1037 | if (PTR_ERR(tx_qp) == -EINVAL) { |
| 1041 | ipoib_warn(priv, "can't use GFP_NOIO for QPs on device %s, using GFP_KERNEL\n", | 1038 | ipoib_warn(priv, "can't use GFP_NOIO for QPs on device %s, using GFP_KERNEL\n", |
| @@ -1170,7 +1167,7 @@ err_tx: | |||
| 1170 | static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p) | 1167 | static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p) |
| 1171 | { | 1168 | { |
| 1172 | struct ipoib_dev_priv *priv = netdev_priv(p->dev); | 1169 | struct ipoib_dev_priv *priv = netdev_priv(p->dev); |
| 1173 | struct ipoib_cm_tx_buf *tx_req; | 1170 | struct ipoib_tx_buf *tx_req; |
| 1174 | unsigned long begin; | 1171 | unsigned long begin; |
| 1175 | 1172 | ||
| 1176 | ipoib_dbg(priv, "Destroy active connection 0x%x head 0x%x tail 0x%x\n", | 1173 | ipoib_dbg(priv, "Destroy active connection 0x%x head 0x%x tail 0x%x\n", |
| @@ -1197,8 +1194,7 @@ timeout: | |||
| 1197 | 1194 | ||
| 1198 | while ((int) p->tx_tail - (int) p->tx_head < 0) { | 1195 | while ((int) p->tx_tail - (int) p->tx_head < 0) { |
| 1199 | tx_req = &p->tx_ring[p->tx_tail & (ipoib_sendq_size - 1)]; | 1196 | tx_req = &p->tx_ring[p->tx_tail & (ipoib_sendq_size - 1)]; |
| 1200 | ib_dma_unmap_single(priv->ca, tx_req->mapping, tx_req->skb->len, | 1197 | ipoib_dma_unmap_tx(priv, tx_req); |
| 1201 | DMA_TO_DEVICE); | ||
| 1202 | dev_kfree_skb_any(tx_req->skb); | 1198 | dev_kfree_skb_any(tx_req->skb); |
| 1203 | ++p->tx_tail; | 1199 | ++p->tx_tail; |
| 1204 | netif_tx_lock_bh(p->dev); | 1200 | netif_tx_lock_bh(p->dev); |
| @@ -1455,7 +1451,6 @@ static void ipoib_cm_stale_task(struct work_struct *work) | |||
| 1455 | spin_unlock_irq(&priv->lock); | 1451 | spin_unlock_irq(&priv->lock); |
| 1456 | } | 1452 | } |
| 1457 | 1453 | ||
| 1458 | |||
| 1459 | static ssize_t show_mode(struct device *d, struct device_attribute *attr, | 1454 | static ssize_t show_mode(struct device *d, struct device_attribute *attr, |
| 1460 | char *buf) | 1455 | char *buf) |
| 1461 | { | 1456 | { |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 63b92cbb29ad..d266667ca9b8 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
| @@ -263,8 +263,7 @@ repost: | |||
| 263 | "for buf %d\n", wr_id); | 263 | "for buf %d\n", wr_id); |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | static int ipoib_dma_map_tx(struct ib_device *ca, | 266 | int ipoib_dma_map_tx(struct ib_device *ca, struct ipoib_tx_buf *tx_req) |
| 267 | struct ipoib_tx_buf *tx_req) | ||
| 268 | { | 267 | { |
| 269 | struct sk_buff *skb = tx_req->skb; | 268 | struct sk_buff *skb = tx_req->skb; |
| 270 | u64 *mapping = tx_req->mapping; | 269 | u64 *mapping = tx_req->mapping; |
| @@ -305,8 +304,8 @@ partial_error: | |||
| 305 | return -EIO; | 304 | return -EIO; |
| 306 | } | 305 | } |
| 307 | 306 | ||
| 308 | static void ipoib_dma_unmap_tx(struct ib_device *ca, | 307 | void ipoib_dma_unmap_tx(struct ipoib_dev_priv *priv, |
| 309 | struct ipoib_tx_buf *tx_req) | 308 | struct ipoib_tx_buf *tx_req) |
| 310 | { | 309 | { |
| 311 | struct sk_buff *skb = tx_req->skb; | 310 | struct sk_buff *skb = tx_req->skb; |
| 312 | u64 *mapping = tx_req->mapping; | 311 | u64 *mapping = tx_req->mapping; |
| @@ -314,7 +313,8 @@ static void ipoib_dma_unmap_tx(struct ib_device *ca, | |||
| 314 | int off; | 313 | int off; |
| 315 | 314 | ||
| 316 | if (skb_headlen(skb)) { | 315 | if (skb_headlen(skb)) { |
| 317 | ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE); | 316 | ib_dma_unmap_single(priv->ca, mapping[0], skb_headlen(skb), |
| 317 | DMA_TO_DEVICE); | ||
| 318 | off = 1; | 318 | off = 1; |
| 319 | } else | 319 | } else |
| 320 | off = 0; | 320 | off = 0; |
| @@ -322,8 +322,8 @@ static void ipoib_dma_unmap_tx(struct ib_device *ca, | |||
| 322 | for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) { | 322 | for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) { |
| 323 | const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | 323 | const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; |
| 324 | 324 | ||
| 325 | ib_dma_unmap_page(ca, mapping[i + off], skb_frag_size(frag), | 325 | ib_dma_unmap_page(priv->ca, mapping[i + off], |
| 326 | DMA_TO_DEVICE); | 326 | skb_frag_size(frag), DMA_TO_DEVICE); |
| 327 | } | 327 | } |
| 328 | } | 328 | } |
| 329 | 329 | ||
| @@ -389,7 +389,7 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) | |||
| 389 | 389 | ||
| 390 | tx_req = &priv->tx_ring[wr_id]; | 390 | tx_req = &priv->tx_ring[wr_id]; |
| 391 | 391 | ||
| 392 | ipoib_dma_unmap_tx(priv->ca, tx_req); | 392 | ipoib_dma_unmap_tx(priv, tx_req); |
| 393 | 393 | ||
| 394 | ++dev->stats.tx_packets; | 394 | ++dev->stats.tx_packets; |
| 395 | dev->stats.tx_bytes += tx_req->skb->len; | 395 | dev->stats.tx_bytes += tx_req->skb->len; |
| @@ -514,24 +514,10 @@ static inline int post_send(struct ipoib_dev_priv *priv, | |||
| 514 | void *head, int hlen) | 514 | void *head, int hlen) |
| 515 | { | 515 | { |
| 516 | struct ib_send_wr *bad_wr; | 516 | struct ib_send_wr *bad_wr; |
| 517 | int i, off; | ||
| 518 | struct sk_buff *skb = tx_req->skb; | 517 | struct sk_buff *skb = tx_req->skb; |
| 519 | skb_frag_t *frags = skb_shinfo(skb)->frags; | ||
| 520 | int nr_frags = skb_shinfo(skb)->nr_frags; | ||
| 521 | u64 *mapping = tx_req->mapping; | ||
| 522 | 518 | ||
| 523 | if (skb_headlen(skb)) { | 519 | ipoib_build_sge(priv, tx_req); |
| 524 | priv->tx_sge[0].addr = mapping[0]; | ||
| 525 | priv->tx_sge[0].length = skb_headlen(skb); | ||
| 526 | off = 1; | ||
| 527 | } else | ||
| 528 | off = 0; | ||
| 529 | 520 | ||
| 530 | for (i = 0; i < nr_frags; ++i) { | ||
| 531 | priv->tx_sge[i + off].addr = mapping[i + off]; | ||
| 532 | priv->tx_sge[i + off].length = skb_frag_size(&frags[i]); | ||
| 533 | } | ||
| 534 | priv->tx_wr.num_sge = nr_frags + off; | ||
| 535 | priv->tx_wr.wr_id = wr_id; | 521 | priv->tx_wr.wr_id = wr_id; |
| 536 | priv->tx_wr.wr.ud.remote_qpn = qpn; | 522 | priv->tx_wr.wr.ud.remote_qpn = qpn; |
| 537 | priv->tx_wr.wr.ud.ah = address; | 523 | priv->tx_wr.wr.ud.ah = address; |
| @@ -617,7 +603,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, | |||
| 617 | ipoib_warn(priv, "post_send failed, error %d\n", rc); | 603 | ipoib_warn(priv, "post_send failed, error %d\n", rc); |
| 618 | ++dev->stats.tx_errors; | 604 | ++dev->stats.tx_errors; |
| 619 | --priv->tx_outstanding; | 605 | --priv->tx_outstanding; |
| 620 | ipoib_dma_unmap_tx(priv->ca, tx_req); | 606 | ipoib_dma_unmap_tx(priv, tx_req); |
| 621 | dev_kfree_skb_any(skb); | 607 | dev_kfree_skb_any(skb); |
| 622 | if (netif_queue_stopped(dev)) | 608 | if (netif_queue_stopped(dev)) |
| 623 | netif_wake_queue(dev); | 609 | netif_wake_queue(dev); |
| @@ -868,7 +854,7 @@ int ipoib_ib_dev_stop(struct net_device *dev) | |||
| 868 | while ((int) priv->tx_tail - (int) priv->tx_head < 0) { | 854 | while ((int) priv->tx_tail - (int) priv->tx_head < 0) { |
| 869 | tx_req = &priv->tx_ring[priv->tx_tail & | 855 | tx_req = &priv->tx_ring[priv->tx_tail & |
| 870 | (ipoib_sendq_size - 1)]; | 856 | (ipoib_sendq_size - 1)]; |
| 871 | ipoib_dma_unmap_tx(priv->ca, tx_req); | 857 | ipoib_dma_unmap_tx(priv, tx_req); |
| 872 | dev_kfree_skb_any(tx_req->skb); | 858 | dev_kfree_skb_any(tx_req->skb); |
| 873 | ++priv->tx_tail; | 859 | ++priv->tx_tail; |
| 874 | --priv->tx_outstanding; | 860 | --priv->tx_outstanding; |
| @@ -985,20 +971,21 @@ static inline int update_child_pkey(struct ipoib_dev_priv *priv) | |||
| 985 | } | 971 | } |
| 986 | 972 | ||
| 987 | static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, | 973 | static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, |
| 988 | enum ipoib_flush_level level) | 974 | enum ipoib_flush_level level, |
| 975 | int nesting) | ||
| 989 | { | 976 | { |
| 990 | struct ipoib_dev_priv *cpriv; | 977 | struct ipoib_dev_priv *cpriv; |
| 991 | struct net_device *dev = priv->dev; | 978 | struct net_device *dev = priv->dev; |
| 992 | int result; | 979 | int result; |
| 993 | 980 | ||
| 994 | down_read(&priv->vlan_rwsem); | 981 | down_read_nested(&priv->vlan_rwsem, nesting); |
| 995 | 982 | ||
| 996 | /* | 983 | /* |
| 997 | * Flush any child interfaces too -- they might be up even if | 984 | * Flush any child interfaces too -- they might be up even if |
| 998 | * the parent is down. | 985 | * the parent is down. |
| 999 | */ | 986 | */ |
| 1000 | list_for_each_entry(cpriv, &priv->child_intfs, list) | 987 | list_for_each_entry(cpriv, &priv->child_intfs, list) |
| 1001 | __ipoib_ib_dev_flush(cpriv, level); | 988 | __ipoib_ib_dev_flush(cpriv, level, nesting + 1); |
| 1002 | 989 | ||
| 1003 | up_read(&priv->vlan_rwsem); | 990 | up_read(&priv->vlan_rwsem); |
| 1004 | 991 | ||
| @@ -1076,7 +1063,7 @@ void ipoib_ib_dev_flush_light(struct work_struct *work) | |||
| 1076 | struct ipoib_dev_priv *priv = | 1063 | struct ipoib_dev_priv *priv = |
| 1077 | container_of(work, struct ipoib_dev_priv, flush_light); | 1064 | container_of(work, struct ipoib_dev_priv, flush_light); |
| 1078 | 1065 | ||
| 1079 | __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_LIGHT); | 1066 | __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_LIGHT, 0); |
| 1080 | } | 1067 | } |
| 1081 | 1068 | ||
| 1082 | void ipoib_ib_dev_flush_normal(struct work_struct *work) | 1069 | void ipoib_ib_dev_flush_normal(struct work_struct *work) |
| @@ -1084,7 +1071,7 @@ void ipoib_ib_dev_flush_normal(struct work_struct *work) | |||
| 1084 | struct ipoib_dev_priv *priv = | 1071 | struct ipoib_dev_priv *priv = |
| 1085 | container_of(work, struct ipoib_dev_priv, flush_normal); | 1072 | container_of(work, struct ipoib_dev_priv, flush_normal); |
| 1086 | 1073 | ||
| 1087 | __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_NORMAL); | 1074 | __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_NORMAL, 0); |
| 1088 | } | 1075 | } |
| 1089 | 1076 | ||
| 1090 | void ipoib_ib_dev_flush_heavy(struct work_struct *work) | 1077 | void ipoib_ib_dev_flush_heavy(struct work_struct *work) |
| @@ -1092,7 +1079,7 @@ void ipoib_ib_dev_flush_heavy(struct work_struct *work) | |||
| 1092 | struct ipoib_dev_priv *priv = | 1079 | struct ipoib_dev_priv *priv = |
| 1093 | container_of(work, struct ipoib_dev_priv, flush_heavy); | 1080 | container_of(work, struct ipoib_dev_priv, flush_heavy); |
| 1094 | 1081 | ||
| 1095 | __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_HEAVY); | 1082 | __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_HEAVY, 0); |
| 1096 | } | 1083 | } |
| 1097 | 1084 | ||
| 1098 | void ipoib_ib_dev_cleanup(struct net_device *dev) | 1085 | void ipoib_ib_dev_cleanup(struct net_device *dev) |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 9e1b203d756d..b2943c84a5dd 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
| @@ -190,7 +190,7 @@ static netdev_features_t ipoib_fix_features(struct net_device *dev, netdev_featu | |||
| 190 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 190 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 191 | 191 | ||
| 192 | if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags)) | 192 | if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags)) |
| 193 | features &= ~(NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); | 193 | features &= ~(NETIF_F_IP_CSUM | NETIF_F_TSO); |
| 194 | 194 | ||
| 195 | return features; | 195 | return features; |
| 196 | } | 196 | } |
| @@ -232,6 +232,7 @@ int ipoib_set_mode(struct net_device *dev, const char *buf) | |||
| 232 | ipoib_warn(priv, "enabling connected mode " | 232 | ipoib_warn(priv, "enabling connected mode " |
| 233 | "will cause multicast packet drops\n"); | 233 | "will cause multicast packet drops\n"); |
| 234 | netdev_update_features(dev); | 234 | netdev_update_features(dev); |
| 235 | dev_set_mtu(dev, ipoib_cm_max_mtu(dev)); | ||
| 235 | rtnl_unlock(); | 236 | rtnl_unlock(); |
| 236 | priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; | 237 | priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; |
| 237 | 238 | ||
| @@ -1128,7 +1129,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv) | |||
| 1128 | { | 1129 | { |
| 1129 | struct ipoib_neigh_table *ntbl = &priv->ntbl; | 1130 | struct ipoib_neigh_table *ntbl = &priv->ntbl; |
| 1130 | struct ipoib_neigh_hash *htbl; | 1131 | struct ipoib_neigh_hash *htbl; |
| 1131 | struct ipoib_neigh **buckets; | 1132 | struct ipoib_neigh __rcu **buckets; |
| 1132 | u32 size; | 1133 | u32 size; |
| 1133 | 1134 | ||
| 1134 | clear_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags); | 1135 | clear_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags); |
| @@ -1146,7 +1147,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv) | |||
| 1146 | htbl->size = size; | 1147 | htbl->size = size; |
| 1147 | htbl->mask = (size - 1); | 1148 | htbl->mask = (size - 1); |
| 1148 | htbl->buckets = buckets; | 1149 | htbl->buckets = buckets; |
| 1149 | ntbl->htbl = htbl; | 1150 | RCU_INIT_POINTER(ntbl->htbl, htbl); |
| 1150 | htbl->ntbl = ntbl; | 1151 | htbl->ntbl = ntbl; |
| 1151 | atomic_set(&ntbl->entries, 0); | 1152 | atomic_set(&ntbl->entries, 0); |
| 1152 | 1153 | ||
| @@ -1577,7 +1578,8 @@ static struct net_device *ipoib_add_port(const char *format, | |||
| 1577 | SET_NETDEV_DEV(priv->dev, hca->dma_device); | 1578 | SET_NETDEV_DEV(priv->dev, hca->dma_device); |
| 1578 | priv->dev->dev_id = port - 1; | 1579 | priv->dev->dev_id = port - 1; |
| 1579 | 1580 | ||
| 1580 | if (!ib_query_port(hca, port, &attr)) | 1581 | result = ib_query_port(hca, port, &attr); |
| 1582 | if (!result) | ||
| 1581 | priv->max_ib_mtu = ib_mtu_enum_to_int(attr.max_mtu); | 1583 | priv->max_ib_mtu = ib_mtu_enum_to_int(attr.max_mtu); |
| 1582 | else { | 1584 | else { |
| 1583 | printk(KERN_WARNING "%s: ib_query_port %d failed\n", | 1585 | printk(KERN_WARNING "%s: ib_query_port %d failed\n", |
| @@ -1598,7 +1600,8 @@ static struct net_device *ipoib_add_port(const char *format, | |||
| 1598 | goto device_init_failed; | 1600 | goto device_init_failed; |
| 1599 | } | 1601 | } |
| 1600 | 1602 | ||
| 1601 | if (ipoib_set_dev_features(priv, hca)) | 1603 | result = ipoib_set_dev_features(priv, hca); |
| 1604 | if (result) | ||
| 1602 | goto device_init_failed; | 1605 | goto device_init_failed; |
| 1603 | 1606 | ||
| 1604 | /* | 1607 | /* |
| @@ -1684,10 +1687,8 @@ static void ipoib_add_one(struct ib_device *device) | |||
| 1684 | struct list_head *dev_list; | 1687 | struct list_head *dev_list; |
| 1685 | struct net_device *dev; | 1688 | struct net_device *dev; |
| 1686 | struct ipoib_dev_priv *priv; | 1689 | struct ipoib_dev_priv *priv; |
| 1687 | int s, e, p; | 1690 | int p; |
| 1688 | 1691 | int count = 0; | |
| 1689 | if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) | ||
| 1690 | return; | ||
| 1691 | 1692 | ||
| 1692 | dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); | 1693 | dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); |
| 1693 | if (!dev_list) | 1694 | if (!dev_list) |
| @@ -1695,24 +1696,22 @@ static void ipoib_add_one(struct ib_device *device) | |||
| 1695 | 1696 | ||
| 1696 | INIT_LIST_HEAD(dev_list); | 1697 | INIT_LIST_HEAD(dev_list); |
| 1697 | 1698 | ||
| 1698 | if (device->node_type == RDMA_NODE_IB_SWITCH) { | 1699 | for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) { |
| 1699 | s = 0; | 1700 | if (!rdma_protocol_ib(device, p)) |
| 1700 | e = 0; | ||
| 1701 | } else { | ||
| 1702 | s = 1; | ||
| 1703 | e = device->phys_port_cnt; | ||
| 1704 | } | ||
| 1705 | |||
| 1706 | for (p = s; p <= e; ++p) { | ||
| 1707 | if (rdma_port_get_link_layer(device, p) != IB_LINK_LAYER_INFINIBAND) | ||
| 1708 | continue; | 1701 | continue; |
| 1709 | dev = ipoib_add_port("ib%d", device, p); | 1702 | dev = ipoib_add_port("ib%d", device, p); |
| 1710 | if (!IS_ERR(dev)) { | 1703 | if (!IS_ERR(dev)) { |
| 1711 | priv = netdev_priv(dev); | 1704 | priv = netdev_priv(dev); |
| 1712 | list_add_tail(&priv->list, dev_list); | 1705 | list_add_tail(&priv->list, dev_list); |
| 1706 | count++; | ||
| 1713 | } | 1707 | } |
| 1714 | } | 1708 | } |
| 1715 | 1709 | ||
| 1710 | if (!count) { | ||
| 1711 | kfree(dev_list); | ||
| 1712 | return; | ||
| 1713 | } | ||
| 1714 | |||
| 1716 | ib_set_client_data(device, &ipoib_client, dev_list); | 1715 | ib_set_client_data(device, &ipoib_client, dev_list); |
| 1717 | } | 1716 | } |
| 1718 | 1717 | ||
| @@ -1721,9 +1720,6 @@ static void ipoib_remove_one(struct ib_device *device) | |||
| 1721 | struct ipoib_dev_priv *priv, *tmp; | 1720 | struct ipoib_dev_priv *priv, *tmp; |
| 1722 | struct list_head *dev_list; | 1721 | struct list_head *dev_list; |
| 1723 | 1722 | ||
| 1724 | if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) | ||
| 1725 | return; | ||
| 1726 | |||
| 1727 | dev_list = ib_get_client_data(device, &ipoib_client); | 1723 | dev_list = ib_get_client_data(device, &ipoib_client); |
| 1728 | if (!dev_list) | 1724 | if (!dev_list) |
| 1729 | return; | 1725 | return; |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index e5cc43074196..851c8219d501 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c | |||
| @@ -141,6 +141,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca) | |||
| 141 | .sq_sig_type = IB_SIGNAL_ALL_WR, | 141 | .sq_sig_type = IB_SIGNAL_ALL_WR, |
| 142 | .qp_type = IB_QPT_UD | 142 | .qp_type = IB_QPT_UD |
| 143 | }; | 143 | }; |
| 144 | struct ib_cq_init_attr cq_attr = {}; | ||
| 144 | 145 | ||
| 145 | int ret, size; | 146 | int ret, size; |
| 146 | int i; | 147 | int i; |
| @@ -176,16 +177,20 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca) | |||
| 176 | else | 177 | else |
| 177 | size += ipoib_recvq_size * ipoib_max_conn_qp; | 178 | size += ipoib_recvq_size * ipoib_max_conn_qp; |
| 178 | } else | 179 | } else |
| 179 | goto out_free_wq; | 180 | if (ret != -ENOSYS) |
| 181 | goto out_free_wq; | ||
| 180 | 182 | ||
| 181 | priv->recv_cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0); | 183 | cq_attr.cqe = size; |
| 184 | priv->recv_cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, | ||
| 185 | dev, &cq_attr); | ||
| 182 | if (IS_ERR(priv->recv_cq)) { | 186 | if (IS_ERR(priv->recv_cq)) { |
| 183 | printk(KERN_WARNING "%s: failed to create receive CQ\n", ca->name); | 187 | printk(KERN_WARNING "%s: failed to create receive CQ\n", ca->name); |
| 184 | goto out_cm_dev_cleanup; | 188 | goto out_cm_dev_cleanup; |
| 185 | } | 189 | } |
| 186 | 190 | ||
| 191 | cq_attr.cqe = ipoib_sendq_size; | ||
| 187 | priv->send_cq = ib_create_cq(priv->ca, ipoib_send_comp_handler, NULL, | 192 | priv->send_cq = ib_create_cq(priv->ca, ipoib_send_comp_handler, NULL, |
| 188 | dev, ipoib_sendq_size, 0); | 193 | dev, &cq_attr); |
| 189 | if (IS_ERR(priv->send_cq)) { | 194 | if (IS_ERR(priv->send_cq)) { |
| 190 | printk(KERN_WARNING "%s: failed to create send CQ\n", ca->name); | 195 | printk(KERN_WARNING "%s: failed to create send CQ\n", ca->name); |
| 191 | goto out_free_recv_cq; | 196 | goto out_free_recv_cq; |
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index cc2dd35ffbc0..5c9f565ea0e8 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c | |||
| @@ -51,19 +51,22 @@ static void iser_cq_callback(struct ib_cq *cq, void *cq_context); | |||
| 51 | 51 | ||
| 52 | static void iser_cq_event_callback(struct ib_event *cause, void *context) | 52 | static void iser_cq_event_callback(struct ib_event *cause, void *context) |
| 53 | { | 53 | { |
| 54 | iser_err("got cq event %d \n", cause->event); | 54 | iser_err("cq event %s (%d)\n", |
| 55 | ib_event_msg(cause->event), cause->event); | ||
| 55 | } | 56 | } |
| 56 | 57 | ||
| 57 | static void iser_qp_event_callback(struct ib_event *cause, void *context) | 58 | static void iser_qp_event_callback(struct ib_event *cause, void *context) |
| 58 | { | 59 | { |
| 59 | iser_err("got qp event %d\n",cause->event); | 60 | iser_err("qp event %s (%d)\n", |
| 61 | ib_event_msg(cause->event), cause->event); | ||
| 60 | } | 62 | } |
| 61 | 63 | ||
| 62 | static void iser_event_handler(struct ib_event_handler *handler, | 64 | static void iser_event_handler(struct ib_event_handler *handler, |
| 63 | struct ib_event *event) | 65 | struct ib_event *event) |
| 64 | { | 66 | { |
| 65 | iser_err("async event %d on device %s port %d\n", event->event, | 67 | iser_err("async event %s (%d) on device %s port %d\n", |
| 66 | event->device->name, event->element.port_num); | 68 | ib_event_msg(event->event), event->event, |
| 69 | event->device->name, event->element.port_num); | ||
| 67 | } | 70 | } |
| 68 | 71 | ||
| 69 | /** | 72 | /** |
| @@ -123,14 +126,17 @@ static int iser_create_device_ib_res(struct iser_device *device) | |||
| 123 | goto pd_err; | 126 | goto pd_err; |
| 124 | 127 | ||
| 125 | for (i = 0; i < device->comps_used; i++) { | 128 | for (i = 0; i < device->comps_used; i++) { |
| 129 | struct ib_cq_init_attr cq_attr = {}; | ||
| 126 | struct iser_comp *comp = &device->comps[i]; | 130 | struct iser_comp *comp = &device->comps[i]; |
| 127 | 131 | ||
| 128 | comp->device = device; | 132 | comp->device = device; |
| 133 | cq_attr.cqe = max_cqe; | ||
| 134 | cq_attr.comp_vector = i; | ||
| 129 | comp->cq = ib_create_cq(device->ib_device, | 135 | comp->cq = ib_create_cq(device->ib_device, |
| 130 | iser_cq_callback, | 136 | iser_cq_callback, |
| 131 | iser_cq_event_callback, | 137 | iser_cq_event_callback, |
| 132 | (void *)comp, | 138 | (void *)comp, |
| 133 | max_cqe, i); | 139 | &cq_attr); |
| 134 | if (IS_ERR(comp->cq)) { | 140 | if (IS_ERR(comp->cq)) { |
| 135 | comp->cq = NULL; | 141 | comp->cq = NULL; |
| 136 | goto cq_err; | 142 | goto cq_err; |
| @@ -873,8 +879,9 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve | |||
| 873 | int ret = 0; | 879 | int ret = 0; |
| 874 | 880 | ||
| 875 | iser_conn = (struct iser_conn *)cma_id->context; | 881 | iser_conn = (struct iser_conn *)cma_id->context; |
| 876 | iser_info("event %d status %d conn %p id %p\n", | 882 | iser_info("%s (%d): status %d conn %p id %p\n", |
| 877 | event->event, event->status, cma_id->context, cma_id); | 883 | rdma_event_msg(event->event), event->event, |
| 884 | event->status, cma_id->context, cma_id); | ||
| 878 | 885 | ||
| 879 | mutex_lock(&iser_conn->state_mutex); | 886 | mutex_lock(&iser_conn->state_mutex); |
| 880 | switch (event->event) { | 887 | switch (event->event) { |
| @@ -913,7 +920,8 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve | |||
| 913 | } | 920 | } |
| 914 | break; | 921 | break; |
| 915 | default: | 922 | default: |
| 916 | iser_err("Unexpected RDMA CM event (%d)\n", event->event); | 923 | iser_err("Unexpected RDMA CM event: %s (%d)\n", |
| 924 | rdma_event_msg(event->event), event->event); | ||
| 917 | break; | 925 | break; |
| 918 | } | 926 | } |
| 919 | mutex_unlock(&iser_conn->state_mutex); | 927 | mutex_unlock(&iser_conn->state_mutex); |
| @@ -1173,10 +1181,13 @@ static void iser_handle_wc(struct ib_wc *wc) | |||
| 1173 | } | 1181 | } |
| 1174 | } else { | 1182 | } else { |
| 1175 | if (wc->status != IB_WC_WR_FLUSH_ERR) | 1183 | if (wc->status != IB_WC_WR_FLUSH_ERR) |
| 1176 | iser_err("wr id %llx status %d vend_err %x\n", | 1184 | iser_err("%s (%d): wr id %llx vend_err %x\n", |
| 1177 | wc->wr_id, wc->status, wc->vendor_err); | 1185 | ib_wc_status_msg(wc->status), wc->status, |
| 1186 | wc->wr_id, wc->vendor_err); | ||
| 1178 | else | 1187 | else |
| 1179 | iser_dbg("flush error: wr id %llx\n", wc->wr_id); | 1188 | iser_dbg("%s (%d): wr id %llx\n", |
| 1189 | ib_wc_status_msg(wc->status), wc->status, | ||
| 1190 | wc->wr_id); | ||
| 1180 | 1191 | ||
| 1181 | if (wc->wr_id == ISER_BEACON_WRID) | 1192 | if (wc->wr_id == ISER_BEACON_WRID) |
| 1182 | /* all flush errors were consumed */ | 1193 | /* all flush errors were consumed */ |
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 575a072d765f..d851e1828d6f 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c | |||
| @@ -80,7 +80,9 @@ isert_qp_event_callback(struct ib_event *e, void *context) | |||
| 80 | { | 80 | { |
| 81 | struct isert_conn *isert_conn = context; | 81 | struct isert_conn *isert_conn = context; |
| 82 | 82 | ||
| 83 | isert_err("conn %p event: %d\n", isert_conn, e->event); | 83 | isert_err("%s (%d): conn %p\n", |
| 84 | ib_event_msg(e->event), e->event, isert_conn); | ||
| 85 | |||
| 84 | switch (e->event) { | 86 | switch (e->event) { |
| 85 | case IB_EVENT_COMM_EST: | 87 | case IB_EVENT_COMM_EST: |
| 86 | rdma_notify(isert_conn->cm_id, IB_EVENT_COMM_EST); | 88 | rdma_notify(isert_conn->cm_id, IB_EVENT_COMM_EST); |
| @@ -318,15 +320,18 @@ isert_alloc_comps(struct isert_device *device, | |||
| 318 | max_cqe = min(ISER_MAX_CQ_LEN, attr->max_cqe); | 320 | max_cqe = min(ISER_MAX_CQ_LEN, attr->max_cqe); |
| 319 | 321 | ||
| 320 | for (i = 0; i < device->comps_used; i++) { | 322 | for (i = 0; i < device->comps_used; i++) { |
| 323 | struct ib_cq_init_attr cq_attr = {}; | ||
| 321 | struct isert_comp *comp = &device->comps[i]; | 324 | struct isert_comp *comp = &device->comps[i]; |
| 322 | 325 | ||
| 323 | comp->device = device; | 326 | comp->device = device; |
| 324 | INIT_WORK(&comp->work, isert_cq_work); | 327 | INIT_WORK(&comp->work, isert_cq_work); |
| 328 | cq_attr.cqe = max_cqe; | ||
| 329 | cq_attr.comp_vector = i; | ||
| 325 | comp->cq = ib_create_cq(device->ib_device, | 330 | comp->cq = ib_create_cq(device->ib_device, |
| 326 | isert_cq_callback, | 331 | isert_cq_callback, |
| 327 | isert_cq_event_callback, | 332 | isert_cq_event_callback, |
| 328 | (void *)comp, | 333 | (void *)comp, |
| 329 | max_cqe, i); | 334 | &cq_attr); |
| 330 | if (IS_ERR(comp->cq)) { | 335 | if (IS_ERR(comp->cq)) { |
| 331 | isert_err("Unable to allocate cq\n"); | 336 | isert_err("Unable to allocate cq\n"); |
| 332 | ret = PTR_ERR(comp->cq); | 337 | ret = PTR_ERR(comp->cq); |
| @@ -770,6 +775,17 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) | |||
| 770 | ret = isert_rdma_post_recvl(isert_conn); | 775 | ret = isert_rdma_post_recvl(isert_conn); |
| 771 | if (ret) | 776 | if (ret) |
| 772 | goto out_conn_dev; | 777 | goto out_conn_dev; |
| 778 | /* | ||
| 779 | * Obtain the second reference now before isert_rdma_accept() to | ||
| 780 | * ensure that any initiator generated REJECT CM event that occurs | ||
| 781 | * asynchronously won't drop the last reference until the error path | ||
| 782 | * in iscsi_target_login_sess_out() does it's ->iscsit_free_conn() -> | ||
| 783 | * isert_free_conn() -> isert_put_conn() -> kref_put(). | ||
| 784 | */ | ||
| 785 | if (!kref_get_unless_zero(&isert_conn->kref)) { | ||
| 786 | isert_warn("conn %p connect_release is running\n", isert_conn); | ||
| 787 | goto out_conn_dev; | ||
| 788 | } | ||
| 773 | 789 | ||
| 774 | ret = isert_rdma_accept(isert_conn); | 790 | ret = isert_rdma_accept(isert_conn); |
| 775 | if (ret) | 791 | if (ret) |
| @@ -831,11 +847,6 @@ isert_connected_handler(struct rdma_cm_id *cma_id) | |||
| 831 | 847 | ||
| 832 | isert_info("conn %p\n", isert_conn); | 848 | isert_info("conn %p\n", isert_conn); |
| 833 | 849 | ||
| 834 | if (!kref_get_unless_zero(&isert_conn->kref)) { | ||
| 835 | isert_warn("conn %p connect_release is running\n", isert_conn); | ||
| 836 | return; | ||
| 837 | } | ||
| 838 | |||
| 839 | mutex_lock(&isert_conn->mutex); | 850 | mutex_lock(&isert_conn->mutex); |
| 840 | if (isert_conn->state != ISER_CONN_FULL_FEATURE) | 851 | if (isert_conn->state != ISER_CONN_FULL_FEATURE) |
| 841 | isert_conn->state = ISER_CONN_UP; | 852 | isert_conn->state = ISER_CONN_UP; |
| @@ -900,7 +911,8 @@ static int | |||
| 900 | isert_np_cma_handler(struct isert_np *isert_np, | 911 | isert_np_cma_handler(struct isert_np *isert_np, |
| 901 | enum rdma_cm_event_type event) | 912 | enum rdma_cm_event_type event) |
| 902 | { | 913 | { |
| 903 | isert_dbg("isert np %p, handling event %d\n", isert_np, event); | 914 | isert_dbg("%s (%d): isert np %p\n", |
| 915 | rdma_event_msg(event), event, isert_np); | ||
| 904 | 916 | ||
| 905 | switch (event) { | 917 | switch (event) { |
| 906 | case RDMA_CM_EVENT_DEVICE_REMOVAL: | 918 | case RDMA_CM_EVENT_DEVICE_REMOVAL: |
| @@ -974,7 +986,8 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) | |||
| 974 | { | 986 | { |
| 975 | int ret = 0; | 987 | int ret = 0; |
| 976 | 988 | ||
| 977 | isert_info("event %d status %d id %p np %p\n", event->event, | 989 | isert_info("%s (%d): status %d id %p np %p\n", |
| 990 | rdma_event_msg(event->event), event->event, | ||
| 978 | event->status, cma_id, cma_id->context); | 991 | event->status, cma_id, cma_id->context); |
| 979 | 992 | ||
| 980 | switch (event->event) { | 993 | switch (event->event) { |
| @@ -1349,7 +1362,7 @@ sequence_cmd: | |||
| 1349 | if (!rc && dump_payload == false && unsol_data) | 1362 | if (!rc && dump_payload == false && unsol_data) |
| 1350 | iscsit_set_unsoliticed_dataout(cmd); | 1363 | iscsit_set_unsoliticed_dataout(cmd); |
| 1351 | else if (dump_payload && imm_data) | 1364 | else if (dump_payload && imm_data) |
| 1352 | target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); | 1365 | target_put_sess_cmd(&cmd->se_cmd); |
| 1353 | 1366 | ||
| 1354 | return 0; | 1367 | return 0; |
| 1355 | } | 1368 | } |
| @@ -1774,7 +1787,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err) | |||
| 1774 | cmd->se_cmd.t_state == TRANSPORT_WRITE_PENDING) { | 1787 | cmd->se_cmd.t_state == TRANSPORT_WRITE_PENDING) { |
| 1775 | struct se_cmd *se_cmd = &cmd->se_cmd; | 1788 | struct se_cmd *se_cmd = &cmd->se_cmd; |
| 1776 | 1789 | ||
| 1777 | target_put_sess_cmd(se_cmd->se_sess, se_cmd); | 1790 | target_put_sess_cmd(se_cmd); |
| 1778 | } | 1791 | } |
| 1779 | } | 1792 | } |
| 1780 | 1793 | ||
| @@ -1947,7 +1960,7 @@ isert_completion_rdma_read(struct iser_tx_desc *tx_desc, | |||
| 1947 | spin_unlock_bh(&cmd->istate_lock); | 1960 | spin_unlock_bh(&cmd->istate_lock); |
| 1948 | 1961 | ||
| 1949 | if (ret) { | 1962 | if (ret) { |
| 1950 | target_put_sess_cmd(se_cmd->se_sess, se_cmd); | 1963 | target_put_sess_cmd(se_cmd); |
| 1951 | transport_send_check_condition_and_sense(se_cmd, | 1964 | transport_send_check_condition_and_sense(se_cmd, |
| 1952 | se_cmd->pi_err, 0); | 1965 | se_cmd->pi_err, 0); |
| 1953 | } else { | 1966 | } else { |
| @@ -2108,10 +2121,13 @@ isert_handle_wc(struct ib_wc *wc) | |||
| 2108 | } | 2121 | } |
| 2109 | } else { | 2122 | } else { |
| 2110 | if (wc->status != IB_WC_WR_FLUSH_ERR) | 2123 | if (wc->status != IB_WC_WR_FLUSH_ERR) |
| 2111 | isert_err("wr id %llx status %d vend_err %x\n", | 2124 | isert_err("%s (%d): wr id %llx vend_err %x\n", |
| 2112 | wc->wr_id, wc->status, wc->vendor_err); | 2125 | ib_wc_status_msg(wc->status), wc->status, |
| 2126 | wc->wr_id, wc->vendor_err); | ||
| 2113 | else | 2127 | else |
| 2114 | isert_dbg("flush error: wr id %llx\n", wc->wr_id); | 2128 | isert_dbg("%s (%d): wr id %llx\n", |
| 2129 | ib_wc_status_msg(wc->status), wc->status, | ||
| 2130 | wc->wr_id); | ||
| 2115 | 2131 | ||
| 2116 | if (wc->wr_id != ISER_FASTREG_LI_WRID) | 2132 | if (wc->wr_id != ISER_FASTREG_LI_WRID) |
| 2117 | isert_cq_comp_err(isert_conn, wc); | 2133 | isert_cq_comp_err(isert_conn, wc); |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 918814cd0f80..31a20b462266 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
| @@ -59,9 +59,10 @@ | |||
| 59 | #define DRV_RELDATE "July 1, 2013" | 59 | #define DRV_RELDATE "July 1, 2013" |
| 60 | 60 | ||
| 61 | MODULE_AUTHOR("Roland Dreier"); | 61 | MODULE_AUTHOR("Roland Dreier"); |
| 62 | MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator " | 62 | MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator"); |
| 63 | "v" DRV_VERSION " (" DRV_RELDATE ")"); | ||
| 64 | MODULE_LICENSE("Dual BSD/GPL"); | 63 | MODULE_LICENSE("Dual BSD/GPL"); |
| 64 | MODULE_VERSION(DRV_VERSION); | ||
| 65 | MODULE_INFO(release_date, DRV_RELDATE); | ||
| 65 | 66 | ||
| 66 | static unsigned int srp_sg_tablesize; | 67 | static unsigned int srp_sg_tablesize; |
| 67 | static unsigned int cmd_sg_entries; | 68 | static unsigned int cmd_sg_entries; |
| @@ -98,7 +99,7 @@ module_param(register_always, bool, 0444); | |||
| 98 | MODULE_PARM_DESC(register_always, | 99 | MODULE_PARM_DESC(register_always, |
| 99 | "Use memory registration even for contiguous memory regions"); | 100 | "Use memory registration even for contiguous memory regions"); |
| 100 | 101 | ||
| 101 | static struct kernel_param_ops srp_tmo_ops; | 102 | static const struct kernel_param_ops srp_tmo_ops; |
| 102 | 103 | ||
| 103 | static int srp_reconnect_delay = 10; | 104 | static int srp_reconnect_delay = 10; |
| 104 | module_param_cb(reconnect_delay, &srp_tmo_ops, &srp_reconnect_delay, | 105 | module_param_cb(reconnect_delay, &srp_tmo_ops, &srp_reconnect_delay, |
| @@ -160,13 +161,10 @@ static int srp_tmo_set(const char *val, const struct kernel_param *kp) | |||
| 160 | { | 161 | { |
| 161 | int tmo, res; | 162 | int tmo, res; |
| 162 | 163 | ||
| 163 | if (strncmp(val, "off", 3) != 0) { | 164 | res = srp_parse_tmo(&tmo, val); |
| 164 | res = kstrtoint(val, 0, &tmo); | 165 | if (res) |
| 165 | if (res) | 166 | goto out; |
| 166 | goto out; | 167 | |
| 167 | } else { | ||
| 168 | tmo = -1; | ||
| 169 | } | ||
| 170 | if (kp->arg == &srp_reconnect_delay) | 168 | if (kp->arg == &srp_reconnect_delay) |
| 171 | res = srp_tmo_valid(tmo, srp_fast_io_fail_tmo, | 169 | res = srp_tmo_valid(tmo, srp_fast_io_fail_tmo, |
| 172 | srp_dev_loss_tmo); | 170 | srp_dev_loss_tmo); |
| @@ -183,7 +181,7 @@ out: | |||
| 183 | return res; | 181 | return res; |
| 184 | } | 182 | } |
| 185 | 183 | ||
| 186 | static struct kernel_param_ops srp_tmo_ops = { | 184 | static const struct kernel_param_ops srp_tmo_ops = { |
| 187 | .get = srp_tmo_get, | 185 | .get = srp_tmo_get, |
| 188 | .set = srp_tmo_set, | 186 | .set = srp_tmo_set, |
| 189 | }; | 187 | }; |
| @@ -253,7 +251,8 @@ static void srp_free_iu(struct srp_host *host, struct srp_iu *iu) | |||
| 253 | 251 | ||
| 254 | static void srp_qp_event(struct ib_event *event, void *context) | 252 | static void srp_qp_event(struct ib_event *event, void *context) |
| 255 | { | 253 | { |
| 256 | pr_debug("QP event %d\n", event->event); | 254 | pr_debug("QP event %s (%d)\n", |
| 255 | ib_event_msg(event->event), event->event); | ||
| 257 | } | 256 | } |
| 258 | 257 | ||
| 259 | static int srp_init_qp(struct srp_target_port *target, | 258 | static int srp_init_qp(struct srp_target_port *target, |
| @@ -465,14 +464,13 @@ static struct srp_fr_pool *srp_alloc_fr_pool(struct srp_target_port *target) | |||
| 465 | */ | 464 | */ |
| 466 | static void srp_destroy_qp(struct srp_rdma_ch *ch) | 465 | static void srp_destroy_qp(struct srp_rdma_ch *ch) |
| 467 | { | 466 | { |
| 468 | struct srp_target_port *target = ch->target; | ||
| 469 | static struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR }; | 467 | static struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR }; |
| 470 | static struct ib_recv_wr wr = { .wr_id = SRP_LAST_WR_ID }; | 468 | static struct ib_recv_wr wr = { .wr_id = SRP_LAST_WR_ID }; |
| 471 | struct ib_recv_wr *bad_wr; | 469 | struct ib_recv_wr *bad_wr; |
| 472 | int ret; | 470 | int ret; |
| 473 | 471 | ||
| 474 | /* Destroying a QP and reusing ch->done is only safe if not connected */ | 472 | /* Destroying a QP and reusing ch->done is only safe if not connected */ |
| 475 | WARN_ON_ONCE(target->connected); | 473 | WARN_ON_ONCE(ch->connected); |
| 476 | 474 | ||
| 477 | ret = ib_modify_qp(ch->qp, &attr, IB_QP_STATE); | 475 | ret = ib_modify_qp(ch->qp, &attr, IB_QP_STATE); |
| 478 | WARN_ONCE(ret, "ib_cm_init_qp_attr() returned %d\n", ret); | 476 | WARN_ONCE(ret, "ib_cm_init_qp_attr() returned %d\n", ret); |
| @@ -499,6 +497,7 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch) | |||
| 499 | struct ib_fmr_pool *fmr_pool = NULL; | 497 | struct ib_fmr_pool *fmr_pool = NULL; |
| 500 | struct srp_fr_pool *fr_pool = NULL; | 498 | struct srp_fr_pool *fr_pool = NULL; |
| 501 | const int m = 1 + dev->use_fast_reg; | 499 | const int m = 1 + dev->use_fast_reg; |
| 500 | struct ib_cq_init_attr cq_attr = {}; | ||
| 502 | int ret; | 501 | int ret; |
| 503 | 502 | ||
| 504 | init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL); | 503 | init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL); |
| @@ -506,15 +505,19 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch) | |||
| 506 | return -ENOMEM; | 505 | return -ENOMEM; |
| 507 | 506 | ||
| 508 | /* + 1 for SRP_LAST_WR_ID */ | 507 | /* + 1 for SRP_LAST_WR_ID */ |
| 508 | cq_attr.cqe = target->queue_size + 1; | ||
| 509 | cq_attr.comp_vector = ch->comp_vector; | ||
| 509 | recv_cq = ib_create_cq(dev->dev, srp_recv_completion, NULL, ch, | 510 | recv_cq = ib_create_cq(dev->dev, srp_recv_completion, NULL, ch, |
| 510 | target->queue_size + 1, ch->comp_vector); | 511 | &cq_attr); |
| 511 | if (IS_ERR(recv_cq)) { | 512 | if (IS_ERR(recv_cq)) { |
| 512 | ret = PTR_ERR(recv_cq); | 513 | ret = PTR_ERR(recv_cq); |
| 513 | goto err; | 514 | goto err; |
| 514 | } | 515 | } |
| 515 | 516 | ||
| 517 | cq_attr.cqe = m * target->queue_size; | ||
| 518 | cq_attr.comp_vector = ch->comp_vector; | ||
| 516 | send_cq = ib_create_cq(dev->dev, srp_send_completion, NULL, ch, | 519 | send_cq = ib_create_cq(dev->dev, srp_send_completion, NULL, ch, |
| 517 | m * target->queue_size, ch->comp_vector); | 520 | &cq_attr); |
| 518 | if (IS_ERR(send_cq)) { | 521 | if (IS_ERR(send_cq)) { |
| 519 | ret = PTR_ERR(send_cq); | 522 | ret = PTR_ERR(send_cq); |
| 520 | goto err_recv_cq; | 523 | goto err_recv_cq; |
| @@ -781,7 +784,7 @@ static int srp_send_req(struct srp_rdma_ch *ch, bool multich) | |||
| 781 | shost_printk(KERN_DEBUG, target->scsi_host, | 784 | shost_printk(KERN_DEBUG, target->scsi_host, |
| 782 | PFX "Topspin/Cisco initiator port ID workaround " | 785 | PFX "Topspin/Cisco initiator port ID workaround " |
| 783 | "activated for target GUID %016llx\n", | 786 | "activated for target GUID %016llx\n", |
| 784 | (unsigned long long) be64_to_cpu(target->ioc_guid)); | 787 | be64_to_cpu(target->ioc_guid)); |
| 785 | memset(req->priv.initiator_port_id, 0, 8); | 788 | memset(req->priv.initiator_port_id, 0, 8); |
| 786 | memcpy(req->priv.initiator_port_id + 8, | 789 | memcpy(req->priv.initiator_port_id + 8, |
| 787 | &target->srp_host->srp_dev->dev->node_guid, 8); | 790 | &target->srp_host->srp_dev->dev->node_guid, 8); |
| @@ -811,35 +814,19 @@ static bool srp_queue_remove_work(struct srp_target_port *target) | |||
| 811 | return changed; | 814 | return changed; |
| 812 | } | 815 | } |
| 813 | 816 | ||
| 814 | static bool srp_change_conn_state(struct srp_target_port *target, | ||
| 815 | bool connected) | ||
| 816 | { | ||
| 817 | bool changed = false; | ||
| 818 | |||
| 819 | spin_lock_irq(&target->lock); | ||
| 820 | if (target->connected != connected) { | ||
| 821 | target->connected = connected; | ||
| 822 | changed = true; | ||
| 823 | } | ||
| 824 | spin_unlock_irq(&target->lock); | ||
| 825 | |||
| 826 | return changed; | ||
| 827 | } | ||
| 828 | |||
| 829 | static void srp_disconnect_target(struct srp_target_port *target) | 817 | static void srp_disconnect_target(struct srp_target_port *target) |
| 830 | { | 818 | { |
| 831 | struct srp_rdma_ch *ch; | 819 | struct srp_rdma_ch *ch; |
| 832 | int i; | 820 | int i; |
| 833 | 821 | ||
| 834 | if (srp_change_conn_state(target, false)) { | 822 | /* XXX should send SRP_I_LOGOUT request */ |
| 835 | /* XXX should send SRP_I_LOGOUT request */ | ||
| 836 | 823 | ||
| 837 | for (i = 0; i < target->ch_count; i++) { | 824 | for (i = 0; i < target->ch_count; i++) { |
| 838 | ch = &target->ch[i]; | 825 | ch = &target->ch[i]; |
| 839 | if (ch->cm_id && ib_send_cm_dreq(ch->cm_id, NULL, 0)) { | 826 | ch->connected = false; |
| 840 | shost_printk(KERN_DEBUG, target->scsi_host, | 827 | if (ch->cm_id && ib_send_cm_dreq(ch->cm_id, NULL, 0)) { |
| 841 | PFX "Sending CM DREQ failed\n"); | 828 | shost_printk(KERN_DEBUG, target->scsi_host, |
| 842 | } | 829 | PFX "Sending CM DREQ failed\n"); |
| 843 | } | 830 | } |
| 844 | } | 831 | } |
| 845 | } | 832 | } |
| @@ -852,7 +839,7 @@ static void srp_free_req_data(struct srp_target_port *target, | |||
| 852 | struct srp_request *req; | 839 | struct srp_request *req; |
| 853 | int i; | 840 | int i; |
| 854 | 841 | ||
| 855 | if (!ch->target || !ch->req_ring) | 842 | if (!ch->req_ring) |
| 856 | return; | 843 | return; |
| 857 | 844 | ||
| 858 | for (i = 0; i < target->req_ring_size; ++i) { | 845 | for (i = 0; i < target->req_ring_size; ++i) { |
| @@ -986,14 +973,26 @@ static void srp_rport_delete(struct srp_rport *rport) | |||
| 986 | srp_queue_remove_work(target); | 973 | srp_queue_remove_work(target); |
| 987 | } | 974 | } |
| 988 | 975 | ||
| 976 | /** | ||
| 977 | * srp_connected_ch() - number of connected channels | ||
| 978 | * @target: SRP target port. | ||
| 979 | */ | ||
| 980 | static int srp_connected_ch(struct srp_target_port *target) | ||
| 981 | { | ||
| 982 | int i, c = 0; | ||
| 983 | |||
| 984 | for (i = 0; i < target->ch_count; i++) | ||
| 985 | c += target->ch[i].connected; | ||
| 986 | |||
| 987 | return c; | ||
| 988 | } | ||
| 989 | |||
| 989 | static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich) | 990 | static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich) |
| 990 | { | 991 | { |
| 991 | struct srp_target_port *target = ch->target; | 992 | struct srp_target_port *target = ch->target; |
| 992 | int ret; | 993 | int ret; |
| 993 | 994 | ||
| 994 | WARN_ON_ONCE(!multich && target->connected); | 995 | WARN_ON_ONCE(!multich && srp_connected_ch(target) > 0); |
| 995 | |||
| 996 | target->qp_in_error = false; | ||
| 997 | 996 | ||
| 998 | ret = srp_lookup_path(ch); | 997 | ret = srp_lookup_path(ch); |
| 999 | if (ret) | 998 | if (ret) |
| @@ -1016,7 +1015,7 @@ static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich) | |||
| 1016 | */ | 1015 | */ |
| 1017 | switch (ch->status) { | 1016 | switch (ch->status) { |
| 1018 | case 0: | 1017 | case 0: |
| 1019 | srp_change_conn_state(target, true); | 1018 | ch->connected = true; |
| 1020 | return 0; | 1019 | return 0; |
| 1021 | 1020 | ||
| 1022 | case SRP_PORT_REDIRECT: | 1021 | case SRP_PORT_REDIRECT: |
| @@ -1214,14 +1213,10 @@ static int srp_rport_reconnect(struct srp_rport *rport) | |||
| 1214 | */ | 1213 | */ |
| 1215 | for (i = 0; i < target->ch_count; i++) { | 1214 | for (i = 0; i < target->ch_count; i++) { |
| 1216 | ch = &target->ch[i]; | 1215 | ch = &target->ch[i]; |
| 1217 | if (!ch->target) | ||
| 1218 | break; | ||
| 1219 | ret += srp_new_cm_id(ch); | 1216 | ret += srp_new_cm_id(ch); |
| 1220 | } | 1217 | } |
| 1221 | for (i = 0; i < target->ch_count; i++) { | 1218 | for (i = 0; i < target->ch_count; i++) { |
| 1222 | ch = &target->ch[i]; | 1219 | ch = &target->ch[i]; |
| 1223 | if (!ch->target) | ||
| 1224 | break; | ||
| 1225 | for (j = 0; j < target->req_ring_size; ++j) { | 1220 | for (j = 0; j < target->req_ring_size; ++j) { |
| 1226 | struct srp_request *req = &ch->req_ring[j]; | 1221 | struct srp_request *req = &ch->req_ring[j]; |
| 1227 | 1222 | ||
| @@ -1230,8 +1225,6 @@ static int srp_rport_reconnect(struct srp_rport *rport) | |||
| 1230 | } | 1225 | } |
| 1231 | for (i = 0; i < target->ch_count; i++) { | 1226 | for (i = 0; i < target->ch_count; i++) { |
| 1232 | ch = &target->ch[i]; | 1227 | ch = &target->ch[i]; |
| 1233 | if (!ch->target) | ||
| 1234 | break; | ||
| 1235 | /* | 1228 | /* |
| 1236 | * Whether or not creating a new CM ID succeeded, create a new | 1229 | * Whether or not creating a new CM ID succeeded, create a new |
| 1237 | * QP. This guarantees that all completion callback function | 1230 | * QP. This guarantees that all completion callback function |
| @@ -1243,13 +1236,13 @@ static int srp_rport_reconnect(struct srp_rport *rport) | |||
| 1243 | for (j = 0; j < target->queue_size; ++j) | 1236 | for (j = 0; j < target->queue_size; ++j) |
| 1244 | list_add(&ch->tx_ring[j]->list, &ch->free_tx); | 1237 | list_add(&ch->tx_ring[j]->list, &ch->free_tx); |
| 1245 | } | 1238 | } |
| 1239 | |||
| 1240 | target->qp_in_error = false; | ||
| 1241 | |||
| 1246 | for (i = 0; i < target->ch_count; i++) { | 1242 | for (i = 0; i < target->ch_count; i++) { |
| 1247 | ch = &target->ch[i]; | 1243 | ch = &target->ch[i]; |
| 1248 | if (ret || !ch->target) { | 1244 | if (ret) |
| 1249 | if (i > 1) | ||
| 1250 | ret = 0; | ||
| 1251 | break; | 1245 | break; |
| 1252 | } | ||
| 1253 | ret = srp_connect_ch(ch, multich); | 1246 | ret = srp_connect_ch(ch, multich); |
| 1254 | multich = true; | 1247 | multich = true; |
| 1255 | } | 1248 | } |
| @@ -1842,7 +1835,7 @@ static void srp_process_aer_req(struct srp_rdma_ch *ch, | |||
| 1842 | s32 delta = be32_to_cpu(req->req_lim_delta); | 1835 | s32 delta = be32_to_cpu(req->req_lim_delta); |
| 1843 | 1836 | ||
| 1844 | shost_printk(KERN_ERR, target->scsi_host, PFX | 1837 | shost_printk(KERN_ERR, target->scsi_host, PFX |
| 1845 | "ignoring AER for LUN %llu\n", be64_to_cpu(req->lun)); | 1838 | "ignoring AER for LUN %llu\n", scsilun_to_int(&req->lun)); |
| 1846 | 1839 | ||
| 1847 | if (srp_response_common(ch, delta, &rsp, sizeof(rsp))) | 1840 | if (srp_response_common(ch, delta, &rsp, sizeof(rsp))) |
| 1848 | shost_printk(KERN_ERR, target->scsi_host, PFX | 1841 | shost_printk(KERN_ERR, target->scsi_host, PFX |
| @@ -1929,20 +1922,21 @@ static void srp_handle_qp_err(u64 wr_id, enum ib_wc_status wc_status, | |||
| 1929 | return; | 1922 | return; |
| 1930 | } | 1923 | } |
| 1931 | 1924 | ||
| 1932 | if (target->connected && !target->qp_in_error) { | 1925 | if (ch->connected && !target->qp_in_error) { |
| 1933 | if (wr_id & LOCAL_INV_WR_ID_MASK) { | 1926 | if (wr_id & LOCAL_INV_WR_ID_MASK) { |
| 1934 | shost_printk(KERN_ERR, target->scsi_host, PFX | 1927 | shost_printk(KERN_ERR, target->scsi_host, PFX |
| 1935 | "LOCAL_INV failed with status %d\n", | 1928 | "LOCAL_INV failed with status %s (%d)\n", |
| 1936 | wc_status); | 1929 | ib_wc_status_msg(wc_status), wc_status); |
| 1937 | } else if (wr_id & FAST_REG_WR_ID_MASK) { | 1930 | } else if (wr_id & FAST_REG_WR_ID_MASK) { |
| 1938 | shost_printk(KERN_ERR, target->scsi_host, PFX | 1931 | shost_printk(KERN_ERR, target->scsi_host, PFX |
| 1939 | "FAST_REG_MR failed status %d\n", | 1932 | "FAST_REG_MR failed status %s (%d)\n", |
| 1940 | wc_status); | 1933 | ib_wc_status_msg(wc_status), wc_status); |
| 1941 | } else { | 1934 | } else { |
| 1942 | shost_printk(KERN_ERR, target->scsi_host, | 1935 | shost_printk(KERN_ERR, target->scsi_host, |
| 1943 | PFX "failed %s status %d for iu %p\n", | 1936 | PFX "failed %s status %s (%d) for iu %p\n", |
| 1944 | send_err ? "send" : "receive", | 1937 | send_err ? "send" : "receive", |
| 1945 | wc_status, (void *)(uintptr_t)wr_id); | 1938 | ib_wc_status_msg(wc_status), wc_status, |
| 1939 | (void *)(uintptr_t)wr_id); | ||
| 1946 | } | 1940 | } |
| 1947 | queue_work(system_long_wq, &target->tl_err_work); | 1941 | queue_work(system_long_wq, &target->tl_err_work); |
| 1948 | } | 1942 | } |
| @@ -2034,7 +2028,7 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd) | |||
| 2034 | memset(cmd, 0, sizeof *cmd); | 2028 | memset(cmd, 0, sizeof *cmd); |
| 2035 | 2029 | ||
| 2036 | cmd->opcode = SRP_CMD; | 2030 | cmd->opcode = SRP_CMD; |
| 2037 | cmd->lun = cpu_to_be64((u64) scmnd->device->lun << 48); | 2031 | int_to_scsilun(scmnd->device->lun, &cmd->lun); |
| 2038 | cmd->tag = tag; | 2032 | cmd->tag = tag; |
| 2039 | memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len); | 2033 | memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len); |
| 2040 | 2034 | ||
| @@ -2367,7 +2361,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event) | |||
| 2367 | case IB_CM_DREQ_RECEIVED: | 2361 | case IB_CM_DREQ_RECEIVED: |
| 2368 | shost_printk(KERN_WARNING, target->scsi_host, | 2362 | shost_printk(KERN_WARNING, target->scsi_host, |
| 2369 | PFX "DREQ received - connection closed\n"); | 2363 | PFX "DREQ received - connection closed\n"); |
| 2370 | srp_change_conn_state(target, false); | 2364 | ch->connected = false; |
| 2371 | if (ib_send_cm_drep(cm_id, NULL, 0)) | 2365 | if (ib_send_cm_drep(cm_id, NULL, 0)) |
| 2372 | shost_printk(KERN_ERR, target->scsi_host, | 2366 | shost_printk(KERN_ERR, target->scsi_host, |
| 2373 | PFX "Sending CM DREP failed\n"); | 2367 | PFX "Sending CM DREP failed\n"); |
| @@ -2414,8 +2408,8 @@ srp_change_queue_depth(struct scsi_device *sdev, int qdepth) | |||
| 2414 | return scsi_change_queue_depth(sdev, qdepth); | 2408 | return scsi_change_queue_depth(sdev, qdepth); |
| 2415 | } | 2409 | } |
| 2416 | 2410 | ||
| 2417 | static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, | 2411 | static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun, |
| 2418 | unsigned int lun, u8 func) | 2412 | u8 func) |
| 2419 | { | 2413 | { |
| 2420 | struct srp_target_port *target = ch->target; | 2414 | struct srp_target_port *target = ch->target; |
| 2421 | struct srp_rport *rport = target->rport; | 2415 | struct srp_rport *rport = target->rport; |
| @@ -2423,7 +2417,7 @@ static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, | |||
| 2423 | struct srp_iu *iu; | 2417 | struct srp_iu *iu; |
| 2424 | struct srp_tsk_mgmt *tsk_mgmt; | 2418 | struct srp_tsk_mgmt *tsk_mgmt; |
| 2425 | 2419 | ||
| 2426 | if (!target->connected || target->qp_in_error) | 2420 | if (!ch->connected || target->qp_in_error) |
| 2427 | return -1; | 2421 | return -1; |
| 2428 | 2422 | ||
| 2429 | init_completion(&ch->tsk_mgmt_done); | 2423 | init_completion(&ch->tsk_mgmt_done); |
| @@ -2449,7 +2443,7 @@ static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, | |||
| 2449 | memset(tsk_mgmt, 0, sizeof *tsk_mgmt); | 2443 | memset(tsk_mgmt, 0, sizeof *tsk_mgmt); |
| 2450 | 2444 | ||
| 2451 | tsk_mgmt->opcode = SRP_TSK_MGMT; | 2445 | tsk_mgmt->opcode = SRP_TSK_MGMT; |
| 2452 | tsk_mgmt->lun = cpu_to_be64((u64) lun << 48); | 2446 | int_to_scsilun(lun, &tsk_mgmt->lun); |
| 2453 | tsk_mgmt->tag = req_tag | SRP_TAG_TSK_MGMT; | 2447 | tsk_mgmt->tag = req_tag | SRP_TAG_TSK_MGMT; |
| 2454 | tsk_mgmt->tsk_mgmt_func = func; | 2448 | tsk_mgmt->tsk_mgmt_func = func; |
| 2455 | tsk_mgmt->task_tag = req_tag; | 2449 | tsk_mgmt->task_tag = req_tag; |
| @@ -2563,8 +2557,7 @@ static ssize_t show_id_ext(struct device *dev, struct device_attribute *attr, | |||
| 2563 | { | 2557 | { |
| 2564 | struct srp_target_port *target = host_to_target(class_to_shost(dev)); | 2558 | struct srp_target_port *target = host_to_target(class_to_shost(dev)); |
| 2565 | 2559 | ||
| 2566 | return sprintf(buf, "0x%016llx\n", | 2560 | return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->id_ext)); |
| 2567 | (unsigned long long) be64_to_cpu(target->id_ext)); | ||
| 2568 | } | 2561 | } |
| 2569 | 2562 | ||
| 2570 | static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr, | 2563 | static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr, |
| @@ -2572,8 +2565,7 @@ static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr, | |||
| 2572 | { | 2565 | { |
| 2573 | struct srp_target_port *target = host_to_target(class_to_shost(dev)); | 2566 | struct srp_target_port *target = host_to_target(class_to_shost(dev)); |
| 2574 | 2567 | ||
| 2575 | return sprintf(buf, "0x%016llx\n", | 2568 | return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->ioc_guid)); |
| 2576 | (unsigned long long) be64_to_cpu(target->ioc_guid)); | ||
| 2577 | } | 2569 | } |
| 2578 | 2570 | ||
| 2579 | static ssize_t show_service_id(struct device *dev, | 2571 | static ssize_t show_service_id(struct device *dev, |
| @@ -2581,8 +2573,7 @@ static ssize_t show_service_id(struct device *dev, | |||
| 2581 | { | 2573 | { |
| 2582 | struct srp_target_port *target = host_to_target(class_to_shost(dev)); | 2574 | struct srp_target_port *target = host_to_target(class_to_shost(dev)); |
| 2583 | 2575 | ||
| 2584 | return sprintf(buf, "0x%016llx\n", | 2576 | return sprintf(buf, "0x%016llx\n", be64_to_cpu(target->service_id)); |
| 2585 | (unsigned long long) be64_to_cpu(target->service_id)); | ||
| 2586 | } | 2577 | } |
| 2587 | 2578 | ||
| 2588 | static ssize_t show_pkey(struct device *dev, struct device_attribute *attr, | 2579 | static ssize_t show_pkey(struct device *dev, struct device_attribute *attr, |
| @@ -2773,7 +2764,7 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target) | |||
| 2773 | 2764 | ||
| 2774 | target->state = SRP_TARGET_SCANNING; | 2765 | target->state = SRP_TARGET_SCANNING; |
| 2775 | sprintf(target->target_name, "SRP.T10:%016llX", | 2766 | sprintf(target->target_name, "SRP.T10:%016llX", |
| 2776 | (unsigned long long) be64_to_cpu(target->id_ext)); | 2767 | be64_to_cpu(target->id_ext)); |
| 2777 | 2768 | ||
| 2778 | if (scsi_add_host(target->scsi_host, host->srp_dev->dev->dma_device)) | 2769 | if (scsi_add_host(target->scsi_host, host->srp_dev->dev->dma_device)) |
| 2779 | return -ENODEV; | 2770 | return -ENODEV; |
| @@ -2797,7 +2788,8 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target) | |||
| 2797 | scsi_scan_target(&target->scsi_host->shost_gendev, | 2788 | scsi_scan_target(&target->scsi_host->shost_gendev, |
| 2798 | 0, target->scsi_id, SCAN_WILD_CARD, 0); | 2789 | 0, target->scsi_id, SCAN_WILD_CARD, 0); |
| 2799 | 2790 | ||
| 2800 | if (!target->connected || target->qp_in_error) { | 2791 | if (srp_connected_ch(target) < target->ch_count || |
| 2792 | target->qp_in_error) { | ||
| 2801 | shost_printk(KERN_INFO, target->scsi_host, | 2793 | shost_printk(KERN_INFO, target->scsi_host, |
| 2802 | PFX "SCSI scan failed - removing SCSI host\n"); | 2794 | PFX "SCSI scan failed - removing SCSI host\n"); |
| 2803 | srp_queue_remove_work(target); | 2795 | srp_queue_remove_work(target); |
| @@ -3146,7 +3138,7 @@ static ssize_t srp_create_target(struct device *dev, | |||
| 3146 | target_host->transportt = ib_srp_transport_template; | 3138 | target_host->transportt = ib_srp_transport_template; |
| 3147 | target_host->max_channel = 0; | 3139 | target_host->max_channel = 0; |
| 3148 | target_host->max_id = 1; | 3140 | target_host->max_id = 1; |
| 3149 | target_host->max_lun = SRP_MAX_LUN; | 3141 | target_host->max_lun = -1LL; |
| 3150 | target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb; | 3142 | target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb; |
| 3151 | 3143 | ||
| 3152 | target = host_to_target(target_host); | 3144 | target = host_to_target(target_host); |
| @@ -3172,11 +3164,11 @@ static ssize_t srp_create_target(struct device *dev, | |||
| 3172 | 3164 | ||
| 3173 | ret = srp_parse_options(buf, target); | 3165 | ret = srp_parse_options(buf, target); |
| 3174 | if (ret) | 3166 | if (ret) |
| 3175 | goto err; | 3167 | goto out; |
| 3176 | 3168 | ||
| 3177 | ret = scsi_init_shared_tag_map(target_host, target_host->can_queue); | 3169 | ret = scsi_init_shared_tag_map(target_host, target_host->can_queue); |
| 3178 | if (ret) | 3170 | if (ret) |
| 3179 | goto err; | 3171 | goto out; |
| 3180 | 3172 | ||
| 3181 | target->req_ring_size = target->queue_size - SRP_TSK_MGMT_SQ_SIZE; | 3173 | target->req_ring_size = target->queue_size - SRP_TSK_MGMT_SQ_SIZE; |
| 3182 | 3174 | ||
| @@ -3187,7 +3179,7 @@ static ssize_t srp_create_target(struct device *dev, | |||
| 3187 | be64_to_cpu(target->ioc_guid), | 3179 | be64_to_cpu(target->ioc_guid), |
| 3188 | be64_to_cpu(target->initiator_ext)); | 3180 | be64_to_cpu(target->initiator_ext)); |
| 3189 | ret = -EEXIST; | 3181 | ret = -EEXIST; |
| 3190 | goto err; | 3182 | goto out; |
| 3191 | } | 3183 | } |
| 3192 | 3184 | ||
| 3193 | if (!srp_dev->has_fmr && !srp_dev->has_fr && !target->allow_ext_sg && | 3185 | if (!srp_dev->has_fmr && !srp_dev->has_fr && !target->allow_ext_sg && |
| @@ -3208,7 +3200,7 @@ static ssize_t srp_create_target(struct device *dev, | |||
| 3208 | spin_lock_init(&target->lock); | 3200 | spin_lock_init(&target->lock); |
| 3209 | ret = ib_query_gid(ibdev, host->port, 0, &target->sgid); | 3201 | ret = ib_query_gid(ibdev, host->port, 0, &target->sgid); |
| 3210 | if (ret) | 3202 | if (ret) |
| 3211 | goto err; | 3203 | goto out; |
| 3212 | 3204 | ||
| 3213 | ret = -ENOMEM; | 3205 | ret = -ENOMEM; |
| 3214 | target->ch_count = max_t(unsigned, num_online_nodes(), | 3206 | target->ch_count = max_t(unsigned, num_online_nodes(), |
| @@ -3219,7 +3211,7 @@ static ssize_t srp_create_target(struct device *dev, | |||
| 3219 | target->ch = kcalloc(target->ch_count, sizeof(*target->ch), | 3211 | target->ch = kcalloc(target->ch_count, sizeof(*target->ch), |
| 3220 | GFP_KERNEL); | 3212 | GFP_KERNEL); |
| 3221 | if (!target->ch) | 3213 | if (!target->ch) |
| 3222 | goto err; | 3214 | goto out; |
| 3223 | 3215 | ||
| 3224 | node_idx = 0; | 3216 | node_idx = 0; |
| 3225 | for_each_online_node(node) { | 3217 | for_each_online_node(node) { |
| @@ -3315,9 +3307,6 @@ err_disconnect: | |||
| 3315 | } | 3307 | } |
| 3316 | 3308 | ||
| 3317 | kfree(target->ch); | 3309 | kfree(target->ch); |
| 3318 | |||
| 3319 | err: | ||
| 3320 | scsi_host_put(target_host); | ||
| 3321 | goto out; | 3310 | goto out; |
| 3322 | } | 3311 | } |
| 3323 | 3312 | ||
| @@ -3387,7 +3376,7 @@ static void srp_add_one(struct ib_device *device) | |||
| 3387 | struct srp_device *srp_dev; | 3376 | struct srp_device *srp_dev; |
| 3388 | struct ib_device_attr *dev_attr; | 3377 | struct ib_device_attr *dev_attr; |
| 3389 | struct srp_host *host; | 3378 | struct srp_host *host; |
| 3390 | int mr_page_shift, s, e, p; | 3379 | int mr_page_shift, p; |
| 3391 | u64 max_pages_per_mr; | 3380 | u64 max_pages_per_mr; |
| 3392 | 3381 | ||
| 3393 | dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL); | 3382 | dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL); |
| @@ -3451,15 +3440,7 @@ static void srp_add_one(struct ib_device *device) | |||
| 3451 | if (IS_ERR(srp_dev->mr)) | 3440 | if (IS_ERR(srp_dev->mr)) |
| 3452 | goto err_pd; | 3441 | goto err_pd; |
| 3453 | 3442 | ||
| 3454 | if (device->node_type == RDMA_NODE_IB_SWITCH) { | 3443 | for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) { |
| 3455 | s = 0; | ||
| 3456 | e = 0; | ||
| 3457 | } else { | ||
| 3458 | s = 1; | ||
| 3459 | e = device->phys_port_cnt; | ||
| 3460 | } | ||
| 3461 | |||
| 3462 | for (p = s; p <= e; ++p) { | ||
| 3463 | host = srp_add_port(srp_dev, p); | 3444 | host = srp_add_port(srp_dev, p); |
| 3464 | if (host) | 3445 | if (host) |
| 3465 | list_add_tail(&host->list, &srp_dev->dev_list); | 3446 | list_add_tail(&host->list, &srp_dev->dev_list); |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index a611556406ac..17ee3f80ba55 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h | |||
| @@ -54,7 +54,6 @@ enum { | |||
| 54 | SRP_DLID_REDIRECT = 2, | 54 | SRP_DLID_REDIRECT = 2, |
| 55 | SRP_STALE_CONN = 3, | 55 | SRP_STALE_CONN = 3, |
| 56 | 56 | ||
| 57 | SRP_MAX_LUN = 512, | ||
| 58 | SRP_DEF_SG_TABLESIZE = 12, | 57 | SRP_DEF_SG_TABLESIZE = 12, |
| 59 | 58 | ||
| 60 | SRP_DEFAULT_QUEUE_SIZE = 1 << 6, | 59 | SRP_DEFAULT_QUEUE_SIZE = 1 << 6, |
| @@ -170,6 +169,7 @@ struct srp_rdma_ch { | |||
| 170 | 169 | ||
| 171 | struct completion tsk_mgmt_done; | 170 | struct completion tsk_mgmt_done; |
| 172 | u8 tsk_mgmt_status; | 171 | u8 tsk_mgmt_status; |
| 172 | bool connected; | ||
| 173 | }; | 173 | }; |
| 174 | 174 | ||
| 175 | /** | 175 | /** |
| @@ -214,7 +214,6 @@ struct srp_target_port { | |||
| 214 | __be16 pkey; | 214 | __be16 pkey; |
| 215 | 215 | ||
| 216 | u32 rq_tmo_jiffies; | 216 | u32 rq_tmo_jiffies; |
| 217 | bool connected; | ||
| 218 | 217 | ||
| 219 | int zero_req_lim; | 218 | int zero_req_lim; |
| 220 | 219 | ||
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 9b84b4c0a000..60ff0a2390e5 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c | |||
| @@ -41,12 +41,12 @@ | |||
| 41 | #include <linux/string.h> | 41 | #include <linux/string.h> |
| 42 | #include <linux/delay.h> | 42 | #include <linux/delay.h> |
| 43 | #include <linux/atomic.h> | 43 | #include <linux/atomic.h> |
| 44 | #include <scsi/scsi_proto.h> | ||
| 44 | #include <scsi/scsi_tcq.h> | 45 | #include <scsi/scsi_tcq.h> |
| 45 | #include <target/configfs_macros.h> | 46 | #include <target/configfs_macros.h> |
| 46 | #include <target/target_core_base.h> | 47 | #include <target/target_core_base.h> |
| 47 | #include <target/target_core_fabric_configfs.h> | 48 | #include <target/target_core_fabric_configfs.h> |
| 48 | #include <target/target_core_fabric.h> | 49 | #include <target/target_core_fabric.h> |
| 49 | #include <target/target_core_configfs.h> | ||
| 50 | #include "ib_srpt.h" | 50 | #include "ib_srpt.h" |
| 51 | 51 | ||
| 52 | /* Name of this kernel module. */ | 52 | /* Name of this kernel module. */ |
| @@ -93,7 +93,6 @@ MODULE_PARM_DESC(srpt_service_guid, | |||
| 93 | " instead of using the node_guid of the first HCA."); | 93 | " instead of using the node_guid of the first HCA."); |
| 94 | 94 | ||
| 95 | static struct ib_client srpt_client; | 95 | static struct ib_client srpt_client; |
| 96 | static const struct target_core_fabric_ops srpt_template; | ||
| 97 | static void srpt_release_channel(struct srpt_rdma_ch *ch); | 96 | static void srpt_release_channel(struct srpt_rdma_ch *ch); |
| 98 | static int srpt_queue_status(struct se_cmd *cmd); | 97 | static int srpt_queue_status(struct se_cmd *cmd); |
| 99 | 98 | ||
| @@ -303,7 +302,7 @@ static void srpt_get_iou(struct ib_dm_mad *mad) | |||
| 303 | int i; | 302 | int i; |
| 304 | 303 | ||
| 305 | ioui = (struct ib_dm_iou_info *)mad->data; | 304 | ioui = (struct ib_dm_iou_info *)mad->data; |
| 306 | ioui->change_id = __constant_cpu_to_be16(1); | 305 | ioui->change_id = cpu_to_be16(1); |
| 307 | ioui->max_controllers = 16; | 306 | ioui->max_controllers = 16; |
| 308 | 307 | ||
| 309 | /* set present for slot 1 and empty for the rest */ | 308 | /* set present for slot 1 and empty for the rest */ |
| @@ -331,13 +330,13 @@ static void srpt_get_ioc(struct srpt_port *sport, u32 slot, | |||
| 331 | 330 | ||
| 332 | if (!slot || slot > 16) { | 331 | if (!slot || slot > 16) { |
| 333 | mad->mad_hdr.status | 332 | mad->mad_hdr.status |
| 334 | = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD); | 333 | = cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD); |
| 335 | return; | 334 | return; |
| 336 | } | 335 | } |
| 337 | 336 | ||
| 338 | if (slot > 2) { | 337 | if (slot > 2) { |
| 339 | mad->mad_hdr.status | 338 | mad->mad_hdr.status |
| 340 | = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC); | 339 | = cpu_to_be16(DM_MAD_STATUS_NO_IOC); |
| 341 | return; | 340 | return; |
| 342 | } | 341 | } |
| 343 | 342 | ||
| @@ -349,10 +348,10 @@ static void srpt_get_ioc(struct srpt_port *sport, u32 slot, | |||
| 349 | iocp->device_version = cpu_to_be16(sdev->dev_attr.hw_ver); | 348 | iocp->device_version = cpu_to_be16(sdev->dev_attr.hw_ver); |
| 350 | iocp->subsys_vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id); | 349 | iocp->subsys_vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id); |
| 351 | iocp->subsys_device_id = 0x0; | 350 | iocp->subsys_device_id = 0x0; |
| 352 | iocp->io_class = __constant_cpu_to_be16(SRP_REV16A_IB_IO_CLASS); | 351 | iocp->io_class = cpu_to_be16(SRP_REV16A_IB_IO_CLASS); |
| 353 | iocp->io_subclass = __constant_cpu_to_be16(SRP_IO_SUBCLASS); | 352 | iocp->io_subclass = cpu_to_be16(SRP_IO_SUBCLASS); |
| 354 | iocp->protocol = __constant_cpu_to_be16(SRP_PROTOCOL); | 353 | iocp->protocol = cpu_to_be16(SRP_PROTOCOL); |
| 355 | iocp->protocol_version = __constant_cpu_to_be16(SRP_PROTOCOL_VERSION); | 354 | iocp->protocol_version = cpu_to_be16(SRP_PROTOCOL_VERSION); |
| 356 | iocp->send_queue_depth = cpu_to_be16(sdev->srq_size); | 355 | iocp->send_queue_depth = cpu_to_be16(sdev->srq_size); |
| 357 | iocp->rdma_read_depth = 4; | 356 | iocp->rdma_read_depth = 4; |
| 358 | iocp->send_size = cpu_to_be32(srp_max_req_size); | 357 | iocp->send_size = cpu_to_be32(srp_max_req_size); |
| @@ -380,13 +379,13 @@ static void srpt_get_svc_entries(u64 ioc_guid, | |||
| 380 | 379 | ||
| 381 | if (!slot || slot > 16) { | 380 | if (!slot || slot > 16) { |
| 382 | mad->mad_hdr.status | 381 | mad->mad_hdr.status |
| 383 | = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD); | 382 | = cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD); |
| 384 | return; | 383 | return; |
| 385 | } | 384 | } |
| 386 | 385 | ||
| 387 | if (slot > 2 || lo > hi || hi > 1) { | 386 | if (slot > 2 || lo > hi || hi > 1) { |
| 388 | mad->mad_hdr.status | 387 | mad->mad_hdr.status |
| 389 | = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC); | 388 | = cpu_to_be16(DM_MAD_STATUS_NO_IOC); |
| 390 | return; | 389 | return; |
| 391 | } | 390 | } |
| 392 | 391 | ||
| @@ -437,7 +436,7 @@ static void srpt_mgmt_method_get(struct srpt_port *sp, struct ib_mad *rq_mad, | |||
| 437 | break; | 436 | break; |
| 438 | default: | 437 | default: |
| 439 | rsp_mad->mad_hdr.status = | 438 | rsp_mad->mad_hdr.status = |
| 440 | __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR); | 439 | cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR); |
| 441 | break; | 440 | break; |
| 442 | } | 441 | } |
| 443 | } | 442 | } |
| @@ -476,7 +475,8 @@ static void srpt_mad_recv_handler(struct ib_mad_agent *mad_agent, | |||
| 476 | rsp = ib_create_send_mad(mad_agent, mad_wc->wc->src_qp, | 475 | rsp = ib_create_send_mad(mad_agent, mad_wc->wc->src_qp, |
| 477 | mad_wc->wc->pkey_index, 0, | 476 | mad_wc->wc->pkey_index, 0, |
| 478 | IB_MGMT_DEVICE_HDR, IB_MGMT_DEVICE_DATA, | 477 | IB_MGMT_DEVICE_HDR, IB_MGMT_DEVICE_DATA, |
| 479 | GFP_KERNEL); | 478 | GFP_KERNEL, |
| 479 | IB_MGMT_BASE_VERSION); | ||
| 480 | if (IS_ERR(rsp)) | 480 | if (IS_ERR(rsp)) |
| 481 | goto err_rsp; | 481 | goto err_rsp; |
| 482 | 482 | ||
| @@ -493,11 +493,11 @@ static void srpt_mad_recv_handler(struct ib_mad_agent *mad_agent, | |||
| 493 | break; | 493 | break; |
| 494 | case IB_MGMT_METHOD_SET: | 494 | case IB_MGMT_METHOD_SET: |
| 495 | dm_mad->mad_hdr.status = | 495 | dm_mad->mad_hdr.status = |
| 496 | __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR); | 496 | cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR); |
| 497 | break; | 497 | break; |
| 498 | default: | 498 | default: |
| 499 | dm_mad->mad_hdr.status = | 499 | dm_mad->mad_hdr.status = |
| 500 | __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD); | 500 | cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD); |
| 501 | break; | 501 | break; |
| 502 | } | 502 | } |
| 503 | 503 | ||
| @@ -1334,12 +1334,12 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx) | |||
| 1334 | 1334 | ||
| 1335 | BUG_ON(ch->sess == NULL); | 1335 | BUG_ON(ch->sess == NULL); |
| 1336 | 1336 | ||
| 1337 | target_put_sess_cmd(ch->sess, &ioctx->cmd); | 1337 | target_put_sess_cmd(&ioctx->cmd); |
| 1338 | goto out; | 1338 | goto out; |
| 1339 | } | 1339 | } |
| 1340 | 1340 | ||
| 1341 | pr_debug("Aborting cmd with state %d and tag %lld\n", state, | 1341 | pr_debug("Aborting cmd with state %d and tag %lld\n", state, |
| 1342 | ioctx->tag); | 1342 | ioctx->cmd.tag); |
| 1343 | 1343 | ||
| 1344 | switch (state) { | 1344 | switch (state) { |
| 1345 | case SRPT_STATE_NEW: | 1345 | case SRPT_STATE_NEW: |
| @@ -1365,11 +1365,11 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx) | |||
| 1365 | * not been received in time. | 1365 | * not been received in time. |
| 1366 | */ | 1366 | */ |
| 1367 | srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx); | 1367 | srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx); |
| 1368 | target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); | 1368 | target_put_sess_cmd(&ioctx->cmd); |
| 1369 | break; | 1369 | break; |
| 1370 | case SRPT_STATE_MGMT_RSP_SENT: | 1370 | case SRPT_STATE_MGMT_RSP_SENT: |
| 1371 | srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); | 1371 | srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); |
| 1372 | target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); | 1372 | target_put_sess_cmd(&ioctx->cmd); |
| 1373 | break; | 1373 | break; |
| 1374 | default: | 1374 | default: |
| 1375 | WARN(1, "Unexpected command state (%d)", state); | 1375 | WARN(1, "Unexpected command state (%d)", state); |
| @@ -1387,7 +1387,6 @@ static void srpt_handle_send_err_comp(struct srpt_rdma_ch *ch, u64 wr_id) | |||
| 1387 | { | 1387 | { |
| 1388 | struct srpt_send_ioctx *ioctx; | 1388 | struct srpt_send_ioctx *ioctx; |
| 1389 | enum srpt_command_state state; | 1389 | enum srpt_command_state state; |
| 1390 | struct se_cmd *cmd; | ||
| 1391 | u32 index; | 1390 | u32 index; |
| 1392 | 1391 | ||
| 1393 | atomic_inc(&ch->sq_wr_avail); | 1392 | atomic_inc(&ch->sq_wr_avail); |
| @@ -1395,7 +1394,6 @@ static void srpt_handle_send_err_comp(struct srpt_rdma_ch *ch, u64 wr_id) | |||
| 1395 | index = idx_from_wr_id(wr_id); | 1394 | index = idx_from_wr_id(wr_id); |
| 1396 | ioctx = ch->ioctx_ring[index]; | 1395 | ioctx = ch->ioctx_ring[index]; |
| 1397 | state = srpt_get_cmd_state(ioctx); | 1396 | state = srpt_get_cmd_state(ioctx); |
| 1398 | cmd = &ioctx->cmd; | ||
| 1399 | 1397 | ||
| 1400 | WARN_ON(state != SRPT_STATE_CMD_RSP_SENT | 1398 | WARN_ON(state != SRPT_STATE_CMD_RSP_SENT |
| 1401 | && state != SRPT_STATE_MGMT_RSP_SENT | 1399 | && state != SRPT_STATE_MGMT_RSP_SENT |
| @@ -1472,10 +1470,8 @@ static void srpt_handle_rdma_err_comp(struct srpt_rdma_ch *ch, | |||
| 1472 | struct srpt_send_ioctx *ioctx, | 1470 | struct srpt_send_ioctx *ioctx, |
| 1473 | enum srpt_opcode opcode) | 1471 | enum srpt_opcode opcode) |
| 1474 | { | 1472 | { |
| 1475 | struct se_cmd *cmd; | ||
| 1476 | enum srpt_command_state state; | 1473 | enum srpt_command_state state; |
| 1477 | 1474 | ||
| 1478 | cmd = &ioctx->cmd; | ||
| 1479 | state = srpt_get_cmd_state(ioctx); | 1475 | state = srpt_get_cmd_state(ioctx); |
| 1480 | switch (opcode) { | 1476 | switch (opcode) { |
| 1481 | case SRPT_RDMA_READ_LAST: | 1477 | case SRPT_RDMA_READ_LAST: |
| @@ -1539,7 +1535,7 @@ static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch, | |||
| 1539 | memset(srp_rsp, 0, sizeof *srp_rsp); | 1535 | memset(srp_rsp, 0, sizeof *srp_rsp); |
| 1540 | srp_rsp->opcode = SRP_RSP; | 1536 | srp_rsp->opcode = SRP_RSP; |
| 1541 | srp_rsp->req_lim_delta = | 1537 | srp_rsp->req_lim_delta = |
| 1542 | __constant_cpu_to_be32(1 + atomic_xchg(&ch->req_lim_delta, 0)); | 1538 | cpu_to_be32(1 + atomic_xchg(&ch->req_lim_delta, 0)); |
| 1543 | srp_rsp->tag = tag; | 1539 | srp_rsp->tag = tag; |
| 1544 | srp_rsp->status = status; | 1540 | srp_rsp->status = status; |
| 1545 | 1541 | ||
| @@ -1589,8 +1585,8 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch, | |||
| 1589 | memset(srp_rsp, 0, sizeof *srp_rsp); | 1585 | memset(srp_rsp, 0, sizeof *srp_rsp); |
| 1590 | 1586 | ||
| 1591 | srp_rsp->opcode = SRP_RSP; | 1587 | srp_rsp->opcode = SRP_RSP; |
| 1592 | srp_rsp->req_lim_delta = __constant_cpu_to_be32(1 | 1588 | srp_rsp->req_lim_delta = |
| 1593 | + atomic_xchg(&ch->req_lim_delta, 0)); | 1589 | cpu_to_be32(1 + atomic_xchg(&ch->req_lim_delta, 0)); |
| 1594 | srp_rsp->tag = tag; | 1590 | srp_rsp->tag = tag; |
| 1595 | 1591 | ||
| 1596 | srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID; | 1592 | srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID; |
| @@ -1634,7 +1630,7 @@ static uint64_t srpt_unpack_lun(const uint8_t *lun, int len) | |||
| 1634 | switch (len) { | 1630 | switch (len) { |
| 1635 | case 8: | 1631 | case 8: |
| 1636 | if ((*((__be64 *)lun) & | 1632 | if ((*((__be64 *)lun) & |
| 1637 | __constant_cpu_to_be64(0x0000FFFFFFFFFFFFLL)) != 0) | 1633 | cpu_to_be64(0x0000FFFFFFFFFFFFLL)) != 0) |
| 1638 | goto out_err; | 1634 | goto out_err; |
| 1639 | break; | 1635 | break; |
| 1640 | case 4: | 1636 | case 4: |
| @@ -1679,7 +1675,7 @@ static int srpt_check_stop_free(struct se_cmd *cmd) | |||
| 1679 | struct srpt_send_ioctx *ioctx = container_of(cmd, | 1675 | struct srpt_send_ioctx *ioctx = container_of(cmd, |
| 1680 | struct srpt_send_ioctx, cmd); | 1676 | struct srpt_send_ioctx, cmd); |
| 1681 | 1677 | ||
| 1682 | return target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); | 1678 | return target_put_sess_cmd(&ioctx->cmd); |
| 1683 | } | 1679 | } |
| 1684 | 1680 | ||
| 1685 | /** | 1681 | /** |
| @@ -1701,7 +1697,7 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, | |||
| 1701 | 1697 | ||
| 1702 | srp_cmd = recv_ioctx->ioctx.buf; | 1698 | srp_cmd = recv_ioctx->ioctx.buf; |
| 1703 | cmd = &send_ioctx->cmd; | 1699 | cmd = &send_ioctx->cmd; |
| 1704 | send_ioctx->tag = srp_cmd->tag; | 1700 | cmd->tag = srp_cmd->tag; |
| 1705 | 1701 | ||
| 1706 | switch (srp_cmd->task_attr) { | 1702 | switch (srp_cmd->task_attr) { |
| 1707 | case SRP_CMD_SIMPLE_Q: | 1703 | case SRP_CMD_SIMPLE_Q: |
| @@ -1772,7 +1768,7 @@ static int srpt_rx_mgmt_fn_tag(struct srpt_send_ioctx *ioctx, u64 tag) | |||
| 1772 | for (i = 0; i < ch->rq_size; ++i) { | 1768 | for (i = 0; i < ch->rq_size; ++i) { |
| 1773 | target = ch->ioctx_ring[i]; | 1769 | target = ch->ioctx_ring[i]; |
| 1774 | if (target->cmd.se_lun == ioctx->cmd.se_lun && | 1770 | if (target->cmd.se_lun == ioctx->cmd.se_lun && |
| 1775 | target->tag == tag && | 1771 | target->cmd.tag == tag && |
| 1776 | srpt_get_cmd_state(target) != SRPT_STATE_DONE) { | 1772 | srpt_get_cmd_state(target) != SRPT_STATE_DONE) { |
| 1777 | ret = 0; | 1773 | ret = 0; |
| 1778 | /* now let the target core abort &target->cmd; */ | 1774 | /* now let the target core abort &target->cmd; */ |
| @@ -1831,7 +1827,7 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, | |||
| 1831 | srp_tsk->task_tag, srp_tsk->tag, ch->cm_id, ch->sess); | 1827 | srp_tsk->task_tag, srp_tsk->tag, ch->cm_id, ch->sess); |
| 1832 | 1828 | ||
| 1833 | srpt_set_cmd_state(send_ioctx, SRPT_STATE_MGMT); | 1829 | srpt_set_cmd_state(send_ioctx, SRPT_STATE_MGMT); |
| 1834 | send_ioctx->tag = srp_tsk->tag; | 1830 | send_ioctx->cmd.tag = srp_tsk->tag; |
| 1835 | tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func); | 1831 | tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func); |
| 1836 | if (tcm_tmr < 0) { | 1832 | if (tcm_tmr < 0) { |
| 1837 | send_ioctx->cmd.se_tmr_req->response = | 1833 | send_ioctx->cmd.se_tmr_req->response = |
| @@ -2080,6 +2076,7 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch) | |||
| 2080 | struct srpt_port *sport = ch->sport; | 2076 | struct srpt_port *sport = ch->sport; |
| 2081 | struct srpt_device *sdev = sport->sdev; | 2077 | struct srpt_device *sdev = sport->sdev; |
| 2082 | u32 srp_sq_size = sport->port_attrib.srp_sq_size; | 2078 | u32 srp_sq_size = sport->port_attrib.srp_sq_size; |
| 2079 | struct ib_cq_init_attr cq_attr = {}; | ||
| 2083 | int ret; | 2080 | int ret; |
| 2084 | 2081 | ||
| 2085 | WARN_ON(ch->rq_size < 1); | 2082 | WARN_ON(ch->rq_size < 1); |
| @@ -2090,8 +2087,9 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch) | |||
| 2090 | goto out; | 2087 | goto out; |
| 2091 | 2088 | ||
| 2092 | retry: | 2089 | retry: |
| 2090 | cq_attr.cqe = ch->rq_size + srp_sq_size; | ||
| 2093 | ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch, | 2091 | ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch, |
| 2094 | ch->rq_size + srp_sq_size, 0); | 2092 | &cq_attr); |
| 2095 | if (IS_ERR(ch->cq)) { | 2093 | if (IS_ERR(ch->cq)) { |
| 2096 | ret = PTR_ERR(ch->cq); | 2094 | ret = PTR_ERR(ch->cq); |
| 2097 | pr_err("failed to create CQ cqe= %d ret= %d\n", | 2095 | pr_err("failed to create CQ cqe= %d ret= %d\n", |
| @@ -2176,12 +2174,9 @@ static void srpt_destroy_ch_ib(struct srpt_rdma_ch *ch) | |||
| 2176 | */ | 2174 | */ |
| 2177 | static void __srpt_close_ch(struct srpt_rdma_ch *ch) | 2175 | static void __srpt_close_ch(struct srpt_rdma_ch *ch) |
| 2178 | { | 2176 | { |
| 2179 | struct srpt_device *sdev; | ||
| 2180 | enum rdma_ch_state prev_state; | 2177 | enum rdma_ch_state prev_state; |
| 2181 | unsigned long flags; | 2178 | unsigned long flags; |
| 2182 | 2179 | ||
| 2183 | sdev = ch->sport->sdev; | ||
| 2184 | |||
| 2185 | spin_lock_irqsave(&ch->spinlock, flags); | 2180 | spin_lock_irqsave(&ch->spinlock, flags); |
| 2186 | prev_state = ch->state; | 2181 | prev_state = ch->state; |
| 2187 | switch (prev_state) { | 2182 | switch (prev_state) { |
| @@ -2454,8 +2449,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, | |||
| 2454 | } | 2449 | } |
| 2455 | 2450 | ||
| 2456 | if (it_iu_len > srp_max_req_size || it_iu_len < 64) { | 2451 | if (it_iu_len > srp_max_req_size || it_iu_len < 64) { |
| 2457 | rej->reason = __constant_cpu_to_be32( | 2452 | rej->reason = cpu_to_be32( |
| 2458 | SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE); | 2453 | SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE); |
| 2459 | ret = -EINVAL; | 2454 | ret = -EINVAL; |
| 2460 | pr_err("rejected SRP_LOGIN_REQ because its" | 2455 | pr_err("rejected SRP_LOGIN_REQ because its" |
| 2461 | " length (%d bytes) is out of range (%d .. %d)\n", | 2456 | " length (%d bytes) is out of range (%d .. %d)\n", |
| @@ -2464,8 +2459,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, | |||
| 2464 | } | 2459 | } |
| 2465 | 2460 | ||
| 2466 | if (!sport->enabled) { | 2461 | if (!sport->enabled) { |
| 2467 | rej->reason = __constant_cpu_to_be32( | 2462 | rej->reason = cpu_to_be32( |
| 2468 | SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); | 2463 | SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); |
| 2469 | ret = -EINVAL; | 2464 | ret = -EINVAL; |
| 2470 | pr_err("rejected SRP_LOGIN_REQ because the target port" | 2465 | pr_err("rejected SRP_LOGIN_REQ because the target port" |
| 2471 | " has not yet been enabled\n"); | 2466 | " has not yet been enabled\n"); |
| @@ -2510,8 +2505,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, | |||
| 2510 | if (*(__be64 *)req->target_port_id != cpu_to_be64(srpt_service_guid) | 2505 | if (*(__be64 *)req->target_port_id != cpu_to_be64(srpt_service_guid) |
| 2511 | || *(__be64 *)(req->target_port_id + 8) != | 2506 | || *(__be64 *)(req->target_port_id + 8) != |
| 2512 | cpu_to_be64(srpt_service_guid)) { | 2507 | cpu_to_be64(srpt_service_guid)) { |
| 2513 | rej->reason = __constant_cpu_to_be32( | 2508 | rej->reason = cpu_to_be32( |
| 2514 | SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL); | 2509 | SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL); |
| 2515 | ret = -ENOMEM; | 2510 | ret = -ENOMEM; |
| 2516 | pr_err("rejected SRP_LOGIN_REQ because it" | 2511 | pr_err("rejected SRP_LOGIN_REQ because it" |
| 2517 | " has an invalid target port identifier.\n"); | 2512 | " has an invalid target port identifier.\n"); |
| @@ -2520,8 +2515,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, | |||
| 2520 | 2515 | ||
| 2521 | ch = kzalloc(sizeof *ch, GFP_KERNEL); | 2516 | ch = kzalloc(sizeof *ch, GFP_KERNEL); |
| 2522 | if (!ch) { | 2517 | if (!ch) { |
| 2523 | rej->reason = __constant_cpu_to_be32( | 2518 | rej->reason = cpu_to_be32( |
| 2524 | SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); | 2519 | SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); |
| 2525 | pr_err("rejected SRP_LOGIN_REQ because no memory.\n"); | 2520 | pr_err("rejected SRP_LOGIN_REQ because no memory.\n"); |
| 2526 | ret = -ENOMEM; | 2521 | ret = -ENOMEM; |
| 2527 | goto reject; | 2522 | goto reject; |
| @@ -2557,8 +2552,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, | |||
| 2557 | 2552 | ||
| 2558 | ret = srpt_create_ch_ib(ch); | 2553 | ret = srpt_create_ch_ib(ch); |
| 2559 | if (ret) { | 2554 | if (ret) { |
| 2560 | rej->reason = __constant_cpu_to_be32( | 2555 | rej->reason = cpu_to_be32( |
| 2561 | SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); | 2556 | SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); |
| 2562 | pr_err("rejected SRP_LOGIN_REQ because creating" | 2557 | pr_err("rejected SRP_LOGIN_REQ because creating" |
| 2563 | " a new RDMA channel failed.\n"); | 2558 | " a new RDMA channel failed.\n"); |
| 2564 | goto free_ring; | 2559 | goto free_ring; |
| @@ -2566,8 +2561,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, | |||
| 2566 | 2561 | ||
| 2567 | ret = srpt_ch_qp_rtr(ch, ch->qp); | 2562 | ret = srpt_ch_qp_rtr(ch, ch->qp); |
| 2568 | if (ret) { | 2563 | if (ret) { |
| 2569 | rej->reason = __constant_cpu_to_be32( | 2564 | rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); |
| 2570 | SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); | ||
| 2571 | pr_err("rejected SRP_LOGIN_REQ because enabling" | 2565 | pr_err("rejected SRP_LOGIN_REQ because enabling" |
| 2572 | " RTR failed (error code = %d)\n", ret); | 2566 | " RTR failed (error code = %d)\n", ret); |
| 2573 | goto destroy_ib; | 2567 | goto destroy_ib; |
| @@ -2585,15 +2579,15 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, | |||
| 2585 | if (!nacl) { | 2579 | if (!nacl) { |
| 2586 | pr_info("Rejected login because no ACL has been" | 2580 | pr_info("Rejected login because no ACL has been" |
| 2587 | " configured yet for initiator %s.\n", ch->sess_name); | 2581 | " configured yet for initiator %s.\n", ch->sess_name); |
| 2588 | rej->reason = __constant_cpu_to_be32( | 2582 | rej->reason = cpu_to_be32( |
| 2589 | SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED); | 2583 | SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED); |
| 2590 | goto destroy_ib; | 2584 | goto destroy_ib; |
| 2591 | } | 2585 | } |
| 2592 | 2586 | ||
| 2593 | ch->sess = transport_init_session(TARGET_PROT_NORMAL); | 2587 | ch->sess = transport_init_session(TARGET_PROT_NORMAL); |
| 2594 | if (IS_ERR(ch->sess)) { | 2588 | if (IS_ERR(ch->sess)) { |
| 2595 | rej->reason = __constant_cpu_to_be32( | 2589 | rej->reason = cpu_to_be32( |
| 2596 | SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); | 2590 | SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); |
| 2597 | pr_debug("Failed to create session\n"); | 2591 | pr_debug("Failed to create session\n"); |
| 2598 | goto deregister_session; | 2592 | goto deregister_session; |
| 2599 | } | 2593 | } |
| @@ -2609,8 +2603,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, | |||
| 2609 | rsp->max_it_iu_len = req->req_it_iu_len; | 2603 | rsp->max_it_iu_len = req->req_it_iu_len; |
| 2610 | rsp->max_ti_iu_len = req->req_it_iu_len; | 2604 | rsp->max_ti_iu_len = req->req_it_iu_len; |
| 2611 | ch->max_ti_iu_len = it_iu_len; | 2605 | ch->max_ti_iu_len = it_iu_len; |
| 2612 | rsp->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT | 2606 | rsp->buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
| 2613 | | SRP_BUF_FORMAT_INDIRECT); | 2607 | | SRP_BUF_FORMAT_INDIRECT); |
| 2614 | rsp->req_lim_delta = cpu_to_be32(ch->rq_size); | 2608 | rsp->req_lim_delta = cpu_to_be32(ch->rq_size); |
| 2615 | atomic_set(&ch->req_lim, ch->rq_size); | 2609 | atomic_set(&ch->req_lim, ch->rq_size); |
| 2616 | atomic_set(&ch->req_lim_delta, 0); | 2610 | atomic_set(&ch->req_lim_delta, 0); |
| @@ -2660,8 +2654,8 @@ free_ch: | |||
| 2660 | reject: | 2654 | reject: |
| 2661 | rej->opcode = SRP_LOGIN_REJ; | 2655 | rej->opcode = SRP_LOGIN_REJ; |
| 2662 | rej->tag = req->tag; | 2656 | rej->tag = req->tag; |
| 2663 | rej->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT | 2657 | rej->buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
| 2664 | | SRP_BUF_FORMAT_INDIRECT); | 2658 | | SRP_BUF_FORMAT_INDIRECT); |
| 2665 | 2659 | ||
| 2666 | ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED, NULL, 0, | 2660 | ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED, NULL, 0, |
| 2667 | (void *)rej, sizeof *rej); | 2661 | (void *)rej, sizeof *rej); |
| @@ -2979,7 +2973,7 @@ static int srpt_write_pending(struct se_cmd *se_cmd) | |||
| 2979 | case CH_DRAINING: | 2973 | case CH_DRAINING: |
| 2980 | case CH_RELEASING: | 2974 | case CH_RELEASING: |
| 2981 | pr_debug("cmd with tag %lld: channel disconnecting\n", | 2975 | pr_debug("cmd with tag %lld: channel disconnecting\n", |
| 2982 | ioctx->tag); | 2976 | ioctx->cmd.tag); |
| 2983 | srpt_set_cmd_state(ioctx, SRPT_STATE_DATA_IN); | 2977 | srpt_set_cmd_state(ioctx, SRPT_STATE_DATA_IN); |
| 2984 | ret = -EINVAL; | 2978 | ret = -EINVAL; |
| 2985 | goto out; | 2979 | goto out; |
| @@ -3054,27 +3048,27 @@ static void srpt_queue_response(struct se_cmd *cmd) | |||
| 3054 | ret = srpt_xfer_data(ch, ioctx); | 3048 | ret = srpt_xfer_data(ch, ioctx); |
| 3055 | if (ret) { | 3049 | if (ret) { |
| 3056 | pr_err("xfer_data failed for tag %llu\n", | 3050 | pr_err("xfer_data failed for tag %llu\n", |
| 3057 | ioctx->tag); | 3051 | ioctx->cmd.tag); |
| 3058 | return; | 3052 | return; |
| 3059 | } | 3053 | } |
| 3060 | } | 3054 | } |
| 3061 | 3055 | ||
| 3062 | if (state != SRPT_STATE_MGMT) | 3056 | if (state != SRPT_STATE_MGMT) |
| 3063 | resp_len = srpt_build_cmd_rsp(ch, ioctx, ioctx->tag, | 3057 | resp_len = srpt_build_cmd_rsp(ch, ioctx, ioctx->cmd.tag, |
| 3064 | cmd->scsi_status); | 3058 | cmd->scsi_status); |
| 3065 | else { | 3059 | else { |
| 3066 | srp_tm_status | 3060 | srp_tm_status |
| 3067 | = tcm_to_srp_tsk_mgmt_status(cmd->se_tmr_req->response); | 3061 | = tcm_to_srp_tsk_mgmt_status(cmd->se_tmr_req->response); |
| 3068 | resp_len = srpt_build_tskmgmt_rsp(ch, ioctx, srp_tm_status, | 3062 | resp_len = srpt_build_tskmgmt_rsp(ch, ioctx, srp_tm_status, |
| 3069 | ioctx->tag); | 3063 | ioctx->cmd.tag); |
| 3070 | } | 3064 | } |
| 3071 | ret = srpt_post_send(ch, ioctx, resp_len); | 3065 | ret = srpt_post_send(ch, ioctx, resp_len); |
| 3072 | if (ret) { | 3066 | if (ret) { |
| 3073 | pr_err("sending cmd response failed for tag %llu\n", | 3067 | pr_err("sending cmd response failed for tag %llu\n", |
| 3074 | ioctx->tag); | 3068 | ioctx->cmd.tag); |
| 3075 | srpt_unmap_sg_to_ib_sge(ch, ioctx); | 3069 | srpt_unmap_sg_to_ib_sge(ch, ioctx); |
| 3076 | srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); | 3070 | srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); |
| 3077 | target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); | 3071 | target_put_sess_cmd(&ioctx->cmd); |
| 3078 | } | 3072 | } |
| 3079 | } | 3073 | } |
| 3080 | 3074 | ||
| @@ -3394,11 +3388,6 @@ static char *srpt_get_fabric_name(void) | |||
| 3394 | return "srpt"; | 3388 | return "srpt"; |
| 3395 | } | 3389 | } |
| 3396 | 3390 | ||
| 3397 | static u8 srpt_get_fabric_proto_ident(struct se_portal_group *se_tpg) | ||
| 3398 | { | ||
| 3399 | return SCSI_TRANSPORTID_PROTOCOLID_SRP; | ||
| 3400 | } | ||
| 3401 | |||
| 3402 | static char *srpt_get_fabric_wwn(struct se_portal_group *tpg) | 3391 | static char *srpt_get_fabric_wwn(struct se_portal_group *tpg) |
| 3403 | { | 3392 | { |
| 3404 | struct srpt_port *sport = container_of(tpg, struct srpt_port, port_tpg_1); | 3393 | struct srpt_port *sport = container_of(tpg, struct srpt_port, port_tpg_1); |
| @@ -3411,69 +3400,6 @@ static u16 srpt_get_tag(struct se_portal_group *tpg) | |||
| 3411 | return 1; | 3400 | return 1; |
| 3412 | } | 3401 | } |
| 3413 | 3402 | ||
| 3414 | static u32 srpt_get_default_depth(struct se_portal_group *se_tpg) | ||
| 3415 | { | ||
| 3416 | return 1; | ||
| 3417 | } | ||
| 3418 | |||
| 3419 | static u32 srpt_get_pr_transport_id(struct se_portal_group *se_tpg, | ||
| 3420 | struct se_node_acl *se_nacl, | ||
| 3421 | struct t10_pr_registration *pr_reg, | ||
| 3422 | int *format_code, unsigned char *buf) | ||
| 3423 | { | ||
| 3424 | struct srpt_node_acl *nacl; | ||
| 3425 | struct spc_rdma_transport_id *tr_id; | ||
| 3426 | |||
| 3427 | nacl = container_of(se_nacl, struct srpt_node_acl, nacl); | ||
| 3428 | tr_id = (void *)buf; | ||
| 3429 | tr_id->protocol_identifier = SCSI_TRANSPORTID_PROTOCOLID_SRP; | ||
| 3430 | memcpy(tr_id->i_port_id, nacl->i_port_id, sizeof(tr_id->i_port_id)); | ||
| 3431 | return sizeof(*tr_id); | ||
| 3432 | } | ||
| 3433 | |||
| 3434 | static u32 srpt_get_pr_transport_id_len(struct se_portal_group *se_tpg, | ||
| 3435 | struct se_node_acl *se_nacl, | ||
| 3436 | struct t10_pr_registration *pr_reg, | ||
| 3437 | int *format_code) | ||
| 3438 | { | ||
| 3439 | *format_code = 0; | ||
| 3440 | return sizeof(struct spc_rdma_transport_id); | ||
| 3441 | } | ||
| 3442 | |||
| 3443 | static char *srpt_parse_pr_out_transport_id(struct se_portal_group *se_tpg, | ||
| 3444 | const char *buf, u32 *out_tid_len, | ||
| 3445 | char **port_nexus_ptr) | ||
| 3446 | { | ||
| 3447 | struct spc_rdma_transport_id *tr_id; | ||
| 3448 | |||
| 3449 | *port_nexus_ptr = NULL; | ||
| 3450 | *out_tid_len = sizeof(struct spc_rdma_transport_id); | ||
| 3451 | tr_id = (void *)buf; | ||
| 3452 | return (char *)tr_id->i_port_id; | ||
| 3453 | } | ||
| 3454 | |||
| 3455 | static struct se_node_acl *srpt_alloc_fabric_acl(struct se_portal_group *se_tpg) | ||
| 3456 | { | ||
| 3457 | struct srpt_node_acl *nacl; | ||
| 3458 | |||
| 3459 | nacl = kzalloc(sizeof(struct srpt_node_acl), GFP_KERNEL); | ||
| 3460 | if (!nacl) { | ||
| 3461 | pr_err("Unable to allocate struct srpt_node_acl\n"); | ||
| 3462 | return NULL; | ||
| 3463 | } | ||
| 3464 | |||
| 3465 | return &nacl->nacl; | ||
| 3466 | } | ||
| 3467 | |||
| 3468 | static void srpt_release_fabric_acl(struct se_portal_group *se_tpg, | ||
| 3469 | struct se_node_acl *se_nacl) | ||
| 3470 | { | ||
| 3471 | struct srpt_node_acl *nacl; | ||
| 3472 | |||
| 3473 | nacl = container_of(se_nacl, struct srpt_node_acl, nacl); | ||
| 3474 | kfree(nacl); | ||
| 3475 | } | ||
| 3476 | |||
| 3477 | static u32 srpt_tpg_get_inst_index(struct se_portal_group *se_tpg) | 3403 | static u32 srpt_tpg_get_inst_index(struct se_portal_group *se_tpg) |
| 3478 | { | 3404 | { |
| 3479 | return 1; | 3405 | return 1; |
| @@ -3547,14 +3473,6 @@ static void srpt_set_default_node_attrs(struct se_node_acl *nacl) | |||
| 3547 | { | 3473 | { |
| 3548 | } | 3474 | } |
| 3549 | 3475 | ||
| 3550 | static u32 srpt_get_task_tag(struct se_cmd *se_cmd) | ||
| 3551 | { | ||
| 3552 | struct srpt_send_ioctx *ioctx; | ||
| 3553 | |||
| 3554 | ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd); | ||
| 3555 | return ioctx->tag; | ||
| 3556 | } | ||
| 3557 | |||
| 3558 | /* Note: only used from inside debug printk's by the TCM core. */ | 3476 | /* Note: only used from inside debug printk's by the TCM core. */ |
| 3559 | static int srpt_get_tcm_cmd_state(struct se_cmd *se_cmd) | 3477 | static int srpt_get_tcm_cmd_state(struct se_cmd *se_cmd) |
| 3560 | { | 3478 | { |
| @@ -3597,40 +3515,19 @@ out: | |||
| 3597 | * configfs callback function invoked for | 3515 | * configfs callback function invoked for |
| 3598 | * mkdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id | 3516 | * mkdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id |
| 3599 | */ | 3517 | */ |
| 3600 | static struct se_node_acl *srpt_make_nodeacl(struct se_portal_group *tpg, | 3518 | static int srpt_init_nodeacl(struct se_node_acl *se_nacl, const char *name) |
| 3601 | struct config_group *group, | ||
| 3602 | const char *name) | ||
| 3603 | { | 3519 | { |
| 3604 | struct srpt_port *sport = container_of(tpg, struct srpt_port, port_tpg_1); | 3520 | struct srpt_port *sport = |
| 3605 | struct se_node_acl *se_nacl, *se_nacl_new; | 3521 | container_of(se_nacl->se_tpg, struct srpt_port, port_tpg_1); |
| 3606 | struct srpt_node_acl *nacl; | 3522 | struct srpt_node_acl *nacl = |
| 3607 | int ret = 0; | 3523 | container_of(se_nacl, struct srpt_node_acl, nacl); |
| 3608 | u32 nexus_depth = 1; | ||
| 3609 | u8 i_port_id[16]; | 3524 | u8 i_port_id[16]; |
| 3610 | 3525 | ||
| 3611 | if (srpt_parse_i_port_id(i_port_id, name) < 0) { | 3526 | if (srpt_parse_i_port_id(i_port_id, name) < 0) { |
| 3612 | pr_err("invalid initiator port ID %s\n", name); | 3527 | pr_err("invalid initiator port ID %s\n", name); |
| 3613 | ret = -EINVAL; | 3528 | return -EINVAL; |
| 3614 | goto err; | ||
| 3615 | } | 3529 | } |
| 3616 | 3530 | ||
| 3617 | se_nacl_new = srpt_alloc_fabric_acl(tpg); | ||
| 3618 | if (!se_nacl_new) { | ||
| 3619 | ret = -ENOMEM; | ||
| 3620 | goto err; | ||
| 3621 | } | ||
| 3622 | /* | ||
| 3623 | * nacl_new may be released by core_tpg_add_initiator_node_acl() | ||
| 3624 | * when converting a node ACL from demo mode to explict | ||
| 3625 | */ | ||
| 3626 | se_nacl = core_tpg_add_initiator_node_acl(tpg, se_nacl_new, name, | ||
| 3627 | nexus_depth); | ||
| 3628 | if (IS_ERR(se_nacl)) { | ||
| 3629 | ret = PTR_ERR(se_nacl); | ||
| 3630 | goto err; | ||
| 3631 | } | ||
| 3632 | /* Locate our struct srpt_node_acl and set sdev and i_port_id. */ | ||
| 3633 | nacl = container_of(se_nacl, struct srpt_node_acl, nacl); | ||
| 3634 | memcpy(&nacl->i_port_id[0], &i_port_id[0], 16); | 3531 | memcpy(&nacl->i_port_id[0], &i_port_id[0], 16); |
| 3635 | nacl->sport = sport; | 3532 | nacl->sport = sport; |
| 3636 | 3533 | ||
| @@ -3638,29 +3535,22 @@ static struct se_node_acl *srpt_make_nodeacl(struct se_portal_group *tpg, | |||
| 3638 | list_add_tail(&nacl->list, &sport->port_acl_list); | 3535 | list_add_tail(&nacl->list, &sport->port_acl_list); |
| 3639 | spin_unlock_irq(&sport->port_acl_lock); | 3536 | spin_unlock_irq(&sport->port_acl_lock); |
| 3640 | 3537 | ||
| 3641 | return se_nacl; | 3538 | return 0; |
| 3642 | err: | ||
| 3643 | return ERR_PTR(ret); | ||
| 3644 | } | 3539 | } |
| 3645 | 3540 | ||
| 3646 | /* | 3541 | /* |
| 3647 | * configfs callback function invoked for | 3542 | * configfs callback function invoked for |
| 3648 | * rmdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id | 3543 | * rmdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id |
| 3649 | */ | 3544 | */ |
| 3650 | static void srpt_drop_nodeacl(struct se_node_acl *se_nacl) | 3545 | static void srpt_cleanup_nodeacl(struct se_node_acl *se_nacl) |
| 3651 | { | 3546 | { |
| 3652 | struct srpt_node_acl *nacl; | 3547 | struct srpt_node_acl *nacl = |
| 3653 | struct srpt_device *sdev; | 3548 | container_of(se_nacl, struct srpt_node_acl, nacl); |
| 3654 | struct srpt_port *sport; | 3549 | struct srpt_port *sport = nacl->sport; |
| 3655 | 3550 | ||
| 3656 | nacl = container_of(se_nacl, struct srpt_node_acl, nacl); | ||
| 3657 | sport = nacl->sport; | ||
| 3658 | sdev = sport->sdev; | ||
| 3659 | spin_lock_irq(&sport->port_acl_lock); | 3551 | spin_lock_irq(&sport->port_acl_lock); |
| 3660 | list_del(&nacl->list); | 3552 | list_del(&nacl->list); |
| 3661 | spin_unlock_irq(&sport->port_acl_lock); | 3553 | spin_unlock_irq(&sport->port_acl_lock); |
| 3662 | core_tpg_del_initiator_node_acl(&sport->port_tpg_1, se_nacl, 1); | ||
| 3663 | srpt_release_fabric_acl(NULL, se_nacl); | ||
| 3664 | } | 3554 | } |
| 3665 | 3555 | ||
| 3666 | static ssize_t srpt_tpg_attrib_show_srp_max_rdma_size( | 3556 | static ssize_t srpt_tpg_attrib_show_srp_max_rdma_size( |
| @@ -3845,8 +3735,7 @@ static struct se_portal_group *srpt_make_tpg(struct se_wwn *wwn, | |||
| 3845 | int res; | 3735 | int res; |
| 3846 | 3736 | ||
| 3847 | /* Initialize sport->port_wwn and sport->port_tpg_1 */ | 3737 | /* Initialize sport->port_wwn and sport->port_tpg_1 */ |
| 3848 | res = core_tpg_register(&srpt_template, &sport->port_wwn, | 3738 | res = core_tpg_register(&sport->port_wwn, &sport->port_tpg_1, SCSI_PROTOCOL_SRP); |
| 3849 | &sport->port_tpg_1, sport, TRANSPORT_TPG_TYPE_NORMAL); | ||
| 3850 | if (res) | 3739 | if (res) |
| 3851 | return ERR_PTR(res); | 3740 | return ERR_PTR(res); |
| 3852 | 3741 | ||
| @@ -3916,20 +3805,14 @@ static struct configfs_attribute *srpt_wwn_attrs[] = { | |||
| 3916 | static const struct target_core_fabric_ops srpt_template = { | 3805 | static const struct target_core_fabric_ops srpt_template = { |
| 3917 | .module = THIS_MODULE, | 3806 | .module = THIS_MODULE, |
| 3918 | .name = "srpt", | 3807 | .name = "srpt", |
| 3808 | .node_acl_size = sizeof(struct srpt_node_acl), | ||
| 3919 | .get_fabric_name = srpt_get_fabric_name, | 3809 | .get_fabric_name = srpt_get_fabric_name, |
| 3920 | .get_fabric_proto_ident = srpt_get_fabric_proto_ident, | ||
| 3921 | .tpg_get_wwn = srpt_get_fabric_wwn, | 3810 | .tpg_get_wwn = srpt_get_fabric_wwn, |
| 3922 | .tpg_get_tag = srpt_get_tag, | 3811 | .tpg_get_tag = srpt_get_tag, |
| 3923 | .tpg_get_default_depth = srpt_get_default_depth, | ||
| 3924 | .tpg_get_pr_transport_id = srpt_get_pr_transport_id, | ||
| 3925 | .tpg_get_pr_transport_id_len = srpt_get_pr_transport_id_len, | ||
| 3926 | .tpg_parse_pr_out_transport_id = srpt_parse_pr_out_transport_id, | ||
| 3927 | .tpg_check_demo_mode = srpt_check_false, | 3812 | .tpg_check_demo_mode = srpt_check_false, |
| 3928 | .tpg_check_demo_mode_cache = srpt_check_true, | 3813 | .tpg_check_demo_mode_cache = srpt_check_true, |
| 3929 | .tpg_check_demo_mode_write_protect = srpt_check_true, | 3814 | .tpg_check_demo_mode_write_protect = srpt_check_true, |
| 3930 | .tpg_check_prod_mode_write_protect = srpt_check_false, | 3815 | .tpg_check_prod_mode_write_protect = srpt_check_false, |
| 3931 | .tpg_alloc_fabric_acl = srpt_alloc_fabric_acl, | ||
| 3932 | .tpg_release_fabric_acl = srpt_release_fabric_acl, | ||
| 3933 | .tpg_get_inst_index = srpt_tpg_get_inst_index, | 3816 | .tpg_get_inst_index = srpt_tpg_get_inst_index, |
| 3934 | .release_cmd = srpt_release_cmd, | 3817 | .release_cmd = srpt_release_cmd, |
| 3935 | .check_stop_free = srpt_check_stop_free, | 3818 | .check_stop_free = srpt_check_stop_free, |
| @@ -3940,7 +3823,6 @@ static const struct target_core_fabric_ops srpt_template = { | |||
| 3940 | .write_pending = srpt_write_pending, | 3823 | .write_pending = srpt_write_pending, |
| 3941 | .write_pending_status = srpt_write_pending_status, | 3824 | .write_pending_status = srpt_write_pending_status, |
| 3942 | .set_default_node_attributes = srpt_set_default_node_attrs, | 3825 | .set_default_node_attributes = srpt_set_default_node_attrs, |
| 3943 | .get_task_tag = srpt_get_task_tag, | ||
| 3944 | .get_cmd_state = srpt_get_tcm_cmd_state, | 3826 | .get_cmd_state = srpt_get_tcm_cmd_state, |
| 3945 | .queue_data_in = srpt_queue_data_in, | 3827 | .queue_data_in = srpt_queue_data_in, |
| 3946 | .queue_status = srpt_queue_status, | 3828 | .queue_status = srpt_queue_status, |
| @@ -3954,12 +3836,8 @@ static const struct target_core_fabric_ops srpt_template = { | |||
| 3954 | .fabric_drop_wwn = srpt_drop_tport, | 3836 | .fabric_drop_wwn = srpt_drop_tport, |
| 3955 | .fabric_make_tpg = srpt_make_tpg, | 3837 | .fabric_make_tpg = srpt_make_tpg, |
| 3956 | .fabric_drop_tpg = srpt_drop_tpg, | 3838 | .fabric_drop_tpg = srpt_drop_tpg, |
| 3957 | .fabric_post_link = NULL, | 3839 | .fabric_init_nodeacl = srpt_init_nodeacl, |
| 3958 | .fabric_pre_unlink = NULL, | 3840 | .fabric_cleanup_nodeacl = srpt_cleanup_nodeacl, |
| 3959 | .fabric_make_np = NULL, | ||
| 3960 | .fabric_drop_np = NULL, | ||
| 3961 | .fabric_make_nodeacl = srpt_make_nodeacl, | ||
| 3962 | .fabric_drop_nodeacl = srpt_drop_nodeacl, | ||
| 3963 | 3841 | ||
| 3964 | .tfc_wwn_attrs = srpt_wwn_attrs, | 3842 | .tfc_wwn_attrs = srpt_wwn_attrs, |
| 3965 | .tfc_tpg_base_attrs = srpt_tpg_attrs, | 3843 | .tfc_tpg_base_attrs = srpt_tpg_attrs, |
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h index 3dae156905de..21f8df67522a 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.h +++ b/drivers/infiniband/ulp/srpt/ib_srpt.h | |||
| @@ -238,14 +238,13 @@ struct srpt_send_ioctx { | |||
| 238 | bool rdma_aborted; | 238 | bool rdma_aborted; |
| 239 | struct se_cmd cmd; | 239 | struct se_cmd cmd; |
| 240 | struct completion tx_done; | 240 | struct completion tx_done; |
| 241 | u64 tag; | ||
| 242 | int sg_cnt; | 241 | int sg_cnt; |
| 243 | int mapped_sg_count; | 242 | int mapped_sg_count; |
| 244 | u16 n_rdma_ius; | 243 | u16 n_rdma_ius; |
| 245 | u8 n_rdma; | 244 | u8 n_rdma; |
| 246 | u8 n_rbuf; | 245 | u8 n_rbuf; |
| 247 | bool queue_status_only; | 246 | bool queue_status_only; |
| 248 | u8 sense_data[SCSI_SENSE_BUFFERSIZE]; | 247 | u8 sense_data[TRANSPORT_SENSE_BUFFER]; |
| 249 | }; | 248 | }; |
| 250 | 249 | ||
| 251 | /** | 250 | /** |
| @@ -410,34 +409,16 @@ struct srpt_device { | |||
| 410 | 409 | ||
| 411 | /** | 410 | /** |
| 412 | * struct srpt_node_acl - Per-initiator ACL data (managed via configfs). | 411 | * struct srpt_node_acl - Per-initiator ACL data (managed via configfs). |
| 412 | * @nacl: Target core node ACL information. | ||
| 413 | * @i_port_id: 128-bit SRP initiator port ID. | 413 | * @i_port_id: 128-bit SRP initiator port ID. |
| 414 | * @sport: port information. | 414 | * @sport: port information. |
| 415 | * @nacl: Target core node ACL information. | ||
| 416 | * @list: Element of the per-HCA ACL list. | 415 | * @list: Element of the per-HCA ACL list. |
| 417 | */ | 416 | */ |
| 418 | struct srpt_node_acl { | 417 | struct srpt_node_acl { |
| 418 | struct se_node_acl nacl; | ||
| 419 | u8 i_port_id[16]; | 419 | u8 i_port_id[16]; |
| 420 | struct srpt_port *sport; | 420 | struct srpt_port *sport; |
| 421 | struct se_node_acl nacl; | ||
| 422 | struct list_head list; | 421 | struct list_head list; |
| 423 | }; | 422 | }; |
| 424 | 423 | ||
| 425 | /* | ||
| 426 | * SRP-releated SCSI persistent reservation definitions. | ||
| 427 | * | ||
| 428 | * See also SPC4r28, section 7.6.1 (Protocol specific parameters introduction). | ||
| 429 | * See also SPC4r28, section 7.6.4.5 (TransportID for initiator ports using | ||
| 430 | * SCSI over an RDMA interface). | ||
| 431 | */ | ||
| 432 | |||
| 433 | enum { | ||
| 434 | SCSI_TRANSPORTID_PROTOCOLID_SRP = 4, | ||
| 435 | }; | ||
| 436 | |||
| 437 | struct spc_rdma_transport_id { | ||
| 438 | uint8_t protocol_identifier; | ||
| 439 | uint8_t reserved[7]; | ||
| 440 | uint8_t i_port_id[16]; | ||
| 441 | }; | ||
| 442 | |||
| 443 | #endif /* IB_SRPT_H */ | 424 | #endif /* IB_SRPT_H */ |
