Commit 5b6cabb0 authored by Don Hiatt's avatar Don Hiatt Committed by Doug Ledford

IB/hfi1: Add 16B RC/UC support

Add 16B bypass packet support for RC/UC traffic types.
Reviewed-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarDon Hiatt <don.hiatt@intel.com>
Signed-off-by: default avatarDasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com>
Signed-off-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 51e658f5
...@@ -459,6 +459,8 @@ static inline u16 hfi1_16B_get_entropy(struct hfi1_16b_header *hdr) ...@@ -459,6 +459,8 @@ static inline u16 hfi1_16B_get_entropy(struct hfi1_16b_header *hdr)
return (u16)(hdr->lrh[3] & OPA_16B_ENTROPY_MASK); return (u16)(hdr->lrh[3] & OPA_16B_ENTROPY_MASK);
} }
#define OPA_16B_MAKE_QW(low_dw, high_dw) (((u64)(high_dw) << 32) | (low_dw))
/* /*
* BTH * BTH
*/ */
...@@ -1538,7 +1540,7 @@ static inline u32 egress_cycles(u32 len, u32 rate) ...@@ -1538,7 +1540,7 @@ static inline u32 egress_cycles(u32 len, u32 rate)
} }
void set_link_ipg(struct hfi1_pportdata *ppd); void set_link_ipg(struct hfi1_pportdata *ppd);
void process_becn(struct hfi1_pportdata *ppd, u8 sl, u16 rlid, u32 lqpn, void process_becn(struct hfi1_pportdata *ppd, u8 sl, u32 rlid, u32 lqpn,
u32 rqpn, u8 svc_type); u32 rqpn, u8 svc_type);
void return_cnp(struct hfi1_ibport *ibp, struct rvt_qp *qp, u32 remote_qpn, void return_cnp(struct hfi1_ibport *ibp, struct rvt_qp *qp, u32 remote_qpn,
u32 pkey, u32 slid, u32 dlid, u8 sc5, u32 pkey, u32 slid, u32 dlid, u8 sc5,
......
This diff is collapsed.
...@@ -735,73 +735,186 @@ static inline void build_ahg(struct rvt_qp *qp, u32 npsn) ...@@ -735,73 +735,186 @@ static inline void build_ahg(struct rvt_qp *qp, u32 npsn)
} }
} }
void hfi1_make_ruc_header(struct rvt_qp *qp, struct ib_other_headers *ohdr, static inline void hfi1_make_ruc_bth(struct rvt_qp *qp,
struct ib_other_headers *ohdr,
u32 bth0, u32 bth1, u32 bth2)
{
bth1 |= qp->remote_qpn;
ohdr->bth[0] = cpu_to_be32(bth0);
ohdr->bth[1] = cpu_to_be32(bth1);
ohdr->bth[2] = cpu_to_be32(bth2);
}
static inline void hfi1_make_ruc_header_16B(struct rvt_qp *qp,
struct ib_other_headers *ohdr,
u32 bth0, u32 bth2, int middle, u32 bth0, u32 bth2, int middle,
struct hfi1_pkt_state *ps) struct hfi1_pkt_state *ps)
{ {
struct hfi1_qp_priv *priv = qp->priv; struct hfi1_qp_priv *priv = qp->priv;
struct hfi1_ibport *ibp = ps->ibp; struct hfi1_ibport *ibp = ps->ibp;
u16 lrh0; struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
u32 nwords; u32 bth1 = 0;
u32 extra_bytes; u32 slid;
u32 bth1; u16 pkey = hfi1_get_pkey(ibp, qp->s_pkey_index);
u8 l4 = OPA_16B_L4_IB_LOCAL;
/* Construct the header. */ u8 extra_bytes = hfi1_get_16b_padding((qp->s_hdrwords << 2),
extra_bytes = -ps->s_txreq->s_cur_size & 3; ps->s_txreq->s_cur_size);
nwords = (ps->s_txreq->s_cur_size + extra_bytes) >> 2; u32 nwords = SIZE_OF_CRC + ((ps->s_txreq->s_cur_size +
lrh0 = HFI1_LRH_BTH; extra_bytes + SIZE_OF_LT) >> 2);
u8 becn = 0;
if (unlikely(rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH) &&
hfi1_check_mcast(rdma_ah_get_dlid(&qp->remote_ah_attr))) {
struct ib_grh *grh;
struct ib_global_route *grd =
rdma_ah_retrieve_grh(&qp->remote_ah_attr);
int hdrwords;
/*
* Ensure OPA GIDs are transformed to IB gids
* before creating the GRH.
*/
if (grd->sgid_index == OPA_GID_INDEX)
grd->sgid_index = 0;
grh = &ps->s_txreq->phdr.hdr.opah.u.l.grh;
l4 = OPA_16B_L4_IB_GLOBAL;
hdrwords = qp->s_hdrwords - 4;
qp->s_hdrwords += hfi1_make_grh(ibp, grh, grd,
hdrwords, nwords);
middle = 0;
}
if (qp->s_mig_state == IB_MIG_MIGRATED)
bth1 |= OPA_BTH_MIG_REQ;
else
middle = 0;
if (middle)
build_ahg(qp, bth2);
else
qp->s_flags &= ~RVT_S_AHG_VALID;
bth0 |= pkey;
bth0 |= extra_bytes << 20;
if (qp->s_flags & RVT_S_ECN) {
qp->s_flags &= ~RVT_S_ECN;
/* we recently received a FECN, so return a BECN */
becn = 1;
}
hfi1_make_ruc_bth(qp, ohdr, bth0, bth1, bth2);
if (!ppd->lid)
slid = be32_to_cpu(OPA_LID_PERMISSIVE);
else
slid = ppd->lid |
(rdma_ah_get_path_bits(&qp->remote_ah_attr) &
((1 << ppd->lmc) - 1));
hfi1_make_16b_hdr(&ps->s_txreq->phdr.hdr.opah,
slid,
opa_get_lid(rdma_ah_get_dlid(&qp->remote_ah_attr),
16B),
(qp->s_hdrwords + nwords) >> 1,
pkey, becn, 0, l4, priv->s_sc);
}
static inline void hfi1_make_ruc_header_9B(struct rvt_qp *qp,
struct ib_other_headers *ohdr,
u32 bth0, u32 bth2, int middle,
struct hfi1_pkt_state *ps)
{
struct hfi1_qp_priv *priv = qp->priv;
struct hfi1_ibport *ibp = ps->ibp;
struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
u32 bth1 = 0;
u16 pkey = hfi1_get_pkey(ibp, qp->s_pkey_index);
u16 lrh0 = HFI1_LRH_BTH;
u16 slid;
u8 extra_bytes = -ps->s_txreq->s_cur_size & 3;
u32 nwords = SIZE_OF_CRC + ((ps->s_txreq->s_cur_size +
extra_bytes) >> 2);
if (unlikely(rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH)) { if (unlikely(rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH)) {
qp->s_hdrwords += struct ib_grh *grh = &ps->s_txreq->phdr.hdr.ibh.u.l.grh;
hfi1_make_grh(ibp, int hdrwords = qp->s_hdrwords - 2;
&ps->s_txreq->phdr.hdr.ibh.u.l.grh,
&qp->remote_ah_attr.grh,
qp->s_hdrwords, nwords);
lrh0 = HFI1_LRH_GRH; lrh0 = HFI1_LRH_GRH;
qp->s_hdrwords +=
hfi1_make_grh(ibp, grh,
rdma_ah_read_grh(&qp->remote_ah_attr),
hdrwords, nwords);
middle = 0; middle = 0;
} }
lrh0 |= (priv->s_sc & 0xf) << 12 | lrh0 |= (priv->s_sc & 0xf) << 12 |
(rdma_ah_get_sl(&qp->remote_ah_attr) & 0xf) << 4; (rdma_ah_get_sl(&qp->remote_ah_attr) & 0xf) << 4;
/*
* reset s_ahg/AHG fields
*
* This insures that the ahgentry/ahgcount
* are at a non-AHG default to protect
* build_verbs_tx_desc() from using
* an include ahgidx.
*
* build_ahg() will modify as appropriate
* to use the AHG feature.
*/
priv->s_ahg->tx_flags = 0;
priv->s_ahg->ahgcount = 0;
priv->s_ahg->ahgidx = 0;
if (qp->s_mig_state == IB_MIG_MIGRATED) if (qp->s_mig_state == IB_MIG_MIGRATED)
bth0 |= IB_BTH_MIG_REQ; bth0 |= IB_BTH_MIG_REQ;
else else
middle = 0; middle = 0;
if (middle) if (middle)
build_ahg(qp, bth2); build_ahg(qp, bth2);
else else
qp->s_flags &= ~RVT_S_AHG_VALID; qp->s_flags &= ~RVT_S_AHG_VALID;
ps->s_txreq->phdr.hdr.ibh.lrh[0] = cpu_to_be16(lrh0);
ps->s_txreq->phdr.hdr.ibh.lrh[1] = bth0 |= pkey;
cpu_to_be16(rdma_ah_get_dlid(&qp->remote_ah_attr));
ps->s_txreq->phdr.hdr.ibh.lrh[2] =
cpu_to_be16(qp->s_hdrwords + nwords + SIZE_OF_CRC);
ps->s_txreq->phdr.hdr.ibh.lrh[3] =
cpu_to_be16(ppd_from_ibp(ibp)->lid |
rdma_ah_get_path_bits(&qp->remote_ah_attr));
bth0 |= hfi1_get_pkey(ibp, qp->s_pkey_index);
bth0 |= extra_bytes << 20; bth0 |= extra_bytes << 20;
ohdr->bth[0] = cpu_to_be32(bth0);
bth1 = qp->remote_qpn;
if (qp->s_flags & RVT_S_ECN) { if (qp->s_flags & RVT_S_ECN) {
qp->s_flags &= ~RVT_S_ECN; qp->s_flags &= ~RVT_S_ECN;
/* we recently received a FECN, so return a BECN */ /* we recently received a FECN, so return a BECN */
bth1 |= (IB_BECN_MASK << IB_BECN_SHIFT); bth1 |= (IB_BECN_MASK << IB_BECN_SHIFT);
} }
ohdr->bth[1] = cpu_to_be32(bth1); hfi1_make_ruc_bth(qp, ohdr, bth0, bth1, bth2);
ohdr->bth[2] = cpu_to_be32(bth2);
if (!ppd->lid)
slid = be16_to_cpu(IB_LID_PERMISSIVE);
else
slid = ppd->lid |
(rdma_ah_get_path_bits(&qp->remote_ah_attr) &
((1 << ppd->lmc) - 1));
hfi1_make_ib_hdr(&ps->s_txreq->phdr.hdr.ibh,
lrh0,
qp->s_hdrwords + nwords,
opa_get_lid(rdma_ah_get_dlid(&qp->remote_ah_attr), 9B),
ppd_from_ibp(ibp)->lid |
rdma_ah_get_path_bits(&qp->remote_ah_attr));
}
typedef void (*hfi1_make_ruc_hdr)(struct rvt_qp *qp,
struct ib_other_headers *ohdr,
u32 bth0, u32 bth2, int middle,
struct hfi1_pkt_state *ps);
/* We support only two types - 9B and 16B for now */
static const hfi1_make_ruc_hdr hfi1_ruc_header_tbl[2] = {
[HFI1_PKT_TYPE_9B] = &hfi1_make_ruc_header_9B,
[HFI1_PKT_TYPE_16B] = &hfi1_make_ruc_header_16B
};
void hfi1_make_ruc_header(struct rvt_qp *qp, struct ib_other_headers *ohdr,
u32 bth0, u32 bth2, int middle,
struct hfi1_pkt_state *ps)
{
struct hfi1_qp_priv *priv = qp->priv;
/*
* reset s_ahg/AHG fields
*
* This insures that the ahgentry/ahgcount
* are at a non-AHG default to protect
* build_verbs_tx_desc() from using
* an include ahgidx.
*
* build_ahg() will modify as appropriate
* to use the AHG feature.
*/
priv->s_ahg->tx_flags = 0;
priv->s_ahg->ahgcount = 0;
priv->s_ahg->ahgidx = 0;
/* Make the appropriate header */
hfi1_ruc_header_tbl[priv->hdr_type](qp, ohdr, bth0, bth2, middle, ps);
} }
/* when sending, force a reschedule every one of these periods */ /* when sending, force a reschedule every one of these periods */
......
...@@ -65,7 +65,7 @@ int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) ...@@ -65,7 +65,7 @@ int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
struct hfi1_qp_priv *priv = qp->priv; struct hfi1_qp_priv *priv = qp->priv;
struct ib_other_headers *ohdr; struct ib_other_headers *ohdr;
struct rvt_swqe *wqe; struct rvt_swqe *wqe;
u32 hwords = 5; u32 hwords;
u32 bth0 = 0; u32 bth0 = 0;
u32 len; u32 len;
u32 pmtu = qp->pmtu; u32 pmtu = qp->pmtu;
...@@ -93,9 +93,23 @@ int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) ...@@ -93,9 +93,23 @@ int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
goto done_free_tx; goto done_free_tx;
} }
ohdr = &ps->s_txreq->phdr.hdr.ibh.u.oth; ps->s_txreq->phdr.hdr.hdr_type = priv->hdr_type;
if (priv->hdr_type == HFI1_PKT_TYPE_9B) {
/* header size in 32-bit words LRH+BTH = (8+12)/4. */
hwords = 5;
if (rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH) if (rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH)
ohdr = &ps->s_txreq->phdr.hdr.ibh.u.l.oth; ohdr = &ps->s_txreq->phdr.hdr.ibh.u.l.oth;
else
ohdr = &ps->s_txreq->phdr.hdr.ibh.u.oth;
} else {
/* header size in 32-bit words 16B LRH+BTH = (16+12)/4. */
hwords = 7;
if ((rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH) &&
(hfi1_check_mcast(rdma_ah_get_dlid(&qp->remote_ah_attr))))
ohdr = &ps->s_txreq->phdr.hdr.opah.u.l.oth;
else
ohdr = &ps->s_txreq->phdr.hdr.opah.u.oth;
}
/* Get the next send request. */ /* Get the next send request. */
wqe = rvt_get_swqe_ptr(qp, qp->s_cur); wqe = rvt_get_swqe_ptr(qp, qp->s_cur);
...@@ -309,6 +323,7 @@ void hfi1_uc_rcv(struct hfi1_packet *packet) ...@@ -309,6 +323,7 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
u32 pmtu = qp->pmtu; u32 pmtu = qp->pmtu;
struct ib_reth *reth; struct ib_reth *reth;
int ret; int ret;
u8 extra_bytes = pad + packet->extra_byte + (SIZE_OF_CRC << 2);
if (hfi1_ruc_check_hdr(ibp, packet)) if (hfi1_ruc_check_hdr(ibp, packet))
return; return;
...@@ -408,7 +423,12 @@ void hfi1_uc_rcv(struct hfi1_packet *packet) ...@@ -408,7 +423,12 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
/* FALLTHROUGH */ /* FALLTHROUGH */
case OP(SEND_MIDDLE): case OP(SEND_MIDDLE):
/* Check for invalid length PMTU or posted rwqe len. */ /* Check for invalid length PMTU or posted rwqe len. */
if (unlikely(tlen != (hdrsize + pmtu + 4))) /*
* There will be no padding for 9B packet but 16B packets
* will come in with some padding since we always add
* CRC and LT bytes which will need to be flit aligned
*/
if (unlikely(tlen != (hdrsize + pmtu + extra_bytes)))
goto rewind; goto rewind;
qp->r_rcv_len += pmtu; qp->r_rcv_len += pmtu;
if (unlikely(qp->r_rcv_len > qp->r_len)) if (unlikely(qp->r_rcv_len > qp->r_len))
...@@ -428,10 +448,10 @@ void hfi1_uc_rcv(struct hfi1_packet *packet) ...@@ -428,10 +448,10 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
send_last: send_last:
/* Check for invalid length. */ /* Check for invalid length. */
/* LAST len should be >= 1 */ /* LAST len should be >= 1 */
if (unlikely(tlen < (hdrsize + pad + 4))) if (unlikely(tlen < (hdrsize + extra_bytes)))
goto rewind; goto rewind;
/* Don't count the CRC. */ /* Don't count the CRC. */
tlen -= (hdrsize + pad + 4); tlen -= (hdrsize + extra_bytes);
wc.byte_len = tlen + qp->r_rcv_len; wc.byte_len = tlen + qp->r_rcv_len;
if (unlikely(wc.byte_len > qp->r_len)) if (unlikely(wc.byte_len > qp->r_len))
goto rewind; goto rewind;
...@@ -524,7 +544,7 @@ void hfi1_uc_rcv(struct hfi1_packet *packet) ...@@ -524,7 +544,7 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
if (unlikely(tlen < (hdrsize + pad + 4))) if (unlikely(tlen < (hdrsize + pad + 4)))
goto drop; goto drop;
/* Don't count the CRC. */ /* Don't count the CRC. */
tlen -= (hdrsize + pad + 4); tlen -= (hdrsize + extra_bytes);
if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) if (unlikely(tlen + qp->r_rcv_len != qp->r_len))
goto drop; goto drop;
if (test_and_clear_bit(RVT_R_REWIND_SGE, &qp->r_aflags)) { if (test_and_clear_bit(RVT_R_REWIND_SGE, &qp->r_aflags)) {
...@@ -544,14 +564,12 @@ void hfi1_uc_rcv(struct hfi1_packet *packet) ...@@ -544,14 +564,12 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
case OP(RDMA_WRITE_LAST): case OP(RDMA_WRITE_LAST):
rdma_last: rdma_last:
/* Get the number of bytes the message was padded by. */
pad = ib_bth_get_pad(ohdr);
/* Check for invalid length. */ /* Check for invalid length. */
/* LAST len should be >= 1 */ /* LAST len should be >= 1 */
if (unlikely(tlen < (hdrsize + pad + 4))) if (unlikely(tlen < (hdrsize + pad + 4)))
goto drop; goto drop;
/* Don't count the CRC. */ /* Don't count the CRC. */
tlen -= (hdrsize + pad + 4); tlen -= (hdrsize + extra_bytes);
if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) if (unlikely(tlen + qp->r_rcv_len != qp->r_len))
goto drop; goto drop;
hfi1_copy_sge(&qp->r_sge, data, tlen, true, false); hfi1_copy_sge(&qp->r_sge, data, tlen, true, false);
......
...@@ -373,7 +373,8 @@ void hfi1_do_send(struct rvt_qp *qp, bool in_thread); ...@@ -373,7 +373,8 @@ void hfi1_do_send(struct rvt_qp *qp, bool in_thread);
void hfi1_send_complete(struct rvt_qp *qp, struct rvt_swqe *wqe, void hfi1_send_complete(struct rvt_qp *qp, struct rvt_swqe *wqe,
enum ib_wc_status status); enum ib_wc_status status);
void hfi1_send_rc_ack(struct hfi1_ctxtdata *, struct rvt_qp *qp, int is_fecn); void hfi1_send_rc_ack(struct hfi1_ctxtdata *rcd, struct rvt_qp *qp,
bool is_fecn);
int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps); int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment