Merge tag 'kbuild-uapi-v4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/masahi...
[GitHub/moto-9609/android_kernel_motorola_exynos9610.git] / include / rdma / ib_sa.h
index 3ff8e64fca85fba18a5ed65ba276195151b0f27a..f5f70e345318151356e022ce46b623a357031920 100644 (file)
@@ -43,6 +43,8 @@
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_mad.h>
+#include <rdma/ib_addr.h>
+#include <rdma/opa_addr.h>
 
 enum {
        IB_SA_CLASS_VERSION             = 2,    /* IB spec version 1.1/1.2 */
@@ -148,13 +150,45 @@ enum ib_sa_mc_join_states {
 #define IB_SA_PATH_REC_PACKET_LIFE_TIME                        IB_SA_COMP_MASK(21)
 #define IB_SA_PATH_REC_PREFERENCE                      IB_SA_COMP_MASK(22)
 
-struct ib_sa_path_rec {
+enum sa_path_rec_type {
+       SA_PATH_REC_TYPE_IB,
+       SA_PATH_REC_TYPE_ROCE_V1,
+       SA_PATH_REC_TYPE_ROCE_V2,
+       SA_PATH_REC_TYPE_OPA
+};
+
+struct sa_path_rec_ib {
        __be64       service_id;
-       union ib_gid dgid;
-       union ib_gid sgid;
        __be16       dlid;
        __be16       slid;
        u8           raw_traffic;
+};
+
+struct sa_path_rec_roce {
+       u8           dmac[ETH_ALEN];
+       /* ignored in IB */
+       int          ifindex;
+       /* ignored in IB */
+       struct net  *net;
+
+};
+
+struct sa_path_rec_opa {
+       __be64       service_id;
+       __be32       dlid;
+       __be32       slid;
+       u8           raw_traffic;
+       u8           l2_8B;
+       u8           l2_10B;
+       u8           l2_9B;
+       u8           l2_16B;
+       u8           qos_type;
+       u8           qos_priority;
+};
+
+struct sa_path_rec {
+       union ib_gid dgid;
+       union ib_gid sgid;
        /* reserved */
        __be32       flow_label;
        u8           hop_limit;
@@ -171,17 +205,109 @@ struct ib_sa_path_rec {
        u8           packet_life_time_selector;
        u8           packet_life_time;
        u8           preference;
-       u8           dmac[ETH_ALEN];
-       /* ignored in IB */
-       int          ifindex;
-       /* ignored in IB */
-       struct net  *net;
-       enum ib_gid_type gid_type;
+       union {
+               struct sa_path_rec_ib ib;
+               struct sa_path_rec_roce roce;
+               struct sa_path_rec_opa opa;
+       };
+       enum sa_path_rec_type rec_type;
 };
 
-static inline struct net_device *ib_get_ndev_from_path(struct ib_sa_path_rec *rec)
+static inline enum ib_gid_type
+               sa_conv_pathrec_to_gid_type(struct sa_path_rec *rec)
+{
+       switch (rec->rec_type) {
+       case SA_PATH_REC_TYPE_ROCE_V1:
+               return IB_GID_TYPE_ROCE;
+       case SA_PATH_REC_TYPE_ROCE_V2:
+               return IB_GID_TYPE_ROCE_UDP_ENCAP;
+       default:
+               return IB_GID_TYPE_IB;
+       }
+}
+
+static inline enum sa_path_rec_type
+               sa_conv_gid_to_pathrec_type(enum ib_gid_type type)
+{
+       switch (type) {
+       case IB_GID_TYPE_ROCE:
+               return SA_PATH_REC_TYPE_ROCE_V1;
+       case IB_GID_TYPE_ROCE_UDP_ENCAP:
+               return SA_PATH_REC_TYPE_ROCE_V2;
+       default:
+               return SA_PATH_REC_TYPE_IB;
+       }
+}
+
+static inline void path_conv_opa_to_ib(struct sa_path_rec *ib,
+                                      struct sa_path_rec *opa)
+{
+       if ((be32_to_cpu(opa->opa.dlid) >=
+            be16_to_cpu(IB_MULTICAST_LID_BASE)) ||
+           (be32_to_cpu(opa->opa.slid) >=
+            be16_to_cpu(IB_MULTICAST_LID_BASE))) {
+               /* Create OPA GID and zero out the LID */
+               ib->dgid.global.interface_id
+                               = OPA_MAKE_ID(be32_to_cpu(opa->opa.dlid));
+               ib->dgid.global.subnet_prefix
+                               = opa->dgid.global.subnet_prefix;
+               ib->sgid.global.interface_id
+                               = OPA_MAKE_ID(be32_to_cpu(opa->opa.slid));
+               ib->dgid.global.subnet_prefix
+                               = opa->dgid.global.subnet_prefix;
+               ib->ib.dlid     = 0;
+
+               ib->ib.slid     = 0;
+       } else {
+               ib->ib.dlid     = htons(ntohl(opa->opa.dlid));
+               ib->ib.slid     = htons(ntohl(opa->opa.slid));
+       }
+       ib->ib.service_id       = opa->opa.service_id;
+       ib->ib.raw_traffic      = opa->opa.raw_traffic;
+}
+
+static inline void path_conv_ib_to_opa(struct sa_path_rec *opa,
+                                      struct sa_path_rec *ib)
 {
-       return rec->net ? dev_get_by_index(rec->net, rec->ifindex) : NULL;
+       __be32 slid, dlid;
+
+       if ((ib_is_opa_gid(&ib->sgid)) ||
+           (ib_is_opa_gid(&ib->dgid))) {
+               slid = htonl(opa_get_lid_from_gid(&ib->sgid));
+               dlid = htonl(opa_get_lid_from_gid(&ib->dgid));
+       } else {
+               slid = htonl(ntohs(ib->ib.slid));
+               dlid = htonl(ntohs(ib->ib.dlid));
+       }
+       opa->opa.slid           = slid;
+       opa->opa.dlid           = dlid;
+       opa->opa.service_id     = ib->ib.service_id;
+       opa->opa.raw_traffic    = ib->ib.raw_traffic;
+}
+
+/* Convert from OPA to IB path record */
+static inline void sa_convert_path_opa_to_ib(struct sa_path_rec *dest,
+                                            struct sa_path_rec *src)
+{
+       if (src->rec_type != SA_PATH_REC_TYPE_OPA)
+               return;
+
+       *dest = *src;
+       dest->rec_type = SA_PATH_REC_TYPE_IB;
+       path_conv_opa_to_ib(dest, src);
+}
+
+/* Convert from IB to OPA path record */
+static inline void sa_convert_path_ib_to_opa(struct sa_path_rec *dest,
+                                            struct sa_path_rec *src)
+{
+       if (src->rec_type != SA_PATH_REC_TYPE_IB)
+               return;
+
+       /* Do a structure copy and overwrite the relevant fields */
+       *dest = *src;
+       dest->rec_type = SA_PATH_REC_TYPE_OPA;
+       path_conv_ib_to_opa(dest, src);
 }
 
 #define IB_SA_MCMEMBER_REC_MGID                                IB_SA_COMP_MASK( 0)
@@ -323,11 +449,11 @@ void ib_sa_cancel_query(int id, struct ib_sa_query *query);
 
 int ib_sa_path_rec_get(struct ib_sa_client *client,
                       struct ib_device *device, u8 port_num,
-                      struct ib_sa_path_rec *rec,
+                      struct sa_path_rec *rec,
                       ib_sa_comp_mask comp_mask,
                       int timeout_ms, gfp_t gfp_mask,
                       void (*callback)(int status,
-                                       struct ib_sa_path_rec *resp,
+                                       struct sa_path_rec *resp,
                                        void *context),
                       void *context,
                       struct ib_sa_query **query);
@@ -428,20 +554,20 @@ int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
  *   path record.
  */
 int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
-                        struct ib_sa_path_rec *rec,
+                        struct sa_path_rec *rec,
                         struct rdma_ah_attr *ah_attr);
 
 /**
  * ib_sa_pack_path - Conert a path record from struct ib_sa_path_rec
  * to IB MAD wire format.
  */
-void ib_sa_pack_path(struct ib_sa_path_rec *rec, void *attribute);
+void ib_sa_pack_path(struct sa_path_rec *rec, void *attribute);
 
 /**
  * ib_sa_unpack_path - Convert a path record from MAD format to struct
  * ib_sa_path_rec.
  */
-void ib_sa_unpack_path(void *attribute, struct ib_sa_path_rec *rec);
+void ib_sa_unpack_path(void *attribute, struct sa_path_rec *rec);
 
 /* Support GuidInfoRecord */
 int ib_sa_guid_info_rec_query(struct ib_sa_client *client,
@@ -459,4 +585,133 @@ bool ib_sa_sendonly_fullmem_support(struct ib_sa_client *client,
                                    struct ib_device *device,
                                    u8 port_num);
 
+static inline bool sa_path_is_roce(struct sa_path_rec *rec)
+{
+       return ((rec->rec_type == SA_PATH_REC_TYPE_ROCE_V1) ||
+               (rec->rec_type == SA_PATH_REC_TYPE_ROCE_V2));
+}
+
+static inline void sa_path_set_service_id(struct sa_path_rec *rec,
+                                         __be64 service_id)
+{
+       if (rec->rec_type == SA_PATH_REC_TYPE_IB)
+               rec->ib.service_id = service_id;
+       else if (rec->rec_type == SA_PATH_REC_TYPE_OPA)
+               rec->opa.service_id = service_id;
+}
+
+static inline void sa_path_set_slid(struct sa_path_rec *rec, __be32 slid)
+{
+       if (rec->rec_type == SA_PATH_REC_TYPE_IB)
+               rec->ib.slid = htons(ntohl(slid));
+       else if (rec->rec_type == SA_PATH_REC_TYPE_OPA)
+               rec->opa.slid = slid;
+}
+
+static inline void sa_path_set_dlid(struct sa_path_rec *rec, __be32 dlid)
+{
+       if (rec->rec_type == SA_PATH_REC_TYPE_IB)
+               rec->ib.dlid = htons(ntohl(dlid));
+       else if (rec->rec_type == SA_PATH_REC_TYPE_OPA)
+               rec->opa.dlid = dlid;
+}
+
+static inline void sa_path_set_raw_traffic(struct sa_path_rec *rec,
+                                          u8 raw_traffic)
+{
+       if (rec->rec_type == SA_PATH_REC_TYPE_IB)
+               rec->ib.raw_traffic = raw_traffic;
+       else if (rec->rec_type == SA_PATH_REC_TYPE_OPA)
+               rec->opa.raw_traffic = raw_traffic;
+}
+
+static inline __be64 sa_path_get_service_id(struct sa_path_rec *rec)
+{
+       if (rec->rec_type == SA_PATH_REC_TYPE_IB)
+               return rec->ib.service_id;
+       else if (rec->rec_type == SA_PATH_REC_TYPE_OPA)
+               return rec->opa.service_id;
+       return 0;
+}
+
+static inline __be32 sa_path_get_slid(struct sa_path_rec *rec)
+{
+       if (rec->rec_type == SA_PATH_REC_TYPE_IB)
+               return htonl(ntohs(rec->ib.slid));
+       else if (rec->rec_type == SA_PATH_REC_TYPE_OPA)
+               return rec->opa.slid;
+       return 0;
+}
+
+static inline __be32 sa_path_get_dlid(struct sa_path_rec *rec)
+{
+       if (rec->rec_type == SA_PATH_REC_TYPE_IB)
+               return htonl(ntohs(rec->ib.dlid));
+       else if (rec->rec_type == SA_PATH_REC_TYPE_OPA)
+               return rec->opa.dlid;
+       return 0;
+}
+
+static inline u8 sa_path_get_raw_traffic(struct sa_path_rec *rec)
+{
+       if (rec->rec_type == SA_PATH_REC_TYPE_IB)
+               return rec->ib.raw_traffic;
+       else if (rec->rec_type == SA_PATH_REC_TYPE_OPA)
+               return rec->opa.raw_traffic;
+       return 0;
+}
+
+static inline void sa_path_set_dmac(struct sa_path_rec *rec, u8 *dmac)
+{
+       if (sa_path_is_roce(rec))
+               memcpy(rec->roce.dmac, dmac, ETH_ALEN);
+}
+
+static inline void sa_path_set_dmac_zero(struct sa_path_rec *rec)
+{
+       if (sa_path_is_roce(rec))
+               eth_zero_addr(rec->roce.dmac);
+}
+
+static inline void sa_path_set_ifindex(struct sa_path_rec *rec, int ifindex)
+{
+       if (sa_path_is_roce(rec))
+               rec->roce.ifindex = ifindex;
+}
+
+static inline void sa_path_set_ndev(struct sa_path_rec *rec, struct net *net)
+{
+       if (sa_path_is_roce(rec))
+               rec->roce.net = net;
+}
+
+static inline u8 *sa_path_get_dmac(struct sa_path_rec *rec)
+{
+       if (sa_path_is_roce(rec))
+               return rec->roce.dmac;
+       return NULL;
+}
+
+static inline int sa_path_get_ifindex(struct sa_path_rec *rec)
+{
+       if (sa_path_is_roce(rec))
+               return rec->roce.ifindex;
+       return 0;
+}
+
+static inline struct net *sa_path_get_ndev(struct sa_path_rec *rec)
+{
+       if (sa_path_is_roce(rec))
+               return rec->roce.net;
+       return NULL;
+}
+
+static inline struct net_device *ib_get_ndev_from_path(struct sa_path_rec *rec)
+{
+       return sa_path_get_ndev(rec) ?
+               dev_get_by_index(sa_path_get_ndev(rec),
+                                sa_path_get_ifindex(rec))
+               : NULL;
+}
+
 #endif /* IB_SA_H */