qlcnic_dcb.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  1. /*
  2. * QLogic qlcnic NIC Driver
  3. * Copyright (c) 2009-2013 QLogic Corporation
  4. *
  5. * See LICENSE.qlcnic for copyright and licensing details.
  6. */
  7. #include <linux/types.h>
  8. #include "qlcnic.h"
  9. #define QLC_DCB_NUM_PARAM 3
  10. #define QLC_DCB_LOCAL_IDX 0
  11. #define QLC_DCB_OPER_IDX 1
  12. #define QLC_DCB_PEER_IDX 2
  13. #define QLC_DCB_GET_MAP(V) (1 << V)
  14. #define QLC_DCB_AEN_BIT 0x2
  15. #define QLC_DCB_FW_VER 0x2
  16. #define QLC_DCB_MAX_TC 0x8
  17. #define QLC_DCB_MAX_APP 0x8
  18. #define QLC_DCB_MAX_PRIO QLC_DCB_MAX_TC
  19. #define QLC_DCB_MAX_PG QLC_DCB_MAX_TC
  20. #define QLC_DCB_TSA_SUPPORT(V) (V & 0x1)
  21. #define QLC_DCB_ETS_SUPPORT(V) ((V >> 1) & 0x1)
  22. #define QLC_DCB_VERSION_SUPPORT(V) ((V >> 2) & 0xf)
  23. #define QLC_DCB_MAX_NUM_TC(V) ((V >> 20) & 0xf)
  24. #define QLC_DCB_MAX_NUM_ETS_TC(V) ((V >> 24) & 0xf)
  25. #define QLC_DCB_MAX_NUM_PFC_TC(V) ((V >> 28) & 0xf)
  26. #define QLC_DCB_GET_TC_PRIO(X, P) ((X >> (P * 3)) & 0x7)
  27. #define QLC_DCB_GET_PGID_PRIO(X, P) ((X >> (P * 8)) & 0xff)
  28. #define QLC_DCB_GET_BWPER_PG(X, P) ((X >> (P * 8)) & 0xff)
  29. #define QLC_DCB_GET_TSA_PG(X, P) ((X >> (P * 8)) & 0xff)
  30. #define QLC_DCB_GET_PFC_PRIO(X, P) (((X >> 24) >> P) & 0x1)
  31. #define QLC_DCB_GET_PROTO_ID_APP(X) ((X >> 8) & 0xffff)
  32. #define QLC_DCB_GET_SELECTOR_APP(X) (X & 0xff)
  33. #define QLC_DCB_LOCAL_PARAM_FWID 0x3
  34. #define QLC_DCB_OPER_PARAM_FWID 0x1
  35. #define QLC_DCB_PEER_PARAM_FWID 0x2
  36. #define QLC_83XX_DCB_GET_NUMAPP(X) ((X >> 2) & 0xf)
  37. #define QLC_83XX_DCB_TSA_VALID(X) (X & 0x1)
  38. #define QLC_83XX_DCB_PFC_VALID(X) ((X >> 1) & 0x1)
  39. #define QLC_83XX_DCB_GET_PRIOMAP_APP(X) (X >> 24)
  40. #define QLC_82XX_DCB_GET_NUMAPP(X) ((X >> 12) & 0xf)
  41. #define QLC_82XX_DCB_TSA_VALID(X) ((X >> 4) & 0x1)
  42. #define QLC_82XX_DCB_PFC_VALID(X) ((X >> 5) & 0x1)
  43. #define QLC_82XX_DCB_GET_PRIOVAL_APP(X) ((X >> 24) & 0x7)
  44. #define QLC_82XX_DCB_GET_PRIOMAP_APP(X) (1 << X)
  45. #define QLC_82XX_DCB_PRIO_TC_MAP (0x76543210)
  46. static const struct dcbnl_rtnl_ops qlcnic_dcbnl_ops;
  47. static void qlcnic_dcb_aen_work(struct work_struct *);
  48. static void qlcnic_dcb_data_cee_param_map(struct qlcnic_adapter *);
  49. static inline void __qlcnic_init_dcbnl_ops(struct qlcnic_dcb *);
  50. static void __qlcnic_dcb_free(struct qlcnic_dcb *);
  51. static int __qlcnic_dcb_attach(struct qlcnic_dcb *);
  52. static int __qlcnic_dcb_query_hw_capability(struct qlcnic_dcb *, char *);
  53. static void __qlcnic_dcb_get_info(struct qlcnic_dcb *);
  54. static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_dcb *);
  55. static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_dcb *, char *, u8);
  56. static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_dcb *);
  57. static void qlcnic_82xx_dcb_aen_handler(struct qlcnic_dcb *, void *);
  58. static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_dcb *);
  59. static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_dcb *, char *, u8);
  60. static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb *);
  61. static int qlcnic_83xx_dcb_register_aen(struct qlcnic_dcb *, bool);
  62. static void qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb *, void *);
  63. struct qlcnic_dcb_capability {
  64. bool tsa_capability;
  65. bool ets_capability;
  66. u8 max_num_tc;
  67. u8 max_ets_tc;
  68. u8 max_pfc_tc;
  69. u8 dcb_capability;
  70. };
  71. struct qlcnic_dcb_param {
  72. u32 hdr_prio_pfc_map[2];
  73. u32 prio_pg_map[2];
  74. u32 pg_bw_map[2];
  75. u32 pg_tsa_map[2];
  76. u32 app[QLC_DCB_MAX_APP];
  77. };
  78. struct qlcnic_dcb_mbx_params {
  79. /* 1st local, 2nd operational 3rd remote */
  80. struct qlcnic_dcb_param type[3];
  81. u32 prio_tc_map;
  82. };
  83. struct qlcnic_82xx_dcb_param_mbx_le {
  84. __le32 hdr_prio_pfc_map[2];
  85. __le32 prio_pg_map[2];
  86. __le32 pg_bw_map[2];
  87. __le32 pg_tsa_map[2];
  88. __le32 app[QLC_DCB_MAX_APP];
  89. };
  90. enum qlcnic_dcb_selector {
  91. QLC_SELECTOR_DEF = 0x0,
  92. QLC_SELECTOR_ETHER,
  93. QLC_SELECTOR_TCP,
  94. QLC_SELECTOR_UDP,
  95. };
  96. enum qlcnic_dcb_prio_type {
  97. QLC_PRIO_NONE = 0,
  98. QLC_PRIO_GROUP,
  99. QLC_PRIO_LINK,
  100. };
  101. enum qlcnic_dcb_pfc_type {
  102. QLC_PFC_DISABLED = 0,
  103. QLC_PFC_FULL,
  104. QLC_PFC_TX,
  105. QLC_PFC_RX
  106. };
  107. struct qlcnic_dcb_prio_cfg {
  108. bool valid;
  109. enum qlcnic_dcb_pfc_type pfc_type;
  110. };
  111. struct qlcnic_dcb_pg_cfg {
  112. bool valid;
  113. u8 total_bw_percent; /* of Link/ port BW */
  114. u8 prio_count;
  115. u8 tsa_type;
  116. };
  117. struct qlcnic_dcb_tc_cfg {
  118. bool valid;
  119. struct qlcnic_dcb_prio_cfg prio_cfg[QLC_DCB_MAX_PRIO];
  120. enum qlcnic_dcb_prio_type prio_type; /* always prio_link */
  121. u8 link_percent; /* % of link bandwidth */
  122. u8 bwg_percent; /* % of BWG's bandwidth */
  123. u8 up_tc_map;
  124. u8 pgid;
  125. };
  126. struct qlcnic_dcb_app {
  127. bool valid;
  128. enum qlcnic_dcb_selector selector;
  129. u16 protocol;
  130. u8 priority;
  131. };
  132. struct qlcnic_dcb_cee {
  133. struct qlcnic_dcb_tc_cfg tc_cfg[QLC_DCB_MAX_TC];
  134. struct qlcnic_dcb_pg_cfg pg_cfg[QLC_DCB_MAX_PG];
  135. struct qlcnic_dcb_app app[QLC_DCB_MAX_APP];
  136. bool tc_param_valid;
  137. bool pfc_mode_enable;
  138. };
  139. struct qlcnic_dcb_cfg {
  140. /* 0 - local, 1 - operational, 2 - remote */
  141. struct qlcnic_dcb_cee type[QLC_DCB_NUM_PARAM];
  142. struct qlcnic_dcb_capability capability;
  143. u32 version;
  144. };
  145. static struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = {
  146. .init_dcbnl_ops = __qlcnic_init_dcbnl_ops,
  147. .free = __qlcnic_dcb_free,
  148. .attach = __qlcnic_dcb_attach,
  149. .query_hw_capability = __qlcnic_dcb_query_hw_capability,
  150. .get_info = __qlcnic_dcb_get_info,
  151. .get_hw_capability = qlcnic_83xx_dcb_get_hw_capability,
  152. .query_cee_param = qlcnic_83xx_dcb_query_cee_param,
  153. .get_cee_cfg = qlcnic_83xx_dcb_get_cee_cfg,
  154. .register_aen = qlcnic_83xx_dcb_register_aen,
  155. .aen_handler = qlcnic_83xx_dcb_aen_handler,
  156. };
  157. static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = {
  158. .init_dcbnl_ops = __qlcnic_init_dcbnl_ops,
  159. .free = __qlcnic_dcb_free,
  160. .attach = __qlcnic_dcb_attach,
  161. .query_hw_capability = __qlcnic_dcb_query_hw_capability,
  162. .get_info = __qlcnic_dcb_get_info,
  163. .get_hw_capability = qlcnic_82xx_dcb_get_hw_capability,
  164. .query_cee_param = qlcnic_82xx_dcb_query_cee_param,
  165. .get_cee_cfg = qlcnic_82xx_dcb_get_cee_cfg,
  166. .aen_handler = qlcnic_82xx_dcb_aen_handler,
  167. };
  168. static u8 qlcnic_dcb_get_num_app(struct qlcnic_adapter *adapter, u32 val)
  169. {
  170. if (qlcnic_82xx_check(adapter))
  171. return QLC_82XX_DCB_GET_NUMAPP(val);
  172. else
  173. return QLC_83XX_DCB_GET_NUMAPP(val);
  174. }
  175. static inline u8 qlcnic_dcb_pfc_hdr_valid(struct qlcnic_adapter *adapter,
  176. u32 val)
  177. {
  178. if (qlcnic_82xx_check(adapter))
  179. return QLC_82XX_DCB_PFC_VALID(val);
  180. else
  181. return QLC_83XX_DCB_PFC_VALID(val);
  182. }
  183. static inline u8 qlcnic_dcb_tsa_hdr_valid(struct qlcnic_adapter *adapter,
  184. u32 val)
  185. {
  186. if (qlcnic_82xx_check(adapter))
  187. return QLC_82XX_DCB_TSA_VALID(val);
  188. else
  189. return QLC_83XX_DCB_TSA_VALID(val);
  190. }
  191. static inline u8 qlcnic_dcb_get_prio_map_app(struct qlcnic_adapter *adapter,
  192. u32 val)
  193. {
  194. if (qlcnic_82xx_check(adapter))
  195. return QLC_82XX_DCB_GET_PRIOMAP_APP(val);
  196. else
  197. return QLC_83XX_DCB_GET_PRIOMAP_APP(val);
  198. }
  199. static int qlcnic_dcb_prio_count(u8 up_tc_map)
  200. {
  201. int j;
  202. for (j = 0; j < QLC_DCB_MAX_TC; j++)
  203. if (up_tc_map & QLC_DCB_GET_MAP(j))
  204. break;
  205. return j;
  206. }
  207. static inline void __qlcnic_init_dcbnl_ops(struct qlcnic_dcb *dcb)
  208. {
  209. if (test_bit(QLCNIC_DCB_STATE, &dcb->state))
  210. dcb->adapter->netdev->dcbnl_ops = &qlcnic_dcbnl_ops;
  211. }
  212. static void qlcnic_set_dcb_ops(struct qlcnic_adapter *adapter)
  213. {
  214. if (qlcnic_82xx_check(adapter))
  215. adapter->dcb->ops = &qlcnic_82xx_dcb_ops;
  216. else if (qlcnic_83xx_check(adapter))
  217. adapter->dcb->ops = &qlcnic_83xx_dcb_ops;
  218. }
  219. int qlcnic_register_dcb(struct qlcnic_adapter *adapter)
  220. {
  221. struct qlcnic_dcb *dcb;
  222. dcb = kzalloc(sizeof(struct qlcnic_dcb), GFP_ATOMIC);
  223. if (!dcb)
  224. return -ENOMEM;
  225. adapter->dcb = dcb;
  226. dcb->adapter = adapter;
  227. qlcnic_set_dcb_ops(adapter);
  228. dcb->state = 0;
  229. return 0;
  230. }
  231. static void __qlcnic_dcb_free(struct qlcnic_dcb *dcb)
  232. {
  233. struct qlcnic_adapter *adapter;
  234. if (!dcb)
  235. return;
  236. adapter = dcb->adapter;
  237. qlcnic_dcb_register_aen(dcb, 0);
  238. while (test_bit(QLCNIC_DCB_AEN_MODE, &dcb->state))
  239. usleep_range(10000, 11000);
  240. cancel_delayed_work_sync(&dcb->aen_work);
  241. if (dcb->wq) {
  242. destroy_workqueue(dcb->wq);
  243. dcb->wq = NULL;
  244. }
  245. kfree(dcb->cfg);
  246. dcb->cfg = NULL;
  247. kfree(dcb->param);
  248. dcb->param = NULL;
  249. kfree(dcb);
  250. adapter->dcb = NULL;
  251. }
  252. static void __qlcnic_dcb_get_info(struct qlcnic_dcb *dcb)
  253. {
  254. qlcnic_dcb_get_hw_capability(dcb);
  255. qlcnic_dcb_get_cee_cfg(dcb);
  256. qlcnic_dcb_register_aen(dcb, 1);
  257. }
  258. static int __qlcnic_dcb_attach(struct qlcnic_dcb *dcb)
  259. {
  260. int err = 0;
  261. INIT_DELAYED_WORK(&dcb->aen_work, qlcnic_dcb_aen_work);
  262. dcb->wq = create_singlethread_workqueue("qlcnic-dcb");
  263. if (!dcb->wq) {
  264. dev_err(&dcb->adapter->pdev->dev,
  265. "DCB workqueue allocation failed. DCB will be disabled\n");
  266. return -1;
  267. }
  268. dcb->cfg = kzalloc(sizeof(struct qlcnic_dcb_cfg), GFP_ATOMIC);
  269. if (!dcb->cfg) {
  270. err = -ENOMEM;
  271. goto out_free_wq;
  272. }
  273. dcb->param = kzalloc(sizeof(struct qlcnic_dcb_mbx_params), GFP_ATOMIC);
  274. if (!dcb->param) {
  275. err = -ENOMEM;
  276. goto out_free_cfg;
  277. }
  278. qlcnic_dcb_get_info(dcb);
  279. return 0;
  280. out_free_cfg:
  281. kfree(dcb->cfg);
  282. dcb->cfg = NULL;
  283. out_free_wq:
  284. destroy_workqueue(dcb->wq);
  285. dcb->wq = NULL;
  286. return err;
  287. }
  288. static int __qlcnic_dcb_query_hw_capability(struct qlcnic_dcb *dcb, char *buf)
  289. {
  290. struct qlcnic_adapter *adapter = dcb->adapter;
  291. struct qlcnic_cmd_args cmd;
  292. u32 mbx_out;
  293. int err;
  294. err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_CAP);
  295. if (err)
  296. return err;
  297. err = qlcnic_issue_cmd(adapter, &cmd);
  298. if (err) {
  299. dev_err(&adapter->pdev->dev,
  300. "Failed to query DCBX capability, err %d\n", err);
  301. } else {
  302. mbx_out = cmd.rsp.arg[1];
  303. if (buf)
  304. memcpy(buf, &mbx_out, sizeof(u32));
  305. }
  306. qlcnic_free_mbx_args(&cmd);
  307. return err;
  308. }
  309. static int __qlcnic_dcb_get_capability(struct qlcnic_dcb *dcb, u32 *val)
  310. {
  311. struct qlcnic_dcb_capability *cap = &dcb->cfg->capability;
  312. u32 mbx_out;
  313. int err;
  314. memset(cap, 0, sizeof(struct qlcnic_dcb_capability));
  315. err = qlcnic_dcb_query_hw_capability(dcb, (char *)val);
  316. if (err)
  317. return err;
  318. mbx_out = *val;
  319. if (QLC_DCB_TSA_SUPPORT(mbx_out))
  320. cap->tsa_capability = true;
  321. if (QLC_DCB_ETS_SUPPORT(mbx_out))
  322. cap->ets_capability = true;
  323. cap->max_num_tc = QLC_DCB_MAX_NUM_TC(mbx_out);
  324. cap->max_ets_tc = QLC_DCB_MAX_NUM_ETS_TC(mbx_out);
  325. cap->max_pfc_tc = QLC_DCB_MAX_NUM_PFC_TC(mbx_out);
  326. if (cap->max_num_tc > QLC_DCB_MAX_TC ||
  327. cap->max_ets_tc > cap->max_num_tc ||
  328. cap->max_pfc_tc > cap->max_num_tc) {
  329. dev_err(&dcb->adapter->pdev->dev, "Invalid DCB configuration\n");
  330. return -EINVAL;
  331. }
  332. return err;
  333. }
  334. static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_dcb *dcb)
  335. {
  336. struct qlcnic_dcb_cfg *cfg = dcb->cfg;
  337. struct qlcnic_dcb_capability *cap;
  338. u32 mbx_out;
  339. int err;
  340. err = __qlcnic_dcb_get_capability(dcb, &mbx_out);
  341. if (err)
  342. return err;
  343. cap = &cfg->capability;
  344. cap->dcb_capability = DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_LLD_MANAGED;
  345. if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability)
  346. set_bit(QLCNIC_DCB_STATE, &dcb->state);
  347. return err;
  348. }
  349. static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_dcb *dcb,
  350. char *buf, u8 type)
  351. {
  352. u16 size = sizeof(struct qlcnic_82xx_dcb_param_mbx_le);
  353. struct qlcnic_adapter *adapter = dcb->adapter;
  354. struct qlcnic_82xx_dcb_param_mbx_le *prsp_le;
  355. struct device *dev = &adapter->pdev->dev;
  356. dma_addr_t cardrsp_phys_addr;
  357. struct qlcnic_dcb_param rsp;
  358. struct qlcnic_cmd_args cmd;
  359. u64 phys_addr;
  360. void *addr;
  361. int err, i;
  362. switch (type) {
  363. case QLC_DCB_LOCAL_PARAM_FWID:
  364. case QLC_DCB_OPER_PARAM_FWID:
  365. case QLC_DCB_PEER_PARAM_FWID:
  366. break;
  367. default:
  368. dev_err(dev, "Invalid parameter type %d\n", type);
  369. return -EINVAL;
  370. }
  371. addr = dma_alloc_coherent(dev, size, &cardrsp_phys_addr, GFP_KERNEL);
  372. if (addr == NULL)
  373. return -ENOMEM;
  374. prsp_le = addr;
  375. err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM);
  376. if (err)
  377. goto out_free_rsp;
  378. phys_addr = cardrsp_phys_addr;
  379. cmd.req.arg[1] = size | (type << 16);
  380. cmd.req.arg[2] = MSD(phys_addr);
  381. cmd.req.arg[3] = LSD(phys_addr);
  382. err = qlcnic_issue_cmd(adapter, &cmd);
  383. if (err) {
  384. dev_err(dev, "Failed to query DCBX parameter, err %d\n", err);
  385. goto out;
  386. }
  387. memset(&rsp, 0, sizeof(struct qlcnic_dcb_param));
  388. rsp.hdr_prio_pfc_map[0] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[0]);
  389. rsp.hdr_prio_pfc_map[1] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[1]);
  390. rsp.prio_pg_map[0] = le32_to_cpu(prsp_le->prio_pg_map[0]);
  391. rsp.prio_pg_map[1] = le32_to_cpu(prsp_le->prio_pg_map[1]);
  392. rsp.pg_bw_map[0] = le32_to_cpu(prsp_le->pg_bw_map[0]);
  393. rsp.pg_bw_map[1] = le32_to_cpu(prsp_le->pg_bw_map[1]);
  394. rsp.pg_tsa_map[0] = le32_to_cpu(prsp_le->pg_tsa_map[0]);
  395. rsp.pg_tsa_map[1] = le32_to_cpu(prsp_le->pg_tsa_map[1]);
  396. for (i = 0; i < QLC_DCB_MAX_APP; i++)
  397. rsp.app[i] = le32_to_cpu(prsp_le->app[i]);
  398. if (buf)
  399. memcpy(buf, &rsp, size);
  400. out:
  401. qlcnic_free_mbx_args(&cmd);
  402. out_free_rsp:
  403. dma_free_coherent(dev, size, addr, cardrsp_phys_addr);
  404. return err;
  405. }
  406. static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_dcb *dcb)
  407. {
  408. struct qlcnic_dcb_mbx_params *mbx;
  409. int err;
  410. mbx = dcb->param;
  411. if (!mbx)
  412. return 0;
  413. err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[0],
  414. QLC_DCB_LOCAL_PARAM_FWID);
  415. if (err)
  416. return err;
  417. err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[1],
  418. QLC_DCB_OPER_PARAM_FWID);
  419. if (err)
  420. return err;
  421. err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[2],
  422. QLC_DCB_PEER_PARAM_FWID);
  423. if (err)
  424. return err;
  425. mbx->prio_tc_map = QLC_82XX_DCB_PRIO_TC_MAP;
  426. qlcnic_dcb_data_cee_param_map(dcb->adapter);
  427. return err;
  428. }
  429. static void qlcnic_dcb_aen_work(struct work_struct *work)
  430. {
  431. struct qlcnic_dcb *dcb;
  432. dcb = container_of(work, struct qlcnic_dcb, aen_work.work);
  433. qlcnic_dcb_get_cee_cfg(dcb);
  434. clear_bit(QLCNIC_DCB_AEN_MODE, &dcb->state);
  435. }
  436. static void qlcnic_82xx_dcb_aen_handler(struct qlcnic_dcb *dcb, void *data)
  437. {
  438. if (test_and_set_bit(QLCNIC_DCB_AEN_MODE, &dcb->state))
  439. return;
  440. queue_delayed_work(dcb->wq, &dcb->aen_work, 0);
  441. }
  442. static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_dcb *dcb)
  443. {
  444. struct qlcnic_dcb_capability *cap = &dcb->cfg->capability;
  445. u32 mbx_out;
  446. int err;
  447. err = __qlcnic_dcb_get_capability(dcb, &mbx_out);
  448. if (err)
  449. return err;
  450. if (mbx_out & BIT_2)
  451. cap->dcb_capability = DCB_CAP_DCBX_VER_CEE;
  452. if (mbx_out & BIT_3)
  453. cap->dcb_capability |= DCB_CAP_DCBX_VER_IEEE;
  454. if (cap->dcb_capability)
  455. cap->dcb_capability |= DCB_CAP_DCBX_LLD_MANAGED;
  456. if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability)
  457. set_bit(QLCNIC_DCB_STATE, &dcb->state);
  458. return err;
  459. }
  460. static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_dcb *dcb,
  461. char *buf, u8 idx)
  462. {
  463. struct qlcnic_adapter *adapter = dcb->adapter;
  464. struct qlcnic_dcb_mbx_params mbx_out;
  465. int err, i, j, k, max_app, size;
  466. struct qlcnic_dcb_param *each;
  467. struct qlcnic_cmd_args cmd;
  468. u32 val;
  469. char *p;
  470. size = 0;
  471. memset(&mbx_out, 0, sizeof(struct qlcnic_dcb_mbx_params));
  472. memset(buf, 0, sizeof(struct qlcnic_dcb_mbx_params));
  473. err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM);
  474. if (err)
  475. return err;
  476. cmd.req.arg[0] |= QLC_DCB_FW_VER << 29;
  477. err = qlcnic_issue_cmd(adapter, &cmd);
  478. if (err) {
  479. dev_err(&adapter->pdev->dev,
  480. "Failed to query DCBX param, err %d\n", err);
  481. goto out;
  482. }
  483. mbx_out.prio_tc_map = cmd.rsp.arg[1];
  484. p = memcpy(buf, &mbx_out, sizeof(u32));
  485. k = 2;
  486. p += sizeof(u32);
  487. for (j = 0; j < QLC_DCB_NUM_PARAM; j++) {
  488. each = &mbx_out.type[j];
  489. each->hdr_prio_pfc_map[0] = cmd.rsp.arg[k++];
  490. each->hdr_prio_pfc_map[1] = cmd.rsp.arg[k++];
  491. each->prio_pg_map[0] = cmd.rsp.arg[k++];
  492. each->prio_pg_map[1] = cmd.rsp.arg[k++];
  493. each->pg_bw_map[0] = cmd.rsp.arg[k++];
  494. each->pg_bw_map[1] = cmd.rsp.arg[k++];
  495. each->pg_tsa_map[0] = cmd.rsp.arg[k++];
  496. each->pg_tsa_map[1] = cmd.rsp.arg[k++];
  497. val = each->hdr_prio_pfc_map[0];
  498. max_app = qlcnic_dcb_get_num_app(adapter, val);
  499. for (i = 0; i < max_app; i++)
  500. each->app[i] = cmd.rsp.arg[i + k];
  501. size = 16 * sizeof(u32);
  502. memcpy(p, &each->hdr_prio_pfc_map[0], size);
  503. p += size;
  504. if (j == 0)
  505. k = 18;
  506. else
  507. k = 34;
  508. }
  509. out:
  510. qlcnic_free_mbx_args(&cmd);
  511. return err;
  512. }
  513. static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb *dcb)
  514. {
  515. int err;
  516. err = qlcnic_dcb_query_cee_param(dcb, (char *)dcb->param, 0);
  517. if (err)
  518. return err;
  519. qlcnic_dcb_data_cee_param_map(dcb->adapter);
  520. return err;
  521. }
  522. static int qlcnic_83xx_dcb_register_aen(struct qlcnic_dcb *dcb, bool flag)
  523. {
  524. u8 val = (flag ? QLCNIC_CMD_INIT_NIC_FUNC : QLCNIC_CMD_STOP_NIC_FUNC);
  525. struct qlcnic_adapter *adapter = dcb->adapter;
  526. struct qlcnic_cmd_args cmd;
  527. int err;
  528. err = qlcnic_alloc_mbx_args(&cmd, adapter, val);
  529. if (err)
  530. return err;
  531. cmd.req.arg[1] = QLC_DCB_AEN_BIT;
  532. err = qlcnic_issue_cmd(adapter, &cmd);
  533. if (err)
  534. dev_err(&adapter->pdev->dev, "Failed to %s DCBX AEN, err %d\n",
  535. (flag ? "register" : "unregister"), err);
  536. qlcnic_free_mbx_args(&cmd);
  537. return err;
  538. }
  539. static void qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb *dcb, void *data)
  540. {
  541. u32 *val = data;
  542. if (test_and_set_bit(QLCNIC_DCB_AEN_MODE, &dcb->state))
  543. return;
  544. if (*val & BIT_8)
  545. set_bit(QLCNIC_DCB_STATE, &dcb->state);
  546. else
  547. clear_bit(QLCNIC_DCB_STATE, &dcb->state);
  548. queue_delayed_work(dcb->wq, &dcb->aen_work, 0);
  549. }
  550. static void qlcnic_dcb_fill_cee_tc_params(struct qlcnic_dcb_mbx_params *mbx,
  551. struct qlcnic_dcb_param *each,
  552. struct qlcnic_dcb_cee *type)
  553. {
  554. struct qlcnic_dcb_tc_cfg *tc_cfg;
  555. u8 i, tc, pgid;
  556. for (i = 0; i < QLC_DCB_MAX_PRIO; i++) {
  557. tc = QLC_DCB_GET_TC_PRIO(mbx->prio_tc_map, i);
  558. tc_cfg = &type->tc_cfg[tc];
  559. tc_cfg->valid = true;
  560. tc_cfg->up_tc_map |= QLC_DCB_GET_MAP(i);
  561. if (QLC_DCB_GET_PFC_PRIO(each->hdr_prio_pfc_map[1], i) &&
  562. type->pfc_mode_enable) {
  563. tc_cfg->prio_cfg[i].valid = true;
  564. tc_cfg->prio_cfg[i].pfc_type = QLC_PFC_FULL;
  565. }
  566. if (i < 4)
  567. pgid = QLC_DCB_GET_PGID_PRIO(each->prio_pg_map[0], i);
  568. else
  569. pgid = QLC_DCB_GET_PGID_PRIO(each->prio_pg_map[1], i);
  570. tc_cfg->pgid = pgid;
  571. tc_cfg->prio_type = QLC_PRIO_LINK;
  572. type->pg_cfg[tc_cfg->pgid].prio_count++;
  573. }
  574. }
  575. static void qlcnic_dcb_fill_cee_pg_params(struct qlcnic_dcb_param *each,
  576. struct qlcnic_dcb_cee *type)
  577. {
  578. struct qlcnic_dcb_pg_cfg *pg_cfg;
  579. u8 i, tsa, bw_per;
  580. for (i = 0; i < QLC_DCB_MAX_PG; i++) {
  581. pg_cfg = &type->pg_cfg[i];
  582. pg_cfg->valid = true;
  583. if (i < 4) {
  584. bw_per = QLC_DCB_GET_BWPER_PG(each->pg_bw_map[0], i);
  585. tsa = QLC_DCB_GET_TSA_PG(each->pg_tsa_map[0], i);
  586. } else {
  587. bw_per = QLC_DCB_GET_BWPER_PG(each->pg_bw_map[1], i);
  588. tsa = QLC_DCB_GET_TSA_PG(each->pg_tsa_map[1], i);
  589. }
  590. pg_cfg->total_bw_percent = bw_per;
  591. pg_cfg->tsa_type = tsa;
  592. }
  593. }
  594. static void
  595. qlcnic_dcb_fill_cee_app_params(struct qlcnic_adapter *adapter, u8 idx,
  596. struct qlcnic_dcb_param *each,
  597. struct qlcnic_dcb_cee *type)
  598. {
  599. struct qlcnic_dcb_app *app;
  600. u8 i, num_app, map, cnt;
  601. struct dcb_app new_app;
  602. num_app = qlcnic_dcb_get_num_app(adapter, each->hdr_prio_pfc_map[0]);
  603. for (i = 0; i < num_app; i++) {
  604. app = &type->app[i];
  605. app->valid = true;
  606. /* Only for CEE (-1) */
  607. app->selector = QLC_DCB_GET_SELECTOR_APP(each->app[i]) - 1;
  608. new_app.selector = app->selector;
  609. app->protocol = QLC_DCB_GET_PROTO_ID_APP(each->app[i]);
  610. new_app.protocol = app->protocol;
  611. map = qlcnic_dcb_get_prio_map_app(adapter, each->app[i]);
  612. cnt = qlcnic_dcb_prio_count(map);
  613. if (cnt >= QLC_DCB_MAX_TC)
  614. cnt = 0;
  615. app->priority = cnt;
  616. new_app.priority = cnt;
  617. if (idx == QLC_DCB_OPER_IDX && adapter->netdev->dcbnl_ops)
  618. dcb_setapp(adapter->netdev, &new_app);
  619. }
  620. }
  621. static void qlcnic_dcb_map_cee_params(struct qlcnic_adapter *adapter, u8 idx)
  622. {
  623. struct qlcnic_dcb_mbx_params *mbx = adapter->dcb->param;
  624. struct qlcnic_dcb_param *each = &mbx->type[idx];
  625. struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
  626. struct qlcnic_dcb_cee *type = &cfg->type[idx];
  627. type->tc_param_valid = false;
  628. type->pfc_mode_enable = false;
  629. memset(type->tc_cfg, 0,
  630. sizeof(struct qlcnic_dcb_tc_cfg) * QLC_DCB_MAX_TC);
  631. memset(type->pg_cfg, 0,
  632. sizeof(struct qlcnic_dcb_pg_cfg) * QLC_DCB_MAX_TC);
  633. if (qlcnic_dcb_pfc_hdr_valid(adapter, each->hdr_prio_pfc_map[0]) &&
  634. cfg->capability.max_pfc_tc)
  635. type->pfc_mode_enable = true;
  636. if (qlcnic_dcb_tsa_hdr_valid(adapter, each->hdr_prio_pfc_map[0]) &&
  637. cfg->capability.max_ets_tc)
  638. type->tc_param_valid = true;
  639. qlcnic_dcb_fill_cee_tc_params(mbx, each, type);
  640. qlcnic_dcb_fill_cee_pg_params(each, type);
  641. qlcnic_dcb_fill_cee_app_params(adapter, idx, each, type);
  642. }
  643. static void qlcnic_dcb_data_cee_param_map(struct qlcnic_adapter *adapter)
  644. {
  645. int i;
  646. for (i = 0; i < QLC_DCB_NUM_PARAM; i++)
  647. qlcnic_dcb_map_cee_params(adapter, i);
  648. dcbnl_cee_notify(adapter->netdev, RTM_GETDCB, DCB_CMD_CEE_GET, 0, 0);
  649. }
  650. static u8 qlcnic_dcb_get_state(struct net_device *netdev)
  651. {
  652. struct qlcnic_adapter *adapter = netdev_priv(netdev);
  653. return test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state);
  654. }
  655. static void qlcnic_dcb_get_perm_hw_addr(struct net_device *netdev, u8 *addr)
  656. {
  657. memcpy(addr, netdev->perm_addr, netdev->addr_len);
  658. }
  659. static void
  660. qlcnic_dcb_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, u8 *prio,
  661. u8 *pgid, u8 *bw_per, u8 *up_tc_map)
  662. {
  663. struct qlcnic_adapter *adapter = netdev_priv(netdev);
  664. struct qlcnic_dcb_tc_cfg *tc_cfg, *temp;
  665. struct qlcnic_dcb_cee *type;
  666. u8 i, cnt, pg;
  667. type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
  668. *prio = *pgid = *bw_per = *up_tc_map = 0;
  669. if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) ||
  670. !type->tc_param_valid)
  671. return;
  672. if (tc < 0 || (tc > QLC_DCB_MAX_TC))
  673. return;
  674. tc_cfg = &type->tc_cfg[tc];
  675. if (!tc_cfg->valid)
  676. return;
  677. *pgid = tc_cfg->pgid;
  678. *prio = tc_cfg->prio_type;
  679. *up_tc_map = tc_cfg->up_tc_map;
  680. pg = *pgid;
  681. for (i = 0, cnt = 0; i < QLC_DCB_MAX_TC; i++) {
  682. temp = &type->tc_cfg[i];
  683. if (temp->valid && (pg == temp->pgid))
  684. cnt++;
  685. }
  686. tc_cfg->bwg_percent = (100 / cnt);
  687. *bw_per = tc_cfg->bwg_percent;
  688. }
  689. static void qlcnic_dcb_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid,
  690. u8 *bw_pct)
  691. {
  692. struct qlcnic_adapter *adapter = netdev_priv(netdev);
  693. struct qlcnic_dcb_pg_cfg *pgcfg;
  694. struct qlcnic_dcb_cee *type;
  695. *bw_pct = 0;
  696. type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
  697. if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) ||
  698. !type->tc_param_valid)
  699. return;
  700. if (pgid < 0 || pgid > QLC_DCB_MAX_PG)
  701. return;
  702. pgcfg = &type->pg_cfg[pgid];
  703. if (!pgcfg->valid)
  704. return;
  705. *bw_pct = pgcfg->total_bw_percent;
  706. }
  707. static void qlcnic_dcb_get_pfc_cfg(struct net_device *netdev, int prio,
  708. u8 *setting)
  709. {
  710. struct qlcnic_adapter *adapter = netdev_priv(netdev);
  711. struct qlcnic_dcb_tc_cfg *tc_cfg;
  712. u8 val = QLC_DCB_GET_MAP(prio);
  713. struct qlcnic_dcb_cee *type;
  714. u8 i;
  715. *setting = 0;
  716. type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
  717. if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) ||
  718. !type->pfc_mode_enable)
  719. return;
  720. for (i = 0; i < QLC_DCB_MAX_TC; i++) {
  721. tc_cfg = &type->tc_cfg[i];
  722. if (!tc_cfg->valid)
  723. continue;
  724. if ((val & tc_cfg->up_tc_map) && (tc_cfg->prio_cfg[prio].valid))
  725. *setting = tc_cfg->prio_cfg[prio].pfc_type;
  726. }
  727. }
  728. static u8 qlcnic_dcb_get_capability(struct net_device *netdev, int capid,
  729. u8 *cap)
  730. {
  731. struct qlcnic_adapter *adapter = netdev_priv(netdev);
  732. if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
  733. return 0;
  734. switch (capid) {
  735. case DCB_CAP_ATTR_PG:
  736. case DCB_CAP_ATTR_UP2TC:
  737. case DCB_CAP_ATTR_PFC:
  738. case DCB_CAP_ATTR_GSP:
  739. *cap = true;
  740. break;
  741. case DCB_CAP_ATTR_PG_TCS:
  742. case DCB_CAP_ATTR_PFC_TCS:
  743. *cap = 0x80; /* 8 priorities for PGs */
  744. break;
  745. case DCB_CAP_ATTR_DCBX:
  746. *cap = adapter->dcb->cfg->capability.dcb_capability;
  747. break;
  748. default:
  749. *cap = false;
  750. }
  751. return 0;
  752. }
  753. static int qlcnic_dcb_get_num_tcs(struct net_device *netdev, int attr, u8 *num)
  754. {
  755. struct qlcnic_adapter *adapter = netdev_priv(netdev);
  756. struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
  757. if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
  758. return -EINVAL;
  759. switch (attr) {
  760. case DCB_NUMTCS_ATTR_PG:
  761. *num = cfg->capability.max_ets_tc;
  762. return 0;
  763. case DCB_NUMTCS_ATTR_PFC:
  764. *num = cfg->capability.max_pfc_tc;
  765. return 0;
  766. default:
  767. return -EINVAL;
  768. }
  769. }
  770. static u8 qlcnic_dcb_get_app(struct net_device *netdev, u8 idtype, u16 id)
  771. {
  772. struct qlcnic_adapter *adapter = netdev_priv(netdev);
  773. struct dcb_app app = {
  774. .selector = idtype,
  775. .protocol = id,
  776. };
  777. if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
  778. return 0;
  779. return dcb_getapp(netdev, &app);
  780. }
  781. static u8 qlcnic_dcb_get_pfc_state(struct net_device *netdev)
  782. {
  783. struct qlcnic_adapter *adapter = netdev_priv(netdev);
  784. struct qlcnic_dcb *dcb = adapter->dcb;
  785. if (!test_bit(QLCNIC_DCB_STATE, &dcb->state))
  786. return 0;
  787. return dcb->cfg->type[QLC_DCB_OPER_IDX].pfc_mode_enable;
  788. }
  789. static u8 qlcnic_dcb_get_dcbx(struct net_device *netdev)
  790. {
  791. struct qlcnic_adapter *adapter = netdev_priv(netdev);
  792. struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
  793. if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
  794. return 0;
  795. return cfg->capability.dcb_capability;
  796. }
  797. static u8 qlcnic_dcb_get_feat_cfg(struct net_device *netdev, int fid, u8 *flag)
  798. {
  799. struct qlcnic_adapter *adapter = netdev_priv(netdev);
  800. struct qlcnic_dcb_cee *type;
  801. if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
  802. return 1;
  803. type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
  804. *flag = 0;
  805. switch (fid) {
  806. case DCB_FEATCFG_ATTR_PG:
  807. if (type->tc_param_valid)
  808. *flag |= DCB_FEATCFG_ENABLE;
  809. else
  810. *flag |= DCB_FEATCFG_ERROR;
  811. break;
  812. case DCB_FEATCFG_ATTR_PFC:
  813. if (type->pfc_mode_enable) {
  814. if (type->tc_cfg[0].prio_cfg[0].pfc_type)
  815. *flag |= DCB_FEATCFG_ENABLE;
  816. } else {
  817. *flag |= DCB_FEATCFG_ERROR;
  818. }
  819. break;
  820. case DCB_FEATCFG_ATTR_APP:
  821. *flag |= DCB_FEATCFG_ENABLE;
  822. break;
  823. default:
  824. netdev_err(netdev, "Invalid Feature ID %d\n", fid);
  825. return 1;
  826. }
  827. return 0;
  828. }
  829. static inline void
  830. qlcnic_dcb_get_pg_tc_cfg_rx(struct net_device *netdev, int prio, u8 *prio_type,
  831. u8 *pgid, u8 *bw_pct, u8 *up_map)
  832. {
  833. *prio_type = *pgid = *bw_pct = *up_map = 0;
  834. }
  835. static inline void
  836. qlcnic_dcb_get_pg_bwg_cfg_rx(struct net_device *netdev, int pgid, u8 *bw_pct)
  837. {
  838. *bw_pct = 0;
  839. }
  840. static int qlcnic_dcb_peer_app_info(struct net_device *netdev,
  841. struct dcb_peer_app_info *info,
  842. u16 *app_count)
  843. {
  844. struct qlcnic_adapter *adapter = netdev_priv(netdev);
  845. struct qlcnic_dcb_cee *peer;
  846. int i;
  847. *app_count = 0;
  848. if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
  849. return 0;
  850. peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX];
  851. for (i = 0; i < QLC_DCB_MAX_APP; i++) {
  852. if (peer->app[i].valid)
  853. (*app_count)++;
  854. }
  855. return 0;
  856. }
  857. static int qlcnic_dcb_peer_app_table(struct net_device *netdev,
  858. struct dcb_app *table)
  859. {
  860. struct qlcnic_adapter *adapter = netdev_priv(netdev);
  861. struct qlcnic_dcb_cee *peer;
  862. struct qlcnic_dcb_app *app;
  863. int i, j;
  864. if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
  865. return 0;
  866. peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX];
  867. for (i = 0, j = 0; i < QLC_DCB_MAX_APP; i++) {
  868. app = &peer->app[i];
  869. if (!app->valid)
  870. continue;
  871. table[j].selector = app->selector;
  872. table[j].priority = app->priority;
  873. table[j++].protocol = app->protocol;
  874. }
  875. return 0;
  876. }
  877. static int qlcnic_dcb_cee_peer_get_pg(struct net_device *netdev,
  878. struct cee_pg *pg)
  879. {
  880. struct qlcnic_adapter *adapter = netdev_priv(netdev);
  881. struct qlcnic_dcb_cee *peer;
  882. u8 i, j, k, map;
  883. if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
  884. return 0;
  885. peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX];
  886. for (i = 0, j = 0; i < QLC_DCB_MAX_PG; i++) {
  887. if (!peer->pg_cfg[i].valid)
  888. continue;
  889. pg->pg_bw[j] = peer->pg_cfg[i].total_bw_percent;
  890. for (k = 0; k < QLC_DCB_MAX_TC; k++) {
  891. if (peer->tc_cfg[i].valid &&
  892. (peer->tc_cfg[i].pgid == i)) {
  893. map = peer->tc_cfg[i].up_tc_map;
  894. pg->prio_pg[j++] = map;
  895. break;
  896. }
  897. }
  898. }
  899. return 0;
  900. }
  901. static int qlcnic_dcb_cee_peer_get_pfc(struct net_device *netdev,
  902. struct cee_pfc *pfc)
  903. {
  904. struct qlcnic_adapter *adapter = netdev_priv(netdev);
  905. struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
  906. struct qlcnic_dcb_tc_cfg *tc;
  907. struct qlcnic_dcb_cee *peer;
  908. u8 i, setting, prio;
  909. pfc->pfc_en = 0;
  910. if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
  911. return 0;
  912. peer = &cfg->type[QLC_DCB_PEER_IDX];
  913. for (i = 0; i < QLC_DCB_MAX_TC; i++) {
  914. tc = &peer->tc_cfg[i];
  915. prio = qlcnic_dcb_prio_count(tc->up_tc_map);
  916. setting = 0;
  917. qlcnic_dcb_get_pfc_cfg(netdev, prio, &setting);
  918. if (setting)
  919. pfc->pfc_en |= QLC_DCB_GET_MAP(i);
  920. }
  921. pfc->tcs_supported = cfg->capability.max_pfc_tc;
  922. return 0;
  923. }
  924. static const struct dcbnl_rtnl_ops qlcnic_dcbnl_ops = {
  925. .getstate = qlcnic_dcb_get_state,
  926. .getpermhwaddr = qlcnic_dcb_get_perm_hw_addr,
  927. .getpgtccfgtx = qlcnic_dcb_get_pg_tc_cfg_tx,
  928. .getpgbwgcfgtx = qlcnic_dcb_get_pg_bwg_cfg_tx,
  929. .getpfccfg = qlcnic_dcb_get_pfc_cfg,
  930. .getcap = qlcnic_dcb_get_capability,
  931. .getnumtcs = qlcnic_dcb_get_num_tcs,
  932. .getapp = qlcnic_dcb_get_app,
  933. .getpfcstate = qlcnic_dcb_get_pfc_state,
  934. .getdcbx = qlcnic_dcb_get_dcbx,
  935. .getfeatcfg = qlcnic_dcb_get_feat_cfg,
  936. .getpgtccfgrx = qlcnic_dcb_get_pg_tc_cfg_rx,
  937. .getpgbwgcfgrx = qlcnic_dcb_get_pg_bwg_cfg_rx,
  938. .peer_getappinfo = qlcnic_dcb_peer_app_info,
  939. .peer_getapptable = qlcnic_dcb_peer_app_table,
  940. .cee_peer_getpg = qlcnic_dcb_cee_peer_get_pg,
  941. .cee_peer_getpfc = qlcnic_dcb_cee_peer_get_pfc,
  942. };