qlcnic_dcb.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  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_AEN_BIT 0x2
  11. #define QLC_DCB_FW_VER 0x2
  12. #define QLC_DCB_MAX_TC 0x8
  13. #define QLC_DCB_MAX_APP 0x8
  14. #define QLC_DCB_TSA_SUPPORT(V) (V & 0x1)
  15. #define QLC_DCB_ETS_SUPPORT(V) ((V >> 1) & 0x1)
  16. #define QLC_DCB_VERSION_SUPPORT(V) ((V >> 2) & 0xf)
  17. #define QLC_DCB_MAX_NUM_TC(V) ((V >> 20) & 0xf)
  18. #define QLC_DCB_MAX_NUM_ETS_TC(V) ((V >> 24) & 0xf)
  19. #define QLC_DCB_MAX_NUM_PFC_TC(V) ((V >> 28) & 0xf)
  20. #define QLC_DCB_GET_TC_PRIO(X, P) ((X >> (P * 3)) & 0x7)
  21. #define QLC_DCB_GET_PGID_PRIO(X, P) ((X >> (P * 8)) & 0xff)
  22. #define QLC_DCB_GET_BWPER_PG(X, P) ((X >> (P * 8)) & 0xff)
  23. #define QLC_DCB_GET_TSA_PG(X, P) ((X >> (P * 8)) & 0xff)
  24. #define QLC_DCB_GET_PFC_PRIO(X, P) (((X >> 24) >> P) & 0x1)
  25. #define QLC_DCB_GET_PROTO_ID_APP(X) ((X >> 8) & 0xffff)
  26. #define QLC_DCB_GET_SELECTOR_APP(X) (X & 0xff)
  27. #define QLC_DCB_LOCAL_PARAM_FWID 0x3
  28. #define QLC_DCB_OPER_PARAM_FWID 0x1
  29. #define QLC_DCB_PEER_PARAM_FWID 0x2
  30. #define QLC_83XX_DCB_GET_NUMAPP(X) ((X >> 2) & 0xf)
  31. #define QLC_83XX_DCB_TSA_VALID(X) (X & 0x1)
  32. #define QLC_83XX_DCB_PFC_VALID(X) ((X >> 1) & 0x1)
  33. #define QLC_83XX_DCB_GET_PRIOMAP_APP(X) (X >> 24)
  34. #define QLC_82XX_DCB_GET_NUMAPP(X) ((X >> 12) & 0xf)
  35. #define QLC_82XX_DCB_TSA_VALID(X) ((X >> 4) & 0x1)
  36. #define QLC_82XX_DCB_PFC_VALID(X) ((X >> 5) & 0x1)
  37. #define QLC_82XX_DCB_GET_PRIOVAL_APP(X) ((X >> 24) & 0x7)
  38. #define QLC_82XX_DCB_GET_PRIOMAP_APP(X) (1 << X)
  39. #define QLC_82XX_DCB_PRIO_TC_MAP (0x76543210)
  40. static void qlcnic_dcb_aen_work(struct work_struct *);
  41. static void __qlcnic_dcb_free(struct qlcnic_adapter *);
  42. static int __qlcnic_dcb_attach(struct qlcnic_adapter *);
  43. static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *, char *);
  44. static void __qlcnic_dcb_get_info(struct qlcnic_adapter *);
  45. static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *);
  46. static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_adapter *, char *, u8);
  47. static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *);
  48. static void qlcnic_82xx_dcb_handle_aen(struct qlcnic_adapter *, void *);
  49. static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *);
  50. static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_adapter *, char *, u8);
  51. static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_adapter *);
  52. static int qlcnic_83xx_dcb_register_aen(struct qlcnic_adapter *, bool);
  53. static void qlcnic_83xx_dcb_handle_aen(struct qlcnic_adapter *, void *);
  54. struct qlcnic_dcb_capability {
  55. bool tsa_capability;
  56. bool ets_capability;
  57. u8 max_num_tc;
  58. u8 max_ets_tc;
  59. u8 max_pfc_tc;
  60. u8 dcb_capability;
  61. };
  62. struct qlcnic_dcb_param {
  63. u32 hdr_prio_pfc_map[2];
  64. u32 prio_pg_map[2];
  65. u32 pg_bw_map[2];
  66. u32 pg_tsa_map[2];
  67. u32 app[QLC_DCB_MAX_APP];
  68. };
  69. struct qlcnic_dcb_mbx_params {
  70. /* 1st local, 2nd operational 3rd remote */
  71. struct qlcnic_dcb_param type[3];
  72. u32 prio_tc_map;
  73. };
  74. struct qlcnic_82xx_dcb_param_mbx_le {
  75. __le32 hdr_prio_pfc_map[2];
  76. __le32 prio_pg_map[2];
  77. __le32 pg_bw_map[2];
  78. __le32 pg_tsa_map[2];
  79. __le32 app[QLC_DCB_MAX_APP];
  80. };
  81. struct qlcnic_dcb_cfg {
  82. struct qlcnic_dcb_capability capability;
  83. u32 version;
  84. };
  85. static struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = {
  86. .free = __qlcnic_dcb_free,
  87. .attach = __qlcnic_dcb_attach,
  88. .query_hw_capability = __qlcnic_dcb_query_hw_capability,
  89. .get_info = __qlcnic_dcb_get_info,
  90. .get_hw_capability = qlcnic_83xx_dcb_get_hw_capability,
  91. .query_cee_param = qlcnic_83xx_dcb_query_cee_param,
  92. .get_cee_cfg = qlcnic_83xx_dcb_get_cee_cfg,
  93. .register_aen = qlcnic_83xx_dcb_register_aen,
  94. .handle_aen = qlcnic_83xx_dcb_handle_aen,
  95. };
  96. static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = {
  97. .free = __qlcnic_dcb_free,
  98. .attach = __qlcnic_dcb_attach,
  99. .query_hw_capability = __qlcnic_dcb_query_hw_capability,
  100. .get_info = __qlcnic_dcb_get_info,
  101. .get_hw_capability = qlcnic_82xx_dcb_get_hw_capability,
  102. .query_cee_param = qlcnic_82xx_dcb_query_cee_param,
  103. .get_cee_cfg = qlcnic_82xx_dcb_get_cee_cfg,
  104. .handle_aen = qlcnic_82xx_dcb_handle_aen,
  105. };
  106. static u8 qlcnic_dcb_get_num_app(struct qlcnic_adapter *adapter, u32 val)
  107. {
  108. if (qlcnic_82xx_check(adapter))
  109. return QLC_82XX_DCB_GET_NUMAPP(val);
  110. else
  111. return QLC_83XX_DCB_GET_NUMAPP(val);
  112. }
  113. void qlcnic_set_dcb_ops(struct qlcnic_adapter *adapter)
  114. {
  115. if (qlcnic_82xx_check(adapter))
  116. adapter->dcb->ops = &qlcnic_82xx_dcb_ops;
  117. else if (qlcnic_83xx_check(adapter))
  118. adapter->dcb->ops = &qlcnic_83xx_dcb_ops;
  119. }
  120. int __qlcnic_register_dcb(struct qlcnic_adapter *adapter)
  121. {
  122. struct qlcnic_dcb *dcb;
  123. dcb = kzalloc(sizeof(struct qlcnic_dcb), GFP_ATOMIC);
  124. if (!dcb)
  125. return -ENOMEM;
  126. adapter->dcb = dcb;
  127. dcb->adapter = adapter;
  128. qlcnic_set_dcb_ops(adapter);
  129. return 0;
  130. }
  131. static void __qlcnic_dcb_free(struct qlcnic_adapter *adapter)
  132. {
  133. struct qlcnic_dcb *dcb = adapter->dcb;
  134. if (!dcb)
  135. return;
  136. qlcnic_dcb_register_aen(adapter, 0);
  137. while (test_bit(__QLCNIC_DCB_IN_AEN, &adapter->state))
  138. usleep_range(10000, 11000);
  139. cancel_delayed_work_sync(&dcb->aen_work);
  140. if (dcb->wq) {
  141. destroy_workqueue(dcb->wq);
  142. dcb->wq = NULL;
  143. }
  144. kfree(dcb->cfg);
  145. dcb->cfg = NULL;
  146. kfree(dcb->param);
  147. dcb->param = NULL;
  148. kfree(dcb);
  149. adapter->dcb = NULL;
  150. }
  151. static void __qlcnic_dcb_get_info(struct qlcnic_adapter *adapter)
  152. {
  153. qlcnic_dcb_get_hw_capability(adapter);
  154. qlcnic_dcb_get_cee_cfg(adapter);
  155. qlcnic_dcb_register_aen(adapter, 1);
  156. }
  157. static int __qlcnic_dcb_attach(struct qlcnic_adapter *adapter)
  158. {
  159. struct qlcnic_dcb *dcb = adapter->dcb;
  160. int err = 0;
  161. INIT_DELAYED_WORK(&dcb->aen_work, qlcnic_dcb_aen_work);
  162. dcb->wq = create_singlethread_workqueue("qlcnic-dcb");
  163. if (!dcb->wq) {
  164. dev_err(&adapter->pdev->dev,
  165. "DCB workqueue allocation failed. DCB will be disabled\n");
  166. return -1;
  167. }
  168. dcb->cfg = kzalloc(sizeof(struct qlcnic_dcb_cfg), GFP_ATOMIC);
  169. if (!dcb->cfg) {
  170. err = -ENOMEM;
  171. goto out_free_wq;
  172. }
  173. dcb->param = kzalloc(sizeof(struct qlcnic_dcb_mbx_params), GFP_ATOMIC);
  174. if (!dcb->param) {
  175. err = -ENOMEM;
  176. goto out_free_cfg;
  177. }
  178. qlcnic_dcb_get_info(adapter);
  179. return 0;
  180. out_free_cfg:
  181. kfree(dcb->cfg);
  182. dcb->cfg = NULL;
  183. out_free_wq:
  184. destroy_workqueue(dcb->wq);
  185. dcb->wq = NULL;
  186. return err;
  187. }
  188. static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *adapter,
  189. char *buf)
  190. {
  191. struct qlcnic_cmd_args cmd;
  192. u32 mbx_out;
  193. int err;
  194. err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_CAP);
  195. if (err)
  196. return err;
  197. err = qlcnic_issue_cmd(adapter, &cmd);
  198. if (err) {
  199. dev_err(&adapter->pdev->dev,
  200. "Failed to query DCBX capability, err %d\n", err);
  201. } else {
  202. mbx_out = cmd.rsp.arg[1];
  203. if (buf)
  204. memcpy(buf, &mbx_out, sizeof(u32));
  205. }
  206. qlcnic_free_mbx_args(&cmd);
  207. return err;
  208. }
  209. static int __qlcnic_dcb_get_capability(struct qlcnic_adapter *adapter, u32 *val)
  210. {
  211. struct qlcnic_dcb_capability *cap = &adapter->dcb->cfg->capability;
  212. u32 mbx_out;
  213. int err;
  214. memset(cap, 0, sizeof(struct qlcnic_dcb_capability));
  215. err = qlcnic_dcb_query_hw_capability(adapter, (char *)val);
  216. if (err)
  217. return err;
  218. mbx_out = *val;
  219. if (QLC_DCB_TSA_SUPPORT(mbx_out))
  220. cap->tsa_capability = true;
  221. if (QLC_DCB_ETS_SUPPORT(mbx_out))
  222. cap->ets_capability = true;
  223. cap->max_num_tc = QLC_DCB_MAX_NUM_TC(mbx_out);
  224. cap->max_ets_tc = QLC_DCB_MAX_NUM_ETS_TC(mbx_out);
  225. cap->max_pfc_tc = QLC_DCB_MAX_NUM_PFC_TC(mbx_out);
  226. if (cap->max_num_tc > QLC_DCB_MAX_TC ||
  227. cap->max_ets_tc > cap->max_num_tc ||
  228. cap->max_pfc_tc > cap->max_num_tc) {
  229. dev_err(&adapter->pdev->dev, "Invalid DCB configuration\n");
  230. return -EINVAL;
  231. }
  232. return err;
  233. }
  234. static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter)
  235. {
  236. struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
  237. struct qlcnic_dcb_capability *cap;
  238. u32 mbx_out;
  239. int err;
  240. err = __qlcnic_dcb_get_capability(adapter, &mbx_out);
  241. if (err)
  242. return err;
  243. cap = &cfg->capability;
  244. cap->dcb_capability = DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_LLD_MANAGED;
  245. if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability)
  246. set_bit(__QLCNIC_DCB_STATE, &adapter->state);
  247. return err;
  248. }
  249. static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_adapter *adapter,
  250. char *buf, u8 type)
  251. {
  252. u16 size = sizeof(struct qlcnic_82xx_dcb_param_mbx_le);
  253. struct qlcnic_82xx_dcb_param_mbx_le *prsp_le;
  254. struct device *dev = &adapter->pdev->dev;
  255. dma_addr_t cardrsp_phys_addr;
  256. struct qlcnic_dcb_param rsp;
  257. struct qlcnic_cmd_args cmd;
  258. u64 phys_addr;
  259. void *addr;
  260. int err, i;
  261. switch (type) {
  262. case QLC_DCB_LOCAL_PARAM_FWID:
  263. case QLC_DCB_OPER_PARAM_FWID:
  264. case QLC_DCB_PEER_PARAM_FWID:
  265. break;
  266. default:
  267. dev_err(dev, "Invalid parameter type %d\n", type);
  268. return -EINVAL;
  269. }
  270. addr = dma_alloc_coherent(&adapter->pdev->dev, size, &cardrsp_phys_addr,
  271. GFP_KERNEL);
  272. if (addr == NULL)
  273. return -ENOMEM;
  274. prsp_le = addr;
  275. err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM);
  276. if (err)
  277. goto out_free_rsp;
  278. phys_addr = cardrsp_phys_addr;
  279. cmd.req.arg[1] = size | (type << 16);
  280. cmd.req.arg[2] = MSD(phys_addr);
  281. cmd.req.arg[3] = LSD(phys_addr);
  282. err = qlcnic_issue_cmd(adapter, &cmd);
  283. if (err) {
  284. dev_err(dev, "Failed to query DCBX parameter, err %d\n", err);
  285. goto out;
  286. }
  287. memset(&rsp, 0, sizeof(struct qlcnic_dcb_param));
  288. rsp.hdr_prio_pfc_map[0] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[0]);
  289. rsp.hdr_prio_pfc_map[1] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[1]);
  290. rsp.prio_pg_map[0] = le32_to_cpu(prsp_le->prio_pg_map[0]);
  291. rsp.prio_pg_map[1] = le32_to_cpu(prsp_le->prio_pg_map[1]);
  292. rsp.pg_bw_map[0] = le32_to_cpu(prsp_le->pg_bw_map[0]);
  293. rsp.pg_bw_map[1] = le32_to_cpu(prsp_le->pg_bw_map[1]);
  294. rsp.pg_tsa_map[0] = le32_to_cpu(prsp_le->pg_tsa_map[0]);
  295. rsp.pg_tsa_map[1] = le32_to_cpu(prsp_le->pg_tsa_map[1]);
  296. for (i = 0; i < QLC_DCB_MAX_APP; i++)
  297. rsp.app[i] = le32_to_cpu(prsp_le->app[i]);
  298. if (buf)
  299. memcpy(buf, &rsp, size);
  300. out:
  301. qlcnic_free_mbx_args(&cmd);
  302. out_free_rsp:
  303. dma_free_coherent(&adapter->pdev->dev, size, addr, cardrsp_phys_addr);
  304. return err;
  305. }
  306. static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter)
  307. {
  308. struct qlcnic_dcb_mbx_params *mbx;
  309. int err;
  310. mbx = adapter->dcb->param;
  311. if (!mbx)
  312. return 0;
  313. err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[0],
  314. QLC_DCB_LOCAL_PARAM_FWID);
  315. if (err)
  316. return err;
  317. err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[1],
  318. QLC_DCB_OPER_PARAM_FWID);
  319. if (err)
  320. return err;
  321. err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[2],
  322. QLC_DCB_PEER_PARAM_FWID);
  323. if (err)
  324. return err;
  325. mbx->prio_tc_map = QLC_82XX_DCB_PRIO_TC_MAP;
  326. return err;
  327. }
  328. static void qlcnic_dcb_aen_work(struct work_struct *work)
  329. {
  330. struct qlcnic_adapter *adapter;
  331. struct qlcnic_dcb *dcb;
  332. dcb = container_of(work, struct qlcnic_dcb, aen_work.work);
  333. adapter = dcb->adapter;
  334. qlcnic_dcb_get_cee_cfg(adapter);
  335. clear_bit(__QLCNIC_DCB_IN_AEN, &adapter->state);
  336. }
  337. static void qlcnic_82xx_dcb_handle_aen(struct qlcnic_adapter *adapter,
  338. void *data)
  339. {
  340. struct qlcnic_dcb *dcb = adapter->dcb;
  341. if (test_and_set_bit(__QLCNIC_DCB_IN_AEN, &adapter->state))
  342. return;
  343. queue_delayed_work(dcb->wq, &dcb->aen_work, 0);
  344. }
  345. static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter)
  346. {
  347. struct qlcnic_dcb_capability *cap = &adapter->dcb->cfg->capability;
  348. u32 mbx_out;
  349. int err;
  350. err = __qlcnic_dcb_get_capability(adapter, &mbx_out);
  351. if (err)
  352. return err;
  353. if (mbx_out & BIT_2)
  354. cap->dcb_capability = DCB_CAP_DCBX_VER_CEE;
  355. if (mbx_out & BIT_3)
  356. cap->dcb_capability |= DCB_CAP_DCBX_VER_IEEE;
  357. if (cap->dcb_capability)
  358. cap->dcb_capability |= DCB_CAP_DCBX_LLD_MANAGED;
  359. if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability)
  360. set_bit(__QLCNIC_DCB_STATE, &adapter->state);
  361. return err;
  362. }
  363. static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_adapter *adapter,
  364. char *buf, u8 idx)
  365. {
  366. struct qlcnic_dcb_mbx_params mbx_out;
  367. int err, i, j, k, max_app, size;
  368. struct qlcnic_dcb_param *each;
  369. struct qlcnic_cmd_args cmd;
  370. u32 val;
  371. char *p;
  372. size = 0;
  373. memset(&mbx_out, 0, sizeof(struct qlcnic_dcb_mbx_params));
  374. memset(buf, 0, sizeof(struct qlcnic_dcb_mbx_params));
  375. err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM);
  376. if (err)
  377. return err;
  378. cmd.req.arg[0] |= QLC_DCB_FW_VER << 29;
  379. err = qlcnic_issue_cmd(adapter, &cmd);
  380. if (err) {
  381. dev_err(&adapter->pdev->dev,
  382. "Failed to query DCBX param, err %d\n", err);
  383. goto out;
  384. }
  385. mbx_out.prio_tc_map = cmd.rsp.arg[1];
  386. p = memcpy(buf, &mbx_out, sizeof(u32));
  387. k = 2;
  388. p += sizeof(u32);
  389. for (j = 0; j < QLC_DCB_NUM_PARAM; j++) {
  390. each = &mbx_out.type[j];
  391. each->hdr_prio_pfc_map[0] = cmd.rsp.arg[k++];
  392. each->hdr_prio_pfc_map[1] = cmd.rsp.arg[k++];
  393. each->prio_pg_map[0] = cmd.rsp.arg[k++];
  394. each->prio_pg_map[1] = cmd.rsp.arg[k++];
  395. each->pg_bw_map[0] = cmd.rsp.arg[k++];
  396. each->pg_bw_map[1] = cmd.rsp.arg[k++];
  397. each->pg_tsa_map[0] = cmd.rsp.arg[k++];
  398. each->pg_tsa_map[1] = cmd.rsp.arg[k++];
  399. val = each->hdr_prio_pfc_map[0];
  400. max_app = qlcnic_dcb_get_num_app(adapter, val);
  401. for (i = 0; i < max_app; i++)
  402. each->app[i] = cmd.rsp.arg[i + k];
  403. size = 16 * sizeof(u32);
  404. memcpy(p, &each->hdr_prio_pfc_map[0], size);
  405. p += size;
  406. if (j == 0)
  407. k = 18;
  408. else
  409. k = 34;
  410. }
  411. out:
  412. qlcnic_free_mbx_args(&cmd);
  413. return err;
  414. }
  415. static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter)
  416. {
  417. struct qlcnic_dcb *dcb = adapter->dcb;
  418. return qlcnic_dcb_query_cee_param(adapter, (char *)dcb->param, 0);
  419. }
  420. static int qlcnic_83xx_dcb_register_aen(struct qlcnic_adapter *adapter,
  421. bool flag)
  422. {
  423. u8 val = (flag ? QLCNIC_CMD_INIT_NIC_FUNC : QLCNIC_CMD_STOP_NIC_FUNC);
  424. struct qlcnic_cmd_args cmd;
  425. int err;
  426. err = qlcnic_alloc_mbx_args(&cmd, adapter, val);
  427. if (err)
  428. return err;
  429. cmd.req.arg[1] = QLC_DCB_AEN_BIT;
  430. err = qlcnic_issue_cmd(adapter, &cmd);
  431. if (err)
  432. dev_err(&adapter->pdev->dev, "Failed to %s DCBX AEN, err %d\n",
  433. (flag ? "register" : "unregister"), err);
  434. qlcnic_free_mbx_args(&cmd);
  435. return err;
  436. }
  437. static void qlcnic_83xx_dcb_handle_aen(struct qlcnic_adapter *adapter,
  438. void *data)
  439. {
  440. struct qlcnic_dcb *dcb = adapter->dcb;
  441. u32 *val = data;
  442. if (test_and_set_bit(__QLCNIC_DCB_IN_AEN, &adapter->state))
  443. return;
  444. if (*val & BIT_8)
  445. set_bit(__QLCNIC_DCB_STATE, &adapter->state);
  446. else
  447. clear_bit(__QLCNIC_DCB_STATE, &adapter->state);
  448. queue_delayed_work(dcb->wq, &dcb->aen_work, 0);
  449. }