1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright(c) 2015 - 2018 Intel Corporation.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * This file is provided under a dual BSD/GPLv2 license. When using or
5*4882a593Smuzhiyun * redistributing this file, you may do so under either license.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * GPL LICENSE SUMMARY
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify
10*4882a593Smuzhiyun * it under the terms of version 2 of the GNU General Public License as
11*4882a593Smuzhiyun * published by the Free Software Foundation.
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful, but
14*4882a593Smuzhiyun * WITHOUT ANY WARRANTY; without even the implied warranty of
15*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16*4882a593Smuzhiyun * General Public License for more details.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * BSD LICENSE
19*4882a593Smuzhiyun *
20*4882a593Smuzhiyun * Redistribution and use in source and binary forms, with or without
21*4882a593Smuzhiyun * modification, are permitted provided that the following conditions
22*4882a593Smuzhiyun * are met:
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * - Redistributions of source code must retain the above copyright
25*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer.
26*4882a593Smuzhiyun * - Redistributions in binary form must reproduce the above copyright
27*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer in
28*4882a593Smuzhiyun * the documentation and/or other materials provided with the
29*4882a593Smuzhiyun * distribution.
30*4882a593Smuzhiyun * - Neither the name of Intel Corporation nor the names of its
31*4882a593Smuzhiyun * contributors may be used to endorse or promote products derived
32*4882a593Smuzhiyun * from this software without specific prior written permission.
33*4882a593Smuzhiyun *
34*4882a593Smuzhiyun * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
35*4882a593Smuzhiyun * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36*4882a593Smuzhiyun * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
37*4882a593Smuzhiyun * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
38*4882a593Smuzhiyun * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39*4882a593Smuzhiyun * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40*4882a593Smuzhiyun * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
41*4882a593Smuzhiyun * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
42*4882a593Smuzhiyun * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43*4882a593Smuzhiyun * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
44*4882a593Smuzhiyun * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45*4882a593Smuzhiyun *
46*4882a593Smuzhiyun */
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #include <linux/spinlock.h>
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #include "hfi.h"
51*4882a593Smuzhiyun #include "mad.h"
52*4882a593Smuzhiyun #include "qp.h"
53*4882a593Smuzhiyun #include "verbs_txreq.h"
54*4882a593Smuzhiyun #include "trace.h"
55*4882a593Smuzhiyun
gid_ok(union ib_gid * gid,__be64 gid_prefix,__be64 id)56*4882a593Smuzhiyun static int gid_ok(union ib_gid *gid, __be64 gid_prefix, __be64 id)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun return (gid->global.interface_id == id &&
59*4882a593Smuzhiyun (gid->global.subnet_prefix == gid_prefix ||
60*4882a593Smuzhiyun gid->global.subnet_prefix == IB_DEFAULT_GID_PREFIX));
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun /*
64*4882a593Smuzhiyun *
65*4882a593Smuzhiyun * This should be called with the QP r_lock held.
66*4882a593Smuzhiyun *
67*4882a593Smuzhiyun * The s_lock will be acquired around the hfi1_migrate_qp() call.
68*4882a593Smuzhiyun */
hfi1_ruc_check_hdr(struct hfi1_ibport * ibp,struct hfi1_packet * packet)69*4882a593Smuzhiyun int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun __be64 guid;
72*4882a593Smuzhiyun unsigned long flags;
73*4882a593Smuzhiyun struct rvt_qp *qp = packet->qp;
74*4882a593Smuzhiyun u8 sc5 = ibp->sl_to_sc[rdma_ah_get_sl(&qp->remote_ah_attr)];
75*4882a593Smuzhiyun u32 dlid = packet->dlid;
76*4882a593Smuzhiyun u32 slid = packet->slid;
77*4882a593Smuzhiyun u32 sl = packet->sl;
78*4882a593Smuzhiyun bool migrated = packet->migrated;
79*4882a593Smuzhiyun u16 pkey = packet->pkey;
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun if (qp->s_mig_state == IB_MIG_ARMED && migrated) {
82*4882a593Smuzhiyun if (!packet->grh) {
83*4882a593Smuzhiyun if ((rdma_ah_get_ah_flags(&qp->alt_ah_attr) &
84*4882a593Smuzhiyun IB_AH_GRH) &&
85*4882a593Smuzhiyun (packet->etype != RHF_RCV_TYPE_BYPASS))
86*4882a593Smuzhiyun return 1;
87*4882a593Smuzhiyun } else {
88*4882a593Smuzhiyun const struct ib_global_route *grh;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun if (!(rdma_ah_get_ah_flags(&qp->alt_ah_attr) &
91*4882a593Smuzhiyun IB_AH_GRH))
92*4882a593Smuzhiyun return 1;
93*4882a593Smuzhiyun grh = rdma_ah_read_grh(&qp->alt_ah_attr);
94*4882a593Smuzhiyun guid = get_sguid(ibp, grh->sgid_index);
95*4882a593Smuzhiyun if (!gid_ok(&packet->grh->dgid, ibp->rvp.gid_prefix,
96*4882a593Smuzhiyun guid))
97*4882a593Smuzhiyun return 1;
98*4882a593Smuzhiyun if (!gid_ok(
99*4882a593Smuzhiyun &packet->grh->sgid,
100*4882a593Smuzhiyun grh->dgid.global.subnet_prefix,
101*4882a593Smuzhiyun grh->dgid.global.interface_id))
102*4882a593Smuzhiyun return 1;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), pkey,
105*4882a593Smuzhiyun sc5, slid))) {
106*4882a593Smuzhiyun hfi1_bad_pkey(ibp, pkey, sl, 0, qp->ibqp.qp_num,
107*4882a593Smuzhiyun slid, dlid);
108*4882a593Smuzhiyun return 1;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun /* Validate the SLID. See Ch. 9.6.1.5 and 17.2.8 */
111*4882a593Smuzhiyun if (slid != rdma_ah_get_dlid(&qp->alt_ah_attr) ||
112*4882a593Smuzhiyun ppd_from_ibp(ibp)->port !=
113*4882a593Smuzhiyun rdma_ah_get_port_num(&qp->alt_ah_attr))
114*4882a593Smuzhiyun return 1;
115*4882a593Smuzhiyun spin_lock_irqsave(&qp->s_lock, flags);
116*4882a593Smuzhiyun hfi1_migrate_qp(qp);
117*4882a593Smuzhiyun spin_unlock_irqrestore(&qp->s_lock, flags);
118*4882a593Smuzhiyun } else {
119*4882a593Smuzhiyun if (!packet->grh) {
120*4882a593Smuzhiyun if ((rdma_ah_get_ah_flags(&qp->remote_ah_attr) &
121*4882a593Smuzhiyun IB_AH_GRH) &&
122*4882a593Smuzhiyun (packet->etype != RHF_RCV_TYPE_BYPASS))
123*4882a593Smuzhiyun return 1;
124*4882a593Smuzhiyun } else {
125*4882a593Smuzhiyun const struct ib_global_route *grh;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun if (!(rdma_ah_get_ah_flags(&qp->remote_ah_attr) &
128*4882a593Smuzhiyun IB_AH_GRH))
129*4882a593Smuzhiyun return 1;
130*4882a593Smuzhiyun grh = rdma_ah_read_grh(&qp->remote_ah_attr);
131*4882a593Smuzhiyun guid = get_sguid(ibp, grh->sgid_index);
132*4882a593Smuzhiyun if (!gid_ok(&packet->grh->dgid, ibp->rvp.gid_prefix,
133*4882a593Smuzhiyun guid))
134*4882a593Smuzhiyun return 1;
135*4882a593Smuzhiyun if (!gid_ok(
136*4882a593Smuzhiyun &packet->grh->sgid,
137*4882a593Smuzhiyun grh->dgid.global.subnet_prefix,
138*4882a593Smuzhiyun grh->dgid.global.interface_id))
139*4882a593Smuzhiyun return 1;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), pkey,
142*4882a593Smuzhiyun sc5, slid))) {
143*4882a593Smuzhiyun hfi1_bad_pkey(ibp, pkey, sl, 0, qp->ibqp.qp_num,
144*4882a593Smuzhiyun slid, dlid);
145*4882a593Smuzhiyun return 1;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun /* Validate the SLID. See Ch. 9.6.1.5 */
148*4882a593Smuzhiyun if ((slid != rdma_ah_get_dlid(&qp->remote_ah_attr)) ||
149*4882a593Smuzhiyun ppd_from_ibp(ibp)->port != qp->port_num)
150*4882a593Smuzhiyun return 1;
151*4882a593Smuzhiyun if (qp->s_mig_state == IB_MIG_REARM && !migrated)
152*4882a593Smuzhiyun qp->s_mig_state = IB_MIG_ARMED;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun return 0;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun /**
159*4882a593Smuzhiyun * hfi1_make_grh - construct a GRH header
160*4882a593Smuzhiyun * @ibp: a pointer to the IB port
161*4882a593Smuzhiyun * @hdr: a pointer to the GRH header being constructed
162*4882a593Smuzhiyun * @grh: the global route address to send to
163*4882a593Smuzhiyun * @hwords: size of header after grh being sent in dwords
164*4882a593Smuzhiyun * @nwords: the number of 32 bit words of data being sent
165*4882a593Smuzhiyun *
166*4882a593Smuzhiyun * Return the size of the header in 32 bit words.
167*4882a593Smuzhiyun */
hfi1_make_grh(struct hfi1_ibport * ibp,struct ib_grh * hdr,const struct ib_global_route * grh,u32 hwords,u32 nwords)168*4882a593Smuzhiyun u32 hfi1_make_grh(struct hfi1_ibport *ibp, struct ib_grh *hdr,
169*4882a593Smuzhiyun const struct ib_global_route *grh, u32 hwords, u32 nwords)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun hdr->version_tclass_flow =
172*4882a593Smuzhiyun cpu_to_be32((IB_GRH_VERSION << IB_GRH_VERSION_SHIFT) |
173*4882a593Smuzhiyun (grh->traffic_class << IB_GRH_TCLASS_SHIFT) |
174*4882a593Smuzhiyun (grh->flow_label << IB_GRH_FLOW_SHIFT));
175*4882a593Smuzhiyun hdr->paylen = cpu_to_be16((hwords + nwords) << 2);
176*4882a593Smuzhiyun /* next_hdr is defined by C8-7 in ch. 8.4.1 */
177*4882a593Smuzhiyun hdr->next_hdr = IB_GRH_NEXT_HDR;
178*4882a593Smuzhiyun hdr->hop_limit = grh->hop_limit;
179*4882a593Smuzhiyun /* The SGID is 32-bit aligned. */
180*4882a593Smuzhiyun hdr->sgid.global.subnet_prefix = ibp->rvp.gid_prefix;
181*4882a593Smuzhiyun hdr->sgid.global.interface_id =
182*4882a593Smuzhiyun grh->sgid_index < HFI1_GUIDS_PER_PORT ?
183*4882a593Smuzhiyun get_sguid(ibp, grh->sgid_index) :
184*4882a593Smuzhiyun get_sguid(ibp, HFI1_PORT_GUID_INDEX);
185*4882a593Smuzhiyun hdr->dgid = grh->dgid;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun /* GRH header size in 32-bit words. */
188*4882a593Smuzhiyun return sizeof(struct ib_grh) / sizeof(u32);
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun #define BTH2_OFFSET (offsetof(struct hfi1_sdma_header, \
192*4882a593Smuzhiyun hdr.ibh.u.oth.bth[2]) / 4)
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun /**
195*4882a593Smuzhiyun * build_ahg - create ahg in s_ahg
196*4882a593Smuzhiyun * @qp: a pointer to QP
197*4882a593Smuzhiyun * @npsn: the next PSN for the request/response
198*4882a593Smuzhiyun *
199*4882a593Smuzhiyun * This routine handles the AHG by allocating an ahg entry and causing the
200*4882a593Smuzhiyun * copy of the first middle.
201*4882a593Smuzhiyun *
202*4882a593Smuzhiyun * Subsequent middles use the copied entry, editing the
203*4882a593Smuzhiyun * PSN with 1 or 2 edits.
204*4882a593Smuzhiyun */
build_ahg(struct rvt_qp * qp,u32 npsn)205*4882a593Smuzhiyun static inline void build_ahg(struct rvt_qp *qp, u32 npsn)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun struct hfi1_qp_priv *priv = qp->priv;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun if (unlikely(qp->s_flags & HFI1_S_AHG_CLEAR))
210*4882a593Smuzhiyun clear_ahg(qp);
211*4882a593Smuzhiyun if (!(qp->s_flags & HFI1_S_AHG_VALID)) {
212*4882a593Smuzhiyun /* first middle that needs copy */
213*4882a593Smuzhiyun if (qp->s_ahgidx < 0)
214*4882a593Smuzhiyun qp->s_ahgidx = sdma_ahg_alloc(priv->s_sde);
215*4882a593Smuzhiyun if (qp->s_ahgidx >= 0) {
216*4882a593Smuzhiyun qp->s_ahgpsn = npsn;
217*4882a593Smuzhiyun priv->s_ahg->tx_flags |= SDMA_TXREQ_F_AHG_COPY;
218*4882a593Smuzhiyun /* save to protect a change in another thread */
219*4882a593Smuzhiyun priv->s_ahg->ahgidx = qp->s_ahgidx;
220*4882a593Smuzhiyun qp->s_flags |= HFI1_S_AHG_VALID;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun } else {
223*4882a593Smuzhiyun /* subsequent middle after valid */
224*4882a593Smuzhiyun if (qp->s_ahgidx >= 0) {
225*4882a593Smuzhiyun priv->s_ahg->tx_flags |= SDMA_TXREQ_F_USE_AHG;
226*4882a593Smuzhiyun priv->s_ahg->ahgidx = qp->s_ahgidx;
227*4882a593Smuzhiyun priv->s_ahg->ahgcount++;
228*4882a593Smuzhiyun priv->s_ahg->ahgdesc[0] =
229*4882a593Smuzhiyun sdma_build_ahg_descriptor(
230*4882a593Smuzhiyun (__force u16)cpu_to_be16((u16)npsn),
231*4882a593Smuzhiyun BTH2_OFFSET,
232*4882a593Smuzhiyun 16,
233*4882a593Smuzhiyun 16);
234*4882a593Smuzhiyun if ((npsn & 0xffff0000) !=
235*4882a593Smuzhiyun (qp->s_ahgpsn & 0xffff0000)) {
236*4882a593Smuzhiyun priv->s_ahg->ahgcount++;
237*4882a593Smuzhiyun priv->s_ahg->ahgdesc[1] =
238*4882a593Smuzhiyun sdma_build_ahg_descriptor(
239*4882a593Smuzhiyun (__force u16)cpu_to_be16(
240*4882a593Smuzhiyun (u16)(npsn >> 16)),
241*4882a593Smuzhiyun BTH2_OFFSET,
242*4882a593Smuzhiyun 0,
243*4882a593Smuzhiyun 16);
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
hfi1_make_ruc_bth(struct rvt_qp * qp,struct ib_other_headers * ohdr,u32 bth0,u32 bth1,u32 bth2)249*4882a593Smuzhiyun static inline void hfi1_make_ruc_bth(struct rvt_qp *qp,
250*4882a593Smuzhiyun struct ib_other_headers *ohdr,
251*4882a593Smuzhiyun u32 bth0, u32 bth1, u32 bth2)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun ohdr->bth[0] = cpu_to_be32(bth0);
254*4882a593Smuzhiyun ohdr->bth[1] = cpu_to_be32(bth1);
255*4882a593Smuzhiyun ohdr->bth[2] = cpu_to_be32(bth2);
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun /**
259*4882a593Smuzhiyun * hfi1_make_ruc_header_16B - build a 16B header
260*4882a593Smuzhiyun * @qp: the queue pair
261*4882a593Smuzhiyun * @ohdr: a pointer to the destination header memory
262*4882a593Smuzhiyun * @bth0: bth0 passed in from the RC/UC builder
263*4882a593Smuzhiyun * @bth2: bth2 passed in from the RC/UC builder
264*4882a593Smuzhiyun * @middle: non zero implies indicates ahg "could" be used
265*4882a593Smuzhiyun * @ps: the current packet state
266*4882a593Smuzhiyun *
267*4882a593Smuzhiyun * This routine may disarm ahg under these situations:
268*4882a593Smuzhiyun * - packet needs a GRH
269*4882a593Smuzhiyun * - BECN needed
270*4882a593Smuzhiyun * - migration state not IB_MIG_MIGRATED
271*4882a593Smuzhiyun */
hfi1_make_ruc_header_16B(struct rvt_qp * qp,struct ib_other_headers * ohdr,u32 bth0,u32 bth1,u32 bth2,int middle,struct hfi1_pkt_state * ps)272*4882a593Smuzhiyun static inline void hfi1_make_ruc_header_16B(struct rvt_qp *qp,
273*4882a593Smuzhiyun struct ib_other_headers *ohdr,
274*4882a593Smuzhiyun u32 bth0, u32 bth1, u32 bth2,
275*4882a593Smuzhiyun int middle,
276*4882a593Smuzhiyun struct hfi1_pkt_state *ps)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun struct hfi1_qp_priv *priv = qp->priv;
279*4882a593Smuzhiyun struct hfi1_ibport *ibp = ps->ibp;
280*4882a593Smuzhiyun struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
281*4882a593Smuzhiyun u32 slid;
282*4882a593Smuzhiyun u16 pkey = hfi1_get_pkey(ibp, qp->s_pkey_index);
283*4882a593Smuzhiyun u8 l4 = OPA_16B_L4_IB_LOCAL;
284*4882a593Smuzhiyun u8 extra_bytes = hfi1_get_16b_padding(
285*4882a593Smuzhiyun (ps->s_txreq->hdr_dwords << 2),
286*4882a593Smuzhiyun ps->s_txreq->s_cur_size);
287*4882a593Smuzhiyun u32 nwords = SIZE_OF_CRC + ((ps->s_txreq->s_cur_size +
288*4882a593Smuzhiyun extra_bytes + SIZE_OF_LT) >> 2);
289*4882a593Smuzhiyun bool becn = false;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun if (unlikely(rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH) &&
292*4882a593Smuzhiyun hfi1_check_mcast(rdma_ah_get_dlid(&qp->remote_ah_attr))) {
293*4882a593Smuzhiyun struct ib_grh *grh;
294*4882a593Smuzhiyun struct ib_global_route *grd =
295*4882a593Smuzhiyun rdma_ah_retrieve_grh(&qp->remote_ah_attr);
296*4882a593Smuzhiyun /*
297*4882a593Smuzhiyun * Ensure OPA GIDs are transformed to IB gids
298*4882a593Smuzhiyun * before creating the GRH.
299*4882a593Smuzhiyun */
300*4882a593Smuzhiyun if (grd->sgid_index == OPA_GID_INDEX)
301*4882a593Smuzhiyun grd->sgid_index = 0;
302*4882a593Smuzhiyun grh = &ps->s_txreq->phdr.hdr.opah.u.l.grh;
303*4882a593Smuzhiyun l4 = OPA_16B_L4_IB_GLOBAL;
304*4882a593Smuzhiyun ps->s_txreq->hdr_dwords +=
305*4882a593Smuzhiyun hfi1_make_grh(ibp, grh, grd,
306*4882a593Smuzhiyun ps->s_txreq->hdr_dwords - LRH_16B_DWORDS,
307*4882a593Smuzhiyun nwords);
308*4882a593Smuzhiyun middle = 0;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun if (qp->s_mig_state == IB_MIG_MIGRATED)
312*4882a593Smuzhiyun bth1 |= OPA_BTH_MIG_REQ;
313*4882a593Smuzhiyun else
314*4882a593Smuzhiyun middle = 0;
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun if (qp->s_flags & RVT_S_ECN) {
317*4882a593Smuzhiyun qp->s_flags &= ~RVT_S_ECN;
318*4882a593Smuzhiyun /* we recently received a FECN, so return a BECN */
319*4882a593Smuzhiyun becn = true;
320*4882a593Smuzhiyun middle = 0;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun if (middle)
323*4882a593Smuzhiyun build_ahg(qp, bth2);
324*4882a593Smuzhiyun else
325*4882a593Smuzhiyun qp->s_flags &= ~HFI1_S_AHG_VALID;
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun bth0 |= pkey;
328*4882a593Smuzhiyun bth0 |= extra_bytes << 20;
329*4882a593Smuzhiyun hfi1_make_ruc_bth(qp, ohdr, bth0, bth1, bth2);
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun if (!ppd->lid)
332*4882a593Smuzhiyun slid = be32_to_cpu(OPA_LID_PERMISSIVE);
333*4882a593Smuzhiyun else
334*4882a593Smuzhiyun slid = ppd->lid |
335*4882a593Smuzhiyun (rdma_ah_get_path_bits(&qp->remote_ah_attr) &
336*4882a593Smuzhiyun ((1 << ppd->lmc) - 1));
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun hfi1_make_16b_hdr(&ps->s_txreq->phdr.hdr.opah,
339*4882a593Smuzhiyun slid,
340*4882a593Smuzhiyun opa_get_lid(rdma_ah_get_dlid(&qp->remote_ah_attr),
341*4882a593Smuzhiyun 16B),
342*4882a593Smuzhiyun (ps->s_txreq->hdr_dwords + nwords) >> 1,
343*4882a593Smuzhiyun pkey, becn, 0, l4, priv->s_sc);
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun /**
347*4882a593Smuzhiyun * hfi1_make_ruc_header_9B - build a 9B header
348*4882a593Smuzhiyun * @qp: the queue pair
349*4882a593Smuzhiyun * @ohdr: a pointer to the destination header memory
350*4882a593Smuzhiyun * @bth0: bth0 passed in from the RC/UC builder
351*4882a593Smuzhiyun * @bth2: bth2 passed in from the RC/UC builder
352*4882a593Smuzhiyun * @middle: non zero implies indicates ahg "could" be used
353*4882a593Smuzhiyun * @ps: the current packet state
354*4882a593Smuzhiyun *
355*4882a593Smuzhiyun * This routine may disarm ahg under these situations:
356*4882a593Smuzhiyun * - packet needs a GRH
357*4882a593Smuzhiyun * - BECN needed
358*4882a593Smuzhiyun * - migration state not IB_MIG_MIGRATED
359*4882a593Smuzhiyun */
hfi1_make_ruc_header_9B(struct rvt_qp * qp,struct ib_other_headers * ohdr,u32 bth0,u32 bth1,u32 bth2,int middle,struct hfi1_pkt_state * ps)360*4882a593Smuzhiyun static inline void hfi1_make_ruc_header_9B(struct rvt_qp *qp,
361*4882a593Smuzhiyun struct ib_other_headers *ohdr,
362*4882a593Smuzhiyun u32 bth0, u32 bth1, u32 bth2,
363*4882a593Smuzhiyun int middle,
364*4882a593Smuzhiyun struct hfi1_pkt_state *ps)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun struct hfi1_qp_priv *priv = qp->priv;
367*4882a593Smuzhiyun struct hfi1_ibport *ibp = ps->ibp;
368*4882a593Smuzhiyun u16 pkey = hfi1_get_pkey(ibp, qp->s_pkey_index);
369*4882a593Smuzhiyun u16 lrh0 = HFI1_LRH_BTH;
370*4882a593Smuzhiyun u8 extra_bytes = -ps->s_txreq->s_cur_size & 3;
371*4882a593Smuzhiyun u32 nwords = SIZE_OF_CRC + ((ps->s_txreq->s_cur_size +
372*4882a593Smuzhiyun extra_bytes) >> 2);
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun if (unlikely(rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH)) {
375*4882a593Smuzhiyun struct ib_grh *grh = &ps->s_txreq->phdr.hdr.ibh.u.l.grh;
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun lrh0 = HFI1_LRH_GRH;
378*4882a593Smuzhiyun ps->s_txreq->hdr_dwords +=
379*4882a593Smuzhiyun hfi1_make_grh(ibp, grh,
380*4882a593Smuzhiyun rdma_ah_read_grh(&qp->remote_ah_attr),
381*4882a593Smuzhiyun ps->s_txreq->hdr_dwords - LRH_9B_DWORDS,
382*4882a593Smuzhiyun nwords);
383*4882a593Smuzhiyun middle = 0;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun lrh0 |= (priv->s_sc & 0xf) << 12 |
386*4882a593Smuzhiyun (rdma_ah_get_sl(&qp->remote_ah_attr) & 0xf) << 4;
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun if (qp->s_mig_state == IB_MIG_MIGRATED)
389*4882a593Smuzhiyun bth0 |= IB_BTH_MIG_REQ;
390*4882a593Smuzhiyun else
391*4882a593Smuzhiyun middle = 0;
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun if (qp->s_flags & RVT_S_ECN) {
394*4882a593Smuzhiyun qp->s_flags &= ~RVT_S_ECN;
395*4882a593Smuzhiyun /* we recently received a FECN, so return a BECN */
396*4882a593Smuzhiyun bth1 |= (IB_BECN_MASK << IB_BECN_SHIFT);
397*4882a593Smuzhiyun middle = 0;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun if (middle)
400*4882a593Smuzhiyun build_ahg(qp, bth2);
401*4882a593Smuzhiyun else
402*4882a593Smuzhiyun qp->s_flags &= ~HFI1_S_AHG_VALID;
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun bth0 |= pkey;
405*4882a593Smuzhiyun bth0 |= extra_bytes << 20;
406*4882a593Smuzhiyun hfi1_make_ruc_bth(qp, ohdr, bth0, bth1, bth2);
407*4882a593Smuzhiyun hfi1_make_ib_hdr(&ps->s_txreq->phdr.hdr.ibh,
408*4882a593Smuzhiyun lrh0,
409*4882a593Smuzhiyun ps->s_txreq->hdr_dwords + nwords,
410*4882a593Smuzhiyun opa_get_lid(rdma_ah_get_dlid(&qp->remote_ah_attr), 9B),
411*4882a593Smuzhiyun ppd_from_ibp(ibp)->lid |
412*4882a593Smuzhiyun rdma_ah_get_path_bits(&qp->remote_ah_attr));
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun typedef void (*hfi1_make_ruc_hdr)(struct rvt_qp *qp,
416*4882a593Smuzhiyun struct ib_other_headers *ohdr,
417*4882a593Smuzhiyun u32 bth0, u32 bth1, u32 bth2, int middle,
418*4882a593Smuzhiyun struct hfi1_pkt_state *ps);
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun /* We support only two types - 9B and 16B for now */
421*4882a593Smuzhiyun static const hfi1_make_ruc_hdr hfi1_ruc_header_tbl[2] = {
422*4882a593Smuzhiyun [HFI1_PKT_TYPE_9B] = &hfi1_make_ruc_header_9B,
423*4882a593Smuzhiyun [HFI1_PKT_TYPE_16B] = &hfi1_make_ruc_header_16B
424*4882a593Smuzhiyun };
425*4882a593Smuzhiyun
hfi1_make_ruc_header(struct rvt_qp * qp,struct ib_other_headers * ohdr,u32 bth0,u32 bth1,u32 bth2,int middle,struct hfi1_pkt_state * ps)426*4882a593Smuzhiyun void hfi1_make_ruc_header(struct rvt_qp *qp, struct ib_other_headers *ohdr,
427*4882a593Smuzhiyun u32 bth0, u32 bth1, u32 bth2, int middle,
428*4882a593Smuzhiyun struct hfi1_pkt_state *ps)
429*4882a593Smuzhiyun {
430*4882a593Smuzhiyun struct hfi1_qp_priv *priv = qp->priv;
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun /*
433*4882a593Smuzhiyun * reset s_ahg/AHG fields
434*4882a593Smuzhiyun *
435*4882a593Smuzhiyun * This insures that the ahgentry/ahgcount
436*4882a593Smuzhiyun * are at a non-AHG default to protect
437*4882a593Smuzhiyun * build_verbs_tx_desc() from using
438*4882a593Smuzhiyun * an include ahgidx.
439*4882a593Smuzhiyun *
440*4882a593Smuzhiyun * build_ahg() will modify as appropriate
441*4882a593Smuzhiyun * to use the AHG feature.
442*4882a593Smuzhiyun */
443*4882a593Smuzhiyun priv->s_ahg->tx_flags = 0;
444*4882a593Smuzhiyun priv->s_ahg->ahgcount = 0;
445*4882a593Smuzhiyun priv->s_ahg->ahgidx = 0;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun /* Make the appropriate header */
448*4882a593Smuzhiyun hfi1_ruc_header_tbl[priv->hdr_type](qp, ohdr, bth0, bth1, bth2, middle,
449*4882a593Smuzhiyun ps);
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun /* when sending, force a reschedule every one of these periods */
453*4882a593Smuzhiyun #define SEND_RESCHED_TIMEOUT (5 * HZ) /* 5s in jiffies */
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun /**
456*4882a593Smuzhiyun * hfi1_schedule_send_yield - test for a yield required for QP
457*4882a593Smuzhiyun * send engine
458*4882a593Smuzhiyun * @timeout: Final time for timeout slice for jiffies
459*4882a593Smuzhiyun * @qp: a pointer to QP
460*4882a593Smuzhiyun * @ps: a pointer to a structure with commonly lookup values for
461*4882a593Smuzhiyun * the the send engine progress
462*4882a593Smuzhiyun * @tid - true if it is the tid leg
463*4882a593Smuzhiyun *
464*4882a593Smuzhiyun * This routine checks if the time slice for the QP has expired
465*4882a593Smuzhiyun * for RC QPs, if so an additional work entry is queued. At this
466*4882a593Smuzhiyun * point, other QPs have an opportunity to be scheduled. It
467*4882a593Smuzhiyun * returns true if a yield is required, otherwise, false
468*4882a593Smuzhiyun * is returned.
469*4882a593Smuzhiyun */
hfi1_schedule_send_yield(struct rvt_qp * qp,struct hfi1_pkt_state * ps,bool tid)470*4882a593Smuzhiyun bool hfi1_schedule_send_yield(struct rvt_qp *qp, struct hfi1_pkt_state *ps,
471*4882a593Smuzhiyun bool tid)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun ps->pkts_sent = true;
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun if (unlikely(time_after(jiffies, ps->timeout))) {
476*4882a593Smuzhiyun if (!ps->in_thread ||
477*4882a593Smuzhiyun workqueue_congested(ps->cpu, ps->ppd->hfi1_wq)) {
478*4882a593Smuzhiyun spin_lock_irqsave(&qp->s_lock, ps->flags);
479*4882a593Smuzhiyun if (!tid) {
480*4882a593Smuzhiyun qp->s_flags &= ~RVT_S_BUSY;
481*4882a593Smuzhiyun hfi1_schedule_send(qp);
482*4882a593Smuzhiyun } else {
483*4882a593Smuzhiyun struct hfi1_qp_priv *priv = qp->priv;
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun if (priv->s_flags &
486*4882a593Smuzhiyun HFI1_S_TID_BUSY_SET) {
487*4882a593Smuzhiyun qp->s_flags &= ~RVT_S_BUSY;
488*4882a593Smuzhiyun priv->s_flags &=
489*4882a593Smuzhiyun ~(HFI1_S_TID_BUSY_SET |
490*4882a593Smuzhiyun RVT_S_BUSY);
491*4882a593Smuzhiyun } else {
492*4882a593Smuzhiyun priv->s_flags &= ~RVT_S_BUSY;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun hfi1_schedule_tid_send(qp);
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun spin_unlock_irqrestore(&qp->s_lock, ps->flags);
498*4882a593Smuzhiyun this_cpu_inc(*ps->ppd->dd->send_schedule);
499*4882a593Smuzhiyun trace_hfi1_rc_expired_time_slice(qp, true);
500*4882a593Smuzhiyun return true;
501*4882a593Smuzhiyun }
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun cond_resched();
504*4882a593Smuzhiyun this_cpu_inc(*ps->ppd->dd->send_schedule);
505*4882a593Smuzhiyun ps->timeout = jiffies + ps->timeout_int;
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun trace_hfi1_rc_expired_time_slice(qp, false);
509*4882a593Smuzhiyun return false;
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun
hfi1_do_send_from_rvt(struct rvt_qp * qp)512*4882a593Smuzhiyun void hfi1_do_send_from_rvt(struct rvt_qp *qp)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun hfi1_do_send(qp, false);
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun
_hfi1_do_send(struct work_struct * work)517*4882a593Smuzhiyun void _hfi1_do_send(struct work_struct *work)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun struct iowait_work *w = container_of(work, struct iowait_work, iowork);
520*4882a593Smuzhiyun struct rvt_qp *qp = iowait_to_qp(w->iow);
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun hfi1_do_send(qp, true);
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun /**
526*4882a593Smuzhiyun * hfi1_do_send - perform a send on a QP
527*4882a593Smuzhiyun * @qp: a pointer to the QP
528*4882a593Smuzhiyun * @in_thread: true if in a workqueue thread
529*4882a593Smuzhiyun *
530*4882a593Smuzhiyun * Process entries in the send work queue until credit or queue is
531*4882a593Smuzhiyun * exhausted. Only allow one CPU to send a packet per QP.
532*4882a593Smuzhiyun * Otherwise, two threads could send packets out of order.
533*4882a593Smuzhiyun */
hfi1_do_send(struct rvt_qp * qp,bool in_thread)534*4882a593Smuzhiyun void hfi1_do_send(struct rvt_qp *qp, bool in_thread)
535*4882a593Smuzhiyun {
536*4882a593Smuzhiyun struct hfi1_pkt_state ps;
537*4882a593Smuzhiyun struct hfi1_qp_priv *priv = qp->priv;
538*4882a593Smuzhiyun int (*make_req)(struct rvt_qp *qp, struct hfi1_pkt_state *ps);
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun ps.dev = to_idev(qp->ibqp.device);
541*4882a593Smuzhiyun ps.ibp = to_iport(qp->ibqp.device, qp->port_num);
542*4882a593Smuzhiyun ps.ppd = ppd_from_ibp(ps.ibp);
543*4882a593Smuzhiyun ps.in_thread = in_thread;
544*4882a593Smuzhiyun ps.wait = iowait_get_ib_work(&priv->s_iowait);
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun trace_hfi1_rc_do_send(qp, in_thread);
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun switch (qp->ibqp.qp_type) {
549*4882a593Smuzhiyun case IB_QPT_RC:
550*4882a593Smuzhiyun if (!loopback && ((rdma_ah_get_dlid(&qp->remote_ah_attr) &
551*4882a593Smuzhiyun ~((1 << ps.ppd->lmc) - 1)) ==
552*4882a593Smuzhiyun ps.ppd->lid)) {
553*4882a593Smuzhiyun rvt_ruc_loopback(qp);
554*4882a593Smuzhiyun return;
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun make_req = hfi1_make_rc_req;
557*4882a593Smuzhiyun ps.timeout_int = qp->timeout_jiffies;
558*4882a593Smuzhiyun break;
559*4882a593Smuzhiyun case IB_QPT_UC:
560*4882a593Smuzhiyun if (!loopback && ((rdma_ah_get_dlid(&qp->remote_ah_attr) &
561*4882a593Smuzhiyun ~((1 << ps.ppd->lmc) - 1)) ==
562*4882a593Smuzhiyun ps.ppd->lid)) {
563*4882a593Smuzhiyun rvt_ruc_loopback(qp);
564*4882a593Smuzhiyun return;
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun make_req = hfi1_make_uc_req;
567*4882a593Smuzhiyun ps.timeout_int = SEND_RESCHED_TIMEOUT;
568*4882a593Smuzhiyun break;
569*4882a593Smuzhiyun default:
570*4882a593Smuzhiyun make_req = hfi1_make_ud_req;
571*4882a593Smuzhiyun ps.timeout_int = SEND_RESCHED_TIMEOUT;
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun spin_lock_irqsave(&qp->s_lock, ps.flags);
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun /* Return if we are already busy processing a work request. */
577*4882a593Smuzhiyun if (!hfi1_send_ok(qp)) {
578*4882a593Smuzhiyun if (qp->s_flags & HFI1_S_ANY_WAIT_IO)
579*4882a593Smuzhiyun iowait_set_flag(&priv->s_iowait, IOWAIT_PENDING_IB);
580*4882a593Smuzhiyun spin_unlock_irqrestore(&qp->s_lock, ps.flags);
581*4882a593Smuzhiyun return;
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun qp->s_flags |= RVT_S_BUSY;
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun ps.timeout_int = ps.timeout_int / 8;
587*4882a593Smuzhiyun ps.timeout = jiffies + ps.timeout_int;
588*4882a593Smuzhiyun ps.cpu = priv->s_sde ? priv->s_sde->cpu :
589*4882a593Smuzhiyun cpumask_first(cpumask_of_node(ps.ppd->dd->node));
590*4882a593Smuzhiyun ps.pkts_sent = false;
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun /* insure a pre-built packet is handled */
593*4882a593Smuzhiyun ps.s_txreq = get_waiting_verbs_txreq(ps.wait);
594*4882a593Smuzhiyun do {
595*4882a593Smuzhiyun /* Check for a constructed packet to be sent. */
596*4882a593Smuzhiyun if (ps.s_txreq) {
597*4882a593Smuzhiyun if (priv->s_flags & HFI1_S_TID_BUSY_SET)
598*4882a593Smuzhiyun qp->s_flags |= RVT_S_BUSY;
599*4882a593Smuzhiyun spin_unlock_irqrestore(&qp->s_lock, ps.flags);
600*4882a593Smuzhiyun /*
601*4882a593Smuzhiyun * If the packet cannot be sent now, return and
602*4882a593Smuzhiyun * the send engine will be woken up later.
603*4882a593Smuzhiyun */
604*4882a593Smuzhiyun if (hfi1_verbs_send(qp, &ps))
605*4882a593Smuzhiyun return;
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun /* allow other tasks to run */
608*4882a593Smuzhiyun if (hfi1_schedule_send_yield(qp, &ps, false))
609*4882a593Smuzhiyun return;
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun spin_lock_irqsave(&qp->s_lock, ps.flags);
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun } while (make_req(qp, &ps));
614*4882a593Smuzhiyun iowait_starve_clear(ps.pkts_sent, &priv->s_iowait);
615*4882a593Smuzhiyun spin_unlock_irqrestore(&qp->s_lock, ps.flags);
616*4882a593Smuzhiyun }
617