Skip to content

Commit 72c07e2

Browse files
Don Hiattdledford
authored andcommitted
IB/hfi1: Add support to receive 16B bypass packets
We introduce a struct hfi1_16b_header to support 16B headers. 16B bypass packets are received by the driver and processed similar to 9B packets. Add basic support to handle 16B packets. 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 13c1922 commit 72c07e2

File tree

12 files changed

+274
-51
lines changed

12 files changed

+274
-51
lines changed

drivers/infiniband/hw/hfi1/chip.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14468,6 +14468,7 @@ void hfi1_deinit_vnic_rsm(struct hfi1_devdata *dd)
1446814468
static void init_rxe(struct hfi1_devdata *dd)
1446914469
{
1447014470
struct rsm_map_table *rmt;
14471+
u64 val;
1447114472

1447214473
/* enable all receive errors */
1447314474
write_csr(dd, RCV_ERR_MASK, ~0ull);
@@ -14492,6 +14493,11 @@ static void init_rxe(struct hfi1_devdata *dd)
1449214493
* (64 bytes). Max_Payload_Size is possibly modified upward in
1449314494
* tune_pcie_caps() which is called after this routine.
1449414495
*/
14496+
14497+
/* Have 16 bytes (4DW) of bypass header available in header queue */
14498+
val = read_csr(dd, RCV_BYPASS);
14499+
val |= (4ull << 16);
14500+
write_csr(dd, RCV_BYPASS, val);
1449514501
}
1449614502

1449714503
static void init_other(struct hfi1_devdata *dd)

drivers/infiniband/hw/hfi1/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ struct diag_pkt {
327327
/* misc. */
328328
#define SC15_PACKET 0xF
329329
#define SIZE_OF_CRC 1
330+
#define SIZE_OF_LT 1
330331

331332
#define LIM_MGMT_P_KEY 0x7FFF
332333
#define FULL_MGMT_P_KEY 0xFFFF

drivers/infiniband/hw/hfi1/driver.c

Lines changed: 112 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,13 @@ static inline struct ib_header *hfi1_get_msgheader(struct hfi1_devdata *dd,
237237
return (struct ib_header *)hfi1_get_header(dd, rhf_addr);
238238
}
239239

240+
static inline struct hfi1_16b_header
241+
*hfi1_get_16B_header(struct hfi1_devdata *dd,
242+
__le32 *rhf_addr)
243+
{
244+
return (struct hfi1_16b_header *)hfi1_get_header(dd, rhf_addr);
245+
}
246+
240247
/*
241248
* Validate and encode the a given RcvArray Buffer size.
242249
* The function will check whether the given size falls within
@@ -925,6 +932,11 @@ static inline int set_armed_to_active(struct hfi1_ctxtdata *rcd,
925932
struct ib_header *hdr = hfi1_get_msgheader(packet->rcd->dd,
926933
packet->rhf_addr);
927934
sc = hfi1_9B_get_sc5(hdr, packet->rhf);
935+
} else if (etype == RHF_RCV_TYPE_BYPASS) {
936+
struct hfi1_16b_header *hdr = hfi1_get_16B_header(
937+
packet->rcd->dd,
938+
packet->rhf_addr);
939+
sc = hfi1_16B_get_sc(hdr);
928940
}
929941
if (sc != SC15_PACKET) {
930942
int hwstate = driver_lstate(rcd->ppd);
@@ -1386,9 +1398,14 @@ static int hfi1_setup_9B_packet(struct hfi1_packet *packet)
13861398
}
13871399

13881400
/* Query commonly used fields from packet header */
1401+
packet->payload = packet->ebuf;
13891402
packet->opcode = ib_bth_get_opcode(packet->ohdr);
13901403
packet->slid = ib_get_slid(hdr);
13911404
packet->dlid = ib_get_dlid(hdr);
1405+
if (unlikely((packet->dlid >= be16_to_cpu(IB_MULTICAST_LID_BASE)) &&
1406+
(packet->dlid != be16_to_cpu(IB_LID_PERMISSIVE))))
1407+
packet->dlid += opa_get_mcast_base(OPA_MCAST_NR) -
1408+
be16_to_cpu(IB_MULTICAST_LID_BASE);
13921409
packet->sl = ib_get_sl(hdr);
13931410
packet->sc = hfi1_9B_get_sc5(hdr, packet->rhf);
13941411
packet->pad = ib_bth_get_pad(packet->ohdr);
@@ -1402,6 +1419,73 @@ static int hfi1_setup_9B_packet(struct hfi1_packet *packet)
14021419
return -EINVAL;
14031420
}
14041421

