提交 977940b8 编写于 作者: A Arthur Kepner 提交者: Greg Kroah-Hartman

staging/rdma/hfi1: optionally prescan rx queue for {B, F}ECNs - UC, RC

To more rapidly respond to Explicit Congestion Notifications, prescan the
receive queue, and process FECNs, and BECNs first.  When a UC, or RC packet
containing a FECN, or BECN is found, immediately react to the ECN (either by
returning a CNP, or adjusting the injection rate). Afterward, the packet will
be processed normally.
Reviewed-by: NMike Marciniszyn <mike.marciniszyn@intel.com>
Reviewed-by: NDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: NArthur Kepner <arthur.kepner@intel.com>
Signed-off-by: NIra Weiny <ira.weiny@intel.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 3e7ccca0
...@@ -436,59 +436,58 @@ static inline void init_packet(struct hfi1_ctxtdata *rcd, ...@@ -436,59 +436,58 @@ static inline void init_packet(struct hfi1_ctxtdata *rcd,
#ifndef CONFIG_PRESCAN_RXQ #ifndef CONFIG_PRESCAN_RXQ
static void prescan_rxq(struct hfi1_packet *packet) {} static void prescan_rxq(struct hfi1_packet *packet) {}
#else /* CONFIG_PRESCAN_RXQ */ #else /* !CONFIG_PRESCAN_RXQ */
static int prescan_receive_queue; static int prescan_receive_queue;
static void process_ecn(struct hfi1_qp *qp, struct hfi1_ib_header *hdr, static void process_ecn(struct hfi1_qp *qp, struct hfi1_ib_header *hdr,
struct hfi1_other_headers *ohdr, struct hfi1_other_headers *ohdr,
u64 rhf, struct ib_grh *grh) u64 rhf, u32 bth1, struct ib_grh *grh)
{ {
struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num); struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
u32 bth1; u32 rqpn = 0;
u16 rlid;
u8 sc5, svc_type; u8 sc5, svc_type;
int is_fecn, is_becn;
switch (qp->ibqp.qp_type) { switch (qp->ibqp.qp_type) {
case IB_QPT_SMI:
case IB_QPT_GSI:
case IB_QPT_UD: case IB_QPT_UD:
rlid = be16_to_cpu(hdr->lrh[3]);
rqpn = be32_to_cpu(ohdr->u.ud.deth[1]) & HFI1_QPN_MASK;
svc_type = IB_CC_SVCTYPE_UD; svc_type = IB_CC_SVCTYPE_UD;
break; break;
case IB_QPT_UC: /* LATER */ case IB_QPT_UC:
case IB_QPT_RC: /* LATER */ rlid = qp->remote_ah_attr.dlid;
rqpn = qp->remote_qpn;
svc_type = IB_CC_SVCTYPE_UC;
break;
case IB_QPT_RC:
rlid = qp->remote_ah_attr.dlid;
rqpn = qp->remote_qpn;
svc_type = IB_CC_SVCTYPE_RC;
break;
default: default:
return; return;
} }
is_fecn = (be32_to_cpu(ohdr->bth[1]) >> HFI1_FECN_SHIFT) &
HFI1_FECN_MASK;
is_becn = (be32_to_cpu(ohdr->bth[1]) >> HFI1_BECN_SHIFT) &
HFI1_BECN_MASK;
sc5 = (be16_to_cpu(hdr->lrh[0]) >> 12) & 0xf; sc5 = (be16_to_cpu(hdr->lrh[0]) >> 12) & 0xf;
if (rhf_dc_info(rhf)) if (rhf_dc_info(rhf))
sc5 |= 0x10; sc5 |= 0x10;
if (is_fecn) { if (bth1 & HFI1_FECN_SMASK) {
u32 src_qpn = be32_to_cpu(ohdr->u.ud.deth[1]) & HFI1_QPN_MASK;
u16 pkey = (u16)be32_to_cpu(ohdr->bth[0]); u16 pkey = (u16)be32_to_cpu(ohdr->bth[0]);
u16 dlid = be16_to_cpu(hdr->lrh[1]); u16 dlid = be16_to_cpu(hdr->lrh[1]);
u16 slid = be16_to_cpu(hdr->lrh[3]);
return_cnp(ibp, qp, src_qpn, pkey, dlid, slid, sc5, grh); return_cnp(ibp, qp, rqpn, pkey, dlid, rlid, sc5, grh);
} }
if (is_becn) { if (bth1 & HFI1_BECN_SMASK) {
struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
u32 lqpn = be32_to_cpu(ohdr->bth[1]) & HFI1_QPN_MASK; u32 lqpn = bth1 & HFI1_QPN_MASK;
u8 sl = ibp->sc_to_sl[sc5]; u8 sl = ibp->sc_to_sl[sc5];
process_becn(ppd, sl, 0, lqpn, 0, svc_type); process_becn(ppd, sl, rlid, lqpn, rqpn, svc_type);
} }
/* turn off BECN, or FECN */
bth1 = be32_to_cpu(ohdr->bth[1]);
bth1 &= ~(HFI1_FECN_MASK << HFI1_FECN_SHIFT);
bth1 &= ~(HFI1_BECN_MASK << HFI1_BECN_SHIFT);
ohdr->bth[1] = cpu_to_be32(bth1);
} }
struct ps_mdata { struct ps_mdata {
...@@ -508,7 +507,6 @@ static inline void init_ps_mdata(struct ps_mdata *mdata, ...@@ -508,7 +507,6 @@ static inline void init_ps_mdata(struct ps_mdata *mdata,
mdata->rcd = rcd; mdata->rcd = rcd;
mdata->rsize = packet->rsize; mdata->rsize = packet->rsize;
mdata->maxcnt = packet->maxcnt; mdata->maxcnt = packet->maxcnt;
mdata->ps_head = packet->rhqoff; mdata->ps_head = packet->rhqoff;
if (HFI1_CAP_IS_KSET(DMA_RTAIL)) { if (HFI1_CAP_IS_KSET(DMA_RTAIL)) {
...@@ -564,7 +562,7 @@ static void prescan_rxq(struct hfi1_packet *packet) ...@@ -564,7 +562,7 @@ static void prescan_rxq(struct hfi1_packet *packet)
struct hfi1_other_headers *ohdr; struct hfi1_other_headers *ohdr;
struct ib_grh *grh = NULL; struct ib_grh *grh = NULL;
u64 rhf = rhf_to_cpu(rhf_addr); u64 rhf = rhf_to_cpu(rhf_addr);
u32 etype = rhf_rcv_type(rhf), qpn; u32 etype = rhf_rcv_type(rhf), qpn, bth1;
int is_ecn = 0; int is_ecn = 0;
u8 lnh; u8 lnh;
...@@ -586,15 +584,13 @@ static void prescan_rxq(struct hfi1_packet *packet) ...@@ -586,15 +584,13 @@ static void prescan_rxq(struct hfi1_packet *packet)
} else } else
goto next; /* just in case */ goto next; /* just in case */
is_ecn |= be32_to_cpu(ohdr->bth[1]) & bth1 = be32_to_cpu(ohdr->bth[1]);
(HFI1_FECN_MASK << HFI1_FECN_SHIFT); is_ecn = !!(bth1 & (HFI1_FECN_SMASK | HFI1_BECN_SMASK));
is_ecn |= be32_to_cpu(ohdr->bth[1]) &
(HFI1_BECN_MASK << HFI1_BECN_SHIFT);
if (!is_ecn) if (!is_ecn)
goto next; goto next;
qpn = be32_to_cpu(ohdr->bth[1]) & HFI1_QPN_MASK; qpn = bth1 & HFI1_QPN_MASK;
rcu_read_lock(); rcu_read_lock();
qp = hfi1_lookup_qpn(ibp, qpn); qp = hfi1_lookup_qpn(ibp, qpn);
...@@ -603,8 +599,12 @@ static void prescan_rxq(struct hfi1_packet *packet) ...@@ -603,8 +599,12 @@ static void prescan_rxq(struct hfi1_packet *packet)
goto next; goto next;
} }
process_ecn(qp, hdr, ohdr, rhf, grh); process_ecn(qp, hdr, ohdr, rhf, bth1, grh);
rcu_read_unlock(); rcu_read_unlock();
/* turn off BECN, FECN */
bth1 &= ~(HFI1_FECN_SMASK | HFI1_BECN_SMASK);
ohdr->bth[1] = cpu_to_be32(bth1);
next: next:
update_ps_mdata(&mdata); update_ps_mdata(&mdata);
} }
......
...@@ -1978,7 +1978,7 @@ void hfi1_rc_rcv(struct hfi1_packet *packet) ...@@ -1978,7 +1978,7 @@ void hfi1_rc_rcv(struct hfi1_packet *packet)
} }
psn = be32_to_cpu(ohdr->bth[2]); psn = be32_to_cpu(ohdr->bth[2]);
opcode = bth0 >> 24; opcode = (bth0 >> 24) & 0xff;
/* /*
* Process responses (ACKs) before anything else. Note that the * Process responses (ACKs) before anything else. Note that the
...@@ -2391,19 +2391,19 @@ void hfi1_rc_hdrerr( ...@@ -2391,19 +2391,19 @@ void hfi1_rc_hdrerr(
struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num); struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
int diff; int diff;
u32 opcode; u32 opcode;
u32 psn; u32 psn, bth0;
/* Check for GRH */ /* Check for GRH */
ohdr = &hdr->u.oth; ohdr = &hdr->u.oth;
if (has_grh) if (has_grh)
ohdr = &hdr->u.l.oth; ohdr = &hdr->u.l.oth;
opcode = be32_to_cpu(ohdr->bth[0]); bth0 = be32_to_cpu(ohdr->bth[0]);
if (hfi1_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode)) if (hfi1_ruc_check_hdr(ibp, hdr, has_grh, qp, bth0))
return; return;
psn = be32_to_cpu(ohdr->bth[2]); psn = be32_to_cpu(ohdr->bth[2]);
opcode >>= 24; opcode = (bth0 >> 24) & 0xff;
/* Only deal with RDMA Writes for now */ /* Only deal with RDMA Writes for now */
if (opcode < IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST) { if (opcode < IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST) {
......
...@@ -268,7 +268,7 @@ void hfi1_uc_rcv(struct hfi1_packet *packet) ...@@ -268,7 +268,7 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
u32 tlen = packet->tlen; u32 tlen = packet->tlen;
struct hfi1_qp *qp = packet->qp; struct hfi1_qp *qp = packet->qp;
struct hfi1_other_headers *ohdr = packet->ohdr; struct hfi1_other_headers *ohdr = packet->ohdr;
u32 opcode; u32 bth0, opcode;
u32 hdrsize = packet->hlen; u32 hdrsize = packet->hlen;
u32 psn; u32 psn;
u32 pad; u32 pad;
...@@ -278,10 +278,9 @@ void hfi1_uc_rcv(struct hfi1_packet *packet) ...@@ -278,10 +278,9 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
int has_grh = rcv_flags & HFI1_HAS_GRH; int has_grh = rcv_flags & HFI1_HAS_GRH;
int ret; int ret;
u32 bth1; u32 bth1;
struct ib_grh *grh = NULL;
opcode = be32_to_cpu(ohdr->bth[0]); bth0 = be32_to_cpu(ohdr->bth[0]);
if (hfi1_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode)) if (hfi1_ruc_check_hdr(ibp, hdr, has_grh, qp, bth0))
return; return;
bth1 = be32_to_cpu(ohdr->bth[1]); bth1 = be32_to_cpu(ohdr->bth[1]);
...@@ -303,6 +302,7 @@ void hfi1_uc_rcv(struct hfi1_packet *packet) ...@@ -303,6 +302,7 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
} }
if (bth1 & HFI1_FECN_SMASK) { if (bth1 & HFI1_FECN_SMASK) {
struct ib_grh *grh = NULL;
u16 pkey = (u16)be32_to_cpu(ohdr->bth[0]); u16 pkey = (u16)be32_to_cpu(ohdr->bth[0]);
u16 slid = be16_to_cpu(hdr->lrh[3]); u16 slid = be16_to_cpu(hdr->lrh[3]);
u16 dlid = be16_to_cpu(hdr->lrh[1]); u16 dlid = be16_to_cpu(hdr->lrh[1]);
...@@ -310,13 +310,16 @@ void hfi1_uc_rcv(struct hfi1_packet *packet) ...@@ -310,13 +310,16 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
u8 sc5; u8 sc5;
sc5 = ibp->sl_to_sc[qp->remote_ah_attr.sl]; sc5 = ibp->sl_to_sc[qp->remote_ah_attr.sl];
if (has_grh)
grh = &hdr->u.l.grh;
return_cnp(ibp, qp, src_qp, pkey, dlid, slid, sc5, grh); return_cnp(ibp, qp, src_qp, pkey, dlid, slid, sc5,
grh);
} }
} }
psn = be32_to_cpu(ohdr->bth[2]); psn = be32_to_cpu(ohdr->bth[2]);
opcode >>= 24; opcode = (bth0 >> 24) & 0xff;
/* Compare the PSN verses the expected PSN. */ /* Compare the PSN verses the expected PSN. */
if (unlikely(cmp_psn(psn, qp->r_psn) != 0)) { if (unlikely(cmp_psn(psn, qp->r_psn) != 0)) {
......
...@@ -2152,11 +2152,40 @@ void hfi1_schedule_send(struct hfi1_qp *qp) ...@@ -2152,11 +2152,40 @@ void hfi1_schedule_send(struct hfi1_qp *qp)
void hfi1_cnp_rcv(struct hfi1_packet *packet) void hfi1_cnp_rcv(struct hfi1_packet *packet)
{ {
struct hfi1_ibport *ibp = &packet->rcd->ppd->ibport_data; struct hfi1_ibport *ibp = &packet->rcd->ppd->ibport_data;
struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
if (packet->qp->ibqp.qp_type == IB_QPT_UC) struct hfi1_ib_header *hdr = packet->hdr;
hfi1_uc_rcv(packet); struct hfi1_qp *qp = packet->qp;
else if (packet->qp->ibqp.qp_type == IB_QPT_UD) u32 lqpn, rqpn = 0;
hfi1_ud_rcv(packet); u16 rlid = 0;
else u8 sl, sc5, sc4_bit, svc_type;
bool sc4_set = has_sc4_bit(packet);
switch (packet->qp->ibqp.qp_type) {
case IB_QPT_UC:
rlid = qp->remote_ah_attr.dlid;
rqpn = qp->remote_qpn;
svc_type = IB_CC_SVCTYPE_UC;
break;
case IB_QPT_RC:
rlid = qp->remote_ah_attr.dlid;
rqpn = qp->remote_qpn;
svc_type = IB_CC_SVCTYPE_RC;
break;
case IB_QPT_SMI:
case IB_QPT_GSI:
case IB_QPT_UD:
svc_type = IB_CC_SVCTYPE_UD;
break;
default:
ibp->n_pkt_drops++; ibp->n_pkt_drops++;
return;
}
sc4_bit = sc4_set << 4;
sc5 = (be16_to_cpu(hdr->lrh[0]) >> 12) & 0xf;
sc5 |= sc4_bit;
sl = ibp->sc_to_sl[sc5];
lqpn = qp->ibqp.qp_num;
process_becn(ppd, sl, rlid, lqpn, rqpn, svc_type);
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册