qlcnic: dcb: Get DCB parameters from the adapter.
authorSucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Fri, 23 Aug 2013 17:38:26 +0000 (13:38 -0400)
committerDavid S. Miller <davem@davemloft.net>
Tue, 27 Aug 2013 19:21:14 +0000 (15:21 -0400)
o Populate driver data structures with local, operational, and peer
  DCB parameters.

Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c

index 2196279b2a18f6c1a729142f10671abdf8133201..fc2972c89e7336fa0d13e16527e0bdad2ad19fc7 100644 (file)
@@ -2142,4 +2142,25 @@ static inline void qlcnic_dcb_get_info(struct qlcnic_adapter *adapter)
        if (dcb && dcb->ops->get_info)
                dcb->ops->get_info(adapter);
 }
+
+static inline int
+qlcnic_dcb_query_cee_param(struct qlcnic_adapter *adapter, char *buf, u8 type)
+{
+       struct qlcnic_dcb *dcb = adapter->dcb;
+
+       if (dcb && dcb->ops->query_cee_param)
+               return dcb->ops->query_cee_param(adapter, buf, type);
+
+       return 0;
+}
+
+static inline int qlcnic_dcb_get_cee_cfg(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_dcb *dcb = adapter->dcb;
+
+       if (dcb && dcb->ops->get_cee_cfg)
+               return dcb->ops->get_cee_cfg(adapter);
+
+       return 0;
+}
 #endif                         /* __QLCNIC_H_ */
index d6d1b10537ea4da8740cca3741d7a97d6da72924..9b27ed89a9bf2e8535f15d63f6c5e32fc7a25b58 100644 (file)
@@ -68,6 +68,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
        {QLCNIC_CMD_CONFIG_VPORT, 4, 4},
        {QLCNIC_CMD_BC_EVENT_SETUP, 2, 1},
        {QLCNIC_CMD_DCB_QUERY_CAP, 1, 2},
+       {QLCNIC_CMD_DCB_QUERY_PARAM, 2, 50},
 };
 
 const u32 qlcnic_83xx_ext_reg_tbl[] = {
index 4af37847213ba3b6900630995507380fdabb920f..bf3b17eaf8b884031911544ac482f5e2d65eb04e 100644 (file)
@@ -40,6 +40,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = {
        {QLCNIC_CMD_GET_LED_STATUS, 4, 2},
        {QLCNIC_CMD_MQ_TX_CONFIG_INTR, 2, 3},
        {QLCNIC_CMD_DCB_QUERY_CAP, 1, 2},
+       {QLCNIC_CMD_DCB_QUERY_PARAM, 4, 1},
 };
 
 static inline u32 qlcnic_get_cmd_signature(struct qlcnic_hardware_context *ahw)
index 121e492f2f8782553a3c703ce1b53ce427a93b6e..e43866f20bbb2448c64d4830504b9d3860035794 100644 (file)
@@ -5,9 +5,14 @@
  * See LICENSE.qlcnic for copyright and licensing details.
  */
 
+#include <linux/types.h>
 #include "qlcnic.h"
 
+#define QLC_DCB_NUM_PARAM              3
+
+#define QLC_DCB_FW_VER                 0x2
 #define QLC_DCB_MAX_TC                 0x8
+#define QLC_DCB_MAX_APP                        0x8
 
 #define QLC_DCB_TSA_SUPPORT(V)         (V & 0x1)
 #define QLC_DCB_ETS_SUPPORT(V)         ((V >> 1) & 0x1)
 #define QLC_DCB_MAX_NUM_TC(V)          ((V >> 20) & 0xf)
 #define QLC_DCB_MAX_NUM_ETS_TC(V)      ((V >> 24) & 0xf)
 #define QLC_DCB_MAX_NUM_PFC_TC(V)      ((V >> 28) & 0xf)
+#define QLC_DCB_GET_TC_PRIO(X, P)      ((X >> (P * 3)) & 0x7)
+#define QLC_DCB_GET_PGID_PRIO(X, P)    ((X >> (P * 8)) & 0xff)
+#define QLC_DCB_GET_BWPER_PG(X, P)     ((X >> (P * 8)) & 0xff)
+#define QLC_DCB_GET_TSA_PG(X, P)       ((X >> (P * 8)) & 0xff)
+#define QLC_DCB_GET_PFC_PRIO(X, P)     (((X >> 24) >> P) & 0x1)
+#define QLC_DCB_GET_PROTO_ID_APP(X)    ((X >> 8) & 0xffff)
+#define QLC_DCB_GET_SELECTOR_APP(X)    (X & 0xff)
+
+#define QLC_DCB_LOCAL_PARAM_FWID       0x3
+#define QLC_DCB_OPER_PARAM_FWID                0x1
+#define QLC_DCB_PEER_PARAM_FWID                0x2
+
+#define QLC_83XX_DCB_GET_NUMAPP(X)     ((X >> 2) & 0xf)
+#define QLC_83XX_DCB_TSA_VALID(X)      (X & 0x1)
+#define QLC_83XX_DCB_PFC_VALID(X)      ((X >> 1) & 0x1)
+#define QLC_83XX_DCB_GET_PRIOMAP_APP(X)        (X >> 24)
+
+#define QLC_82XX_DCB_GET_NUMAPP(X)     ((X >> 12) & 0xf)
+#define QLC_82XX_DCB_TSA_VALID(X)      ((X >> 4) & 0x1)
+#define QLC_82XX_DCB_PFC_VALID(X)      ((X >> 5) & 0x1)
+#define QLC_82XX_DCB_GET_PRIOVAL_APP(X)        ((X >> 24) & 0x7)
+#define QLC_82XX_DCB_GET_PRIOMAP_APP(X)        (1 << X)
+#define QLC_82XX_DCB_PRIO_TC_MAP       (0x76543210)
 
 static void __qlcnic_dcb_free(struct qlcnic_adapter *);
 static int __qlcnic_dcb_attach(struct qlcnic_adapter *);
@@ -22,8 +50,12 @@ static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *, char *);
 static void __qlcnic_dcb_get_info(struct qlcnic_adapter *);
 
 static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *);
