mlxsw: pci: Allow to use CQEs of version 1 and version 2
authorJiri Pirko <jiri@mellanox.com>
Thu, 3 May 2018 11:59:41 +0000 (14:59 +0300)
committerDavid S. Miller <davem@davemloft.net>
Thu, 3 May 2018 17:44:43 +0000 (13:44 -0400)
Use previously added resources to query FW support for multiple versions
of CQEs. Use the biggest version supported. For SDQs, it has no sense to
use version 2 as it does not introduce any new features, but it is
twice the size of CQE version 1.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/cmd.h
drivers/net/ethernet/mellanox/mlxsw/pci.c

index 479511c..669226b 100644 (file)
@@ -662,6 +662,12 @@ MLXSW_ITEM32(cmd_mbox, config_profile, set_kvd_hash_single_size, 0x0C, 25, 1);
  */
 MLXSW_ITEM32(cmd_mbox, config_profile, set_kvd_hash_double_size, 0x0C, 26, 1);
 
+/* cmd_mbox_config_set_cqe_version
+ * Capability bit. Setting a bit to 1 configures the profile
+ * according to the mailbox contents.
+ */
+MLXSW_ITEM32(cmd_mbox, config_profile, set_cqe_version, 0x08, 0, 1);
+
 /* cmd_mbox_config_profile_max_vepa_channels
  * Maximum number of VEPA channels per port (0 through 16)
  * 0 - multi-channel VEPA is disabled
@@ -841,6 +847,14 @@ MLXSW_ITEM32_INDEXED(cmd_mbox, config_profile, swid_config_type,
 MLXSW_ITEM32_INDEXED(cmd_mbox, config_profile, swid_config_properties,
                     0x60, 0, 8, 0x08, 0x00, false);
 
+/* cmd_mbox_config_profile_cqe_version
+ * CQE version:
+ * 0: CQE version is 0
+ * 1: CQE version is either 1 or 2
+ * CQE ver 1 or 2 is configured by Completion Queue Context field cqe_ver.
+ */
+MLXSW_ITEM32(cmd_mbox, config_profile, cqe_version, 0xB0, 0, 8);
+
 /* ACCESS_REG - Access EMAD Supported Register
  * ----------------------------------
  * OpMod == 0 (N/A), INMmod == 0 (N/A)
@@ -1032,11 +1046,15 @@ static inline int mlxsw_cmd_sw2hw_cq(struct mlxsw_core *mlxsw_core,
                                 0, cq_number, in_mbox, MLXSW_CMD_MBOX_SIZE);
 }
 
-/* cmd_mbox_sw2hw_cq_cv
+enum mlxsw_cmd_mbox_sw2hw_cq_cqe_ver {
+       MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_1,
+       MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_2,
+};
+
+/* cmd_mbox_sw2hw_cq_cqe_ver
  * CQE Version.
- * 0 - CQE Version 0, 1 - CQE Version 1
  */
-MLXSW_ITEM32(cmd_mbox, sw2hw_cq, cv, 0x00, 28, 4);
+MLXSW_ITEM32(cmd_mbox, sw2hw_cq, cqe_ver, 0x00, 28, 4);
 
 /* cmd_mbox_sw2hw_cq_c_eqn
  * Event Queue this CQ reports completion events to.
index 24686ba..e9ce0e2 100644 (file)
@@ -156,6 +156,8 @@ struct mlxsw_pci {
        } cmd;
        struct mlxsw_bus_info bus_info;
        const struct pci_device_id *id;
+       enum mlxsw_pci_cqe_v max_cqe_ver; /* Maximal supported CQE version */
+       u8 num_sdq_cqs; /* Number of CQs used for SDQs */
 };
 
 static void mlxsw_pci_queue_tasklet_schedule(struct mlxsw_pci_queue *q)
@@ -477,6 +479,17 @@ static void mlxsw_pci_rdq_fini(struct mlxsw_pci *mlxsw_pci,
        }
 }
 
