aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDevesh Sharma <devesh.sharma@avagotech.com>2016-01-28 08:59:57 -0500
committerDoug Ledford <dledford@redhat.com>2016-02-29 17:12:10 -0500
commit6b0626679d81626eac47cba7940f1435ec480b2e (patch)
treec1a6c349ce41632c63f95a4dc19d37ad16846ddd
parente1614869d370d4d1599d771346d7da570f1d2bfa (diff)
RDMA/ocrdma: Support RoCE-v2 in the UD path
This patch adds following changes to support RoCE-v2 in the UD path. * During AH creation GID-type is resolved for a given gid-index. * Based on GID-type protocol header is built. * Work completion reports network header type and set IB_WC_WITH_NETWORK_HDR_TYPE flag in wc->wc_flags to indicate that the network header type is valid. Signed-off-by: Somnath Kotur <somnath.kotur@avagotech.com> Signed-off-by: Devesh Sharma <devesh.sharma@avagotech.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma.h1
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_ah.c70
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_sli.h5
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_verbs.c22
4 files changed, 82 insertions, 16 deletions
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h
index b58833d9b909..45bdfa0e3b2b 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma.h
@@ -357,6 +357,7 @@ struct ocrdma_ah {
357 struct ocrdma_av *av; 357 struct ocrdma_av *av;
358 u16 sgid_index; 358 u16 sgid_index;
359 u32 id; 359 u32 id;
360 u8 hdr_type;
360}; 361};
361 362
362struct ocrdma_qp_hwq_info { 363struct ocrdma_qp_hwq_info {
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
index 3790771f2baa..4aed1dbb0b97 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
@@ -55,6 +55,21 @@
55 55
56#define OCRDMA_VID_PCP_SHIFT 0xD 56#define OCRDMA_VID_PCP_SHIFT 0xD
57 57
58static u16 ocrdma_hdr_type_to_proto_num(int devid, u8 hdr_type)
59{
60 switch (hdr_type) {
61 case OCRDMA_L3_TYPE_IB_GRH:
62 return (u16)0x8915;
63 case OCRDMA_L3_TYPE_IPV4:
64 return (u16)0x0800;
65 case OCRDMA_L3_TYPE_IPV6:
66 return (u16)0x86dd;
67 default:
68 pr_err("ocrdma%d: Invalid network header\n", devid);
69 return 0;
70 }
71}
72
58static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah, 73static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
59 struct ib_ah_attr *attr, union ib_gid *sgid, 74 struct ib_ah_attr *attr, union ib_gid *sgid,
60 int pdid, bool *isvlan, u16 vlan_tag) 75 int pdid, bool *isvlan, u16 vlan_tag)
@@ -63,10 +78,23 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
63 struct ocrdma_eth_vlan eth; 78 struct ocrdma_eth_vlan eth;
64 struct ocrdma_grh grh; 79 struct ocrdma_grh grh;
65 int eth_sz; 80 int eth_sz;
81 u16 proto_num = 0;
82 u8 nxthdr = 0x11;
83 struct iphdr ipv4;
84 union {
85 struct sockaddr _sockaddr;
86 struct sockaddr_in _sockaddr_in;
87 struct sockaddr_in6 _sockaddr_in6;
88 } sgid_addr, dgid_addr;
66 89
67 memset(&eth, 0, sizeof(eth)); 90 memset(&eth, 0, sizeof(eth));
68 memset(&grh, 0, sizeof(grh)); 91 memset(&grh, 0, sizeof(grh));
69 92
93 /* Protocol Number */
94 proto_num = ocrdma_hdr_type_to_proto_num(dev->id, ah->hdr_type);
95 if (!proto_num)
96 return -EINVAL;
97 nxthdr = (proto_num == 0x8915) ? 0x1b : 0x11;
70 /* VLAN */ 98 /* VLAN */
71 if (!vlan_tag || (vlan_tag > 0xFFF)) 99 if (!vlan_tag || (vlan_tag > 0xFFF))
72 vlan_tag = dev->pvid; 100 vlan_tag = dev->pvid;
@@ -78,13 +106,13 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
78 dev->id); 106 dev->id);
79 } 107 }
80 eth.eth_type = cpu_to_be16(0x8100); 108 eth.eth_type = cpu_to_be16(0x8100);
81 eth.roce_eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE); 109 eth.roce_eth_type = cpu_to_be16(proto_num);
82 vlan_tag |= (dev->sl & 0x07) << OCRDMA_VID_PCP_SHIFT; 110 vlan_tag |= (dev->sl & 0x07) << OCRDMA_VID_PCP_SHIFT;
83 eth.vlan_tag = cpu_to_be16(vlan_tag); 111 eth.vlan_tag = cpu_to_be16(vlan_tag);
84 eth_sz = sizeof(struct ocrdma_eth_vlan); 112 eth_sz = sizeof(struct ocrdma_eth_vlan);
85 *isvlan = true; 113 *isvlan = true;
86 } else { 114 } else {
87 eth.eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE); 115 eth.eth_type = cpu_to_be16(proto_num);
88 eth_sz = sizeof(struct ocrdma_eth_basic); 116 eth_sz = sizeof(struct ocrdma_eth_basic);
89 } 117 }
90 /* MAC */ 118 /* MAC */
@@ -93,18 +121,33 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
93 if (status) 121 if (status)
94 return status; 122 return status;
95 ah->sgid_index = attr->grh.sgid_index; 123 ah->sgid_index = attr->grh.sgid_index;
96 memcpy(&grh.sgid[0], sgid->raw, sizeof(union ib_gid));
97 memcpy(&grh.dgid[0], attr->grh.dgid.raw, sizeof(attr->grh.dgid.raw));
98
99 grh.tclass_flow = cpu_to_be32((6 << 28) |
100 (attr->grh.traffic_class << 24) |
101 attr->grh.flow_label);
102 /* 0x1b is next header value in GRH */
103 grh.pdid_hoplimit = cpu_to_be32((pdid << 16) |
104 (0x1b << 8) | attr->grh.hop_limit);
105 /* Eth HDR */ 124 /* Eth HDR */
106 memcpy(&ah->av->eth_hdr, &eth, eth_sz); 125 memcpy(&ah->av->eth_hdr, &eth, eth_sz);
107 memcpy((u8 *)ah->av + eth_sz, &grh, sizeof(struct ocrdma_grh)); 126 if (ah->hdr_type == RDMA_NETWORK_IPV4) {
127 *((__be16 *)&ipv4) = htons((4 << 12) | (5 << 8) |
128 attr->grh.traffic_class);
129 ipv4.id = cpu_to_be16(pdid);
130 ipv4.frag_off = htons(IP_DF);
131 ipv4.tot_len = htons(0);
132 ipv4.ttl = attr->grh.hop_limit;
133 ipv4.protocol = nxthdr;
134 rdma_gid2ip(&sgid_addr._sockaddr, sgid);
135 ipv4.saddr = sgid_addr._sockaddr_in.sin_addr.s_addr;
136 rdma_gid2ip(&dgid_addr._sockaddr, &attr->grh.dgid);
137 ipv4.daddr = dgid_addr._sockaddr_in.sin_addr.s_addr;
138 memcpy((u8 *)ah->av + eth_sz, &ipv4, sizeof(struct iphdr));
139 } else {
140 memcpy(&grh.sgid[0], sgid->raw, sizeof(union ib_gid));
141 grh.tclass_flow = cpu_to_be32((6 << 28) |
142 (attr->grh.traffic_class << 24) |
143 attr->grh.flow_label);
144 memcpy(&grh.dgid[0], attr->grh.dgid.raw,
145 sizeof(attr->grh.dgid.raw));
146 grh.pdid_hoplimit = cpu_to_be32((pdid << 16) |
147 (nxthdr << 8) |
148 attr->grh.hop_limit);
149 memcpy((u8 *)ah->av + eth_sz, &grh, sizeof(struct ocrdma_grh));
150 }
108 if (*isvlan) 151 if (*isvlan)
109 ah->av->valid |= OCRDMA_AV_VLAN_VALID; 152 ah->av->valid |= OCRDMA_AV_VLAN_VALID;
110 ah->av->valid = cpu_to_le32(ah->av->valid); 153 ah->av->valid = cpu_to_le32(ah->av->valid);
@@ -128,6 +171,7 @@ struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr)
128 171
129 if (atomic_cmpxchg(&dev->update_sl, 1, 0)) 172 if (atomic_cmpxchg(&dev->update_sl, 1, 0))
130 ocrdma_init_service_level(dev); 173 ocrdma_init_service_level(dev);
174
131 ah = kzalloc(sizeof(*ah), GFP_ATOMIC); 175 ah = kzalloc(sizeof(*ah), GFP_ATOMIC);
132 if (!ah) 176 if (!ah)
133 return ERR_PTR(-ENOMEM); 177 return ERR_PTR(-ENOMEM);
@@ -148,6 +192,8 @@ struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr)
148 vlan_tag = vlan_dev_vlan_id(sgid_attr.ndev); 192 vlan_tag = vlan_dev_vlan_id(sgid_attr.ndev);
149 dev_put(sgid_attr.ndev); 193 dev_put(sgid_attr.ndev);
150 } 194 }
195 /* Get network header type for this GID */
196 ah->hdr_type = ib_gid_to_network_type(sgid_attr.gid_type, &sgid);
151 197
152 if ((pd->uctx) && 198 if ((pd->uctx) &&
153 (!rdma_is_multicast_addr((struct in6_addr *)attr->grh.dgid.raw)) && 199 (!rdma_is_multicast_addr((struct in6_addr *)attr->grh.dgid.raw)) &&
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
index 8d75bd4a46ff..3d15948cbf7c 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
@@ -1740,8 +1740,11 @@ enum {
1740 1740
1741 /* w1 */ 1741 /* w1 */
1742 OCRDMA_CQE_UD_XFER_LEN_SHIFT = 16, 1742 OCRDMA_CQE_UD_XFER_LEN_SHIFT = 16,
1743 OCRDMA_CQE_UD_XFER_LEN_MASK = 0x1FFF,
1743 OCRDMA_CQE_PKEY_SHIFT = 0, 1744 OCRDMA_CQE_PKEY_SHIFT = 0,
1744 OCRDMA_CQE_PKEY_MASK = 0xFFFF, 1745 OCRDMA_CQE_PKEY_MASK = 0xFFFF,
1746 OCRDMA_CQE_UD_L3TYPE_SHIFT = 29,
1747 OCRDMA_CQE_UD_L3TYPE_MASK = 0x07,
1745 1748
1746 /* w2 */ 1749 /* w2 */
1747 OCRDMA_CQE_QPN_SHIFT = 0, 1750 OCRDMA_CQE_QPN_SHIFT = 0,
@@ -1866,7 +1869,7 @@ struct ocrdma_ewqe_ud_hdr {
1866 u32 rsvd_dest_qpn; 1869 u32 rsvd_dest_qpn;
1867 u32 qkey; 1870 u32 qkey;
1868 u32 rsvd_ahid; 1871 u32 rsvd_ahid;
1869 u32 rsvd; 1872 u32 hdr_type;
1870}; 1873};
1871 1874
1872/* extended wqe followed by hdr_wqe for Fast Memory register */ 1875/* extended wqe followed by hdr_wqe for Fast Memory register */
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index 12420e4ecf3d..4df3f132d607 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -2005,6 +2005,7 @@ static void ocrdma_build_ud_hdr(struct ocrdma_qp *qp,
2005 else 2005 else
2006 ud_hdr->qkey = ud_wr(wr)->remote_qkey; 2006 ud_hdr->qkey = ud_wr(wr)->remote_qkey;
2007 ud_hdr->rsvd_ahid = ah->id; 2007 ud_hdr->rsvd_ahid = ah->id;
2008 ud_hdr->hdr_type = ah->hdr_type;
2008 if (ah->av->valid & OCRDMA_AV_VLAN_VALID) 2009 if (ah->av->valid & OCRDMA_AV_VLAN_VALID)
2009 hdr->cw |= (OCRDMA_FLAG_AH_VLAN_PR << OCRDMA_WQE_FLAGS_SHIFT); 2010 hdr->cw |= (OCRDMA_FLAG_AH_VLAN_PR << OCRDMA_WQE_FLAGS_SHIFT);
2010} 2011}
@@ -2717,9 +2718,11 @@ static bool ocrdma_poll_scqe(struct ocrdma_qp *qp, struct ocrdma_cqe *cqe,
2717 return expand; 2718 return expand;
2718} 2719}
2719 2720
2720static int ocrdma_update_ud_rcqe(struct ib_wc *ibwc, struct ocrdma_cqe *cqe) 2721static int ocrdma_update_ud_rcqe(struct ocrdma_dev *dev, struct ib_wc *ibwc,
2722 struct ocrdma_cqe *cqe)
2721{ 2723{
2722 int status; 2724 int status;
2725 u16 hdr_type = 0;
2723 2726
2724 status = (le32_to_cpu(cqe->flags_status_srcqpn) & 2727 status = (le32_to_cpu(cqe->flags_status_srcqpn) &
2725 OCRDMA_CQE_UD_STATUS_MASK) >> OCRDMA_CQE_UD_STATUS_SHIFT; 2728 OCRDMA_CQE_UD_STATUS_MASK) >> OCRDMA_CQE_UD_STATUS_SHIFT;
@@ -2728,7 +2731,17 @@ static int ocrdma_update_ud_rcqe(struct ib_wc *ibwc, struct ocrdma_cqe *cqe)
2728 ibwc->pkey_index = 0; 2731 ibwc->pkey_index = 0;
2729 ibwc->wc_flags = IB_WC_GRH; 2732 ibwc->wc_flags = IB_WC_GRH;
2730 ibwc->byte_len = (le32_to_cpu(cqe->ud.rxlen_pkey) >> 2733 ibwc->byte_len = (le32_to_cpu(cqe->ud.rxlen_pkey) >>
2731 OCRDMA_CQE_UD_XFER_LEN_SHIFT); 2734 OCRDMA_CQE_UD_XFER_LEN_SHIFT) &
2735 OCRDMA_CQE_UD_XFER_LEN_MASK;
2736
2737 if (ocrdma_is_udp_encap_supported(dev)) {
2738 hdr_type = (le32_to_cpu(cqe->ud.rxlen_pkey) >>
2739 OCRDMA_CQE_UD_L3TYPE_SHIFT) &
2740 OCRDMA_CQE_UD_L3TYPE_MASK;
2741 ibwc->wc_flags |= IB_WC_WITH_NETWORK_HDR_TYPE;
2742 ibwc->network_hdr_type = hdr_type;
2743 }
2744
2732 return status; 2745 return status;
2733} 2746}
2734 2747
@@ -2791,12 +2804,15 @@ static bool ocrdma_poll_err_rcqe(struct ocrdma_qp *qp, struct ocrdma_cqe *cqe,
2791static void ocrdma_poll_success_rcqe(struct ocrdma_qp *qp, 2804static void ocrdma_poll_success_rcqe(struct ocrdma_qp *qp,
2792 struct ocrdma_cqe *cqe, struct ib_wc *ibwc) 2805 struct ocrdma_cqe *cqe, struct ib_wc *ibwc)
2793{ 2806{
2807 struct ocrdma_dev *dev;
2808
2809 dev = get_ocrdma_dev(qp->ibqp.device);
2794 ibwc->opcode = IB_WC_RECV; 2810 ibwc->opcode = IB_WC_RECV;
2795 ibwc->qp = &qp->ibqp; 2811 ibwc->qp = &qp->ibqp;
2796 ibwc->status = IB_WC_SUCCESS; 2812 ibwc->status = IB_WC_SUCCESS;
2797 2813
2798 if (qp->qp_type == IB_QPT_UD || qp->qp_type == IB_QPT_GSI) 2814 if (qp->qp_type == IB_QPT_UD || qp->qp_type == IB_QPT_GSI)
2799 ocrdma_update_ud_rcqe(ibwc, cqe); 2815 ocrdma_update_ud_rcqe(dev, ibwc, cqe);
2800 else 2816 else
2801 ibwc->byte_len = le32_to_cpu(cqe->rq.rxlen); 2817 ibwc->byte_len = le32_to_cpu(cqe->rq.rxlen);
2802 2818