RDMA/hns: Add check for SL
[sfrench/cifs-2.6.git] / drivers / infiniband / hw / hns / hns_roce_ah.c
index e77fcc74f15c49a497329a9019246d613c96007f..3df032ddda1891980a8ea8eb652b5f0d283e7218 100644 (file)
@@ -33,7 +33,9 @@
 #include <linux/pci.h>
 #include <rdma/ib_addr.h>
 #include <rdma/ib_cache.h>
+#include "hnae3.h"
 #include "hns_roce_device.h"
+#include "hns_roce_hw_v2.h"
 
 static inline u16 get_ah_udp_sport(const struct rdma_ah_attr *ah_attr)
 {
@@ -57,6 +59,7 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
        struct hns_roce_dev *hr_dev = to_hr_dev(ibah->device);
        struct hns_roce_ah *ah = to_hr_ah(ibah);
        int ret = 0;
+       u32 max_sl;
 
        if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08 && udata)
                return -EOPNOTSUPP;
@@ -70,9 +73,17 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
        ah->av.hop_limit = grh->hop_limit;
        ah->av.flowlabel = grh->flow_label;
        ah->av.udp_sport = get_ah_udp_sport(ah_attr);
-       ah->av.sl = rdma_ah_get_sl(ah_attr);
        ah->av.tclass = get_tclass(grh);
 
+       ah->av.sl = rdma_ah_get_sl(ah_attr);
+       max_sl = min_t(u32, MAX_SERVICE_LEVEL, hr_dev->caps.sl_num - 1);
+       if (unlikely(ah->av.sl > max_sl)) {
+               ibdev_err_ratelimited(&hr_dev->ib_dev,
+                                     "failed to set sl, sl (%u) shouldn't be larger than %u.\n",
+                                     ah->av.sl, max_sl);
+               return -EINVAL;
+       }
+
        memcpy(ah->av.dgid, grh->dgid.raw, HNS_ROCE_GID_SIZE);
        memcpy(ah->av.mac, ah_attr->roce.dmac, ETH_ALEN);