diff options
50 files changed, 1096 insertions, 510 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 8dca9d89c6c1..989ff1149390 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -439,7 +439,7 @@ F: drivers/hwmon/ams/ | |||
| 439 | AMSO1100 RNIC DRIVER | 439 | AMSO1100 RNIC DRIVER |
| 440 | M: Tom Tucker <tom@opengridcomputing.com> | 440 | M: Tom Tucker <tom@opengridcomputing.com> |
| 441 | M: Steve Wise <swise@opengridcomputing.com> | 441 | M: Steve Wise <swise@opengridcomputing.com> |
| 442 | L: general@lists.openfabrics.org | 442 | L: linux-rdma@vger.kernel.org |
| 443 | S: Maintained | 443 | S: Maintained |
| 444 | F: drivers/infiniband/hw/amso1100/ | 444 | F: drivers/infiniband/hw/amso1100/ |
| 445 | 445 | ||
| @@ -1494,7 +1494,7 @@ F: drivers/net/cxgb3/ | |||
| 1494 | 1494 | ||
| 1495 | CXGB3 IWARP RNIC DRIVER (IW_CXGB3) | 1495 | CXGB3 IWARP RNIC DRIVER (IW_CXGB3) |
| 1496 | M: Steve Wise <swise@chelsio.com> | 1496 | M: Steve Wise <swise@chelsio.com> |
| 1497 | L: general@lists.openfabrics.org | 1497 | L: linux-rdma@vger.kernel.org |
| 1498 | W: http://www.openfabrics.org | 1498 | W: http://www.openfabrics.org |
| 1499 | S: Supported | 1499 | S: Supported |
| 1500 | F: drivers/infiniband/hw/cxgb3/ | 1500 | F: drivers/infiniband/hw/cxgb3/ |
| @@ -1868,7 +1868,7 @@ F: fs/efs/ | |||
| 1868 | EHCA (IBM GX bus InfiniBand adapter) DRIVER | 1868 | EHCA (IBM GX bus InfiniBand adapter) DRIVER |
| 1869 | M: Hoang-Nam Nguyen <hnguyen@de.ibm.com> | 1869 | M: Hoang-Nam Nguyen <hnguyen@de.ibm.com> |
| 1870 | M: Christoph Raisch <raisch@de.ibm.com> | 1870 | M: Christoph Raisch <raisch@de.ibm.com> |
| 1871 | L: general@lists.openfabrics.org | 1871 | L: linux-rdma@vger.kernel.org |
| 1872 | S: Supported | 1872 | S: Supported |
| 1873 | F: drivers/infiniband/hw/ehca/ | 1873 | F: drivers/infiniband/hw/ehca/ |
| 1874 | 1874 | ||
| @@ -2552,7 +2552,7 @@ INFINIBAND SUBSYSTEM | |||
| 2552 | M: Roland Dreier <rolandd@cisco.com> | 2552 | M: Roland Dreier <rolandd@cisco.com> |
| 2553 | M: Sean Hefty <sean.hefty@intel.com> | 2553 | M: Sean Hefty <sean.hefty@intel.com> |
| 2554 | M: Hal Rosenstock <hal.rosenstock@gmail.com> | 2554 | M: Hal Rosenstock <hal.rosenstock@gmail.com> |
| 2555 | L: general@lists.openfabrics.org (moderated for non-subscribers) | 2555 | L: linux-rdma@vger.kernel.org |
| 2556 | W: http://www.openib.org/ | 2556 | W: http://www.openib.org/ |
| 2557 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git | 2557 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git |
| 2558 | S: Supported | 2558 | S: Supported |
| @@ -2729,7 +2729,7 @@ F: drivers/net/ipg.c | |||
| 2729 | 2729 | ||
| 2730 | IPATH DRIVER | 2730 | IPATH DRIVER |
| 2731 | M: Ralph Campbell <infinipath@qlogic.com> | 2731 | M: Ralph Campbell <infinipath@qlogic.com> |
| 2732 | L: general@lists.openfabrics.org | 2732 | L: linux-rdma@vger.kernel.org |
| 2733 | T: git git://git.qlogic.com/ipath-linux-2.6 | 2733 | T: git git://git.qlogic.com/ipath-linux-2.6 |
| 2734 | S: Supported | 2734 | S: Supported |
| 2735 | F: drivers/infiniband/hw/ipath/ | 2735 | F: drivers/infiniband/hw/ipath/ |
| @@ -3485,7 +3485,7 @@ F: drivers/scsi/NCR_D700.* | |||
| 3485 | NETEFFECT IWARP RNIC DRIVER (IW_NES) | 3485 | NETEFFECT IWARP RNIC DRIVER (IW_NES) |
| 3486 | M: Faisal Latif <faisal.latif@intel.com> | 3486 | M: Faisal Latif <faisal.latif@intel.com> |
| 3487 | M: Chien Tung <chien.tin.tung@intel.com> | 3487 | M: Chien Tung <chien.tin.tung@intel.com> |
| 3488 | L: general@lists.openfabrics.org | 3488 | L: linux-rdma@vger.kernel.org |
| 3489 | W: http://www.neteffect.com | 3489 | W: http://www.neteffect.com |
| 3490 | S: Supported | 3490 | S: Supported |
| 3491 | F: drivers/infiniband/hw/nes/ | 3491 | F: drivers/infiniband/hw/nes/ |
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 8f9509e1ebf7..55d093a36ae4 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c | |||
| @@ -362,6 +362,7 @@ static void destroy_cm_id(struct iw_cm_id *cm_id) | |||
| 362 | * In either case, must tell the provider to reject. | 362 | * In either case, must tell the provider to reject. |
| 363 | */ | 363 | */ |
| 364 | cm_id_priv->state = IW_CM_STATE_DESTROYING; | 364 | cm_id_priv->state = IW_CM_STATE_DESTROYING; |
| 365 | cm_id->device->iwcm->reject(cm_id, NULL, 0); | ||
| 365 | break; | 366 | break; |
| 366 | case IW_CM_STATE_CONN_SENT: | 367 | case IW_CM_STATE_CONN_SENT: |
| 367 | case IW_CM_STATE_DESTROYING: | 368 | case IW_CM_STATE_DESTROYING: |
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index de922a04ca2d..5cef8f87b96b 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c | |||
| @@ -51,8 +51,7 @@ static struct list_head ib_mad_port_list; | |||
| 51 | static u32 ib_mad_client_id = 0; | 51 | static u32 ib_mad_client_id = 0; |
| 52 | 52 | ||
| 53 | /* Port list lock */ | 53 | /* Port list lock */ |
| 54 | static spinlock_t ib_mad_port_list_lock; | 54 | static DEFINE_SPINLOCK(ib_mad_port_list_lock); |
| 55 | |||
| 56 | 55 | ||
| 57 | /* Forward declarations */ | 56 | /* Forward declarations */ |
| 58 | static int method_in_use(struct ib_mad_mgmt_method_table **method, | 57 | static int method_in_use(struct ib_mad_mgmt_method_table **method, |
| @@ -2984,8 +2983,6 @@ static int __init ib_mad_init_module(void) | |||
| 2984 | { | 2983 | { |
| 2985 | int ret; | 2984 | int ret; |
| 2986 | 2985 | ||
| 2987 | spin_lock_init(&ib_mad_port_list_lock); | ||
| 2988 | |||
| 2989 | ib_mad_cache = kmem_cache_create("ib_mad", | 2986 | ib_mad_cache = kmem_cache_create("ib_mad", |
| 2990 | sizeof(struct ib_mad_private), | 2987 | sizeof(struct ib_mad_private), |
| 2991 | 0, | 2988 | 0, |
| @@ -3021,4 +3018,3 @@ static void __exit ib_mad_cleanup_module(void) | |||
| 3021 | 3018 | ||
| 3022 | module_init(ib_mad_init_module); | 3019 | module_init(ib_mad_init_module); |
| 3023 | module_exit(ib_mad_cleanup_module); | 3020 | module_exit(ib_mad_cleanup_module); |
| 3024 | |||
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c index 107f170c57cd..8d82ba171353 100644 --- a/drivers/infiniband/core/multicast.c +++ b/drivers/infiniband/core/multicast.c | |||
| @@ -106,6 +106,8 @@ struct mcast_group { | |||
| 106 | struct ib_sa_query *query; | 106 | struct ib_sa_query *query; |
| 107 | int query_id; | 107 | int query_id; |
| 108 | u16 pkey_index; | 108 | u16 pkey_index; |
| 109 | u8 leave_state; | ||
| 110 | int retries; | ||
| 109 | }; | 111 | }; |
| 110 | 112 | ||
| 111 | struct mcast_member { | 113 | struct mcast_member { |
| @@ -350,6 +352,7 @@ static int send_leave(struct mcast_group *group, u8 leave_state) | |||
| 350 | 352 | ||
| 351 | rec = group->rec; | 353 | rec = group->rec; |
| 352 | rec.join_state = leave_state; | 354 | rec.join_state = leave_state; |
| 355 | group->leave_state = leave_state; | ||
| 353 | 356 | ||
| 354 | ret = ib_sa_mcmember_rec_query(&sa_client, port->dev->device, | 357 | ret = ib_sa_mcmember_rec_query(&sa_client, port->dev->device, |
| 355 | port->port_num, IB_SA_METHOD_DELETE, &rec, | 358 | port->port_num, IB_SA_METHOD_DELETE, &rec, |
| @@ -542,7 +545,11 @@ static void leave_handler(int status, struct ib_sa_mcmember_rec *rec, | |||
| 542 | { | 545 | { |
| 543 | struct mcast_group *group = context; | 546 | struct mcast_group *group = context; |
| 544 | 547 | ||
| 545 | mcast_work_handler(&group->work); | 548 | if (status && group->retries > 0 && |
| 549 | !send_leave(group, group->leave_state)) | ||
| 550 | group->retries--; | ||
| 551 | else | ||
| 552 | mcast_work_handler(&group->work); | ||
| 546 | } | 553 | } |
| 547 | 554 | ||
| 548 | static struct mcast_group *acquire_group(struct mcast_port *port, | 555 | static struct mcast_group *acquire_group(struct mcast_port *port, |
| @@ -565,6 +572,7 @@ static struct mcast_group *acquire_group(struct mcast_port *port, | |||
| 565 | if (!group) | 572 | if (!group) |
| 566 | return NULL; | 573 | return NULL; |
| 567 | 574 | ||
| 575 | group->retries = 3; | ||
| 568 | group->port = port; | 576 | group->port = port; |
| 569 | group->rec.mgid = *mgid; | 577 | group->rec.mgid = *mgid; |
| 570 | group->pkey_index = MCAST_INVALID_PKEY_INDEX; | 578 | group->pkey_index = MCAST_INVALID_PKEY_INDEX; |
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 1865049e80f7..82543716d59e 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c | |||
| @@ -109,10 +109,10 @@ static struct ib_client sa_client = { | |||
| 109 | .remove = ib_sa_remove_one | 109 | .remove = ib_sa_remove_one |
| 110 | }; | 110 | }; |
| 111 | 111 | ||
| 112 | static spinlock_t idr_lock; | 112 | static DEFINE_SPINLOCK(idr_lock); |
| 113 | static DEFINE_IDR(query_idr); | 113 | static DEFINE_IDR(query_idr); |
| 114 | 114 | ||
| 115 | static spinlock_t tid_lock; | 115 | static DEFINE_SPINLOCK(tid_lock); |
| 116 | static u32 tid; | 116 | static u32 tid; |
| 117 | 117 | ||
| 118 | #define PATH_REC_FIELD(field) \ | 118 | #define PATH_REC_FIELD(field) \ |
| @@ -1077,9 +1077,6 @@ static int __init ib_sa_init(void) | |||
| 1077 | { | 1077 | { |
| 1078 | int ret; | 1078 | int ret; |
| 1079 | 1079 | ||
| 1080 | spin_lock_init(&idr_lock); | ||
| 1081 | spin_lock_init(&tid_lock); | ||
| 1082 | |||
| 1083 | get_random_bytes(&tid, sizeof tid); | 1080 | get_random_bytes(&tid, sizeof tid); |
| 1084 | 1081 | ||
| 1085 | ret = ib_register_client(&sa_client); | 1082 | ret = ib_register_client(&sa_client); |
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index eb36a81dd09b..d3fff9e008a3 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
| @@ -73,7 +73,7 @@ DEFINE_IDR(ib_uverbs_cq_idr); | |||
| 73 | DEFINE_IDR(ib_uverbs_qp_idr); | 73 | DEFINE_IDR(ib_uverbs_qp_idr); |
| 74 | DEFINE_IDR(ib_uverbs_srq_idr); | 74 | DEFINE_IDR(ib_uverbs_srq_idr); |
| 75 | 75 | ||
| 76 | static spinlock_t map_lock; | 76 | static DEFINE_SPINLOCK(map_lock); |
| 77 | static struct ib_uverbs_device *dev_table[IB_UVERBS_MAX_DEVICES]; | 77 | static struct ib_uverbs_device *dev_table[IB_UVERBS_MAX_DEVICES]; |
| 78 | static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES); | 78 | static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES); |
| 79 | 79 | ||
| @@ -584,14 +584,16 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, | |||
| 584 | 584 | ||
| 585 | if (hdr.command < 0 || | 585 | if (hdr.command < 0 || |
| 586 | hdr.command >= ARRAY_SIZE(uverbs_cmd_table) || | 586 | hdr.command >= ARRAY_SIZE(uverbs_cmd_table) || |
| 587 | !uverbs_cmd_table[hdr.command] || | 587 | !uverbs_cmd_table[hdr.command]) |
| 588 | !(file->device->ib_dev->uverbs_cmd_mask & (1ull << hdr.command))) | ||
| 589 | return -EINVAL; | 588 | return -EINVAL; |
| 590 | 589 | ||
| 591 | if (!file->ucontext && | 590 | if (!file->ucontext && |
| 592 | hdr.command != IB_USER_VERBS_CMD_GET_CONTEXT) | 591 | hdr.command != IB_USER_VERBS_CMD_GET_CONTEXT) |
| 593 | return -EINVAL; | 592 | return -EINVAL; |
| 594 | 593 | ||
| 594 | if (!(file->device->ib_dev->uverbs_cmd_mask & (1ull << hdr.command))) | ||
| 595 | return -ENOSYS; | ||
| 596 | |||
| 595 | return uverbs_cmd_table[hdr.command](file, buf + sizeof hdr, | 597 | return uverbs_cmd_table[hdr.command](file, buf + sizeof hdr, |
| 596 | hdr.in_words * 4, hdr.out_words * 4); | 598 | hdr.in_words * 4, hdr.out_words * 4); |
| 597 | } | 599 | } |
| @@ -836,8 +838,6 @@ static int __init ib_uverbs_init(void) | |||
| 836 | { | 838 | { |
| 837 | int ret; | 839 | int ret; |
| 838 | 840 | ||
| 839 | spin_lock_init(&map_lock); | ||
| 840 | |||
| 841 | ret = register_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES, | 841 | ret = register_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES, |
| 842 | "infiniband_verbs"); | 842 | "infiniband_verbs"); |
| 843 | if (ret) { | 843 | if (ret) { |
diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c index 0cfbb6d2f762..8250740c94b0 100644 --- a/drivers/infiniband/hw/amso1100/c2.c +++ b/drivers/infiniband/hw/amso1100/c2.c | |||
| @@ -86,11 +86,7 @@ MODULE_DEVICE_TABLE(pci, c2_pci_table); | |||
| 86 | 86 | ||
| 87 | static void c2_print_macaddr(struct net_device *netdev) | 87 | static void c2_print_macaddr(struct net_device *netdev) |
| 88 | { | 88 | { |
| 89 | pr_debug("%s: MAC %02X:%02X:%02X:%02X:%02X:%02X, " | 89 | pr_debug("%s: MAC %pM, IRQ %u\n", netdev->name, netdev->dev_addr, netdev->irq); |
| 90 | "IRQ %u\n", netdev->name, | ||
| 91 | netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], | ||
| 92 | netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5], | ||
| 93 | netdev->irq); | ||
| 94 | } | 90 | } |
| 95 | 91 | ||
| 96 | static void c2_set_rxbufsize(struct c2_port *c2_port) | 92 | static void c2_set_rxbufsize(struct c2_port *c2_port) |
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c index f1948fad85d7..ad723bd8bf49 100644 --- a/drivers/infiniband/hw/amso1100/c2_provider.c +++ b/drivers/infiniband/hw/amso1100/c2_provider.c | |||
| @@ -780,11 +780,11 @@ int c2_register_device(struct c2_dev *dev) | |||
| 780 | /* Register pseudo network device */ | 780 | /* Register pseudo network device */ |
| 781 | dev->pseudo_netdev = c2_pseudo_netdev_init(dev); | 781 | dev->pseudo_netdev = c2_pseudo_netdev_init(dev); |
| 782 | if (!dev->pseudo_netdev) | 782 | if (!dev->pseudo_netdev) |
| 783 | goto out3; | 783 | goto out; |
| 784 | 784 | ||
| 785 | ret = register_netdev(dev->pseudo_netdev); | 785 | ret = register_netdev(dev->pseudo_netdev); |
| 786 | if (ret) | 786 | if (ret) |
| 787 | goto out2; | 787 | goto out_free_netdev; |
| 788 | 788 | ||
| 789 | pr_debug("%s:%u\n", __func__, __LINE__); | 789 | pr_debug("%s:%u\n", __func__, __LINE__); |
| 790 | strlcpy(dev->ibdev.name, "amso%d", IB_DEVICE_NAME_MAX); | 790 | strlcpy(dev->ibdev.name, "amso%d", IB_DEVICE_NAME_MAX); |
| @@ -851,6 +851,10 @@ int c2_register_device(struct c2_dev *dev) | |||
| 851 | dev->ibdev.post_recv = c2_post_receive; | 851 | dev->ibdev.post_recv = c2_post_receive; |
| 852 | 852 | ||
| 853 | dev->ibdev.iwcm = kmalloc(sizeof(*dev->ibdev.iwcm), GFP_KERNEL); | 853 | dev->ibdev.iwcm = kmalloc(sizeof(*dev->ibdev.iwcm), GFP_KERNEL); |
| 854 | if (dev->ibdev.iwcm == NULL) { | ||
| 855 | ret = -ENOMEM; | ||
| 856 | goto out_unregister_netdev; | ||
| 857 | } | ||
| 854 | dev->ibdev.iwcm->add_ref = c2_add_ref; | 858 | dev->ibdev.iwcm->add_ref = c2_add_ref; |
| 855 | dev->ibdev.iwcm->rem_ref = c2_rem_ref; | 859 | dev->ibdev.iwcm->rem_ref = c2_rem_ref; |
| 856 | dev->ibdev.iwcm->get_qp = c2_get_qp; | 860 | dev->ibdev.iwcm->get_qp = c2_get_qp; |
| @@ -862,23 +866,25 @@ int c2_register_device(struct c2_dev *dev) | |||
| 862 | 866 | ||
| 863 | ret = ib_register_device(&dev->ibdev); | 867 | ret = ib_register_device(&dev->ibdev); |
| 864 | if (ret) | 868 | if (ret) |
| 865 | goto out1; | 869 | goto out_free_iwcm; |
| 866 | 870 | ||
| 867 | for (i = 0; i < ARRAY_SIZE(c2_dev_attributes); ++i) { | 871 | for (i = 0; i < ARRAY_SIZE(c2_dev_attributes); ++i) { |
| 868 | ret = device_create_file(&dev->ibdev.dev, | 872 | ret = device_create_file(&dev->ibdev.dev, |
| 869 | c2_dev_attributes[i]); | 873 | c2_dev_attributes[i]); |
| 870 | if (ret) | 874 | if (ret) |
| 871 | goto out0; | 875 | goto out_unregister_ibdev; |
| 872 | } | 876 | } |
| 873 | goto out3; | 877 | goto out; |
| 874 | 878 | ||
| 875 | out0: | 879 | out_unregister_ibdev: |
| 876 | ib_unregister_device(&dev->ibdev); | 880 | ib_unregister_device(&dev->ibdev); |
| 877 | out1: | 881 | out_free_iwcm: |
| 882 | kfree(dev->ibdev.iwcm); | ||
| 883 | out_unregister_netdev: | ||
| 878 | unregister_netdev(dev->pseudo_netdev); | 884 | unregister_netdev(dev->pseudo_netdev); |
| 879 | out2: | 885 | out_free_netdev: |
| 880 | free_netdev(dev->pseudo_netdev); | 886 | free_netdev(dev->pseudo_netdev); |
| 881 | out3: | 887 | out: |
| 882 | pr_debug("%s:%u ret=%d\n", __func__, __LINE__, ret); | 888 | pr_debug("%s:%u ret=%d\n", __func__, __LINE__, ret); |
| 883 | return ret; | 889 | return ret; |
| 884 | } | 890 | } |
diff --git a/drivers/infiniband/hw/cxgb3/iwch.c b/drivers/infiniband/hw/cxgb3/iwch.c index 3f0c99daae8c..b0ea0105ddf6 100644 --- a/drivers/infiniband/hw/cxgb3/iwch.c +++ b/drivers/infiniband/hw/cxgb3/iwch.c | |||
| @@ -105,11 +105,9 @@ static void rnic_init(struct iwch_dev *rnicp) | |||
| 105 | static void open_rnic_dev(struct t3cdev *tdev) | 105 | static void open_rnic_dev(struct t3cdev *tdev) |
| 106 | { | 106 | { |
| 107 | struct iwch_dev *rnicp; | 107 | struct iwch_dev *rnicp; |
| 108 | static int vers_printed; | ||
| 109 | 108 | ||
| 110 | PDBG("%s t3cdev %p\n", __func__, tdev); | 109 | PDBG("%s t3cdev %p\n", __func__, tdev); |
| 111 | if (!vers_printed++) | 110 | printk_once(KERN_INFO MOD "Chelsio T3 RDMA Driver - version %s\n", |
| 112 | printk(KERN_INFO MOD "Chelsio T3 RDMA Driver - version %s\n", | ||
| 113 | DRV_VERSION); | 111 | DRV_VERSION); |
| 114 | rnicp = (struct iwch_dev *)ib_alloc_device(sizeof(*rnicp)); | 112 | rnicp = (struct iwch_dev *)ib_alloc_device(sizeof(*rnicp)); |
| 115 | if (!rnicp) { | 113 | if (!rnicp) { |
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index fab18a2c74a8..5b635aa5947e 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | #include "ehca_tools.h" | 52 | #include "ehca_tools.h" |
| 53 | #include "hcp_if.h" | 53 | #include "hcp_if.h" |
| 54 | 54 | ||
| 55 | #define HCAD_VERSION "0028" | 55 | #define HCAD_VERSION "0029" |
| 56 | 56 | ||
| 57 | MODULE_LICENSE("Dual BSD/GPL"); | 57 | MODULE_LICENSE("Dual BSD/GPL"); |
| 58 | MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>"); | 58 | MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>"); |
| @@ -64,7 +64,7 @@ static int ehca_hw_level = 0; | |||
| 64 | static int ehca_poll_all_eqs = 1; | 64 | static int ehca_poll_all_eqs = 1; |
| 65 | 65 | ||
| 66 | int ehca_debug_level = 0; | 66 | int ehca_debug_level = 0; |
| 67 | int ehca_nr_ports = 2; | 67 | int ehca_nr_ports = -1; |
| 68 | int ehca_use_hp_mr = 0; | 68 | int ehca_use_hp_mr = 0; |
| 69 | int ehca_port_act_time = 30; | 69 | int ehca_port_act_time = 30; |
| 70 | int ehca_static_rate = -1; | 70 | int ehca_static_rate = -1; |
| @@ -95,8 +95,8 @@ MODULE_PARM_DESC(hw_level, | |||
| 95 | "Hardware level (0: autosensing (default), " | 95 | "Hardware level (0: autosensing (default), " |
| 96 | "0x10..0x14: eHCA, 0x20..0x23: eHCA2)"); | 96 | "0x10..0x14: eHCA, 0x20..0x23: eHCA2)"); |
| 97 | MODULE_PARM_DESC(nr_ports, | 97 | MODULE_PARM_DESC(nr_ports, |
| 98 | "number of connected ports (-1: autodetect, 1: port one only, " | 98 | "number of connected ports (-1: autodetect (default), " |
| 99 | "2: two ports (default)"); | 99 | "1: port one only, 2: two ports)"); |
| 100 | MODULE_PARM_DESC(use_hp_mr, | 100 | MODULE_PARM_DESC(use_hp_mr, |
| 101 | "Use high performance MRs (default: no)"); | 101 | "Use high performance MRs (default: no)"); |
| 102 | MODULE_PARM_DESC(port_act_time, | 102 | MODULE_PARM_DESC(port_act_time, |
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c index 5a3d96f84c79..8fd88cd828fd 100644 --- a/drivers/infiniband/hw/ehca/ehca_reqs.c +++ b/drivers/infiniband/hw/ehca/ehca_reqs.c | |||
| @@ -786,7 +786,11 @@ repoll: | |||
| 786 | wc->slid = cqe->rlid; | 786 | wc->slid = cqe->rlid; |
| 787 | wc->dlid_path_bits = cqe->dlid; | 787 | wc->dlid_path_bits = cqe->dlid; |
| 788 | wc->src_qp = cqe->remote_qp_number; | 788 | wc->src_qp = cqe->remote_qp_number; |
| 789 | wc->wc_flags = cqe->w_completion_flags; | 789 | /* |
| 790 | * HW has "Immed data present" and "GRH present" in bits 6 and 5. | ||
| 791 | * SW defines those in bits 1 and 0, so we can just shift and mask. | ||
| 792 | */ | ||
| 793 | wc->wc_flags = (cqe->w_completion_flags >> 5) & 3; | ||
| 790 | wc->ex.imm_data = cpu_to_be32(cqe->immediate_data); | 794 | wc->ex.imm_data = cpu_to_be32(cqe->immediate_data); |
| 791 | wc->sl = cqe->service_level; | 795 | wc->sl = cqe->service_level; |
| 792 | 796 | ||
diff --git a/drivers/infiniband/hw/ehca/ehca_sqp.c b/drivers/infiniband/hw/ehca/ehca_sqp.c index c568b28f4e20..8c1213f8916a 100644 --- a/drivers/infiniband/hw/ehca/ehca_sqp.c +++ b/drivers/infiniband/hw/ehca/ehca_sqp.c | |||
| @@ -125,14 +125,30 @@ struct ib_perf { | |||
| 125 | u8 data[192]; | 125 | u8 data[192]; |
| 126 | } __attribute__ ((packed)); | 126 | } __attribute__ ((packed)); |
| 127 | 127 | ||
| 128 | /* TC/SL/FL packed into 32 bits, as in ClassPortInfo */ | ||
| 129 | struct tcslfl { | ||
| 130 | u32 tc:8; | ||
| 131 | u32 sl:4; | ||
| 132 | u32 fl:20; | ||
| 133 | } __attribute__ ((packed)); | ||
| 134 | |||
| 135 | /* IP Version/TC/FL packed into 32 bits, as in GRH */ | ||
| 136 | struct vertcfl { | ||
| 137 | u32 ver:4; | ||
| 138 | u32 tc:8; | ||
| 139 | u32 fl:20; | ||
| 140 | } __attribute__ ((packed)); | ||
| 128 | 141 | ||
| 129 | static int ehca_process_perf(struct ib_device *ibdev, u8 port_num, | 142 | static int ehca_process_perf(struct ib_device *ibdev, u8 port_num, |
| 143 | struct ib_wc *in_wc, struct ib_grh *in_grh, | ||
| 130 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 144 | struct ib_mad *in_mad, struct ib_mad *out_mad) |
| 131 | { | 145 | { |
| 132 | struct ib_perf *in_perf = (struct ib_perf *)in_mad; | 146 | struct ib_perf *in_perf = (struct ib_perf *)in_mad; |
| 133 | struct ib_perf *out_perf = (struct ib_perf *)out_mad; | 147 | struct ib_perf *out_perf = (struct ib_perf *)out_mad; |
| 134 | struct ib_class_port_info *poi = | 148 | struct ib_class_port_info *poi = |
| 135 | (struct ib_class_port_info *)out_perf->data; | 149 | (struct ib_class_port_info *)out_perf->data; |
| 150 | struct tcslfl *tcslfl = | ||
| 151 | (struct tcslfl *)&poi->redirect_tcslfl; | ||
| 136 | struct ehca_shca *shca = | 152 | struct ehca_shca *shca = |
| 137 | container_of(ibdev, struct ehca_shca, ib_device); | 153 | container_of(ibdev, struct ehca_shca, ib_device); |
| 138 | struct ehca_sport *sport = &shca->sport[port_num - 1]; | 154 | struct ehca_sport *sport = &shca->sport[port_num - 1]; |
| @@ -158,10 +174,29 @@ static int ehca_process_perf(struct ib_device *ibdev, u8 port_num, | |||
| 158 | poi->base_version = 1; | 174 | poi->base_version = 1; |
| 159 | poi->class_version = 1; | 175 | poi->class_version = 1; |
| 160 | poi->resp_time_value = 18; | 176 | poi->resp_time_value = 18; |
| 161 | poi->redirect_lid = sport->saved_attr.lid; | 177 | |
| 162 | poi->redirect_qp = sport->pma_qp_nr; | 178 | /* copy local routing information from WC where applicable */ |
| 179 | tcslfl->sl = in_wc->sl; | ||
| 180 | poi->redirect_lid = | ||
| 181 | sport->saved_attr.lid | in_wc->dlid_path_bits; | ||
| 182 | poi->redirect_qp = sport->pma_qp_nr; | ||
| 163 | poi->redirect_qkey = IB_QP1_QKEY; | 183 | poi->redirect_qkey = IB_QP1_QKEY; |
| 164 | poi->redirect_pkey = IB_DEFAULT_PKEY_FULL; | 184 | |
| 185 | ehca_query_pkey(ibdev, port_num, in_wc->pkey_index, | ||
| 186 | &poi->redirect_pkey); | ||
| 187 | |||
| 188 | /* if request was globally routed, copy route info */ | ||
| 189 | if (in_grh) { | ||
| 190 | struct vertcfl *vertcfl = | ||
| 191 | (struct vertcfl *)&in_grh->version_tclass_flow; | ||
| 192 | memcpy(poi->redirect_gid, in_grh->dgid.raw, | ||
| 193 | sizeof(poi->redirect_gid)); | ||
| 194 | tcslfl->tc = vertcfl->tc; | ||
| 195 | tcslfl->fl = vertcfl->fl; | ||
| 196 | } else | ||
| 197 | /* else only fill in default GID */ | ||
| 198 | ehca_query_gid(ibdev, port_num, 0, | ||
| 199 | (union ib_gid *)&poi->redirect_gid); | ||
| 165 | 200 | ||
| 166 | ehca_dbg(ibdev, "ehca_pma_lid=%x ehca_pma_qp=%x", | 201 | ehca_dbg(ibdev, "ehca_pma_lid=%x ehca_pma_qp=%x", |
| 167 | sport->saved_attr.lid, sport->pma_qp_nr); | 202 | sport->saved_attr.lid, sport->pma_qp_nr); |
| @@ -183,8 +218,7 @@ perf_reply: | |||
| 183 | 218 | ||
| 184 | int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | 219 | int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, |
| 185 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 220 | struct ib_wc *in_wc, struct ib_grh *in_grh, |
| 186 | struct ib_mad *in_mad, | 221 | struct ib_mad *in_mad, struct ib_mad *out_mad) |
| 187 | struct ib_mad *out_mad) | ||
| 188 | { | 222 | { |
| 189 | int ret; | 223 | int ret; |
| 190 | 224 | ||
| @@ -196,7 +230,8 @@ int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | |||
| 196 | return IB_MAD_RESULT_SUCCESS; | 230 | return IB_MAD_RESULT_SUCCESS; |
| 197 | 231 | ||
| 198 | ehca_dbg(ibdev, "port_num=%x src_qp=%x", port_num, in_wc->src_qp); | 232 | ehca_dbg(ibdev, "port_num=%x src_qp=%x", port_num, in_wc->src_qp); |
| 199 | ret = ehca_process_perf(ibdev, port_num, in_mad, out_mad); | 233 | ret = ehca_process_perf(ibdev, port_num, in_wc, in_grh, |
| 234 | in_mad, out_mad); | ||
| 200 | 235 | ||
| 201 | return ret; | 236 | return ret; |
| 202 | } | 237 | } |
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index 23173982b32c..38a287006612 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c | |||
| @@ -1616,7 +1616,7 @@ static int try_alloc_port(struct ipath_devdata *dd, int port, | |||
| 1616 | pd->port_cnt = 1; | 1616 | pd->port_cnt = 1; |
| 1617 | port_fp(fp) = pd; | 1617 | port_fp(fp) = pd; |
| 1618 | pd->port_pid = get_pid(task_pid(current)); | 1618 | pd->port_pid = get_pid(task_pid(current)); |
| 1619 | strncpy(pd->port_comm, current->comm, sizeof(pd->port_comm)); | 1619 | strlcpy(pd->port_comm, current->comm, sizeof(pd->port_comm)); |
| 1620 | ipath_stats.sps_ports++; | 1620 | ipath_stats.sps_ports++; |
| 1621 | ret = 0; | 1621 | ret = 0; |
| 1622 | } else | 1622 | } else |
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c index 16a702d46018..ceb98ee78666 100644 --- a/drivers/infiniband/hw/ipath/ipath_mad.c +++ b/drivers/infiniband/hw/ipath/ipath_mad.c | |||
| @@ -60,7 +60,7 @@ static int recv_subn_get_nodedescription(struct ib_smp *smp, | |||
| 60 | if (smp->attr_mod) | 60 | if (smp->attr_mod) |
| 61 | smp->status |= IB_SMP_INVALID_FIELD; | 61 | smp->status |= IB_SMP_INVALID_FIELD; |
| 62 | 62 | ||
| 63 | strncpy(smp->data, ibdev->node_desc, sizeof(smp->data)); | 63 | memcpy(smp->data, ibdev->node_desc, sizeof(smp->data)); |
| 64 | 64 | ||
| 65 | return reply(smp); | 65 | return reply(smp); |
| 66 | } | 66 | } |
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index ae3d7590346e..3cb3f47a10b8 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
| @@ -342,6 +342,9 @@ static struct ib_ucontext *mlx4_ib_alloc_ucontext(struct ib_device *ibdev, | |||
| 342 | struct mlx4_ib_alloc_ucontext_resp resp; | 342 | struct mlx4_ib_alloc_ucontext_resp resp; |
| 343 | int err; | 343 | int err; |
| 344 | 344 | ||
| 345 | if (!dev->ib_active) | ||
| 346 | return ERR_PTR(-EAGAIN); | ||
| 347 | |||
| 345 | resp.qp_tab_size = dev->dev->caps.num_qps; | 348 | resp.qp_tab_size = dev->dev->caps.num_qps; |
| 346 | resp.bf_reg_size = dev->dev->caps.bf_reg_size; | 349 | resp.bf_reg_size = dev->dev->caps.bf_reg_size; |
| 347 | resp.bf_regs_per_page = dev->dev->caps.bf_regs_per_page; | 350 | resp.bf_regs_per_page = dev->dev->caps.bf_regs_per_page; |
| @@ -540,15 +543,11 @@ static struct device_attribute *mlx4_class_attributes[] = { | |||
| 540 | 543 | ||
| 541 | static void *mlx4_ib_add(struct mlx4_dev *dev) | 544 | static void *mlx4_ib_add(struct mlx4_dev *dev) |
| 542 | { | 545 | { |
| 543 | static int mlx4_ib_version_printed; | ||
| 544 | struct mlx4_ib_dev *ibdev; | 546 | struct mlx4_ib_dev *ibdev; |
| 545 | int num_ports = 0; | 547 | int num_ports = 0; |
| 546 | int i; | 548 | int i; |
| 547 | 549 | ||
| 548 | if (!mlx4_ib_version_printed) { | 550 | printk_once(KERN_INFO "%s", mlx4_ib_version); |
| 549 | printk(KERN_INFO "%s", mlx4_ib_version); | ||
| 550 | ++mlx4_ib_version_printed; | ||
| 551 | } | ||
| 552 | 551 | ||
| 553 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) | 552 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) |
| 554 | num_ports++; | 553 | num_ports++; |
| @@ -673,6 +672,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) | |||
| 673 | goto err_reg; | 672 | goto err_reg; |
| 674 | } | 673 | } |
| 675 | 674 | ||
| 675 | ibdev->ib_active = true; | ||
| 676 | |||
| 676 | return ibdev; | 677 | return ibdev; |
| 677 | 678 | ||
| 678 | err_reg: | 679 | err_reg: |
| @@ -729,6 +730,7 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, | |||
| 729 | break; | 730 | break; |
| 730 | 731 | ||
| 731 | case MLX4_DEV_EVENT_CATASTROPHIC_ERROR: | 732 | case MLX4_DEV_EVENT_CATASTROPHIC_ERROR: |
| 733 | ibdev->ib_active = false; | ||
| 732 | ibev.event = IB_EVENT_DEVICE_FATAL; | 734 | ibev.event = IB_EVENT_DEVICE_FATAL; |
| 733 | break; | 735 | break; |
| 734 | 736 | ||
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index 8a7dd6795fa0..3486d7675e56 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h | |||
| @@ -175,6 +175,7 @@ struct mlx4_ib_dev { | |||
| 175 | spinlock_t sm_lock; | 175 | spinlock_t sm_lock; |
| 176 | 176 | ||
| 177 | struct mutex cap_mask_mutex; | 177 | struct mutex cap_mask_mutex; |
| 178 | bool ib_active; | ||
| 178 | }; | 179 | }; |
| 179 | 180 | ||
| 180 | static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev) | 181 | static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev) |
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index c4a02648c8af..219b10397b4d 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c | |||
| @@ -615,10 +615,12 @@ static enum mlx4_qp_state to_mlx4_state(enum ib_qp_state state) | |||
| 615 | } | 615 | } |
| 616 | 616 | ||
| 617 | static void mlx4_ib_lock_cqs(struct mlx4_ib_cq *send_cq, struct mlx4_ib_cq *recv_cq) | 617 | static void mlx4_ib_lock_cqs(struct mlx4_ib_cq *send_cq, struct mlx4_ib_cq *recv_cq) |
| 618 | __acquires(&send_cq->lock) __acquires(&recv_cq->lock) | ||
| 618 | { | 619 | { |
| 619 | if (send_cq == recv_cq) | 620 | if (send_cq == recv_cq) { |
| 620 | spin_lock_irq(&send_cq->lock); | 621 | spin_lock_irq(&send_cq->lock); |
| 621 | else if (send_cq->mcq.cqn < recv_cq->mcq.cqn) { | 622 | __acquire(&recv_cq->lock); |
| 623 | } else if (send_cq->mcq.cqn < recv_cq->mcq.cqn) { | ||
| 622 | spin_lock_irq(&send_cq->lock); | 624 | spin_lock_irq(&send_cq->lock); |
| 623 | spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING); | 625 | spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING); |
| 624 | } else { | 626 | } else { |
| @@ -628,10 +630,12 @@ static void mlx4_ib_lock_cqs(struct mlx4_ib_cq *send_cq, struct mlx4_ib_cq *recv | |||
| 628 | } | 630 | } |
| 629 | 631 | ||
| 630 | static void mlx4_ib_unlock_cqs(struct mlx4_ib_cq *send_cq, struct mlx4_ib_cq *recv_cq) | 632 | static void mlx4_ib_unlock_cqs(struct mlx4_ib_cq *send_cq, struct mlx4_ib_cq *recv_cq) |
| 633 | __releases(&send_cq->lock) __releases(&recv_cq->lock) | ||
| 631 | { | 634 | { |
| 632 | if (send_cq == recv_cq) | 635 | if (send_cq == recv_cq) { |
| 636 | __release(&recv_cq->lock); | ||
| 633 | spin_unlock_irq(&send_cq->lock); | 637 | spin_unlock_irq(&send_cq->lock); |
| 634 | else if (send_cq->mcq.cqn < recv_cq->mcq.cqn) { | 638 | } else if (send_cq->mcq.cqn < recv_cq->mcq.cqn) { |
| 635 | spin_unlock(&recv_cq->lock); | 639 | spin_unlock(&recv_cq->lock); |
| 636 | spin_unlock_irq(&send_cq->lock); | 640 | spin_unlock_irq(&send_cq->lock); |
| 637 | } else { | 641 | } else { |
diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c index 65ad359fdf16..056b2a4c6970 100644 --- a/drivers/infiniband/hw/mthca/mthca_catas.c +++ b/drivers/infiniband/hw/mthca/mthca_catas.c | |||
| @@ -88,6 +88,7 @@ static void handle_catas(struct mthca_dev *dev) | |||
| 88 | event.device = &dev->ib_dev; | 88 | event.device = &dev->ib_dev; |
| 89 | event.event = IB_EVENT_DEVICE_FATAL; | 89 | event.event = IB_EVENT_DEVICE_FATAL; |
| 90 | event.element.port_num = 0; | 90 | event.element.port_num = 0; |
| 91 | dev->active = false; | ||
| 91 | 92 | ||
| 92 | ib_dispatch_event(&event); | 93 | ib_dispatch_event(&event); |
| 93 | 94 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_config_reg.h b/drivers/infiniband/hw/mthca/mthca_config_reg.h index 75671f75cac4..155bc66395be 100644 --- a/drivers/infiniband/hw/mthca/mthca_config_reg.h +++ b/drivers/infiniband/hw/mthca/mthca_config_reg.h | |||
| @@ -34,8 +34,6 @@ | |||
| 34 | #ifndef MTHCA_CONFIG_REG_H | 34 | #ifndef MTHCA_CONFIG_REG_H |
| 35 | #define MTHCA_CONFIG_REG_H | 35 | #define MTHCA_CONFIG_REG_H |
| 36 | 36 | ||
| 37 | #include <asm/page.h> | ||
| 38 | |||
| 39 | #define MTHCA_HCR_BASE 0x80680 | 37 | #define MTHCA_HCR_BASE 0x80680 |
| 40 | #define MTHCA_HCR_SIZE 0x0001c | 38 | #define MTHCA_HCR_SIZE 0x0001c |
| 41 | #define MTHCA_ECR_BASE 0x80700 | 39 | #define MTHCA_ECR_BASE 0x80700 |
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index 9ef611f6dd36..7e6a6d64ad4e 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h | |||
| @@ -357,6 +357,7 @@ struct mthca_dev { | |||
| 357 | struct ib_ah *sm_ah[MTHCA_MAX_PORTS]; | 357 | struct ib_ah *sm_ah[MTHCA_MAX_PORTS]; |
| 358 | spinlock_t sm_lock; | 358 | spinlock_t sm_lock; |
| 359 | u8 rate[MTHCA_MAX_PORTS]; | 359 | u8 rate[MTHCA_MAX_PORTS]; |
| 360 | bool active; | ||
| 360 | }; | 361 | }; |
| 361 | 362 | ||
| 362 | #ifdef CONFIG_INFINIBAND_MTHCA_DEBUG | 363 | #ifdef CONFIG_INFINIBAND_MTHCA_DEBUG |
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index 90e4e450a120..8c31fa36e95e 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c | |||
| @@ -829,27 +829,34 @@ int mthca_init_eq_table(struct mthca_dev *dev) | |||
| 829 | 829 | ||
| 830 | if (dev->mthca_flags & MTHCA_FLAG_MSI_X) { | 830 | if (dev->mthca_flags & MTHCA_FLAG_MSI_X) { |
| 831 | static const char *eq_name[] = { | 831 | static const char *eq_name[] = { |
| 832 | [MTHCA_EQ_COMP] = DRV_NAME " (comp)", | 832 | [MTHCA_EQ_COMP] = DRV_NAME "-comp", |
| 833 | [MTHCA_EQ_ASYNC] = DRV_NAME " (async)", | 833 | [MTHCA_EQ_ASYNC] = DRV_NAME "-async", |
| 834 | [MTHCA_EQ_CMD] = DRV_NAME " (cmd)" | 834 | [MTHCA_EQ_CMD] = DRV_NAME "-cmd" |
| 835 | }; | 835 | }; |
| 836 | 836 | ||
| 837 | for (i = 0; i < MTHCA_NUM_EQ; ++i) { | 837 | for (i = 0; i < MTHCA_NUM_EQ; ++i) { |
| 838 | snprintf(dev->eq_table.eq[i].irq_name, | ||
| 839 | IB_DEVICE_NAME_MAX, | ||
| 840 | "%s@pci:%s", eq_name[i], | ||
| 841 | pci_name(dev->pdev)); | ||
| 838 | err = request_irq(dev->eq_table.eq[i].msi_x_vector, | 842 | err = request_irq(dev->eq_table.eq[i].msi_x_vector, |
| 839 | mthca_is_memfree(dev) ? | 843 | mthca_is_memfree(dev) ? |
| 840 | mthca_arbel_msi_x_interrupt : | 844 | mthca_arbel_msi_x_interrupt : |
| 841 | mthca_tavor_msi_x_interrupt, | 845 | mthca_tavor_msi_x_interrupt, |
| 842 | 0, eq_name[i], dev->eq_table.eq + i); | 846 | 0, dev->eq_table.eq[i].irq_name, |
| 847 | dev->eq_table.eq + i); | ||
| 843 | if (err) | 848 | if (err) |
| 844 | goto err_out_cmd; | 849 | goto err_out_cmd; |
| 845 | dev->eq_table.eq[i].have_irq = 1; | 850 | dev->eq_table.eq[i].have_irq = 1; |
| 846 | } | 851 | } |
| 847 | } else { | 852 | } else { |
| 853 | snprintf(dev->eq_table.eq[0].irq_name, IB_DEVICE_NAME_MAX, | ||
| 854 | DRV_NAME "@pci:%s", pci_name(dev->pdev)); | ||
| 848 | err = request_irq(dev->pdev->irq, | 855 | err = request_irq(dev->pdev->irq, |
| 849 | mthca_is_memfree(dev) ? | 856 | mthca_is_memfree(dev) ? |
| 850 | mthca_arbel_interrupt : | 857 | mthca_arbel_interrupt : |
| 851 | mthca_tavor_interrupt, | 858 | mthca_tavor_interrupt, |
| 852 | IRQF_SHARED, DRV_NAME, dev); | 859 | IRQF_SHARED, dev->eq_table.eq[0].irq_name, dev); |
| 853 | if (err) | 860 | if (err) |
| 854 | goto err_out_cmd; | 861 | goto err_out_cmd; |
| 855 | dev->eq_table.have_irq = 1; | 862 | dev->eq_table.have_irq = 1; |
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 13da9f1d24c0..b01b28987874 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c | |||
| @@ -1116,6 +1116,8 @@ static int __mthca_init_one(struct pci_dev *pdev, int hca_type) | |||
| 1116 | pci_set_drvdata(pdev, mdev); | 1116 | pci_set_drvdata(pdev, mdev); |
| 1117 | mdev->hca_type = hca_type; | 1117 | mdev->hca_type = hca_type; |
| 1118 | 1118 | ||
| 1119 | mdev->active = true; | ||
| 1120 | |||
| 1119 | return 0; | 1121 | return 0; |
| 1120 | 1122 | ||
| 1121 | err_unregister: | 1123 | err_unregister: |
| @@ -1215,15 +1217,11 @@ int __mthca_restart_one(struct pci_dev *pdev) | |||
| 1215 | static int __devinit mthca_init_one(struct pci_dev *pdev, | 1217 | static int __devinit mthca_init_one(struct pci_dev *pdev, |
| 1216 | const struct pci_device_id *id) | 1218 | const struct pci_device_id *id) |
| 1217 | { | 1219 | { |
| 1218 | static int mthca_version_printed = 0; | ||
| 1219 | int ret; | 1220 | int ret; |
| 1220 | 1221 | ||
| 1221 | mutex_lock(&mthca_device_mutex); | 1222 | mutex_lock(&mthca_device_mutex); |
| 1222 | 1223 | ||
| 1223 | if (!mthca_version_printed) { | 1224 | printk_once(KERN_INFO "%s", mthca_version); |
| 1224 | printk(KERN_INFO "%s", mthca_version); | ||
| 1225 | ++mthca_version_printed; | ||
| 1226 | } | ||
| 1227 | 1225 | ||
| 1228 | if (id->driver_data >= ARRAY_SIZE(mthca_hca_table)) { | 1226 | if (id->driver_data >= ARRAY_SIZE(mthca_hca_table)) { |
| 1229 | printk(KERN_ERR PFX "%s has invalid driver data %lx\n", | 1227 | printk(KERN_ERR PFX "%s has invalid driver data %lx\n", |
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 87ad889e367b..bcf7a4014820 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c | |||
| @@ -334,6 +334,9 @@ static struct ib_ucontext *mthca_alloc_ucontext(struct ib_device *ibdev, | |||
| 334 | struct mthca_ucontext *context; | 334 | struct mthca_ucontext *context; |
| 335 | int err; | 335 | int err; |
| 336 | 336 | ||
| 337 | if (!(to_mdev(ibdev)->active)) | ||
| 338 | return ERR_PTR(-EAGAIN); | ||
| 339 | |||
| 337 | memset(&uresp, 0, sizeof uresp); | 340 | memset(&uresp, 0, sizeof uresp); |
| 338 | 341 | ||
| 339 | uresp.qp_tab_size = to_mdev(ibdev)->limits.num_qps; | 342 | uresp.qp_tab_size = to_mdev(ibdev)->limits.num_qps; |
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h index c621f8794b88..90f4c4d2e983 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.h +++ b/drivers/infiniband/hw/mthca/mthca_provider.h | |||
| @@ -113,6 +113,7 @@ struct mthca_eq { | |||
| 113 | int nent; | 113 | int nent; |
| 114 | struct mthca_buf_list *page_list; | 114 | struct mthca_buf_list *page_list; |
| 115 | struct mthca_mr mr; | 115 | struct mthca_mr mr; |
| 116 | char irq_name[IB_DEVICE_NAME_MAX]; | ||
| 116 | }; | 117 | }; |
| 117 | 118 | ||
| 118 | struct mthca_av; | 119 | struct mthca_av; |
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index f5081bfde6db..c10576fa60c1 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c | |||
| @@ -1319,10 +1319,12 @@ int mthca_alloc_qp(struct mthca_dev *dev, | |||
| 1319 | } | 1319 | } |
| 1320 | 1320 | ||
| 1321 | static void mthca_lock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq) | 1321 | static void mthca_lock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq) |
| 1322 | __acquires(&send_cq->lock) __acquires(&recv_cq->lock) | ||
| 1322 | { | 1323 | { |
| 1323 | if (send_cq == recv_cq) | 1324 | if (send_cq == recv_cq) { |
| 1324 | spin_lock_irq(&send_cq->lock); | 1325 | spin_lock_irq(&send_cq->lock); |
| 1325 | else if (send_cq->cqn < recv_cq->cqn) { | 1326 | __acquire(&recv_cq->lock); |
| 1327 | } else if (send_cq->cqn < recv_cq->cqn) { | ||
| 1326 | spin_lock_irq(&send_cq->lock); | 1328 | spin_lock_irq(&send_cq->lock); |
| 1327 | spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING); | 1329 | spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING); |
| 1328 | } else { | 1330 | } else { |
| @@ -1332,10 +1334,12 @@ static void mthca_lock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq) | |||
| 1332 | } | 1334 | } |
| 1333 | 1335 | ||
| 1334 | static void mthca_unlock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq) | 1336 | static void mthca_unlock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq) |
| 1337 | __releases(&send_cq->lock) __releases(&recv_cq->lock) | ||
| 1335 | { | 1338 | { |
| 1336 | if (send_cq == recv_cq) | 1339 | if (send_cq == recv_cq) { |
| 1340 | __release(&recv_cq->lock); | ||
| 1337 | spin_unlock_irq(&send_cq->lock); | 1341 | spin_unlock_irq(&send_cq->lock); |
| 1338 | else if (send_cq->cqn < recv_cq->cqn) { | 1342 | } else if (send_cq->cqn < recv_cq->cqn) { |
| 1339 | spin_unlock(&recv_cq->lock); | 1343 | spin_unlock(&recv_cq->lock); |
| 1340 | spin_unlock_irq(&send_cq->lock); | 1344 | spin_unlock_irq(&send_cq->lock); |
| 1341 | } else { | 1345 | } else { |
diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c index acb6817f6060..2a13a163d337 100644 --- a/drivers/infiniband/hw/mthca/mthca_reset.c +++ b/drivers/infiniband/hw/mthca/mthca_reset.c | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | * SOFTWARE. | 30 | * SOFTWARE. |
| 31 | */ | 31 | */ |
| 32 | 32 | ||
| 33 | #include <linux/init.h> | ||
| 34 | #include <linux/errno.h> | 33 | #include <linux/errno.h> |
| 35 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
| 36 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index bf1720f7f35f..bcc6abc4faff 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h | |||
| @@ -523,7 +523,7 @@ int nes_cm_disconn(struct nes_qp *); | |||
| 523 | void nes_cm_disconn_worker(void *); | 523 | void nes_cm_disconn_worker(void *); |
| 524 | 524 | ||
| 525 | /* nes_verbs.c */ | 525 | /* nes_verbs.c */ |
| 526 | int nes_hw_modify_qp(struct nes_device *, struct nes_qp *, u32, u32); | 526 | int nes_hw_modify_qp(struct nes_device *, struct nes_qp *, u32, u32, u32); |
| 527 | int nes_modify_qp(struct ib_qp *, struct ib_qp_attr *, int, struct ib_udata *); | 527 | int nes_modify_qp(struct ib_qp *, struct ib_qp_attr *, int, struct ib_udata *); |
| 528 | struct nes_ib_device *nes_init_ofa_device(struct net_device *); | 528 | struct nes_ib_device *nes_init_ofa_device(struct net_device *); |
| 529 | void nes_destroy_ofa_device(struct nes_ib_device *); | 529 | void nes_destroy_ofa_device(struct nes_ib_device *); |
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 114b802771ad..73473db19863 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c | |||
| @@ -2450,19 +2450,16 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod | |||
| 2450 | */ | 2450 | */ |
| 2451 | int nes_cm_disconn(struct nes_qp *nesqp) | 2451 | int nes_cm_disconn(struct nes_qp *nesqp) |
| 2452 | { | 2452 | { |
| 2453 | unsigned long flags; | 2453 | struct disconn_work *work; |
| 2454 | |||
| 2455 | spin_lock_irqsave(&nesqp->lock, flags); | ||
| 2456 | if (nesqp->disconn_pending == 0) { | ||
| 2457 | nesqp->disconn_pending++; | ||
| 2458 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 2459 | /* init our disconnect work element, to */ | ||
| 2460 | INIT_WORK(&nesqp->disconn_work, nes_disconnect_worker); | ||
| 2461 | 2454 | ||
| 2462 | queue_work(g_cm_core->disconn_wq, &nesqp->disconn_work); | 2455 | work = kzalloc(sizeof *work, GFP_ATOMIC); |
| 2463 | } else | 2456 | if (!work) |
| 2464 | spin_unlock_irqrestore(&nesqp->lock, flags); | 2457 | return -ENOMEM; /* Timer will clean up */ |
| 2465 | 2458 | ||
| 2459 | nes_add_ref(&nesqp->ibqp); | ||
| 2460 | work->nesqp = nesqp; | ||
| 2461 | INIT_WORK(&work->work, nes_disconnect_worker); | ||
| 2462 | queue_work(g_cm_core->disconn_wq, &work->work); | ||
| 2466 | return 0; | 2463 | return 0; |
| 2467 | } | 2464 | } |
| 2468 | 2465 | ||
| @@ -2472,11 +2469,14 @@ int nes_cm_disconn(struct nes_qp *nesqp) | |||
| 2472 | */ | 2469 | */ |
| 2473 | static void nes_disconnect_worker(struct work_struct *work) | 2470 | static void nes_disconnect_worker(struct work_struct *work) |
| 2474 | { | 2471 | { |
| 2475 | struct nes_qp *nesqp = container_of(work, struct nes_qp, disconn_work); | 2472 | struct disconn_work *dwork = container_of(work, struct disconn_work, work); |
| 2473 | struct nes_qp *nesqp = dwork->nesqp; | ||
| 2476 | 2474 | ||
| 2475 | kfree(dwork); | ||
| 2477 | nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n", | 2476 | nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n", |
| 2478 | nesqp->last_aeq, nesqp->hwqp.qp_id); | 2477 | nesqp->last_aeq, nesqp->hwqp.qp_id); |
| 2479 | nes_cm_disconn_true(nesqp); | 2478 | nes_cm_disconn_true(nesqp); |
| 2479 | nes_rem_ref(&nesqp->ibqp); | ||
| 2480 | } | 2480 | } |
| 2481 | 2481 | ||
| 2482 | 2482 | ||
| @@ -2493,7 +2493,12 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) | |||
| 2493 | u16 last_ae; | 2493 | u16 last_ae; |
| 2494 | u8 original_hw_tcp_state; | 2494 | u8 original_hw_tcp_state; |
| 2495 | u8 original_ibqp_state; | 2495 | u8 original_ibqp_state; |
| 2496 | u8 issued_disconnect_reset = 0; | 2496 | enum iw_cm_event_type disconn_status = IW_CM_EVENT_STATUS_OK; |
| 2497 | int issue_disconn = 0; | ||
| 2498 | int issue_close = 0; | ||
| 2499 | int issue_flush = 0; | ||
| 2500 | u32 flush_q = NES_CQP_FLUSH_RQ; | ||
| 2501 | struct ib_event ibevent; | ||
| 2497 | 2502 | ||
| 2498 | if (!nesqp) { | 2503 | if (!nesqp) { |
| 2499 | nes_debug(NES_DBG_CM, "disconnect_worker nesqp is NULL\n"); | 2504 | nes_debug(NES_DBG_CM, "disconnect_worker nesqp is NULL\n"); |
| @@ -2517,24 +2522,55 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) | |||
| 2517 | original_ibqp_state = nesqp->ibqp_state; | 2522 | original_ibqp_state = nesqp->ibqp_state; |
| 2518 | last_ae = nesqp->last_aeq; | 2523 | last_ae = nesqp->last_aeq; |
| 2519 | 2524 | ||
| 2525 | if (nesqp->term_flags) { | ||
| 2526 | issue_disconn = 1; | ||
| 2527 | issue_close = 1; | ||
| 2528 | nesqp->cm_id = NULL; | ||
| 2529 | if (nesqp->flush_issued == 0) { | ||
| 2530 | nesqp->flush_issued = 1; | ||
| 2531 | issue_flush = 1; | ||
| 2532 | } | ||
| 2533 | } else if ((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) || | ||
| 2534 | ((original_ibqp_state == IB_QPS_RTS) && | ||
| 2535 | (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET))) { | ||
| 2536 | issue_disconn = 1; | ||
| 2537 | if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) | ||
| 2538 | disconn_status = IW_CM_EVENT_STATUS_RESET; | ||
| 2539 | } | ||
| 2540 | |||
| 2541 | if (((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSED) || | ||
| 2542 | (original_hw_tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT) || | ||
| 2543 | (last_ae == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) || | ||
| 2544 | (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET))) { | ||
| 2545 | issue_close = 1; | ||
| 2546 | nesqp->cm_id = NULL; | ||
| 2547 | if (nesqp->flush_issued == 0) { | ||
| 2548 | nesqp->flush_issued = 1; | ||
| 2549 | issue_flush = 1; | ||
| 2550 | } | ||
| 2551 | } | ||
| 2552 | |||
| 2553 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 2520 | 2554 | ||
| 2521 | nes_debug(NES_DBG_CM, "set ibqp_state=%u\n", nesqp->ibqp_state); | 2555 | if ((issue_flush) && (nesqp->destroyed == 0)) { |
| 2556 | /* Flush the queue(s) */ | ||
| 2557 | if (nesqp->hw_iwarp_state >= NES_AEQE_IWARP_STATE_TERMINATE) | ||
| 2558 | flush_q |= NES_CQP_FLUSH_SQ; | ||
| 2559 | flush_wqes(nesvnic->nesdev, nesqp, flush_q, 1); | ||
| 2522 | 2560 | ||
| 2523 | if ((nesqp->cm_id) && (cm_id->event_handler)) { | 2561 | if (nesqp->term_flags) { |
| 2524 | if ((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) || | 2562 | ibevent.device = nesqp->ibqp.device; |
| 2525 | ((original_ibqp_state == IB_QPS_RTS) && | 2563 | ibevent.event = nesqp->terminate_eventtype; |
| 2526 | (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET))) { | 2564 | ibevent.element.qp = &nesqp->ibqp; |
| 2565 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); | ||
| 2566 | } | ||
| 2567 | } | ||
| 2568 | |||
| 2569 | if ((cm_id) && (cm_id->event_handler)) { | ||
| 2570 | if (issue_disconn) { | ||
| 2527 | atomic_inc(&cm_disconnects); | 2571 | atomic_inc(&cm_disconnects); |
| 2528 | cm_event.event = IW_CM_EVENT_DISCONNECT; | 2572 | cm_event.event = IW_CM_EVENT_DISCONNECT; |
| 2529 | if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) { | 2573 | cm_event.status = disconn_status; |
| 2530 | cm_event.status = IW_CM_EVENT_STATUS_RESET; | ||
| 2531 | nes_debug(NES_DBG_CM, "Generating a CM " | ||
| 2532 | "Disconnect Event (status reset) for " | ||
| 2533 | "QP%u, cm_id = %p. \n", | ||
| 2534 | nesqp->hwqp.qp_id, cm_id); | ||
| 2535 | } else | ||
| 2536 | cm_event.status = IW_CM_EVENT_STATUS_OK; | ||
| 2537 | |||
| 2538 | cm_event.local_addr = cm_id->local_addr; | 2574 | cm_event.local_addr = cm_id->local_addr; |
| 2539 | cm_event.remote_addr = cm_id->remote_addr; | 2575 | cm_event.remote_addr = cm_id->remote_addr; |
| 2540 | cm_event.private_data = NULL; | 2576 | cm_event.private_data = NULL; |
| @@ -2547,29 +2583,14 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) | |||
| 2547 | nesqp->hwqp.sq_tail, cm_id, | 2583 | nesqp->hwqp.sq_tail, cm_id, |
| 2548 | atomic_read(&nesqp->refcount)); | 2584 | atomic_read(&nesqp->refcount)); |
| 2549 | 2585 | ||
| 2550 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 2551 | ret = cm_id->event_handler(cm_id, &cm_event); | 2586 | ret = cm_id->event_handler(cm_id, &cm_event); |
| 2552 | if (ret) | 2587 | if (ret) |
| 2553 | nes_debug(NES_DBG_CM, "OFA CM event_handler " | 2588 | nes_debug(NES_DBG_CM, "OFA CM event_handler " |
| 2554 | "returned, ret=%d\n", ret); | 2589 | "returned, ret=%d\n", ret); |
| 2555 | spin_lock_irqsave(&nesqp->lock, flags); | ||
| 2556 | } | 2590 | } |
| 2557 | 2591 | ||
| 2558 | nesqp->disconn_pending = 0; | 2592 | if (issue_close) { |
| 2559 | /* There might have been another AE while the lock was released */ | ||
| 2560 | original_hw_tcp_state = nesqp->hw_tcp_state; | ||
| 2561 | original_ibqp_state = nesqp->ibqp_state; | ||
| 2562 | last_ae = nesqp->last_aeq; | ||
| 2563 | |||
| 2564 | if ((issued_disconnect_reset == 0) && (nesqp->cm_id) && | ||
| 2565 | ((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSED) || | ||
| 2566 | (original_hw_tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT) || | ||
| 2567 | (last_ae == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) || | ||
| 2568 | (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET))) { | ||
| 2569 | atomic_inc(&cm_closes); | 2593 | atomic_inc(&cm_closes); |
| 2570 | nesqp->cm_id = NULL; | ||
| 2571 | nesqp->in_disconnect = 0; | ||
| 2572 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 2573 | nes_disconnect(nesqp, 1); | 2594 | nes_disconnect(nesqp, 1); |
| 2574 | 2595 | ||
| 2575 | cm_id->provider_data = nesqp; | 2596 | cm_id->provider_data = nesqp; |
| @@ -2588,28 +2609,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) | |||
| 2588 | } | 2609 | } |
| 2589 | 2610 | ||
| 2590 | cm_id->rem_ref(cm_id); | 2611 | cm_id->rem_ref(cm_id); |
| 2591 | |||
| 2592 | spin_lock_irqsave(&nesqp->lock, flags); | ||
| 2593 | if (nesqp->flush_issued == 0) { | ||
| 2594 | nesqp->flush_issued = 1; | ||
| 2595 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 2596 | flush_wqes(nesvnic->nesdev, nesqp, | ||
| 2597 | NES_CQP_FLUSH_RQ, 1); | ||
| 2598 | } else | ||
| 2599 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 2600 | } else { | ||
| 2601 | cm_id = nesqp->cm_id; | ||
| 2602 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 2603 | /* check to see if the inbound reset beat the outbound reset */ | ||
| 2604 | if ((!cm_id) && (last_ae==NES_AEQE_AEID_RESET_SENT)) { | ||
| 2605 | nes_debug(NES_DBG_CM, "QP%u: Decing refcount " | ||
| 2606 | "due to inbound reset beating the " | ||
| 2607 | "outbound reset.\n", nesqp->hwqp.qp_id); | ||
| 2608 | } | ||
| 2609 | } | 2612 | } |
| 2610 | } else { | ||
| 2611 | nesqp->disconn_pending = 0; | ||
| 2612 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 2613 | } | 2613 | } |
| 2614 | 2614 | ||
| 2615 | return 0; | 2615 | return 0; |
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h index 8b7e7c0e496e..90e8e4d8a5ce 100644 --- a/drivers/infiniband/hw/nes/nes_cm.h +++ b/drivers/infiniband/hw/nes/nes_cm.h | |||
| @@ -410,8 +410,6 @@ struct nes_cm_ops { | |||
| 410 | int schedule_nes_timer(struct nes_cm_node *, struct sk_buff *, | 410 | int schedule_nes_timer(struct nes_cm_node *, struct sk_buff *, |
| 411 | enum nes_timer_type, int, int); | 411 | enum nes_timer_type, int, int); |
| 412 | 412 | ||
| 413 | int nes_cm_disconn(struct nes_qp *); | ||
| 414 | |||
| 415 | int nes_accept(struct iw_cm_id *, struct iw_cm_conn_param *); | 413 | int nes_accept(struct iw_cm_id *, struct iw_cm_conn_param *); |
| 416 | int nes_reject(struct iw_cm_id *, const void *, u8); | 414 | int nes_reject(struct iw_cm_id *, const void *, u8); |
| 417 | int nes_connect(struct iw_cm_id *, struct iw_cm_conn_param *); | 415 | int nes_connect(struct iw_cm_id *, struct iw_cm_conn_param *); |
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 4a84d02ece06..63a1a8e1e8a3 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c | |||
| @@ -74,6 +74,8 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
| 74 | static void process_critical_error(struct nes_device *nesdev); | 74 | static void process_critical_error(struct nes_device *nesdev); |
| 75 | static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number); | 75 | static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number); |
| 76 | static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode); | 76 | static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode); |
| 77 | static void nes_terminate_timeout(unsigned long context); | ||
| 78 | static void nes_terminate_start_timer(struct nes_qp *nesqp); | ||
| 77 | 79 | ||
| 78 | #ifdef CONFIG_INFINIBAND_NES_DEBUG | 80 | #ifdef CONFIG_INFINIBAND_NES_DEBUG |
| 79 | static unsigned char *nes_iwarp_state_str[] = { | 81 | static unsigned char *nes_iwarp_state_str[] = { |
| @@ -2903,6 +2905,417 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq) | |||
| 2903 | } | 2905 | } |
| 2904 | 2906 | ||
| 2905 | 2907 | ||
| 2908 | static u8 *locate_mpa(u8 *pkt, u32 aeq_info) | ||
| 2909 | { | ||
| 2910 | u16 pkt_len; | ||
| 2911 | |||
| 2912 | if (aeq_info & NES_AEQE_Q2_DATA_ETHERNET) { | ||
| 2913 | /* skip over ethernet header */ | ||
| 2914 | pkt_len = be16_to_cpu(*(u16 *)(pkt + ETH_HLEN - 2)); | ||
| 2915 | pkt += ETH_HLEN; | ||
| 2916 | |||
| 2917 | /* Skip over IP and TCP headers */ | ||
| 2918 | pkt += 4 * (pkt[0] & 0x0f); | ||
| 2919 | pkt += 4 * ((pkt[12] >> 4) & 0x0f); | ||
| 2920 | } | ||
| 2921 | return pkt; | ||
| 2922 | } | ||
| 2923 | |||
| 2924 | /* Determine if incoming error pkt is rdma layer */ | ||
| 2925 | static u32 iwarp_opcode(struct nes_qp *nesqp, u32 aeq_info) | ||
| 2926 | { | ||
| 2927 | u8 *pkt; | ||
| 2928 | u16 *mpa; | ||
| 2929 | u32 opcode = 0xffffffff; | ||
| 2930 | |||
| 2931 | if (aeq_info & NES_AEQE_Q2_DATA_WRITTEN) { | ||
| 2932 | pkt = nesqp->hwqp.q2_vbase + BAD_FRAME_OFFSET; | ||
| 2933 | mpa = (u16 *)locate_mpa(pkt, aeq_info); | ||
| 2934 | opcode = be16_to_cpu(mpa[1]) & 0xf; | ||
| 2935 | } | ||
| 2936 | |||
| 2937 | return opcode; | ||
| 2938 | } | ||
| 2939 | |||
| 2940 | /* Build iWARP terminate header */ | ||
| 2941 | static int nes_bld_terminate_hdr(struct nes_qp *nesqp, u16 async_event_id, u32 aeq_info) | ||
| 2942 | { | ||
| 2943 | u8 *pkt = nesqp->hwqp.q2_vbase + BAD_FRAME_OFFSET; | ||
| 2944 | u16 ddp_seg_len; | ||
| 2945 | int copy_len = 0; | ||
| 2946 | u8 is_tagged = 0; | ||
| 2947 | u8 flush_code = 0; | ||
| 2948 | struct nes_terminate_hdr *termhdr; | ||
| 2949 | |||
| 2950 | termhdr = (struct nes_terminate_hdr *)nesqp->hwqp.q2_vbase; | ||
| 2951 | memset(termhdr, 0, 64); | ||
| 2952 | |||
| 2953 | if (aeq_info & NES_AEQE_Q2_DATA_WRITTEN) { | ||
| 2954 | |||
| 2955 | /* Use data from offending packet to fill in ddp & rdma hdrs */ | ||
| 2956 | pkt = locate_mpa(pkt, aeq_info); | ||
| 2957 | ddp_seg_len = be16_to_cpu(*(u16 *)pkt); | ||
| 2958 | if (ddp_seg_len) { | ||
| 2959 | copy_len = 2; | ||
| 2960 | termhdr->hdrct = DDP_LEN_FLAG; | ||
| 2961 | if (pkt[2] & 0x80) { | ||
| 2962 | is_tagged = 1; | ||
| 2963 | if (ddp_seg_len >= TERM_DDP_LEN_TAGGED) { | ||
| 2964 | copy_len += TERM_DDP_LEN_TAGGED; | ||
| 2965 | termhdr->hdrct |= DDP_HDR_FLAG; | ||
| 2966 | } | ||
| 2967 | } else { | ||
| 2968 | if (ddp_seg_len >= TERM_DDP_LEN_UNTAGGED) { | ||
| 2969 | copy_len += TERM_DDP_LEN_UNTAGGED; | ||
| 2970 | termhdr->hdrct |= DDP_HDR_FLAG; | ||
| 2971 | } | ||
| 2972 | |||
| 2973 | if (ddp_seg_len >= (TERM_DDP_LEN_UNTAGGED + TERM_RDMA_LEN)) { | ||
| 2974 | if ((pkt[3] & RDMA_OPCODE_MASK) == RDMA_READ_REQ_OPCODE) { | ||
| 2975 | copy_len += TERM_RDMA_LEN; | ||
| 2976 | termhdr->hdrct |= RDMA_HDR_FLAG; | ||
| 2977 | } | ||
| 2978 | } | ||
| 2979 | } | ||
| 2980 | } | ||
| 2981 | } | ||
| 2982 | |||
| 2983 | switch (async_event_id) { | ||
| 2984 | case NES_AEQE_AEID_AMP_UNALLOCATED_STAG: | ||
| 2985 | switch (iwarp_opcode(nesqp, aeq_info)) { | ||
| 2986 | case IWARP_OPCODE_WRITE: | ||
| 2987 | flush_code = IB_WC_LOC_PROT_ERR; | ||
| 2988 | termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER; | ||
| 2989 | termhdr->error_code = DDP_TAGGED_INV_STAG; | ||
| 2990 | break; | ||
| 2991 | default: | ||
| 2992 | flush_code = IB_WC_REM_ACCESS_ERR; | ||
| 2993 | termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT; | ||
| 2994 | termhdr->error_code = RDMAP_INV_STAG; | ||
| 2995 | } | ||
| 2996 | break; | ||
| 2997 | case NES_AEQE_AEID_AMP_INVALID_STAG: | ||
| 2998 | flush_code = IB_WC_REM_ACCESS_ERR; | ||
| 2999 | termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT; | ||
| 3000 | termhdr->error_code = RDMAP_INV_STAG; | ||
| 3001 | break; | ||
| 3002 | case NES_AEQE_AEID_AMP_BAD_QP: | ||
| 3003 | flush_code = IB_WC_LOC_QP_OP_ERR; | ||
| 3004 | termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER; | ||
| 3005 | termhdr->error_code = DDP_UNTAGGED_INV_QN; | ||
| 3006 | break; | ||
| 3007 | case NES_AEQE_AEID_AMP_BAD_STAG_KEY: | ||
| 3008 | case NES_AEQE_AEID_AMP_BAD_STAG_INDEX: | ||
| 3009 | switch (iwarp_opcode(nesqp, aeq_info)) { | ||
| 3010 | case IWARP_OPCODE_SEND_INV: | ||
| 3011 | case IWARP_OPCODE_SEND_SE_INV: | ||
| 3012 | flush_code = IB_WC_REM_OP_ERR; | ||
| 3013 | termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP; | ||
| 3014 | termhdr->error_code = RDMAP_CANT_INV_STAG; | ||
| 3015 | break; | ||
| 3016 | default: | ||
| 3017 | flush_code = IB_WC_REM_ACCESS_ERR; | ||
| 3018 | termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT; | ||
| 3019 | termhdr->error_code = RDMAP_INV_STAG; | ||
| 3020 | } | ||
| 3021 | break; | ||
| 3022 | case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION: | ||
| 3023 | if (aeq_info & (NES_AEQE_Q2_DATA_ETHERNET | NES_AEQE_Q2_DATA_MPA)) { | ||
| 3024 | flush_code = IB_WC_LOC_PROT_ERR; | ||
| 3025 | termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER; | ||
| 3026 | termhdr->error_code = DDP_TAGGED_BOUNDS; | ||
| 3027 | } else { | ||
| 3028 | flush_code = IB_WC_REM_ACCESS_ERR; | ||
| 3029 | termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT; | ||
| 3030 | termhdr->error_code = RDMAP_INV_BOUNDS; | ||
| 3031 | } | ||
| 3032 | break; | ||
| 3033 | case NES_AEQE_AEID_AMP_RIGHTS_VIOLATION: | ||
| 3034 | case NES_AEQE_AEID_AMP_INVALIDATE_NO_REMOTE_ACCESS_RIGHTS: | ||
| 3035 | case NES_AEQE_AEID_PRIV_OPERATION_DENIED: | ||
| 3036 | flush_code = IB_WC_REM_ACCESS_ERR; | ||
| 3037 | termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT; | ||
| 3038 | termhdr->error_code = RDMAP_ACCESS; | ||
| 3039 | break; | ||
| 3040 | case NES_AEQE_AEID_AMP_TO_WRAP: | ||
| 3041 | flush_code = IB_WC_REM_ACCESS_ERR; | ||
| 3042 | termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT; | ||
| 3043 | termhdr->error_code = RDMAP_TO_WRAP; | ||
| 3044 | break; | ||
| 3045 | case NES_AEQE_AEID_AMP_BAD_PD: | ||
| 3046 | switch (iwarp_opcode(nesqp, aeq_info)) { | ||
| 3047 | case IWARP_OPCODE_WRITE: | ||
| 3048 | flush_code = IB_WC_LOC_PROT_ERR; | ||
| 3049 | termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER; | ||
| 3050 | termhdr->error_code = DDP_TAGGED_UNASSOC_STAG; | ||
| 3051 | break; | ||
| 3052 | case IWARP_OPCODE_SEND_INV: | ||
| 3053 | case IWARP_OPCODE_SEND_SE_INV: | ||
| 3054 | flush_code = IB_WC_REM_ACCESS_ERR; | ||
| 3055 | termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT; | ||
| 3056 | termhdr->error_code = RDMAP_CANT_INV_STAG; | ||
| 3057 | break; | ||
| 3058 | default: | ||
| 3059 | flush_code = IB_WC_REM_ACCESS_ERR; | ||
| 3060 | termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_PROT; | ||
| 3061 | termhdr->error_code = RDMAP_UNASSOC_STAG; | ||
| 3062 | } | ||
| 3063 | break; | ||
| 3064 | case NES_AEQE_AEID_LLP_RECEIVED_MARKER_AND_LENGTH_FIELDS_DONT_MATCH: | ||
| 3065 | flush_code = IB_WC_LOC_LEN_ERR; | ||
| 3066 | termhdr->layer_etype = (LAYER_MPA << 4) | DDP_LLP; | ||
| 3067 | termhdr->error_code = MPA_MARKER; | ||
| 3068 | break; | ||
| 3069 | case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR: | ||
| 3070 | flush_code = IB_WC_GENERAL_ERR; | ||
| 3071 | termhdr->layer_etype = (LAYER_MPA << 4) | DDP_LLP; | ||
| 3072 | termhdr->error_code = MPA_CRC; | ||
| 3073 | break; | ||
| 3074 | case NES_AEQE_AEID_LLP_SEGMENT_TOO_LARGE: | ||
| 3075 | case NES_AEQE_AEID_LLP_SEGMENT_TOO_SMALL: | ||
| 3076 | flush_code = IB_WC_LOC_LEN_ERR; | ||
| 3077 | termhdr->layer_etype = (LAYER_DDP << 4) | DDP_CATASTROPHIC; | ||
| 3078 | termhdr->error_code = DDP_CATASTROPHIC_LOCAL; | ||
| 3079 | break; | ||
| 3080 | case NES_AEQE_AEID_DDP_LCE_LOCAL_CATASTROPHIC: | ||
| 3081 | case NES_AEQE_AEID_DDP_NO_L_BIT: | ||
| 3082 | flush_code = IB_WC_FATAL_ERR; | ||
| 3083 | termhdr->layer_etype = (LAYER_DDP << 4) | DDP_CATASTROPHIC; | ||
| 3084 | termhdr->error_code = DDP_CATASTROPHIC_LOCAL; | ||
| 3085 | break; | ||
| 3086 | case NES_AEQE_AEID_DDP_INVALID_MSN_GAP_IN_MSN: | ||
| 3087 | case NES_AEQE_AEID_DDP_INVALID_MSN_RANGE_IS_NOT_VALID: | ||
| 3088 | flush_code = IB_WC_GENERAL_ERR; | ||
| 3089 | termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER; | ||
| 3090 | termhdr->error_code = DDP_UNTAGGED_INV_MSN_RANGE; | ||
| 3091 | break; | ||
| 3092 | case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER: | ||
| 3093 | flush_code = IB_WC_LOC_LEN_ERR; | ||
| 3094 | termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER; | ||
| 3095 | termhdr->error_code = DDP_UNTAGGED_INV_TOO_LONG; | ||
| 3096 | break; | ||
| 3097 | case NES_AEQE_AEID_DDP_UBE_INVALID_DDP_VERSION: | ||
| 3098 | flush_code = IB_WC_GENERAL_ERR; | ||
| 3099 | if (is_tagged) { | ||
| 3100 | termhdr->layer_etype = (LAYER_DDP << 4) | DDP_TAGGED_BUFFER; | ||
| 3101 | termhdr->error_code = DDP_TAGGED_INV_DDP_VER; | ||
| 3102 | } else { | ||
| 3103 | termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER; | ||
| 3104 | termhdr->error_code = DDP_UNTAGGED_INV_DDP_VER; | ||
| 3105 | } | ||
| 3106 | break; | ||
| 3107 | case NES_AEQE_AEID_DDP_UBE_INVALID_MO: | ||
| 3108 | flush_code = IB_WC_GENERAL_ERR; | ||
| 3109 | termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER; | ||
| 3110 | termhdr->error_code = DDP_UNTAGGED_INV_MO; | ||
| 3111 | break; | ||
| 3112 | case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE: | ||
| 3113 | flush_code = IB_WC_REM_OP_ERR; | ||
| 3114 | termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER; | ||
| 3115 | termhdr->error_code = DDP_UNTAGGED_INV_MSN_NO_BUF; | ||
| 3116 | break; | ||
| 3117 | case NES_AEQE_AEID_DDP_UBE_INVALID_QN: | ||
| 3118 | flush_code = IB_WC_GENERAL_ERR; | ||
| 3119 | termhdr->layer_etype = (LAYER_DDP << 4) | DDP_UNTAGGED_BUFFER; | ||
| 3120 | termhdr->error_code = DDP_UNTAGGED_INV_QN; | ||
| 3121 | break; | ||
| 3122 | case NES_AEQE_AEID_RDMAP_ROE_INVALID_RDMAP_VERSION: | ||
| 3123 | flush_code = IB_WC_GENERAL_ERR; | ||
| 3124 | termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP; | ||
| 3125 | termhdr->error_code = RDMAP_INV_RDMAP_VER; | ||
| 3126 | break; | ||
| 3127 | case NES_AEQE_AEID_RDMAP_ROE_UNEXPECTED_OPCODE: | ||
| 3128 | flush_code = IB_WC_LOC_QP_OP_ERR; | ||
| 3129 | termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP; | ||
| 3130 | termhdr->error_code = RDMAP_UNEXPECTED_OP; | ||
| 3131 | break; | ||
| 3132 | default: | ||
| 3133 | flush_code = IB_WC_FATAL_ERR; | ||
| 3134 | termhdr->layer_etype = (LAYER_RDMA << 4) | RDMAP_REMOTE_OP; | ||
| 3135 | termhdr->error_code = RDMAP_UNSPECIFIED; | ||
| 3136 | break; | ||
| 3137 | } | ||
| 3138 | |||
| 3139 | if (copy_len) | ||
| 3140 | memcpy(termhdr + 1, pkt, copy_len); | ||
| 3141 | |||
| 3142 | if ((flush_code) && ((NES_AEQE_INBOUND_RDMA & aeq_info) == 0)) { | ||
| 3143 | if (aeq_info & NES_AEQE_SQ) | ||
| 3144 | nesqp->term_sq_flush_code = flush_code; | ||
| 3145 | else | ||
| 3146 | nesqp->term_rq_flush_code = flush_code; | ||
| 3147 | } | ||
| 3148 | |||
| 3149 | return sizeof(struct nes_terminate_hdr) + copy_len; | ||
| 3150 | } | ||
| 3151 | |||
| 3152 | static void nes_terminate_connection(struct nes_device *nesdev, struct nes_qp *nesqp, | ||
| 3153 | struct nes_hw_aeqe *aeqe, enum ib_event_type eventtype) | ||
| 3154 | { | ||
| 3155 | u64 context; | ||
| 3156 | unsigned long flags; | ||
| 3157 | u32 aeq_info; | ||
| 3158 | u16 async_event_id; | ||
| 3159 | u8 tcp_state; | ||
| 3160 | u8 iwarp_state; | ||
| 3161 | u32 termlen = 0; | ||
| 3162 | u32 mod_qp_flags = NES_CQP_QP_IWARP_STATE_TERMINATE | | ||
| 3163 | NES_CQP_QP_TERM_DONT_SEND_FIN; | ||
| 3164 | struct nes_adapter *nesadapter = nesdev->nesadapter; | ||
| 3165 | |||
| 3166 | if (nesqp->term_flags & NES_TERM_SENT) | ||
| 3167 | return; /* Sanity check */ | ||
| 3168 | |||
| 3169 | aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]); | ||
| 3170 | tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT; | ||
| 3171 | iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT; | ||
| 3172 | async_event_id = (u16)aeq_info; | ||
| 3173 | |||
| 3174 | context = (unsigned long)nesadapter->qp_table[le32_to_cpu( | ||
| 3175 | aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN]; | ||
| 3176 | if (!context) { | ||
| 3177 | WARN_ON(!context); | ||
| 3178 | return; | ||
| 3179 | } | ||
| 3180 | |||
| 3181 | nesqp = (struct nes_qp *)(unsigned long)context; | ||
| 3182 | spin_lock_irqsave(&nesqp->lock, flags); | ||
| 3183 | nesqp->hw_iwarp_state = iwarp_state; | ||
| 3184 | nesqp->hw_tcp_state = tcp_state; | ||
| 3185 | nesqp->last_aeq = async_event_id; | ||
| 3186 | nesqp->terminate_eventtype = eventtype; | ||
| 3187 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 3188 | |||
| 3189 | if (nesadapter->send_term_ok) | ||
| 3190 | termlen = nes_bld_terminate_hdr(nesqp, async_event_id, aeq_info); | ||
| 3191 | else | ||
| 3192 | mod_qp_flags |= NES_CQP_QP_TERM_DONT_SEND_TERM_MSG; | ||
| 3193 | |||
| 3194 | nes_terminate_start_timer(nesqp); | ||
| 3195 | nesqp->term_flags |= NES_TERM_SENT; | ||
| 3196 | nes_hw_modify_qp(nesdev, nesqp, mod_qp_flags, termlen, 0); | ||
| 3197 | } | ||
| 3198 | |||
| 3199 | static void nes_terminate_send_fin(struct nes_device *nesdev, | ||
| 3200 | struct nes_qp *nesqp, struct nes_hw_aeqe *aeqe) | ||
| 3201 | { | ||
| 3202 | u32 aeq_info; | ||
| 3203 | u16 async_event_id; | ||
| 3204 | u8 tcp_state; | ||
| 3205 | u8 iwarp_state; | ||
| 3206 | unsigned long flags; | ||
| 3207 | |||
| 3208 | aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]); | ||
| 3209 | tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT; | ||
| 3210 | iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT; | ||
| 3211 | async_event_id = (u16)aeq_info; | ||
| 3212 | |||
| 3213 | spin_lock_irqsave(&nesqp->lock, flags); | ||
| 3214 | nesqp->hw_iwarp_state = iwarp_state; | ||
| 3215 | nesqp->hw_tcp_state = tcp_state; | ||
| 3216 | nesqp->last_aeq = async_event_id; | ||
| 3217 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 3218 | |||
| 3219 | /* Send the fin only */ | ||
| 3220 | nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_TERMINATE | | ||
| 3221 | NES_CQP_QP_TERM_DONT_SEND_TERM_MSG, 0, 0); | ||
| 3222 | } | ||
| 3223 | |||
| 3224 | /* Cleanup after a terminate sent or received */ | ||
| 3225 | static void nes_terminate_done(struct nes_qp *nesqp, int timeout_occurred) | ||
| 3226 | { | ||
| 3227 | u32 next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR; | ||
| 3228 | unsigned long flags; | ||
| 3229 | struct nes_vnic *nesvnic = to_nesvnic(nesqp->ibqp.device); | ||
| 3230 | struct nes_device *nesdev = nesvnic->nesdev; | ||
| 3231 | u8 first_time = 0; | ||
| 3232 | |||
| 3233 | spin_lock_irqsave(&nesqp->lock, flags); | ||
| 3234 | if (nesqp->hte_added) { | ||
| 3235 | nesqp->hte_added = 0; | ||
| 3236 | next_iwarp_state |= NES_CQP_QP_DEL_HTE; | ||
| 3237 | } | ||
| 3238 | |||
| 3239 | first_time = (nesqp->term_flags & NES_TERM_DONE) == 0; | ||
| 3240 | nesqp->term_flags |= NES_TERM_DONE; | ||
| 3241 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 3242 | |||
| 3243 | /* Make sure we go through this only once */ | ||
| 3244 | if (first_time) { | ||
| 3245 | if (timeout_occurred == 0) | ||
| 3246 | del_timer(&nesqp->terminate_timer); | ||
| 3247 | else | ||
| 3248 | next_iwarp_state |= NES_CQP_QP_RESET; | ||
| 3249 | |||
| 3250 | nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 0); | ||
| 3251 | nes_cm_disconn(nesqp); | ||
| 3252 | } | ||
| 3253 | } | ||
| 3254 | |||
| 3255 | static void nes_terminate_received(struct nes_device *nesdev, | ||
| 3256 | struct nes_qp *nesqp, struct nes_hw_aeqe *aeqe) | ||
| 3257 | { | ||
| 3258 | u32 aeq_info; | ||
| 3259 | u8 *pkt; | ||
| 3260 | u32 *mpa; | ||
| 3261 | u8 ddp_ctl; | ||
| 3262 | u8 rdma_ctl; | ||
| 3263 | u16 aeq_id = 0; | ||
| 3264 | |||
| 3265 | aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]); | ||
| 3266 | if (aeq_info & NES_AEQE_Q2_DATA_WRITTEN) { | ||
| 3267 | /* Terminate is not a performance path so the silicon */ | ||
| 3268 | /* did not validate the frame - do it now */ | ||
| 3269 | pkt = nesqp->hwqp.q2_vbase + BAD_FRAME_OFFSET; | ||
| 3270 | mpa = (u32 *)locate_mpa(pkt, aeq_info); | ||
| 3271 | ddp_ctl = (be32_to_cpu(mpa[0]) >> 8) & 0xff; | ||
| 3272 | rdma_ctl = be32_to_cpu(mpa[0]) & 0xff; | ||
| 3273 | if ((ddp_ctl & 0xc0) != 0x40) | ||
| 3274 | aeq_id = NES_AEQE_AEID_DDP_LCE_LOCAL_CATASTROPHIC; | ||
| 3275 | else if ((ddp_ctl & 0x03) != 1) | ||
| 3276 | aeq_id = NES_AEQE_AEID_DDP_UBE_INVALID_DDP_VERSION; | ||
| 3277 | else if (be32_to_cpu(mpa[2]) != 2) | ||
| 3278 | aeq_id = NES_AEQE_AEID_DDP_UBE_INVALID_QN; | ||
| 3279 | else if (be32_to_cpu(mpa[3]) != 1) | ||
| 3280 | aeq_id = NES_AEQE_AEID_DDP_INVALID_MSN_GAP_IN_MSN; | ||
| 3281 | else if (be32_to_cpu(mpa[4]) != 0) | ||
| 3282 | aeq_id = NES_AEQE_AEID_DDP_UBE_INVALID_MO; | ||
| 3283 | else if ((rdma_ctl & 0xc0) != 0x40) | ||
| 3284 | aeq_id = NES_AEQE_AEID_RDMAP_ROE_INVALID_RDMAP_VERSION; | ||
| 3285 | |||
| 3286 | if (aeq_id) { | ||
| 3287 | /* Bad terminate recvd - send back a terminate */ | ||
| 3288 | aeq_info = (aeq_info & 0xffff0000) | aeq_id; | ||
| 3289 | aeqe->aeqe_words[NES_AEQE_MISC_IDX] = cpu_to_le32(aeq_info); | ||
| 3290 | nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL); | ||
| 3291 | return; | ||
| 3292 | } | ||
| 3293 | } | ||
| 3294 | |||
| 3295 | nesqp->term_flags |= NES_TERM_RCVD; | ||
| 3296 | nesqp->terminate_eventtype = IB_EVENT_QP_FATAL; | ||
| 3297 | nes_terminate_start_timer(nesqp); | ||
| 3298 | nes_terminate_send_fin(nesdev, nesqp, aeqe); | ||
| 3299 | } | ||
| 3300 | |||
| 3301 | /* Timeout routine in case terminate fails to complete */ | ||
| 3302 | static void nes_terminate_timeout(unsigned long context) | ||
| 3303 | { | ||
| 3304 | struct nes_qp *nesqp = (struct nes_qp *)(unsigned long)context; | ||
| 3305 | |||
| 3306 | nes_terminate_done(nesqp, 1); | ||
| 3307 | } | ||
| 3308 | |||
| 3309 | /* Set a timer in case hw cannot complete the terminate sequence */ | ||
| 3310 | static void nes_terminate_start_timer(struct nes_qp *nesqp) | ||
| 3311 | { | ||
| 3312 | init_timer(&nesqp->terminate_timer); | ||
| 3313 | nesqp->terminate_timer.function = nes_terminate_timeout; | ||
| 3314 | nesqp->terminate_timer.expires = jiffies + HZ; | ||
| 3315 | nesqp->terminate_timer.data = (unsigned long)nesqp; | ||
| 3316 | add_timer(&nesqp->terminate_timer); | ||
| 3317 | } | ||
| 3318 | |||
| 2906 | /** | 3319 | /** |
| 2907 | * nes_process_iwarp_aeqe | 3320 | * nes_process_iwarp_aeqe |
| 2908 | */ | 3321 | */ |
| @@ -2910,28 +3323,27 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
| 2910 | struct nes_hw_aeqe *aeqe) | 3323 | struct nes_hw_aeqe *aeqe) |
| 2911 | { | 3324 | { |
| 2912 | u64 context; | 3325 | u64 context; |
| 2913 | u64 aeqe_context = 0; | ||
| 2914 | unsigned long flags; | 3326 | unsigned long flags; |
| 2915 | struct nes_qp *nesqp; | 3327 | struct nes_qp *nesqp; |
| 3328 | struct nes_hw_cq *hw_cq; | ||
| 3329 | struct nes_cq *nescq; | ||
| 2916 | int resource_allocated; | 3330 | int resource_allocated; |
| 2917 | /* struct iw_cm_id *cm_id; */ | ||
| 2918 | struct nes_adapter *nesadapter = nesdev->nesadapter; | 3331 | struct nes_adapter *nesadapter = nesdev->nesadapter; |
| 2919 | struct ib_event ibevent; | ||
| 2920 | /* struct iw_cm_event cm_event; */ | ||
| 2921 | u32 aeq_info; | 3332 | u32 aeq_info; |
| 2922 | u32 next_iwarp_state = 0; | 3333 | u32 next_iwarp_state = 0; |
| 2923 | u16 async_event_id; | 3334 | u16 async_event_id; |
| 2924 | u8 tcp_state; | 3335 | u8 tcp_state; |
| 2925 | u8 iwarp_state; | 3336 | u8 iwarp_state; |
| 3337 | int must_disconn = 1; | ||
| 3338 | int must_terminate = 0; | ||
| 3339 | struct ib_event ibevent; | ||
| 2926 | 3340 | ||
| 2927 | nes_debug(NES_DBG_AEQ, "\n"); | 3341 | nes_debug(NES_DBG_AEQ, "\n"); |
| 2928 | aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]); | 3342 | aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]); |
| 2929 | if ((NES_AEQE_INBOUND_RDMA&aeq_info) || (!(NES_AEQE_QP&aeq_info))) { | 3343 | if ((NES_AEQE_INBOUND_RDMA & aeq_info) || (!(NES_AEQE_QP & aeq_info))) { |
| 2930 | context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]); | 3344 | context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]); |
| 2931 | context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32; | 3345 | context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32; |
| 2932 | } else { | 3346 | } else { |
| 2933 | aeqe_context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]); | ||
| 2934 | aeqe_context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32; | ||
| 2935 | context = (unsigned long)nesadapter->qp_table[le32_to_cpu( | 3347 | context = (unsigned long)nesadapter->qp_table[le32_to_cpu( |
| 2936 | aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN]; | 3348 | aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN]; |
| 2937 | BUG_ON(!context); | 3349 | BUG_ON(!context); |
| @@ -2948,7 +3360,11 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
| 2948 | 3360 | ||
| 2949 | switch (async_event_id) { | 3361 | switch (async_event_id) { |
| 2950 | case NES_AEQE_AEID_LLP_FIN_RECEIVED: | 3362 | case NES_AEQE_AEID_LLP_FIN_RECEIVED: |
| 2951 | nesqp = *((struct nes_qp **)&context); | 3363 | nesqp = (struct nes_qp *)(unsigned long)context; |
| 3364 | |||
| 3365 | if (nesqp->term_flags) | ||
| 3366 | return; /* Ignore it, wait for close complete */ | ||
| 3367 | |||
| 2952 | if (atomic_inc_return(&nesqp->close_timer_started) == 1) { | 3368 | if (atomic_inc_return(&nesqp->close_timer_started) == 1) { |
| 2953 | nesqp->cm_id->add_ref(nesqp->cm_id); | 3369 | nesqp->cm_id->add_ref(nesqp->cm_id); |
| 2954 | schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp, | 3370 | schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp, |
| @@ -2959,18 +3375,24 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
| 2959 | nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), | 3375 | nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), |
| 2960 | async_event_id, nesqp->last_aeq, tcp_state); | 3376 | async_event_id, nesqp->last_aeq, tcp_state); |
| 2961 | } | 3377 | } |
| 3378 | |||
| 2962 | if ((tcp_state != NES_AEQE_TCP_STATE_CLOSE_WAIT) || | 3379 | if ((tcp_state != NES_AEQE_TCP_STATE_CLOSE_WAIT) || |
| 2963 | (nesqp->ibqp_state != IB_QPS_RTS)) { | 3380 | (nesqp->ibqp_state != IB_QPS_RTS)) { |
| 2964 | /* FIN Received but tcp state or IB state moved on, | 3381 | /* FIN Received but tcp state or IB state moved on, |
| 2965 | should expect a close complete */ | 3382 | should expect a close complete */ |
| 2966 | return; | 3383 | return; |
| 2967 | } | 3384 | } |
| 3385 | |||
| 2968 | case NES_AEQE_AEID_LLP_CLOSE_COMPLETE: | 3386 | case NES_AEQE_AEID_LLP_CLOSE_COMPLETE: |
| 3387 | nesqp = (struct nes_qp *)(unsigned long)context; | ||
| 3388 | if (nesqp->term_flags) { | ||
| 3389 | nes_terminate_done(nesqp, 0); | ||
| 3390 | return; | ||
| 3391 | } | ||
| 3392 | |||
| 2969 | case NES_AEQE_AEID_LLP_CONNECTION_RESET: | 3393 | case NES_AEQE_AEID_LLP_CONNECTION_RESET: |
| 2970 | case NES_AEQE_AEID_TERMINATE_SENT: | ||
| 2971 | case NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE: | ||
| 2972 | case NES_AEQE_AEID_RESET_SENT: | 3394 | case NES_AEQE_AEID_RESET_SENT: |
| 2973 | nesqp = *((struct nes_qp **)&context); | 3395 | nesqp = (struct nes_qp *)(unsigned long)context; |
| 2974 | if (async_event_id == NES_AEQE_AEID_RESET_SENT) { | 3396 | if (async_event_id == NES_AEQE_AEID_RESET_SENT) { |
| 2975 | tcp_state = NES_AEQE_TCP_STATE_CLOSED; | 3397 | tcp_state = NES_AEQE_TCP_STATE_CLOSED; |
| 2976 | } | 3398 | } |
| @@ -2982,12 +3404,7 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
| 2982 | if ((tcp_state == NES_AEQE_TCP_STATE_CLOSED) || | 3404 | if ((tcp_state == NES_AEQE_TCP_STATE_CLOSED) || |
| 2983 | (tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT)) { | 3405 | (tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT)) { |
| 2984 | nesqp->hte_added = 0; | 3406 | nesqp->hte_added = 0; |
| 2985 | spin_unlock_irqrestore(&nesqp->lock, flags); | 3407 | next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_DEL_HTE; |
| 2986 | nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u to remove hte\n", | ||
| 2987 | nesqp->hwqp.qp_id); | ||
| 2988 | nes_hw_modify_qp(nesdev, nesqp, | ||
| 2989 | NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_DEL_HTE, 0); | ||
| 2990 | spin_lock_irqsave(&nesqp->lock, flags); | ||
| 2991 | } | 3408 | } |
| 2992 | 3409 | ||
| 2993 | if ((nesqp->ibqp_state == IB_QPS_RTS) && | 3410 | if ((nesqp->ibqp_state == IB_QPS_RTS) && |
| @@ -2999,151 +3416,106 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
| 2999 | nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING; | 3416 | nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING; |
| 3000 | break; | 3417 | break; |
| 3001 | case NES_AEQE_IWARP_STATE_TERMINATE: | 3418 | case NES_AEQE_IWARP_STATE_TERMINATE: |
| 3002 | next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE; | 3419 | must_disconn = 0; /* terminate path takes care of disconn */ |
| 3003 | nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_TERMINATE; | 3420 | if (nesqp->term_flags == 0) |
| 3004 | if (async_event_id == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) { | 3421 | must_terminate = 1; |
| 3005 | next_iwarp_state |= 0x02000000; | ||
| 3006 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; | ||
| 3007 | } | ||
| 3008 | break; | 3422 | break; |
| 3009 | default: | ||
| 3010 | next_iwarp_state = 0; | ||
| 3011 | } | ||
| 3012 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 3013 | if (next_iwarp_state) { | ||
| 3014 | nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X," | ||
| 3015 | " also added another reference\n", | ||
| 3016 | nesqp->hwqp.qp_id, next_iwarp_state); | ||
| 3017 | nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0); | ||
| 3018 | } | 3423 | } |
| 3019 | nes_cm_disconn(nesqp); | ||
| 3020 | } else { | 3424 | } else { |
| 3021 | if (async_event_id == NES_AEQE_AEID_LLP_FIN_RECEIVED) { | 3425 | if (async_event_id == NES_AEQE_AEID_LLP_FIN_RECEIVED) { |
| 3022 | /* FIN Received but ib state not RTS, | 3426 | /* FIN Received but ib state not RTS, |
| 3023 | close complete will be on its way */ | 3427 | close complete will be on its way */ |
| 3024 | spin_unlock_irqrestore(&nesqp->lock, flags); | 3428 | must_disconn = 0; |
| 3025 | return; | ||
| 3026 | } | ||
| 3027 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 3028 | if (async_event_id == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) { | ||
| 3029 | next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000; | ||
| 3030 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; | ||
| 3031 | nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X," | ||
| 3032 | " also added another reference\n", | ||
| 3033 | nesqp->hwqp.qp_id, next_iwarp_state); | ||
| 3034 | nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0); | ||
| 3035 | } | 3429 | } |
| 3036 | nes_cm_disconn(nesqp); | ||
| 3037 | } | 3430 | } |
| 3038 | break; | ||
| 3039 | case NES_AEQE_AEID_LLP_TERMINATE_RECEIVED: | ||
| 3040 | nesqp = *((struct nes_qp **)&context); | ||
| 3041 | spin_lock_irqsave(&nesqp->lock, flags); | ||
| 3042 | nesqp->hw_iwarp_state = iwarp_state; | ||
| 3043 | nesqp->hw_tcp_state = tcp_state; | ||
| 3044 | nesqp->last_aeq = async_event_id; | ||
| 3045 | spin_unlock_irqrestore(&nesqp->lock, flags); | 3431 | spin_unlock_irqrestore(&nesqp->lock, flags); |
| 3046 | nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TERMINATE_RECEIVED" | 3432 | |
| 3047 | " event on QP%u \n Q2 Data:\n", | 3433 | if (must_terminate) |
| 3048 | nesqp->hwqp.qp_id); | 3434 | nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL); |
| 3049 | if (nesqp->ibqp.event_handler) { | 3435 | else if (must_disconn) { |
| 3050 | ibevent.device = nesqp->ibqp.device; | 3436 | if (next_iwarp_state) { |
| 3051 | ibevent.element.qp = &nesqp->ibqp; | 3437 | nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X\n", |
| 3052 | ibevent.event = IB_EVENT_QP_FATAL; | 3438 | nesqp->hwqp.qp_id, next_iwarp_state); |
| 3053 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); | 3439 | nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 0); |
| 3054 | } | 3440 | } |
| 3055 | if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) || | ||
| 3056 | ((nesqp->ibqp_state == IB_QPS_RTS)&& | ||
| 3057 | (async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) { | ||
| 3058 | nes_cm_disconn(nesqp); | 3441 | nes_cm_disconn(nesqp); |
| 3059 | } else { | ||
| 3060 | nesqp->in_disconnect = 0; | ||
| 3061 | wake_up(&nesqp->kick_waitq); | ||
| 3062 | } | 3442 | } |
| 3063 | break; | 3443 | break; |
| 3064 | case NES_AEQE_AEID_LLP_TOO_MANY_RETRIES: | 3444 | |
| 3065 | nesqp = *((struct nes_qp **)&context); | 3445 | case NES_AEQE_AEID_TERMINATE_SENT: |
| 3066 | spin_lock_irqsave(&nesqp->lock, flags); | 3446 | nesqp = (struct nes_qp *)(unsigned long)context; |
| 3067 | nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_ERROR; | 3447 | nes_terminate_send_fin(nesdev, nesqp, aeqe); |
| 3068 | nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED; | ||
| 3069 | nesqp->last_aeq = async_event_id; | ||
| 3070 | if (nesqp->cm_id) { | ||
| 3071 | nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TOO_MANY_RETRIES" | ||
| 3072 | " event on QP%u, remote IP = 0x%08X \n", | ||
| 3073 | nesqp->hwqp.qp_id, | ||
| 3074 | ntohl(nesqp->cm_id->remote_addr.sin_addr.s_addr)); | ||
| 3075 | } else { | ||
| 3076 | nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TOO_MANY_RETRIES" | ||
| 3077 | " event on QP%u \n", | ||
| 3078 | nesqp->hwqp.qp_id); | ||
| 3079 | } | ||
| 3080 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 3081 | next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_RESET; | ||
| 3082 | nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0); | ||
| 3083 | if (nesqp->ibqp.event_handler) { | ||
| 3084 | ibevent.device = nesqp->ibqp.device; | ||
| 3085 | ibevent.element.qp = &nesqp->ibqp; | ||
| 3086 | ibevent.event = IB_EVENT_QP_FATAL; | ||
| 3087 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); | ||
| 3088 | } | ||
| 3089 | break; | 3448 | break; |
| 3090 | case NES_AEQE_AEID_AMP_BAD_STAG_INDEX: | 3449 | |
| 3091 | if (NES_AEQE_INBOUND_RDMA&aeq_info) { | 3450 | case NES_AEQE_AEID_LLP_TERMINATE_RECEIVED: |
| 3092 | nesqp = nesadapter->qp_table[le32_to_cpu( | 3451 | nesqp = (struct nes_qp *)(unsigned long)context; |
| 3093 | aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN]; | 3452 | nes_terminate_received(nesdev, nesqp, aeqe); |
| 3094 | } else { | ||
| 3095 | /* TODO: get the actual WQE and mask off wqe index */ | ||
| 3096 | context &= ~((u64)511); | ||
| 3097 | nesqp = *((struct nes_qp **)&context); | ||
| 3098 | } | ||
| 3099 | spin_lock_irqsave(&nesqp->lock, flags); | ||
| 3100 | nesqp->hw_iwarp_state = iwarp_state; | ||
| 3101 | nesqp->hw_tcp_state = tcp_state; | ||
| 3102 | nesqp->last_aeq = async_event_id; | ||
| 3103 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 3104 | nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_AMP_BAD_STAG_INDEX event on QP%u\n", | ||
| 3105 | nesqp->hwqp.qp_id); | ||
| 3106 | if (nesqp->ibqp.event_handler) { | ||
| 3107 | ibevent.device = nesqp->ibqp.device; | ||
| 3108 | ibevent.element.qp = &nesqp->ibqp; | ||
| 3109 | ibevent.event = IB_EVENT_QP_ACCESS_ERR; | ||
| 3110 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); | ||
| 3111 | } | ||
| 3112 | break; | 3453 | break; |
| 3454 | |||
| 3455 | case NES_AEQE_AEID_AMP_BAD_STAG_KEY: | ||
| 3456 | case NES_AEQE_AEID_AMP_BAD_STAG_INDEX: | ||
| 3113 | case NES_AEQE_AEID_AMP_UNALLOCATED_STAG: | 3457 | case NES_AEQE_AEID_AMP_UNALLOCATED_STAG: |
| 3114 | nesqp = *((struct nes_qp **)&context); | 3458 | case NES_AEQE_AEID_AMP_INVALID_STAG: |
| 3115 | spin_lock_irqsave(&nesqp->lock, flags); | 3459 | case NES_AEQE_AEID_AMP_RIGHTS_VIOLATION: |
| 3116 | nesqp->hw_iwarp_state = iwarp_state; | 3460 | case NES_AEQE_AEID_AMP_INVALIDATE_NO_REMOTE_ACCESS_RIGHTS: |
| 3117 | nesqp->hw_tcp_state = tcp_state; | ||
| 3118 | nesqp->last_aeq = async_event_id; | ||
| 3119 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 3120 | nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_AMP_UNALLOCATED_STAG event on QP%u\n", | ||
| 3121 | nesqp->hwqp.qp_id); | ||
| 3122 | if (nesqp->ibqp.event_handler) { | ||
| 3123 | ibevent.device = nesqp->ibqp.device; | ||
| 3124 | ibevent.element.qp = &nesqp->ibqp; | ||
| 3125 | ibevent.event = IB_EVENT_QP_ACCESS_ERR; | ||
| 3126 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); | ||
| 3127 | } | ||
| 3128 | break; | ||
| 3129 | case NES_AEQE_AEID_PRIV_OPERATION_DENIED: | 3461 | case NES_AEQE_AEID_PRIV_OPERATION_DENIED: |
| 3130 | nesqp = nesadapter->qp_table[le32_to_cpu(aeqe->aeqe_words | 3462 | case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER: |
| 3131 | [NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN]; | 3463 | case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION: |
| 3132 | spin_lock_irqsave(&nesqp->lock, flags); | 3464 | case NES_AEQE_AEID_AMP_TO_WRAP: |
| 3133 | nesqp->hw_iwarp_state = iwarp_state; | 3465 | nesqp = (struct nes_qp *)(unsigned long)context; |
| 3134 | nesqp->hw_tcp_state = tcp_state; | 3466 | nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_ACCESS_ERR); |
| 3135 | nesqp->last_aeq = async_event_id; | 3467 | break; |
| 3136 | spin_unlock_irqrestore(&nesqp->lock, flags); | 3468 | |
| 3137 | nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_PRIV_OPERATION_DENIED event on QP%u," | 3469 | case NES_AEQE_AEID_LLP_SEGMENT_TOO_LARGE: |
| 3138 | " nesqp = %p, AE reported %p\n", | 3470 | case NES_AEQE_AEID_LLP_SEGMENT_TOO_SMALL: |
| 3139 | nesqp->hwqp.qp_id, nesqp, *((struct nes_qp **)&context)); | 3471 | case NES_AEQE_AEID_DDP_UBE_INVALID_MO: |
| 3140 | if (nesqp->ibqp.event_handler) { | 3472 | case NES_AEQE_AEID_DDP_UBE_INVALID_QN: |
| 3141 | ibevent.device = nesqp->ibqp.device; | 3473 | nesqp = (struct nes_qp *)(unsigned long)context; |
| 3142 | ibevent.element.qp = &nesqp->ibqp; | 3474 | if (iwarp_opcode(nesqp, aeq_info) > IWARP_OPCODE_TERM) { |
| 3143 | ibevent.event = IB_EVENT_QP_ACCESS_ERR; | 3475 | aeq_info &= 0xffff0000; |
| 3144 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); | 3476 | aeq_info |= NES_AEQE_AEID_RDMAP_ROE_UNEXPECTED_OPCODE; |
| 3477 | aeqe->aeqe_words[NES_AEQE_MISC_IDX] = cpu_to_le32(aeq_info); | ||
| 3145 | } | 3478 | } |
| 3479 | |||
| 3480 | case NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE: | ||
| 3481 | case NES_AEQE_AEID_LLP_TOO_MANY_RETRIES: | ||
| 3482 | case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE: | ||
| 3483 | case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR: | ||
| 3484 | case NES_AEQE_AEID_AMP_BAD_QP: | ||
| 3485 | case NES_AEQE_AEID_LLP_RECEIVED_MARKER_AND_LENGTH_FIELDS_DONT_MATCH: | ||
| 3486 | case NES_AEQE_AEID_DDP_LCE_LOCAL_CATASTROPHIC: | ||
| 3487 | case NES_AEQE_AEID_DDP_NO_L_BIT: | ||
| 3488 | case NES_AEQE_AEID_DDP_INVALID_MSN_GAP_IN_MSN: | ||
| 3489 | case NES_AEQE_AEID_DDP_INVALID_MSN_RANGE_IS_NOT_VALID: | ||
| 3490 | case NES_AEQE_AEID_DDP_UBE_INVALID_DDP_VERSION: | ||
| 3491 | case NES_AEQE_AEID_RDMAP_ROE_INVALID_RDMAP_VERSION: | ||
| 3492 | case NES_AEQE_AEID_RDMAP_ROE_UNEXPECTED_OPCODE: | ||
| 3493 | case NES_AEQE_AEID_AMP_BAD_PD: | ||
| 3494 | case NES_AEQE_AEID_AMP_FASTREG_SHARED: | ||
| 3495 | case NES_AEQE_AEID_AMP_FASTREG_VALID_STAG: | ||
| 3496 | case NES_AEQE_AEID_AMP_FASTREG_MW_STAG: | ||
| 3497 | case NES_AEQE_AEID_AMP_FASTREG_INVALID_RIGHTS: | ||
| 3498 | case NES_AEQE_AEID_AMP_FASTREG_PBL_TABLE_OVERFLOW: | ||
| 3499 | case NES_AEQE_AEID_AMP_FASTREG_INVALID_LENGTH: | ||
| 3500 | case NES_AEQE_AEID_AMP_INVALIDATE_SHARED: | ||
| 3501 | case NES_AEQE_AEID_AMP_INVALIDATE_MR_WITH_BOUND_WINDOWS: | ||
| 3502 | case NES_AEQE_AEID_AMP_MWBIND_VALID_STAG: | ||
| 3503 | case NES_AEQE_AEID_AMP_MWBIND_OF_MR_STAG: | ||
| 3504 | case NES_AEQE_AEID_AMP_MWBIND_TO_ZERO_BASED_STAG: | ||
| 3505 | case NES_AEQE_AEID_AMP_MWBIND_TO_MW_STAG: | ||
| 3506 | case NES_AEQE_AEID_AMP_MWBIND_INVALID_RIGHTS: | ||
| 3507 | case NES_AEQE_AEID_AMP_MWBIND_INVALID_BOUNDS: | ||
| 3508 | case NES_AEQE_AEID_AMP_MWBIND_TO_INVALID_PARENT: | ||
| 3509 | case NES_AEQE_AEID_AMP_MWBIND_BIND_DISABLED: | ||
| 3510 | case NES_AEQE_AEID_BAD_CLOSE: | ||
| 3511 | case NES_AEQE_AEID_RDMA_READ_WHILE_ORD_ZERO: | ||
| 3512 | case NES_AEQE_AEID_STAG_ZERO_INVALID: | ||
| 3513 | case NES_AEQE_AEID_ROE_INVALID_RDMA_READ_REQUEST: | ||
| 3514 | case NES_AEQE_AEID_ROE_INVALID_RDMA_WRITE_OR_READ_RESP: | ||
| 3515 | nesqp = (struct nes_qp *)(unsigned long)context; | ||
| 3516 | nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL); | ||
| 3146 | break; | 3517 | break; |
| 3518 | |||
| 3147 | case NES_AEQE_AEID_CQ_OPERATION_ERROR: | 3519 | case NES_AEQE_AEID_CQ_OPERATION_ERROR: |
| 3148 | context <<= 1; | 3520 | context <<= 1; |
| 3149 | nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u, %p\n", | 3521 | nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u, %p\n", |
| @@ -3153,83 +3525,19 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
| 3153 | if (resource_allocated) { | 3525 | if (resource_allocated) { |
| 3154 | printk(KERN_ERR PFX "%s: Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u\n", | 3526 | printk(KERN_ERR PFX "%s: Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u\n", |
| 3155 | __func__, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])); | 3527 | __func__, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])); |
| 3528 | hw_cq = (struct nes_hw_cq *)(unsigned long)context; | ||
| 3529 | if (hw_cq) { | ||
| 3530 | nescq = container_of(hw_cq, struct nes_cq, hw_cq); | ||
| 3531 | if (nescq->ibcq.event_handler) { | ||
| 3532 | ibevent.device = nescq->ibcq.device; | ||
| 3533 | ibevent.event = IB_EVENT_CQ_ERR; | ||
| 3534 | ibevent.element.cq = &nescq->ibcq; | ||
| 3535 | nescq->ibcq.event_handler(&ibevent, nescq->ibcq.cq_context); | ||
| 3536 | } | ||
| 3537 | } | ||
| 3156 | } | 3538 | } |
| 3157 | break; | 3539 | break; |
| 3158 | case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER: | 3540 | |
| 3159 | nesqp = nesadapter->qp_table[le32_to_cpu( | ||
| 3160 | aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN]; | ||
| 3161 | spin_lock_irqsave(&nesqp->lock, flags); | ||
| 3162 | nesqp->hw_iwarp_state = iwarp_state; | ||
| 3163 | nesqp->hw_tcp_state = tcp_state; | ||
| 3164 | nesqp->last_aeq = async_event_id; | ||
| 3165 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 3166 | nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG" | ||
| 3167 | "_FOR_AVAILABLE_BUFFER event on QP%u\n", | ||
| 3168 | nesqp->hwqp.qp_id); | ||
| 3169 | if (nesqp->ibqp.event_handler) { | ||
| 3170 | ibevent.device = nesqp->ibqp.device; | ||
| 3171 | ibevent.element.qp = &nesqp->ibqp; | ||
| 3172 | ibevent.event = IB_EVENT_QP_ACCESS_ERR; | ||
| 3173 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); | ||
| 3174 | } | ||
| 3175 | /* tell cm to disconnect, cm will queue work to thread */ | ||
| 3176 | nes_cm_disconn(nesqp); | ||
| 3177 | break; | ||
| 3178 | case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE: | ||
| 3179 | nesqp = *((struct nes_qp **)&context); | ||
| 3180 | spin_lock_irqsave(&nesqp->lock, flags); | ||
| 3181 | nesqp->hw_iwarp_state = iwarp_state; | ||
| 3182 | nesqp->hw_tcp_state = tcp_state; | ||
| 3183 | nesqp->last_aeq = async_event_id; | ||
| 3184 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 3185 | nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_DDP_UBE_INVALID_MSN" | ||
| 3186 | "_NO_BUFFER_AVAILABLE event on QP%u\n", | ||
| 3187 | nesqp->hwqp.qp_id); | ||
| 3188 | if (nesqp->ibqp.event_handler) { | ||
| 3189 | ibevent.device = nesqp->ibqp.device; | ||
| 3190 | ibevent.element.qp = &nesqp->ibqp; | ||
| 3191 | ibevent.event = IB_EVENT_QP_FATAL; | ||
| 3192 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); | ||
| 3193 | } | ||
| 3194 | /* tell cm to disconnect, cm will queue work to thread */ | ||
| 3195 | nes_cm_disconn(nesqp); | ||
| 3196 | break; | ||
| 3197 | case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR: | ||
| 3198 | nesqp = *((struct nes_qp **)&context); | ||
| 3199 | spin_lock_irqsave(&nesqp->lock, flags); | ||
| 3200 | nesqp->hw_iwarp_state = iwarp_state; | ||
| 3201 | nesqp->hw_tcp_state = tcp_state; | ||
| 3202 | nesqp->last_aeq = async_event_id; | ||
| 3203 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 3204 | nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR" | ||
| 3205 | " event on QP%u \n Q2 Data:\n", | ||
| 3206 | nesqp->hwqp.qp_id); | ||
| 3207 | if (nesqp->ibqp.event_handler) { | ||
| 3208 | ibevent.device = nesqp->ibqp.device; | ||
| 3209 | ibevent.element.qp = &nesqp->ibqp; | ||
| 3210 | ibevent.event = IB_EVENT_QP_FATAL; | ||
| 3211 | nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context); | ||
| 3212 | } | ||
| 3213 | /* tell cm to disconnect, cm will queue work to thread */ | ||
| 3214 | nes_cm_disconn(nesqp); | ||
| 3215 | break; | ||
| 3216 | /* TODO: additional AEs need to be here */ | ||
| 3217 | case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION: | ||
| 3218 | nesqp = *((struct nes_qp **)&context); | ||
| 3219 | spin_lock_irqsave(&nesqp->lock, flags); | ||
| 3220 | nesqp->hw_iwarp_state = iwarp_state; | ||
| 3221 | nesqp->hw_tcp_state = tcp_state; | ||
| 3222 | nesqp->last_aeq = async_event_id; | ||
| 3223 | spin_unlock_irqrestore(&nesqp->lock, flags); | ||
| 3224 | if (nesqp->ibqp.event_handler) { | ||
| 3225 | ibevent.device = nesqp->ibqp.device; | ||
| 3226 | ibevent.element.qp = &nesqp->ibqp; | ||
| 3227 | ibevent.event = IB_EVENT_QP_ACCESS_ERR; | ||
| 3228 | nesqp->ibqp.event_handler(&ibevent, | ||
| 3229 | nesqp->ibqp.qp_context); | ||
| 3230 | } | ||
| 3231 | nes_cm_disconn(nesqp); | ||
| 3232 | break; | ||
| 3233 | default: | 3541 | default: |
| 3234 | nes_debug(NES_DBG_AEQ, "Processing an iWARP related AE for QP, misc = 0x%04X\n", | 3542 | nes_debug(NES_DBG_AEQ, "Processing an iWARP related AE for QP, misc = 0x%04X\n", |
| 3235 | async_event_id); | 3543 | async_event_id); |
| @@ -3238,7 +3546,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, | |||
| 3238 | 3546 | ||
| 3239 | } | 3547 | } |
| 3240 | 3548 | ||
| 3241 | |||
| 3242 | /** | 3549 | /** |
| 3243 | * nes_iwarp_ce_handler | 3550 | * nes_iwarp_ce_handler |
| 3244 | */ | 3551 | */ |
| @@ -3373,6 +3680,8 @@ void flush_wqes(struct nes_device *nesdev, struct nes_qp *nesqp, | |||
| 3373 | { | 3680 | { |
| 3374 | struct nes_cqp_request *cqp_request; | 3681 | struct nes_cqp_request *cqp_request; |
| 3375 | struct nes_hw_cqp_wqe *cqp_wqe; | 3682 | struct nes_hw_cqp_wqe *cqp_wqe; |
| 3683 | u32 sq_code = (NES_IWARP_CQE_MAJOR_FLUSH << 16) | NES_IWARP_CQE_MINOR_FLUSH; | ||
| 3684 | u32 rq_code = (NES_IWARP_CQE_MAJOR_FLUSH << 16) | NES_IWARP_CQE_MINOR_FLUSH; | ||
| 3376 | int ret; | 3685 | int ret; |
| 3377 | 3686 | ||
| 3378 | cqp_request = nes_get_cqp_request(nesdev); | 3687 | cqp_request = nes_get_cqp_request(nesdev); |
| @@ -3389,6 +3698,24 @@ void flush_wqes(struct nes_device *nesdev, struct nes_qp *nesqp, | |||
| 3389 | cqp_wqe = &cqp_request->cqp_wqe; | 3698 | cqp_wqe = &cqp_request->cqp_wqe; |
| 3390 | nes_fill_init_cqp_wqe(cqp_wqe, nesdev); | 3699 | nes_fill_init_cqp_wqe(cqp_wqe, nesdev); |
| 3391 | 3700 | ||
| 3701 | /* If wqe in error was identified, set code to be put into cqe */ | ||
| 3702 | if ((nesqp->term_sq_flush_code) && (which_wq & NES_CQP_FLUSH_SQ)) { | ||
| 3703 | which_wq |= NES_CQP_FLUSH_MAJ_MIN; | ||
| 3704 | sq_code = (CQE_MAJOR_DRV << 16) | nesqp->term_sq_flush_code; | ||
| 3705 | nesqp->term_sq_flush_code = 0; | ||
| 3706 | } | ||
| 3707 | |||
| 3708 | if ((nesqp->term_rq_flush_code) && (which_wq & NES_CQP_FLUSH_RQ)) { | ||
| 3709 | which_wq |= NES_CQP_FLUSH_MAJ_MIN; | ||
| 3710 | rq_code = (CQE_MAJOR_DRV << 16) | nesqp->term_rq_flush_code; | ||
| 3711 | nesqp->term_rq_flush_code = 0; | ||
| 3712 | } | ||
| 3713 | |||
| 3714 | if (which_wq & NES_CQP_FLUSH_MAJ_MIN) { | ||
| 3715 | cqp_wqe->wqe_words[NES_CQP_QP_WQE_FLUSH_SQ_CODE] = cpu_to_le32(sq_code); | ||
| 3716 | cqp_wqe->wqe_words[NES_CQP_QP_WQE_FLUSH_RQ_CODE] = cpu_to_le32(rq_code); | ||
| 3717 | } | ||
| 3718 | |||
| 3392 | cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = | 3719 | cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = |
| 3393 | cpu_to_le32(NES_CQP_FLUSH_WQES | which_wq); | 3720 | cpu_to_le32(NES_CQP_FLUSH_WQES | which_wq); |
| 3394 | cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesqp->hwqp.qp_id); | 3721 | cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesqp->hwqp.qp_id); |
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index c3654c6383fe..f28a41ba9fa1 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h | |||
| @@ -241,6 +241,7 @@ enum nes_cqp_stag_wqeword_idx { | |||
| 241 | }; | 241 | }; |
| 242 | 242 | ||
| 243 | #define NES_CQP_OP_IWARP_STATE_SHIFT 28 | 243 | #define NES_CQP_OP_IWARP_STATE_SHIFT 28 |
| 244 | #define NES_CQP_OP_TERMLEN_SHIFT 28 | ||
| 244 | 245 | ||
| 245 | enum nes_cqp_qp_bits { | 246 | enum nes_cqp_qp_bits { |
| 246 | NES_CQP_QP_ARP_VALID = (1<<8), | 247 | NES_CQP_QP_ARP_VALID = (1<<8), |
| @@ -265,12 +266,16 @@ enum nes_cqp_qp_bits { | |||
| 265 | NES_CQP_QP_IWARP_STATE_TERMINATE = (5<<NES_CQP_OP_IWARP_STATE_SHIFT), | 266 | NES_CQP_QP_IWARP_STATE_TERMINATE = (5<<NES_CQP_OP_IWARP_STATE_SHIFT), |
| 266 | NES_CQP_QP_IWARP_STATE_ERROR = (6<<NES_CQP_OP_IWARP_STATE_SHIFT), | 267 | NES_CQP_QP_IWARP_STATE_ERROR = (6<<NES_CQP_OP_IWARP_STATE_SHIFT), |
| 267 | NES_CQP_QP_IWARP_STATE_MASK = (7<<NES_CQP_OP_IWARP_STATE_SHIFT), | 268 | NES_CQP_QP_IWARP_STATE_MASK = (7<<NES_CQP_OP_IWARP_STATE_SHIFT), |
| 269 | NES_CQP_QP_TERM_DONT_SEND_FIN = (1<<24), | ||
| 270 | NES_CQP_QP_TERM_DONT_SEND_TERM_MSG = (1<<25), | ||
| 268 | NES_CQP_QP_RESET = (1<<31), | 271 | NES_CQP_QP_RESET = (1<<31), |
| 269 | }; | 272 | }; |
| 270 | 273 | ||
| 271 | enum nes_cqp_qp_wqe_word_idx { | 274 | enum nes_cqp_qp_wqe_word_idx { |
| 272 | NES_CQP_QP_WQE_CONTEXT_LOW_IDX = 6, | 275 | NES_CQP_QP_WQE_CONTEXT_LOW_IDX = 6, |
| 273 | NES_CQP_QP_WQE_CONTEXT_HIGH_IDX = 7, | 276 | NES_CQP_QP_WQE_CONTEXT_HIGH_IDX = 7, |
| 277 | NES_CQP_QP_WQE_FLUSH_SQ_CODE = 8, | ||
| 278 | NES_CQP_QP_WQE_FLUSH_RQ_CODE = 9, | ||
| 274 | NES_CQP_QP_WQE_NEW_MSS_IDX = 15, | 279 | NES_CQP_QP_WQE_NEW_MSS_IDX = 15, |
| 275 | }; | 280 | }; |
| 276 | 281 | ||
| @@ -361,6 +366,7 @@ enum nes_cqp_arp_bits { | |||
| 361 | enum nes_cqp_flush_bits { | 366 | enum nes_cqp_flush_bits { |
| 362 | NES_CQP_FLUSH_SQ = (1<<30), | 367 | NES_CQP_FLUSH_SQ = (1<<30), |
| 363 | NES_CQP_FLUSH_RQ = (1<<31), | 368 | NES_CQP_FLUSH_RQ = (1<<31), |
| 369 | NES_CQP_FLUSH_MAJ_MIN = (1<<28), | ||
| 364 | }; | 370 | }; |
| 365 | 371 | ||
| 366 | enum nes_cqe_opcode_bits { | 372 | enum nes_cqe_opcode_bits { |
| @@ -633,11 +639,14 @@ enum nes_aeqe_bits { | |||
| 633 | NES_AEQE_INBOUND_RDMA = (1<<19), | 639 | NES_AEQE_INBOUND_RDMA = (1<<19), |
| 634 | NES_AEQE_IWARP_STATE_MASK = (7<<20), | 640 | NES_AEQE_IWARP_STATE_MASK = (7<<20), |
| 635 | NES_AEQE_TCP_STATE_MASK = (0xf<<24), | 641 | NES_AEQE_TCP_STATE_MASK = (0xf<<24), |
| 642 | NES_AEQE_Q2_DATA_WRITTEN = (0x3<<28), | ||
| 636 | NES_AEQE_VALID = (1<<31), | 643 | NES_AEQE_VALID = (1<<31), |
| 637 | }; | 644 | }; |
| 638 | 645 | ||
| 639 | #define NES_AEQE_IWARP_STATE_SHIFT 20 | 646 | #define NES_AEQE_IWARP_STATE_SHIFT 20 |
| 640 | #define NES_AEQE_TCP_STATE_SHIFT 24 | 647 | #define NES_AEQE_TCP_STATE_SHIFT 24 |
| 648 | #define NES_AEQE_Q2_DATA_ETHERNET (1<<28) | ||
| 649 | #define NES_AEQE_Q2_DATA_MPA (1<<29) | ||
| 641 | 650 | ||
| 642 | enum nes_aeqe_iwarp_state { | 651 | enum nes_aeqe_iwarp_state { |
| 643 | NES_AEQE_IWARP_STATE_NON_EXISTANT = 0, | 652 | NES_AEQE_IWARP_STATE_NON_EXISTANT = 0, |
| @@ -751,6 +760,15 @@ enum nes_iwarp_sq_wqe_bits { | |||
| 751 | NES_IWARP_SQ_OP_NOP = 12, | 760 | NES_IWARP_SQ_OP_NOP = 12, |
| 752 | }; | 761 | }; |
| 753 | 762 | ||
| 763 | enum nes_iwarp_cqe_major_code { | ||
| 764 | NES_IWARP_CQE_MAJOR_FLUSH = 1, | ||
| 765 | NES_IWARP_CQE_MAJOR_DRV = 0x8000 | ||
| 766 | }; | ||
| 767 | |||
| 768 | enum nes_iwarp_cqe_minor_code { | ||
| 769 | NES_IWARP_CQE_MINOR_FLUSH = 1 | ||
| 770 | }; | ||
| 771 | |||
| 754 | #define NES_EEPROM_READ_REQUEST (1<<16) | 772 | #define NES_EEPROM_READ_REQUEST (1<<16) |
| 755 | #define NES_MAC_ADDR_VALID (1<<20) | 773 | #define NES_MAC_ADDR_VALID (1<<20) |
| 756 | 774 | ||
| @@ -1119,6 +1137,7 @@ struct nes_adapter { | |||
| 1119 | u8 netdev_max; /* from host nic address count in EEPROM */ | 1137 | u8 netdev_max; /* from host nic address count in EEPROM */ |
| 1120 | u8 port_count; | 1138 | u8 port_count; |
| 1121 | u8 virtwq; | 1139 | u8 virtwq; |
| 1140 | u8 send_term_ok; | ||
| 1122 | u8 et_use_adaptive_rx_coalesce; | 1141 | u8 et_use_adaptive_rx_coalesce; |
| 1123 | u8 adapter_fcn_count; | 1142 | u8 adapter_fcn_count; |
| 1124 | u8 pft_mcast_map[NES_PFT_SIZE]; | 1143 | u8 pft_mcast_map[NES_PFT_SIZE]; |
| @@ -1217,6 +1236,90 @@ struct nes_ib_device { | |||
| 1217 | u32 num_pd; | 1236 | u32 num_pd; |
| 1218 | }; | 1237 | }; |
| 1219 | 1238 | ||
| 1239 | enum nes_hdrct_flags { | ||
| 1240 | DDP_LEN_FLAG = 0x80, | ||
| 1241 | DDP_HDR_FLAG = 0x40, | ||
| 1242 | RDMA_HDR_FLAG = 0x20 | ||
| 1243 | }; | ||
| 1244 | |||
| 1245 | enum nes_term_layers { | ||
| 1246 | LAYER_RDMA = 0, | ||
| 1247 | LAYER_DDP = 1, | ||
| 1248 | LAYER_MPA = 2 | ||
| 1249 | }; | ||
| 1250 | |||
| 1251 | enum nes_term_error_types { | ||
| 1252 | RDMAP_CATASTROPHIC = 0, | ||
| 1253 | RDMAP_REMOTE_PROT = 1, | ||
| 1254 | RDMAP_REMOTE_OP = 2, | ||
| 1255 | DDP_CATASTROPHIC = 0, | ||
| 1256 | DDP_TAGGED_BUFFER = 1, | ||
| 1257 | DDP_UNTAGGED_BUFFER = 2, | ||
| 1258 | DDP_LLP = 3 | ||
| 1259 | }; | ||
| 1260 | |||
| 1261 | enum nes_term_rdma_errors { | ||
| 1262 | RDMAP_INV_STAG = 0x00, | ||
| 1263 | RDMAP_INV_BOUNDS = 0x01, | ||
| 1264 | RDMAP_ACCESS = 0x02, | ||
| 1265 | RDMAP_UNASSOC_STAG = 0x03, | ||
| 1266 | RDMAP_TO_WRAP = 0x04, | ||
| 1267 | RDMAP_INV_RDMAP_VER = 0x05, | ||
| 1268 | RDMAP_UNEXPECTED_OP = 0x06, | ||
| 1269 | RDMAP_CATASTROPHIC_LOCAL = 0x07, | ||
| 1270 | RDMAP_CATASTROPHIC_GLOBAL = 0x08, | ||
| 1271 | RDMAP_CANT_INV_STAG = 0x09, | ||
| 1272 | RDMAP_UNSPECIFIED = 0xff | ||
| 1273 | }; | ||
| 1274 | |||
| 1275 | enum nes_term_ddp_errors { | ||
| 1276 | DDP_CATASTROPHIC_LOCAL = 0x00, | ||
| 1277 | DDP_TAGGED_INV_STAG = 0x00, | ||
| 1278 | DDP_TAGGED_BOUNDS = 0x01, | ||
| 1279 | DDP_TAGGED_UNASSOC_STAG = 0x02, | ||
| 1280 | DDP_TAGGED_TO_WRAP = 0x03, | ||
| 1281 | DDP_TAGGED_INV_DDP_VER = 0x04, | ||
| 1282 | DDP_UNTAGGED_INV_QN = 0x01, | ||
| 1283 | DDP_UNTAGGED_INV_MSN_NO_BUF = 0x02, | ||
| 1284 | DDP_UNTAGGED_INV_MSN_RANGE = 0x03, | ||
| 1285 | DDP_UNTAGGED_INV_MO = 0x04, | ||
| 1286 | DDP_UNTAGGED_INV_TOO_LONG = 0x05, | ||
| 1287 | DDP_UNTAGGED_INV_DDP_VER = 0x06 | ||
| 1288 | }; | ||
| 1289 | |||
| 1290 | enum nes_term_mpa_errors { | ||
| 1291 | MPA_CLOSED = 0x01, | ||
| 1292 | MPA_CRC = 0x02, | ||
| 1293 | MPA_MARKER = 0x03, | ||
| 1294 | MPA_REQ_RSP = 0x04, | ||
| 1295 | }; | ||
| 1296 | |||
| 1297 | struct nes_terminate_hdr { | ||
| 1298 | u8 layer_etype; | ||
| 1299 | u8 error_code; | ||
| 1300 | u8 hdrct; | ||
| 1301 | u8 rsvd; | ||
| 1302 | }; | ||
| 1303 | |||
| 1304 | /* Used to determine how to fill in terminate error codes */ | ||
| 1305 | #define IWARP_OPCODE_WRITE 0 | ||
| 1306 | #define IWARP_OPCODE_READREQ 1 | ||
| 1307 | #define IWARP_OPCODE_READRSP 2 | ||
| 1308 | #define IWARP_OPCODE_SEND 3 | ||
| 1309 | #define IWARP_OPCODE_SEND_INV 4 | ||
| 1310 | #define IWARP_OPCODE_SEND_SE 5 | ||
| 1311 | #define IWARP_OPCODE_SEND_SE_INV 6 | ||
| 1312 | #define IWARP_OPCODE_TERM 7 | ||
| 1313 | |||
| 1314 | /* These values are used only during terminate processing */ | ||
| 1315 | #define TERM_DDP_LEN_TAGGED 14 | ||
| 1316 | #define TERM_DDP_LEN_UNTAGGED 18 | ||
| 1317 | #define TERM_RDMA_LEN 28 | ||
| 1318 | #define RDMA_OPCODE_MASK 0x0f | ||
| 1319 | #define RDMA_READ_REQ_OPCODE 1 | ||
| 1320 | #define BAD_FRAME_OFFSET 64 | ||
| 1321 | #define CQE_MAJOR_DRV 0x8000 | ||
| 1322 | |||
| 1220 | #define nes_vlan_rx vlan_hwaccel_receive_skb | 1323 | #define nes_vlan_rx vlan_hwaccel_receive_skb |
| 1221 | #define nes_netif_rx netif_receive_skb | 1324 | #define nes_netif_rx netif_receive_skb |
| 1222 | 1325 | ||
diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c index a282031d15c7..9687c397ce1a 100644 --- a/drivers/infiniband/hw/nes/nes_utils.c +++ b/drivers/infiniband/hw/nes/nes_utils.c | |||
| @@ -183,6 +183,9 @@ int nes_read_eeprom_values(struct nes_device *nesdev, struct nes_adapter *nesada | |||
| 183 | } else if (((major_ver == 2) && (minor_ver > 21)) || ((major_ver > 2) && (major_ver != 255))) { | 183 | } else if (((major_ver == 2) && (minor_ver > 21)) || ((major_ver > 2) && (major_ver != 255))) { |
| 184 | nesadapter->virtwq = 1; | 184 | nesadapter->virtwq = 1; |
| 185 | } | 185 | } |
| 186 | if (((major_ver == 3) && (minor_ver >= 16)) || (major_ver > 3)) | ||
| 187 | nesadapter->send_term_ok = 1; | ||
| 188 | |||
| 186 | nesadapter->firmware_version = (((u32)(u8)(eeprom_data>>8)) << 16) + | 189 | nesadapter->firmware_version = (((u32)(u8)(eeprom_data>>8)) << 16) + |
| 187 | (u32)((u8)eeprom_data); | 190 | (u32)((u8)eeprom_data); |
| 188 | 191 | ||
| @@ -548,7 +551,7 @@ struct nes_cqp_request *nes_get_cqp_request(struct nes_device *nesdev) | |||
| 548 | spin_unlock_irqrestore(&nesdev->cqp.lock, flags); | 551 | spin_unlock_irqrestore(&nesdev->cqp.lock, flags); |
| 549 | } | 552 | } |
| 550 | if (cqp_request == NULL) { | 553 | if (cqp_request == NULL) { |
| 551 | cqp_request = kzalloc(sizeof(struct nes_cqp_request), GFP_KERNEL); | 554 | cqp_request = kzalloc(sizeof(struct nes_cqp_request), GFP_ATOMIC); |
| 552 | if (cqp_request) { | 555 | if (cqp_request) { |
| 553 | cqp_request->dynamic = 1; | 556 | cqp_request->dynamic = 1; |
| 554 | INIT_LIST_HEAD(&cqp_request->list); | 557 | INIT_LIST_HEAD(&cqp_request->list); |
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 21e0fd336cf7..a680c42d6e8c 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c | |||
| @@ -667,15 +667,32 @@ static int nes_query_device(struct ib_device *ibdev, struct ib_device_attr *prop | |||
| 667 | */ | 667 | */ |
| 668 | static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr *props) | 668 | static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr *props) |
| 669 | { | 669 | { |
| 670 | struct nes_vnic *nesvnic = to_nesvnic(ibdev); | ||
| 671 | struct net_device *netdev = nesvnic->netdev; | ||
| 672 | |||
| 670 | memset(props, 0, sizeof(*props)); | 673 | memset(props, 0, sizeof(*props)); |
| 671 | 674 | ||
| 672 | props->max_mtu = IB_MTU_2048; | 675 | props->max_mtu = IB_MTU_4096; |
| 673 | props->active_mtu = IB_MTU_2048; | 676 | |
| 677 | if (netdev->mtu >= 4096) | ||
| 678 | props->active_mtu = IB_MTU_4096; | ||
| 679 | else if (netdev->mtu >= 2048) | ||
| 680 | props->active_mtu = IB_MTU_2048; | ||
| 681 | else if (netdev->mtu >= 1024) | ||
| 682 | props->active_mtu = IB_MTU_1024; | ||
| 683 | else if (netdev->mtu >= 512) | ||
| 684 | props->active_mtu = IB_MTU_512; | ||
| 685 | else | ||
| 686 | props->active_mtu = IB_MTU_256; | ||
| 687 | |||
| 674 | props->lid = 1; | 688 | props->lid = 1; |
| 675 | props->lmc = 0; | 689 | props->lmc = 0; |
| 676 | props->sm_lid = 0; | 690 | props->sm_lid = 0; |
| 677 | props->sm_sl = 0; | 691 | props->sm_sl = 0; |
| 678 | props->state = IB_PORT_ACTIVE; | 692 | if (nesvnic->linkup) |
| 693 | props->state = IB_PORT_ACTIVE; | ||
| 694 | else | ||
| 695 | props->state = IB_PORT_DOWN; | ||
| 679 | props->phys_state = 0; | 696 | props->phys_state = 0; |
| 680 | props->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_REINIT_SUP | | 697 | props->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_REINIT_SUP | |
| 681 | IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP; | 698 | IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP; |
| @@ -1506,12 +1523,45 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, | |||
| 1506 | 1523 | ||
| 1507 | 1524 | ||
| 1508 | /** | 1525 | /** |
| 1526 | * nes_clean_cq | ||
| 1527 | */ | ||
| 1528 | static void nes_clean_cq(struct nes_qp *nesqp, struct nes_cq *nescq) | ||
| 1529 | { | ||
| 1530 | u32 cq_head; | ||
| 1531 | u32 lo; | ||
| 1532 | u32 hi; | ||
| 1533 | u64 u64temp; | ||
| 1534 | unsigned long flags = 0; | ||
| 1535 | |||
| 1536 | spin_lock_irqsave(&nescq->lock, flags); | ||
| 1537 | |||
| 1538 | cq_head = nescq->hw_cq.cq_head; | ||
| 1539 | while (le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) { | ||
| 1540 | rmb(); | ||
| 1541 | lo = le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]); | ||
| 1542 | hi = le32_to_cpu(nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]); | ||
| 1543 | u64temp = (((u64)hi) << 32) | ((u64)lo); | ||
| 1544 | u64temp &= ~(NES_SW_CONTEXT_ALIGN-1); | ||
| 1545 | if (u64temp == (u64)(unsigned long)nesqp) { | ||
| 1546 | /* Zero the context value so cqe will be ignored */ | ||
| 1547 | nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX] = 0; | ||
| 1548 | nescq->hw_cq.cq_vbase[cq_head].cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX] = 0; | ||
| 1549 | } | ||
| 1550 | |||
| 1551 | if (++cq_head >= nescq->hw_cq.cq_size) | ||
| 1552 | cq_head = 0; | ||
| 1553 | } | ||
| 1554 | |||
| 1555 | spin_unlock_irqrestore(&nescq->lock, flags); | ||
| 1556 | } | ||
| 1557 | |||
| 1558 | |||
| 1559 | /** | ||
| 1509 | * nes_destroy_qp | 1560 | * nes_destroy_qp |
| 1510 | */ | 1561 | */ |
| 1511 | static int nes_destroy_qp(struct ib_qp *ibqp) | 1562 | static int nes_destroy_qp(struct ib_qp *ibqp) |
| 1512 | { | 1563 | { |
| 1513 | struct nes_qp *nesqp = to_nesqp(ibqp); | 1564 | struct nes_qp *nesqp = to_nesqp(ibqp); |
| 1514 | /* struct nes_vnic *nesvnic = to_nesvnic(ibqp->device); */ | ||
| 1515 | struct nes_ucontext *nes_ucontext; | 1565 | struct nes_ucontext *nes_ucontext; |
| 1516 | struct ib_qp_attr attr; | 1566 | struct ib_qp_attr attr; |
| 1517 | struct iw_cm_id *cm_id; | 1567 | struct iw_cm_id *cm_id; |
| @@ -1548,7 +1598,6 @@ static int nes_destroy_qp(struct ib_qp *ibqp) | |||
| 1548 | nes_debug(NES_DBG_QP, "OFA CM event_handler returned, ret=%d\n", ret); | 1598 | nes_debug(NES_DBG_QP, "OFA CM event_handler returned, ret=%d\n", ret); |
| 1549 | } | 1599 | } |
| 1550 | 1600 | ||
| 1551 | |||
| 1552 | if (nesqp->user_mode) { | 1601 | if (nesqp->user_mode) { |
| 1553 | if ((ibqp->uobject)&&(ibqp->uobject->context)) { | 1602 | if ((ibqp->uobject)&&(ibqp->uobject->context)) { |
| 1554 | nes_ucontext = to_nesucontext(ibqp->uobject->context); | 1603 | nes_ucontext = to_nesucontext(ibqp->uobject->context); |
| @@ -1560,6 +1609,13 @@ static int nes_destroy_qp(struct ib_qp *ibqp) | |||
| 1560 | } | 1609 | } |
| 1561 | if (nesqp->pbl_pbase) | 1610 | if (nesqp->pbl_pbase) |
| 1562 | kunmap(nesqp->page); | 1611 | kunmap(nesqp->page); |
| 1612 | } else { | ||
| 1613 | /* Clean any pending completions from the cq(s) */ | ||
| 1614 | if (nesqp->nesscq) | ||
| 1615 | nes_clean_cq(nesqp, nesqp->nesscq); | ||
| 1616 | |||
| 1617 | if ((nesqp->nesrcq) && (nesqp->nesrcq != nesqp->nesscq)) | ||
| 1618 | nes_clean_cq(nesqp, nesqp->nesrcq); | ||
| 1563 | } | 1619 | } |
| 1564 | 1620 | ||
| 1565 | nes_rem_ref(&nesqp->ibqp); | 1621 | nes_rem_ref(&nesqp->ibqp); |
| @@ -2884,7 +2940,7 @@ static int nes_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
| 2884 | * nes_hw_modify_qp | 2940 | * nes_hw_modify_qp |
| 2885 | */ | 2941 | */ |
| 2886 | int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp, | 2942 | int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp, |
| 2887 | u32 next_iwarp_state, u32 wait_completion) | 2943 | u32 next_iwarp_state, u32 termlen, u32 wait_completion) |
| 2888 | { | 2944 | { |
| 2889 | struct nes_hw_cqp_wqe *cqp_wqe; | 2945 | struct nes_hw_cqp_wqe *cqp_wqe; |
| 2890 | /* struct iw_cm_id *cm_id = nesqp->cm_id; */ | 2946 | /* struct iw_cm_id *cm_id = nesqp->cm_id; */ |
| @@ -2916,6 +2972,13 @@ int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp, | |||
| 2916 | set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id); | 2972 | set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id); |
| 2917 | set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, (u64)nesqp->nesqp_context_pbase); | 2973 | set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, (u64)nesqp->nesqp_context_pbase); |
| 2918 | 2974 | ||
| 2975 | /* If sending a terminate message, fill in the length (in words) */ | ||
| 2976 | if (((next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK) == NES_CQP_QP_IWARP_STATE_TERMINATE) && | ||
| 2977 | !(next_iwarp_state & NES_CQP_QP_TERM_DONT_SEND_TERM_MSG)) { | ||
| 2978 | termlen = ((termlen + 3) >> 2) << NES_CQP_OP_TERMLEN_SHIFT; | ||
| 2979 | set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_NEW_MSS_IDX, termlen); | ||
| 2980 | } | ||
| 2981 | |||
| 2919 | atomic_set(&cqp_request->refcount, 2); | 2982 | atomic_set(&cqp_request->refcount, 2); |
| 2920 | nes_post_cqp_request(nesdev, cqp_request); | 2983 | nes_post_cqp_request(nesdev, cqp_request); |
| 2921 | 2984 | ||
| @@ -3086,6 +3149,9 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
| 3086 | } | 3149 | } |
| 3087 | nes_debug(NES_DBG_MOD_QP, "QP%u: new state = error\n", | 3150 | nes_debug(NES_DBG_MOD_QP, "QP%u: new state = error\n", |
| 3088 | nesqp->hwqp.qp_id); | 3151 | nesqp->hwqp.qp_id); |
| 3152 | if (nesqp->term_flags) | ||
| 3153 | del_timer(&nesqp->terminate_timer); | ||
| 3154 | |||
| 3089 | next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR; | 3155 | next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR; |
| 3090 | /* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */ | 3156 | /* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */ |
| 3091 | if (nesqp->hte_added) { | 3157 | if (nesqp->hte_added) { |
| @@ -3163,7 +3229,7 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
| 3163 | 3229 | ||
| 3164 | if (issue_modify_qp) { | 3230 | if (issue_modify_qp) { |
| 3165 | nes_debug(NES_DBG_MOD_QP, "call nes_hw_modify_qp\n"); | 3231 | nes_debug(NES_DBG_MOD_QP, "call nes_hw_modify_qp\n"); |
| 3166 | ret = nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 1); | 3232 | ret = nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 1); |
| 3167 | if (ret) | 3233 | if (ret) |
| 3168 | nes_debug(NES_DBG_MOD_QP, "nes_hw_modify_qp (next_iwarp_state = 0x%08X)" | 3234 | nes_debug(NES_DBG_MOD_QP, "nes_hw_modify_qp (next_iwarp_state = 0x%08X)" |
| 3169 | " failed for QP%u.\n", | 3235 | " failed for QP%u.\n", |
| @@ -3328,6 +3394,12 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, | |||
| 3328 | head = nesqp->hwqp.sq_head; | 3394 | head = nesqp->hwqp.sq_head; |
| 3329 | 3395 | ||
| 3330 | while (ib_wr) { | 3396 | while (ib_wr) { |
| 3397 | /* Check for QP error */ | ||
| 3398 | if (nesqp->term_flags) { | ||
| 3399 | err = -EINVAL; | ||
| 3400 | break; | ||
| 3401 | } | ||
| 3402 | |||
| 3331 | /* Check for SQ overflow */ | 3403 | /* Check for SQ overflow */ |
| 3332 | if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) { | 3404 | if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) { |
| 3333 | err = -EINVAL; | 3405 | err = -EINVAL; |
| @@ -3484,6 +3556,12 @@ static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, | |||
| 3484 | head = nesqp->hwqp.rq_head; | 3556 | head = nesqp->hwqp.rq_head; |
| 3485 | 3557 | ||
| 3486 | while (ib_wr) { | 3558 | while (ib_wr) { |
| 3559 | /* Check for QP error */ | ||
| 3560 | if (nesqp->term_flags) { | ||
| 3561 | err = -EINVAL; | ||
| 3562 | break; | ||
| 3563 | } | ||
| 3564 | |||
| 3487 | if (ib_wr->num_sge > nesdev->nesadapter->max_sge) { | 3565 | if (ib_wr->num_sge > nesdev->nesadapter->max_sge) { |
| 3488 | err = -EINVAL; | 3566 | err = -EINVAL; |
| 3489 | break; | 3567 | break; |
| @@ -3547,7 +3625,6 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) | |||
| 3547 | { | 3625 | { |
| 3548 | u64 u64temp; | 3626 | u64 u64temp; |
| 3549 | u64 wrid; | 3627 | u64 wrid; |
| 3550 | /* u64 u64temp; */ | ||
| 3551 | unsigned long flags = 0; | 3628 | unsigned long flags = 0; |
| 3552 | struct nes_vnic *nesvnic = to_nesvnic(ibcq->device); | 3629 | struct nes_vnic *nesvnic = to_nesvnic(ibcq->device); |
| 3553 | struct nes_device *nesdev = nesvnic->nesdev; | 3630 | struct nes_device *nesdev = nesvnic->nesdev; |
| @@ -3555,12 +3632,13 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) | |||
| 3555 | struct nes_qp *nesqp; | 3632 | struct nes_qp *nesqp; |
| 3556 | struct nes_hw_cqe cqe; | 3633 | struct nes_hw_cqe cqe; |
| 3557 | u32 head; | 3634 | u32 head; |
| 3558 | u32 wq_tail; | 3635 | u32 wq_tail = 0; |
| 3559 | u32 cq_size; | 3636 | u32 cq_size; |
| 3560 | u32 cqe_count = 0; | 3637 | u32 cqe_count = 0; |
| 3561 | u32 wqe_index; | 3638 | u32 wqe_index; |
| 3562 | u32 u32temp; | 3639 | u32 u32temp; |
| 3563 | /* u32 counter; */ | 3640 | u32 move_cq_head = 1; |
| 3641 | u32 err_code; | ||
| 3564 | 3642 | ||
| 3565 | nes_debug(NES_DBG_CQ, "\n"); | 3643 | nes_debug(NES_DBG_CQ, "\n"); |
| 3566 | 3644 | ||
| @@ -3570,29 +3648,40 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) | |||
| 3570 | cq_size = nescq->hw_cq.cq_size; | 3648 | cq_size = nescq->hw_cq.cq_size; |
| 3571 | 3649 | ||
| 3572 | while (cqe_count < num_entries) { | 3650 | while (cqe_count < num_entries) { |
| 3573 | if (le32_to_cpu(nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & | 3651 | if ((le32_to_cpu(nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & |
| 3574 | NES_CQE_VALID) { | 3652 | NES_CQE_VALID) == 0) |
| 3575 | /* | 3653 | break; |
| 3576 | * Make sure we read CQ entry contents *after* | 3654 | |
| 3577 | * we've checked the valid bit. | 3655 | /* |
| 3578 | */ | 3656 | * Make sure we read CQ entry contents *after* |
| 3579 | rmb(); | 3657 | * we've checked the valid bit. |
| 3580 | 3658 | */ | |
| 3581 | cqe = nescq->hw_cq.cq_vbase[head]; | 3659 | rmb(); |
| 3582 | nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0; | 3660 | |
| 3583 | u32temp = le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]); | 3661 | cqe = nescq->hw_cq.cq_vbase[head]; |
| 3584 | wqe_index = u32temp & | 3662 | u32temp = le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]); |
| 3585 | (nesdev->nesadapter->max_qp_wr - 1); | 3663 | wqe_index = u32temp & (nesdev->nesadapter->max_qp_wr - 1); |
| 3586 | u32temp &= ~(NES_SW_CONTEXT_ALIGN-1); | 3664 | u32temp &= ~(NES_SW_CONTEXT_ALIGN-1); |
| 3587 | /* parse CQE, get completion context from WQE (either rq or sq */ | 3665 | /* parse CQE, get completion context from WQE (either rq or sq) */ |
| 3588 | u64temp = (((u64)(le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX])))<<32) | | 3666 | u64temp = (((u64)(le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX])))<<32) | |
| 3589 | ((u64)u32temp); | 3667 | ((u64)u32temp); |
| 3590 | nesqp = *((struct nes_qp **)&u64temp); | 3668 | |
| 3669 | if (u64temp) { | ||
| 3670 | nesqp = (struct nes_qp *)(unsigned long)u64temp; | ||
| 3591 | memset(entry, 0, sizeof *entry); | 3671 | memset(entry, 0, sizeof *entry); |
| 3592 | if (cqe.cqe_words[NES_CQE_ERROR_CODE_IDX] == 0) { | 3672 | if (cqe.cqe_words[NES_CQE_ERROR_CODE_IDX] == 0) { |
| 3593 | entry->status = IB_WC_SUCCESS; | 3673 | entry->status = IB_WC_SUCCESS; |
| 3594 | } else { | 3674 | } else { |
| 3595 | entry->status = IB_WC_WR_FLUSH_ERR; | 3675 | err_code = le32_to_cpu(cqe.cqe_words[NES_CQE_ERROR_CODE_IDX]); |
| 3676 | if (NES_IWARP_CQE_MAJOR_DRV == (err_code >> 16)) { | ||
| 3677 | entry->status = err_code & 0x0000ffff; | ||
| 3678 | |||
| 3679 | /* The rest of the cqe's will be marked as flushed */ | ||
| 3680 | nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX] = | ||
| 3681 | cpu_to_le32((NES_IWARP_CQE_MAJOR_FLUSH << 16) | | ||
| 3682 | NES_IWARP_CQE_MINOR_FLUSH); | ||
| 3683 | } else | ||
| 3684 | entry->status = IB_WC_WR_FLUSH_ERR; | ||
| 3596 | } | 3685 | } |
| 3597 | 3686 | ||
| 3598 | entry->qp = &nesqp->ibqp; | 3687 | entry->qp = &nesqp->ibqp; |
| @@ -3601,20 +3690,18 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) | |||
| 3601 | if (le32_to_cpu(cqe.cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_SQ) { | 3690 | if (le32_to_cpu(cqe.cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_SQ) { |
| 3602 | if (nesqp->skip_lsmm) { | 3691 | if (nesqp->skip_lsmm) { |
| 3603 | nesqp->skip_lsmm = 0; | 3692 | nesqp->skip_lsmm = 0; |
| 3604 | wq_tail = nesqp->hwqp.sq_tail++; | 3693 | nesqp->hwqp.sq_tail++; |
| 3605 | } | 3694 | } |
| 3606 | 3695 | ||
| 3607 | /* Working on a SQ Completion*/ | 3696 | /* Working on a SQ Completion*/ |
| 3608 | wq_tail = wqe_index; | 3697 | wrid = (((u64)(cpu_to_le32((u32)nesqp->hwqp.sq_vbase[wqe_index]. |
| 3609 | nesqp->hwqp.sq_tail = (wqe_index+1)&(nesqp->hwqp.sq_size - 1); | ||
| 3610 | wrid = (((u64)(cpu_to_le32((u32)nesqp->hwqp.sq_vbase[wq_tail]. | ||
| 3611 | wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) | | 3698 | wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) | |
| 3612 | ((u64)(cpu_to_le32((u32)nesqp->hwqp.sq_vbase[wq_tail]. | 3699 | ((u64)(cpu_to_le32((u32)nesqp->hwqp.sq_vbase[wqe_index]. |
| 3613 | wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX]))); | 3700 | wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX]))); |
| 3614 | entry->byte_len = le32_to_cpu(nesqp->hwqp.sq_vbase[wq_tail]. | 3701 | entry->byte_len = le32_to_cpu(nesqp->hwqp.sq_vbase[wqe_index]. |
| 3615 | wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX]); | 3702 | wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX]); |
| 3616 | 3703 | ||
| 3617 | switch (le32_to_cpu(nesqp->hwqp.sq_vbase[wq_tail]. | 3704 | switch (le32_to_cpu(nesqp->hwqp.sq_vbase[wqe_index]. |
| 3618 | wqe_words[NES_IWARP_SQ_WQE_MISC_IDX]) & 0x3f) { | 3705 | wqe_words[NES_IWARP_SQ_WQE_MISC_IDX]) & 0x3f) { |
| 3619 | case NES_IWARP_SQ_OP_RDMAW: | 3706 | case NES_IWARP_SQ_OP_RDMAW: |
| 3620 | nes_debug(NES_DBG_CQ, "Operation = RDMA WRITE.\n"); | 3707 | nes_debug(NES_DBG_CQ, "Operation = RDMA WRITE.\n"); |
| @@ -3623,7 +3710,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) | |||
| 3623 | case NES_IWARP_SQ_OP_RDMAR: | 3710 | case NES_IWARP_SQ_OP_RDMAR: |
| 3624 | nes_debug(NES_DBG_CQ, "Operation = RDMA READ.\n"); | 3711 | nes_debug(NES_DBG_CQ, "Operation = RDMA READ.\n"); |
| 3625 | entry->opcode = IB_WC_RDMA_READ; | 3712 | entry->opcode = IB_WC_RDMA_READ; |
| 3626 | entry->byte_len = le32_to_cpu(nesqp->hwqp.sq_vbase[wq_tail]. | 3713 | entry->byte_len = le32_to_cpu(nesqp->hwqp.sq_vbase[wqe_index]. |
| 3627 | wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX]); | 3714 | wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX]); |
| 3628 | break; | 3715 | break; |
| 3629 | case NES_IWARP_SQ_OP_SENDINV: | 3716 | case NES_IWARP_SQ_OP_SENDINV: |
| @@ -3634,33 +3721,54 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) | |||
| 3634 | entry->opcode = IB_WC_SEND; | 3721 | entry->opcode = IB_WC_SEND; |
| 3635 | break; | 3722 | break; |
| 3636 | } | 3723 | } |
| 3724 | |||
| 3725 | nesqp->hwqp.sq_tail = (wqe_index+1)&(nesqp->hwqp.sq_size - 1); | ||
| 3726 | if ((entry->status != IB_WC_SUCCESS) && (nesqp->hwqp.sq_tail != nesqp->hwqp.sq_head)) { | ||
| 3727 | move_cq_head = 0; | ||
| 3728 | wq_tail = nesqp->hwqp.sq_tail; | ||
| 3729 | } | ||
| 3637 | } else { | 3730 | } else { |
| 3638 | /* Working on a RQ Completion*/ | 3731 | /* Working on a RQ Completion*/ |
| 3639 | wq_tail = wqe_index; | ||
| 3640 | nesqp->hwqp.rq_tail = (wqe_index+1)&(nesqp->hwqp.rq_size - 1); | ||
| 3641 | entry->byte_len = le32_to_cpu(cqe.cqe_words[NES_CQE_PAYLOAD_LENGTH_IDX]); | 3732 | entry->byte_len = le32_to_cpu(cqe.cqe_words[NES_CQE_PAYLOAD_LENGTH_IDX]); |
| 3642 | wrid = ((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wq_tail].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_LOW_IDX]))) | | 3733 | wrid = ((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wqe_index].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_LOW_IDX]))) | |
| 3643 | ((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wq_tail].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_HIGH_IDX]))<<32); | 3734 | ((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wqe_index].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_HIGH_IDX]))<<32); |
| 3644 | entry->opcode = IB_WC_RECV; | 3735 | entry->opcode = IB_WC_RECV; |
| 3736 | |||
| 3737 | nesqp->hwqp.rq_tail = (wqe_index+1)&(nesqp->hwqp.rq_size - 1); | ||
| 3738 | if ((entry->status != IB_WC_SUCCESS) && (nesqp->hwqp.rq_tail != nesqp->hwqp.rq_head)) { | ||
| 3739 | move_cq_head = 0; | ||
| 3740 | wq_tail = nesqp->hwqp.rq_tail; | ||
| 3741 | } | ||
| 3645 | } | 3742 | } |
| 3743 | |||
| 3646 | entry->wr_id = wrid; | 3744 | entry->wr_id = wrid; |
| 3745 | entry++; | ||
| 3746 | cqe_count++; | ||
| 3747 | } | ||
| 3647 | 3748 | ||
| 3749 | if (move_cq_head) { | ||
| 3750 | nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0; | ||
| 3648 | if (++head >= cq_size) | 3751 | if (++head >= cq_size) |
| 3649 | head = 0; | 3752 | head = 0; |
| 3650 | cqe_count++; | ||
| 3651 | nescq->polled_completions++; | 3753 | nescq->polled_completions++; |
| 3754 | |||
| 3652 | if ((nescq->polled_completions > (cq_size / 2)) || | 3755 | if ((nescq->polled_completions > (cq_size / 2)) || |
| 3653 | (nescq->polled_completions == 255)) { | 3756 | (nescq->polled_completions == 255)) { |
| 3654 | nes_debug(NES_DBG_CQ, "CQ%u Issuing CQE Allocate since more than half of cqes" | 3757 | nes_debug(NES_DBG_CQ, "CQ%u Issuing CQE Allocate since more than half of cqes" |
| 3655 | " are pending %u of %u.\n", | 3758 | " are pending %u of %u.\n", |
| 3656 | nescq->hw_cq.cq_number, nescq->polled_completions, cq_size); | 3759 | nescq->hw_cq.cq_number, nescq->polled_completions, cq_size); |
| 3657 | nes_write32(nesdev->regs+NES_CQE_ALLOC, | 3760 | nes_write32(nesdev->regs+NES_CQE_ALLOC, |
| 3658 | nescq->hw_cq.cq_number | (nescq->polled_completions << 16)); | 3761 | nescq->hw_cq.cq_number | (nescq->polled_completions << 16)); |
| 3659 | nescq->polled_completions = 0; | 3762 | nescq->polled_completions = 0; |
| 3660 | } | 3763 | } |
| 3661 | entry++; | 3764 | } else { |
| 3662 | } else | 3765 | /* Update the wqe index and set status to flush */ |
| 3663 | break; | 3766 | wqe_index = le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]); |
| 3767 | wqe_index = (wqe_index & (~(nesdev->nesadapter->max_qp_wr - 1))) | wq_tail; | ||
| 3768 | nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX] = | ||
| 3769 | cpu_to_le32(wqe_index); | ||
| 3770 | move_cq_head = 1; /* ready for next pass */ | ||
| 3771 | } | ||
| 3664 | } | 3772 | } |
| 3665 | 3773 | ||
| 3666 | if (nescq->polled_completions) { | 3774 | if (nescq->polled_completions) { |
diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h index 41c07f29f7c9..89822d75f82e 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.h +++ b/drivers/infiniband/hw/nes/nes_verbs.h | |||
| @@ -40,6 +40,10 @@ struct nes_device; | |||
| 40 | #define NES_MAX_USER_DB_REGIONS 4096 | 40 | #define NES_MAX_USER_DB_REGIONS 4096 |
| 41 | #define NES_MAX_USER_WQ_REGIONS 4096 | 41 | #define NES_MAX_USER_WQ_REGIONS 4096 |
| 42 | 42 | ||
| 43 | #define NES_TERM_SENT 0x01 | ||
| 44 | #define NES_TERM_RCVD 0x02 | ||
| 45 | #define NES_TERM_DONE 0x04 | ||
| 46 | |||
| 43 | struct nes_ucontext { | 47 | struct nes_ucontext { |
| 44 | struct ib_ucontext ibucontext; | 48 | struct ib_ucontext ibucontext; |
| 45 | struct nes_device *nesdev; | 49 | struct nes_device *nesdev; |
| @@ -119,6 +123,11 @@ struct nes_wq { | |||
| 119 | spinlock_t lock; | 123 | spinlock_t lock; |
| 120 | }; | 124 | }; |
| 121 | 125 | ||
| 126 | struct disconn_work { | ||
| 127 | struct work_struct work; | ||
| 128 | struct nes_qp *nesqp; | ||
| 129 | }; | ||
| 130 | |||
| 122 | struct iw_cm_id; | 131 | struct iw_cm_id; |
| 123 | struct ietf_mpa_frame; | 132 | struct ietf_mpa_frame; |
| 124 | 133 | ||
| @@ -127,7 +136,6 @@ struct nes_qp { | |||
| 127 | void *allocated_buffer; | 136 | void *allocated_buffer; |
| 128 | struct iw_cm_id *cm_id; | 137 | struct iw_cm_id *cm_id; |
| 129 | struct workqueue_struct *wq; | 138 | struct workqueue_struct *wq; |
| 130 | struct work_struct disconn_work; | ||
| 131 | struct nes_cq *nesscq; | 139 | struct nes_cq *nesscq; |
| 132 | struct nes_cq *nesrcq; | 140 | struct nes_cq *nesrcq; |
| 133 | struct nes_pd *nespd; | 141 | struct nes_pd *nespd; |
| @@ -155,9 +163,13 @@ struct nes_qp { | |||
| 155 | void *pbl_vbase; | 163 | void *pbl_vbase; |
| 156 | dma_addr_t pbl_pbase; | 164 | dma_addr_t pbl_pbase; |
| 157 | struct page *page; | 165 | struct page *page; |
| 166 | struct timer_list terminate_timer; | ||
| 167 | enum ib_event_type terminate_eventtype; | ||
| 158 | wait_queue_head_t kick_waitq; | 168 | wait_queue_head_t kick_waitq; |
| 159 | u16 in_disconnect; | 169 | u16 in_disconnect; |
| 160 | u16 private_data_len; | 170 | u16 private_data_len; |
| 171 | u16 term_sq_flush_code; | ||
| 172 | u16 term_rq_flush_code; | ||
| 161 | u8 active_conn; | 173 | u8 active_conn; |
| 162 | u8 skip_lsmm; | 174 | u8 skip_lsmm; |
| 163 | u8 user_mode; | 175 | u8 user_mode; |
| @@ -165,7 +177,7 @@ struct nes_qp { | |||
| 165 | u8 hw_iwarp_state; | 177 | u8 hw_iwarp_state; |
| 166 | u8 flush_issued; | 178 | u8 flush_issued; |
| 167 | u8 hw_tcp_state; | 179 | u8 hw_tcp_state; |
| 168 | u8 disconn_pending; | 180 | u8 term_flags; |
| 169 | u8 destroyed; | 181 | u8 destroyed; |
| 170 | }; | 182 | }; |
| 171 | #endif /* NES_VERBS_H */ | 183 | #endif /* NES_VERBS_H */ |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 181b1f32325f..8f4b4fca2a1d 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | */ | 31 | */ |
| 32 | 32 | ||
| 33 | #include <rdma/ib_cm.h> | 33 | #include <rdma/ib_cm.h> |
| 34 | #include <rdma/ib_cache.h> | ||
| 35 | #include <net/dst.h> | 34 | #include <net/dst.h> |
| 36 | #include <net/icmp.h> | 35 | #include <net/icmp.h> |
| 37 | #include <linux/icmpv6.h> | 36 | #include <linux/icmpv6.h> |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index e7e5adf84e84..e35f4a0ea9d5 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
| @@ -36,7 +36,6 @@ | |||
| 36 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
| 37 | #include <linux/dma-mapping.h> | 37 | #include <linux/dma-mapping.h> |
| 38 | 38 | ||
| 39 | #include <rdma/ib_cache.h> | ||
| 40 | #include <linux/ip.h> | 39 | #include <linux/ip.h> |
| 41 | #include <linux/tcp.h> | 40 | #include <linux/tcp.h> |
| 42 | 41 | ||
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index e319d91f60a6..2bf5116deec4 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
| @@ -604,8 +604,11 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) | |||
| 604 | skb_queue_len(&neigh->queue)); | 604 | skb_queue_len(&neigh->queue)); |
| 605 | goto err_drop; | 605 | goto err_drop; |
| 606 | } | 606 | } |
| 607 | } else | 607 | } else { |
| 608 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 608 | ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha)); | 609 | ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha)); |
| 610 | return; | ||
| 611 | } | ||
| 609 | } else { | 612 | } else { |
| 610 | neigh->ah = NULL; | 613 | neigh->ah = NULL; |
| 611 | 614 | ||
| @@ -688,7 +691,9 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, | |||
| 688 | ipoib_dbg(priv, "Send unicast ARP to %04x\n", | 691 | ipoib_dbg(priv, "Send unicast ARP to %04x\n", |
| 689 | be16_to_cpu(path->pathrec.dlid)); | 692 | be16_to_cpu(path->pathrec.dlid)); |
| 690 | 693 | ||
| 694 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 691 | ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr)); | 695 | ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr)); |
| 696 | return; | ||
| 692 | } else if ((path->query || !path_rec_start(dev, path)) && | 697 | } else if ((path->query || !path_rec_start(dev, path)) && |
| 693 | skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { | 698 | skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { |
| 694 | /* put pseudoheader back on for next time */ | 699 | /* put pseudoheader back on for next time */ |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index a0e97532e714..25874fc680c9 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
| @@ -720,7 +720,9 @@ out: | |||
| 720 | } | 720 | } |
| 721 | } | 721 | } |
| 722 | 722 | ||
| 723 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 723 | ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN); | 724 | ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN); |
| 725 | return; | ||
| 724 | } | 726 | } |
| 725 | 727 | ||
| 726 | unlock: | 728 | unlock: |
| @@ -758,6 +760,20 @@ void ipoib_mcast_dev_flush(struct net_device *dev) | |||
| 758 | } | 760 | } |
| 759 | } | 761 | } |
| 760 | 762 | ||
| 763 | static int ipoib_mcast_addr_is_valid(const u8 *addr, unsigned int addrlen, | ||
| 764 | const u8 *broadcast) | ||
| 765 | { | ||
| 766 | if (addrlen != INFINIBAND_ALEN) | ||
| 767 | return 0; | ||
| 768 | /* reserved QPN, prefix, scope */ | ||
| 769 | if (memcmp(addr, broadcast, 6)) | ||
| 770 | return 0; | ||
| 771 | /* signature lower, pkey */ | ||
| 772 | if (memcmp(addr + 7, broadcast + 7, 3)) | ||
| 773 | return 0; | ||
| 774 | return 1; | ||
| 775 | } | ||
| 776 | |||
| 761 | void ipoib_mcast_restart_task(struct work_struct *work) | 777 | void ipoib_mcast_restart_task(struct work_struct *work) |
| 762 | { | 778 | { |
| 763 | struct ipoib_dev_priv *priv = | 779 | struct ipoib_dev_priv *priv = |
| @@ -791,6 +807,11 @@ void ipoib_mcast_restart_task(struct work_struct *work) | |||
| 791 | for (mclist = dev->mc_list; mclist; mclist = mclist->next) { | 807 | for (mclist = dev->mc_list; mclist; mclist = mclist->next) { |
| 792 | union ib_gid mgid; | 808 | union ib_gid mgid; |
| 793 | 809 | ||
| 810 | if (!ipoib_mcast_addr_is_valid(mclist->dmi_addr, | ||
| 811 | mclist->dmi_addrlen, | ||
| 812 | dev->broadcast)) | ||
| 813 | continue; | ||
| 814 | |||
| 794 | memcpy(mgid.raw, mclist->dmi_addr + 4, sizeof mgid); | 815 | memcpy(mgid.raw, mclist->dmi_addr + 4, sizeof mgid); |
| 795 | 816 | ||
| 796 | mcast = __ipoib_mcast_find(dev, &mgid); | 817 | mcast = __ipoib_mcast_find(dev, &mgid); |
diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c index ac57b6a42c6e..ccfe276943f0 100644 --- a/drivers/net/mlx4/cq.c +++ b/drivers/net/mlx4/cq.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | * SOFTWARE. | 34 | * SOFTWARE. |
| 35 | */ | 35 | */ |
| 36 | 36 | ||
| 37 | #include <linux/init.h> | ||
| 38 | #include <linux/hardirq.h> | 37 | #include <linux/hardirq.h> |
| 39 | 38 | ||
| 40 | #include <linux/mlx4/cmd.h> | 39 | #include <linux/mlx4/cmd.h> |
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c index b9ceddde46c0..bffb7995cb70 100644 --- a/drivers/net/mlx4/eq.c +++ b/drivers/net/mlx4/eq.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | * SOFTWARE. | 31 | * SOFTWARE. |
| 32 | */ | 32 | */ |
| 33 | 33 | ||
| 34 | #include <linux/init.h> | ||
| 35 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
| 36 | #include <linux/mm.h> | 35 | #include <linux/mm.h> |
| 37 | #include <linux/dma-mapping.h> | 36 | #include <linux/dma-mapping.h> |
| @@ -42,6 +41,10 @@ | |||
| 42 | #include "fw.h" | 41 | #include "fw.h" |
| 43 | 42 | ||
| 44 | enum { | 43 | enum { |
| 44 | MLX4_IRQNAME_SIZE = 64 | ||
| 45 | }; | ||
| 46 | |||
| 47 | enum { | ||
| 45 | MLX4_NUM_ASYNC_EQE = 0x100, | 48 | MLX4_NUM_ASYNC_EQE = 0x100, |
| 46 | MLX4_NUM_SPARE_EQE = 0x80, | 49 | MLX4_NUM_SPARE_EQE = 0x80, |
| 47 | MLX4_EQ_ENTRY_SIZE = 0x20 | 50 | MLX4_EQ_ENTRY_SIZE = 0x20 |
| @@ -526,48 +529,6 @@ static void mlx4_unmap_clr_int(struct mlx4_dev *dev) | |||
| 526 | iounmap(priv->clr_base); | 529 | iounmap(priv->clr_base); |
| 527 | } | 530 | } |
| 528 | 531 | ||
| 529 | int mlx4_map_eq_icm(struct mlx4_dev *dev, u64 icm_virt) | ||
| 530 | { | ||
| 531 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
| 532 | int ret; | ||
| 533 | |||
| 534 | /* | ||
| 535 | * We assume that mapping one page is enough for the whole EQ | ||
| 536 | * context table. This is fine with all current HCAs, because | ||
| 537 | * we only use 32 EQs and each EQ uses 64 bytes of context | ||
| 538 | * memory, or 1 KB total. | ||
| 539 | */ | ||
| 540 | priv->eq_table.icm_virt = icm_virt; | ||
| 541 | priv->eq_table.icm_page = alloc_page(GFP_HIGHUSER); | ||
| 542 | if (!priv->eq_table.icm_page) | ||
| 543 | return -ENOMEM; | ||
| 544 | priv->eq_table.icm_dma = pci_map_page(dev->pdev, priv->eq_table.icm_page, 0, | ||
| 545 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
| 546 | if (pci_dma_mapping_error(dev->pdev, priv->eq_table.icm_dma)) { | ||
| 547 | __free_page(priv->eq_table.icm_page); | ||
| 548 | return -ENOMEM; | ||
| 549 | } | ||
| 550 | |||
| 551 | ret = mlx4_MAP_ICM_page(dev, priv->eq_table.icm_dma, icm_virt); | ||
| 552 | if (ret) { | ||
| 553 | pci_unmap_page(dev->pdev, priv->eq_table.icm_dma, PAGE_SIZE, | ||
| 554 | PCI_DMA_BIDIRECTIONAL); | ||
| 555 | __free_page(priv->eq_table.icm_page); | ||
| 556 | } | ||
| 557 | |||
| 558 | return ret; | ||
| 559 | } | ||
| 560 | |||
| 561 | void mlx4_unmap_eq_icm(struct mlx4_dev *dev) | ||
| 562 | { | ||
| 563 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
| 564 | |||
| 565 | mlx4_UNMAP_ICM(dev, priv->eq_table.icm_virt, 1); | ||
| 566 | pci_unmap_page(dev->pdev, priv->eq_table.icm_dma, PAGE_SIZE, | ||
| 567 | PCI_DMA_BIDIRECTIONAL); | ||
| 568 | __free_page(priv->eq_table.icm_page); | ||
| 569 | } | ||
| 570 | |||
| 571 | int mlx4_alloc_eq_table(struct mlx4_dev *dev) | 532 | int mlx4_alloc_eq_table(struct mlx4_dev *dev) |
| 572 | { | 533 | { |
| 573 | struct mlx4_priv *priv = mlx4_priv(dev); | 534 | struct mlx4_priv *priv = mlx4_priv(dev); |
| @@ -615,7 +576,9 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) | |||
| 615 | priv->eq_table.clr_int = priv->clr_base + | 576 | priv->eq_table.clr_int = priv->clr_base + |
| 616 | (priv->eq_table.inta_pin < 32 ? 4 : 0); | 577 | (priv->eq_table.inta_pin < 32 ? 4 : 0); |
| 617 | 578 | ||
| 618 | priv->eq_table.irq_names = kmalloc(16 * dev->caps.num_comp_vectors, GFP_KERNEL); | 579 | priv->eq_table.irq_names = |
| 580 | kmalloc(MLX4_IRQNAME_SIZE * (dev->caps.num_comp_vectors + 1), | ||
| 581 | GFP_KERNEL); | ||
| 619 | if (!priv->eq_table.irq_names) { | 582 | if (!priv->eq_table.irq_names) { |
| 620 | err = -ENOMEM; | 583 | err = -ENOMEM; |
| 621 | goto err_out_bitmap; | 584 | goto err_out_bitmap; |
| @@ -638,17 +601,25 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) | |||
| 638 | goto err_out_comp; | 601 | goto err_out_comp; |
| 639 | 602 | ||
| 640 | if (dev->flags & MLX4_FLAG_MSI_X) { | 603 | if (dev->flags & MLX4_FLAG_MSI_X) { |
| 641 | static const char async_eq_name[] = "mlx4-async"; | ||
| 642 | const char *eq_name; | 604 | const char *eq_name; |
| 643 | 605 | ||
| 644 | for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i) { | 606 | for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i) { |
| 645 | if (i < dev->caps.num_comp_vectors) { | 607 | if (i < dev->caps.num_comp_vectors) { |
| 646 | snprintf(priv->eq_table.irq_names + i * 16, 16, | 608 | snprintf(priv->eq_table.irq_names + |
| 647 | "mlx4-comp-%d", i); | 609 | i * MLX4_IRQNAME_SIZE, |
| 648 | eq_name = priv->eq_table.irq_names + i * 16; | 610 | MLX4_IRQNAME_SIZE, |
| 649 | } else | 611 | "mlx4-comp-%d@pci:%s", i, |
| 650 | eq_name = async_eq_name; | 612 | pci_name(dev->pdev)); |
| 613 | } else { | ||
| 614 | snprintf(priv->eq_table.irq_names + | ||
| 615 | i * MLX4_IRQNAME_SIZE, | ||
| 616 | MLX4_IRQNAME_SIZE, | ||
| 617 | "mlx4-async@pci:%s", | ||
| 618 | pci_name(dev->pdev)); | ||
| 619 | } | ||
| 651 | 620 | ||
| 621 | eq_name = priv->eq_table.irq_names + | ||
| 622 | i * MLX4_IRQNAME_SIZE; | ||
| 652 | err = request_irq(priv->eq_table.eq[i].irq, | 623 | err = request_irq(priv->eq_table.eq[i].irq, |
| 653 | mlx4_msi_x_interrupt, 0, eq_name, | 624 | mlx4_msi_x_interrupt, 0, eq_name, |
| 654 | priv->eq_table.eq + i); | 625 | priv->eq_table.eq + i); |
| @@ -658,8 +629,12 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) | |||
| 658 | priv->eq_table.eq[i].have_irq = 1; | 629 | priv->eq_table.eq[i].have_irq = 1; |
| 659 | } | 630 | } |
| 660 | } else { | 631 | } else { |
| 632 | snprintf(priv->eq_table.irq_names, | ||
| 633 | MLX4_IRQNAME_SIZE, | ||
| 634 | DRV_NAME "@pci:%s", | ||
| 635 | pci_name(dev->pdev)); | ||
| 661 | err = request_irq(dev->pdev->irq, mlx4_interrupt, | 636 | err = request_irq(dev->pdev->irq, mlx4_interrupt, |
| 662 | IRQF_SHARED, DRV_NAME, dev); | 637 | IRQF_SHARED, priv->eq_table.irq_names, dev); |
| 663 | if (err) | 638 | if (err) |
| 664 | goto err_out_async; | 639 | goto err_out_async; |
| 665 | 640 | ||
diff --git a/drivers/net/mlx4/icm.c b/drivers/net/mlx4/icm.c index baf4bf66062c..04b382fcb8c8 100644 --- a/drivers/net/mlx4/icm.c +++ b/drivers/net/mlx4/icm.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | * SOFTWARE. | 31 | * SOFTWARE. |
| 32 | */ | 32 | */ |
| 33 | 33 | ||
| 34 | #include <linux/init.h> | ||
| 35 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
| 36 | #include <linux/mm.h> | 35 | #include <linux/mm.h> |
| 37 | #include <linux/scatterlist.h> | 36 | #include <linux/scatterlist.h> |
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index dac621b1e9fc..3dd481e77f92 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c | |||
| @@ -525,7 +525,10 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, | |||
| 525 | goto err_unmap_aux; | 525 | goto err_unmap_aux; |
| 526 | } | 526 | } |
| 527 | 527 | ||
| 528 | err = mlx4_map_eq_icm(dev, init_hca->eqc_base); | 528 | err = mlx4_init_icm_table(dev, &priv->eq_table.table, |
| 529 | init_hca->eqc_base, dev_cap->eqc_entry_sz, | ||
| 530 | dev->caps.num_eqs, dev->caps.num_eqs, | ||
| 531 | 0, 0); | ||
| 529 | if (err) { | 532 | if (err) { |
| 530 | mlx4_err(dev, "Failed to map EQ context memory, aborting.\n"); | 533 | mlx4_err(dev, "Failed to map EQ context memory, aborting.\n"); |
| 531 | goto err_unmap_cmpt; | 534 | goto err_unmap_cmpt; |
| @@ -668,7 +671,7 @@ err_unmap_mtt: | |||
| 668 | mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table); | 671 | mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table); |
| 669 | 672 | ||
| 670 | err_unmap_eq: | 673 | err_unmap_eq: |
| 671 | mlx4_unmap_eq_icm(dev); | 674 | mlx4_cleanup_icm_table(dev, &priv->eq_table.table); |
| 672 | 675 | ||
| 673 | err_unmap_cmpt: | 676 | err_unmap_cmpt: |
| 674 | mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table); | 677 | mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table); |
| @@ -698,11 +701,11 @@ static void mlx4_free_icms(struct mlx4_dev *dev) | |||
| 698 | mlx4_cleanup_icm_table(dev, &priv->qp_table.qp_table); | 701 | mlx4_cleanup_icm_table(dev, &priv->qp_table.qp_table); |
| 699 | mlx4_cleanup_icm_table(dev, &priv->mr_table.dmpt_table); | 702 | mlx4_cleanup_icm_table(dev, &priv->mr_table.dmpt_table); |
| 700 | mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table); | 703 | mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table); |
| 704 | mlx4_cleanup_icm_table(dev, &priv->eq_table.table); | ||
| 701 | mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table); | 705 | mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table); |
| 702 | mlx4_cleanup_icm_table(dev, &priv->cq_table.cmpt_table); | 706 | mlx4_cleanup_icm_table(dev, &priv->cq_table.cmpt_table); |
| 703 | mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table); | 707 | mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table); |
| 704 | mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table); | 708 | mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table); |
| 705 | mlx4_unmap_eq_icm(dev); | ||
| 706 | 709 | ||
| 707 | mlx4_UNMAP_ICM_AUX(dev); | 710 | mlx4_UNMAP_ICM_AUX(dev); |
| 708 | mlx4_free_icm(dev, priv->fw.aux_icm, 0); | 711 | mlx4_free_icm(dev, priv->fw.aux_icm, 0); |
| @@ -786,7 +789,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev) | |||
| 786 | return 0; | 789 | return 0; |
| 787 | 790 | ||
| 788 | err_close: | 791 | err_close: |
| 789 | mlx4_close_hca(dev); | 792 | mlx4_CLOSE_HCA(dev, 0); |
| 790 | 793 | ||
| 791 | err_free_icm: | 794 | err_free_icm: |
| 792 | mlx4_free_icms(dev); | 795 | mlx4_free_icms(dev); |
| @@ -1070,18 +1073,12 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1070 | goto err_disable_pdev; | 1073 | goto err_disable_pdev; |
| 1071 | } | 1074 | } |
| 1072 | 1075 | ||
| 1073 | err = pci_request_region(pdev, 0, DRV_NAME); | 1076 | err = pci_request_regions(pdev, DRV_NAME); |
| 1074 | if (err) { | 1077 | if (err) { |
| 1075 | dev_err(&pdev->dev, "Cannot request control region, aborting.\n"); | 1078 | dev_err(&pdev->dev, "Couldn't get PCI resources, aborting\n"); |
| 1076 | goto err_disable_pdev; | 1079 | goto err_disable_pdev; |
| 1077 | } | 1080 | } |
| 1078 | 1081 | ||
| 1079 | err = pci_request_region(pdev, 2, DRV_NAME); | ||
| 1080 | if (err) { | ||
| 1081 | dev_err(&pdev->dev, "Cannot request UAR region, aborting.\n"); | ||
| 1082 | goto err_release_bar0; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | pci_set_master(pdev); | 1082 | pci_set_master(pdev); |
| 1086 | 1083 | ||
| 1087 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); | 1084 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); |
| @@ -1090,7 +1087,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1090 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | 1087 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
| 1091 | if (err) { | 1088 | if (err) { |
| 1092 | dev_err(&pdev->dev, "Can't set PCI DMA mask, aborting.\n"); | 1089 | dev_err(&pdev->dev, "Can't set PCI DMA mask, aborting.\n"); |
| 1093 | goto err_release_bar2; | 1090 | goto err_release_regions; |
| 1094 | } | 1091 | } |
| 1095 | } | 1092 | } |
| 1096 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); | 1093 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); |
| @@ -1101,7 +1098,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1101 | if (err) { | 1098 | if (err) { |
| 1102 | dev_err(&pdev->dev, "Can't set consistent PCI DMA mask, " | 1099 | dev_err(&pdev->dev, "Can't set consistent PCI DMA mask, " |
| 1103 | "aborting.\n"); | 1100 | "aborting.\n"); |
| 1104 | goto err_release_bar2; | 1101 | goto err_release_regions; |
| 1105 | } | 1102 | } |
| 1106 | } | 1103 | } |
| 1107 | 1104 | ||
| @@ -1110,7 +1107,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1110 | dev_err(&pdev->dev, "Device struct alloc failed, " | 1107 | dev_err(&pdev->dev, "Device struct alloc failed, " |
| 1111 | "aborting.\n"); | 1108 | "aborting.\n"); |
| 1112 | err = -ENOMEM; | 1109 | err = -ENOMEM; |
| 1113 | goto err_release_bar2; | 1110 | goto err_release_regions; |
| 1114 | } | 1111 | } |
| 1115 | 1112 | ||
| 1116 | dev = &priv->dev; | 1113 | dev = &priv->dev; |
| @@ -1205,11 +1202,8 @@ err_cmd: | |||
| 1205 | err_free_dev: | 1202 | err_free_dev: |
| 1206 | kfree(priv); | 1203 | kfree(priv); |
| 1207 | 1204 | ||
| 1208 | err_release_bar2: | 1205 | err_release_regions: |
| 1209 | pci_release_region(pdev, 2); | 1206 | pci_release_regions(pdev); |
| 1210 | |||
| 1211 | err_release_bar0: | ||
| 1212 | pci_release_region(pdev, 0); | ||
| 1213 | 1207 | ||
| 1214 | err_disable_pdev: | 1208 | err_disable_pdev: |
| 1215 | pci_disable_device(pdev); | 1209 | pci_disable_device(pdev); |
| @@ -1265,8 +1259,7 @@ static void mlx4_remove_one(struct pci_dev *pdev) | |||
| 1265 | pci_disable_msix(pdev); | 1259 | pci_disable_msix(pdev); |
| 1266 | 1260 | ||
| 1267 | kfree(priv); | 1261 | kfree(priv); |
| 1268 | pci_release_region(pdev, 2); | 1262 | pci_release_regions(pdev); |
| 1269 | pci_release_region(pdev, 0); | ||
| 1270 | pci_disable_device(pdev); | 1263 | pci_disable_device(pdev); |
| 1271 | pci_set_drvdata(pdev, NULL); | 1264 | pci_set_drvdata(pdev, NULL); |
| 1272 | } | 1265 | } |
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c index 6053c357a470..5ccbce9866fe 100644 --- a/drivers/net/mlx4/mcg.c +++ b/drivers/net/mlx4/mcg.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | * SOFTWARE. | 31 | * SOFTWARE. |
| 32 | */ | 32 | */ |
| 33 | 33 | ||
| 34 | #include <linux/init.h> | ||
| 35 | #include <linux/string.h> | 34 | #include <linux/string.h> |
| 36 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| 37 | 36 | ||
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index 5bd79c2b184f..bc72d6e4919b 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h | |||
| @@ -205,9 +205,7 @@ struct mlx4_eq_table { | |||
| 205 | void __iomem **uar_map; | 205 | void __iomem **uar_map; |
| 206 | u32 clr_mask; | 206 | u32 clr_mask; |
| 207 | struct mlx4_eq *eq; | 207 | struct mlx4_eq *eq; |
| 208 | u64 icm_virt; | 208 | struct mlx4_icm_table table; |
| 209 | struct page *icm_page; | ||
| 210 | dma_addr_t icm_dma; | ||
| 211 | struct mlx4_icm_table cmpt_table; | 209 | struct mlx4_icm_table cmpt_table; |
| 212 | int have_irq; | 210 | int have_irq; |
| 213 | u8 inta_pin; | 211 | u8 inta_pin; |
| @@ -373,9 +371,6 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, | |||
| 373 | struct mlx4_dev_cap *dev_cap, | 371 | struct mlx4_dev_cap *dev_cap, |
| 374 | struct mlx4_init_hca_param *init_hca); | 372 | struct mlx4_init_hca_param *init_hca); |
| 375 | 373 | ||
| 376 | int mlx4_map_eq_icm(struct mlx4_dev *dev, u64 icm_virt); | ||
| 377 | void mlx4_unmap_eq_icm(struct mlx4_dev *dev); | ||
| 378 | |||
| 379 | int mlx4_cmd_init(struct mlx4_dev *dev); | 374 | int mlx4_cmd_init(struct mlx4_dev *dev); |
| 380 | void mlx4_cmd_cleanup(struct mlx4_dev *dev); | 375 | void mlx4_cmd_cleanup(struct mlx4_dev *dev); |
| 381 | void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param); | 376 | void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param); |
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c index f96948be0a44..ca7ab8e7b4cc 100644 --- a/drivers/net/mlx4/mr.c +++ b/drivers/net/mlx4/mr.c | |||
| @@ -32,7 +32,6 @@ | |||
| 32 | * SOFTWARE. | 32 | * SOFTWARE. |
| 33 | */ | 33 | */ |
| 34 | 34 | ||
| 35 | #include <linux/init.h> | ||
| 36 | #include <linux/errno.h> | 35 | #include <linux/errno.h> |
| 37 | 36 | ||
| 38 | #include <linux/mlx4/cmd.h> | 37 | #include <linux/mlx4/cmd.h> |
diff --git a/drivers/net/mlx4/pd.c b/drivers/net/mlx4/pd.c index 26d1a7a9e375..c4988d6bd5b2 100644 --- a/drivers/net/mlx4/pd.c +++ b/drivers/net/mlx4/pd.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | * SOFTWARE. | 31 | * SOFTWARE. |
| 32 | */ | 32 | */ |
| 33 | 33 | ||
| 34 | #include <linux/init.h> | ||
| 35 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
| 36 | 35 | ||
| 37 | #include <asm/page.h> | 36 | #include <asm/page.h> |
diff --git a/drivers/net/mlx4/profile.c b/drivers/net/mlx4/profile.c index bd22df95adf9..ca25b9dc8378 100644 --- a/drivers/net/mlx4/profile.c +++ b/drivers/net/mlx4/profile.c | |||
| @@ -32,8 +32,6 @@ | |||
| 32 | * SOFTWARE. | 32 | * SOFTWARE. |
| 33 | */ | 33 | */ |
| 34 | 34 | ||
| 35 | #include <linux/init.h> | ||
| 36 | |||
| 37 | #include "mlx4.h" | 35 | #include "mlx4.h" |
| 38 | #include "fw.h" | 36 | #include "fw.h" |
| 39 | 37 | ||
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c index 1c565ef8d179..42ab9fc01d3e 100644 --- a/drivers/net/mlx4/qp.c +++ b/drivers/net/mlx4/qp.c | |||
| @@ -33,8 +33,6 @@ | |||
| 33 | * SOFTWARE. | 33 | * SOFTWARE. |
| 34 | */ | 34 | */ |
| 35 | 35 | ||
| 36 | #include <linux/init.h> | ||
| 37 | |||
| 38 | #include <linux/mlx4/cmd.h> | 36 | #include <linux/mlx4/cmd.h> |
| 39 | #include <linux/mlx4/qp.h> | 37 | #include <linux/mlx4/qp.h> |
| 40 | 38 | ||
diff --git a/drivers/net/mlx4/reset.c b/drivers/net/mlx4/reset.c index 3951b884c0fb..e5741dab3825 100644 --- a/drivers/net/mlx4/reset.c +++ b/drivers/net/mlx4/reset.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | * SOFTWARE. | 31 | * SOFTWARE. |
| 32 | */ | 32 | */ |
| 33 | 33 | ||
| 34 | #include <linux/init.h> | ||
| 35 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
| 36 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
| 37 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
diff --git a/drivers/net/mlx4/srq.c b/drivers/net/mlx4/srq.c index fe9f218691f5..1377d0dc8f1f 100644 --- a/drivers/net/mlx4/srq.c +++ b/drivers/net/mlx4/srq.c | |||
| @@ -31,8 +31,6 @@ | |||
| 31 | * SOFTWARE. | 31 | * SOFTWARE. |
| 32 | */ | 32 | */ |
| 33 | 33 | ||
| 34 | #include <linux/init.h> | ||
| 35 | |||
| 36 | #include <linux/mlx4/cmd.h> | 34 | #include <linux/mlx4/cmd.h> |
| 37 | 35 | ||
| 38 | #include "mlx4.h" | 36 | #include "mlx4.h" |
