>From 0d3da6ad682c4655cd909aefe5bc294c55f5f711 Mon Sep 17 00:00:00 2001
From: Yevgeny Petrilin <[EMAIL PROTECTED]>
Date: Mon, 21 Apr 2008 17:40:57 +0300
Subject: [PATCH] mlx4: Different port type support

Multiprotocol supports different port types.
The port types are delivered through module parameters,
crossed with firmware capabilities.
Each consumer of mlx4_core should query for supported port types,
mlx4_ib can no longer assume that all phisical ports belong to it.

Signed-off-by: Yevgeny Petrilin <[EMAIL PROTECTED]>
---
 drivers/infiniband/hw/mlx4/mad.c     |    6 +-
 drivers/infiniband/hw/mlx4/main.c    |   12 ++++-
 drivers/infiniband/hw/mlx4/mlx4_ib.h |    2 +
 drivers/net/mlx4/fw.c                |    4 ++
 drivers/net/mlx4/fw.h                |    1 +
 drivers/net/mlx4/main.c              |   84 ++++++++++++++++++++++++++++++++++
 include/linux/mlx4/device.h          |   32 +++++++++++++
 7 files changed, 136 insertions(+), 5 deletions(-)

diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 4c1e72f..d91ba56 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -297,7 +297,7 @@ int mlx4_ib_mad_init(struct mlx4_ib_dev *dev)
        int p, q;
        int ret;

