Skip to content

Commit 5786adf

Browse files
Don Hiattdledford
authored andcommitted
IB/hfi1: Add support to process 16B header errors
Enhance hdr_rcverr() to also handle errors during 16B bypass packet receive. Reviewed-by: Dennis Dalessandro <[email protected]> Signed-off-by: Don Hiatt <[email protected]> Signed-off-by: Dennis Dalessandro <[email protected]> Signed-off-by: Doug Ledford <[email protected]>
1 parent 30e0741 commit 5786adf

File tree

6 files changed

+112
-33
lines changed

6 files changed

+112
-33
lines changed

drivers/infiniband/hw/hfi1/driver.c

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -269,38 +269,42 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
269269
{
270270
struct ib_header *rhdr = packet->hdr;
271271
u32 rte = rhf_rcv_type_err(packet->rhf);
272-
u8 lnh = ib_get_lnh(rhdr);
273-
bool has_grh = false;
272+
u32 mlid_base;
274273
struct hfi1_ibport *ibp = rcd_to_iport(rcd);
275274
struct hfi1_devdata *dd = ppd->dd;
276275
struct rvt_dev_info *rdi = &dd->verbs_dev.rdi;
277276

278277
if (packet->rhf & (RHF_VCRC_ERR | RHF_ICRC_ERR))
279278
return;
280279

281-
if (lnh == HFI1_LRH_BTH) {
282-
packet->ohdr = &rhdr->u.oth;
283-
} else if (lnh == HFI1_LRH_GRH) {
284-
has_grh = true;
285-
packet->ohdr = &rhdr->u.l.oth;
286-
packet->grh = &rhdr->u.l.grh;
287-
} else {
280+
if (packet->etype == RHF_RCV_TYPE_BYPASS) {
288281
goto drop;
282+
} else {
283+
u8 lnh = ib_get_lnh(rhdr);
284+
285+
mlid_base = be16_to_cpu(IB_MULTICAST_LID_BASE);
286+
if (lnh == HFI1_LRH_BTH) {
287+
packet->ohdr = &rhdr->u.oth;
288+
} else if (lnh == HFI1_LRH_GRH) {
289+
packet->ohdr = &rhdr->u.l.oth;
290+
packet->grh = &rhdr->u.l.grh;
291+
} else {
292+
goto drop;
293+
}
289294
}
290295

291296
if (packet->rhf & RHF_TID_ERR) {
292297
/* For TIDERR and RC QPs preemptively schedule a NAK */
293298
u32 tlen = rhf_pkt_len(packet->rhf); /* in bytes */
294299
u32 dlid = ib_get_dlid(rhdr);
295300
u32 qp_num;
296-
u32 mlid_base = be16_to_cpu(IB_MULTICAST_LID_BASE);
297301

298302
/* Sanity check packet */
299303
if (tlen < 24)
300304
goto drop;
301305

302306
/* Check for GRH */
303-
if (has_grh) {
307+
if (packet->grh) {
304308
u32 vtf;
305309
struct ib_grh *grh = packet->grh;
306310

@@ -1370,6 +1374,35 @@ static inline void hfi1_setup_ib_header(struct hfi1_packet *packet)
13701374
packet->hlen = (u8 *)packet->rhf_addr - (u8 *)packet->hdr;
13711375
}
13721376

1377+
static int hfi1_bypass_ingress_pkt_check(struct hfi1_packet *packet)
1378+
{
1379+
struct hfi1_pportdata *ppd = packet->rcd->ppd;
1380+
1381+
/* slid and dlid cannot be 0 */
1382+
if ((!packet->slid) || (!packet->dlid))
1383+
return -EINVAL;
1384+
1385+
/* Compare port lid with incoming packet dlid */
1386+
if ((!(hfi1_is_16B_mcast(packet->dlid))) &&
1387+
(packet->dlid !=
1388+
opa_get_lid(be32_to_cpu(OPA_LID_PERMISSIVE), 16B))) {
1389+
if (packet->dlid != ppd->lid)
1390+
return -EINVAL;
1391+
}
1392+
1393+
/* No multicast packets with SC15 */
1394+
if ((hfi1_is_16B_mcast(packet->dlid)) && (packet->sc == 0xF))
1395+
return -EINVAL;
1396+
1397+
/* Packets with permissive DLID always on SC15 */
1398+
if ((packet->dlid == opa_get_lid(be32_to_cpu(OPA_LID_PERMISSIVE),
1399+
16B)) &&
1400+
(packet->sc != 0xF))
1401+
return -EINVAL;
1402+
1403+
return 0;
1404+
}
1405+
13731406
static int hfi1_setup_9B_packet(struct hfi1_packet *packet)
13741407
{
13751408
struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd);
@@ -1479,6 +1512,9 @@ static int hfi1_setup_bypass_packet(struct hfi1_packet *packet)
14791512
packet->fecn = hfi1_16B_get_fecn(packet->hdr);
14801513
packet->becn = hfi1_16B_get_becn(packet->hdr);
14811514

1515+
if (hfi1_bypass_ingress_pkt_check(packet))
1516+
goto drop;
1517+
14821518
return 0;
14831519
drop:
14841520
hfi1_cdbg(PKT, "%s: packet dropped\n", __func__);

drivers/infiniband/hw/hfi1/hfi.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,10 @@ struct hfi1_packet {
372372
#define OPA_16B_FECN_SHIFT 28
373373
#define OPA_16B_L2_MASK 0x60000000ull
374374
#define OPA_16B_L2_SHIFT 29
375+
#define OPA_16B_PKEY_MASK 0xFFFF0000ull
376+
#define OPA_16B_PKEY_SHIFT 16
377+
#define OPA_16B_LEN_MASK 0x7FF00000ull
378+
#define OPA_16B_LEN_SHIFT 20
375379

376380
/*
377381
* OPA 16B L2/L4 Encodings
@@ -420,6 +424,11 @@ static inline u8 hfi1_16B_get_l2(struct hfi1_16b_header *hdr)
420424
return (u8)((hdr->lrh[1] & OPA_16B_L2_MASK) >> OPA_16B_L2_SHIFT);
421425
}
422426

427+
static inline u16 hfi1_16B_get_pkey(struct hfi1_16b_header *hdr)
428+
{
429+
return (u16)((hdr->lrh[2] & OPA_16B_PKEY_MASK) >> OPA_16B_PKEY_SHIFT);
430+
}
431+
423432
/*
424433
* BTH
425434
*/
@@ -1597,9 +1606,9 @@ static void ingress_pkey_table_fail(struct hfi1_pportdata *ppd, u16 pkey,
15971606
* by HW and rcv_pkey_check function should be called instead.
15981607
*/
15991608
static inline int ingress_pkey_check(struct hfi1_pportdata *ppd, u16 pkey,
1600-
u8 sc5, u8 idx, u16 slid)
1609+
u8 sc5, u8 idx, u32 slid, bool force)
16011610
{
1602-
if (!(ppd->part_enforce & HFI1_PART_ENFORCE_IN))
1611+
if (!(force) && !(ppd->part_enforce & HFI1_PART_ENFORCE_IN))
16031612
return 0;
16041613

16051614
/* If SC15, pkey[0:14] must be 0x7fff */

drivers/infiniband/hw/hfi1/ruc.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -227,15 +227,23 @@ int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet)
227227
u32 sl = packet->sl;
228228
int migrated;
229229
u32 bth0, bth1;
230+
u16 pkey;
230231

231232
bth0 = be32_to_cpu(packet->ohdr->bth[0]);
232233
bth1 = be32_to_cpu(packet->ohdr->bth[1]);
233-
migrated = bth0 & IB_BTH_MIG_REQ;
234+
if (packet->etype == RHF_RCV_TYPE_BYPASS) {
235+
pkey = hfi1_16B_get_pkey(packet->hdr);
236+
migrated = bth1 & OPA_BTH_MIG_REQ;
237+
} else {
238+
pkey = ib_bth_get_pkey(packet->ohdr);
239+
migrated = bth0 & IB_BTH_MIG_REQ;
240+
}
234241

235242
if (qp->s_mig_state == IB_MIG_ARMED && migrated) {
236243
if (!packet->grh) {
237-
if (rdma_ah_get_ah_flags(&qp->alt_ah_attr) &
238-
IB_AH_GRH)
244+
if ((rdma_ah_get_ah_flags(&qp->alt_ah_attr) &
245+
IB_AH_GRH) &&
246+
(packet->etype != RHF_RCV_TYPE_BYPASS))
239247
return 1;
240248
} else {
241249
const struct ib_global_route *grh;
@@ -254,10 +262,10 @@ int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet)
254262
grh->dgid.global.interface_id))
255263
return 1;
256264
}
257-
if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), (u16)bth0,
265+
if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), pkey,
258266
sc5, slid))) {
259-
hfi1_bad_pkey(ibp, (u16)bth0, sl,
260-
0, qp->ibqp.qp_num, slid, dlid);
267+
hfi1_bad_pkey(ibp, pkey, sl, 0, qp->ibqp.qp_num,
268+
slid, dlid);
261269
return 1;
262270
}
263271
/* Validate the SLID. See Ch. 9.6.1.5 and 17.2.8 */
@@ -270,8 +278,9 @@ int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet)
270278
spin_unlock_irqrestore(&qp->s_lock, flags);
271279
} else {
272280
if (!packet->grh) {
273-
if (rdma_ah_get_ah_flags(&qp->remote_ah_attr) &
274-
IB_AH_GRH)
281+
if ((rdma_ah_get_ah_flags(&qp->remote_ah_attr) &
282+
IB_AH_GRH) &&
283+
(packet->etype != RHF_RCV_TYPE_BYPASS))
275284
return 1;
276285
} else {
277286
const struct ib_global_route *grh;
@@ -290,10 +299,10 @@ int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet)
290299
grh->dgid.global.interface_id))
291300
return 1;
292301
}
293-
if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), (u16)bth0,
302+
if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), pkey,
294303
sc5, slid))) {
295-
hfi1_bad_pkey(ibp, (u16)bth0, sl,
296-
0, qp->ibqp.qp_num, slid, dlid);
304+
hfi1_bad_pkey(ibp, pkey, sl, 0, qp->ibqp.qp_num,
305+
slid, dlid);
297306
return 1;
298307
}
299308
/* Validate the SLID. See Ch. 9.6.1.5 */