+static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_adapter *, char *, u8);
+static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *);
 
 static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *);
+static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_adapter *, char *, u8);
+static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_adapter *);
 
 struct qlcnic_dcb_capability {
        bool    tsa_capability;
@@ -34,6 +66,28 @@ struct qlcnic_dcb_capability {
        u8      dcb_capability;
 };
 
+struct qlcnic_dcb_param {
+       u32 hdr_prio_pfc_map[2];
+       u32 prio_pg_map[2];
+       u32 pg_bw_map[2];
+       u32 pg_tsa_map[2];
+       u32 app[QLC_DCB_MAX_APP];
+};
+
+struct qlcnic_dcb_mbx_params {
+       /* 1st local, 2nd operational 3rd remote */
+       struct qlcnic_dcb_param type[3];
+       u32 prio_tc_map;
+};
+
+struct qlcnic_82xx_dcb_param_mbx_le {
+       __le32 hdr_prio_pfc_map[2];
+       __le32 prio_pg_map[2];
+       __le32 pg_bw_map[2];
+       __le32 pg_tsa_map[2];
+       __le32 app[QLC_DCB_MAX_APP];
+};
+
 struct qlcnic_dcb_cfg {
        struct qlcnic_dcb_capability capability;
        u32 version;
@@ -46,6 +100,8 @@ static struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = {
        .get_info               = __qlcnic_dcb_get_info,
 
        .get_hw_capability      = qlcnic_83xx_dcb_get_hw_capability,
+       .query_cee_param        = qlcnic_83xx_dcb_query_cee_param,
+       .get_cee_cfg            = qlcnic_83xx_dcb_get_cee_cfg,
 };
 
 static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = {
@@ -55,8 +111,18 @@ static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = {
        .get_info               = __qlcnic_dcb_get_info,
 
        .get_hw_capability      = qlcnic_82xx_dcb_get_hw_capability,
+       .query_cee_param        = qlcnic_82xx_dcb_query_cee_param,
+       .get_cee_cfg            = qlcnic_82xx_dcb_get_cee_cfg,
 };
 
+static u8 qlcnic_dcb_get_num_app(struct qlcnic_adapter *adapter, u32 val)
+{
+       if (qlcnic_82xx_check(adapter))
+               return QLC_82XX_DCB_GET_NUMAPP(val);
+       else
+               return QLC_83XX_DCB_GET_NUMAPP(val);
+}
+
 void qlcnic_set_dcb_ops(struct qlcnic_adapter *adapter)
 {
        if (qlcnic_82xx_check(adapter))
@@ -88,6 +154,8 @@ static void __qlcnic_dcb_free(struct qlcnic_adapter *adapter)
 
        kfree(dcb->cfg);
        dcb->cfg = NULL;
+       kfree(dcb->param);
+       dcb->param = NULL;
        kfree(dcb);
        adapter->dcb = NULL;
 }
@@ -95,19 +163,32 @@ static void __qlcnic_dcb_free(struct qlcnic_adapter *adapter)
 static void __qlcnic_dcb_get_info(struct qlcnic_adapter *adapter)
 {
        qlcnic_dcb_get_hw_capability(adapter);
+       qlcnic_dcb_get_cee_cfg(adapter);
 }
 
 static int __qlcnic_dcb_attach(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_dcb *dcb = adapter->dcb;
+       int err = 0;
 
        dcb->cfg = kzalloc(sizeof(struct qlcnic_dcb_cfg), GFP_ATOMIC);
        if (!dcb->cfg)
                return -ENOMEM;
 
+       dcb->param = kzalloc(sizeof(struct qlcnic_dcb_mbx_params), GFP_ATOMIC);
+       if (!dcb->param) {
+               err = -ENOMEM;
+               goto out_free_cfg;
+       }
+
        qlcnic_dcb_get_info(adapter);
 
        return 0;
+out_free_cfg:
+       kfree(dcb->cfg);
+       dcb->cfg = NULL;
+
+       return err;
 }
 
 static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *adapter,
@@ -189,6 +270,104 @@ static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter)
        return err;
 }
 
+static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_adapter *adapter,
+                                          char *buf, u8 type)
+{
+       u16 size = sizeof(struct qlcnic_82xx_dcb_param_mbx_le);
+       struct qlcnic_82xx_dcb_param_mbx_le *prsp_le;
+       struct device *dev = &adapter->pdev->dev;
+       dma_addr_t cardrsp_phys_addr;
+       struct qlcnic_dcb_param rsp;
+       struct qlcnic_cmd_args cmd;
+       u64 phys_addr;
+       void *addr;
+       int err, i;
+
+       switch (type) {
+       case QLC_DCB_LOCAL_PARAM_FWID:
+       case QLC_DCB_OPER_PARAM_FWID:
+       case QLC_DCB_PEER_PARAM_FWID:
+               break;
+       default:
+               dev_err(dev, "Invalid parameter type %d\n", type);
+               return -EINVAL;
+       }
+
+       addr = dma_alloc_coherent(&adapter->pdev->dev, size, &cardrsp_phys_addr,
+                                 GFP_KERNEL);
+       if (addr == NULL)
+               return -ENOMEM;
+
+       prsp_le = addr;
+
+       err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM);
+       if (err)
+               goto out_free_rsp;
+
+       phys_addr = cardrsp_phys_addr;
+       cmd.req.arg[1] = size | (type << 16);
+       cmd.req.arg[2] = MSD(phys_addr);
+       cmd.req.arg[3] = LSD(phys_addr);
+
+       err = qlcnic_issue_cmd(adapter, &cmd);
+       if (err) {
+               dev_err(dev, "Failed to query DCBX parameter, err %d\n", err);
+               goto out;
+       }
+
+       memset(&rsp, 0, sizeof(struct qlcnic_dcb_param));
+       rsp.hdr_prio_pfc_map[0] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[0]);
+       rsp.hdr_prio_pfc_map[1] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[1]);
+       rsp.prio_pg_map[0] = le32_to_cpu(prsp_le->prio_pg_map[0]);
+       rsp.prio_pg_map[1] = le32_to_cpu(prsp_le->prio_pg_map[1]);
+       rsp.pg_bw_map[0] = le32_to_cpu(prsp_le->pg_bw_map[0]);
+       rsp.pg_bw_map[1] = le32_to_cpu(prsp_le->pg_bw_map[1]);
+       rsp.pg_tsa_map[0] = le32_to_cpu(prsp_le->pg_tsa_map[0]);
+       rsp.pg_tsa_map[1] = le32_to_cpu(prsp_le->pg_tsa_map[1]);
+
+       for (i = 0; i < QLC_DCB_MAX_APP; i++)
+               rsp.app[i] = le32_to_cpu(prsp_le->app[i]);
+
+       if (buf)
+               memcpy(buf, &rsp, size);
+out:
+       qlcnic_free_mbx_args(&cmd);
+
+out_free_rsp:
+       dma_free_coherent(&adapter->pdev->dev, size, addr, cardrsp_phys_addr);
+
+       return err;
+}
+
+static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_dcb_mbx_params *mbx;
+       int err;
+
+       mbx = adapter->dcb->param;
+       if (!mbx)
+               return 0;
+
+       err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[0],
+                                        QLC_DCB_LOCAL_PARAM_FWID);
+       if (err)
+               return err;
+
+       err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[1],
+                                        QLC_DCB_OPER_PARAM_FWID);
+       if (err)
+               return err;
+
+       err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[2],
+                                        QLC_DCB_PEER_PARAM_FWID);
+       if (err)
+               return err;
+
+       mbx->prio_tc_map = QLC_82XX_DCB_PRIO_TC_MAP;
+
+       return err;
+}
+
 static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_dcb_capability *cap = &adapter->dcb->cfg->capability;