-       for (p = 0; p < dev->dev->caps.num_ports; ++p)
+       for (p = 0; p < dev->num_ports; ++p)
                for (q = 0; q <= 1; ++q) {
                        agent = ib_register_mad_agent(&dev->ib_dev, p + 1,
                                                      q ? IB_QPT_GSI : 
IB_QPT_SMI,
@@ -313,7 +313,7 @@ int mlx4_ib_mad_init(struct mlx4_ib_dev *dev)
        return 0;

 err:
-       for (p = 0; p < dev->dev->caps.num_ports; ++p)
+       for (p = 0; p < dev->num_ports; ++p)
                for (q = 0; q <= 1; ++q)
                        if (dev->send_agent[p][q])
                                ib_unregister_mad_agent(dev->send_agent[p][q]);
@@ -326,7 +326,7 @@ void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev)
        struct ib_mad_agent *agent;
        int p, q;

-       for (p = 0; p < dev->dev->caps.num_ports; ++p) {
+       for (p = 0; p < dev->num_ports; ++p) {
                for (q = 0; q <= 1; ++q) {
                        agent = dev->send_agent[p][q];
                        dev->send_agent[p][q] = NULL;
diff --git a/drivers/infiniband/hw/mlx4/main.c 
b/drivers/infiniband/hw/mlx4/main.c
index 3c7f938..507dbe3 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -549,11 +549,15 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
        MLX4_INIT_DOORBELL_LOCK(&ibdev->uar_lock);

        ibdev->dev = dev;
+       ibdev->ports_map = mlx4_get_ports_of_type(dev, MLX4_PORT_TYPE_IB);

        strlcpy(ibdev->ib_dev.name, "mlx4_%d", IB_DEVICE_NAME_MAX);
        ibdev->ib_dev.owner             = THIS_MODULE;
        ibdev->ib_dev.node_type         = RDMA_NODE_IB_CA;
-       ibdev->ib_dev.phys_port_cnt     = dev->caps.num_ports;
+       ibdev->num_ports = 0;
+       mlx4_foreach_port(i, ibdev->ports_map)
+               ibdev->num_ports++;
+       ibdev->ib_dev.phys_port_cnt     = ibdev->num_ports;
        ibdev->ib_dev.num_comp_vectors  = 1;
        ibdev->ib_dev.dma_device        = &dev->pdev->dev;

@@ -667,7 +671,7 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void 
*ibdev_ptr)
        struct mlx4_ib_dev *ibdev = ibdev_ptr;
        int p;

-       for (p = 1; p <= dev->caps.num_ports; ++p)
+       for (p = 1; p <= ibdev->num_ports; ++p)
                mlx4_CLOSE_PORT(dev, p);

        mlx4_ib_mad_cleanup(ibdev);
@@ -682,6 +686,10 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void 
*ibdev_ptr,
                          enum mlx4_dev_event event, int port)
 {
        struct ib_event ibev;
+       struct mlx4_ib_dev *ibdev = to_mdev((struct ib_device *) ibdev_ptr);
+
+       if (port > ibdev->num_ports)
+               return;

        switch (event) {
        case MLX4_DEV_EVENT_PORT_UP:
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h 
b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 5cf9947..9d4f7a7 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -155,6 +155,8 @@ struct mlx4_ib_ah {
 struct mlx4_ib_dev {
        struct ib_device        ib_dev;
        struct mlx4_dev        *dev;
+       u32                     ports_map;
+       int                     num_ports;
        void __iomem           *uar_map;

        struct mlx4_uar         priv_uar;
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index b0ad0d1..e875b08 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -322,6 +322,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct 
mlx4_dev_cap *dev_cap)
                        dev_cap->max_pkeys[i]      = 1 << (field & 0xf);
                }
        } else {
+#define QUERY_PORT_SUPPORTED_TYPE_OFFSET       0x00
 #define QUERY_PORT_MTU_OFFSET                  0x01
 #define QUERY_PORT_WIDTH_OFFSET                        0x06
 #define QUERY_PORT_MAX_GID_PKEY_OFFSET         0x07
@@ -334,6 +335,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct 
mlx4_dev_cap *dev_cap)
                        if (err)
                                goto out;

+                       MLX4_GET(field, outbox,
+                                QUERY_PORT_SUPPORTED_TYPE_OFFSET);
+                       dev_cap->supported_port_types[i] = field & 3;
                        MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET);
                        dev_cap->max_mtu[i]        = field & 0xf;
                        MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET);
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index a2e827c..50a6a7d 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -97,6 +97,7 @@ struct mlx4_dev_cap {
        u32 reserved_lkey;
        u64 max_icm_sz;
        int max_gso_sz;
+       u8  supported_port_types[MLX4_MAX_PORTS + 1];
        u8  log_max_macs[MLX4_MAX_PORTS + 1];
        u8  log_max_vlans[MLX4_MAX_PORTS + 1];
 };
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index f309532..1651d8e 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -100,11 +100,50 @@ module_param_named(use_prio, use_prio, bool, 0444);
 MODULE_PARM_DESC(use_prio, "Enable steering by VLAN priority on ETH ports "
                  "(0/1, default 0)");

+static char *port_type_arr[MLX4_MAX_PORTS] = { [0 ... (MLX4_MAX_PORTS-1)] = 
"ib"};
+module_param_array_named(port_type, port_type_arr, charp, NULL, 0444);
+MODULE_PARM_DESC(port_type, "Ports L2 type (ib/eth/auto, entry per port, "
+                 "comma seperated, default ib for all)");
+
+static int mlx4_check_port_params(struct mlx4_dev *dev,
+                                 enum mlx4_port_type *port_type)
+{
+       if (port_type[0] != port_type[1] &&
+           !(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) {
+               mlx4_err(dev, "Only same port types supported "
+                        "on this HCA, aborting.\n");
+               return -EINVAL;
+       }
+       if ((port_type[0] == MLX4_PORT_TYPE_ETH) &&
+           (port_type[1] == MLX4_PORT_TYPE_IB)) {
+               mlx4_err(dev, "eth-ib configuration is not supported.\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void mlx4_str2port_type(char **port_str,
+                              enum mlx4_port_type *port_type)
+{
+       int i;
+
+       for (i = 0; i < MLX4_MAX_PORTS; i++) {
+               if (!strcmp(port_str[i], "eth"))
+                       port_type[i] = MLX4_PORT_TYPE_ETH;
+               else
+                       port_type[i] = MLX4_PORT_TYPE_IB;
+       }
+}
+
+

 static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 {
        int err;
        int i;
+       enum mlx4_port_type port_type[MLX4_MAX_PORTS];
+
+       mlx4_str2port_type(port_type_arr, port_type);

        err = mlx4_QUERY_DEV_CAP(dev, dev_cap);
        if (err) {
@@ -180,7 +219,24 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct 
mlx4_dev_cap *dev_cap)
        dev->caps.log_num_vlans = ilog2(roundup_pow_of_two(num_vlan + 2));
        dev->caps.log_num_prios = use_prio ? 3: 0;

+       err = mlx4_check_port_params(dev, port_type);
+       if (err)
+               return err;
+
        for (i = 1; i <= dev->caps.num_ports; ++i) {
+               if (!dev_cap->supported_port_types[i]) {
+                       mlx4_warn(dev, "FW doesn't support Multi Protocol, "
+                                 "loading IB only\n");
+                       dev->caps.port_type[i] = MLX4_PORT_TYPE_IB;
+                       continue;
+               }
+               if (port_type[i-1] & dev_cap->supported_port_types[i])
+                       dev->caps.port_type[i] = port_type[i-1];
+               else {
+                       mlx4_err(dev, "Requested port type for port %d "
+                                "not supported by HW\n", i);
+                       return -ENODEV;
+               }
                if (dev->caps.log_num_macs > dev_cap->log_max_macs[i]) {
                        dev->caps.log_num_macs = dev_cap->log_max_macs[i];
                        mlx4_warn(dev, "Requested number of MACs is too much "
@@ -1004,10 +1060,38 @@ static struct pci_driver mlx4_driver = {
        .remove         = __devexit_p(mlx4_remove_one)
 };

+static int __init mlx4_verify_params(void)
+{
+       int i;
+
+       for (i = 0; i < MLX4_MAX_PORTS; ++i) {
+               if (strcmp(port_type_arr[i], "eth") &&
+                   strcmp(port_type_arr[i], "ib")) {
+                       printk(KERN_WARNING "mlx4_core: bad port_type for "
+                              "port %d: %s\n", i, port_type_arr[i]);
+                       return -1;
+               }
+       }
+       if ((num_mac < 1) || (num_mac > 127)) {
+               printk(KERN_WARNING "mlx4_core: bad num_mac: %d\n", num_mac);
+               return -1;
+       }
+
+       if ((num_vlan < 0) || (num_vlan > 126)) {
+               printk(KERN_WARNING "mlx4_core: bad num_vlan: %d\n", num_vlan);
+               return -1;
+       }
+
+       return 0;
+}
+
 static int __init mlx4_init(void)
 {
        int ret;

+       if (mlx4_verify_params())
+               return -EINVAL;
+
        ret = mlx4_catas_init();
        if (ret)
                return ret;
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 955eeca..4279b2f 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -62,6 +62,7 @@ enum {
        MLX4_DEV_CAP_FLAG_IPOIB_CSUM    = 1 <<  7,
        MLX4_DEV_CAP_FLAG_BAD_PKEY_CNTR = 1 <<  8,
        MLX4_DEV_CAP_FLAG_BAD_QKEY_CNTR = 1 <<  9,
+       MLX4_DEV_CAP_FLAG_DPDP          = 1 << 12,
        MLX4_DEV_CAP_FLAG_MEM_WINDOW    = 1 << 16,
        MLX4_DEV_CAP_FLAG_APM           = 1 << 17,
        MLX4_DEV_CAP_FLAG_ATOMIC        = 1 << 18,
@@ -143,6 +144,11 @@ enum qp_region {
        MLX4_QP_REGION_COUNT
 };

+enum mlx4_port_type {
+       MLX4_PORT_TYPE_IB       = 1 << 0,
+       MLX4_PORT_TYPE_ETH      = 1 << 1,
+};
+
 enum {
        MLX4_NUM_FEXCH          = 64 * 1024,
 };
@@ -206,6 +212,7 @@ struct mlx4_caps {
        int                     log_num_macs;
        int                     log_num_vlans;
        int                     log_num_prios;
+       enum mlx4_port_type     port_type[MLX4_MAX_PORTS + 1];
 };

 struct mlx4_buf_list {
@@ -365,6 +372,31 @@ struct mlx4_init_port_param {
        u64                     si_guid;
 };

+static inline void mlx4_query_steer_cap(struct mlx4_dev *dev, int *log_mac,
+                                       int *log_vlan, int *log_prio)
+{
+       *log_mac = dev->caps.log_num_macs;
+       *log_vlan = dev->caps.log_num_vlans;
+       *log_prio = dev->caps.log_num_prios;
+}
+
+static inline u32 mlx4_get_ports_of_type(struct mlx4_dev *dev,
+                                        enum mlx4_port_type ptype)
+{
+       u32 ret = 0;
+       int i;
+
+       for (i = 1; i <= dev->caps.num_ports; ++i) {
+               if (dev->caps.port_type[i] == ptype)
+                       ret |= 1 << (i-1);
+       }
+       return ret;
+}
+
+#define mlx4_foreach_port(port, bitmap) \
+           for ((port) = 1; (port) <= MLX4_MAX_PORTS; (port)++) \
+               if (bitmap & 1 << ((port)-1))
+
 int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct,
                   struct mlx4_buf *buf);
 void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf);
-- 
1.5.4

_______________________________________________
general mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to