diff options
Diffstat (limited to 'drivers/infiniband')
29 files changed, 362 insertions, 193 deletions
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index d294bbc42f09..1205e8027829 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <net/arp.h> | 35 | #include <net/arp.h> |
36 | #include <net/neighbour.h> | 36 | #include <net/neighbour.h> |
37 | #include <net/route.h> | 37 | #include <net/route.h> |
38 | #include <net/netevent.h> | ||
38 | #include <rdma/ib_addr.h> | 39 | #include <rdma/ib_addr.h> |
39 | 40 | ||
40 | MODULE_AUTHOR("Sean Hefty"); | 41 | MODULE_AUTHOR("Sean Hefty"); |
@@ -326,25 +327,22 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr) | |||
326 | } | 327 | } |
327 | EXPORT_SYMBOL(rdma_addr_cancel); | 328 | EXPORT_SYMBOL(rdma_addr_cancel); |
328 | 329 | ||
329 | static int addr_arp_recv(struct sk_buff *skb, struct net_device *dev, | 330 | static int netevent_callback(struct notifier_block *self, unsigned long event, |
330 | struct packet_type *pkt, struct net_device *orig_dev) | 331 | void *ctx) |
331 | { | 332 | { |
332 | struct arphdr *arp_hdr; | 333 | if (event == NETEVENT_NEIGH_UPDATE) { |
334 | struct neighbour *neigh = ctx; | ||
333 | 335 | ||
334 | arp_hdr = (struct arphdr *) skb->nh.raw; | 336 | if (neigh->dev->type == ARPHRD_INFINIBAND && |
335 | 337 | (neigh->nud_state & NUD_VALID)) { | |
336 | if (arp_hdr->ar_op == htons(ARPOP_REQUEST) || | 338 | set_timeout(jiffies); |
337 | arp_hdr->ar_op == htons(ARPOP_REPLY)) | 339 | } |
338 | set_timeout(jiffies); | 340 | } |
339 | |||
340 | kfree_skb(skb); | ||
341 | return 0; | 341 | return 0; |
342 | } | 342 | } |
343 | 343 | ||
344 | static struct packet_type addr_arp = { | 344 | static struct notifier_block nb = { |
345 | .type = __constant_htons(ETH_P_ARP), | 345 | .notifier_call = netevent_callback |
346 | .func = addr_arp_recv, | ||
347 | .af_packet_priv = (void*) 1, | ||
348 | }; | 346 | }; |
349 | 347 | ||
350 | static int addr_init(void) | 348 | static int addr_init(void) |
@@ -353,13 +351,13 @@ static int addr_init(void) | |||
353 | if (!addr_wq) | 351 | if (!addr_wq) |
354 | return -ENOMEM; | 352 | return -ENOMEM; |
355 | 353 | ||
356 | dev_add_pack(&addr_arp); | 354 | register_netevent_notifier(&nb); |
357 | return 0; | 355 | return 0; |
358 | } | 356 | } |
359 | 357 | ||
360 | static void addr_cleanup(void) | 358 | static void addr_cleanup(void) |
361 | { | 359 | { |
362 | dev_remove_pack(&addr_arp); | 360 | unregister_netevent_notifier(&nb); |
363 | destroy_workqueue(addr_wq); | 361 | destroy_workqueue(addr_wq); |
364 | } | 362 | } |
365 | 363 | ||
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index e05ca2cdc73f..75313ade2e0d 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c | |||
@@ -301,7 +301,8 @@ static void ib_cache_event(struct ib_event_handler *handler, | |||
301 | event->event == IB_EVENT_PORT_ACTIVE || | 301 | event->event == IB_EVENT_PORT_ACTIVE || |
302 | event->event == IB_EVENT_LID_CHANGE || | 302 | event->event == IB_EVENT_LID_CHANGE || |
303 | event->event == IB_EVENT_PKEY_CHANGE || | 303 | event->event == IB_EVENT_PKEY_CHANGE || |
304 | event->event == IB_EVENT_SM_CHANGE) { | 304 | event->event == IB_EVENT_SM_CHANGE || |
305 | event->event == IB_EVENT_CLIENT_REREGISTER) { | ||
305 | work = kmalloc(sizeof *work, GFP_ATOMIC); | 306 | work = kmalloc(sizeof *work, GFP_ATOMIC); |
306 | if (work) { | 307 | if (work) { |
307 | INIT_WORK(&work->work, ib_cache_task, work); | 308 | INIT_WORK(&work->work, ib_cache_task, work); |
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 3f6705f3083a..0de335b7bfc2 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
@@ -701,7 +701,7 @@ static void cm_reset_to_idle(struct cm_id_private *cm_id_priv) | |||
701 | } | 701 | } |
702 | } | 702 | } |
703 | 703 | ||
704 | void ib_destroy_cm_id(struct ib_cm_id *cm_id) | 704 | static void cm_destroy_id(struct ib_cm_id *cm_id, int err) |
705 | { | 705 | { |
706 | struct cm_id_private *cm_id_priv; | 706 | struct cm_id_private *cm_id_priv; |
707 | struct cm_work *work; | 707 | struct cm_work *work; |
@@ -735,12 +735,22 @@ retest: | |||
735 | sizeof cm_id_priv->av.port->cm_dev->ca_guid, | 735 | sizeof cm_id_priv->av.port->cm_dev->ca_guid, |
736 | NULL, 0); | 736 | NULL, 0); |
737 | break; | 737 | break; |
738 | case IB_CM_REQ_RCVD: | ||
739 | if (err == -ENOMEM) { | ||
740 | /* Do not reject to allow future retries. */ | ||
741 | cm_reset_to_idle(cm_id_priv); | ||
742 | spin_unlock_irqrestore(&cm_id_priv->lock, flags); | ||
743 | } else { | ||
744 | spin_unlock_irqrestore(&cm_id_priv->lock, flags); | ||
745 | ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED, | ||
746 | NULL, 0, NULL, 0); | ||
747 | } | ||
748 | break; | ||
738 | case IB_CM_MRA_REQ_RCVD: | 749 | case IB_CM_MRA_REQ_RCVD: |
739 | case IB_CM_REP_SENT: | 750 | case IB_CM_REP_SENT: |
740 | case IB_CM_MRA_REP_RCVD: | 751 | case IB_CM_MRA_REP_RCVD: |
741 | ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg); | 752 | ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg); |
742 | /* Fall through */ | 753 | /* Fall through */ |
743 | case IB_CM_REQ_RCVD: | ||
744 | case IB_CM_MRA_REQ_SENT: | 754 | case IB_CM_MRA_REQ_SENT: |
745 | case IB_CM_REP_RCVD: | 755 | case IB_CM_REP_RCVD: |
746 | case IB_CM_MRA_REP_SENT: | 756 | case IB_CM_MRA_REP_SENT: |
@@ -775,6 +785,11 @@ retest: | |||
775 | kfree(cm_id_priv->private_data); | 785 | kfree(cm_id_priv->private_data); |
776 | kfree(cm_id_priv); | 786 | kfree(cm_id_priv); |
777 | } | 787 | } |
788 | |||
789 | void ib_destroy_cm_id(struct ib_cm_id *cm_id) | ||
790 | { | ||
791 | cm_destroy_id(cm_id, 0); | ||
792 | } | ||
778 | EXPORT_SYMBOL(ib_destroy_cm_id); | 793 | EXPORT_SYMBOL(ib_destroy_cm_id); |
779 | 794 | ||
780 | int ib_cm_listen(struct ib_cm_id *cm_id, __be64 service_id, __be64 service_mask, | 795 | int ib_cm_listen(struct ib_cm_id *cm_id, __be64 service_id, __be64 service_mask, |
@@ -960,8 +975,10 @@ int ib_send_cm_req(struct ib_cm_id *cm_id, | |||
960 | 975 | ||
961 | cm_id_priv->timewait_info = cm_create_timewait_info(cm_id_priv-> | 976 | cm_id_priv->timewait_info = cm_create_timewait_info(cm_id_priv-> |
962 | id.local_id); | 977 | id.local_id); |
963 | if (IS_ERR(cm_id_priv->timewait_info)) | 978 | if (IS_ERR(cm_id_priv->timewait_info)) { |
979 | ret = PTR_ERR(cm_id_priv->timewait_info); | ||
964 | goto out; | 980 | goto out; |
981 | } | ||
965 | 982 | ||
966 | ret = cm_init_av_by_path(param->primary_path, &cm_id_priv->av); | 983 | ret = cm_init_av_by_path(param->primary_path, &cm_id_priv->av); |
967 | if (ret) | 984 | if (ret) |
@@ -1163,7 +1180,7 @@ static void cm_process_work(struct cm_id_private *cm_id_priv, | |||
1163 | } | 1180 | } |
1164 | cm_deref_id(cm_id_priv); | 1181 | cm_deref_id(cm_id_priv); |
1165 | if (ret) | 1182 | if (ret) |
1166 | ib_destroy_cm_id(&cm_id_priv->id); | 1183 | cm_destroy_id(&cm_id_priv->id, ret); |
1167 | } | 1184 | } |
1168 | 1185 | ||
1169 | static void cm_format_mra(struct cm_mra_msg *mra_msg, | 1186 | static void cm_format_mra(struct cm_mra_msg *mra_msg, |
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 863f64befc7c..d6f99d5720fc 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
@@ -262,14 +262,14 @@ static void cma_detach_from_dev(struct rdma_id_private *id_priv) | |||
262 | static int cma_acquire_ib_dev(struct rdma_id_private *id_priv) | 262 | static int cma_acquire_ib_dev(struct rdma_id_private *id_priv) |
263 | { | 263 | { |
264 | struct cma_device *cma_dev; | 264 | struct cma_device *cma_dev; |
265 | union ib_gid *gid; | 265 | union ib_gid gid; |
266 | int ret = -ENODEV; | 266 | int ret = -ENODEV; |
267 | 267 | ||
268 | gid = ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr); | 268 | ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid), |
269 | 269 | ||
270 | mutex_lock(&lock); | 270 | mutex_lock(&lock); |
271 | list_for_each_entry(cma_dev, &dev_list, list) { | 271 | list_for_each_entry(cma_dev, &dev_list, list) { |
272 | ret = ib_find_cached_gid(cma_dev->device, gid, | 272 | ret = ib_find_cached_gid(cma_dev->device, &gid, |
273 | &id_priv->id.port_num, NULL); | 273 | &id_priv->id.port_num, NULL); |
274 | if (!ret) { | 274 | if (!ret) { |
275 | cma_attach_to_dev(id_priv, cma_dev); | 275 | cma_attach_to_dev(id_priv, cma_dev); |
@@ -812,6 +812,7 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) | |||
812 | cma_modify_qp_err(&id_priv->id); | 812 | cma_modify_qp_err(&id_priv->id); |
813 | status = ib_event->param.rej_rcvd.reason; | 813 | status = ib_event->param.rej_rcvd.reason; |
814 | event = RDMA_CM_EVENT_REJECTED; | 814 | event = RDMA_CM_EVENT_REJECTED; |
815 | private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE; | ||
815 | break; | 816 | break; |
816 | default: | 817 | default: |
817 | printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d", | 818 | printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d", |
@@ -1134,8 +1135,8 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, | |||
1134 | struct ib_sa_path_rec path_rec; | 1135 | struct ib_sa_path_rec path_rec; |
1135 | 1136 | ||
1136 | memset(&path_rec, 0, sizeof path_rec); | 1137 | memset(&path_rec, 0, sizeof path_rec); |
1137 | path_rec.sgid = *ib_addr_get_sgid(addr); | 1138 | ib_addr_get_sgid(addr, &path_rec.sgid); |
1138 | path_rec.dgid = *ib_addr_get_dgid(addr); | 1139 | ib_addr_get_dgid(addr, &path_rec.dgid); |
1139 | path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(addr)); | 1140 | path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(addr)); |
1140 | path_rec.numb_path = 1; | 1141 | path_rec.numb_path = 1; |
1141 | 1142 | ||
@@ -1263,7 +1264,7 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv) | |||
1263 | { | 1264 | { |
1264 | struct cma_device *cma_dev; | 1265 | struct cma_device *cma_dev; |
1265 | struct ib_port_attr port_attr; | 1266 | struct ib_port_attr port_attr; |
1266 | union ib_gid *gid; | 1267 | union ib_gid gid; |
1267 | u16 pkey; | 1268 | u16 pkey; |
1268 | int ret; | 1269 | int ret; |
1269 | u8 p; | 1270 | u8 p; |
@@ -1284,8 +1285,7 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv) | |||
1284 | } | 1285 | } |
1285 | 1286 | ||
1286 | port_found: | 1287 | port_found: |
1287 | gid = ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr); | 1288 | ret = ib_get_cached_gid(cma_dev->device, p, 0, &gid); |
1288 | ret = ib_get_cached_gid(cma_dev->device, p, 0, gid); | ||
1289 | if (ret) | 1289 | if (ret) |
1290 | goto out; | 1290 | goto out; |
1291 | 1291 | ||
@@ -1293,6 +1293,7 @@ port_found: | |||
1293 | if (ret) | 1293 | if (ret) |
1294 | goto out; | 1294 | goto out; |
1295 | 1295 | ||
1296 | ib_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid); | ||
1296 | ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey); | 1297 | ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey); |
1297 | id_priv->id.port_num = p; | 1298 | id_priv->id.port_num = p; |
1298 | cma_attach_to_dev(id_priv, cma_dev); | 1299 | cma_attach_to_dev(id_priv, cma_dev); |
@@ -1339,6 +1340,7 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv) | |||
1339 | { | 1340 | { |
1340 | struct cma_work *work; | 1341 | struct cma_work *work; |
1341 | struct sockaddr_in *src_in, *dst_in; | 1342 | struct sockaddr_in *src_in, *dst_in; |
1343 | union ib_gid gid; | ||
1342 | int ret; | 1344 | int ret; |
1343 | 1345 | ||
1344 | work = kzalloc(sizeof *work, GFP_KERNEL); | 1346 | work = kzalloc(sizeof *work, GFP_KERNEL); |
@@ -1351,8 +1353,8 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv) | |||
1351 | goto err; | 1353 | goto err; |
1352 | } | 1354 | } |
1353 | 1355 | ||
1354 | ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr, | 1356 | ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid); |
1355 | ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr)); | 1357 | ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid); |
1356 | 1358 | ||
1357 | if (cma_zero_addr(&id_priv->id.route.addr.src_addr)) { | 1359 | if (cma_zero_addr(&id_priv->id.route.addr.src_addr)) { |
1358 | src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr; | 1360 | src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr; |
diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c index 615fe9cc6c56..86a3b2d401db 100644 --- a/drivers/infiniband/core/fmr_pool.c +++ b/drivers/infiniband/core/fmr_pool.c | |||
@@ -426,7 +426,7 @@ EXPORT_SYMBOL(ib_flush_fmr_pool); | |||
426 | struct ib_pool_fmr *ib_fmr_pool_map_phys(struct ib_fmr_pool *pool_handle, | 426 | struct ib_pool_fmr *ib_fmr_pool_map_phys(struct ib_fmr_pool *pool_handle, |
427 | u64 *page_list, | 427 | u64 *page_list, |
428 | int list_len, | 428 | int list_len, |
429 | u64 *io_virtual_address) | 429 | u64 io_virtual_address) |
430 | { | 430 | { |
431 | struct ib_fmr_pool *pool = pool_handle; | 431 | struct ib_fmr_pool *pool = pool_handle; |
432 | struct ib_pool_fmr *fmr; | 432 | struct ib_pool_fmr *fmr; |
@@ -440,7 +440,7 @@ struct ib_pool_fmr *ib_fmr_pool_map_phys(struct ib_fmr_pool *pool_handle, | |||
440 | fmr = ib_fmr_cache_lookup(pool, | 440 | fmr = ib_fmr_cache_lookup(pool, |
441 | page_list, | 441 | page_list, |
442 | list_len, | 442 | list_len, |
443 | *io_virtual_address); | 443 | io_virtual_address); |
444 | if (fmr) { | 444 | if (fmr) { |
445 | /* found in cache */ | 445 | /* found in cache */ |
446 | ++fmr->ref_count; | 446 | ++fmr->ref_count; |
@@ -464,7 +464,7 @@ struct ib_pool_fmr *ib_fmr_pool_map_phys(struct ib_fmr_pool *pool_handle, | |||
464 | spin_unlock_irqrestore(&pool->pool_lock, flags); | 464 | spin_unlock_irqrestore(&pool->pool_lock, flags); |
465 | 465 | ||
466 | result = ib_map_phys_fmr(fmr->fmr, page_list, list_len, | 466 | result = ib_map_phys_fmr(fmr->fmr, page_list, list_len, |
467 | *io_virtual_address); | 467 | io_virtual_address); |
468 | 468 | ||
469 | if (result) { | 469 | if (result) { |
470 | spin_lock_irqsave(&pool->pool_lock, flags); | 470 | spin_lock_irqsave(&pool->pool_lock, flags); |
@@ -481,7 +481,7 @@ struct ib_pool_fmr *ib_fmr_pool_map_phys(struct ib_fmr_pool *pool_handle, | |||
481 | fmr->ref_count = 1; | 481 | fmr->ref_count = 1; |
482 | 482 | ||
483 | if (pool->cache_bucket) { | 483 | if (pool->cache_bucket) { |
484 | fmr->io_virtual_address = *io_virtual_address; | 484 | fmr->io_virtual_address = io_virtual_address; |
485 | fmr->page_list_len = list_len; | 485 | fmr->page_list_len = list_len; |
486 | memcpy(fmr->page_list, page_list, list_len * sizeof(*page_list)); | 486 | memcpy(fmr->page_list, page_list, list_len * sizeof(*page_list)); |
487 | 487 | ||
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 5ed4dab52a6f..1c3cfbbe6a97 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c | |||
@@ -167,6 +167,15 @@ static int is_vendor_method_in_use( | |||
167 | return 0; | 167 | return 0; |
168 | } | 168 | } |
169 | 169 | ||
170 | int ib_response_mad(struct ib_mad *mad) | ||
171 | { | ||
172 | return ((mad->mad_hdr.method & IB_MGMT_METHOD_RESP) || | ||
173 | (mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS) || | ||
174 | ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_BM) && | ||
175 | (mad->mad_hdr.attr_mod & IB_BM_ATTR_MOD_RESP))); | ||
176 | } | ||
177 | EXPORT_SYMBOL(ib_response_mad); | ||
178 | |||
170 | /* | 179 | /* |
171 | * ib_register_mad_agent - Register to send/receive MADs | 180 | * ib_register_mad_agent - Register to send/receive MADs |
172 | */ | 181 | */ |
@@ -570,13 +579,6 @@ int ib_unregister_mad_agent(struct ib_mad_agent *mad_agent) | |||
570 | } | 579 | } |
571 | EXPORT_SYMBOL(ib_unregister_mad_agent); | 580 | EXPORT_SYMBOL(ib_unregister_mad_agent); |
572 | 581 | ||
573 | static inline int response_mad(struct ib_mad *mad) | ||
574 | { | ||
575 | /* Trap represses are responses although response bit is reset */ | ||
576 | return ((mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS) || | ||
577 | (mad->mad_hdr.method & IB_MGMT_METHOD_RESP)); | ||
578 | } | ||
579 | |||
580 | static void dequeue_mad(struct ib_mad_list_head *mad_list) | 582 | static void dequeue_mad(struct ib_mad_list_head *mad_list) |
581 | { | 583 | { |
582 | struct ib_mad_queue *mad_queue; | 584 | struct ib_mad_queue *mad_queue; |
@@ -723,7 +725,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, | |||
723 | switch (ret) | 725 | switch (ret) |
724 | { | 726 | { |
725 | case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY: | 727 | case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY: |
726 | if (response_mad(&mad_priv->mad.mad) && | 728 | if (ib_response_mad(&mad_priv->mad.mad) && |
727 | mad_agent_priv->agent.recv_handler) { | 729 | mad_agent_priv->agent.recv_handler) { |
728 | local->mad_priv = mad_priv; | 730 | local->mad_priv = mad_priv; |
729 | local->recv_mad_agent = mad_agent_priv; | 731 | local->recv_mad_agent = mad_agent_priv; |
@@ -1551,7 +1553,7 @@ find_mad_agent(struct ib_mad_port_private *port_priv, | |||
1551 | unsigned long flags; | 1553 | unsigned long flags; |
1552 | 1554 | ||
1553 | spin_lock_irqsave(&port_priv->reg_lock, flags); | 1555 | spin_lock_irqsave(&port_priv->reg_lock, flags); |
1554 | if (response_mad(mad)) { | 1556 | if (ib_response_mad(mad)) { |
1555 | u32 hi_tid; | 1557 | u32 hi_tid; |
1556 | struct ib_mad_agent_private *entry; | 1558 | struct ib_mad_agent_private *entry; |
1557 | 1559 | ||
@@ -1799,7 +1801,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, | |||
1799 | } | 1801 | } |
1800 | 1802 | ||
1801 | /* Complete corresponding request */ | 1803 | /* Complete corresponding request */ |
1802 | if (response_mad(mad_recv_wc->recv_buf.mad)) { | 1804 | if (ib_response_mad(mad_recv_wc->recv_buf.mad)) { |
1803 | spin_lock_irqsave(&mad_agent_priv->lock, flags); | 1805 | spin_lock_irqsave(&mad_agent_priv->lock, flags); |
1804 | mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); | 1806 | mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); |
1805 | if (!mad_send_wr) { | 1807 | if (!mad_send_wr) { |
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index e911c99ff843..d6b84226bba7 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c | |||
@@ -405,7 +405,8 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event | |||
405 | event->event == IB_EVENT_PORT_ACTIVE || | 405 | event->event == IB_EVENT_PORT_ACTIVE || |
406 | event->event == IB_EVENT_LID_CHANGE || | 406 | event->event == IB_EVENT_LID_CHANGE || |
407 | event->event == IB_EVENT_PKEY_CHANGE || | 407 | event->event == IB_EVENT_PKEY_CHANGE || |
408 | event->event == IB_EVENT_SM_CHANGE) { | 408 | event->event == IB_EVENT_SM_CHANGE || |
409 | event->event == IB_EVENT_CLIENT_REREGISTER) { | ||
409 | struct ib_sa_device *sa_dev; | 410 | struct ib_sa_device *sa_dev; |
410 | sa_dev = container_of(handler, typeof(*sa_dev), event_handler); | 411 | sa_dev = container_of(handler, typeof(*sa_dev), event_handler); |
411 | 412 | ||
@@ -488,13 +489,13 @@ static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent) | |||
488 | spin_unlock_irqrestore(&tid_lock, flags); | 489 | spin_unlock_irqrestore(&tid_lock, flags); |
489 | } | 490 | } |
490 | 491 | ||
491 | static int send_mad(struct ib_sa_query *query, int timeout_ms) | 492 | static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask) |
492 | { | 493 | { |
493 | unsigned long flags; | 494 | unsigned long flags; |
494 | int ret, id; | 495 | int ret, id; |
495 | 496 | ||
496 | retry: | 497 | retry: |
497 | if (!idr_pre_get(&query_idr, GFP_ATOMIC)) | 498 | if (!idr_pre_get(&query_idr, gfp_mask)) |
498 | return -ENOMEM; | 499 | return -ENOMEM; |
499 | spin_lock_irqsave(&idr_lock, flags); | 500 | spin_lock_irqsave(&idr_lock, flags); |
500 | ret = idr_get_new(&query_idr, query, &id); | 501 | ret = idr_get_new(&query_idr, query, &id); |
@@ -630,7 +631,7 @@ int ib_sa_path_rec_get(struct ib_device *device, u8 port_num, | |||
630 | 631 | ||
631 | *sa_query = &query->sa_query; | 632 | *sa_query = &query->sa_query; |
632 | 633 | ||
633 | ret = send_mad(&query->sa_query, timeout_ms); | 634 | ret = send_mad(&query->sa_query, timeout_ms, gfp_mask); |
634 | if (ret < 0) | 635 | if (ret < 0) |
635 | goto err2; | 636 | goto err2; |
636 | 637 | ||
@@ -752,7 +753,7 @@ int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method, | |||
752 | 753 | ||
753 | *sa_query = &query->sa_query; | 754 | *sa_query = &query->sa_query; |
754 | 755 | ||
755 | ret = send_mad(&query->sa_query, timeout_ms); | 756 | ret = send_mad(&query->sa_query, timeout_ms, gfp_mask); |
756 | if (ret < 0) | 757 | if (ret < 0) |
757 | goto err2; | 758 | goto err2; |
758 | 759 | ||
@@ -844,7 +845,7 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num, | |||
844 | 845 | ||
845 | *sa_query = &query->sa_query; | 846 | *sa_query = &query->sa_query; |
846 | 847 | ||
847 | ret = send_mad(&query->sa_query, timeout_ms); | 848 | ret = send_mad(&query->sa_query, timeout_ms, gfp_mask); |
848 | if (ret < 0) | 849 | if (ret < 0) |
849 | goto err2; | 850 | goto err2; |
850 | 851 | ||
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index afe70a549c2f..1273f8807e84 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c | |||
@@ -112,8 +112,10 @@ struct ib_umad_device { | |||
112 | struct ib_umad_file { | 112 | struct ib_umad_file { |
113 | struct ib_umad_port *port; | 113 | struct ib_umad_port *port; |
114 | struct list_head recv_list; | 114 | struct list_head recv_list; |
115 | struct list_head send_list; | ||
115 | struct list_head port_list; | 116 | struct list_head port_list; |
116 | spinlock_t recv_lock; | 117 | spinlock_t recv_lock; |
118 | spinlock_t send_lock; | ||
117 | wait_queue_head_t recv_wait; | 119 | wait_queue_head_t recv_wait; |
118 | struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS]; | 120 | struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS]; |
119 | int agents_dead; | 121 | int agents_dead; |
@@ -177,12 +179,21 @@ static int queue_packet(struct ib_umad_file *file, | |||
177 | return ret; | 179 | return ret; |
178 | } | 180 | } |
179 | 181 | ||
182 | static void dequeue_send(struct ib_umad_file *file, | ||
183 | struct ib_umad_packet *packet) | ||
184 | { | ||
185 | spin_lock_irq(&file->send_lock); | ||
186 | list_del(&packet->list); | ||
187 | spin_unlock_irq(&file->send_lock); | ||
188 | } | ||
189 | |||
180 | static void send_handler(struct ib_mad_agent *agent, | 190 | static void send_handler(struct ib_mad_agent *agent, |
181 | struct ib_mad_send_wc *send_wc) | 191 | struct ib_mad_send_wc *send_wc) |
182 | { | 192 | { |
183 | struct ib_umad_file *file = agent->context; | 193 | struct ib_umad_file *file = agent->context; |
184 | struct ib_umad_packet *packet = send_wc->send_buf->context[0]; | 194 | struct ib_umad_packet *packet = send_wc->send_buf->context[0]; |
185 | 195 | ||
196 | dequeue_send(file, packet); | ||
186 | ib_destroy_ah(packet->msg->ah); | 197 | ib_destroy_ah(packet->msg->ah); |
187 | ib_free_send_mad(packet->msg); | 198 | ib_free_send_mad(packet->msg); |
188 | 199 | ||
@@ -370,6 +381,51 @@ static int copy_rmpp_mad(struct ib_mad_send_buf *msg, const char __user *buf) | |||
370 | return 0; | 381 | return 0; |
371 | } | 382 | } |
372 | 383 | ||
384 | static int same_destination(struct ib_user_mad_hdr *hdr1, | ||
385 | struct ib_user_mad_hdr *hdr2) | ||
386 | { | ||
387 | if (!hdr1->grh_present && !hdr2->grh_present) | ||
388 | return (hdr1->lid == hdr2->lid); | ||
389 | |||
390 | if (hdr1->grh_present && hdr2->grh_present) | ||
391 | return !memcmp(hdr1->gid, hdr2->gid, 16); | ||
392 | |||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | static int is_duplicate(struct ib_umad_file *file, | ||
397 | struct ib_umad_packet *packet) | ||
398 | { | ||
399 | struct ib_umad_packet *sent_packet; | ||
400 | struct ib_mad_hdr *sent_hdr, *hdr; | ||
401 | |||
402 | hdr = (struct ib_mad_hdr *) packet->mad.data; | ||
403 | list_for_each_entry(sent_packet, &file->send_list, list) { | ||
404 | sent_hdr = (struct ib_mad_hdr *) sent_packet->mad.data; | ||
405 | |||
406 | if ((hdr->tid != sent_hdr->tid) || | ||
407 | (hdr->mgmt_class != sent_hdr->mgmt_class)) | ||
408 | continue; | ||
409 | |||
410 | /* | ||
411 | * No need to be overly clever here. If two new operations have | ||
412 | * the same TID, reject the second as a duplicate. This is more | ||
413 | * restrictive than required by the spec. | ||
414 | */ | ||
415 | if (!ib_response_mad((struct ib_mad *) hdr)) { | ||
416 | if (!ib_response_mad((struct ib_mad *) sent_hdr)) | ||
417 | return 1; | ||
418 | continue; | ||
419 | } else if (!ib_response_mad((struct ib_mad *) sent_hdr)) | ||
420 | continue; | ||
421 | |||
422 | if (same_destination(&packet->mad.hdr, &sent_packet->mad.hdr)) | ||
423 | return 1; | ||
424 | } | ||
425 | |||
426 | return 0; | ||
427 | } | ||
428 | |||
373 | static ssize_t ib_umad_write(struct file *filp, const char __user *buf, | 429 | static ssize_t ib_umad_write(struct file *filp, const char __user *buf, |
374 | size_t count, loff_t *pos) | 430 | size_t count, loff_t *pos) |
375 | { | 431 | { |
@@ -379,7 +435,6 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, | |||
379 | struct ib_ah_attr ah_attr; | 435 | struct ib_ah_attr ah_attr; |
380 | struct ib_ah *ah; | 436 | struct ib_ah *ah; |
381 | struct ib_rmpp_mad *rmpp_mad; | 437 | struct ib_rmpp_mad *rmpp_mad; |
382 | u8 method; | ||
383 | __be64 *tid; | 438 | __be64 *tid; |
384 | int ret, data_len, hdr_len, copy_offset, rmpp_active; | 439 | int ret, data_len, hdr_len, copy_offset, rmpp_active; |
385 | 440 | ||
@@ -473,28 +528,36 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, | |||
473 | } | 528 | } |
474 | 529 | ||
475 | /* | 530 | /* |
476 | * If userspace is generating a request that will generate a | 531 | * Set the high-order part of the transaction ID to make MADs from |
477 | * response, we need to make sure the high-order part of the | 532 | * different agents unique, and allow routing responses back to the |
478 | * transaction ID matches the agent being used to send the | 533 | * original requestor. |
479 | * MAD. | ||
480 | */ | 534 | */ |
481 | method = ((struct ib_mad_hdr *) packet->msg->mad)->method; | 535 | if (!ib_response_mad(packet->msg->mad)) { |
482 | |||
483 | if (!(method & IB_MGMT_METHOD_RESP) && | ||
484 | method != IB_MGMT_METHOD_TRAP_REPRESS && | ||
485 | method != IB_MGMT_METHOD_SEND) { | ||
486 | tid = &((struct ib_mad_hdr *) packet->msg->mad)->tid; | 536 | tid = &((struct ib_mad_hdr *) packet->msg->mad)->tid; |
487 | *tid = cpu_to_be64(((u64) agent->hi_tid) << 32 | | 537 | *tid = cpu_to_be64(((u64) agent->hi_tid) << 32 | |
488 | (be64_to_cpup(tid) & 0xffffffff)); | 538 | (be64_to_cpup(tid) & 0xffffffff)); |
539 | rmpp_mad->mad_hdr.tid = *tid; | ||
540 | } | ||
541 | |||
542 | spin_lock_irq(&file->send_lock); | ||
543 | ret = is_duplicate(file, packet); | ||
544 | if (!ret) | ||
545 | list_add_tail(&packet->list, &file->send_list); | ||
546 | spin_unlock_irq(&file->send_lock); | ||
547 | if (ret) { | ||
548 | ret = -EINVAL; | ||
549 | goto err_msg; | ||
489 | } | 550 | } |
490 | 551 | ||
491 | ret = ib_post_send_mad(packet->msg, NULL); | 552 | ret = ib_post_send_mad(packet->msg, NULL); |
492 | if (ret) | 553 | if (ret) |
493 | goto err_msg; | 554 | goto err_send; |
494 | 555 | ||
495 | up_read(&file->port->mutex); | 556 | up_read(&file->port->mutex); |
496 | return count; | 557 | return count; |
497 | 558 | ||
559 | err_send: | ||
560 | dequeue_send(file, packet); | ||
498 | err_msg: | 561 | err_msg: |
499 | ib_free_send_mad(packet->msg); | 562 | ib_free_send_mad(packet->msg); |
500 | err_ah: | 563 | err_ah: |
@@ -657,7 +720,9 @@ static int ib_umad_open(struct inode *inode, struct file *filp) | |||
657 | } | 720 | } |
658 | 721 | ||
659 | spin_lock_init(&file->recv_lock); | 722 | spin_lock_init(&file->recv_lock); |
723 | spin_lock_init(&file->send_lock); | ||
660 | INIT_LIST_HEAD(&file->recv_list); | 724 | INIT_LIST_HEAD(&file->recv_list); |
725 | INIT_LIST_HEAD(&file->send_list); | ||
661 | init_waitqueue_head(&file->recv_wait); | 726 | init_waitqueue_head(&file->recv_wait); |
662 | 727 | ||
663 | file->port = port; | 728 | file->port = port; |
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index bb9bee56a824..102a59c033ff 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/kref.h> | 42 | #include <linux/kref.h> |
43 | #include <linux/idr.h> | 43 | #include <linux/idr.h> |
44 | #include <linux/mutex.h> | 44 | #include <linux/mutex.h> |
45 | #include <linux/completion.h> | ||
45 | 46 | ||
46 | #include <rdma/ib_verbs.h> | 47 | #include <rdma/ib_verbs.h> |
47 | #include <rdma/ib_user_verbs.h> | 48 | #include <rdma/ib_user_verbs.h> |
@@ -69,6 +70,7 @@ | |||
69 | 70 | ||
70 | struct ib_uverbs_device { | 71 | struct ib_uverbs_device { |
71 | struct kref ref; | 72 | struct kref ref; |
73 | struct completion comp; | ||
72 | int devnum; | 74 | int devnum; |
73 | struct cdev *dev; | 75 | struct cdev *dev; |
74 | struct class_device *class_dev; | 76 | struct class_device *class_dev; |
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index bdf5d5098190..30923eb68ec7 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
@@ -42,6 +42,13 @@ | |||
42 | 42 | ||
43 | #include "uverbs.h" | 43 | #include "uverbs.h" |
44 | 44 | ||
45 | static struct lock_class_key pd_lock_key; | ||
46 | static struct lock_class_key mr_lock_key; | ||
47 | static struct lock_class_key cq_lock_key; | ||
48 | static struct lock_class_key qp_lock_key; | ||
49 | static struct lock_class_key ah_lock_key; | ||
50 | static struct lock_class_key srq_lock_key; | ||
51 | |||
45 | #define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \ | 52 | #define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \ |
46 | do { \ | 53 | do { \ |
47 | (udata)->inbuf = (void __user *) (ibuf); \ | 54 | (udata)->inbuf = (void __user *) (ibuf); \ |
@@ -76,12 +83,13 @@ | |||
76 | */ | 83 | */ |
77 | 84 | ||
78 | static void init_uobj(struct ib_uobject *uobj, u64 user_handle, | 85 | static void init_uobj(struct ib_uobject *uobj, u64 user_handle, |
79 | struct ib_ucontext *context) | 86 | struct ib_ucontext *context, struct lock_class_key *key) |
80 | { | 87 | { |
81 | uobj->user_handle = user_handle; | 88 | uobj->user_handle = user_handle; |
82 | uobj->context = context; | 89 | uobj->context = context; |
83 | kref_init(&uobj->ref); | 90 | kref_init(&uobj->ref); |
84 | init_rwsem(&uobj->mutex); | 91 | init_rwsem(&uobj->mutex); |
92 | lockdep_set_class(&uobj->mutex, key); | ||
85 | uobj->live = 0; | 93 | uobj->live = 0; |
86 | } | 94 | } |
87 | 95 | ||
@@ -470,7 +478,7 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file, | |||
470 | if (!uobj) | 478 | if (!uobj) |
471 | return -ENOMEM; | 479 | return -ENOMEM; |
472 | 480 | ||
473 | init_uobj(uobj, 0, file->ucontext); | 481 | init_uobj(uobj, 0, file->ucontext, &pd_lock_key); |
474 | down_write(&uobj->mutex); | 482 | down_write(&uobj->mutex); |
475 | 483 | ||
476 | pd = file->device->ib_dev->alloc_pd(file->device->ib_dev, | 484 | pd = file->device->ib_dev->alloc_pd(file->device->ib_dev, |
@@ -591,7 +599,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, | |||
591 | if (!obj) | 599 | if (!obj) |
592 | return -ENOMEM; | 600 | return -ENOMEM; |
593 | 601 | ||
594 | init_uobj(&obj->uobject, 0, file->ucontext); | 602 | init_uobj(&obj->uobject, 0, file->ucontext, &mr_lock_key); |
595 | down_write(&obj->uobject.mutex); | 603 | down_write(&obj->uobject.mutex); |
596 | 604 | ||
597 | /* | 605 | /* |
@@ -770,7 +778,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, | |||
770 | if (!obj) | 778 | if (!obj) |
771 | return -ENOMEM; | 779 | return -ENOMEM; |
772 | 780 | ||
773 | init_uobj(&obj->uobject, cmd.user_handle, file->ucontext); | 781 | init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &cq_lock_key); |
774 | down_write(&obj->uobject.mutex); | 782 | down_write(&obj->uobject.mutex); |
775 | 783 | ||
776 | if (cmd.comp_channel >= 0) { | 784 | if (cmd.comp_channel >= 0) { |
@@ -1051,13 +1059,14 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, | |||
1051 | if (!obj) | 1059 | if (!obj) |
1052 | return -ENOMEM; | 1060 | return -ENOMEM; |
1053 | 1061 | ||
1054 | init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext); | 1062 | init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key); |
1055 | down_write(&obj->uevent.uobject.mutex); | 1063 | down_write(&obj->uevent.uobject.mutex); |
1056 | 1064 | ||
1065 | srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL; | ||
1057 | pd = idr_read_pd(cmd.pd_handle, file->ucontext); | 1066 | pd = idr_read_pd(cmd.pd_handle, file->ucontext); |
1058 | scq = idr_read_cq(cmd.send_cq_handle, file->ucontext); | 1067 | scq = idr_read_cq(cmd.send_cq_handle, file->ucontext); |
1059 | rcq = idr_read_cq(cmd.recv_cq_handle, file->ucontext); | 1068 | rcq = cmd.recv_cq_handle == cmd.send_cq_handle ? |
1060 | srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL; | 1069 | scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext); |
1061 | 1070 | ||
1062 | if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) { | 1071 | if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) { |
1063 | ret = -EINVAL; | 1072 | ret = -EINVAL; |
@@ -1125,7 +1134,8 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, | |||
1125 | 1134 | ||
1126 | put_pd_read(pd); | 1135 | put_pd_read(pd); |
1127 | put_cq_read(scq); | 1136 | put_cq_read(scq); |
1128 | put_cq_read(rcq); | 1137 | if (rcq != scq) |
1138 | put_cq_read(rcq); | ||
1129 | if (srq) | 1139 | if (srq) |
1130 | put_srq_read(srq); | 1140 | put_srq_read(srq); |
1131 | 1141 | ||
@@ -1150,7 +1160,7 @@ err_put: | |||
1150 | put_pd_read(pd); | 1160 | put_pd_read(pd); |
1151 | if (scq) | 1161 | if (scq) |
1152 | put_cq_read(scq); | 1162 | put_cq_read(scq); |
1153 | if (rcq) | 1163 | if (rcq && rcq != scq) |
1154 | put_cq_read(rcq); | 1164 | put_cq_read(rcq); |
1155 | if (srq) | 1165 | if (srq) |
1156 | put_srq_read(srq); | 1166 | put_srq_read(srq); |
@@ -1751,7 +1761,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, | |||
1751 | if (!uobj) | 1761 | if (!uobj) |
1752 | return -ENOMEM; | 1762 | return -ENOMEM; |
1753 | 1763 | ||
1754 | init_uobj(uobj, cmd.user_handle, file->ucontext); | 1764 | init_uobj(uobj, cmd.user_handle, file->ucontext, &ah_lock_key); |
1755 | down_write(&uobj->mutex); | 1765 | down_write(&uobj->mutex); |
1756 | 1766 | ||
1757 | pd = idr_read_pd(cmd.pd_handle, file->ucontext); | 1767 | pd = idr_read_pd(cmd.pd_handle, file->ucontext); |
@@ -1775,7 +1785,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, | |||
1775 | ah = ib_create_ah(pd, &attr); | 1785 | ah = ib_create_ah(pd, &attr); |
1776 | if (IS_ERR(ah)) { | 1786 | if (IS_ERR(ah)) { |
1777 | ret = PTR_ERR(ah); | 1787 | ret = PTR_ERR(ah); |
1778 | goto err; | 1788 | goto err_put; |
1779 | } | 1789 | } |
1780 | 1790 | ||
1781 | ah->uobject = uobj; | 1791 | ah->uobject = uobj; |
@@ -1811,6 +1821,9 @@ err_copy: | |||
1811 | err_destroy: | 1821 | err_destroy: |
1812 | ib_destroy_ah(ah); | 1822 | ib_destroy_ah(ah); |
1813 | 1823 | ||
1824 | err_put: | ||
1825 | put_pd_read(pd); | ||
1826 | |||
1814 | err: | 1827 | err: |
1815 | put_uobj_write(uobj); | 1828 | put_uobj_write(uobj); |
1816 | return ret; | 1829 | return ret; |
@@ -1963,7 +1976,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, | |||
1963 | if (!obj) | 1976 | if (!obj) |
1964 | return -ENOMEM; | 1977 | return -ENOMEM; |
1965 | 1978 | ||
1966 | init_uobj(&obj->uobject, cmd.user_handle, file->ucontext); | 1979 | init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &srq_lock_key); |
1967 | down_write(&obj->uobject.mutex); | 1980 | down_write(&obj->uobject.mutex); |
1968 | 1981 | ||
1969 | pd = idr_read_pd(cmd.pd_handle, file->ucontext); | 1982 | pd = idr_read_pd(cmd.pd_handle, file->ucontext); |
@@ -1984,7 +1997,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, | |||
1984 | srq = pd->device->create_srq(pd, &attr, &udata); | 1997 | srq = pd->device->create_srq(pd, &attr, &udata); |
1985 | if (IS_ERR(srq)) { | 1998 | if (IS_ERR(srq)) { |
1986 | ret = PTR_ERR(srq); | 1999 | ret = PTR_ERR(srq); |
1987 | goto err; | 2000 | goto err_put; |
1988 | } | 2001 | } |
1989 | 2002 | ||
1990 | srq->device = pd->device; | 2003 | srq->device = pd->device; |
@@ -2029,6 +2042,9 @@ err_copy: | |||
2029 | err_destroy: | 2042 | err_destroy: |
2030 | ib_destroy_srq(srq); | 2043 | ib_destroy_srq(srq); |
2031 | 2044 | ||
2045 | err_put: | ||
2046 | put_pd_read(pd); | ||
2047 | |||
2032 | err: | 2048 | err: |
2033 | put_uobj_write(&obj->uobject); | 2049 | put_uobj_write(&obj->uobject); |
2034 | return ret; | 2050 | return ret; |
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index e725cccc7cde..4e16314e8e6d 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
@@ -122,7 +122,7 @@ static void ib_uverbs_release_dev(struct kref *ref) | |||
122 | struct ib_uverbs_device *dev = | 122 | struct ib_uverbs_device *dev = |
123 | container_of(ref, struct ib_uverbs_device, ref); | 123 | container_of(ref, struct ib_uverbs_device, ref); |
124 | 124 | ||
125 | kfree(dev); | 125 | complete(&dev->comp); |
126 | } | 126 | } |
127 | 127 | ||
128 | void ib_uverbs_release_ucq(struct ib_uverbs_file *file, | 128 | void ib_uverbs_release_ucq(struct ib_uverbs_file *file, |
@@ -740,6 +740,7 @@ static void ib_uverbs_add_one(struct ib_device *device) | |||
740 | return; | 740 | return; |
741 | 741 | ||
742 | kref_init(&uverbs_dev->ref); | 742 | kref_init(&uverbs_dev->ref); |
743 | init_completion(&uverbs_dev->comp); | ||
743 | 744 | ||
744 | spin_lock(&map_lock); | 745 | spin_lock(&map_lock); |
745 | uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES); | 746 | uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES); |
@@ -793,6 +794,8 @@ err_cdev: | |||
793 | 794 | ||
794 | err: | 795 | err: |
795 | kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); | 796 | kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); |
797 | wait_for_completion(&uverbs_dev->comp); | ||
798 | kfree(uverbs_dev); | ||
796 | return; | 799 | return; |
797 | } | 800 | } |
798 | 801 | ||
@@ -812,7 +815,10 @@ static void ib_uverbs_remove_one(struct ib_device *device) | |||
812 | spin_unlock(&map_lock); | 815 | spin_unlock(&map_lock); |
813 | 816 | ||
814 | clear_bit(uverbs_dev->devnum, dev_map); | 817 | clear_bit(uverbs_dev->devnum, dev_map); |
818 | |||
815 | kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); | 819 | kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); |
820 | wait_for_completion(&uverbs_dev->comp); | ||
821 | kfree(uverbs_dev); | ||
816 | } | 822 | } |
817 | 823 | ||
818 | static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags, | 824 | static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags, |
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 823131d58b34..f98518d912b5 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
@@ -859,6 +859,38 @@ static void ipath_rcv_layer(struct ipath_devdata *dd, u32 etail, | |||
859 | __ipath_layer_rcv_lid(dd, hdr); | 859 | __ipath_layer_rcv_lid(dd, hdr); |
860 | } | 860 | } |
861 | 861 | ||
862 | static void ipath_rcv_hdrerr(struct ipath_devdata *dd, | ||
863 | u32 eflags, | ||
864 | u32 l, | ||
865 | u32 etail, | ||
866 | u64 *rc) | ||
867 | { | ||
868 | char emsg[128]; | ||
869 | struct ipath_message_header *hdr; | ||
870 | |||
871 | get_rhf_errstring(eflags, emsg, sizeof emsg); | ||
872 | hdr = (struct ipath_message_header *)&rc[1]; | ||
873 | ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u " | ||
874 | "tlen=%x opcode=%x egridx=%x: %s\n", | ||
875 | eflags, l, | ||
876 | ipath_hdrget_rcv_type((__le32 *) rc), | ||
877 | ipath_hdrget_length_in_bytes((__le32 *) rc), | ||
878 | be32_to_cpu(hdr->bth[0]) >> 24, | ||
879 | etail, emsg); | ||
880 | |||
881 | /* Count local link integrity errors. */ | ||
882 | if (eflags & (INFINIPATH_RHF_H_ICRCERR | INFINIPATH_RHF_H_VCRCERR)) { | ||
883 | u8 n = (dd->ipath_ibcctrl >> | ||
884 | INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) & | ||
885 | INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK; | ||
886 | |||
887 | if (++dd->ipath_lli_counter > n) { | ||
888 | dd->ipath_lli_counter = 0; | ||
889 | dd->ipath_lli_errors++; | ||
890 | } | ||
891 | } | ||
892 | } | ||
893 | |||
862 | /* | 894 | /* |
863 | * ipath_kreceive - receive a packet | 895 | * ipath_kreceive - receive a packet |
864 | * @dd: the infinipath device | 896 | * @dd: the infinipath device |
@@ -875,7 +907,6 @@ void ipath_kreceive(struct ipath_devdata *dd) | |||
875 | struct ipath_message_header *hdr; | 907 | struct ipath_message_header *hdr; |
876 | u32 eflags, i, etype, tlen, pkttot = 0, updegr=0, reloop=0; | 908 | u32 eflags, i, etype, tlen, pkttot = 0, updegr=0, reloop=0; |
877 | static u64 totcalls; /* stats, may eventually remove */ | 909 | static u64 totcalls; /* stats, may eventually remove */ |
878 | char emsg[128]; | ||
879 | 910 | ||
880 | if (!dd->ipath_hdrqtailptr) { | 911 | if (!dd->ipath_hdrqtailptr) { |
881 | ipath_dev_err(dd, | 912 | ipath_dev_err(dd, |
@@ -938,26 +969,9 @@ reloop: | |||
938 | "%x\n", etype); | 969 | "%x\n", etype); |
939 | } | 970 | } |
940 | 971 | ||
941 | if (eflags & ~(INFINIPATH_RHF_H_TIDERR | | 972 | if (unlikely(eflags)) |
942 | INFINIPATH_RHF_H_IHDRERR)) { | 973 | ipath_rcv_hdrerr(dd, eflags, l, etail, rc); |
943 | get_rhf_errstring(eflags, emsg, sizeof emsg); | 974 | else if (etype == RCVHQ_RCV_TYPE_NON_KD) { |
944 | ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u " | ||
945 | "tlen=%x opcode=%x egridx=%x: %s\n", | ||
946 | eflags, l, etype, tlen, bthbytes[0], | ||
947 | ipath_hdrget_index((__le32 *) rc), emsg); | ||
948 | /* Count local link integrity errors. */ | ||
949 | if (eflags & (INFINIPATH_RHF_H_ICRCERR | | ||
950 | INFINIPATH_RHF_H_VCRCERR)) { | ||
951 | u8 n = (dd->ipath_ibcctrl >> | ||
952 | INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) & | ||
953 | INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK; | ||
954 | |||
955 | if (++dd->ipath_lli_counter > n) { | ||
956 | dd->ipath_lli_counter = 0; | ||
957 | dd->ipath_lli_errors++; | ||
958 | } | ||
959 | } | ||
960 | } else if (etype == RCVHQ_RCV_TYPE_NON_KD) { | ||
961 | int ret = __ipath_verbs_rcv(dd, rc + 1, | 975 | int ret = __ipath_verbs_rcv(dd, rc + 1, |
962 | ebuf, tlen); | 976 | ebuf, tlen); |
963 | if (ret == -ENODEV) | 977 | if (ret == -ENODEV) |
@@ -981,25 +995,7 @@ reloop: | |||
981 | else if (etype == RCVHQ_RCV_TYPE_EXPECTED) | 995 | else if (etype == RCVHQ_RCV_TYPE_EXPECTED) |
982 | ipath_dbg("Bug: Expected TID, opcode %x; ignored\n", | 996 | ipath_dbg("Bug: Expected TID, opcode %x; ignored\n", |
983 | be32_to_cpu(hdr->bth[0]) & 0xff); | 997 | be32_to_cpu(hdr->bth[0]) & 0xff); |
984 | else if (eflags & (INFINIPATH_RHF_H_TIDERR | | 998 | else { |
985 | INFINIPATH_RHF_H_IHDRERR)) { | ||
986 | /* | ||
987 | * This is a type 3 packet, only the LRH is in the | ||
988 | * rcvhdrq, the rest of the header is in the eager | ||
989 | * buffer. | ||
990 | */ | ||
991 | u8 opcode; | ||
992 | if (ebuf) { | ||
993 | bthbytes = (u8 *) ebuf; | ||
994 | opcode = *bthbytes; | ||
995 | } | ||
996 | else | ||
997 | opcode = 0; | ||
998 | get_rhf_errstring(eflags, emsg, sizeof emsg); | ||
999 | ipath_dbg("Err %x (%s), opcode %x, egrbuf %x, " | ||
1000 | "len %x\n", eflags, emsg, opcode, etail, | ||
1001 | tlen); | ||
1002 | } else { | ||
1003 | /* | 999 | /* |
1004 | * error packet, type of error unknown. | 1000 | * error packet, type of error unknown. |
1005 | * Probably type 3, but we don't know, so don't | 1001 | * Probably type 3, but we don't know, so don't |
diff --git a/drivers/infiniband/hw/ipath/ipath_keys.c b/drivers/infiniband/hw/ipath/ipath_keys.c index 46773c673a1a..a5ca279370aa 100644 --- a/drivers/infiniband/hw/ipath/ipath_keys.c +++ b/drivers/infiniband/hw/ipath/ipath_keys.c | |||
@@ -197,6 +197,21 @@ int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss, | |||
197 | size_t off; | 197 | size_t off; |
198 | int ret; | 198 | int ret; |
199 | 199 | ||
200 | /* | ||
201 | * We use RKEY == zero for physical addresses | ||
202 | * (see ipath_get_dma_mr). | ||
203 | */ | ||
204 | if (rkey == 0) { | ||
205 | sge->mr = NULL; | ||
206 | sge->vaddr = phys_to_virt(vaddr); | ||
207 | sge->length = len; | ||
208 | sge->sge_length = len; | ||
209 | ss->sg_list = NULL; | ||
210 | ss->num_sge = 1; | ||
211 | ret = 1; | ||
212 | goto bail; | ||
213 | } | ||
214 | |||
200 | mr = rkt->table[(rkey >> (32 - ib_ipath_lkey_table_size))]; | 215 | mr = rkt->table[(rkey >> (32 - ib_ipath_lkey_table_size))]; |
201 | if (unlikely(mr == NULL || mr->lkey != rkey)) { | 216 | if (unlikely(mr == NULL || mr->lkey != rkey)) { |
202 | ret = 0; | 217 | ret = 0; |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index 56ac336dd1ec..d70a9b6b5239 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c | |||
@@ -191,10 +191,6 @@ void ipath_skip_sge(struct ipath_sge_state *ss, u32 length) | |||
191 | { | 191 | { |
192 | struct ipath_sge *sge = &ss->sge; | 192 | struct ipath_sge *sge = &ss->sge; |
193 | 193 | ||
194 | while (length > sge->sge_length) { | ||
195 | length -= sge->sge_length; | ||
196 | ss->sge = *ss->sg_list++; | ||
197 | } | ||
198 | while (length) { | 194 | while (length) { |
199 | u32 len = sge->length; | 195 | u32 len = sge->length; |
200 | 196 | ||
@@ -627,6 +623,7 @@ static int ipath_query_device(struct ib_device *ibdev, | |||
627 | props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR | | 623 | props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR | |
628 | IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT | | 624 | IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT | |
629 | IB_DEVICE_SYS_IMAGE_GUID; | 625 | IB_DEVICE_SYS_IMAGE_GUID; |
626 | props->page_size_cap = PAGE_SIZE; | ||
630 | props->vendor_id = ipath_layer_get_vendorid(dev->dd); | 627 | props->vendor_id = ipath_layer_get_vendorid(dev->dd); |
631 | props->vendor_part_id = ipath_layer_get_deviceid(dev->dd); | 628 | props->vendor_part_id = ipath_layer_get_deviceid(dev->dd); |
632 | props->hw_ver = ipath_layer_get_pcirev(dev->dd); | 629 | props->hw_ver = ipath_layer_get_pcirev(dev->dd); |
diff --git a/drivers/infiniband/hw/mthca/mthca_allocator.c b/drivers/infiniband/hw/mthca/mthca_allocator.c index 9ba3211cef7c..25157f57a6d0 100644 --- a/drivers/infiniband/hw/mthca/mthca_allocator.c +++ b/drivers/infiniband/hw/mthca/mthca_allocator.c | |||
@@ -108,14 +108,15 @@ void mthca_alloc_cleanup(struct mthca_alloc *alloc) | |||
108 | * serialize access to the array. | 108 | * serialize access to the array. |
109 | */ | 109 | */ |
110 | 110 | ||
111 | #define MTHCA_ARRAY_MASK (PAGE_SIZE / sizeof (void *) - 1) | ||
112 | |||
111 | void *mthca_array_get(struct mthca_array *array, int index) | 113 | void *mthca_array_get(struct mthca_array *array, int index) |
112 | { | 114 | { |
113 | int p = (index * sizeof (void *)) >> PAGE_SHIFT; | 115 | int p = (index * sizeof (void *)) >> PAGE_SHIFT; |
114 | 116 | ||
115 | if (array->page_list[p].page) { | 117 | if (array->page_list[p].page) |
116 | int i = index & (PAGE_SIZE / sizeof (void *) - 1); | 118 | return array->page_list[p].page[index & MTHCA_ARRAY_MASK]; |
117 | return array->page_list[p].page[i]; | 119 | else |
118 | } else | ||
119 | return NULL; | 120 | return NULL; |
120 | } | 121 | } |
121 | 122 | ||
@@ -130,8 +131,7 @@ int mthca_array_set(struct mthca_array *array, int index, void *value) | |||
130 | if (!array->page_list[p].page) | 131 | if (!array->page_list[p].page) |
131 | return -ENOMEM; | 132 | return -ENOMEM; |
132 | 133 | ||
133 | array->page_list[p].page[index & (PAGE_SIZE / sizeof (void *) - 1)] = | 134 | array->page_list[p].page[index & MTHCA_ARRAY_MASK] = value; |
134 | value; | ||
135 | ++array->page_list[p].used; | 135 | ++array->page_list[p].used; |
136 | 136 | ||
137 | return 0; | 137 | return 0; |
@@ -144,7 +144,8 @@ void mthca_array_clear(struct mthca_array *array, int index) | |||
144 | if (--array->page_list[p].used == 0) { | 144 | if (--array->page_list[p].used == 0) { |
145 | free_page((unsigned long) array->page_list[p].page); | 145 | free_page((unsigned long) array->page_list[p].page); |
146 | array->page_list[p].page = NULL; | 146 | array->page_list[p].page = NULL; |
147 | } | 147 | } else |
148 | array->page_list[p].page[index & MTHCA_ARRAY_MASK] = NULL; | ||
148 | 149 | ||
149 | if (array->page_list[p].used < 0) | 150 | if (array->page_list[p].used < 0) |
150 | pr_debug("Array %p index %d page %d with ref count %d < 0\n", | 151 | pr_debug("Array %p index %d page %d with ref count %d < 0\n", |
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index b12aa03be251..e215041b2db9 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c | |||
@@ -303,9 +303,10 @@ int mthca_ah_query(struct ib_ah *ibah, struct ib_ah_attr *attr) | |||
303 | memset(attr, 0, sizeof *attr); | 303 | memset(attr, 0, sizeof *attr); |
304 | attr->dlid = be16_to_cpu(ah->av->dlid); | 304 | attr->dlid = be16_to_cpu(ah->av->dlid); |
305 | attr->sl = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; | 305 | attr->sl = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; |
306 | attr->static_rate = ah->av->msg_sr & 0x7; | ||
307 | attr->src_path_bits = ah->av->g_slid & 0x7F; | ||
308 | attr->port_num = be32_to_cpu(ah->av->port_pd) >> 24; | 306 | attr->port_num = be32_to_cpu(ah->av->port_pd) >> 24; |
307 | attr->static_rate = mthca_rate_to_ib(dev, ah->av->msg_sr & 0x7, | ||
308 | attr->port_num); | ||
309 | attr->src_path_bits = ah->av->g_slid & 0x7F; | ||
309 | attr->ah_flags = mthca_ah_grh_present(ah) ? IB_AH_GRH : 0; | 310 | attr->ah_flags = mthca_ah_grh_present(ah) ? IB_AH_GRH : 0; |
310 | 311 | ||
311 | if (attr->ah_flags) { | 312 | if (attr->ah_flags) { |
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index d0f7731802c9..deabc14b4ea4 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c | |||
@@ -778,11 +778,12 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) | |||
778 | ((dev->fw_ver & 0xffff0000ull) >> 16) | | 778 | ((dev->fw_ver & 0xffff0000ull) >> 16) | |
779 | ((dev->fw_ver & 0x0000ffffull) << 16); | 779 | ((dev->fw_ver & 0x0000ffffull) << 16); |
780 | 780 | ||
781 | MTHCA_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET); | ||
782 | dev->cmd.max_cmds = 1 << lg; | ||
783 | |||
781 | mthca_dbg(dev, "FW version %012llx, max commands %d\n", | 784 | mthca_dbg(dev, "FW version %012llx, max commands %d\n", |
782 | (unsigned long long) dev->fw_ver, dev->cmd.max_cmds); | 785 | (unsigned long long) dev->fw_ver, dev->cmd.max_cmds); |
783 | 786 | ||
784 | MTHCA_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET); | ||
785 | dev->cmd.max_cmds = 1 << lg; | ||
786 | MTHCA_GET(dev->catas_err.addr, outbox, QUERY_FW_ERR_START_OFFSET); | 787 | MTHCA_GET(dev->catas_err.addr, outbox, QUERY_FW_ERR_START_OFFSET); |
787 | MTHCA_GET(dev->catas_err.size, outbox, QUERY_FW_ERR_SIZE_OFFSET); | 788 | MTHCA_GET(dev->catas_err.size, outbox, QUERY_FW_ERR_SIZE_OFFSET); |
788 | 789 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 557cde3a4563..7b82c1907f04 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c | |||
@@ -967,12 +967,12 @@ static struct { | |||
967 | } mthca_hca_table[] = { | 967 | } mthca_hca_table[] = { |
968 | [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 4, 0), | 968 | [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 4, 0), |
969 | .flags = 0 }, | 969 | .flags = 0 }, |
970 | [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 400), | 970 | [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 600), |
971 | .flags = MTHCA_FLAG_PCIE }, | 971 | .flags = MTHCA_FLAG_PCIE }, |
972 | [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 0), | 972 | [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 400), |
973 | .flags = MTHCA_FLAG_MEMFREE | | 973 | .flags = MTHCA_FLAG_MEMFREE | |
974 | MTHCA_FLAG_PCIE }, | 974 | MTHCA_FLAG_PCIE }, |
975 | [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 0, 800), | 975 | [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 1, 0), |
976 | .flags = MTHCA_FLAG_MEMFREE | | 976 | .flags = MTHCA_FLAG_MEMFREE | |
977 | MTHCA_FLAG_PCIE | | 977 | MTHCA_FLAG_PCIE | |
978 | MTHCA_FLAG_SINAI_OPT } | 978 | MTHCA_FLAG_SINAI_OPT } |
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 230ae21db8fd..265b1d1c4a62 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c | |||
@@ -1287,11 +1287,7 @@ int mthca_register_device(struct mthca_dev *dev) | |||
1287 | (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | | 1287 | (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | |
1288 | (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | | 1288 | (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | |
1289 | (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) | | 1289 | (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) | |
1290 | (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) | | 1290 | (1ull << IB_USER_VERBS_CMD_DETACH_MCAST); |
1291 | (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | | ||
1292 | (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | | ||
1293 | (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) | | ||
1294 | (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ); | ||
1295 | dev->ib_dev.node_type = IB_NODE_CA; | 1291 | dev->ib_dev.node_type = IB_NODE_CA; |
1296 | dev->ib_dev.phys_port_cnt = dev->limits.num_ports; | 1292 | dev->ib_dev.phys_port_cnt = dev->limits.num_ports; |
1297 | dev->ib_dev.dma_device = &dev->pdev->dev; | 1293 | dev->ib_dev.dma_device = &dev->pdev->dev; |
@@ -1316,6 +1312,11 @@ int mthca_register_device(struct mthca_dev *dev) | |||
1316 | dev->ib_dev.modify_srq = mthca_modify_srq; | 1312 | dev->ib_dev.modify_srq = mthca_modify_srq; |
1317 | dev->ib_dev.query_srq = mthca_query_srq; | 1313 | dev->ib_dev.query_srq = mthca_query_srq; |
1318 | dev->ib_dev.destroy_srq = mthca_destroy_srq; | 1314 | dev->ib_dev.destroy_srq = mthca_destroy_srq; |
1315 | dev->ib_dev.uverbs_cmd_mask |= | ||
1316 | (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | | ||
1317 | (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | | ||
1318 | (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) | | ||
1319 | (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ); | ||
1319 | 1320 | ||
1320 | if (mthca_is_memfree(dev)) | 1321 | if (mthca_is_memfree(dev)) |
1321 | dev->ib_dev.post_srq_recv = mthca_arbel_post_srq_recv; | 1322 | dev->ib_dev.post_srq_recv = mthca_arbel_post_srq_recv; |
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h index 8de2887ba15c..9a5bece3fa5c 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.h +++ b/drivers/infiniband/hw/mthca/mthca_provider.h | |||
@@ -136,8 +136,8 @@ struct mthca_ah { | |||
136 | * We have one global lock that protects dev->cq/qp_table. Each | 136 | * We have one global lock that protects dev->cq/qp_table. Each |
137 | * struct mthca_cq/qp also has its own lock. An individual qp lock | 137 | * struct mthca_cq/qp also has its own lock. An individual qp lock |
138 | * may be taken inside of an individual cq lock. Both cqs attached to | 138 | * may be taken inside of an individual cq lock. Both cqs attached to |
139 | * a qp may be locked, with the send cq locked first. No other | 139 | * a qp may be locked, with the cq with the lower cqn locked first. |
140 | * nesting should be done. | 140 | * No other nesting should be done. |
141 | * | 141 | * |
142 | * Each struct mthca_cq/qp also has an ref count, protected by the | 142 | * Each struct mthca_cq/qp also has an ref count, protected by the |
143 | * corresponding table lock. The pointer from the cq/qp_table to the | 143 | * corresponding table lock. The pointer from the cq/qp_table to the |
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 490fc783bb0c..2e8f6f36e0a5 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c | |||
@@ -99,6 +99,10 @@ enum { | |||
99 | MTHCA_QP_BIT_RSC = 1 << 3 | 99 | MTHCA_QP_BIT_RSC = 1 << 3 |
100 | }; | 100 | }; |
101 | 101 | ||
102 | enum { | ||
103 | MTHCA_SEND_DOORBELL_FENCE = 1 << 5 | ||
104 | }; | ||
105 | |||
102 | struct mthca_qp_path { | 106 | struct mthca_qp_path { |
103 | __be32 port_pkey; | 107 | __be32 port_pkey; |
104 | u8 rnr_retry; | 108 | u8 rnr_retry; |
@@ -222,9 +226,8 @@ static void *get_send_wqe(struct mthca_qp *qp, int n) | |||
222 | (PAGE_SIZE - 1)); | 226 | (PAGE_SIZE - 1)); |
223 | } | 227 | } |
224 | 228 | ||
225 | static void mthca_wq_init(struct mthca_wq *wq) | 229 | static void mthca_wq_reset(struct mthca_wq *wq) |
226 | { | 230 | { |
227 | /* mthca_alloc_qp_common() initializes the locks */ | ||
228 | wq->next_ind = 0; | 231 | wq->next_ind = 0; |
229 | wq->last_comp = wq->max - 1; | 232 | wq->last_comp = wq->max - 1; |
230 | wq->head = 0; | 233 | wq->head = 0; |
@@ -845,10 +848,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
845 | mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq), qp->qpn, | 848 | mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq), qp->qpn, |
846 | qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL); | 849 | qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL); |
847 | 850 | ||
848 | mthca_wq_init(&qp->sq); | 851 | mthca_wq_reset(&qp->sq); |
849 | qp->sq.last = get_send_wqe(qp, qp->sq.max - 1); | 852 | qp->sq.last = get_send_wqe(qp, qp->sq.max - 1); |
850 | 853 | ||
851 | mthca_wq_init(&qp->rq); | 854 | mthca_wq_reset(&qp->rq); |
852 | qp->rq.last = get_recv_wqe(qp, qp->rq.max - 1); | 855 | qp->rq.last = get_recv_wqe(qp, qp->rq.max - 1); |
853 | 856 | ||
854 | if (mthca_is_memfree(dev)) { | 857 | if (mthca_is_memfree(dev)) { |
@@ -1112,9 +1115,9 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev, | |||
1112 | qp->atomic_rd_en = 0; | 1115 | qp->atomic_rd_en = 0; |
1113 | qp->resp_depth = 0; | 1116 | qp->resp_depth = 0; |
1114 | qp->sq_policy = send_policy; | 1117 | qp->sq_policy = send_policy; |
1115 | mthca_wq_init(&qp->sq); | 1118 | mthca_wq_reset(&qp->sq); |
1116 | mthca_wq_init(&qp->rq); | 1119 | mthca_wq_reset(&qp->rq); |
1117 | /* these are initialized separately so lockdep can tell them apart */ | 1120 | |
1118 | spin_lock_init(&qp->sq.lock); | 1121 | spin_lock_init(&qp->sq.lock); |
1119 | spin_lock_init(&qp->rq.lock); | 1122 | spin_lock_init(&qp->rq.lock); |
1120 | 1123 | ||
@@ -1260,6 +1263,32 @@ int mthca_alloc_qp(struct mthca_dev *dev, | |||
1260 | return 0; | 1263 | return 0; |
1261 | } | 1264 | } |
1262 | 1265 | ||
1266 | static void mthca_lock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq) | ||
1267 | { | ||
1268 | if (send_cq == recv_cq) | ||
1269 | spin_lock_irq(&send_cq->lock); | ||
1270 | else if (send_cq->cqn < recv_cq->cqn) { | ||
1271 | spin_lock_irq(&send_cq->lock); | ||
1272 | spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING); | ||
1273 | } else { | ||
1274 | spin_lock_irq(&recv_cq->lock); | ||
1275 | spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING); | ||
1276 | } | ||
1277 | } | ||
1278 | |||
1279 | static void mthca_unlock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq) | ||
1280 | { | ||
1281 | if (send_cq == recv_cq) | ||
1282 | spin_unlock_irq(&send_cq->lock); | ||
1283 | else if (send_cq->cqn < recv_cq->cqn) { | ||
1284 | spin_unlock(&recv_cq->lock); | ||
1285 | spin_unlock_irq(&send_cq->lock); | ||
1286 | } else { | ||
1287 | spin_unlock(&send_cq->lock); | ||
1288 | spin_unlock_irq(&recv_cq->lock); | ||
1289 | } | ||
1290 | } | ||
1291 | |||
1263 | int mthca_alloc_sqp(struct mthca_dev *dev, | 1292 | int mthca_alloc_sqp(struct mthca_dev *dev, |
1264 | struct mthca_pd *pd, | 1293 | struct mthca_pd *pd, |
1265 | struct mthca_cq *send_cq, | 1294 | struct mthca_cq *send_cq, |
@@ -1312,17 +1341,13 @@ int mthca_alloc_sqp(struct mthca_dev *dev, | |||
1312 | * Lock CQs here, so that CQ polling code can do QP lookup | 1341 | * Lock CQs here, so that CQ polling code can do QP lookup |
1313 | * without taking a lock. | 1342 | * without taking a lock. |
1314 | */ | 1343 | */ |
1315 | spin_lock_irq(&send_cq->lock); | 1344 | mthca_lock_cqs(send_cq, recv_cq); |
1316 | if (send_cq != recv_cq) | ||
1317 | spin_lock(&recv_cq->lock); | ||
1318 | 1345 | ||
1319 | spin_lock(&dev->qp_table.lock); | 1346 | spin_lock(&dev->qp_table.lock); |
1320 | mthca_array_clear(&dev->qp_table.qp, mqpn); | 1347 | mthca_array_clear(&dev->qp_table.qp, mqpn); |
1321 | spin_unlock(&dev->qp_table.lock); | 1348 | spin_unlock(&dev->qp_table.lock); |
1322 | 1349 | ||
1323 | if (send_cq != recv_cq) | 1350 | mthca_unlock_cqs(send_cq, recv_cq); |
1324 | spin_unlock(&recv_cq->lock); | ||
1325 | spin_unlock_irq(&send_cq->lock); | ||
1326 | 1351 | ||
1327 | err_out: | 1352 | err_out: |
1328 | dma_free_coherent(&dev->pdev->dev, sqp->header_buf_size, | 1353 | dma_free_coherent(&dev->pdev->dev, sqp->header_buf_size, |
@@ -1356,9 +1381,7 @@ void mthca_free_qp(struct mthca_dev *dev, | |||
1356 | * Lock CQs here, so that CQ polling code can do QP lookup | 1381 | * Lock CQs here, so that CQ polling code can do QP lookup |
1357 | * without taking a lock. | 1382 | * without taking a lock. |
1358 | */ | 1383 | */ |
1359 | spin_lock_irq(&send_cq->lock); | 1384 | mthca_lock_cqs(send_cq, recv_cq); |
1360 | if (send_cq != recv_cq) | ||
1361 | spin_lock(&recv_cq->lock); | ||
1362 | 1385 | ||
1363 | spin_lock(&dev->qp_table.lock); | 1386 | spin_lock(&dev->qp_table.lock); |
1364 | mthca_array_clear(&dev->qp_table.qp, | 1387 | mthca_array_clear(&dev->qp_table.qp, |
@@ -1366,9 +1389,7 @@ void mthca_free_qp(struct mthca_dev *dev, | |||
1366 | --qp->refcount; | 1389 | --qp->refcount; |
1367 | spin_unlock(&dev->qp_table.lock); | 1390 | spin_unlock(&dev->qp_table.lock); |
1368 | 1391 | ||
1369 | if (send_cq != recv_cq) | 1392 | mthca_unlock_cqs(send_cq, recv_cq); |
1370 | spin_unlock(&recv_cq->lock); | ||
1371 | spin_unlock_irq(&send_cq->lock); | ||
1372 | 1393 | ||
1373 | wait_event(qp->wait, !get_qp_refcount(dev, qp)); | 1394 | wait_event(qp->wait, !get_qp_refcount(dev, qp)); |
1374 | 1395 | ||
@@ -1503,7 +1524,7 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
1503 | int i; | 1524 | int i; |
1504 | int size; | 1525 | int size; |
1505 | int size0 = 0; | 1526 | int size0 = 0; |
1506 | u32 f0 = 0; | 1527 | u32 f0; |
1507 | int ind; | 1528 | int ind; |
1508 | u8 op0 = 0; | 1529 | u8 op0 = 0; |
1509 | 1530 | ||
@@ -1687,6 +1708,8 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
1687 | if (!size0) { | 1708 | if (!size0) { |
1688 | size0 = size; | 1709 | size0 = size; |
1689 | op0 = mthca_opcode[wr->opcode]; | 1710 | op0 = mthca_opcode[wr->opcode]; |
1711 | f0 = wr->send_flags & IB_SEND_FENCE ? | ||
1712 | MTHCA_SEND_DOORBELL_FENCE : 0; | ||
1690 | } | 1713 | } |
1691 | 1714 | ||
1692 | ++ind; | 1715 | ++ind; |
@@ -1844,7 +1867,7 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
1844 | int i; | 1867 | int i; |
1845 | int size; | 1868 | int size; |
1846 | int size0 = 0; | 1869 | int size0 = 0; |
1847 | u32 f0 = 0; | 1870 | u32 f0; |
1848 | int ind; | 1871 | int ind; |
1849 | u8 op0 = 0; | 1872 | u8 op0 = 0; |
1850 | 1873 | ||
@@ -2052,6 +2075,8 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
2052 | if (!size0) { | 2075 | if (!size0) { |
2053 | size0 = size; | 2076 | size0 = size; |
2054 | op0 = mthca_opcode[wr->opcode]; | 2077 | op0 = mthca_opcode[wr->opcode]; |
2078 | f0 = wr->send_flags & IB_SEND_FENCE ? | ||
2079 | MTHCA_SEND_DOORBELL_FENCE : 0; | ||
2055 | } | 2080 | } |
2056 | 2081 | ||
2057 | ++ind; | 2082 | ++ind; |
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index fab417c5cf43..b60a9d79ae54 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c | |||
@@ -370,7 +370,8 @@ int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, | |||
370 | return -EINVAL; | 370 | return -EINVAL; |
371 | 371 | ||
372 | if (attr_mask & IB_SRQ_LIMIT) { | 372 | if (attr_mask & IB_SRQ_LIMIT) { |
373 | if (attr->srq_limit > srq->max) | 373 | u32 max_wr = mthca_is_memfree(dev) ? srq->max - 1 : srq->max; |
374 | if (attr->srq_limit > max_wr) | ||
374 | return -EINVAL; | 375 | return -EINVAL; |
375 | 376 | ||
376 | mutex_lock(&srq->mutex); | 377 | mutex_lock(&srq->mutex); |
diff --git a/drivers/infiniband/ulp/ipoib/Kconfig b/drivers/infiniband/ulp/ipoib/Kconfig index 13d6d01c72c0..d74653d7de1c 100644 --- a/drivers/infiniband/ulp/ipoib/Kconfig +++ b/drivers/infiniband/ulp/ipoib/Kconfig | |||
@@ -6,8 +6,7 @@ config INFINIBAND_IPOIB | |||
6 | transports IP packets over InfiniBand so you can use your IB | 6 | transports IP packets over InfiniBand so you can use your IB |
7 | device as a fancy NIC. | 7 | device as a fancy NIC. |
8 | 8 | ||
9 | The IPoIB protocol is defined by the IETF ipoib working | 9 | See Documentation/infiniband/ipoib.txt for more information |
10 | group: <http://www.ietf.org/html.charters/ipoib-charter.html>. | ||
11 | 10 | ||
12 | config INFINIBAND_IPOIB_DEBUG | 11 | config INFINIBAND_IPOIB_DEBUG |
13 | bool "IP-over-InfiniBand debugging" if EMBEDDED | 12 | bool "IP-over-InfiniBand debugging" if EMBEDDED |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 3f89f5e19036..474aa214ab57 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
@@ -212,6 +212,7 @@ struct ipoib_path { | |||
212 | 212 | ||
213 | struct ipoib_neigh { | 213 | struct ipoib_neigh { |
214 | struct ipoib_ah *ah; | 214 | struct ipoib_ah *ah; |
215 | union ib_gid dgid; | ||
215 | struct sk_buff_head queue; | 216 | struct sk_buff_head queue; |
216 | 217 | ||
217 | struct neighbour *neighbour; | 218 | struct neighbour *neighbour; |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 1c6ea1c682a5..cf71d2a5515c 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -404,6 +404,8 @@ static void path_rec_completion(int status, | |||
404 | list_for_each_entry(neigh, &path->neigh_list, list) { | 404 | list_for_each_entry(neigh, &path->neigh_list, list) { |
405 | kref_get(&path->ah->ref); | 405 | kref_get(&path->ah->ref); |
406 | neigh->ah = path->ah; | 406 | neigh->ah = path->ah; |
407 | memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw, | ||
408 | sizeof(union ib_gid)); | ||
407 | 409 | ||
408 | while ((skb = __skb_dequeue(&neigh->queue))) | 410 | while ((skb = __skb_dequeue(&neigh->queue))) |
409 | __skb_queue_tail(&skqueue, skb); | 411 | __skb_queue_tail(&skqueue, skb); |
@@ -510,6 +512,8 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) | |||
510 | if (path->ah) { | 512 | if (path->ah) { |
511 | kref_get(&path->ah->ref); | 513 | kref_get(&path->ah->ref); |
512 | neigh->ah = path->ah; | 514 | neigh->ah = path->ah; |
515 | memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw, | ||
516 | sizeof(union ib_gid)); | ||
513 | 517 | ||
514 | ipoib_send(dev, skb, path->ah, | 518 | ipoib_send(dev, skb, path->ah, |
515 | be32_to_cpup((__be32 *) skb->dst->neighbour->ha)); | 519 | be32_to_cpup((__be32 *) skb->dst->neighbour->ha)); |
@@ -633,6 +637,25 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
633 | neigh = *to_ipoib_neigh(skb->dst->neighbour); | 637 | neigh = *to_ipoib_neigh(skb->dst->neighbour); |
634 | 638 | ||
635 | if (likely(neigh->ah)) { | 639 | if (likely(neigh->ah)) { |
640 | if (unlikely(memcmp(&neigh->dgid.raw, | ||
641 | skb->dst->neighbour->ha + 4, | ||
642 | sizeof(union ib_gid)))) { | ||
643 | spin_lock(&priv->lock); | ||
644 | /* | ||
645 | * It's safe to call ipoib_put_ah() inside | ||
646 | * priv->lock here, because we know that | ||
647 | * path->ah will always hold one more reference, | ||
648 | * so ipoib_put_ah() will never do more than | ||
649 | * decrement the ref count. | ||
650 | */ | ||
651 | ipoib_put_ah(neigh->ah); | ||
652 | list_del(&neigh->list); | ||
653 | ipoib_neigh_free(neigh); | ||
654 | spin_unlock(&priv->lock); | ||
655 | ipoib_path_lookup(skb, dev); | ||
656 | goto out; | ||
657 | } | ||
658 | |||
636 | ipoib_send(dev, skb, neigh->ah, | 659 | ipoib_send(dev, skb, neigh->ah, |
637 | be32_to_cpup((__be32 *) skb->dst->neighbour->ha)); | 660 | be32_to_cpup((__be32 *) skb->dst->neighbour->ha)); |
638 | goto out; | 661 | goto out; |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index ab40488182b3..b5e6a7be603d 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
@@ -264,6 +264,10 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, | |||
264 | if (!ah) { | 264 | if (!ah) { |
265 | ipoib_warn(priv, "ib_address_create failed\n"); | 265 | ipoib_warn(priv, "ib_address_create failed\n"); |
266 | } else { | 266 | } else { |
267 | spin_lock_irq(&priv->lock); | ||
268 | mcast->ah = ah; | ||
269 | spin_unlock_irq(&priv->lock); | ||
270 | |||
267 | ipoib_dbg_mcast(priv, "MGID " IPOIB_GID_FMT | 271 | ipoib_dbg_mcast(priv, "MGID " IPOIB_GID_FMT |
268 | " AV %p, LID 0x%04x, SL %d\n", | 272 | " AV %p, LID 0x%04x, SL %d\n", |
269 | IPOIB_GID_ARG(mcast->mcmember.mgid), | 273 | IPOIB_GID_ARG(mcast->mcmember.mgid), |
@@ -271,10 +275,6 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, | |||
271 | be16_to_cpu(mcast->mcmember.mlid), | 275 | be16_to_cpu(mcast->mcmember.mlid), |
272 | mcast->mcmember.sl); | 276 | mcast->mcmember.sl); |
273 | } | 277 | } |
274 | |||
275 | spin_lock_irq(&priv->lock); | ||
276 | mcast->ah = ah; | ||
277 | spin_unlock_irq(&priv->lock); | ||
278 | } | 278 | } |
279 | 279 | ||
280 | /* actually send any queued packets */ | 280 | /* actually send any queued packets */ |
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 34b0da5cfa0a..1437d7ee3b19 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c | |||
@@ -378,21 +378,6 @@ iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn) | |||
378 | return iser_conn_set_full_featured_mode(conn); | 378 | return iser_conn_set_full_featured_mode(conn); |
379 | } | 379 | } |
380 | 380 | ||
381 | static void | ||
382 | iscsi_iser_conn_terminate(struct iscsi_conn *conn) | ||
383 | { | ||
384 | struct iscsi_iser_conn *iser_conn = conn->dd_data; | ||
385 | struct iser_conn *ib_conn = iser_conn->ib_conn; | ||
386 | |||
387 | BUG_ON(!ib_conn); | ||
388 | /* starts conn teardown process, waits until all previously * | ||
389 | * posted buffers get flushed, deallocates all conn resources */ | ||
390 | iser_conn_terminate(ib_conn); | ||
391 | iser_conn->ib_conn = NULL; | ||
392 | conn->recv_lock = NULL; | ||
393 | } | ||
394 | |||
395 | |||
396 | static struct iscsi_transport iscsi_iser_transport; | 381 | static struct iscsi_transport iscsi_iser_transport; |
397 | 382 | ||
398 | static struct iscsi_cls_session * | 383 | static struct iscsi_cls_session * |
@@ -555,13 +540,13 @@ iscsi_iser_ep_poll(__u64 ep_handle, int timeout_ms) | |||
555 | static void | 540 | static void |
556 | iscsi_iser_ep_disconnect(__u64 ep_handle) | 541 | iscsi_iser_ep_disconnect(__u64 ep_handle) |
557 | { | 542 | { |
558 | struct iser_conn *ib_conn = iscsi_iser_ib_conn_lookup(ep_handle); | 543 | struct iser_conn *ib_conn; |
559 | 544 | ||
545 | ib_conn = iscsi_iser_ib_conn_lookup(ep_handle); | ||
560 | if (!ib_conn) | 546 | if (!ib_conn) |
561 | return; | 547 | return; |
562 | 548 | ||
563 | iser_err("ib conn %p state %d\n",ib_conn, ib_conn->state); | 549 | iser_err("ib conn %p state %d\n",ib_conn, ib_conn->state); |
564 | |||
565 | iser_conn_terminate(ib_conn); | 550 | iser_conn_terminate(ib_conn); |
566 | } | 551 | } |
567 | 552 | ||
@@ -614,9 +599,6 @@ static struct iscsi_transport iscsi_iser_transport = { | |||
614 | .get_session_param = iscsi_session_get_param, | 599 | .get_session_param = iscsi_session_get_param, |
615 | .start_conn = iscsi_iser_conn_start, | 600 | .start_conn = iscsi_iser_conn_start, |
616 | .stop_conn = iscsi_conn_stop, | 601 | .stop_conn = iscsi_conn_stop, |
617 | /* these are called as part of conn recovery */ | ||
618 | .suspend_conn_recv = NULL, /* FIXME is/how this relvant to iser? */ | ||
619 | .terminate_conn = iscsi_iser_conn_terminate, | ||
620 | /* IO */ | 602 | /* IO */ |
621 | .send_pdu = iscsi_conn_send_pdu, | 603 | .send_pdu = iscsi_conn_send_pdu, |
622 | .get_stats = iscsi_iser_conn_get_stats, | 604 | .get_stats = iscsi_iser_conn_get_stats, |
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index ff117bbf81b4..72febf1f8ff8 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c | |||
@@ -594,7 +594,7 @@ int iser_reg_page_vec(struct iser_conn *ib_conn, | |||
594 | mem = ib_fmr_pool_map_phys(ib_conn->fmr_pool, | 594 | mem = ib_fmr_pool_map_phys(ib_conn->fmr_pool, |
595 | page_list, | 595 | page_list, |
596 | page_vec->length, | 596 | page_vec->length, |
597 | &io_addr); | 597 | io_addr); |
598 | 598 | ||
599 | if (IS_ERR(mem)) { | 599 | if (IS_ERR(mem)) { |
600 | status = (int)PTR_ERR(mem); | 600 | status = (int)PTR_ERR(mem); |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 4e22afef7206..8257d5a2c8f8 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -77,6 +77,14 @@ MODULE_PARM_DESC(topspin_workarounds, | |||
77 | 77 | ||
78 | static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad }; | 78 | static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad }; |
79 | 79 | ||
80 | static int mellanox_workarounds = 1; | ||
81 | |||
82 | module_param(mellanox_workarounds, int, 0444); | ||
83 | MODULE_PARM_DESC(mellanox_workarounds, | ||
84 | "Enable workarounds for Mellanox SRP target bugs if != 0"); | ||
85 | |||
86 | static const u8 mellanox_oui[3] = { 0x00, 0x02, 0xc9 }; | ||
87 | |||
80 | static void srp_add_one(struct ib_device *device); | 88 | static void srp_add_one(struct ib_device *device); |
81 | static void srp_remove_one(struct ib_device *device); | 89 | static void srp_remove_one(struct ib_device *device); |
82 | static void srp_completion(struct ib_cq *cq, void *target_ptr); | 90 | static void srp_completion(struct ib_cq *cq, void *target_ptr); |
@@ -526,8 +534,10 @@ static int srp_reconnect_target(struct srp_target_port *target) | |||
526 | while (ib_poll_cq(target->cq, 1, &wc) > 0) | 534 | while (ib_poll_cq(target->cq, 1, &wc) > 0) |
527 | ; /* nothing */ | 535 | ; /* nothing */ |
528 | 536 | ||
537 | spin_lock_irq(target->scsi_host->host_lock); | ||
529 | list_for_each_entry_safe(req, tmp, &target->req_queue, list) | 538 | list_for_each_entry_safe(req, tmp, &target->req_queue, list) |
530 | srp_reset_req(target, req); | 539 | srp_reset_req(target, req); |
540 | spin_unlock_irq(target->scsi_host->host_lock); | ||
531 | 541 | ||
532 | target->rx_head = 0; | 542 | target->rx_head = 0; |
533 | target->tx_head = 0; | 543 | target->tx_head = 0; |
@@ -567,7 +577,7 @@ err: | |||
567 | return ret; | 577 | return ret; |
568 | } | 578 | } |
569 | 579 | ||
570 | static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat, | 580 | static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat, |
571 | int sg_cnt, struct srp_request *req, | 581 | int sg_cnt, struct srp_request *req, |
572 | struct srp_direct_buf *buf) | 582 | struct srp_direct_buf *buf) |
573 | { | 583 | { |
@@ -577,10 +587,15 @@ static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat, | |||
577 | int page_cnt; | 587 | int page_cnt; |
578 | int i, j; | 588 | int i, j; |
579 | int ret; | 589 | int ret; |
590 | struct srp_device *dev = target->srp_host->dev; | ||
580 | 591 | ||
581 | if (!dev->fmr_pool) | 592 | if (!dev->fmr_pool) |
582 | return -ENODEV; | 593 | return -ENODEV; |
583 | 594 | ||
595 | if ((sg_dma_address(&scat[0]) & ~dev->fmr_page_mask) && | ||
596 | mellanox_workarounds && !memcmp(&target->ioc_guid, mellanox_oui, 3)) | ||
597 | return -EINVAL; | ||
598 | |||
584 | len = page_cnt = 0; | 599 | len = page_cnt = 0; |
585 | for (i = 0; i < sg_cnt; ++i) { | 600 | for (i = 0; i < sg_cnt; ++i) { |
586 | if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) { | 601 | if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) { |
@@ -615,9 +630,10 @@ static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat, | |||
615 | (sg_dma_address(&scat[i]) & dev->fmr_page_mask) + j; | 630 | (sg_dma_address(&scat[i]) & dev->fmr_page_mask) + j; |
616 | 631 | ||
617 | req->fmr = ib_fmr_pool_map_phys(dev->fmr_pool, | 632 | req->fmr = ib_fmr_pool_map_phys(dev->fmr_pool, |
618 | dma_pages, page_cnt, &io_addr); | 633 | dma_pages, page_cnt, io_addr); |
619 | if (IS_ERR(req->fmr)) { | 634 | if (IS_ERR(req->fmr)) { |
620 | ret = PTR_ERR(req->fmr); | 635 | ret = PTR_ERR(req->fmr); |
636 | req->fmr = NULL; | ||
621 | goto out; | 637 | goto out; |
622 | } | 638 | } |
623 | 639 | ||
@@ -682,7 +698,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, | |||
682 | buf->va = cpu_to_be64(sg_dma_address(scat)); | 698 | buf->va = cpu_to_be64(sg_dma_address(scat)); |
683 | buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey); | 699 | buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey); |
684 | buf->len = cpu_to_be32(sg_dma_len(scat)); | 700 | buf->len = cpu_to_be32(sg_dma_len(scat)); |
685 | } else if (srp_map_fmr(target->srp_host->dev, scat, count, req, | 701 | } else if (srp_map_fmr(target, scat, count, req, |
686 | (void *) cmd->add_data)) { | 702 | (void *) cmd->add_data)) { |
687 | /* | 703 | /* |
688 | * FMR mapping failed, and the scatterlist has more | 704 | * FMR mapping failed, and the scatterlist has more |