diff options
author | Devesh Sharma <devesh.sharma@avagotech.com> | 2016-01-28 08:59:57 -0500 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-02-29 17:12:10 -0500 |
commit | 6b0626679d81626eac47cba7940f1435ec480b2e (patch) | |
tree | c1a6c349ce41632c63f95a4dc19d37ad16846ddd | |
parent | e1614869d370d4d1599d771346d7da570f1d2bfa (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.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/ocrdma/ocrdma_ah.c | 70 | ||||
-rw-r--r-- | drivers/infiniband/hw/ocrdma/ocrdma_sli.h | 5 | ||||
-rw-r--r-- | drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 22 |
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 | ||
362 | struct ocrdma_qp_hwq_info { | 363 | struct 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 | ||
58 | static 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 | |||
58 | static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah, | 73 | static 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(ð, 0, sizeof(eth)); | 90 | memset(ð, 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_sz); | 125 | memcpy(&ah->av->eth_hdr, ð, 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 | ||
2720 | static int ocrdma_update_ud_rcqe(struct ib_wc *ibwc, struct ocrdma_cqe *cqe) | 2721 | static 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, | |||
2791 | static void ocrdma_poll_success_rcqe(struct ocrdma_qp *qp, | 2804 | static 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 | ||