IB/hfi1: Fix handling of FECN marked multicast packet
authorMike Marciniszyn <mike.marciniszyn@intel.com>
Tue, 1 May 2018 12:35:36 +0000 (05:35 -0700)
committerDoug Ledford <dledford@redhat.com>
Thu, 3 May 2018 19:24:44 +0000 (15:24 -0400)
The code for handling a marked UD packet unconditionally returns the
dlid in the header of the FECN marked packet.  This is not correct
for multicast packets where the DLID is in the multicast range.

The subsequent attempt to send the CNP with the multicast lid will
cause the chip to halt the ack send context because the source
lid doesn't match the chip programming.   The send context will
be halted and flush any other pending packets in the pio ring causing
the CNP to not be sent.

A part of investigating the fix, it was determined that the 16B work
broke the FECN routine badly with inconsistent use of 16 bit and 32 bits
types for lids and pkeys.  Since the port's source lid was correctly 32
bits the type mixmatches need to be dealt with at the same time as
fixing the CNP header issue.

Fix these issues by:
- Using the ports lid for as the SLID for responding to FECN marked UD
  packets
- Insure pkey is always 16 bit in this and subordinate routines
- Insure lids are 32 bits in this and subordinate routines

Cc: <stable@vger.kernel.org> # 4.14.x
Fixes: 88733e3b8450 ("IB/hfi1: Add 16B UD support")
Reviewed-by: Don Hiatt <don.hiatt@intel.com>
Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/hfi1/driver.c
drivers/infiniband/hw/hfi1/hfi.h
drivers/infiniband/hw/hfi1/ud.c

