From: Sucheta Chakraborty Date: Fri, 23 Aug 2013 17:38:26 +0000 (-0400) Subject: qlcnic: dcb: Get DCB parameters from the adapter. X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=fb859ed6916faeae6b44027d2e0738836a11e8c1;p=linux-beck.git qlcnic: dcb: Get DCB parameters from the adapter. o Populate driver data structures with local, operational, and peer DCB parameters. Signed-off-by: Sucheta Chakraborty Signed-off-by: David S. Miller --- diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 2196279b2a18..fc2972c89e73 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -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_ */ diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index d6d1b10537ea..9b27ed89a9bf 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -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[] = { diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index 4af37847213b..bf3b17eaf8b8 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -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) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c index 121e492f2f87..e43866f20bbb 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c @@ -5,9 +5,14 @@ * See LICENSE.qlcnic for copyright and licensing details. */ +#include #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) @@ -15,6 +20,29 @@ #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); +} diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h index 45dc1fab4608..d1775d7c151e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h @@ -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 diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h index 243018b69809..d2276b80661c 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h @@ -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 diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c index b154048383e9..3c0e02a003ba 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c @@ -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[] = {