+static void mlxsw_pci_cq_pre_init(struct mlxsw_pci *mlxsw_pci,
+                                 struct mlxsw_pci_queue *q)
+{
+       q->u.cq.v = mlxsw_pci->max_cqe_ver;
+
+       /* For SDQ it is pointless to use CQEv2, so use CQEv1 instead */
+       if (q->u.cq.v == MLXSW_PCI_CQE_V2 &&
+           q->num < mlxsw_pci->num_sdq_cqs)
+               q->u.cq.v = MLXSW_PCI_CQE_V1;
+}
+
 static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
                             struct mlxsw_pci_queue *q)
 {
@@ -491,7 +504,13 @@ static int mlxsw_pci_cq_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
                mlxsw_pci_cqe_owner_set(q->u.cq.v, elem, 1);
        }
 
-       mlxsw_cmd_mbox_sw2hw_cq_cv_set(mbox, 0); /* CQE ver 0 */
+       if (q->u.cq.v == MLXSW_PCI_CQE_V1)
+               mlxsw_cmd_mbox_sw2hw_cq_cqe_ver_set(mbox,
+                               MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_1);
+       else if (q->u.cq.v == MLXSW_PCI_CQE_V2)
+               mlxsw_cmd_mbox_sw2hw_cq_cqe_ver_set(mbox,
+                               MLXSW_CMD_MBOX_SW2HW_CQ_CQE_VER_2);
+
        mlxsw_cmd_mbox_sw2hw_cq_c_eqn_set(mbox, MLXSW_PCI_EQ_COMP_NUM);
        mlxsw_cmd_mbox_sw2hw_cq_st_set(mbox, 0);
        mlxsw_cmd_mbox_sw2hw_cq_log_cq_size_set(mbox, ilog2(q->count));
@@ -643,6 +662,18 @@ static void mlxsw_pci_cq_tasklet(unsigned long data)
        }
 }
 