@@ -211,3 +390,72 @@ static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter)
 
        return err;
 }
+
+static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_adapter *adapter,
+                                          char *buf, u8 idx)
+{
+       struct qlcnic_dcb_mbx_params mbx_out;
+       int err, i, j, k, max_app, size;
+       struct qlcnic_dcb_param *each;
+       struct qlcnic_cmd_args cmd;
+       u32 val;
+       char *p;
+
+       size = 0;
+       memset(&mbx_out, 0, sizeof(struct qlcnic_dcb_mbx_params));
+       memset(buf, 0, sizeof(struct qlcnic_dcb_mbx_params));
+
+       err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM);
+       if (err)
+               return err;
+
+       cmd.req.arg[0] |= QLC_DCB_FW_VER << 29;
+       err = qlcnic_issue_cmd(adapter, &cmd);
+       if (err) {
+               dev_err(&adapter->pdev->dev,
+                       "Failed to query DCBX param, err %d\n", err);
+               goto out;
+       }
+
+       mbx_out.prio_tc_map = cmd.rsp.arg[1];
+       p = memcpy(buf, &mbx_out, sizeof(u32));
+       k = 2;
+       p += sizeof(u32);
+
+       for (j = 0; j < QLC_DCB_NUM_PARAM; j++) {
+               each = &mbx_out.type[j];
+
+               each->hdr_prio_pfc_map[0] = cmd.rsp.arg[k++];
+               each->hdr_prio_pfc_map[1] = cmd.rsp.arg[k++];
+               each->prio_pg_map[0] = cmd.rsp.arg[k++];
+               each->prio_pg_map[1] = cmd.rsp.arg[k++];
+               each->pg_bw_map[0] = cmd.rsp.arg[k++];
+               each->pg_bw_map[1] = cmd.rsp.arg[k++];
+               each->pg_tsa_map[0] = cmd.rsp.arg[k++];
+               each->pg_tsa_map[1] = cmd.rsp.arg[k++];
+               val = each->hdr_prio_pfc_map[0];
+
+               max_app = qlcnic_dcb_get_num_app(adapter, val);
+               for (i = 0; i < max_app; i++)
+                       each->app[i] = cmd.rsp.arg[i + k];
+
+               size = 16 * sizeof(u32);
+               memcpy(p, &each->hdr_prio_pfc_map[0], size);
+               p += size;
+               if (j == 0)
+                       k = 18;
+               else
+                       k = 34;
+       }
+out:
+       qlcnic_free_mbx_args(&cmd);
+
+       return err;
+}
+
+static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_dcb *dcb = adapter->dcb;
+
+       return qlcnic_dcb_query_cee_param(adapter, (char *)dcb->param, 0);
+}
index 45dc1fab4608b147963f42a2e171ebbefcdb83b0..d1775d7c151efccf9068c4662783f61c4ffe778b 100644 (file)
@@ -23,10 +23,13 @@ struct qlcnic_dcb_ops {
        int (*query_hw_capability) (struct qlcnic_adapter *, char *);
        int (*get_hw_capability) (struct qlcnic_adapter *);
        void (*get_info) (struct qlcnic_adapter *);
+       int (*query_cee_param) (struct qlcnic_adapter *, char *, u8);
+       int (*get_cee_cfg) (struct qlcnic_adapter *);
 };
 
 struct qlcnic_dcb {
-       struct qlcnic_dcb_ops   *ops;
-       struct qlcnic_dcb_cfg   *cfg;
+       struct qlcnic_dcb_mbx_params    *param;
+       struct qlcnic_dcb_ops           *ops;
+       struct qlcnic_dcb_cfg           *cfg;
 };
 #endif
