diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 18:29:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 18:29:11 -0400 |
commit | 829d464e60151a525c7ba57e7acfc4fc297f7069 (patch) | |
tree | 6307966acabb65f332213cb886fddd4f0821c164 /drivers | |
parent | b65d04a7859f4cfea1a40de260cb52d8f7897aff (diff) | |
parent | e5a010690141ab805b059ba10f7401b80e0be831 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
IB/ehca: Tweak trace message format
IB/ehca: Fix device registration
IB/ipath: Fix RDMA reads
RDMA/cma: Optimize error handling
RDMA/cma: Eliminate unnecessary remove_list
RDMA/cma: Set status correctly on route resolution error
RDMA/cma: Fix device removal race
RDMA/cma: Fix leak of cm_ids in case of failures
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/infiniband/core/cma.c | 47 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_main.c | 36 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_tools.h | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_rc.c | 59 |
4 files changed, 80 insertions, 64 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 1178bd434d1b..9ae4f3a67c70 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
@@ -874,23 +874,25 @@ static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id, | |||
874 | __u16 port; | 874 | __u16 port; |
875 | u8 ip_ver; | 875 | u8 ip_ver; |
876 | 876 | ||
877 | if (cma_get_net_info(ib_event->private_data, listen_id->ps, | ||
878 | &ip_ver, &port, &src, &dst)) | ||
879 | goto err; | ||
880 | |||
877 | id = rdma_create_id(listen_id->event_handler, listen_id->context, | 881 | id = rdma_create_id(listen_id->event_handler, listen_id->context, |
878 | listen_id->ps); | 882 | listen_id->ps); |
879 | if (IS_ERR(id)) | 883 | if (IS_ERR(id)) |
880 | return NULL; | 884 | goto err; |
885 | |||
886 | cma_save_net_info(&id->route.addr, &listen_id->route.addr, | ||
887 | ip_ver, port, src, dst); | ||
881 | 888 | ||
882 | rt = &id->route; | 889 | rt = &id->route; |
883 | rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1; | 890 | rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1; |
884 | rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths, GFP_KERNEL); | 891 | rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths, |
892 | GFP_KERNEL); | ||
885 | if (!rt->path_rec) | 893 | if (!rt->path_rec) |
886 | goto err; | 894 | goto destroy_id; |
887 | 895 | ||
888 | if (cma_get_net_info(ib_event->private_data, listen_id->ps, | ||
889 | &ip_ver, &port, &src, &dst)) | ||
890 | goto err; | ||
891 | |||
892 | cma_save_net_info(&id->route.addr, &listen_id->route.addr, | ||
893 | ip_ver, port, src, dst); | ||
894 | rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path; | 896 | rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path; |
895 | if (rt->num_paths == 2) | 897 | if (rt->num_paths == 2) |
896 | rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path; | 898 | rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path; |
@@ -903,8 +905,10 @@ static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id, | |||
903 | id_priv = container_of(id, struct rdma_id_private, id); | 905 | id_priv = container_of(id, struct rdma_id_private, id); |
904 | id_priv->state = CMA_CONNECT; | 906 | id_priv->state = CMA_CONNECT; |
905 | return id_priv; | 907 | return id_priv; |
906 | err: | 908 | |
909 | destroy_id: | ||
907 | rdma_destroy_id(id); | 910 | rdma_destroy_id(id); |
911 | err: | ||
908 | return NULL; | 912 | return NULL; |
909 | } | 913 | } |
910 | 914 | ||
@@ -932,6 +936,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) | |||
932 | mutex_unlock(&lock); | 936 | mutex_unlock(&lock); |
933 | if (ret) { | 937 | if (ret) { |
934 | ret = -ENODEV; | 938 | ret = -ENODEV; |
939 | cma_exch(conn_id, CMA_DESTROYING); | ||
935 | cma_release_remove(conn_id); | 940 | cma_release_remove(conn_id); |
936 | rdma_destroy_id(&conn_id->id); | 941 | rdma_destroy_id(&conn_id->id); |
937 | goto out; | 942 | goto out; |
@@ -1307,6 +1312,7 @@ static void cma_query_handler(int status, struct ib_sa_path_rec *path_rec, | |||
1307 | work->old_state = CMA_ROUTE_QUERY; | 1312 | work->old_state = CMA_ROUTE_QUERY; |
1308 | work->new_state = CMA_ADDR_RESOLVED; | 1313 | work->new_state = CMA_ADDR_RESOLVED; |
1309 | work->event.event = RDMA_CM_EVENT_ROUTE_ERROR; | 1314 | work->event.event = RDMA_CM_EVENT_ROUTE_ERROR; |
1315 | work->event.status = status; | ||
1310 | } | 1316 | } |
1311 | 1317 | ||
1312 | queue_work(cma_wq, &work->work); | 1318 | queue_work(cma_wq, &work->work); |
@@ -1862,6 +1868,11 @@ static int cma_connect_ib(struct rdma_id_private *id_priv, | |||
1862 | 1868 | ||
1863 | ret = ib_send_cm_req(id_priv->cm_id.ib, &req); | 1869 | ret = ib_send_cm_req(id_priv->cm_id.ib, &req); |
1864 | out: | 1870 | out: |
1871 | if (ret && !IS_ERR(id_priv->cm_id.ib)) { | ||
1872 | ib_destroy_cm_id(id_priv->cm_id.ib); | ||
1873 | id_priv->cm_id.ib = NULL; | ||
1874 | } | ||
1875 | |||
1865 | kfree(private_data); | 1876 | kfree(private_data); |
1866 | return ret; | 1877 | return ret; |
1867 | } | 1878 | } |
@@ -1889,10 +1900,8 @@ static int cma_connect_iw(struct rdma_id_private *id_priv, | |||
1889 | cm_id->remote_addr = *sin; | 1900 | cm_id->remote_addr = *sin; |
1890 | 1901 | ||
1891 | ret = cma_modify_qp_rtr(&id_priv->id); | 1902 | ret = cma_modify_qp_rtr(&id_priv->id); |
1892 | if (ret) { | 1903 | if (ret) |
1893 | iw_destroy_cm_id(cm_id); | 1904 | goto out; |
1894 | return ret; | ||
1895 | } | ||
1896 | 1905 | ||
1897 | iw_param.ord = conn_param->initiator_depth; | 1906 | iw_param.ord = conn_param->initiator_depth; |
1898 | iw_param.ird = conn_param->responder_resources; | 1907 | iw_param.ird = conn_param->responder_resources; |
@@ -1904,6 +1913,10 @@ static int cma_connect_iw(struct rdma_id_private *id_priv, | |||
1904 | iw_param.qpn = conn_param->qp_num; | 1913 | iw_param.qpn = conn_param->qp_num; |
1905 | ret = iw_cm_connect(cm_id, &iw_param); | 1914 | ret = iw_cm_connect(cm_id, &iw_param); |
1906 | out: | 1915 | out: |
1916 | if (ret && !IS_ERR(cm_id)) { | ||
1917 | iw_destroy_cm_id(cm_id); | ||
1918 | id_priv->cm_id.iw = NULL; | ||
1919 | } | ||
1907 | return ret; | 1920 | return ret; |
1908 | } | 1921 | } |
1909 | 1922 | ||
@@ -2142,12 +2155,9 @@ static int cma_remove_id_dev(struct rdma_id_private *id_priv) | |||
2142 | 2155 | ||
2143 | static void cma_process_remove(struct cma_device *cma_dev) | 2156 | static void cma_process_remove(struct cma_device *cma_dev) |
2144 | { | 2157 | { |
2145 | struct list_head remove_list; | ||
2146 | struct rdma_id_private *id_priv; | 2158 | struct rdma_id_private *id_priv; |
2147 | int ret; | 2159 | int ret; |
2148 | 2160 | ||
2149 | INIT_LIST_HEAD(&remove_list); | ||
2150 | |||
2151 | mutex_lock(&lock); | 2161 | mutex_lock(&lock); |
2152 | while (!list_empty(&cma_dev->id_list)) { | 2162 | while (!list_empty(&cma_dev->id_list)) { |
2153 | id_priv = list_entry(cma_dev->id_list.next, | 2163 | id_priv = list_entry(cma_dev->id_list.next, |
@@ -2158,8 +2168,7 @@ static void cma_process_remove(struct cma_device *cma_dev) | |||
2158 | continue; | 2168 | continue; |
2159 | } | 2169 | } |
2160 | 2170 | ||
2161 | list_del(&id_priv->list); | 2171 | list_del_init(&id_priv->list); |
2162 | list_add_tail(&id_priv->list, &remove_list); | ||
2163 | atomic_inc(&id_priv->refcount); | 2172 | atomic_inc(&id_priv->refcount); |
2164 | mutex_unlock(&lock); | 2173 | mutex_unlock(&lock); |
2165 | 2174 | ||
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index 2380994418a5..024d511c4b58 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |||
@@ -49,7 +49,7 @@ | |||
49 | MODULE_LICENSE("Dual BSD/GPL"); | 49 | MODULE_LICENSE("Dual BSD/GPL"); |
50 | MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>"); | 50 | MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>"); |
51 | MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver"); | 51 | MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver"); |
52 | MODULE_VERSION("SVNEHCA_0016"); | 52 | MODULE_VERSION("SVNEHCA_0017"); |
53 | 53 | ||
54 | int ehca_open_aqp1 = 0; | 54 | int ehca_open_aqp1 = 0; |
55 | int ehca_debug_level = 0; | 55 | int ehca_debug_level = 0; |
@@ -239,7 +239,7 @@ init_node_guid1: | |||
239 | return ret; | 239 | return ret; |
240 | } | 240 | } |
241 | 241 | ||
242 | int ehca_register_device(struct ehca_shca *shca) | 242 | int ehca_init_device(struct ehca_shca *shca) |
243 | { | 243 | { |
244 | int ret; | 244 | int ret; |
245 | 245 | ||
@@ -317,11 +317,6 @@ int ehca_register_device(struct ehca_shca *shca) | |||
317 | /* shca->ib_device.process_mad = ehca_process_mad; */ | 317 | /* shca->ib_device.process_mad = ehca_process_mad; */ |
318 | shca->ib_device.mmap = ehca_mmap; | 318 | shca->ib_device.mmap = ehca_mmap; |
319 | 319 | ||
320 | ret = ib_register_device(&shca->ib_device); | ||
321 | if (ret) | ||
322 | ehca_err(&shca->ib_device, | ||
323 | "ib_register_device() failed ret=%x", ret); | ||
324 | |||
325 | return ret; | 320 | return ret; |
326 | } | 321 | } |
327 | 322 | ||
@@ -561,9 +556,9 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev, | |||
561 | goto probe1; | 556 | goto probe1; |
562 | } | 557 | } |
563 | 558 | ||
564 | ret = ehca_register_device(shca); | 559 | ret = ehca_init_device(shca); |
565 | if (ret) { | 560 | if (ret) { |
566 | ehca_gen_err("Cannot register Infiniband device"); | 561 | ehca_gen_err("Cannot init ehca device struct"); |
567 | goto probe1; | 562 | goto probe1; |
568 | } | 563 | } |
569 | 564 | ||
@@ -571,7 +566,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev, | |||
571 | ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, 2048); | 566 | ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, 2048); |
572 | if (ret) { | 567 | if (ret) { |
573 | ehca_err(&shca->ib_device, "Cannot create EQ."); | 568 | ehca_err(&shca->ib_device, "Cannot create EQ."); |
574 | goto probe2; | 569 | goto probe1; |
575 | } | 570 | } |
576 | 571 | ||
577 | ret = ehca_create_eq(shca, &shca->neq, EHCA_NEQ, 513); | 572 | ret = ehca_create_eq(shca, &shca->neq, EHCA_NEQ, 513); |
@@ -600,6 +595,13 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev, | |||
600 | goto probe5; | 595 | goto probe5; |
601 | } | 596 | } |
602 | 597 | ||
598 | ret = ib_register_device(&shca->ib_device); | ||
599 | if (ret) { | ||
600 | ehca_err(&shca->ib_device, | ||
601 | "ib_register_device() failed ret=%x", ret); | ||
602 | goto probe6; | ||
603 | } | ||
604 | |||
603 | /* create AQP1 for port 1 */ | 605 | /* create AQP1 for port 1 */ |
604 | if (ehca_open_aqp1 == 1) { | 606 | if (ehca_open_aqp1 == 1) { |
605 | shca->sport[0].port_state = IB_PORT_DOWN; | 607 | shca->sport[0].port_state = IB_PORT_DOWN; |
@@ -607,7 +609,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev, | |||
607 | if (ret) { | 609 | if (ret) { |
608 | ehca_err(&shca->ib_device, | 610 | ehca_err(&shca->ib_device, |
609 | "Cannot create AQP1 for port 1."); | 611 | "Cannot create AQP1 for port 1."); |
610 | goto probe6; | 612 | goto probe7; |
611 | } | 613 | } |
612 | } | 614 | } |
613 | 615 | ||
@@ -618,7 +620,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev, | |||
618 | if (ret) { | 620 | if (ret) { |
619 | ehca_err(&shca->ib_device, | 621 | ehca_err(&shca->ib_device, |
620 | "Cannot create AQP1 for port 2."); | 622 | "Cannot create AQP1 for port 2."); |
621 | goto probe7; | 623 | goto probe8; |
622 | } | 624 | } |
623 | } | 625 | } |
624 | 626 | ||
@@ -630,12 +632,15 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev, | |||
630 | 632 | ||
631 | return 0; | 633 | return 0; |
632 | 634 | ||
633 | probe7: | 635 | probe8: |
634 | ret = ehca_destroy_aqp1(&shca->sport[0]); | 636 | ret = ehca_destroy_aqp1(&shca->sport[0]); |
635 | if (ret) | 637 | if (ret) |
636 | ehca_err(&shca->ib_device, | 638 | ehca_err(&shca->ib_device, |
637 | "Cannot destroy AQP1 for port 1. ret=%x", ret); | 639 | "Cannot destroy AQP1 for port 1. ret=%x", ret); |
638 | 640 | ||
641 | probe7: | ||
642 | ib_unregister_device(&shca->ib_device); | ||
643 | |||
639 | probe6: | 644 | probe6: |
640 | ret = ehca_dereg_internal_maxmr(shca); | 645 | ret = ehca_dereg_internal_maxmr(shca); |
641 | if (ret) | 646 | if (ret) |
@@ -660,9 +665,6 @@ probe3: | |||
660 | ehca_err(&shca->ib_device, | 665 | ehca_err(&shca->ib_device, |
661 | "Cannot destroy EQ. ret=%x", ret); | 666 | "Cannot destroy EQ. ret=%x", ret); |
662 | 667 | ||
663 | probe2: | ||
664 | ib_unregister_device(&shca->ib_device); | ||
665 | |||
666 | probe1: | 668 | probe1: |
667 | ib_dealloc_device(&shca->ib_device); | 669 | ib_dealloc_device(&shca->ib_device); |
668 | 670 | ||
@@ -750,7 +752,7 @@ int __init ehca_module_init(void) | |||
750 | int ret; | 752 | int ret; |
751 | 753 | ||
752 | printk(KERN_INFO "eHCA Infiniband Device Driver " | 754 | printk(KERN_INFO "eHCA Infiniband Device Driver " |
753 | "(Rel.: SVNEHCA_0016)\n"); | 755 | "(Rel.: SVNEHCA_0017)\n"); |
754 | idr_init(&ehca_qp_idr); | 756 | idr_init(&ehca_qp_idr); |
755 | idr_init(&ehca_cq_idr); | 757 | idr_init(&ehca_cq_idr); |
756 | spin_lock_init(&ehca_qp_idr_lock); | 758 | spin_lock_init(&ehca_qp_idr_lock); |
diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h index 9f56bb846d93..809da3ef706b 100644 --- a/drivers/infiniband/hw/ehca/ehca_tools.h +++ b/drivers/infiniband/hw/ehca/ehca_tools.h | |||
@@ -117,7 +117,7 @@ extern int ehca_debug_level; | |||
117 | unsigned int l = (unsigned int)(len); \ | 117 | unsigned int l = (unsigned int)(len); \ |
118 | unsigned char *deb = (unsigned char*)(adr); \ | 118 | unsigned char *deb = (unsigned char*)(adr); \ |
119 | for (x = 0; x < l; x += 16) { \ | 119 | for (x = 0; x < l; x += 16) { \ |
120 | printk("EHCA_DMP:%s" format \ | 120 | printk("EHCA_DMP:%s " format \ |
121 | " adr=%p ofs=%04x %016lx %016lx\n", \ | 121 | " adr=%p ofs=%04x %016lx %016lx\n", \ |
122 | __FUNCTION__, ##args, deb, x, \ | 122 | __FUNCTION__, ##args, deb, x, \ |
123 | *((u64 *)&deb[0]), *((u64 *)&deb[8])); \ | 123 | *((u64 *)&deb[0]), *((u64 *)&deb[8])); \ |
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index a504cf67f272..ce6038743c5c 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c | |||
@@ -241,10 +241,7 @@ int ipath_make_rc_req(struct ipath_qp *qp, | |||
241 | * original work request since we may need to resend | 241 | * original work request since we may need to resend |
242 | * it. | 242 | * it. |
243 | */ | 243 | */ |
244 | qp->s_sge.sge = wqe->sg_list[0]; | 244 | len = wqe->length; |
245 | qp->s_sge.sg_list = wqe->sg_list + 1; | ||
246 | qp->s_sge.num_sge = wqe->wr.num_sge; | ||
247 | qp->s_len = len = wqe->length; | ||
248 | ss = &qp->s_sge; | 245 | ss = &qp->s_sge; |
249 | bth2 = 0; | 246 | bth2 = 0; |
250 | switch (wqe->wr.opcode) { | 247 | switch (wqe->wr.opcode) { |
@@ -368,14 +365,23 @@ int ipath_make_rc_req(struct ipath_qp *qp, | |||
368 | default: | 365 | default: |
369 | goto done; | 366 | goto done; |
370 | } | 367 | } |
368 | qp->s_sge.sge = wqe->sg_list[0]; | ||
369 | qp->s_sge.sg_list = wqe->sg_list + 1; | ||
370 | qp->s_sge.num_sge = wqe->wr.num_sge; | ||
371 | qp->s_len = wqe->length; | ||
371 | if (newreq) { | 372 | if (newreq) { |
372 | qp->s_tail++; | 373 | qp->s_tail++; |
373 | if (qp->s_tail >= qp->s_size) | 374 | if (qp->s_tail >= qp->s_size) |
374 | qp->s_tail = 0; | 375 | qp->s_tail = 0; |
375 | } | 376 | } |
376 | bth2 |= qp->s_psn++ & IPATH_PSN_MASK; | 377 | bth2 |= qp->s_psn & IPATH_PSN_MASK; |
377 | if ((int)(qp->s_psn - qp->s_next_psn) > 0) | 378 | if (wqe->wr.opcode == IB_WR_RDMA_READ) |
378 | qp->s_next_psn = qp->s_psn; | 379 | qp->s_psn = wqe->lpsn + 1; |
380 | else { | ||
381 | qp->s_psn++; | ||
382 | if ((int)(qp->s_psn - qp->s_next_psn) > 0) | ||
383 | qp->s_next_psn = qp->s_psn; | ||
384 | } | ||
379 | /* | 385 | /* |
380 | * Put the QP on the pending list so lost ACKs will cause | 386 | * Put the QP on the pending list so lost ACKs will cause |
381 | * a retry. More than one request can be pending so the | 387 | * a retry. More than one request can be pending so the |
@@ -690,13 +696,6 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc) | |||
690 | struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last); | 696 | struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last); |
691 | struct ipath_ibdev *dev; | 697 | struct ipath_ibdev *dev; |
692 | 698 | ||
693 | /* | ||
694 | * If there are no requests pending, we are done. | ||
695 | */ | ||
696 | if (ipath_cmp24(psn, qp->s_next_psn) >= 0 || | ||
697 | qp->s_last == qp->s_tail) | ||
698 | goto done; | ||
699 | |||
700 | if (qp->s_retry == 0) { | 699 | if (qp->s_retry == 0) { |
701 | wc->wr_id = wqe->wr.wr_id; | 700 | wc->wr_id = wqe->wr.wr_id; |
702 | wc->status = IB_WC_RETRY_EXC_ERR; | 701 | wc->status = IB_WC_RETRY_EXC_ERR; |
@@ -731,8 +730,6 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc) | |||
731 | dev->n_rc_resends += (int)qp->s_psn - (int)psn; | 730 | dev->n_rc_resends += (int)qp->s_psn - (int)psn; |
732 | 731 | ||
733 | reset_psn(qp, psn); | 732 | reset_psn(qp, psn); |
734 | |||
735 | done: | ||
736 | tasklet_hi_schedule(&qp->s_task); | 733 | tasklet_hi_schedule(&qp->s_task); |
737 | 734 | ||
738 | bail: | 735 | bail: |
@@ -765,6 +762,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) | |||
765 | struct ib_wc wc; | 762 | struct ib_wc wc; |
766 | struct ipath_swqe *wqe; | 763 | struct ipath_swqe *wqe; |
767 | int ret = 0; | 764 | int ret = 0; |
765 | u32 ack_psn; | ||
768 | 766 | ||
769 | /* | 767 | /* |
770 | * Remove the QP from the timeout queue (or RNR timeout queue). | 768 | * Remove the QP from the timeout queue (or RNR timeout queue). |
@@ -777,26 +775,26 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) | |||
777 | list_del_init(&qp->timerwait); | 775 | list_del_init(&qp->timerwait); |
778 | spin_unlock(&dev->pending_lock); | 776 | spin_unlock(&dev->pending_lock); |
779 | 777 | ||
778 | /* Nothing is pending to ACK/NAK. */ | ||
779 | if (unlikely(qp->s_last == qp->s_tail)) | ||
780 | goto bail; | ||
781 | |||
780 | /* | 782 | /* |
781 | * Note that NAKs implicitly ACK outstanding SEND and RDMA write | 783 | * Note that NAKs implicitly ACK outstanding SEND and RDMA write |
782 | * requests and implicitly NAK RDMA read and atomic requests issued | 784 | * requests and implicitly NAK RDMA read and atomic requests issued |
783 | * before the NAK'ed request. The MSN won't include the NAK'ed | 785 | * before the NAK'ed request. The MSN won't include the NAK'ed |
784 | * request but will include an ACK'ed request(s). | 786 | * request but will include an ACK'ed request(s). |
785 | */ | 787 | */ |
788 | ack_psn = psn; | ||
789 | if (aeth >> 29) | ||
790 | ack_psn--; | ||
786 | wqe = get_swqe_ptr(qp, qp->s_last); | 791 | wqe = get_swqe_ptr(qp, qp->s_last); |
787 | 792 | ||
788 | /* Nothing is pending to ACK/NAK. */ | ||
789 | if (qp->s_last == qp->s_tail) | ||
790 | goto bail; | ||
791 | |||
792 | /* | 793 | /* |
793 | * The MSN might be for a later WQE than the PSN indicates so | 794 | * The MSN might be for a later WQE than the PSN indicates so |
794 | * only complete WQEs that the PSN finishes. | 795 | * only complete WQEs that the PSN finishes. |
795 | */ | 796 | */ |
796 | while (ipath_cmp24(psn, wqe->lpsn) >= 0) { | 797 | while (ipath_cmp24(ack_psn, wqe->lpsn) >= 0) { |
797 | /* If we are ACKing a WQE, the MSN should be >= the SSN. */ | ||
798 | if (ipath_cmp24(aeth, wqe->ssn) < 0) | ||
799 | break; | ||
800 | /* | 798 | /* |
801 | * If this request is a RDMA read or atomic, and the ACK is | 799 | * If this request is a RDMA read or atomic, and the ACK is |
802 | * for a later operation, this ACK NAKs the RDMA read or | 800 | * for a later operation, this ACK NAKs the RDMA read or |
@@ -807,7 +805,8 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) | |||
807 | * is sent but before the response is received. | 805 | * is sent but before the response is received. |
808 | */ | 806 | */ |
809 | if ((wqe->wr.opcode == IB_WR_RDMA_READ && | 807 | if ((wqe->wr.opcode == IB_WR_RDMA_READ && |
810 | opcode != OP(RDMA_READ_RESPONSE_LAST)) || | 808 | (opcode != OP(RDMA_READ_RESPONSE_LAST) || |
809 | ipath_cmp24(ack_psn, wqe->lpsn) != 0)) || | ||
811 | ((wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || | 810 | ((wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || |
812 | wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) && | 811 | wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) && |
813 | (opcode != OP(ATOMIC_ACKNOWLEDGE) || | 812 | (opcode != OP(ATOMIC_ACKNOWLEDGE) || |
@@ -825,6 +824,10 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) | |||
825 | */ | 824 | */ |
826 | goto bail; | 825 | goto bail; |
827 | } | 826 | } |
827 | if (wqe->wr.opcode == IB_WR_RDMA_READ || | ||
828 | wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP || | ||
829 | wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) | ||
830 | tasklet_hi_schedule(&qp->s_task); | ||
828 | /* Post a send completion queue entry if requested. */ | 831 | /* Post a send completion queue entry if requested. */ |
829 | if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &qp->s_flags) || | 832 | if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &qp->s_flags) || |
830 | (wqe->wr.send_flags & IB_SEND_SIGNALED)) { | 833 | (wqe->wr.send_flags & IB_SEND_SIGNALED)) { |
@@ -1055,7 +1058,8 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, | |||
1055 | /* no AETH, no ACK */ | 1058 | /* no AETH, no ACK */ |
1056 | if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) { | 1059 | if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) { |
1057 | dev->n_rdma_seq++; | 1060 | dev->n_rdma_seq++; |
1058 | ipath_restart_rc(qp, qp->s_last_psn + 1, &wc); | 1061 | if (qp->s_last != qp->s_tail) |
1062 | ipath_restart_rc(qp, qp->s_last_psn + 1, &wc); | ||
1059 | goto ack_done; | 1063 | goto ack_done; |
1060 | } | 1064 | } |
1061 | rdma_read: | 1065 | rdma_read: |
@@ -1091,7 +1095,8 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, | |||
1091 | /* ACKs READ req. */ | 1095 | /* ACKs READ req. */ |
1092 | if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) { | 1096 | if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) { |
1093 | dev->n_rdma_seq++; | 1097 | dev->n_rdma_seq++; |
1094 | ipath_restart_rc(qp, qp->s_last_psn + 1, &wc); | 1098 | if (qp->s_last != qp->s_tail) |
1099 | ipath_restart_rc(qp, qp->s_last_psn + 1, &wc); | ||
1095 | goto ack_done; | 1100 | goto ack_done; |
1096 | } | 1101 | } |
1097 | /* FALLTHROUGH */ | 1102 | /* FALLTHROUGH */ |