aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/hfi1/driver.c
diff options
context:
space:
mode:
authorDon Hiatt <don.hiatt@intel.com>2017-08-04 13:54:10 -0700
committerDoug Ledford <dledford@redhat.com>2017-08-22 14:22:37 -0400
commit5786adf3fde7aa22a68eedac9c59e40da76ffbfb (patch)
treedfa52895b4f06e5eae1c1db86c51a8a946380c35 /drivers/infiniband/hw/hfi1/driver.c
parentIB/hfi1: Add support to send 16B bypass packets (diff)
downloadlinux-dev-5786adf3fde7aa22a68eedac9c59e40da76ffbfb.tar.xz
linux-dev-5786adf3fde7aa22a68eedac9c59e40da76ffbfb.zip
IB/hfi1: Add support to process 16B header errors
Enhance hdr_rcverr() to also handle errors during 16B bypass packet receive. 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>
Diffstat (limited to '')
-rw-r--r--drivers/infiniband/hw/hfi1/driver.c58
1 files changed, 47 insertions, 11 deletions
diff --git a/drivers/infiniband/hw/hfi1/driver.c b/drivers/infiniband/hw/hfi1/driver.c
index 5280d82c344e..ae6a90d2a31c 100644
--- a/drivers/infiniband/hw/hfi1/driver.c
+++ b/drivers/infiniband/hw/hfi1/driver.c
@@ -269,8 +269,7 @@ 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);
- u8 lnh = ib_get_lnh(rhdr);
- bool has_grh = false;
+ u32 mlid_base;
struct hfi1_ibport *ibp = rcd_to_iport(rcd);
struct hfi1_devdata *dd = ppd->dd;
struct rvt_dev_info *rdi = &dd->verbs_dev.rdi;
@@ -278,14 +277,20 @@ 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 {
+ if (packet->etype == RHF_RCV_TYPE_BYPASS) {
goto drop;
+ } else {
+ u8 lnh = ib_get_lnh(rhdr);
+
+ mlid_base = be16_to_cpu(IB_MULTICAST_LID_BASE);
+ if (lnh == HFI1_LRH_BTH) {
+ packet->ohdr = &rhdr->u.oth;
+ } else if (lnh == HFI1_LRH_GRH) {
+ packet->ohdr = &rhdr->u.l.oth;
+ packet->grh = &rhdr->u.l.grh;
+ } else {
+ goto drop;
+ }
}
if (packet->rhf & RHF_TID_ERR) {
@@ -293,14 +298,13 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
u32 tlen = rhf_pkt_len(packet->rhf); /* in bytes */
u32 dlid = ib_get_dlid(rhdr);
u32 qp_num;
- u32 mlid_base = be16_to_cpu(IB_MULTICAST_LID_BASE);
/* Sanity check packet */
if (tlen < 24)
goto drop;
/* Check for GRH */
- if (has_grh) {
+ if (packet->grh) {
u32 vtf;
struct ib_grh *grh = packet->grh;
@@ -1370,6 +1374,35 @@ static inline void hfi1_setup_ib_header(struct hfi1_packet *packet)
packet->hlen = (u8 *)packet->rhf_addr - (u8 *)packet->hdr;
}
+static int hfi1_bypass_ingress_pkt_check(struct hfi1_packet *packet)
+{
+ struct hfi1_pportdata *ppd = packet->rcd->ppd;
+
+ /* slid and dlid cannot be 0 */
+ if ((!packet->slid) || (!packet->dlid))
+ return -EINVAL;
+
+ /* Compare port lid with incoming packet dlid */
+ if ((!(hfi1_is_16B_mcast(packet->dlid))) &&
+ (packet->dlid !=
+ opa_get_lid(be32_to_cpu(OPA_LID_PERMISSIVE), 16B))) {
+ if (packet->dlid != ppd->lid)
+ return -EINVAL;
+ }
+
+ /* No multicast packets with SC15 */
+ if ((hfi1_is_16B_mcast(packet->dlid)) && (packet->sc == 0xF))
+ return -EINVAL;
+
+ /* Packets with permissive DLID always on SC15 */
+ if ((packet->dlid == opa_get_lid(be32_to_cpu(OPA_LID_PERMISSIVE),
+ 16B)) &&
+ (packet->sc != 0xF))
+ return -EINVAL;
+
+ return 0;
+}
+
static int hfi1_setup_9B_packet(struct hfi1_packet *packet)
{
struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd);
@@ -1479,6 +1512,9 @@ static int hfi1_setup_bypass_packet(struct hfi1_packet *packet)
packet->fecn = hfi1_16B_get_fecn(packet->hdr);
packet->becn = hfi1_16B_get_becn(packet->hdr);
+ if (hfi1_bypass_ingress_pkt_check(packet))
+ goto drop;
+
return 0;
drop:
hfi1_cdbg(PKT, "%s: packet dropped\n", __func__);