index 243018b698096bebb2842e4041b68cbf5d4974ea..d2276b80661cfb016d0c5fc364be50e52e53b6b4 100644 (file)
@@ -86,6 +86,7 @@ enum qlcnic_regs {
 #define QLCNIC_CMD_BC_EVENT_SETUP              0x31
 #define        QLCNIC_CMD_CONFIG_VPORT                 0x32
 #define        QLCNIC_CMD_DCB_QUERY_CAP                0x34
+#define        QLCNIC_CMD_DCB_QUERY_PARAM              0x35
 #define QLCNIC_CMD_GET_MAC_STATS               0x37
 #define QLCNIC_CMD_82XX_SET_DRV_VER            0x38
 #define QLCNIC_CMD_MQ_TX_CONFIG_INTR           0x39
index b154048383e97c0beaca4421fb26660e87aaf811..3c0e02a003ba3c1dfef52c8443e1046326d70a33 100644 (file)
@@ -1285,6 +1285,7 @@ static const int qlcnic_pf_passthru_supp_cmds[] = {
        QLCNIC_CMD_GET_PORT_CONFIG,
        QLCNIC_CMD_GET_LINK_STATUS,
        QLCNIC_CMD_DCB_QUERY_CAP,
+       QLCNIC_CMD_DCB_QUERY_PARAM,
 };
 
 static const struct qlcnic_sriov_cmd_handler qlcnic_pf_bc_cmd_hdlr[] = {