index 46d1475b2154fc22485ad1eb0052b1feb3cf54b3..bd837a048bf49602c5659b32932f583f71f8b2d4 100644 (file)
@@ -433,31 +433,43 @@ void hfi1_process_ecn_slowpath(struct rvt_qp *qp, struct hfi1_packet *pkt,
                               bool do_cnp)
 {
        struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
+       struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
        struct ib_other_headers *ohdr = pkt->ohdr;
        struct ib_grh *grh = pkt->grh;
        u32 rqpn = 0, bth1;
-       u16 pkey, rlid, dlid = ib_get_dlid(pkt->hdr);
+       u16 pkey;
+       u32 rlid, slid, dlid = 0;
        u8 hdr_type, sc, svc_type;
        bool is_mcast = false;
 
+       /* can be called from prescan */
        if (pkt->etype == RHF_RCV_TYPE_BYPASS) {
                is_mcast = hfi1_is_16B_mcast(dlid);
                pkey = hfi1_16B_get_pkey(pkt->hdr);
                sc = hfi1_16B_get_sc(pkt->hdr);
+               dlid = hfi1_16B_get_dlid(pkt->hdr);
+               slid = hfi1_16B_get_slid(pkt->hdr);
                hdr_type = HFI1_PKT_TYPE_16B;
        } else {
                is_mcast = (dlid > be16_to_cpu(IB_MULTICAST_LID_BASE)) &&
                           (dlid != be16_to_cpu(IB_LID_PERMISSIVE));
                pkey = ib_bth_get_pkey(ohdr);
                sc = hfi1_9B_get_sc5(pkt->hdr, pkt->rhf);
+               dlid = ib_get_dlid(pkt->hdr);
+               slid = ib_get_slid(pkt->hdr);
                hdr_type = HFI1_PKT_TYPE_9B;
        }
 
        switch (qp->ibqp.qp_type) {
+       case IB_QPT_UD:
+               dlid = ppd->lid;
+               rlid = slid;
+               rqpn = ib_get_sqpn(pkt->ohdr);
+               svc_type = IB_CC_SVCTYPE_UD;
+               break;
        case IB_QPT_SMI:
        case IB_QPT_GSI:
-       case IB_QPT_UD:
-               rlid = ib_get_slid(pkt->hdr);
+               rlid = slid;
                rqpn = ib_get_sqpn(pkt->ohdr);
                svc_type = IB_CC_SVCTYPE_UD;
                break;
@@ -482,7 +494,6 @@ void hfi1_process_ecn_slowpath(struct rvt_qp *qp, struct hfi1_packet *pkt,
                                              dlid, rlid, sc, grh);
 
        if (!is_mcast && (bth1 & IB_BECN_SMASK)) {
-               struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
                u32 lqpn = bth1 & RVT_QPN_MASK;
                u8 sl = ibp->sc_to_sl[sc];
 
index 32c48265405ea42bdb6440f8a80832aacc290dec..cac2c62bc42d6d496c307e66dd4ac6c7f0ada16e 100644 (file)
@@ -1537,13 +1537,13 @@ void set_link_ipg(struct hfi1_pportdata *ppd);
 void process_becn(struct hfi1_pportdata *ppd, u8 sl, u32 rlid, u32 lqpn,
                  u32 rqpn, u8 svc_type);
 void return_cnp(struct hfi1_ibport *ibp, struct rvt_qp *qp, u32 remote_qpn,
-               u32 pkey, u32 slid, u32 dlid, u8 sc5,
+               u16 pkey, u32 slid, u32 dlid, u8 sc5,
                const struct ib_grh *old_grh);
 void return_cnp_16B(struct hfi1_ibport *ibp, struct rvt_qp *qp,
-                   u32 remote_qpn, u32 pkey, u32 slid, u32 dlid,
+                   u32 remote_qpn, u16 pkey, u32 slid, u32 dlid,
                    u8 sc5, const struct ib_grh *old_grh);
 typedef void (*hfi1_handle_cnp)(struct hfi1_ibport *ibp, struct rvt_qp *qp,
-                               u32 remote_qpn, u32 pkey, u32 slid, u32 dlid,
+                               u32 remote_qpn, u16 pkey, u32 slid, u32 dlid,
                                u8 sc5, const struct ib_grh *old_grh);
 
 #define PKEY_CHECK_INVALID -1
@@ -2437,7 +2437,7 @@ static inline void hfi1_make_16b_hdr(struct hfi1_16b_header *hdr,
                ((slid >> OPA_16B_SLID_SHIFT) << OPA_16B_SLID_HIGH_SHIFT);
        lrh2 = (lrh2 & ~OPA_16B_DLID_MASK) |
                ((dlid >> OPA_16B_DLID_SHIFT) << OPA_16B_DLID_HIGH_SHIFT);
-       lrh2 = (lrh2 & ~OPA_16B_PKEY_MASK) | (pkey << OPA_16B_PKEY_SHIFT);
+       lrh2 = (lrh2 & ~OPA_16B_PKEY_MASK) | ((u32)pkey << OPA_16B_PKEY_SHIFT);
        lrh2 = (lrh2 & ~OPA_16B_L4_MASK) | l4;
 
        hdr->lrh[0] = lrh0;
index bcf3b0bebac8b69cb0fd77dd42c08fe86df2526d..69c17a5ef03871b73c0810fd3945f2111ac56e4f 100644 (file)
@@ -628,7 +628,7 @@ int hfi1_lookup_pkey_idx(struct hfi1_ibport *ibp, u16 pkey)
 }
 
 void return_cnp_16B(struct hfi1_ibport *ibp, struct rvt_qp *qp,
-                   u32 remote_qpn, u32 pkey, u32 slid, u32 dlid,
+                   u32 remote_qpn, u16 pkey, u32 slid, u32 dlid,
                    u8 sc5, const struct ib_grh *old_grh)
 {
        u64 pbc, pbc_flags = 0;
@@ -687,7 +687,7 @@ void return_cnp_16B(struct hfi1_ibport *ibp, struct rvt_qp *qp,
 }
 
 void return_cnp(struct hfi1_ibport *ibp, struct rvt_qp *qp, u32 remote_qpn,
-               u32 pkey, u32 slid, u32 dlid, u8 sc5,
+               u16 pkey, u32 slid, u32 dlid, u8 sc5,
                const struct ib_grh *old_grh)
 {
        u64 pbc, pbc_flags = 0;