18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * QLogic qlcnic NIC Driver 48c2ecf20Sopenharmony_ci * Copyright (c) 2009-2013 QLogic Corporation 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/types.h> 88c2ecf20Sopenharmony_ci#include "qlcnic.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#define QLC_DCB_NUM_PARAM 3 118c2ecf20Sopenharmony_ci#define QLC_DCB_LOCAL_IDX 0 128c2ecf20Sopenharmony_ci#define QLC_DCB_OPER_IDX 1 138c2ecf20Sopenharmony_ci#define QLC_DCB_PEER_IDX 2 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define QLC_DCB_GET_MAP(V) (1 << V) 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#define QLC_DCB_FW_VER 0x2 188c2ecf20Sopenharmony_ci#define QLC_DCB_MAX_TC 0x8 198c2ecf20Sopenharmony_ci#define QLC_DCB_MAX_APP 0x8 208c2ecf20Sopenharmony_ci#define QLC_DCB_MAX_PRIO QLC_DCB_MAX_TC 218c2ecf20Sopenharmony_ci#define QLC_DCB_MAX_PG QLC_DCB_MAX_TC 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define QLC_DCB_TSA_SUPPORT(V) (V & 0x1) 248c2ecf20Sopenharmony_ci#define QLC_DCB_ETS_SUPPORT(V) ((V >> 1) & 0x1) 258c2ecf20Sopenharmony_ci#define QLC_DCB_VERSION_SUPPORT(V) ((V >> 2) & 0xf) 268c2ecf20Sopenharmony_ci#define QLC_DCB_MAX_NUM_TC(V) ((V >> 20) & 0xf) 278c2ecf20Sopenharmony_ci#define QLC_DCB_MAX_NUM_ETS_TC(V) ((V >> 24) & 0xf) 288c2ecf20Sopenharmony_ci#define QLC_DCB_MAX_NUM_PFC_TC(V) ((V >> 28) & 0xf) 298c2ecf20Sopenharmony_ci#define QLC_DCB_GET_TC_PRIO(X, P) ((X >> (P * 3)) & 0x7) 308c2ecf20Sopenharmony_ci#define QLC_DCB_GET_PGID_PRIO(X, P) ((X >> (P * 8)) & 0xff) 318c2ecf20Sopenharmony_ci#define QLC_DCB_GET_BWPER_PG(X, P) ((X >> (P * 8)) & 0xff) 328c2ecf20Sopenharmony_ci#define QLC_DCB_GET_TSA_PG(X, P) ((X >> (P * 8)) & 0xff) 338c2ecf20Sopenharmony_ci#define QLC_DCB_GET_PFC_PRIO(X, P) (((X >> 24) >> P) & 0x1) 348c2ecf20Sopenharmony_ci#define QLC_DCB_GET_PROTO_ID_APP(X) ((X >> 8) & 0xffff) 358c2ecf20Sopenharmony_ci#define QLC_DCB_GET_SELECTOR_APP(X) (X & 0xff) 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#define QLC_DCB_LOCAL_PARAM_FWID 0x3 388c2ecf20Sopenharmony_ci#define QLC_DCB_OPER_PARAM_FWID 0x1 398c2ecf20Sopenharmony_ci#define QLC_DCB_PEER_PARAM_FWID 0x2 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define QLC_83XX_DCB_GET_NUMAPP(X) ((X >> 2) & 0xf) 428c2ecf20Sopenharmony_ci#define QLC_83XX_DCB_TSA_VALID(X) (X & 0x1) 438c2ecf20Sopenharmony_ci#define QLC_83XX_DCB_PFC_VALID(X) ((X >> 1) & 0x1) 448c2ecf20Sopenharmony_ci#define QLC_83XX_DCB_GET_PRIOMAP_APP(X) (X >> 24) 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#define QLC_82XX_DCB_GET_NUMAPP(X) ((X >> 12) & 0xf) 478c2ecf20Sopenharmony_ci#define QLC_82XX_DCB_TSA_VALID(X) ((X >> 4) & 0x1) 488c2ecf20Sopenharmony_ci#define QLC_82XX_DCB_PFC_VALID(X) ((X >> 5) & 0x1) 498c2ecf20Sopenharmony_ci#define QLC_82XX_DCB_GET_PRIOVAL_APP(X) ((X >> 24) & 0x7) 508c2ecf20Sopenharmony_ci#define QLC_82XX_DCB_GET_PRIOMAP_APP(X) (1 << X) 518c2ecf20Sopenharmony_ci#define QLC_82XX_DCB_PRIO_TC_MAP (0x76543210) 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic const struct dcbnl_rtnl_ops qlcnic_dcbnl_ops; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic void qlcnic_dcb_aen_work(struct work_struct *); 568c2ecf20Sopenharmony_cistatic void qlcnic_dcb_data_cee_param_map(struct qlcnic_adapter *); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic inline void __qlcnic_init_dcbnl_ops(struct qlcnic_dcb *); 598c2ecf20Sopenharmony_cistatic void __qlcnic_dcb_free(struct qlcnic_dcb *); 608c2ecf20Sopenharmony_cistatic int __qlcnic_dcb_attach(struct qlcnic_dcb *); 618c2ecf20Sopenharmony_cistatic int __qlcnic_dcb_query_hw_capability(struct qlcnic_dcb *, char *); 628c2ecf20Sopenharmony_cistatic void __qlcnic_dcb_get_info(struct qlcnic_dcb *); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_dcb *); 658c2ecf20Sopenharmony_cistatic int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_dcb *, char *, u8); 668c2ecf20Sopenharmony_cistatic int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_dcb *); 678c2ecf20Sopenharmony_cistatic void qlcnic_82xx_dcb_aen_handler(struct qlcnic_dcb *, void *); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_dcb *); 708c2ecf20Sopenharmony_cistatic int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_dcb *, char *, u8); 718c2ecf20Sopenharmony_cistatic int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb *); 728c2ecf20Sopenharmony_cistatic void qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb *, void *); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistruct qlcnic_dcb_capability { 758c2ecf20Sopenharmony_ci bool tsa_capability; 768c2ecf20Sopenharmony_ci bool ets_capability; 778c2ecf20Sopenharmony_ci u8 max_num_tc; 788c2ecf20Sopenharmony_ci u8 max_ets_tc; 798c2ecf20Sopenharmony_ci u8 max_pfc_tc; 808c2ecf20Sopenharmony_ci u8 dcb_capability; 818c2ecf20Sopenharmony_ci}; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistruct qlcnic_dcb_param { 848c2ecf20Sopenharmony_ci u32 hdr_prio_pfc_map[2]; 858c2ecf20Sopenharmony_ci u32 prio_pg_map[2]; 868c2ecf20Sopenharmony_ci u32 pg_bw_map[2]; 878c2ecf20Sopenharmony_ci u32 pg_tsa_map[2]; 888c2ecf20Sopenharmony_ci u32 app[QLC_DCB_MAX_APP]; 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistruct qlcnic_dcb_mbx_params { 928c2ecf20Sopenharmony_ci /* 1st local, 2nd operational 3rd remote */ 938c2ecf20Sopenharmony_ci struct qlcnic_dcb_param type[3]; 948c2ecf20Sopenharmony_ci u32 prio_tc_map; 958c2ecf20Sopenharmony_ci}; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistruct qlcnic_82xx_dcb_param_mbx_le { 988c2ecf20Sopenharmony_ci __le32 hdr_prio_pfc_map[2]; 998c2ecf20Sopenharmony_ci __le32 prio_pg_map[2]; 1008c2ecf20Sopenharmony_ci __le32 pg_bw_map[2]; 1018c2ecf20Sopenharmony_ci __le32 pg_tsa_map[2]; 1028c2ecf20Sopenharmony_ci __le32 app[QLC_DCB_MAX_APP]; 1038c2ecf20Sopenharmony_ci}; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cienum qlcnic_dcb_selector { 1068c2ecf20Sopenharmony_ci QLC_SELECTOR_DEF = 0x0, 1078c2ecf20Sopenharmony_ci QLC_SELECTOR_ETHER, 1088c2ecf20Sopenharmony_ci QLC_SELECTOR_TCP, 1098c2ecf20Sopenharmony_ci QLC_SELECTOR_UDP, 1108c2ecf20Sopenharmony_ci}; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cienum qlcnic_dcb_prio_type { 1138c2ecf20Sopenharmony_ci QLC_PRIO_NONE = 0, 1148c2ecf20Sopenharmony_ci QLC_PRIO_GROUP, 1158c2ecf20Sopenharmony_ci QLC_PRIO_LINK, 1168c2ecf20Sopenharmony_ci}; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cienum qlcnic_dcb_pfc_type { 1198c2ecf20Sopenharmony_ci QLC_PFC_DISABLED = 0, 1208c2ecf20Sopenharmony_ci QLC_PFC_FULL, 1218c2ecf20Sopenharmony_ci QLC_PFC_TX, 1228c2ecf20Sopenharmony_ci QLC_PFC_RX 1238c2ecf20Sopenharmony_ci}; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistruct qlcnic_dcb_prio_cfg { 1268c2ecf20Sopenharmony_ci bool valid; 1278c2ecf20Sopenharmony_ci enum qlcnic_dcb_pfc_type pfc_type; 1288c2ecf20Sopenharmony_ci}; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistruct qlcnic_dcb_pg_cfg { 1318c2ecf20Sopenharmony_ci bool valid; 1328c2ecf20Sopenharmony_ci u8 total_bw_percent; /* of Link/ port BW */ 1338c2ecf20Sopenharmony_ci u8 prio_count; 1348c2ecf20Sopenharmony_ci u8 tsa_type; 1358c2ecf20Sopenharmony_ci}; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cistruct qlcnic_dcb_tc_cfg { 1388c2ecf20Sopenharmony_ci bool valid; 1398c2ecf20Sopenharmony_ci struct qlcnic_dcb_prio_cfg prio_cfg[QLC_DCB_MAX_PRIO]; 1408c2ecf20Sopenharmony_ci enum qlcnic_dcb_prio_type prio_type; /* always prio_link */ 1418c2ecf20Sopenharmony_ci u8 link_percent; /* % of link bandwidth */ 1428c2ecf20Sopenharmony_ci u8 bwg_percent; /* % of BWG's bandwidth */ 1438c2ecf20Sopenharmony_ci u8 up_tc_map; 1448c2ecf20Sopenharmony_ci u8 pgid; 1458c2ecf20Sopenharmony_ci}; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistruct qlcnic_dcb_app { 1488c2ecf20Sopenharmony_ci bool valid; 1498c2ecf20Sopenharmony_ci enum qlcnic_dcb_selector selector; 1508c2ecf20Sopenharmony_ci u16 protocol; 1518c2ecf20Sopenharmony_ci u8 priority; 1528c2ecf20Sopenharmony_ci}; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistruct qlcnic_dcb_cee { 1558c2ecf20Sopenharmony_ci struct qlcnic_dcb_tc_cfg tc_cfg[QLC_DCB_MAX_TC]; 1568c2ecf20Sopenharmony_ci struct qlcnic_dcb_pg_cfg pg_cfg[QLC_DCB_MAX_PG]; 1578c2ecf20Sopenharmony_ci struct qlcnic_dcb_app app[QLC_DCB_MAX_APP]; 1588c2ecf20Sopenharmony_ci bool tc_param_valid; 1598c2ecf20Sopenharmony_ci bool pfc_mode_enable; 1608c2ecf20Sopenharmony_ci}; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistruct qlcnic_dcb_cfg { 1638c2ecf20Sopenharmony_ci /* 0 - local, 1 - operational, 2 - remote */ 1648c2ecf20Sopenharmony_ci struct qlcnic_dcb_cee type[QLC_DCB_NUM_PARAM]; 1658c2ecf20Sopenharmony_ci struct qlcnic_dcb_capability capability; 1668c2ecf20Sopenharmony_ci u32 version; 1678c2ecf20Sopenharmony_ci}; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic const struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = { 1708c2ecf20Sopenharmony_ci .init_dcbnl_ops = __qlcnic_init_dcbnl_ops, 1718c2ecf20Sopenharmony_ci .free = __qlcnic_dcb_free, 1728c2ecf20Sopenharmony_ci .attach = __qlcnic_dcb_attach, 1738c2ecf20Sopenharmony_ci .query_hw_capability = __qlcnic_dcb_query_hw_capability, 1748c2ecf20Sopenharmony_ci .get_info = __qlcnic_dcb_get_info, 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci .get_hw_capability = qlcnic_83xx_dcb_get_hw_capability, 1778c2ecf20Sopenharmony_ci .query_cee_param = qlcnic_83xx_dcb_query_cee_param, 1788c2ecf20Sopenharmony_ci .get_cee_cfg = qlcnic_83xx_dcb_get_cee_cfg, 1798c2ecf20Sopenharmony_ci .aen_handler = qlcnic_83xx_dcb_aen_handler, 1808c2ecf20Sopenharmony_ci}; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic const struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = { 1838c2ecf20Sopenharmony_ci .init_dcbnl_ops = __qlcnic_init_dcbnl_ops, 1848c2ecf20Sopenharmony_ci .free = __qlcnic_dcb_free, 1858c2ecf20Sopenharmony_ci .attach = __qlcnic_dcb_attach, 1868c2ecf20Sopenharmony_ci .query_hw_capability = __qlcnic_dcb_query_hw_capability, 1878c2ecf20Sopenharmony_ci .get_info = __qlcnic_dcb_get_info, 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci .get_hw_capability = qlcnic_82xx_dcb_get_hw_capability, 1908c2ecf20Sopenharmony_ci .query_cee_param = qlcnic_82xx_dcb_query_cee_param, 1918c2ecf20Sopenharmony_ci .get_cee_cfg = qlcnic_82xx_dcb_get_cee_cfg, 1928c2ecf20Sopenharmony_ci .aen_handler = qlcnic_82xx_dcb_aen_handler, 1938c2ecf20Sopenharmony_ci}; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_cistatic u8 qlcnic_dcb_get_num_app(struct qlcnic_adapter *adapter, u32 val) 1968c2ecf20Sopenharmony_ci{ 1978c2ecf20Sopenharmony_ci if (qlcnic_82xx_check(adapter)) 1988c2ecf20Sopenharmony_ci return QLC_82XX_DCB_GET_NUMAPP(val); 1998c2ecf20Sopenharmony_ci else 2008c2ecf20Sopenharmony_ci return QLC_83XX_DCB_GET_NUMAPP(val); 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic inline u8 qlcnic_dcb_pfc_hdr_valid(struct qlcnic_adapter *adapter, 2048c2ecf20Sopenharmony_ci u32 val) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci if (qlcnic_82xx_check(adapter)) 2078c2ecf20Sopenharmony_ci return QLC_82XX_DCB_PFC_VALID(val); 2088c2ecf20Sopenharmony_ci else 2098c2ecf20Sopenharmony_ci return QLC_83XX_DCB_PFC_VALID(val); 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic inline u8 qlcnic_dcb_tsa_hdr_valid(struct qlcnic_adapter *adapter, 2138c2ecf20Sopenharmony_ci u32 val) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci if (qlcnic_82xx_check(adapter)) 2168c2ecf20Sopenharmony_ci return QLC_82XX_DCB_TSA_VALID(val); 2178c2ecf20Sopenharmony_ci else 2188c2ecf20Sopenharmony_ci return QLC_83XX_DCB_TSA_VALID(val); 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic inline u8 qlcnic_dcb_get_prio_map_app(struct qlcnic_adapter *adapter, 2228c2ecf20Sopenharmony_ci u32 val) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci if (qlcnic_82xx_check(adapter)) 2258c2ecf20Sopenharmony_ci return QLC_82XX_DCB_GET_PRIOMAP_APP(val); 2268c2ecf20Sopenharmony_ci else 2278c2ecf20Sopenharmony_ci return QLC_83XX_DCB_GET_PRIOMAP_APP(val); 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic int qlcnic_dcb_prio_count(u8 up_tc_map) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci int j; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci for (j = 0; j < QLC_DCB_MAX_TC; j++) 2358c2ecf20Sopenharmony_ci if (up_tc_map & QLC_DCB_GET_MAP(j)) 2368c2ecf20Sopenharmony_ci break; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci return j; 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic inline void __qlcnic_init_dcbnl_ops(struct qlcnic_dcb *dcb) 2428c2ecf20Sopenharmony_ci{ 2438c2ecf20Sopenharmony_ci if (test_bit(QLCNIC_DCB_STATE, &dcb->state)) 2448c2ecf20Sopenharmony_ci dcb->adapter->netdev->dcbnl_ops = &qlcnic_dcbnl_ops; 2458c2ecf20Sopenharmony_ci} 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cistatic void qlcnic_set_dcb_ops(struct qlcnic_adapter *adapter) 2488c2ecf20Sopenharmony_ci{ 2498c2ecf20Sopenharmony_ci if (qlcnic_82xx_check(adapter)) 2508c2ecf20Sopenharmony_ci adapter->dcb->ops = &qlcnic_82xx_dcb_ops; 2518c2ecf20Sopenharmony_ci else if (qlcnic_83xx_check(adapter)) 2528c2ecf20Sopenharmony_ci adapter->dcb->ops = &qlcnic_83xx_dcb_ops; 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ciint qlcnic_register_dcb(struct qlcnic_adapter *adapter) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci struct qlcnic_dcb *dcb; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci if (qlcnic_sriov_vf_check(adapter)) 2608c2ecf20Sopenharmony_ci return 0; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci dcb = kzalloc(sizeof(struct qlcnic_dcb), GFP_ATOMIC); 2638c2ecf20Sopenharmony_ci if (!dcb) 2648c2ecf20Sopenharmony_ci return -ENOMEM; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci adapter->dcb = dcb; 2678c2ecf20Sopenharmony_ci dcb->adapter = adapter; 2688c2ecf20Sopenharmony_ci qlcnic_set_dcb_ops(adapter); 2698c2ecf20Sopenharmony_ci dcb->state = 0; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci return 0; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic void __qlcnic_dcb_free(struct qlcnic_dcb *dcb) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci if (!dcb) 2798c2ecf20Sopenharmony_ci return; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci adapter = dcb->adapter; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci while (test_bit(QLCNIC_DCB_AEN_MODE, &dcb->state)) 2848c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&dcb->aen_work); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci if (dcb->wq) { 2898c2ecf20Sopenharmony_ci destroy_workqueue(dcb->wq); 2908c2ecf20Sopenharmony_ci dcb->wq = NULL; 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci kfree(dcb->cfg); 2948c2ecf20Sopenharmony_ci dcb->cfg = NULL; 2958c2ecf20Sopenharmony_ci kfree(dcb->param); 2968c2ecf20Sopenharmony_ci dcb->param = NULL; 2978c2ecf20Sopenharmony_ci kfree(dcb); 2988c2ecf20Sopenharmony_ci adapter->dcb = NULL; 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_cistatic void __qlcnic_dcb_get_info(struct qlcnic_dcb *dcb) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci qlcnic_dcb_get_hw_capability(dcb); 3048c2ecf20Sopenharmony_ci qlcnic_dcb_get_cee_cfg(dcb); 3058c2ecf20Sopenharmony_ci} 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cistatic int __qlcnic_dcb_attach(struct qlcnic_dcb *dcb) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci int err = 0; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&dcb->aen_work, qlcnic_dcb_aen_work); 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci dcb->wq = create_singlethread_workqueue("qlcnic-dcb"); 3148c2ecf20Sopenharmony_ci if (!dcb->wq) { 3158c2ecf20Sopenharmony_ci dev_err(&dcb->adapter->pdev->dev, 3168c2ecf20Sopenharmony_ci "DCB workqueue allocation failed. DCB will be disabled\n"); 3178c2ecf20Sopenharmony_ci return -1; 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci dcb->cfg = kzalloc(sizeof(struct qlcnic_dcb_cfg), GFP_ATOMIC); 3218c2ecf20Sopenharmony_ci if (!dcb->cfg) { 3228c2ecf20Sopenharmony_ci err = -ENOMEM; 3238c2ecf20Sopenharmony_ci goto out_free_wq; 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci dcb->param = kzalloc(sizeof(struct qlcnic_dcb_mbx_params), GFP_ATOMIC); 3278c2ecf20Sopenharmony_ci if (!dcb->param) { 3288c2ecf20Sopenharmony_ci err = -ENOMEM; 3298c2ecf20Sopenharmony_ci goto out_free_cfg; 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci return 0; 3338c2ecf20Sopenharmony_ciout_free_cfg: 3348c2ecf20Sopenharmony_ci kfree(dcb->cfg); 3358c2ecf20Sopenharmony_ci dcb->cfg = NULL; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ciout_free_wq: 3388c2ecf20Sopenharmony_ci destroy_workqueue(dcb->wq); 3398c2ecf20Sopenharmony_ci dcb->wq = NULL; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci return err; 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic int __qlcnic_dcb_query_hw_capability(struct qlcnic_dcb *dcb, char *buf) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = dcb->adapter; 3478c2ecf20Sopenharmony_ci struct qlcnic_cmd_args cmd; 3488c2ecf20Sopenharmony_ci u32 mbx_out; 3498c2ecf20Sopenharmony_ci int err; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_CAP); 3528c2ecf20Sopenharmony_ci if (err) 3538c2ecf20Sopenharmony_ci return err; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci err = qlcnic_issue_cmd(adapter, &cmd); 3568c2ecf20Sopenharmony_ci if (err) { 3578c2ecf20Sopenharmony_ci dev_err(&adapter->pdev->dev, 3588c2ecf20Sopenharmony_ci "Failed to query DCBX capability, err %d\n", err); 3598c2ecf20Sopenharmony_ci } else { 3608c2ecf20Sopenharmony_ci mbx_out = cmd.rsp.arg[1]; 3618c2ecf20Sopenharmony_ci if (buf) 3628c2ecf20Sopenharmony_ci memcpy(buf, &mbx_out, sizeof(u32)); 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci qlcnic_free_mbx_args(&cmd); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci return err; 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_cistatic int __qlcnic_dcb_get_capability(struct qlcnic_dcb *dcb, u32 *val) 3718c2ecf20Sopenharmony_ci{ 3728c2ecf20Sopenharmony_ci struct qlcnic_dcb_capability *cap = &dcb->cfg->capability; 3738c2ecf20Sopenharmony_ci u32 mbx_out; 3748c2ecf20Sopenharmony_ci int err; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci memset(cap, 0, sizeof(struct qlcnic_dcb_capability)); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci err = qlcnic_dcb_query_hw_capability(dcb, (char *)val); 3798c2ecf20Sopenharmony_ci if (err) 3808c2ecf20Sopenharmony_ci return err; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci mbx_out = *val; 3838c2ecf20Sopenharmony_ci if (QLC_DCB_TSA_SUPPORT(mbx_out)) 3848c2ecf20Sopenharmony_ci cap->tsa_capability = true; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci if (QLC_DCB_ETS_SUPPORT(mbx_out)) 3878c2ecf20Sopenharmony_ci cap->ets_capability = true; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci cap->max_num_tc = QLC_DCB_MAX_NUM_TC(mbx_out); 3908c2ecf20Sopenharmony_ci cap->max_ets_tc = QLC_DCB_MAX_NUM_ETS_TC(mbx_out); 3918c2ecf20Sopenharmony_ci cap->max_pfc_tc = QLC_DCB_MAX_NUM_PFC_TC(mbx_out); 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci if (cap->max_num_tc > QLC_DCB_MAX_TC || 3948c2ecf20Sopenharmony_ci cap->max_ets_tc > cap->max_num_tc || 3958c2ecf20Sopenharmony_ci cap->max_pfc_tc > cap->max_num_tc) { 3968c2ecf20Sopenharmony_ci dev_err(&dcb->adapter->pdev->dev, "Invalid DCB configuration\n"); 3978c2ecf20Sopenharmony_ci return -EINVAL; 3988c2ecf20Sopenharmony_ci } 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci return err; 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_cistatic int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_dcb *dcb) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci struct qlcnic_dcb_cfg *cfg = dcb->cfg; 4068c2ecf20Sopenharmony_ci struct qlcnic_dcb_capability *cap; 4078c2ecf20Sopenharmony_ci u32 mbx_out; 4088c2ecf20Sopenharmony_ci int err; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci err = __qlcnic_dcb_get_capability(dcb, &mbx_out); 4118c2ecf20Sopenharmony_ci if (err) 4128c2ecf20Sopenharmony_ci return err; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci cap = &cfg->capability; 4158c2ecf20Sopenharmony_ci cap->dcb_capability = DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_LLD_MANAGED; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability) 4188c2ecf20Sopenharmony_ci set_bit(QLCNIC_DCB_STATE, &dcb->state); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci return err; 4218c2ecf20Sopenharmony_ci} 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_cistatic int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_dcb *dcb, 4248c2ecf20Sopenharmony_ci char *buf, u8 type) 4258c2ecf20Sopenharmony_ci{ 4268c2ecf20Sopenharmony_ci u16 size = sizeof(struct qlcnic_82xx_dcb_param_mbx_le); 4278c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = dcb->adapter; 4288c2ecf20Sopenharmony_ci struct qlcnic_82xx_dcb_param_mbx_le *prsp_le; 4298c2ecf20Sopenharmony_ci struct device *dev = &adapter->pdev->dev; 4308c2ecf20Sopenharmony_ci dma_addr_t cardrsp_phys_addr; 4318c2ecf20Sopenharmony_ci struct qlcnic_dcb_param rsp; 4328c2ecf20Sopenharmony_ci struct qlcnic_cmd_args cmd; 4338c2ecf20Sopenharmony_ci u64 phys_addr; 4348c2ecf20Sopenharmony_ci void *addr; 4358c2ecf20Sopenharmony_ci int err, i; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci switch (type) { 4388c2ecf20Sopenharmony_ci case QLC_DCB_LOCAL_PARAM_FWID: 4398c2ecf20Sopenharmony_ci case QLC_DCB_OPER_PARAM_FWID: 4408c2ecf20Sopenharmony_ci case QLC_DCB_PEER_PARAM_FWID: 4418c2ecf20Sopenharmony_ci break; 4428c2ecf20Sopenharmony_ci default: 4438c2ecf20Sopenharmony_ci dev_err(dev, "Invalid parameter type %d\n", type); 4448c2ecf20Sopenharmony_ci return -EINVAL; 4458c2ecf20Sopenharmony_ci } 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci addr = dma_alloc_coherent(dev, size, &cardrsp_phys_addr, GFP_KERNEL); 4488c2ecf20Sopenharmony_ci if (addr == NULL) 4498c2ecf20Sopenharmony_ci return -ENOMEM; 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci prsp_le = addr; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM); 4548c2ecf20Sopenharmony_ci if (err) 4558c2ecf20Sopenharmony_ci goto out_free_rsp; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci phys_addr = cardrsp_phys_addr; 4588c2ecf20Sopenharmony_ci cmd.req.arg[1] = size | (type << 16); 4598c2ecf20Sopenharmony_ci cmd.req.arg[2] = MSD(phys_addr); 4608c2ecf20Sopenharmony_ci cmd.req.arg[3] = LSD(phys_addr); 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci err = qlcnic_issue_cmd(adapter, &cmd); 4638c2ecf20Sopenharmony_ci if (err) { 4648c2ecf20Sopenharmony_ci dev_err(dev, "Failed to query DCBX parameter, err %d\n", err); 4658c2ecf20Sopenharmony_ci goto out; 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci memset(&rsp, 0, sizeof(struct qlcnic_dcb_param)); 4698c2ecf20Sopenharmony_ci rsp.hdr_prio_pfc_map[0] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[0]); 4708c2ecf20Sopenharmony_ci rsp.hdr_prio_pfc_map[1] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[1]); 4718c2ecf20Sopenharmony_ci rsp.prio_pg_map[0] = le32_to_cpu(prsp_le->prio_pg_map[0]); 4728c2ecf20Sopenharmony_ci rsp.prio_pg_map[1] = le32_to_cpu(prsp_le->prio_pg_map[1]); 4738c2ecf20Sopenharmony_ci rsp.pg_bw_map[0] = le32_to_cpu(prsp_le->pg_bw_map[0]); 4748c2ecf20Sopenharmony_ci rsp.pg_bw_map[1] = le32_to_cpu(prsp_le->pg_bw_map[1]); 4758c2ecf20Sopenharmony_ci rsp.pg_tsa_map[0] = le32_to_cpu(prsp_le->pg_tsa_map[0]); 4768c2ecf20Sopenharmony_ci rsp.pg_tsa_map[1] = le32_to_cpu(prsp_le->pg_tsa_map[1]); 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci for (i = 0; i < QLC_DCB_MAX_APP; i++) 4798c2ecf20Sopenharmony_ci rsp.app[i] = le32_to_cpu(prsp_le->app[i]); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci if (buf) 4828c2ecf20Sopenharmony_ci memcpy(buf, &rsp, size); 4838c2ecf20Sopenharmony_ciout: 4848c2ecf20Sopenharmony_ci qlcnic_free_mbx_args(&cmd); 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ciout_free_rsp: 4878c2ecf20Sopenharmony_ci dma_free_coherent(dev, size, addr, cardrsp_phys_addr); 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci return err; 4908c2ecf20Sopenharmony_ci} 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_cistatic int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_dcb *dcb) 4938c2ecf20Sopenharmony_ci{ 4948c2ecf20Sopenharmony_ci struct qlcnic_dcb_mbx_params *mbx; 4958c2ecf20Sopenharmony_ci int err; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci mbx = dcb->param; 4988c2ecf20Sopenharmony_ci if (!mbx) 4998c2ecf20Sopenharmony_ci return 0; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[0], 5028c2ecf20Sopenharmony_ci QLC_DCB_LOCAL_PARAM_FWID); 5038c2ecf20Sopenharmony_ci if (err) 5048c2ecf20Sopenharmony_ci return err; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[1], 5078c2ecf20Sopenharmony_ci QLC_DCB_OPER_PARAM_FWID); 5088c2ecf20Sopenharmony_ci if (err) 5098c2ecf20Sopenharmony_ci return err; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[2], 5128c2ecf20Sopenharmony_ci QLC_DCB_PEER_PARAM_FWID); 5138c2ecf20Sopenharmony_ci if (err) 5148c2ecf20Sopenharmony_ci return err; 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci mbx->prio_tc_map = QLC_82XX_DCB_PRIO_TC_MAP; 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci qlcnic_dcb_data_cee_param_map(dcb->adapter); 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci return err; 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_cistatic void qlcnic_dcb_aen_work(struct work_struct *work) 5248c2ecf20Sopenharmony_ci{ 5258c2ecf20Sopenharmony_ci struct qlcnic_dcb *dcb; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci dcb = container_of(work, struct qlcnic_dcb, aen_work.work); 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci qlcnic_dcb_get_cee_cfg(dcb); 5308c2ecf20Sopenharmony_ci clear_bit(QLCNIC_DCB_AEN_MODE, &dcb->state); 5318c2ecf20Sopenharmony_ci} 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_cistatic void qlcnic_82xx_dcb_aen_handler(struct qlcnic_dcb *dcb, void *data) 5348c2ecf20Sopenharmony_ci{ 5358c2ecf20Sopenharmony_ci if (test_and_set_bit(QLCNIC_DCB_AEN_MODE, &dcb->state)) 5368c2ecf20Sopenharmony_ci return; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci queue_delayed_work(dcb->wq, &dcb->aen_work, 0); 5398c2ecf20Sopenharmony_ci} 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_cistatic int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_dcb *dcb) 5428c2ecf20Sopenharmony_ci{ 5438c2ecf20Sopenharmony_ci struct qlcnic_dcb_capability *cap = &dcb->cfg->capability; 5448c2ecf20Sopenharmony_ci u32 mbx_out; 5458c2ecf20Sopenharmony_ci int err; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci err = __qlcnic_dcb_get_capability(dcb, &mbx_out); 5488c2ecf20Sopenharmony_ci if (err) 5498c2ecf20Sopenharmony_ci return err; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci if (mbx_out & BIT_2) 5528c2ecf20Sopenharmony_ci cap->dcb_capability = DCB_CAP_DCBX_VER_CEE; 5538c2ecf20Sopenharmony_ci if (mbx_out & BIT_3) 5548c2ecf20Sopenharmony_ci cap->dcb_capability |= DCB_CAP_DCBX_VER_IEEE; 5558c2ecf20Sopenharmony_ci if (cap->dcb_capability) 5568c2ecf20Sopenharmony_ci cap->dcb_capability |= DCB_CAP_DCBX_LLD_MANAGED; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability) 5598c2ecf20Sopenharmony_ci set_bit(QLCNIC_DCB_STATE, &dcb->state); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci return err; 5628c2ecf20Sopenharmony_ci} 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_cistatic int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_dcb *dcb, 5658c2ecf20Sopenharmony_ci char *buf, u8 idx) 5668c2ecf20Sopenharmony_ci{ 5678c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = dcb->adapter; 5688c2ecf20Sopenharmony_ci struct qlcnic_dcb_mbx_params mbx_out; 5698c2ecf20Sopenharmony_ci int err, i, j, k, max_app, size; 5708c2ecf20Sopenharmony_ci struct qlcnic_dcb_param *each; 5718c2ecf20Sopenharmony_ci struct qlcnic_cmd_args cmd; 5728c2ecf20Sopenharmony_ci u32 val; 5738c2ecf20Sopenharmony_ci char *p; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci size = 0; 5768c2ecf20Sopenharmony_ci memset(&mbx_out, 0, sizeof(struct qlcnic_dcb_mbx_params)); 5778c2ecf20Sopenharmony_ci memset(buf, 0, sizeof(struct qlcnic_dcb_mbx_params)); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM); 5808c2ecf20Sopenharmony_ci if (err) 5818c2ecf20Sopenharmony_ci return err; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci cmd.req.arg[0] |= QLC_DCB_FW_VER << 29; 5848c2ecf20Sopenharmony_ci err = qlcnic_issue_cmd(adapter, &cmd); 5858c2ecf20Sopenharmony_ci if (err) { 5868c2ecf20Sopenharmony_ci dev_err(&adapter->pdev->dev, 5878c2ecf20Sopenharmony_ci "Failed to query DCBX param, err %d\n", err); 5888c2ecf20Sopenharmony_ci goto out; 5898c2ecf20Sopenharmony_ci } 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci mbx_out.prio_tc_map = cmd.rsp.arg[1]; 5928c2ecf20Sopenharmony_ci p = memcpy(buf, &mbx_out, sizeof(u32)); 5938c2ecf20Sopenharmony_ci k = 2; 5948c2ecf20Sopenharmony_ci p += sizeof(u32); 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci for (j = 0; j < QLC_DCB_NUM_PARAM; j++) { 5978c2ecf20Sopenharmony_ci each = &mbx_out.type[j]; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci each->hdr_prio_pfc_map[0] = cmd.rsp.arg[k++]; 6008c2ecf20Sopenharmony_ci each->hdr_prio_pfc_map[1] = cmd.rsp.arg[k++]; 6018c2ecf20Sopenharmony_ci each->prio_pg_map[0] = cmd.rsp.arg[k++]; 6028c2ecf20Sopenharmony_ci each->prio_pg_map[1] = cmd.rsp.arg[k++]; 6038c2ecf20Sopenharmony_ci each->pg_bw_map[0] = cmd.rsp.arg[k++]; 6048c2ecf20Sopenharmony_ci each->pg_bw_map[1] = cmd.rsp.arg[k++]; 6058c2ecf20Sopenharmony_ci each->pg_tsa_map[0] = cmd.rsp.arg[k++]; 6068c2ecf20Sopenharmony_ci each->pg_tsa_map[1] = cmd.rsp.arg[k++]; 6078c2ecf20Sopenharmony_ci val = each->hdr_prio_pfc_map[0]; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci max_app = qlcnic_dcb_get_num_app(adapter, val); 6108c2ecf20Sopenharmony_ci for (i = 0; i < max_app; i++) 6118c2ecf20Sopenharmony_ci each->app[i] = cmd.rsp.arg[i + k]; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci size = 16 * sizeof(u32); 6148c2ecf20Sopenharmony_ci memcpy(p, &each->hdr_prio_pfc_map[0], size); 6158c2ecf20Sopenharmony_ci p += size; 6168c2ecf20Sopenharmony_ci if (j == 0) 6178c2ecf20Sopenharmony_ci k = 18; 6188c2ecf20Sopenharmony_ci else 6198c2ecf20Sopenharmony_ci k = 34; 6208c2ecf20Sopenharmony_ci } 6218c2ecf20Sopenharmony_ciout: 6228c2ecf20Sopenharmony_ci qlcnic_free_mbx_args(&cmd); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci return err; 6258c2ecf20Sopenharmony_ci} 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_cistatic int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb *dcb) 6288c2ecf20Sopenharmony_ci{ 6298c2ecf20Sopenharmony_ci int err; 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci err = qlcnic_dcb_query_cee_param(dcb, (char *)dcb->param, 0); 6328c2ecf20Sopenharmony_ci if (err) 6338c2ecf20Sopenharmony_ci return err; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci qlcnic_dcb_data_cee_param_map(dcb->adapter); 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci return err; 6388c2ecf20Sopenharmony_ci} 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_cistatic void qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb *dcb, void *data) 6418c2ecf20Sopenharmony_ci{ 6428c2ecf20Sopenharmony_ci u32 *val = data; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci if (test_and_set_bit(QLCNIC_DCB_AEN_MODE, &dcb->state)) 6458c2ecf20Sopenharmony_ci return; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci if (*val & BIT_8) 6488c2ecf20Sopenharmony_ci set_bit(QLCNIC_DCB_STATE, &dcb->state); 6498c2ecf20Sopenharmony_ci else 6508c2ecf20Sopenharmony_ci clear_bit(QLCNIC_DCB_STATE, &dcb->state); 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci queue_delayed_work(dcb->wq, &dcb->aen_work, 0); 6538c2ecf20Sopenharmony_ci} 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_cistatic void qlcnic_dcb_fill_cee_tc_params(struct qlcnic_dcb_mbx_params *mbx, 6568c2ecf20Sopenharmony_ci struct qlcnic_dcb_param *each, 6578c2ecf20Sopenharmony_ci struct qlcnic_dcb_cee *type) 6588c2ecf20Sopenharmony_ci{ 6598c2ecf20Sopenharmony_ci struct qlcnic_dcb_tc_cfg *tc_cfg; 6608c2ecf20Sopenharmony_ci u8 i, tc, pgid; 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci for (i = 0; i < QLC_DCB_MAX_PRIO; i++) { 6638c2ecf20Sopenharmony_ci tc = QLC_DCB_GET_TC_PRIO(mbx->prio_tc_map, i); 6648c2ecf20Sopenharmony_ci tc_cfg = &type->tc_cfg[tc]; 6658c2ecf20Sopenharmony_ci tc_cfg->valid = true; 6668c2ecf20Sopenharmony_ci tc_cfg->up_tc_map |= QLC_DCB_GET_MAP(i); 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci if (QLC_DCB_GET_PFC_PRIO(each->hdr_prio_pfc_map[1], i) && 6698c2ecf20Sopenharmony_ci type->pfc_mode_enable) { 6708c2ecf20Sopenharmony_ci tc_cfg->prio_cfg[i].valid = true; 6718c2ecf20Sopenharmony_ci tc_cfg->prio_cfg[i].pfc_type = QLC_PFC_FULL; 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci if (i < 4) 6758c2ecf20Sopenharmony_ci pgid = QLC_DCB_GET_PGID_PRIO(each->prio_pg_map[0], i); 6768c2ecf20Sopenharmony_ci else 6778c2ecf20Sopenharmony_ci pgid = QLC_DCB_GET_PGID_PRIO(each->prio_pg_map[1], i); 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci tc_cfg->pgid = pgid; 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci tc_cfg->prio_type = QLC_PRIO_LINK; 6828c2ecf20Sopenharmony_ci type->pg_cfg[tc_cfg->pgid].prio_count++; 6838c2ecf20Sopenharmony_ci } 6848c2ecf20Sopenharmony_ci} 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_cistatic void qlcnic_dcb_fill_cee_pg_params(struct qlcnic_dcb_param *each, 6878c2ecf20Sopenharmony_ci struct qlcnic_dcb_cee *type) 6888c2ecf20Sopenharmony_ci{ 6898c2ecf20Sopenharmony_ci struct qlcnic_dcb_pg_cfg *pg_cfg; 6908c2ecf20Sopenharmony_ci u8 i, tsa, bw_per; 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci for (i = 0; i < QLC_DCB_MAX_PG; i++) { 6938c2ecf20Sopenharmony_ci pg_cfg = &type->pg_cfg[i]; 6948c2ecf20Sopenharmony_ci pg_cfg->valid = true; 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci if (i < 4) { 6978c2ecf20Sopenharmony_ci bw_per = QLC_DCB_GET_BWPER_PG(each->pg_bw_map[0], i); 6988c2ecf20Sopenharmony_ci tsa = QLC_DCB_GET_TSA_PG(each->pg_tsa_map[0], i); 6998c2ecf20Sopenharmony_ci } else { 7008c2ecf20Sopenharmony_ci bw_per = QLC_DCB_GET_BWPER_PG(each->pg_bw_map[1], i); 7018c2ecf20Sopenharmony_ci tsa = QLC_DCB_GET_TSA_PG(each->pg_tsa_map[1], i); 7028c2ecf20Sopenharmony_ci } 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci pg_cfg->total_bw_percent = bw_per; 7058c2ecf20Sopenharmony_ci pg_cfg->tsa_type = tsa; 7068c2ecf20Sopenharmony_ci } 7078c2ecf20Sopenharmony_ci} 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_cistatic void 7108c2ecf20Sopenharmony_ciqlcnic_dcb_fill_cee_app_params(struct qlcnic_adapter *adapter, u8 idx, 7118c2ecf20Sopenharmony_ci struct qlcnic_dcb_param *each, 7128c2ecf20Sopenharmony_ci struct qlcnic_dcb_cee *type) 7138c2ecf20Sopenharmony_ci{ 7148c2ecf20Sopenharmony_ci struct qlcnic_dcb_app *app; 7158c2ecf20Sopenharmony_ci u8 i, num_app, map, cnt; 7168c2ecf20Sopenharmony_ci struct dcb_app new_app; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci num_app = qlcnic_dcb_get_num_app(adapter, each->hdr_prio_pfc_map[0]); 7198c2ecf20Sopenharmony_ci for (i = 0; i < num_app; i++) { 7208c2ecf20Sopenharmony_ci app = &type->app[i]; 7218c2ecf20Sopenharmony_ci app->valid = true; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci /* Only for CEE (-1) */ 7248c2ecf20Sopenharmony_ci app->selector = QLC_DCB_GET_SELECTOR_APP(each->app[i]) - 1; 7258c2ecf20Sopenharmony_ci new_app.selector = app->selector; 7268c2ecf20Sopenharmony_ci app->protocol = QLC_DCB_GET_PROTO_ID_APP(each->app[i]); 7278c2ecf20Sopenharmony_ci new_app.protocol = app->protocol; 7288c2ecf20Sopenharmony_ci map = qlcnic_dcb_get_prio_map_app(adapter, each->app[i]); 7298c2ecf20Sopenharmony_ci cnt = qlcnic_dcb_prio_count(map); 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci if (cnt >= QLC_DCB_MAX_TC) 7328c2ecf20Sopenharmony_ci cnt = 0; 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci app->priority = cnt; 7358c2ecf20Sopenharmony_ci new_app.priority = cnt; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci if (idx == QLC_DCB_OPER_IDX && adapter->netdev->dcbnl_ops) 7388c2ecf20Sopenharmony_ci dcb_setapp(adapter->netdev, &new_app); 7398c2ecf20Sopenharmony_ci } 7408c2ecf20Sopenharmony_ci} 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_cistatic void qlcnic_dcb_map_cee_params(struct qlcnic_adapter *adapter, u8 idx) 7438c2ecf20Sopenharmony_ci{ 7448c2ecf20Sopenharmony_ci struct qlcnic_dcb_mbx_params *mbx = adapter->dcb->param; 7458c2ecf20Sopenharmony_ci struct qlcnic_dcb_param *each = &mbx->type[idx]; 7468c2ecf20Sopenharmony_ci struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg; 7478c2ecf20Sopenharmony_ci struct qlcnic_dcb_cee *type = &cfg->type[idx]; 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci type->tc_param_valid = false; 7508c2ecf20Sopenharmony_ci type->pfc_mode_enable = false; 7518c2ecf20Sopenharmony_ci memset(type->tc_cfg, 0, 7528c2ecf20Sopenharmony_ci sizeof(struct qlcnic_dcb_tc_cfg) * QLC_DCB_MAX_TC); 7538c2ecf20Sopenharmony_ci memset(type->pg_cfg, 0, 7548c2ecf20Sopenharmony_ci sizeof(struct qlcnic_dcb_pg_cfg) * QLC_DCB_MAX_TC); 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci if (qlcnic_dcb_pfc_hdr_valid(adapter, each->hdr_prio_pfc_map[0]) && 7578c2ecf20Sopenharmony_ci cfg->capability.max_pfc_tc) 7588c2ecf20Sopenharmony_ci type->pfc_mode_enable = true; 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci if (qlcnic_dcb_tsa_hdr_valid(adapter, each->hdr_prio_pfc_map[0]) && 7618c2ecf20Sopenharmony_ci cfg->capability.max_ets_tc) 7628c2ecf20Sopenharmony_ci type->tc_param_valid = true; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci qlcnic_dcb_fill_cee_tc_params(mbx, each, type); 7658c2ecf20Sopenharmony_ci qlcnic_dcb_fill_cee_pg_params(each, type); 7668c2ecf20Sopenharmony_ci qlcnic_dcb_fill_cee_app_params(adapter, idx, each, type); 7678c2ecf20Sopenharmony_ci} 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_cistatic void qlcnic_dcb_data_cee_param_map(struct qlcnic_adapter *adapter) 7708c2ecf20Sopenharmony_ci{ 7718c2ecf20Sopenharmony_ci int i; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci for (i = 0; i < QLC_DCB_NUM_PARAM; i++) 7748c2ecf20Sopenharmony_ci qlcnic_dcb_map_cee_params(adapter, i); 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci dcbnl_cee_notify(adapter->netdev, RTM_GETDCB, DCB_CMD_CEE_GET, 0, 0); 7778c2ecf20Sopenharmony_ci} 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_cistatic u8 qlcnic_dcb_get_state(struct net_device *netdev) 7808c2ecf20Sopenharmony_ci{ 7818c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = netdev_priv(netdev); 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci return test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state); 7848c2ecf20Sopenharmony_ci} 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_cistatic void qlcnic_dcb_get_perm_hw_addr(struct net_device *netdev, u8 *addr) 7878c2ecf20Sopenharmony_ci{ 7888c2ecf20Sopenharmony_ci memcpy(addr, netdev->perm_addr, netdev->addr_len); 7898c2ecf20Sopenharmony_ci} 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_cistatic void 7928c2ecf20Sopenharmony_ciqlcnic_dcb_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, u8 *prio, 7938c2ecf20Sopenharmony_ci u8 *pgid, u8 *bw_per, u8 *up_tc_map) 7948c2ecf20Sopenharmony_ci{ 7958c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = netdev_priv(netdev); 7968c2ecf20Sopenharmony_ci struct qlcnic_dcb_tc_cfg *tc_cfg, *temp; 7978c2ecf20Sopenharmony_ci struct qlcnic_dcb_cee *type; 7988c2ecf20Sopenharmony_ci u8 i, cnt, pg; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX]; 8018c2ecf20Sopenharmony_ci *prio = *pgid = *bw_per = *up_tc_map = 0; 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) || 8048c2ecf20Sopenharmony_ci !type->tc_param_valid) 8058c2ecf20Sopenharmony_ci return; 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci if (tc < 0 || (tc >= QLC_DCB_MAX_TC)) 8088c2ecf20Sopenharmony_ci return; 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci tc_cfg = &type->tc_cfg[tc]; 8118c2ecf20Sopenharmony_ci if (!tc_cfg->valid) 8128c2ecf20Sopenharmony_ci return; 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci *pgid = tc_cfg->pgid; 8158c2ecf20Sopenharmony_ci *prio = tc_cfg->prio_type; 8168c2ecf20Sopenharmony_ci *up_tc_map = tc_cfg->up_tc_map; 8178c2ecf20Sopenharmony_ci pg = *pgid; 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci for (i = 0, cnt = 0; i < QLC_DCB_MAX_TC; i++) { 8208c2ecf20Sopenharmony_ci temp = &type->tc_cfg[i]; 8218c2ecf20Sopenharmony_ci if (temp->valid && (pg == temp->pgid)) 8228c2ecf20Sopenharmony_ci cnt++; 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci tc_cfg->bwg_percent = (100 / cnt); 8268c2ecf20Sopenharmony_ci *bw_per = tc_cfg->bwg_percent; 8278c2ecf20Sopenharmony_ci} 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_cistatic void qlcnic_dcb_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid, 8308c2ecf20Sopenharmony_ci u8 *bw_pct) 8318c2ecf20Sopenharmony_ci{ 8328c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = netdev_priv(netdev); 8338c2ecf20Sopenharmony_ci struct qlcnic_dcb_pg_cfg *pgcfg; 8348c2ecf20Sopenharmony_ci struct qlcnic_dcb_cee *type; 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci *bw_pct = 0; 8378c2ecf20Sopenharmony_ci type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX]; 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) || 8408c2ecf20Sopenharmony_ci !type->tc_param_valid) 8418c2ecf20Sopenharmony_ci return; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci if (pgid < 0 || pgid >= QLC_DCB_MAX_PG) 8448c2ecf20Sopenharmony_ci return; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci pgcfg = &type->pg_cfg[pgid]; 8478c2ecf20Sopenharmony_ci if (!pgcfg->valid) 8488c2ecf20Sopenharmony_ci return; 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci *bw_pct = pgcfg->total_bw_percent; 8518c2ecf20Sopenharmony_ci} 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_cistatic void qlcnic_dcb_get_pfc_cfg(struct net_device *netdev, int prio, 8548c2ecf20Sopenharmony_ci u8 *setting) 8558c2ecf20Sopenharmony_ci{ 8568c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = netdev_priv(netdev); 8578c2ecf20Sopenharmony_ci struct qlcnic_dcb_tc_cfg *tc_cfg; 8588c2ecf20Sopenharmony_ci u8 val = QLC_DCB_GET_MAP(prio); 8598c2ecf20Sopenharmony_ci struct qlcnic_dcb_cee *type; 8608c2ecf20Sopenharmony_ci u8 i; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci *setting = 0; 8638c2ecf20Sopenharmony_ci type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX]; 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) || 8668c2ecf20Sopenharmony_ci !type->pfc_mode_enable) 8678c2ecf20Sopenharmony_ci return; 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci for (i = 0; i < QLC_DCB_MAX_TC; i++) { 8708c2ecf20Sopenharmony_ci tc_cfg = &type->tc_cfg[i]; 8718c2ecf20Sopenharmony_ci if (!tc_cfg->valid) 8728c2ecf20Sopenharmony_ci continue; 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci if ((val & tc_cfg->up_tc_map) && (tc_cfg->prio_cfg[prio].valid)) 8758c2ecf20Sopenharmony_ci *setting = tc_cfg->prio_cfg[prio].pfc_type; 8768c2ecf20Sopenharmony_ci } 8778c2ecf20Sopenharmony_ci} 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_cistatic u8 qlcnic_dcb_get_capability(struct net_device *netdev, int capid, 8808c2ecf20Sopenharmony_ci u8 *cap) 8818c2ecf20Sopenharmony_ci{ 8828c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = netdev_priv(netdev); 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state)) 8858c2ecf20Sopenharmony_ci return 1; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci switch (capid) { 8888c2ecf20Sopenharmony_ci case DCB_CAP_ATTR_PG: 8898c2ecf20Sopenharmony_ci case DCB_CAP_ATTR_UP2TC: 8908c2ecf20Sopenharmony_ci case DCB_CAP_ATTR_PFC: 8918c2ecf20Sopenharmony_ci case DCB_CAP_ATTR_GSP: 8928c2ecf20Sopenharmony_ci *cap = true; 8938c2ecf20Sopenharmony_ci break; 8948c2ecf20Sopenharmony_ci case DCB_CAP_ATTR_PG_TCS: 8958c2ecf20Sopenharmony_ci case DCB_CAP_ATTR_PFC_TCS: 8968c2ecf20Sopenharmony_ci *cap = 0x80; /* 8 priorities for PGs */ 8978c2ecf20Sopenharmony_ci break; 8988c2ecf20Sopenharmony_ci case DCB_CAP_ATTR_DCBX: 8998c2ecf20Sopenharmony_ci *cap = adapter->dcb->cfg->capability.dcb_capability; 9008c2ecf20Sopenharmony_ci break; 9018c2ecf20Sopenharmony_ci default: 9028c2ecf20Sopenharmony_ci *cap = false; 9038c2ecf20Sopenharmony_ci } 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci return 0; 9068c2ecf20Sopenharmony_ci} 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_cistatic int qlcnic_dcb_get_num_tcs(struct net_device *netdev, int attr, u8 *num) 9098c2ecf20Sopenharmony_ci{ 9108c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = netdev_priv(netdev); 9118c2ecf20Sopenharmony_ci struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg; 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state)) 9148c2ecf20Sopenharmony_ci return -EINVAL; 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci switch (attr) { 9178c2ecf20Sopenharmony_ci case DCB_NUMTCS_ATTR_PG: 9188c2ecf20Sopenharmony_ci *num = cfg->capability.max_ets_tc; 9198c2ecf20Sopenharmony_ci return 0; 9208c2ecf20Sopenharmony_ci case DCB_NUMTCS_ATTR_PFC: 9218c2ecf20Sopenharmony_ci *num = cfg->capability.max_pfc_tc; 9228c2ecf20Sopenharmony_ci return 0; 9238c2ecf20Sopenharmony_ci default: 9248c2ecf20Sopenharmony_ci return -EINVAL; 9258c2ecf20Sopenharmony_ci } 9268c2ecf20Sopenharmony_ci} 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_cistatic int qlcnic_dcb_get_app(struct net_device *netdev, u8 idtype, u16 id) 9298c2ecf20Sopenharmony_ci{ 9308c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = netdev_priv(netdev); 9318c2ecf20Sopenharmony_ci struct dcb_app app = { 9328c2ecf20Sopenharmony_ci .selector = idtype, 9338c2ecf20Sopenharmony_ci .protocol = id, 9348c2ecf20Sopenharmony_ci }; 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state)) 9378c2ecf20Sopenharmony_ci return -EINVAL; 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci return dcb_getapp(netdev, &app); 9408c2ecf20Sopenharmony_ci} 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_cistatic u8 qlcnic_dcb_get_pfc_state(struct net_device *netdev) 9438c2ecf20Sopenharmony_ci{ 9448c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = netdev_priv(netdev); 9458c2ecf20Sopenharmony_ci struct qlcnic_dcb *dcb = adapter->dcb; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci if (!test_bit(QLCNIC_DCB_STATE, &dcb->state)) 9488c2ecf20Sopenharmony_ci return 0; 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci return dcb->cfg->type[QLC_DCB_OPER_IDX].pfc_mode_enable; 9518c2ecf20Sopenharmony_ci} 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_cistatic u8 qlcnic_dcb_get_dcbx(struct net_device *netdev) 9548c2ecf20Sopenharmony_ci{ 9558c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = netdev_priv(netdev); 9568c2ecf20Sopenharmony_ci struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state)) 9598c2ecf20Sopenharmony_ci return 0; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci return cfg->capability.dcb_capability; 9628c2ecf20Sopenharmony_ci} 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_cistatic u8 qlcnic_dcb_get_feat_cfg(struct net_device *netdev, int fid, u8 *flag) 9658c2ecf20Sopenharmony_ci{ 9668c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = netdev_priv(netdev); 9678c2ecf20Sopenharmony_ci struct qlcnic_dcb_cee *type; 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state)) 9708c2ecf20Sopenharmony_ci return 1; 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX]; 9738c2ecf20Sopenharmony_ci *flag = 0; 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci switch (fid) { 9768c2ecf20Sopenharmony_ci case DCB_FEATCFG_ATTR_PG: 9778c2ecf20Sopenharmony_ci if (type->tc_param_valid) 9788c2ecf20Sopenharmony_ci *flag |= DCB_FEATCFG_ENABLE; 9798c2ecf20Sopenharmony_ci else 9808c2ecf20Sopenharmony_ci *flag |= DCB_FEATCFG_ERROR; 9818c2ecf20Sopenharmony_ci break; 9828c2ecf20Sopenharmony_ci case DCB_FEATCFG_ATTR_PFC: 9838c2ecf20Sopenharmony_ci if (type->pfc_mode_enable) { 9848c2ecf20Sopenharmony_ci if (type->tc_cfg[0].prio_cfg[0].pfc_type) 9858c2ecf20Sopenharmony_ci *flag |= DCB_FEATCFG_ENABLE; 9868c2ecf20Sopenharmony_ci } else { 9878c2ecf20Sopenharmony_ci *flag |= DCB_FEATCFG_ERROR; 9888c2ecf20Sopenharmony_ci } 9898c2ecf20Sopenharmony_ci break; 9908c2ecf20Sopenharmony_ci case DCB_FEATCFG_ATTR_APP: 9918c2ecf20Sopenharmony_ci *flag |= DCB_FEATCFG_ENABLE; 9928c2ecf20Sopenharmony_ci break; 9938c2ecf20Sopenharmony_ci default: 9948c2ecf20Sopenharmony_ci netdev_err(netdev, "Invalid Feature ID %d\n", fid); 9958c2ecf20Sopenharmony_ci return 1; 9968c2ecf20Sopenharmony_ci } 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci return 0; 9998c2ecf20Sopenharmony_ci} 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_cistatic inline void 10028c2ecf20Sopenharmony_ciqlcnic_dcb_get_pg_tc_cfg_rx(struct net_device *netdev, int prio, u8 *prio_type, 10038c2ecf20Sopenharmony_ci u8 *pgid, u8 *bw_pct, u8 *up_map) 10048c2ecf20Sopenharmony_ci{ 10058c2ecf20Sopenharmony_ci *prio_type = *pgid = *bw_pct = *up_map = 0; 10068c2ecf20Sopenharmony_ci} 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_cistatic inline void 10098c2ecf20Sopenharmony_ciqlcnic_dcb_get_pg_bwg_cfg_rx(struct net_device *netdev, int pgid, u8 *bw_pct) 10108c2ecf20Sopenharmony_ci{ 10118c2ecf20Sopenharmony_ci *bw_pct = 0; 10128c2ecf20Sopenharmony_ci} 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_cistatic int qlcnic_dcb_peer_app_info(struct net_device *netdev, 10158c2ecf20Sopenharmony_ci struct dcb_peer_app_info *info, 10168c2ecf20Sopenharmony_ci u16 *app_count) 10178c2ecf20Sopenharmony_ci{ 10188c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = netdev_priv(netdev); 10198c2ecf20Sopenharmony_ci struct qlcnic_dcb_cee *peer; 10208c2ecf20Sopenharmony_ci int i; 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci memset(info, 0, sizeof(*info)); 10238c2ecf20Sopenharmony_ci *app_count = 0; 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state)) 10268c2ecf20Sopenharmony_ci return 0; 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX]; 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci for (i = 0; i < QLC_DCB_MAX_APP; i++) { 10318c2ecf20Sopenharmony_ci if (peer->app[i].valid) 10328c2ecf20Sopenharmony_ci (*app_count)++; 10338c2ecf20Sopenharmony_ci } 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci return 0; 10368c2ecf20Sopenharmony_ci} 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_cistatic int qlcnic_dcb_peer_app_table(struct net_device *netdev, 10398c2ecf20Sopenharmony_ci struct dcb_app *table) 10408c2ecf20Sopenharmony_ci{ 10418c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = netdev_priv(netdev); 10428c2ecf20Sopenharmony_ci struct qlcnic_dcb_cee *peer; 10438c2ecf20Sopenharmony_ci struct qlcnic_dcb_app *app; 10448c2ecf20Sopenharmony_ci int i, j; 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state)) 10478c2ecf20Sopenharmony_ci return 0; 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX]; 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci for (i = 0, j = 0; i < QLC_DCB_MAX_APP; i++) { 10528c2ecf20Sopenharmony_ci app = &peer->app[i]; 10538c2ecf20Sopenharmony_ci if (!app->valid) 10548c2ecf20Sopenharmony_ci continue; 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci table[j].selector = app->selector; 10578c2ecf20Sopenharmony_ci table[j].priority = app->priority; 10588c2ecf20Sopenharmony_ci table[j++].protocol = app->protocol; 10598c2ecf20Sopenharmony_ci } 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci return 0; 10628c2ecf20Sopenharmony_ci} 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_cistatic int qlcnic_dcb_cee_peer_get_pg(struct net_device *netdev, 10658c2ecf20Sopenharmony_ci struct cee_pg *pg) 10668c2ecf20Sopenharmony_ci{ 10678c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = netdev_priv(netdev); 10688c2ecf20Sopenharmony_ci struct qlcnic_dcb_cee *peer; 10698c2ecf20Sopenharmony_ci u8 i, j, k, map; 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state)) 10728c2ecf20Sopenharmony_ci return 0; 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX]; 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci for (i = 0, j = 0; i < QLC_DCB_MAX_PG; i++) { 10778c2ecf20Sopenharmony_ci if (!peer->pg_cfg[i].valid) 10788c2ecf20Sopenharmony_ci continue; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci pg->pg_bw[j] = peer->pg_cfg[i].total_bw_percent; 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci for (k = 0; k < QLC_DCB_MAX_TC; k++) { 10838c2ecf20Sopenharmony_ci if (peer->tc_cfg[i].valid && 10848c2ecf20Sopenharmony_ci (peer->tc_cfg[i].pgid == i)) { 10858c2ecf20Sopenharmony_ci map = peer->tc_cfg[i].up_tc_map; 10868c2ecf20Sopenharmony_ci pg->prio_pg[j++] = map; 10878c2ecf20Sopenharmony_ci break; 10888c2ecf20Sopenharmony_ci } 10898c2ecf20Sopenharmony_ci } 10908c2ecf20Sopenharmony_ci } 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci return 0; 10938c2ecf20Sopenharmony_ci} 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_cistatic int qlcnic_dcb_cee_peer_get_pfc(struct net_device *netdev, 10968c2ecf20Sopenharmony_ci struct cee_pfc *pfc) 10978c2ecf20Sopenharmony_ci{ 10988c2ecf20Sopenharmony_ci struct qlcnic_adapter *adapter = netdev_priv(netdev); 10998c2ecf20Sopenharmony_ci struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg; 11008c2ecf20Sopenharmony_ci struct qlcnic_dcb_tc_cfg *tc; 11018c2ecf20Sopenharmony_ci struct qlcnic_dcb_cee *peer; 11028c2ecf20Sopenharmony_ci u8 i, setting, prio; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci pfc->pfc_en = 0; 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state)) 11078c2ecf20Sopenharmony_ci return 0; 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci peer = &cfg->type[QLC_DCB_PEER_IDX]; 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci for (i = 0; i < QLC_DCB_MAX_TC; i++) { 11128c2ecf20Sopenharmony_ci tc = &peer->tc_cfg[i]; 11138c2ecf20Sopenharmony_ci prio = qlcnic_dcb_prio_count(tc->up_tc_map); 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci setting = 0; 11168c2ecf20Sopenharmony_ci qlcnic_dcb_get_pfc_cfg(netdev, prio, &setting); 11178c2ecf20Sopenharmony_ci if (setting) 11188c2ecf20Sopenharmony_ci pfc->pfc_en |= QLC_DCB_GET_MAP(i); 11198c2ecf20Sopenharmony_ci } 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci pfc->tcs_supported = cfg->capability.max_pfc_tc; 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci return 0; 11248c2ecf20Sopenharmony_ci} 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_cistatic const struct dcbnl_rtnl_ops qlcnic_dcbnl_ops = { 11278c2ecf20Sopenharmony_ci .getstate = qlcnic_dcb_get_state, 11288c2ecf20Sopenharmony_ci .getpermhwaddr = qlcnic_dcb_get_perm_hw_addr, 11298c2ecf20Sopenharmony_ci .getpgtccfgtx = qlcnic_dcb_get_pg_tc_cfg_tx, 11308c2ecf20Sopenharmony_ci .getpgbwgcfgtx = qlcnic_dcb_get_pg_bwg_cfg_tx, 11318c2ecf20Sopenharmony_ci .getpfccfg = qlcnic_dcb_get_pfc_cfg, 11328c2ecf20Sopenharmony_ci .getcap = qlcnic_dcb_get_capability, 11338c2ecf20Sopenharmony_ci .getnumtcs = qlcnic_dcb_get_num_tcs, 11348c2ecf20Sopenharmony_ci .getapp = qlcnic_dcb_get_app, 11358c2ecf20Sopenharmony_ci .getpfcstate = qlcnic_dcb_get_pfc_state, 11368c2ecf20Sopenharmony_ci .getdcbx = qlcnic_dcb_get_dcbx, 11378c2ecf20Sopenharmony_ci .getfeatcfg = qlcnic_dcb_get_feat_cfg, 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci .getpgtccfgrx = qlcnic_dcb_get_pg_tc_cfg_rx, 11408c2ecf20Sopenharmony_ci .getpgbwgcfgrx = qlcnic_dcb_get_pg_bwg_cfg_rx, 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_ci .peer_getappinfo = qlcnic_dcb_peer_app_info, 11438c2ecf20Sopenharmony_ci .peer_getapptable = qlcnic_dcb_peer_app_table, 11448c2ecf20Sopenharmony_ci .cee_peer_getpg = qlcnic_dcb_cee_peer_get_pg, 11458c2ecf20Sopenharmony_ci .cee_peer_getpfc = qlcnic_dcb_cee_peer_get_pfc, 11468c2ecf20Sopenharmony_ci}; 1147