+static u16 mlxsw_pci_cq_elem_count(const struct mlxsw_pci_queue *q)
+{
+       return q->u.cq.v == MLXSW_PCI_CQE_V2 ? MLXSW_PCI_CQE2_COUNT :
+                                              MLXSW_PCI_CQE01_COUNT;
+}
+
+static u8 mlxsw_pci_cq_elem_size(const struct mlxsw_pci_queue *q)
+{
+       return q->u.cq.v == MLXSW_PCI_CQE_V2 ? MLXSW_PCI_CQE2_SIZE :
+                                              MLXSW_PCI_CQE01_SIZE;
+}
+
 static int mlxsw_pci_eq_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
                             struct mlxsw_pci_queue *q)
 {
@@ -755,11 +786,15 @@ static void mlxsw_pci_eq_tasklet(unsigned long data)
 struct mlxsw_pci_queue_ops {
        const char *name;
        enum mlxsw_pci_queue_type type;
+       void (*pre_init)(struct mlxsw_pci *mlxsw_pci,
+                        struct mlxsw_pci_queue *q);
        int (*init)(struct mlxsw_pci *mlxsw_pci, char *mbox,
                    struct mlxsw_pci_queue *q);
        void (*fini)(struct mlxsw_pci *mlxsw_pci,
                     struct mlxsw_pci_queue *q);
        void (*tasklet)(unsigned long data);
+       u16 (*elem_count_f)(const struct mlxsw_pci_queue *q);
+       u8 (*elem_size_f)(const struct mlxsw_pci_queue *q);
        u16 elem_count;
        u8 elem_size;
 };
@@ -782,11 +817,12 @@ static const struct mlxsw_pci_queue_ops mlxsw_pci_rdq_ops = {
 
 static const struct mlxsw_pci_queue_ops mlxsw_pci_cq_ops = {
        .type           = MLXSW_PCI_QUEUE_TYPE_CQ,
+       .pre_init       = mlxsw_pci_cq_pre_init,
        .init           = mlxsw_pci_cq_init,
        .fini           = mlxsw_pci_cq_fini,
        .tasklet        = mlxsw_pci_cq_tasklet,
-       .elem_count     = MLXSW_PCI_CQE01_COUNT,
-       .elem_size      = MLXSW_PCI_CQE01_SIZE
+       .elem_count_f   = mlxsw_pci_cq_elem_count,
+       .elem_size_f    = mlxsw_pci_cq_elem_size
 };
 
 static const struct mlxsw_pci_queue_ops mlxsw_pci_eq_ops = {
@@ -806,12 +842,15 @@ static int mlxsw_pci_queue_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
        int i;
        int err;
 
-       q->u.cq.v = MLXSW_PCI_CQE_V0;
+       q->num = q_num;
+       if (q_ops->pre_init)
+               q_ops->pre_init(mlxsw_pci, q);
 
        spin_lock_init(&q->lock);
-       q->num = q_num;
-       q->count = q_ops->elem_count;
-       q->elem_size = q_ops->elem_size;
+       q->count = q_ops->elem_count_f ? q_ops->elem_count_f(q) :
+                                        q_ops->elem_count;
+       q->elem_size = q_ops->elem_size_f ? q_ops->elem_size_f(q) :
+                                           q_ops->elem_size;
        q->type = q_ops->type;
        q->pci = mlxsw_pci;
 
@@ -840,7 +879,7 @@ static int mlxsw_pci_queue_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
 
                elem_info = mlxsw_pci_queue_elem_info_get(q, i);
                elem_info->elem =
-                       __mlxsw_pci_queue_elem_get(q, q_ops->elem_size, i);
+                       __mlxsw_pci_queue_elem_get(q, q->elem_size, i);
        }
 
        mlxsw_cmd_mbox_zero(mbox);
@@ -952,6 +991,8 @@ static int mlxsw_pci_aqs_init(struct mlxsw_pci *mlxsw_pci, char *mbox)
                return -EINVAL;
        }
 
+       mlxsw_pci->num_sdq_cqs = num_sdqs;
+
        err = mlxsw_pci_queue_group_init(mlxsw_pci, mbox, &mlxsw_pci_eq_ops,
                                         num_eqs);
        if (err) {
@@ -1192,6 +1233,11 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox,
                mlxsw_pci_config_profile_swid_config(mlxsw_pci, mbox, i,
                                                     &profile->swid_config[i]);
 
+       if (mlxsw_pci->max_cqe_ver > MLXSW_PCI_CQE_V0) {
+               mlxsw_cmd_mbox_config_profile_set_cqe_version_set(mbox, 1);
+               mlxsw_cmd_mbox_config_profile_cqe_version_set(mbox, 1);
+       }
+
        return mlxsw_cmd_config_profile_set(mlxsw_pci->core, mbox);
 }
 
@@ -1386,6 +1432,21 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
        if (err)
                goto err_query_resources;
 
+       if (MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V2) &&
+           MLXSW_CORE_RES_GET(mlxsw_core, CQE_V2))
+               mlxsw_pci->max_cqe_ver = MLXSW_PCI_CQE_V2;
+       else if (MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V1) &&
+                MLXSW_CORE_RES_GET(mlxsw_core, CQE_V1))
+               mlxsw_pci->max_cqe_ver = MLXSW_PCI_CQE_V1;
+       else if ((MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V0) &&
+                 MLXSW_CORE_RES_GET(mlxsw_core, CQE_V0)) ||
+                !MLXSW_CORE_RES_VALID(mlxsw_core, CQE_V0)) {
+               mlxsw_pci->max_cqe_ver = MLXSW_PCI_CQE_V0;
+       } else {
+               dev_err(&pdev->dev, "Invalid supported CQE version combination reported\n");
+               goto err_cqe_v_check;
+       }
+
        err = mlxsw_pci_config_profile(mlxsw_pci, mbox, profile, res);
        if (err)
                goto err_config_profile;
@@ -1408,6 +1469,7 @@ err_request_eq_irq:
        mlxsw_pci_aqs_fini(mlxsw_pci);
 err_aqs_init:
 err_config_profile:
+err_cqe_v_check:
 err_query_resources:
 err_boardinfo:
        mlxsw_pci_fw_area_fini(mlxsw_pci);