drivers/infiniband/hw/hfi1/ud.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ static void ud_loopback(struct rvt_qp *sqp, struct rvt_swqe *swqe)
109109
slid = ppd->lid | (rdma_ah_get_path_bits(ah_attr) &
110110
((1 << ppd->lmc) - 1));
111111
if (unlikely(ingress_pkey_check(ppd, pkey, sc5,
112-
qp->s_pkey_index, slid))) {
112+
qp->s_pkey_index,
113+
slid, false))) {
113114
hfi1_bad_pkey(ibp, pkey,
114115
rdma_ah_get_sl(ah_attr),
115116
sqp->ibqp.qp_num, qp->ibqp.qp_num,

drivers/infiniband/hw/hfi1/verbs.c

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,24 @@ static u64 hfi1_fault_tx(struct rvt_qp *qp, u8 opcode, u64 pbc)
568568
return pbc;
569569
}
570570

571+
static int hfi1_do_pkey_check(struct hfi1_packet *packet)
572+
{
573+
struct hfi1_ctxtdata *rcd = packet->rcd;
574+
struct hfi1_pportdata *ppd = rcd->ppd;
575+
struct hfi1_16b_header *hdr = packet->hdr;
576+
u16 pkey;
577+
578+
/* Pkey check needed only for bypass packets */
579+
if (packet->etype != RHF_RCV_TYPE_BYPASS)
580+
return 0;
581+
582+
/* Perform pkey check */
583+
pkey = hfi1_16B_get_pkey(hdr);
584+
return ingress_pkey_check(ppd, pkey, packet->sc,
585+
packet->qp->s_pkey_index,
586+
packet->slid, true);
587+
}
588+
571589
static inline void hfi1_handle_packet(struct hfi1_packet *packet,
572590
bool is_mcast)
573591
{
@@ -594,6 +612,8 @@ static inline void hfi1_handle_packet(struct hfi1_packet *packet,
594612
goto drop;
595613
list_for_each_entry_rcu(p, &mcast->qp_list, list) {
596614
packet->qp = p->qp;
615+
if (hfi1_do_pkey_check(packet))
616+
goto drop;
597617
spin_lock_irqsave(&packet->qp->r_lock, flags);
598618
packet_handler = qp_ok(packet);
599619
if (likely(packet_handler))
@@ -613,15 +633,16 @@ static inline void hfi1_handle_packet(struct hfi1_packet *packet,
613633
qp_num = ib_bth_get_qpn(packet->ohdr);
614634
rcu_read_lock();
615635
packet->qp = rvt_lookup_qpn(rdi, &ibp->rvp, qp_num);
616-
if (!packet->qp) {
617-
rcu_read_unlock();
618-
goto drop;
619-
}
636+
if (!packet->qp)
637+
goto unlock_drop;
638+
639+
if (hfi1_do_pkey_check(packet))
640+
goto unlock_drop;
641+
620642
if (unlikely(hfi1_dbg_fault_opcode(packet->qp, packet->opcode,
621-
true))) {
622-
rcu_read_unlock();
623-
goto drop;
624-
}
643+
true)))
644+
goto unlock_drop;
645+
625646
spin_lock_irqsave(&packet->qp->r_lock, flags);
626647
packet_handler = qp_ok(packet);
627648
if (likely(packet_handler))
@@ -632,6 +653,8 @@ static inline void hfi1_handle_packet(struct hfi1_packet *packet,
632653
rcu_read_unlock();
633654
}
634655
return;
656+
unlock_drop:
657+
rcu_read_unlock();
635658
drop:
636659
ibp->rvp.n_pkt_drops++;
637660
}

drivers/infiniband/hw/hfi1/verbs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ struct hfi1_packet;
9595
#define HFI1_VENDOR_IPG cpu_to_be16(0xFFA0)
9696

9797
#define IB_DEFAULT_GID_PREFIX cpu_to_be64(0xfe80000000000000ULL)
98+
#define OPA_BTH_MIG_REQ BIT(31)
9899

99100
#define RC_OP(x) IB_OPCODE_RC_##x
100101
#define UC_OP(x) IB_OPCODE_UC_##x

0 commit comments

Comments
 (0)