1422+
static int hfi1_setup_bypass_packet(struct hfi1_packet *packet)
1423+
{
1424+
/*
1425+
* Bypass packets have a different header/payload split
1426+
* compared to an IB packet.
1427+
* Current split is set such that 16 bytes of the actual
1428+
* header is in the header buffer and the remining is in
1429+
* the eager buffer. We chose 16 since hfi1 driver only
1430+
* supports 16B bypass packets and we will be able to
1431+
* receive the entire LRH with such a split.
1432+
*/
1433+
1434+
struct hfi1_ctxtdata *rcd = packet->rcd;
1435+
struct hfi1_pportdata *ppd = rcd->ppd;
1436+
struct hfi1_ibport *ibp = &ppd->ibport_data;
1437+
u8 l4;
1438+
u8 grh_len;
1439+
1440+
packet->hdr = (struct hfi1_16b_header *)
1441+
hfi1_get_16B_header(packet->rcd->dd,
1442+
packet->rhf_addr);
1443+
packet->hlen = (u8 *)packet->rhf_addr - (u8 *)packet->hdr;
1444+
1445+
l4 = hfi1_16B_get_l4(packet->hdr);
1446+
if (l4 == OPA_16B_L4_IB_LOCAL) {
1447+
grh_len = 0;
1448+
packet->ohdr = packet->ebuf;
1449+
packet->grh = NULL;
1450+
} else if (l4 == OPA_16B_L4_IB_GLOBAL) {
1451+
u32 vtf;
1452+
1453+
grh_len = sizeof(struct ib_grh);
1454+
packet->ohdr = packet->ebuf + grh_len;
1455+
packet->grh = packet->ebuf;
1456+
if (packet->grh->next_hdr != IB_GRH_NEXT_HDR)
1457+
goto drop;
1458+
vtf = be32_to_cpu(packet->grh->version_tclass_flow);
1459+
if ((vtf >> IB_GRH_VERSION_SHIFT) != IB_GRH_VERSION)
1460+
goto drop;
1461+
} else {
1462+
goto drop;
1463+
}
1464+
1465+
/* Query commonly used fields from packet header */
1466+
packet->opcode = ib_bth_get_opcode(packet->ohdr);
1467+
packet->hlen = hdr_len_by_opcode[packet->opcode] + 8 + grh_len;
1468+
packet->payload = packet->ebuf + packet->hlen - (4 * sizeof(u32));
1469+
packet->slid = hfi1_16B_get_slid(packet->hdr);
1470+
packet->dlid = hfi1_16B_get_dlid(packet->hdr);
1471+
if (unlikely(hfi1_is_16B_mcast(packet->dlid)))
1472+
packet->dlid += opa_get_mcast_base(OPA_MCAST_NR) -
1473+
opa_get_lid(opa_get_mcast_base(OPA_MCAST_NR),
1474+
16B);
1475+
packet->sc = hfi1_16B_get_sc(packet->hdr);
1476+
packet->sl = ibp->sc_to_sl[packet->sc];
1477+
packet->pad = hfi1_16B_bth_get_pad(packet->ohdr);
1478+
packet->extra_byte = SIZE_OF_LT;
1479+
packet->fecn = hfi1_16B_get_fecn(packet->hdr);
1480+
packet->becn = hfi1_16B_get_becn(packet->hdr);
1481+
1482+
return 0;
1483+
drop:
1484+
hfi1_cdbg(PKT, "%s: packet dropped\n", __func__);
1485+
ibp->rvp.n_pkt_drops++;
1486+
return -EINVAL;
1487+
}
1488+
14051489
void handle_eflags(struct hfi1_packet *packet)
14061490
{
14071491
struct hfi1_ctxtdata *rcd = packet->rcd;
@@ -1464,8 +1548,8 @@ static inline bool hfi1_is_vnic_packet(struct hfi1_packet *packet)
14641548
if (packet->rcd->is_vnic)
14651549
return true;
14661550

1467-
if ((HFI1_GET_L2_TYPE(packet->ebuf) == OPA_VNIC_L2_TYPE) &&
1468-
(HFI1_GET_L4_TYPE(packet->ebuf) == OPA_VNIC_L4_ETHR))
1551+
if ((hfi1_16B_get_l2(packet->ebuf) == OPA_16B_L2_TYPE) &&
1552+
(hfi1_16B_get_l4(packet->ebuf) == OPA_16B_L4_ETHR))
14691553
return true;
14701554

14711555
return false;
@@ -1475,25 +1559,38 @@ int process_receive_bypass(struct hfi1_packet *packet)
14751559
{
14761560
struct hfi1_devdata *dd = packet->rcd->dd;
14771561

1478-
if (unlikely(rhf_err_flags(packet->rhf))) {
1479-
handle_eflags(packet);
1480-
} else if (hfi1_is_vnic_packet(packet)) {
1562+
if (hfi1_is_vnic_packet(packet)) {
14811563
hfi1_vnic_bypass_rcv(packet);
14821564
return RHF_RCV_CONTINUE;
14831565
}
14841566

1485-
dd_dev_err(dd, "Unsupported bypass packet. Dropping\n");
1486-
incr_cntr64(&dd->sw_rcv_bypass_packet_errors);
1487-
if (!(dd->err_info_rcvport.status_and_code & OPA_EI_STATUS_SMASK)) {
1488-
u64 *flits = packet->ebuf;
1567+
if (hfi1_setup_bypass_packet(packet))
1568+
return RHF_RCV_CONTINUE;
1569+
1570+
if (unlikely(rhf_err_flags(packet->rhf))) {
1571+
handle_eflags(packet);
1572+
return RHF_RCV_CONTINUE;
1573+
}
14891574

1490-
if (flits && !(packet->rhf & RHF_LEN_ERR)) {
1491-
dd->err_info_rcvport.packet_flit1 = flits[0];
1492-
dd->err_info_rcvport.packet_flit2 =
1493-
packet->tlen > sizeof(flits[0]) ? flits[1] : 0;
1575+
if (hfi1_16B_get_l2(packet->hdr) == 0x2) {
1576+
hfi1_16B_rcv(packet);
1577+
} else {
1578+
dd_dev_err(dd,
1579+
"Bypass packets other than 16B are not supported in normal operation. Dropping\n");
1580+
incr_cntr64(&dd->sw_rcv_bypass_packet_errors);
1581+
if (!(dd->err_info_rcvport.status_and_code &
1582+
OPA_EI_STATUS_SMASK)) {
1583+
u64 *flits = packet->ebuf;
1584+
1585+
if (flits && !(packet->rhf & RHF_LEN_ERR)) {
1586+
dd->err_info_rcvport.packet_flit1 = flits[0];
1587+
dd->err_info_rcvport.packet_flit2 =
1588+
packet->tlen > sizeof(flits[0]) ?
1589+
flits[1] : 0;
1590+
}
1591+
dd->err_info_rcvport.status_and_code |=
1592+
(OPA_EI_STATUS_SMASK | BAD_L2_ERR);
14941593
}
1495-
dd->err_info_rcvport.status_and_code |=
1496-
(OPA_EI_STATUS_SMASK | BAD_L2_ERR);
14971594
}
14981595
return RHF_RCV_CONTINUE;
14991596
}

drivers/infiniband/hw/hfi1/hfi.h

Lines changed: 127 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
#include <linux/i2c.h>
6767
#include <linux/i2c-algo-bit.h>
6868
#include <rdma/ib_hdrs.h>
69+
#include <rdma/opa_addr.h>
6970
#include <linux/rhashtable.h>
7071
#include <linux/netdevice.h>
7172
#include <rdma/rdma_vt.h>
@@ -325,6 +326,7 @@ struct hfi1_ctxtdata {
325326
struct hfi1_packet {
326327
void *ebuf;
327328
void *hdr;
329+
void *payload;
328330
struct hfi1_ctxtdata *rcd;
329331
__le32 *rhf_addr;
330332
struct rvt_qp *qp;
@@ -351,6 +353,83 @@ struct hfi1_packet {
351353
bool fecn;
352354
};
353355

356+
/*
357+
* OPA 16B Header
358+
*/
359+
#define OPA_16B_L4_MASK 0xFFull
360+
#define OPA_16B_SC_MASK 0x1F00000ull
361+
#define OPA_16B_SC_SHIFT 20
362+
#define OPA_16B_LID_MASK 0xFFFFFull
363+
#define OPA_16B_DLID_MASK 0xF000ull
364+
#define OPA_16B_DLID_SHIFT 20
365+
#define OPA_16B_DLID_HIGH_SHIFT 12
366+
#define OPA_16B_SLID_MASK 0xF00ull
367+
#define OPA_16B_SLID_SHIFT 20
368+
#define OPA_16B_SLID_HIGH_SHIFT 8
369+
#define OPA_16B_BECN_MASK 0x80000000ull
370+
#define OPA_16B_BECN_SHIFT 31
371+
#define OPA_16B_FECN_MASK 0x10000000ull
372+
#define OPA_16B_FECN_SHIFT 28
373+
#define OPA_16B_L2_MASK 0x60000000ull
374+
#define OPA_16B_L2_SHIFT 29
375+
376+
/*
377+
* OPA 16B L2/L4 Encodings
378+
*/
379+
#define OPA_16B_L2_TYPE 0x02
380+
#define OPA_16B_L4_IB_LOCAL 0x09
381+
#define OPA_16B_L4_IB_GLOBAL 0x0A
382+
#define OPA_16B_L4_ETHR OPA_VNIC_L4_ETHR
383+
384+
static inline u8 hfi1_16B_get_l4(struct hfi1_16b_header *hdr)
385+
{
386+
return (u8)(hdr->lrh[2] & OPA_16B_L4_MASK);
387+
}
388+
389+
static inline u8 hfi1_16B_get_sc(struct hfi1_16b_header *hdr)
390+
{
391+
return (u8)((hdr->lrh[1] & OPA_16B_SC_MASK) >> OPA_16B_SC_SHIFT);
392+
}
393+
394+
static inline u32 hfi1_16B_get_dlid(struct hfi1_16b_header *hdr)
395+
{
396+
return (u32)((hdr->lrh[1] & OPA_16B_LID_MASK) |
397+
(((hdr->lrh[2] & OPA_16B_DLID_MASK) >>
398+
OPA_16B_DLID_HIGH_SHIFT) << OPA_16B_DLID_SHIFT));
399+
}
400+
401+
static inline u32 hfi1_16B_get_slid(struct hfi1_16b_header *hdr)
402+
{
403+
return (u32)((hdr->lrh[0] & OPA_16B_LID_MASK) |
404+
(((hdr->lrh[2] & OPA_16B_SLID_MASK) >>
405+
OPA_16B_SLID_HIGH_SHIFT) << OPA_16B_SLID_SHIFT));
406+
}
407+
408+
static inline u8 hfi1_16B_get_becn(struct hfi1_16b_header *hdr)
409+
{
410+
return (u8)((hdr->lrh[0] & OPA_16B_BECN_MASK) >> OPA_16B_BECN_SHIFT);
411+
}
412+
413+
static inline u8 hfi1_16B_get_fecn(struct hfi1_16b_header *hdr)
414+
{
415+
return (u8)((hdr->lrh[1] & OPA_16B_FECN_MASK) >> OPA_16B_FECN_SHIFT);
416+
}
417+
418+
static inline u8 hfi1_16B_get_l2(struct hfi1_16b_header *hdr)
419+
{
420+
return (u8)((hdr->lrh[1] & OPA_16B_L2_MASK) >> OPA_16B_L2_SHIFT);
421+
}
422+
423+
/*
424+
* BTH
425+
*/
426+
#define OPA_16B_BTH_PAD_MASK 7
427+
static inline u8 hfi1_16B_bth_get_pad(struct ib_other_headers *ohdr)
428+
{
429+
return (u8)((be32_to_cpu(ohdr->bth[0]) >> IB_BTH_PAD_SHIFT) &
430+
OPA_16B_BTH_PAD_MASK);
431+
}
432+
354433
struct rvt_sge_state;
355434

356435
/*
@@ -2084,11 +2163,55 @@ int hfi1_tempsense_rd(struct hfi1_devdata *dd, struct hfi1_temp *temp);
20842163

20852164
/*
20862165
* hfi1_check_mcast- Check if the given lid is
2087-
* in the IB multicast range.
2166+
* in the OPA multicast range.
2167+
*
2168+
* The LID might either reside in ah.dlid or might be
2169+
* in the GRH of the address handle as DGID if extended
2170+
* addresses are in use.
20882171
*/
2089-
static inline bool hfi1_check_mcast(u16 lid)
2172+
static inline bool hfi1_check_mcast(u32 lid)
2173+
{
2174+
return ((lid >= opa_get_mcast_base(OPA_MCAST_NR)) &&
2175+
(lid != be32_to_cpu(OPA_LID_PERMISSIVE)));
2176+
}
2177+
2178+
#define opa_get_lid(lid, format) \
2179+
__opa_get_lid(lid, OPA_PORT_PACKET_FORMAT_##format)
2180+
2181+
/* Convert a lid to a specific lid space */
2182+
static inline u32 __opa_get_lid(u32 lid, u8 format)
2183+
{
2184+
bool is_mcast = hfi1_check_mcast(lid);
2185+
2186+
switch (format) {
2187+
case OPA_PORT_PACKET_FORMAT_8B:
2188+
case OPA_PORT_PACKET_FORMAT_10B:
2189+
if (is_mcast)
2190+
return (lid - opa_get_mcast_base(OPA_MCAST_NR) +
2191+
0xF0000);
2192+
return lid & 0xFFFFF;
2193+
case OPA_PORT_PACKET_FORMAT_16B:
2194+
if (is_mcast)
2195+
return (lid - opa_get_mcast_base(OPA_MCAST_NR) +
2196+
0xF00000);
2197+
return lid & 0xFFFFFF;
2198+
case OPA_PORT_PACKET_FORMAT_9B:
2199+
if (is_mcast)
2200+
return (lid -
2201+
opa_get_mcast_base(OPA_MCAST_NR) +
2202+
be16_to_cpu(IB_MULTICAST_LID_BASE));
2203+
else
2204+
return lid & 0xFFFF;
2205+
default:
2206+
return lid;
2207+
}
2208+
}
2209+
2210+
/* Return true if the given lid is the OPA 16B multicast range */
2211+
static inline bool hfi1_is_16B_mcast(u32 lid)
20902212
{
2091-
return ((lid >= be16_to_cpu(IB_MULTICAST_LID_BASE)) &&
2092-
(lid != be16_to_cpu(IB_LID_PERMISSIVE)));
2213+
return ((lid >=
2214+
opa_get_lid(opa_get_mcast_base(OPA_MCAST_NR), 16B)) &&
2215+
(lid != opa_get_lid(be32_to_cpu(OPA_LID_PERMISSIVE), 16B)));
20932216
}
20942217
#endif /* _HFI1_KERNEL_H */

drivers/infiniband/hw/hfi1/rc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1916,7 +1916,7 @@ void process_becn(struct hfi1_pportdata *ppd, u8 sl, u16 rlid, u32 lqpn,
19161916
void hfi1_rc_rcv(struct hfi1_packet *packet)
19171917
{
19181918
struct hfi1_ctxtdata *rcd = packet->rcd;
1919-
void *data = packet->ebuf;
1919+
void *data = packet->payload;
19201920
u32 tlen = packet->tlen;
19211921
struct rvt_qp *qp = packet->qp;
19221922
struct hfi1_ibport *ibp = rcd_to_iport(rcd);

drivers/infiniband/hw/hfi1/uc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
297297
void hfi1_uc_rcv(struct hfi1_packet *packet)
298298
{
299299
struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd);
300-
void *data = packet->ebuf;
300+
void *data = packet->payload;
301301
u32 tlen = packet->tlen;
302302
struct rvt_qp *qp = packet->qp;
303303
struct ib_other_headers *ohdr = packet->ohdr;

0 commit comments

Comments
 (0)