IB/hfi1: Setup common IB fields in hfi1_packet struct
We move many common IB fields into the hfi1_packet structure and set them up in a single function. This allows us to set the fields in a single place and not deal with them throughout the driver. Reviewed-by: Brian Welty <brian.welty@intel.com> Reviewed-by: Dasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com> Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Signed-off-by: Don Hiatt <don.hiatt@intel.com> Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
parent
228d2af1b7
commit
9039746cdf
|
@ -9810,15 +9810,6 @@ void hfi1_clear_tids(struct hfi1_ctxtdata *rcd)
|
|||
hfi1_put_tid(dd, i, PT_INVALID, 0, 0);
|
||||
}
|
||||
|
||||
struct ib_header *hfi1_get_msgheader(
|
||||
struct hfi1_devdata *dd, __le32 *rhf_addr)
|
||||
{
|
||||
u32 offset = rhf_hdrq_offset(rhf_to_cpu(rhf_addr));
|
||||
|
||||
return (struct ib_header *)
|
||||
(rhf_addr - dd->rhf_offset + offset);
|
||||
}
|
||||
|
||||
static const char * const ib_cfg_name_strings[] = {
|
||||
"HFI1_IB_CFG_LIDLMC",
|
||||
"HFI1_IB_CFG_LWID_DG_ENB",
|
||||
|
|
|
@ -1347,8 +1347,6 @@ enum {
|
|||
u64 get_all_cpu_total(u64 __percpu *cntr);
|
||||
void hfi1_start_cleanup(struct hfi1_devdata *dd);
|
||||
void hfi1_clear_tids(struct hfi1_ctxtdata *rcd);
|
||||
struct ib_header *hfi1_get_msgheader(
|
||||
struct hfi1_devdata *dd, __le32 *rhf_addr);
|
||||
void hfi1_init_ctxt(struct send_context *sc);
|
||||
void hfi1_put_tid(struct hfi1_devdata *dd, u32 index,
|
||||
u32 type, unsigned long pa, u16 order);
|
||||
|
|
|
@ -325,6 +325,7 @@ struct diag_pkt {
|
|||
#define HFI1_LRH_BTH 0x0002 /* 1. word of IB LRH - next header: BTH */
|
||||
|
||||
/* misc. */
|
||||
#define SC15_PACKET 0xF
|
||||
#define SIZE_OF_CRC 1
|
||||
|
||||
#define LIM_MGMT_P_KEY 0x7FFF
|
||||
|
|
|
@ -224,6 +224,20 @@ static inline void *get_egrbuf(const struct hfi1_ctxtdata *rcd, u64 rhf,
|
|||
(offset * RCV_BUF_BLOCK_SIZE));
|
||||
}
|
||||
|
||||
static inline void *hfi1_get_header(struct hfi1_devdata *dd,
|
||||
__le32 *rhf_addr)
|
||||
{
|
||||
u32 offset = rhf_hdrq_offset(rhf_to_cpu(rhf_addr));
|
||||
|
||||
return (void *)(rhf_addr - dd->rhf_offset + offset);
|
||||
}
|
||||
|
||||
static inline struct ib_header *hfi1_get_msgheader(struct hfi1_devdata *dd,
|
||||
__le32 *rhf_addr)
|
||||
{
|
||||
return (struct ib_header *)hfi1_get_header(dd, rhf_addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate and encode the a given RcvArray Buffer size.
|
||||
* The function will check whether the given size falls within
|
||||
|
@ -249,7 +263,8 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
|
|||
{
|
||||
struct ib_header *rhdr = packet->hdr;
|
||||
u32 rte = rhf_rcv_type_err(packet->rhf);
|
||||
int lnh = ib_get_lnh(rhdr);
|
||||
u8 lnh = ib_get_lnh(rhdr);
|
||||
bool has_grh = false;
|
||||
struct hfi1_ibport *ibp = rcd_to_iport(rcd);
|
||||
struct hfi1_devdata *dd = ppd->dd;
|
||||
struct rvt_dev_info *rdi = &dd->verbs_dev.rdi;
|
||||
|
@ -257,37 +272,42 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
|
|||
if (packet->rhf & (RHF_VCRC_ERR | RHF_ICRC_ERR))
|
||||
return;
|
||||
|
||||
if (lnh == HFI1_LRH_BTH) {
|
||||
packet->ohdr = &rhdr->u.oth;
|
||||
} else if (lnh == HFI1_LRH_GRH) {
|
||||
has_grh = true;
|
||||
packet->ohdr = &rhdr->u.l.oth;
|
||||
packet->grh = &rhdr->u.l.grh;
|
||||
} else {
|
||||
goto drop;
|
||||
}
|
||||
|
||||
if (packet->rhf & RHF_TID_ERR) {
|
||||
/* For TIDERR and RC QPs preemptively schedule a NAK */
|
||||
struct ib_other_headers *ohdr = NULL;
|
||||
u32 tlen = rhf_pkt_len(packet->rhf); /* in bytes */
|
||||
u16 lid = ib_get_dlid(rhdr);
|
||||
u32 dlid = ib_get_dlid(rhdr);
|
||||
u32 qp_num;
|
||||
u32 rcv_flags = 0;
|
||||
u32 mlid_base = be16_to_cpu(IB_MULTICAST_LID_BASE);
|
||||
|
||||
/* Sanity check packet */
|
||||
if (tlen < 24)
|
||||
goto drop;
|
||||
|
||||
/* Check for GRH */
|
||||
if (lnh == HFI1_LRH_BTH) {
|
||||
ohdr = &rhdr->u.oth;
|
||||
} else if (lnh == HFI1_LRH_GRH) {
|
||||
if (has_grh) {
|
||||
u32 vtf;
|
||||
struct ib_grh *grh = packet->grh;
|
||||
|
||||
ohdr = &rhdr->u.l.oth;
|
||||
if (rhdr->u.l.grh.next_hdr != IB_GRH_NEXT_HDR)
|
||||
if (grh->next_hdr != IB_GRH_NEXT_HDR)
|
||||
goto drop;
|
||||
vtf = be32_to_cpu(rhdr->u.l.grh.version_tclass_flow);
|
||||
vtf = be32_to_cpu(grh->version_tclass_flow);
|
||||
if ((vtf >> IB_GRH_VERSION_SHIFT) != IB_GRH_VERSION)
|
||||
goto drop;
|
||||
rcv_flags |= HFI1_HAS_GRH;
|
||||
} else {
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* Get the destination QP number. */
|
||||
qp_num = ib_bth_get_qpn(ohdr);
|
||||
if (lid < be16_to_cpu(IB_MULTICAST_LID_BASE)) {
|
||||
qp_num = ib_bth_get_qpn(packet->ohdr);
|
||||
if (dlid < mlid_base) {
|
||||
struct rvt_qp *qp;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -312,11 +332,7 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
|
|||
|
||||
switch (qp->ibqp.qp_type) {
|
||||
case IB_QPT_RC:
|
||||
hfi1_rc_hdrerr(
|
||||
rcd,
|
||||
rhdr,
|
||||
rcv_flags,
|
||||
qp);
|
||||
hfi1_rc_hdrerr(rcd, packet, qp);
|
||||
break;
|
||||
default:
|
||||
/* For now don't handle any other QP types */
|
||||
|
@ -332,9 +348,8 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
|
|||
switch (rte) {
|
||||
case RHF_RTE_ERROR_OP_CODE_ERR:
|
||||
{
|
||||
u32 opcode;
|
||||
void *ebuf = NULL;
|
||||
__be32 *bth = NULL;
|
||||
u8 opcode;
|
||||
|
||||
if (rhf_use_egr_bfr(packet->rhf))
|
||||
ebuf = packet->ebuf;
|
||||
|
@ -342,16 +357,7 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
|
|||
if (!ebuf)
|
||||
goto drop; /* this should never happen */
|
||||
|
||||
if (lnh == HFI1_LRH_BTH)
|
||||
bth = (__be32 *)ebuf;
|
||||
else if (lnh == HFI1_LRH_GRH)
|
||||
bth = (__be32 *)((char *)ebuf + sizeof(struct ib_grh));
|
||||
else
|
||||
goto drop;
|
||||
|
||||
opcode = be32_to_cpu(bth[0]) >> 24;
|
||||
opcode &= 0xff;
|
||||
|
||||
opcode = ib_bth_get_opcode(packet->ohdr);
|
||||
if (opcode == IB_OPCODE_CNP) {
|
||||
/*
|
||||
* Only in pre-B0 h/w is the CNP_OPCODE handled
|
||||
|
@ -365,7 +371,7 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
|
|||
sc5 = hfi1_9B_get_sc5(rhdr, packet->rhf);
|
||||
sl = ibp->sc_to_sl[sc5];
|
||||
|
||||
lqpn = be32_to_cpu(bth[1]) & RVT_QPN_MASK;
|
||||
lqpn = ib_bth_get_qpn(packet->ohdr);
|
||||
rcu_read_lock();
|
||||
qp = rvt_lookup_qpn(rdi, &ibp->rvp, lqpn);
|
||||
if (!qp) {
|
||||
|
@ -415,7 +421,6 @@ static inline void init_packet(struct hfi1_ctxtdata *rcd,
|
|||
packet->rhf = rhf_to_cpu(packet->rhf_addr);
|
||||
packet->rhqoff = rcd->head;
|
||||
packet->numpkt = 0;
|
||||
packet->rcv_flags = 0;
|
||||
}
|
||||
|
||||
void hfi1_process_ecn_slowpath(struct rvt_qp *qp, struct hfi1_packet *pkt,
|
||||
|
@ -424,15 +429,12 @@ void hfi1_process_ecn_slowpath(struct rvt_qp *qp, struct hfi1_packet *pkt,
|
|||
struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
|
||||
struct ib_header *hdr = pkt->hdr;
|
||||
struct ib_other_headers *ohdr = pkt->ohdr;
|
||||
struct ib_grh *grh = NULL;
|
||||
struct ib_grh *grh = pkt->grh;
|
||||
u32 rqpn = 0, bth1;
|
||||
u16 rlid, dlid = ib_get_dlid(hdr);
|
||||
u8 sc, svc_type;
|
||||
bool is_mcast = false;
|
||||
|
||||
if (pkt->rcv_flags & HFI1_HAS_GRH)
|
||||
grh = &hdr->u.l.grh;
|
||||
|
||||
switch (qp->ibqp.qp_type) {
|
||||
case IB_QPT_SMI:
|
||||
case IB_QPT_GSI:
|
||||
|
@ -591,9 +593,10 @@ static void __prescan_rxq(struct hfi1_packet *packet)
|
|||
|
||||
if (lnh == HFI1_LRH_BTH) {
|
||||
packet->ohdr = &hdr->u.oth;
|
||||
packet->grh = NULL;
|
||||
} else if (lnh == HFI1_LRH_GRH) {
|
||||
packet->ohdr = &hdr->u.l.oth;
|
||||
packet->rcv_flags |= HFI1_HAS_GRH;
|
||||
packet->grh = &hdr->u.l.grh;
|
||||
} else {
|
||||
goto next; /* just in case */
|
||||
}
|
||||
|
@ -698,10 +701,9 @@ static inline int process_rcv_packet(struct hfi1_packet *packet, int thread)
|
|||
{
|
||||
int ret;
|
||||
|
||||
packet->hdr = hfi1_get_msgheader(packet->rcd->dd,
|
||||
packet->rhf_addr);
|
||||
packet->hlen = (u8 *)packet->rhf_addr - (u8 *)packet->hdr;
|
||||
packet->etype = rhf_rcv_type(packet->rhf);
|
||||
|
||||
packet->hlen = (u8 *)packet->rhf_addr - (u8 *)packet->hdr;
|
||||
/* total length */
|
||||
packet->tlen = rhf_pkt_len(packet->rhf); /* in bytes */
|
||||
/* retrieve eager buffer details */
|
||||
|
@ -759,7 +761,7 @@ static inline void process_rcv_update(int last, struct hfi1_packet *packet)
|
|||
packet->etail, 0, 0);
|
||||
packet->updegr = 0;
|
||||
}
|
||||
packet->rcv_flags = 0;
|
||||
packet->grh = NULL;
|
||||
}
|
||||
|
||||
static inline void finish_packet(struct hfi1_packet *packet)
|
||||
|
@ -896,12 +898,15 @@ static inline int set_armed_to_active(struct hfi1_ctxtdata *rcd,
|
|||
struct hfi1_devdata *dd)
|
||||
{
|
||||
struct work_struct *lsaw = &rcd->ppd->linkstate_active_work;
|
||||
struct ib_header *hdr = hfi1_get_msgheader(packet->rcd->dd,
|
||||
packet->rhf_addr);
|
||||
u8 etype = rhf_rcv_type(packet->rhf);
|
||||
u8 sc = SC15_PACKET;
|
||||
|
||||
if (etype == RHF_RCV_TYPE_IB &&
|
||||
hfi1_9B_get_sc5(hdr, packet->rhf) != 0xf) {
|
||||
if (etype == RHF_RCV_TYPE_IB) {
|
||||
struct ib_header *hdr = hfi1_get_msgheader(packet->rcd->dd,
|
||||
packet->rhf_addr);
|
||||
sc = hfi1_9B_get_sc5(hdr, packet->rhf);
|
||||
}
|
||||
if (sc != SC15_PACKET) {
|
||||
int hwstate = read_logical_state(dd);
|
||||
|
||||
if (hwstate != LSTATE_ACTIVE) {
|
||||
|
@ -1321,6 +1326,58 @@ int hfi1_reset_device(int unit)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline void hfi1_setup_ib_header(struct hfi1_packet *packet)
|
||||
{
|
||||
packet->hdr = (struct hfi1_ib_message_header *)
|
||||
hfi1_get_msgheader(packet->rcd->dd,
|
||||
packet->rhf_addr);
|
||||
packet->hlen = (u8 *)packet->rhf_addr - (u8 *)packet->hdr;
|
||||
}
|
||||
|
||||
static int hfi1_setup_9B_packet(struct hfi1_packet *packet)
|
||||
{
|
||||
struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd);
|
||||
struct ib_header *hdr;
|
||||
u8 lnh;
|
||||
|
||||
hfi1_setup_ib_header(packet);
|
||||
hdr = packet->hdr;
|
||||
|
||||
lnh = ib_get_lnh(hdr);
|
||||
if (lnh == HFI1_LRH_BTH) {
|
||||
packet->ohdr = &hdr->u.oth;
|
||||
packet->grh = NULL;
|
||||
} else if (lnh == HFI1_LRH_GRH) {
|
||||
u32 vtf;
|
||||
|
||||
packet->ohdr = &hdr->u.l.oth;
|
||||
packet->grh = &hdr->u.l.grh;
|
||||
if (packet->grh->next_hdr != IB_GRH_NEXT_HDR)
|
||||
goto drop;
|
||||
vtf = be32_to_cpu(packet->grh->version_tclass_flow);
|
||||
if ((vtf >> IB_GRH_VERSION_SHIFT) != IB_GRH_VERSION)
|
||||
goto drop;
|
||||
} else {
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* Query commonly used fields from packet header */
|
||||
packet->opcode = ib_bth_get_opcode(packet->ohdr);
|
||||
packet->slid = ib_get_slid(hdr);
|
||||
packet->dlid = ib_get_dlid(hdr);
|
||||
packet->sl = ib_get_sl(hdr);
|
||||
packet->sc = hfi1_9B_get_sc5(hdr, packet->rhf);
|
||||
packet->pad = ib_bth_get_pad(packet->ohdr);
|
||||
packet->extra_byte = 0;
|
||||
packet->fecn = ib_bth_get_fecn(packet->ohdr);
|
||||
packet->becn = ib_bth_get_becn(packet->ohdr);
|
||||
|
||||
return 0;
|
||||
drop:
|
||||
ibp->rvp.n_pkt_drops++;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void handle_eflags(struct hfi1_packet *packet)
|
||||
{
|
||||
struct hfi1_ctxtdata *rcd = packet->rcd;
|
||||
|
@ -1351,6 +1408,9 @@ int process_receive_ib(struct hfi1_packet *packet)
|
|||
if (unlikely(hfi1_dbg_fault_packet(packet)))
|
||||
return RHF_RCV_CONTINUE;
|
||||
|
||||
if (hfi1_setup_9B_packet(packet))
|
||||
return RHF_RCV_CONTINUE;
|
||||
|
||||
trace_hfi1_rcvhdr(packet->rcd->ppd->dd,
|
||||
packet->rcd->ctxt,
|
||||
rhf_err_flags(packet->rhf),
|
||||
|
@ -1422,6 +1482,7 @@ int process_receive_error(struct hfi1_packet *packet)
|
|||
rhf_rcv_type_err(packet->rhf) == 3))
|
||||
return RHF_RCV_CONTINUE;
|
||||
|
||||
hfi1_setup_ib_header(packet);
|
||||
handle_eflags(packet);
|
||||
|
||||
if (unlikely(rhf_err_flags(packet->rhf)))
|
||||
|
@ -1435,6 +1496,8 @@ int kdeth_process_expected(struct hfi1_packet *packet)
|
|||
{
|
||||
if (unlikely(hfi1_dbg_fault_packet(packet)))
|
||||
return RHF_RCV_CONTINUE;
|
||||
|
||||
hfi1_setup_ib_header(packet);
|
||||
if (unlikely(rhf_err_flags(packet->rhf)))
|
||||
handle_eflags(packet);
|
||||
|
||||
|
@ -1445,6 +1508,7 @@ int kdeth_process_expected(struct hfi1_packet *packet)
|
|||
|
||||
int kdeth_process_eager(struct hfi1_packet *packet)
|
||||
{
|
||||
hfi1_setup_ib_header(packet);
|
||||
if (unlikely(rhf_err_flags(packet->rhf)))
|
||||
handle_eflags(packet);
|
||||
if (unlikely(hfi1_dbg_fault_packet(packet)))
|
||||
|
|
|
@ -356,17 +356,26 @@ struct hfi1_packet {
|
|||
__le32 *rhf_addr;
|
||||
struct rvt_qp *qp;
|
||||
struct ib_other_headers *ohdr;
|
||||
struct ib_grh *grh;
|
||||
u64 rhf;
|
||||
u32 maxcnt;
|
||||
u32 rhqoff;
|
||||
u32 dlid;
|
||||
u32 slid;
|
||||
u16 tlen;
|
||||
s16 etail;
|
||||
u8 hlen;
|
||||
u8 numpkt;
|
||||
u8 rsize;
|
||||
u8 updegr;
|
||||
u8 rcv_flags;
|
||||
u8 etype;
|
||||
u8 extra_byte;
|
||||
u8 pad;
|
||||
u8 sc;
|
||||
u8 sl;
|
||||
u8 opcode;
|
||||
bool becn;
|
||||
bool fecn;
|
||||
};
|
||||
|
||||
struct rvt_sge_state;
|
||||
|
@ -2086,4 +2095,14 @@ int hfi1_tempsense_rd(struct hfi1_devdata *dd, struct hfi1_temp *temp);
|
|||
|
||||
#define DD_DEV_ENTRY(dd) __string(dev, dev_name(&(dd)->pcidev->dev))
|
||||
#define DD_DEV_ASSIGN(dd) __assign_str(dev, dev_name(&(dd)->pcidev->dev))
|
||||
|
||||
/*
|
||||
* hfi1_check_mcast- Check if the given lid is
|
||||
* in the IB multicast range.
|
||||
*/
|
||||
static inline bool hfi1_check_mcast(u16 lid)
|
||||
{
|
||||
return ((lid >= be16_to_cpu(IB_MULTICAST_LID_BASE)) &&
|
||||
(lid != be16_to_cpu(IB_LID_PERMISSIVE)));
|
||||
}
|
||||
#endif /* _HFI1_KERNEL_H */
|
||||
|
|
|
@ -1916,17 +1916,16 @@ void process_becn(struct hfi1_pportdata *ppd, u8 sl, u16 rlid, u32 lqpn,
|
|||
void hfi1_rc_rcv(struct hfi1_packet *packet)
|
||||
{
|
||||
struct hfi1_ctxtdata *rcd = packet->rcd;
|
||||
struct ib_header *hdr = packet->hdr;
|
||||
u32 rcv_flags = packet->rcv_flags;
|
||||
void *data = packet->ebuf;
|
||||
u32 tlen = packet->tlen;
|
||||
struct rvt_qp *qp = packet->qp;
|
||||
struct hfi1_ibport *ibp = rcd_to_iport(rcd);
|
||||
struct ib_other_headers *ohdr = packet->ohdr;
|
||||
u32 bth0, opcode;
|
||||
u32 bth0;
|
||||
u32 opcode = packet->opcode;
|
||||
u32 hdrsize = packet->hlen;
|
||||
u32 psn;
|
||||
u32 pad;
|
||||
u32 pad = packet->pad;
|
||||
struct ib_wc wc;
|
||||
u32 pmtu = qp->pmtu;
|
||||
int diff;
|
||||
|
@ -1938,14 +1937,13 @@ void hfi1_rc_rcv(struct hfi1_packet *packet)
|
|||
u32 rkey;
|
||||
|
||||
lockdep_assert_held(&qp->r_lock);
|
||||
|
||||
bth0 = be32_to_cpu(ohdr->bth[0]);
|
||||
if (hfi1_ruc_check_hdr(ibp, hdr, rcv_flags & HFI1_HAS_GRH, qp, bth0))
|
||||
if (hfi1_ruc_check_hdr(ibp, packet))
|
||||
return;
|
||||
|
||||
is_fecn = process_ecn(qp, packet, false);
|
||||
|
||||
psn = ib_bth_get_psn(ohdr);
|
||||
opcode = ib_bth_get_opcode(ohdr);
|
||||
|
||||
/*
|
||||
* Process responses (ACKs) before anything else. Note that the
|
||||
|
@ -2075,8 +2073,6 @@ void hfi1_rc_rcv(struct hfi1_packet *packet)
|
|||
wc.wc_flags = 0;
|
||||
wc.ex.imm_data = 0;
|
||||
send_last:
|
||||
/* Get the number of bytes the message was padded by. */
|
||||
pad = ib_bth_get_pad(ohdr);
|
||||
/* Check for invalid length. */
|
||||
/* LAST len should be >= 1 */
|
||||
if (unlikely(tlen < (hdrsize + pad + 4)))
|
||||
|
@ -2369,28 +2365,19 @@ void hfi1_rc_rcv(struct hfi1_packet *packet)
|
|||
|
||||
void hfi1_rc_hdrerr(
|
||||
struct hfi1_ctxtdata *rcd,
|
||||
struct ib_header *hdr,
|
||||
u32 rcv_flags,
|
||||
struct hfi1_packet *packet,
|
||||
struct rvt_qp *qp)
|
||||
{
|
||||
int has_grh = rcv_flags & HFI1_HAS_GRH;
|
||||
struct ib_other_headers *ohdr;
|
||||
struct hfi1_ibport *ibp = rcd_to_iport(rcd);
|
||||
int diff;
|
||||
u32 opcode;
|
||||
u32 psn, bth0;
|
||||
u32 psn;
|
||||
|
||||
/* Check for GRH */
|
||||
ohdr = &hdr->u.oth;
|
||||
if (has_grh)
|
||||
ohdr = &hdr->u.l.oth;
|
||||
|
||||
bth0 = be32_to_cpu(ohdr->bth[0]);
|
||||
if (hfi1_ruc_check_hdr(ibp, hdr, has_grh, qp, bth0))
|
||||
if (hfi1_ruc_check_hdr(ibp, packet))
|
||||
return;
|
||||
|
||||
psn = ib_bth_get_psn(ohdr);
|
||||
opcode = ib_bth_get_opcode(ohdr);
|
||||
psn = ib_bth_get_psn(packet->ohdr);
|
||||
opcode = ib_bth_get_opcode(packet->ohdr);
|
||||
|
||||
/* Only deal with RDMA Writes for now */
|
||||
if (opcode < IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST) {
|
||||
|
|
|
@ -214,100 +214,95 @@ static int gid_ok(union ib_gid *gid, __be64 gid_prefix, __be64 id)
|
|||
*
|
||||
* The s_lock will be acquired around the hfi1_migrate_qp() call.
|
||||
*/
|
||||
int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct ib_header *hdr,
|
||||
int has_grh, struct rvt_qp *qp, u32 bth0)
|
||||
int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet)
|
||||
{
|
||||
__be64 guid;
|
||||
unsigned long flags;
|
||||
struct rvt_qp *qp = packet->qp;
|
||||
u8 sc5 = ibp->sl_to_sc[rdma_ah_get_sl(&qp->remote_ah_attr)];
|
||||
u32 dlid = packet->dlid;
|
||||
u32 slid = packet->slid;
|
||||
u32 sl = packet->sl;
|
||||
int migrated;
|
||||
u32 bth0, bth1;
|
||||
|
||||
if (qp->s_mig_state == IB_MIG_ARMED && (bth0 & IB_BTH_MIG_REQ)) {
|
||||
if (!has_grh) {
|
||||
bth0 = be32_to_cpu(packet->ohdr->bth[0]);
|
||||
bth1 = be32_to_cpu(packet->ohdr->bth[1]);
|
||||
migrated = bth0 & IB_BTH_MIG_REQ;
|
||||
|
||||
if (qp->s_mig_state == IB_MIG_ARMED && migrated) {
|
||||
if (!packet->grh) {
|
||||
if (rdma_ah_get_ah_flags(&qp->alt_ah_attr) &
|
||||
IB_AH_GRH)
|
||||
goto err;
|
||||
return 1;
|
||||
} else {
|
||||
const struct ib_global_route *grh;
|
||||
|
||||
if (!(rdma_ah_get_ah_flags(&qp->alt_ah_attr) &
|
||||
IB_AH_GRH))
|
||||
goto err;
|
||||
return 1;
|
||||
grh = rdma_ah_read_grh(&qp->alt_ah_attr);
|
||||
guid = get_sguid(ibp, grh->sgid_index);
|
||||
if (!gid_ok(&hdr->u.l.grh.dgid, ibp->rvp.gid_prefix,
|
||||
if (!gid_ok(&packet->grh->dgid, ibp->rvp.gid_prefix,
|
||||
guid))
|
||||
goto err;
|
||||
return 1;
|
||||
if (!gid_ok(
|
||||
&hdr->u.l.grh.sgid,
|
||||
&packet->grh->sgid,
|
||||
grh->dgid.global.subnet_prefix,
|
||||
grh->dgid.global.interface_id))
|
||||
goto err;
|
||||
return 1;
|
||||
}
|
||||
if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), (u16)bth0, sc5,
|
||||
ib_get_slid(hdr)))) {
|
||||
hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_P_KEY,
|
||||
(u16)bth0,
|
||||
ib_get_sl(hdr),
|
||||
0, qp->ibqp.qp_num,
|
||||
ib_get_slid(hdr),
|
||||
ib_get_dlid(hdr));
|
||||
goto err;
|
||||
if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), (u16)bth0,
|
||||
sc5, slid))) {
|
||||
hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_P_KEY, (u16)bth0, sl,
|
||||
0, qp->ibqp.qp_num, slid, dlid);
|
||||
return 1;
|
||||
}
|
||||
/* Validate the SLID. See Ch. 9.6.1.5 and 17.2.8 */
|
||||
if (ib_get_slid(hdr) !=
|
||||
rdma_ah_get_dlid(&qp->alt_ah_attr) ||
|
||||
if (slid != rdma_ah_get_dlid(&qp->alt_ah_attr) ||
|
||||
ppd_from_ibp(ibp)->port !=
|
||||
rdma_ah_get_port_num(&qp->alt_ah_attr))
|
||||
goto err;
|
||||
return 1;
|
||||
spin_lock_irqsave(&qp->s_lock, flags);
|
||||
hfi1_migrate_qp(qp);
|
||||
spin_unlock_irqrestore(&qp->s_lock, flags);
|
||||
} else {
|
||||
if (!has_grh) {
|
||||
if (!packet->grh) {
|
||||
if (rdma_ah_get_ah_flags(&qp->remote_ah_attr) &
|
||||
IB_AH_GRH)
|
||||
goto err;
|
||||
return 1;
|
||||
} else {
|
||||
const struct ib_global_route *grh;
|
||||
|
||||
if (!(rdma_ah_get_ah_flags(&qp->remote_ah_attr) &
|
||||
IB_AH_GRH))
|
||||
goto err;
|
||||
return 1;
|
||||
grh = rdma_ah_read_grh(&qp->remote_ah_attr);
|
||||
guid = get_sguid(ibp, grh->sgid_index);
|
||||
if (!gid_ok(&hdr->u.l.grh.dgid, ibp->rvp.gid_prefix,
|
||||
if (!gid_ok(&packet->grh->dgid, ibp->rvp.gid_prefix,
|
||||
guid))
|
||||
goto err;
|
||||
return 1;
|
||||
if (!gid_ok(
|
||||
&hdr->u.l.grh.sgid,
|
||||
&packet->grh->sgid,
|
||||
grh->dgid.global.subnet_prefix,
|
||||
grh->dgid.global.interface_id))
|
||||
goto err;
|
||||
return 1;
|
||||
}
|
||||
if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), (u16)bth0, sc5,
|
||||
ib_get_slid(hdr)))) {
|
||||
hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_P_KEY,
|
||||
(u16)bth0,
|
||||
ib_get_sl(hdr),
|
||||
0, qp->ibqp.qp_num,
|
||||
ib_get_slid(hdr),
|
||||
ib_get_dlid(hdr));
|
||||
goto err;
|
||||
if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), (u16)bth0,
|
||||
sc5, slid))) {
|
||||
hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_P_KEY, (u16)bth0, sl,
|
||||
0, qp->ibqp.qp_num, slid, dlid);
|
||||
return 1;
|
||||
}
|
||||
/* Validate the SLID. See Ch. 9.6.1.5 */
|
||||
if (ib_get_slid(hdr) !=
|
||||
rdma_ah_get_dlid(&qp->remote_ah_attr) ||
|
||||
if ((slid != rdma_ah_get_dlid(&qp->remote_ah_attr)) ||
|
||||
ppd_from_ibp(ibp)->port != qp->port_num)
|
||||
goto err;
|
||||
if (qp->s_mig_state == IB_MIG_REARM &&
|
||||
!(bth0 & IB_BTH_MIG_REQ))
|
||||
return 1;
|
||||
if (qp->s_mig_state == IB_MIG_REARM && !migrated)
|
||||
qp->s_mig_state = IB_MIG_ARMED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -297,31 +297,25 @@ int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
|
|||
void hfi1_uc_rcv(struct hfi1_packet *packet)
|
||||
{
|
||||
struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd);
|
||||
struct ib_header *hdr = packet->hdr;
|
||||
u32 rcv_flags = packet->rcv_flags;
|
||||
void *data = packet->ebuf;
|
||||
u32 tlen = packet->tlen;
|
||||
struct rvt_qp *qp = packet->qp;
|
||||
struct ib_other_headers *ohdr = packet->ohdr;
|
||||
u32 bth0, opcode;
|
||||
u32 opcode = packet->opcode;
|
||||
u32 hdrsize = packet->hlen;
|
||||
u32 psn;
|
||||
u32 pad;
|
||||
u32 pad = packet->pad;
|
||||
struct ib_wc wc;
|
||||
u32 pmtu = qp->pmtu;
|
||||
struct ib_reth *reth;
|
||||
int has_grh = rcv_flags & HFI1_HAS_GRH;
|
||||
int ret;
|
||||
|
||||
bth0 = be32_to_cpu(ohdr->bth[0]);
|
||||
if (hfi1_ruc_check_hdr(ibp, hdr, has_grh, qp, bth0))
|
||||
if (hfi1_ruc_check_hdr(ibp, packet))
|
||||
return;
|
||||
|
||||
process_ecn(qp, packet, true);
|
||||
|
||||
psn = ib_bth_get_psn(ohdr);
|
||||
opcode = ib_bth_get_opcode(ohdr);
|
||||
|
||||
/* Compare the PSN verses the expected PSN. */
|
||||
if (unlikely(cmp_psn(psn, qp->r_psn) != 0)) {
|
||||
/*
|
||||
|
@ -432,8 +426,6 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
|
|||
wc.ex.imm_data = 0;
|
||||
wc.wc_flags = 0;
|
||||
send_last:
|
||||
/* Get the number of bytes the message was padded by. */
|
||||
pad = ib_bth_get_pad(ohdr);
|
||||
/* Check for invalid length. */
|
||||
/* LAST len should be >= 1 */
|
||||
if (unlikely(tlen < (hdrsize + pad + 4)))
|
||||
|
@ -527,8 +519,6 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
|
|||
rdma_last_imm:
|
||||
wc.wc_flags = IB_WC_WITH_IMM;
|
||||
|
||||
/* Get the number of bytes the message was padded by. */
|
||||
pad = ib_bth_get_pad(ohdr);
|
||||
/* Check for invalid length. */
|
||||
/* LAST len should be >= 1 */
|
||||
if (unlikely(tlen < (hdrsize + pad + 4)))
|
||||
|
|
|
@ -668,36 +668,31 @@ static int opa_smp_check(struct hfi1_ibport *ibp, u16 pkey, u8 sc5,
|
|||
void hfi1_ud_rcv(struct hfi1_packet *packet)
|
||||
{
|
||||
struct ib_other_headers *ohdr = packet->ohdr;
|
||||
int opcode;
|
||||
u32 hdrsize = packet->hlen;
|
||||
struct ib_wc wc;
|
||||
u32 qkey;
|
||||
u32 src_qp;
|
||||
u16 dlid, pkey;
|
||||
u16 pkey;
|
||||
int mgmt_pkey_idx = -1;
|
||||
struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd);
|
||||
struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
|
||||
struct ib_header *hdr = packet->hdr;
|
||||
u32 rcv_flags = packet->rcv_flags;
|
||||
void *data = packet->ebuf;
|
||||
u32 tlen = packet->tlen;
|
||||
struct rvt_qp *qp = packet->qp;
|
||||
bool has_grh = rcv_flags & HFI1_HAS_GRH;
|
||||
u8 sc5 = hfi1_9B_get_sc5(hdr, packet->rhf);
|
||||
u32 bth1;
|
||||
u8 sl_from_sc, sl;
|
||||
u16 slid;
|
||||
u8 extra_bytes;
|
||||
u8 sl_from_sc;
|
||||
u8 extra_bytes = packet->pad;
|
||||
u8 opcode = packet->opcode;
|
||||
u8 sl = packet->sl;
|
||||
u32 dlid = packet->dlid;
|
||||
u32 slid = packet->slid;
|
||||
|
||||
bth1 = be32_to_cpu(ohdr->bth[1]);
|
||||
qkey = ib_get_qkey(ohdr);
|
||||
src_qp = ib_get_sqpn(ohdr);
|
||||
dlid = ib_get_dlid(hdr);
|
||||
bth1 = be32_to_cpu(ohdr->bth[1]);
|
||||
slid = ib_get_slid(hdr);
|
||||
pkey = ib_bth_get_pkey(ohdr);
|
||||
opcode = ib_bth_get_opcode(ohdr);
|
||||
sl = ib_get_sl(hdr);
|
||||
extra_bytes = ib_bth_get_pad(ohdr);
|
||||
extra_bytes += (SIZE_OF_CRC << 2);
|
||||
sl_from_sc = ibp->sc_to_sl[sc5];
|
||||
|
||||
|
@ -811,7 +806,7 @@ void hfi1_ud_rcv(struct hfi1_packet *packet)
|
|||
qp->r_flags |= RVT_R_REUSE_SGE;
|
||||
goto drop;
|
||||
}
|
||||
if (has_grh) {
|
||||
if (packet->grh) {
|
||||
hfi1_copy_sge(&qp->r_sge, &hdr->u.l.grh,
|
||||
sizeof(struct ib_grh), true, false);
|
||||
wc.wc_flags |= IB_WC_GRH;
|
||||
|
|
|
@ -508,13 +508,14 @@ void hfi1_copy_sge(
|
|||
/*
|
||||
* Make sure the QP is ready and able to accept the given opcode.
|
||||
*/
|
||||
static inline opcode_handler qp_ok(int opcode, struct hfi1_packet *packet)
|
||||
static inline opcode_handler qp_ok(struct hfi1_packet *packet)
|
||||
{
|
||||
if (!(ib_rvt_state_ops[packet->qp->state] & RVT_PROCESS_RECV_OK))
|
||||
return NULL;
|
||||
if (((opcode & RVT_OPCODE_QP_MASK) == packet->qp->allowed_ops) ||
|
||||
(opcode == IB_OPCODE_CNP))
|
||||
return opcode_handler_tbl[opcode];
|
||||
if (((packet->opcode & RVT_OPCODE_QP_MASK) ==
|
||||
packet->qp->allowed_ops) ||
|
||||
(packet->opcode == IB_OPCODE_CNP))
|
||||
return opcode_handler_tbl[packet->opcode];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -548,68 +549,34 @@ static u64 hfi1_fault_tx(struct rvt_qp *qp, u8 opcode, u64 pbc)
|
|||
return pbc;
|
||||
}
|
||||
|
||||
/**
|
||||
* hfi1_ib_rcv - process an incoming packet
|
||||
* @packet: data packet information
|
||||
*
|
||||
* This is called to process an incoming packet at interrupt level.
|
||||
*
|
||||
* Tlen is the length of the header + data + CRC in bytes.
|
||||
*/
|
||||
void hfi1_ib_rcv(struct hfi1_packet *packet)
|
||||
static inline void hfi1_handle_packet(struct hfi1_packet *packet,
|
||||
bool is_mcast)
|
||||
{
|
||||
u32 qp_num;
|
||||
struct hfi1_ctxtdata *rcd = packet->rcd;
|
||||
struct ib_header *hdr = packet->hdr;
|
||||
u32 tlen = packet->tlen;
|
||||
struct hfi1_pportdata *ppd = rcd->ppd;
|
||||
struct hfi1_ibport *ibp = rcd_to_iport(rcd);
|
||||
struct rvt_dev_info *rdi = &ppd->dd->verbs_dev.rdi;
|
||||
opcode_handler packet_handler;
|
||||
unsigned long flags;
|
||||
u32 qp_num;
|
||||
int lnh;
|
||||
u8 opcode;
|
||||
u16 lid;
|
||||
|
||||
/* Check for GRH */
|
||||
lnh = ib_get_lnh(hdr);
|
||||
if (lnh == HFI1_LRH_BTH) {
|
||||
packet->ohdr = &hdr->u.oth;
|
||||
} else if (lnh == HFI1_LRH_GRH) {
|
||||
u32 vtf;
|
||||
inc_opstats(packet->tlen, &rcd->opstats->stats[packet->opcode]);
|
||||
|
||||
packet->ohdr = &hdr->u.l.oth;
|
||||
if (hdr->u.l.grh.next_hdr != IB_GRH_NEXT_HDR)
|
||||
goto drop;
|
||||
vtf = be32_to_cpu(hdr->u.l.grh.version_tclass_flow);
|
||||
if ((vtf >> IB_GRH_VERSION_SHIFT) != IB_GRH_VERSION)
|
||||
goto drop;
|
||||
packet->rcv_flags |= HFI1_HAS_GRH;
|
||||
} else {
|
||||
goto drop;
|
||||
}
|
||||
|
||||
trace_input_ibhdr(rcd->dd, packet, !!(packet->rhf & RHF_DC_INFO_SMASK));
|
||||
opcode = ib_bth_get_opcode(packet->ohdr);
|
||||
inc_opstats(tlen, &rcd->opstats->stats[opcode]);
|
||||
|
||||
/* Get the destination QP number. */
|
||||
qp_num = ib_bth_get_qpn(packet->ohdr);
|
||||
lid = ib_get_dlid(hdr);
|
||||
if (unlikely((lid >= be16_to_cpu(IB_MULTICAST_LID_BASE)) &&
|
||||
(lid != be16_to_cpu(IB_LID_PERMISSIVE)))) {
|
||||
if (unlikely(is_mcast)) {
|
||||
struct rvt_mcast *mcast;
|
||||
struct rvt_mcast_qp *p;
|
||||
|
||||
if (lnh != HFI1_LRH_GRH)
|
||||
if (!packet->grh)
|
||||
goto drop;
|
||||
mcast = rvt_mcast_find(&ibp->rvp, &hdr->u.l.grh.dgid, lid);
|
||||
mcast = rvt_mcast_find(&ibp->rvp,
|
||||
&packet->grh->dgid,
|
||||
packet->dlid);
|
||||
if (!mcast)
|
||||
goto drop;
|
||||
list_for_each_entry_rcu(p, &mcast->qp_list, list) {
|
||||
packet->qp = p->qp;
|
||||
spin_lock_irqsave(&packet->qp->r_lock, flags);
|
||||
packet_handler = qp_ok(opcode, packet);
|
||||
packet_handler = qp_ok(packet);
|
||||
if (likely(packet_handler))
|
||||
packet_handler(packet);
|
||||
else
|
||||
|
@ -623,19 +590,21 @@ void hfi1_ib_rcv(struct hfi1_packet *packet)
|
|||
if (atomic_dec_return(&mcast->refcount) <= 1)
|
||||
wake_up(&mcast->wait);
|
||||
} else {
|
||||
/* Get the destination QP number. */
|
||||
qp_num = ib_bth_get_qpn(packet->ohdr);
|
||||
rcu_read_lock();
|
||||
packet->qp = rvt_lookup_qpn(rdi, &ibp->rvp, qp_num);
|
||||
if (!packet->qp) {
|
||||
rcu_read_unlock();
|
||||
goto drop;
|
||||
}
|
||||
if (unlikely(hfi1_dbg_fault_opcode(packet->qp, opcode,
|
||||
if (unlikely(hfi1_dbg_fault_opcode(packet->qp, packet->opcode,
|
||||
true))) {
|
||||
rcu_read_unlock();
|
||||
goto drop;
|
||||
}
|
||||
spin_lock_irqsave(&packet->qp->r_lock, flags);
|
||||
packet_handler = qp_ok(opcode, packet);
|
||||
packet_handler = qp_ok(packet);
|
||||
if (likely(packet_handler))
|
||||
packet_handler(packet);
|
||||
else
|
||||
|
@ -644,11 +613,29 @@ void hfi1_ib_rcv(struct hfi1_packet *packet)
|
|||
rcu_read_unlock();
|
||||
}
|
||||
return;
|
||||
|
||||
drop:
|
||||
ibp->rvp.n_pkt_drops++;
|
||||
}
|
||||
|
||||
/**
|
||||
* hfi1_ib_rcv - process an incoming packet
|
||||
* @packet: data packet information
|
||||
*
|
||||
* This is called to process an incoming packet at interrupt level.
|
||||
*/
|
||||
void hfi1_ib_rcv(struct hfi1_packet *packet)
|
||||
{
|
||||
struct hfi1_ctxtdata *rcd = packet->rcd;
|
||||
bool is_mcast = false;
|
||||
|
||||
if (unlikely(hfi1_check_mcast(packet->dlid)))
|
||||
is_mcast = true;
|
||||
|
||||
trace_input_ibhdr(rcd->dd, packet,
|
||||
!!(packet->rhf & RHF_DC_INFO_SMASK));
|
||||
hfi1_handle_packet(packet, is_mcast);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called from a timer to check for QPs
|
||||
* which need kernel memory in order to send a packet.
|
||||
|
|
|
@ -307,8 +307,7 @@ void hfi1_rc_rcv(struct hfi1_packet *packet);
|
|||
|
||||
void hfi1_rc_hdrerr(
|
||||
struct hfi1_ctxtdata *rcd,
|
||||
struct ib_header *hdr,
|
||||
u32 rcv_flags,
|
||||
struct hfi1_packet *packet,
|
||||
struct rvt_qp *qp);
|
||||
|
||||
u8 ah_to_sc(struct ib_device *ibdev, struct rdma_ah_attr *ah_attr);
|
||||
|
@ -346,8 +345,7 @@ static inline u8 get_opcode(struct ib_header *h)
|
|||
return be32_to_cpu(h->u.l.oth.bth[0]) >> 24;
|
||||
}
|
||||
|
||||
int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct ib_header *hdr,
|
||||
int has_grh, struct rvt_qp *qp, u32 bth0);
|
||||
int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet);
|
||||
|
||||
u32 hfi1_make_grh(struct hfi1_ibport *ibp, struct ib_grh *hdr,
|
||||
const struct ib_global_route *grh, u32 hwords, u32 nwords);
|
||||
|
|
Loading…
Reference in New Issue