PageRenderTime 55ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/drivers/net/bnx2x/bnx2x_dcb.c

https://bitbucket.org/ndreys/linux-sunxi
C | 2244 lines | 1715 code | 314 blank | 215 comment | 285 complexity | bc38dcdc789678075fe6476f3b8bde4a MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1. /* bnx2x_dcb.c: Broadcom Everest network driver.
  2. *
  3. * Copyright 2009-2011 Broadcom Corporation
  4. *
  5. * Unless you and Broadcom execute a separate written software license
  6. * agreement governing use of this software, this software is licensed to you
  7. * under the terms of the GNU General Public License version 2, available
  8. * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
  9. *
  10. * Notwithstanding the above, under no circumstances may you combine this
  11. * software in any way with any other Broadcom software provided under a
  12. * license other than the GPL, without Broadcom's express prior written
  13. * consent.
  14. *
  15. * Maintained by: Eilon Greenstein <eilong@broadcom.com>
  16. * Written by: Dmitry Kravkov
  17. *
  18. */
  19. #include <linux/netdevice.h>
  20. #include <linux/types.h>
  21. #include <linux/errno.h>
  22. #ifdef BCM_DCBNL
  23. #include <linux/dcbnl.h>
  24. #endif
  25. #include "bnx2x.h"
  26. #include "bnx2x_cmn.h"
  27. #include "bnx2x_dcb.h"
  28. /* forward declarations of dcbx related functions */
  29. static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
  30. static void bnx2x_pfc_set_pfc(struct bnx2x *bp);
  31. static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp);
  32. static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
  33. static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
  34. u32 *set_configuration_ets_pg,
  35. u32 *pri_pg_tbl);
  36. static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp,
  37. u32 *pg_pri_orginal_spread,
  38. struct pg_help_data *help_data);
  39. static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
  40. struct pg_help_data *help_data,
  41. struct dcbx_ets_feature *ets,
  42. u32 *pg_pri_orginal_spread);
  43. static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
  44. struct cos_help_data *cos_data,
  45. u32 *pg_pri_orginal_spread,
  46. struct dcbx_ets_feature *ets);
  47. static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp);
  48. static void bnx2x_pfc_set(struct bnx2x *bp)
  49. {
  50. struct bnx2x_nig_brb_pfc_port_params pfc_params = {0};
  51. u32 pri_bit, val = 0;
  52. u8 pri;
  53. /* Tx COS configuration */
  54. if (bp->dcbx_port_params.ets.cos_params[0].pauseable)
  55. pfc_params.rx_cos0_priority_mask =
  56. bp->dcbx_port_params.ets.cos_params[0].pri_bitmask;
  57. if (bp->dcbx_port_params.ets.cos_params[1].pauseable)
  58. pfc_params.rx_cos1_priority_mask =
  59. bp->dcbx_port_params.ets.cos_params[1].pri_bitmask;
  60. /**
  61. * Rx COS configuration
  62. * Changing PFC RX configuration .
  63. * In RX COS0 will always be configured to lossy and COS1 to lossless
  64. */
  65. for (pri = 0 ; pri < MAX_PFC_PRIORITIES ; pri++) {
  66. pri_bit = 1 << pri;
  67. if (pri_bit & DCBX_PFC_PRI_PAUSE_MASK(bp))
  68. val |= 1 << (pri * 4);
  69. }
  70. pfc_params.pkt_priority_to_cos = val;
  71. /* RX COS0 */
  72. pfc_params.llfc_low_priority_classes = 0;
  73. /* RX COS1 */
  74. pfc_params.llfc_high_priority_classes = DCBX_PFC_PRI_PAUSE_MASK(bp);
  75. /* BRB configuration */
  76. pfc_params.cos0_pauseable = false;
  77. pfc_params.cos1_pauseable = true;
  78. bnx2x_acquire_phy_lock(bp);
  79. bp->link_params.feature_config_flags |= FEATURE_CONFIG_PFC_ENABLED;
  80. bnx2x_update_pfc(&bp->link_params, &bp->link_vars, &pfc_params);
  81. bnx2x_release_phy_lock(bp);
  82. }
  83. static void bnx2x_pfc_clear(struct bnx2x *bp)
  84. {
  85. struct bnx2x_nig_brb_pfc_port_params nig_params = {0};
  86. nig_params.pause_enable = 1;
  87. #ifdef BNX2X_SAFC
  88. if (bp->flags & SAFC_TX_FLAG) {
  89. u32 high = 0, low = 0;
  90. int i;
  91. for (i = 0; i < BNX2X_MAX_PRIORITY; i++) {
  92. if (bp->pri_map[i] == 1)
  93. high |= (1 << i);
  94. if (bp->pri_map[i] == 0)
  95. low |= (1 << i);
  96. }
  97. nig_params.llfc_low_priority_classes = high;
  98. nig_params.llfc_low_priority_classes = low;
  99. nig_params.pause_enable = 0;
  100. nig_params.llfc_enable = 1;
  101. nig_params.llfc_out_en = 1;
  102. }
  103. #endif /* BNX2X_SAFC */
  104. bnx2x_acquire_phy_lock(bp);
  105. bp->link_params.feature_config_flags &= ~FEATURE_CONFIG_PFC_ENABLED;
  106. bnx2x_update_pfc(&bp->link_params, &bp->link_vars, &nig_params);
  107. bnx2x_release_phy_lock(bp);
  108. }
  109. static void bnx2x_dump_dcbx_drv_param(struct bnx2x *bp,
  110. struct dcbx_features *features,
  111. u32 error)
  112. {
  113. u8 i = 0;
  114. DP(NETIF_MSG_LINK, "local_mib.error %x\n", error);
  115. /* PG */
  116. DP(NETIF_MSG_LINK,
  117. "local_mib.features.ets.enabled %x\n", features->ets.enabled);
  118. for (i = 0; i < DCBX_MAX_NUM_PG_BW_ENTRIES; i++)
  119. DP(NETIF_MSG_LINK,
  120. "local_mib.features.ets.pg_bw_tbl[%d] %d\n", i,
  121. DCBX_PG_BW_GET(features->ets.pg_bw_tbl, i));
  122. for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++)
  123. DP(NETIF_MSG_LINK,
  124. "local_mib.features.ets.pri_pg_tbl[%d] %d\n", i,
  125. DCBX_PRI_PG_GET(features->ets.pri_pg_tbl, i));
  126. /* pfc */
  127. DP(NETIF_MSG_LINK, "dcbx_features.pfc.pri_en_bitmap %x\n",
  128. features->pfc.pri_en_bitmap);
  129. DP(NETIF_MSG_LINK, "dcbx_features.pfc.pfc_caps %x\n",
  130. features->pfc.pfc_caps);
  131. DP(NETIF_MSG_LINK, "dcbx_features.pfc.enabled %x\n",
  132. features->pfc.enabled);
  133. DP(NETIF_MSG_LINK, "dcbx_features.app.default_pri %x\n",
  134. features->app.default_pri);
  135. DP(NETIF_MSG_LINK, "dcbx_features.app.tc_supported %x\n",
  136. features->app.tc_supported);
  137. DP(NETIF_MSG_LINK, "dcbx_features.app.enabled %x\n",
  138. features->app.enabled);
  139. for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++) {
  140. DP(NETIF_MSG_LINK,
  141. "dcbx_features.app.app_pri_tbl[%x].app_id %x\n",
  142. i, features->app.app_pri_tbl[i].app_id);
  143. DP(NETIF_MSG_LINK,
  144. "dcbx_features.app.app_pri_tbl[%x].pri_bitmap %x\n",
  145. i, features->app.app_pri_tbl[i].pri_bitmap);
  146. DP(NETIF_MSG_LINK,
  147. "dcbx_features.app.app_pri_tbl[%x].appBitfield %x\n",
  148. i, features->app.app_pri_tbl[i].appBitfield);
  149. }
  150. }
  151. static void bnx2x_dcbx_get_ap_priority(struct bnx2x *bp,
  152. u8 pri_bitmap,
  153. u8 llfc_traf_type)
  154. {
  155. u32 pri = MAX_PFC_PRIORITIES;
  156. u32 index = MAX_PFC_PRIORITIES - 1;
  157. u32 pri_mask;
  158. u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
  159. /* Choose the highest priority */
  160. while ((MAX_PFC_PRIORITIES == pri) && (0 != index)) {
  161. pri_mask = 1 << index;
  162. if (GET_FLAGS(pri_bitmap, pri_mask))
  163. pri = index ;
  164. index--;
  165. }
  166. if (pri < MAX_PFC_PRIORITIES)
  167. ttp[llfc_traf_type] = max_t(u32, ttp[llfc_traf_type], pri);
  168. }
  169. static void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp,
  170. struct dcbx_app_priority_feature *app,
  171. u32 error) {
  172. u8 index;
  173. u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
  174. if (GET_FLAGS(error, DCBX_LOCAL_APP_ERROR))
  175. DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_ERROR\n");
  176. if (app->enabled && !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR)) {
  177. bp->dcbx_port_params.app.enabled = true;
  178. for (index = 0 ; index < LLFC_DRIVER_TRAFFIC_TYPE_MAX; index++)
  179. ttp[index] = 0;
  180. if (app->default_pri < MAX_PFC_PRIORITIES)
  181. ttp[LLFC_TRAFFIC_TYPE_NW] = app->default_pri;
  182. for (index = 0 ; index < DCBX_MAX_APP_PROTOCOL; index++) {
  183. struct dcbx_app_priority_entry *entry =
  184. app->app_pri_tbl;
  185. if (GET_FLAGS(entry[index].appBitfield,
  186. DCBX_APP_SF_ETH_TYPE) &&
  187. ETH_TYPE_FCOE == entry[index].app_id)
  188. bnx2x_dcbx_get_ap_priority(bp,
  189. entry[index].pri_bitmap,
  190. LLFC_TRAFFIC_TYPE_FCOE);
  191. if (GET_FLAGS(entry[index].appBitfield,
  192. DCBX_APP_SF_PORT) &&
  193. TCP_PORT_ISCSI == entry[index].app_id)
  194. bnx2x_dcbx_get_ap_priority(bp,
  195. entry[index].pri_bitmap,
  196. LLFC_TRAFFIC_TYPE_ISCSI);
  197. }
  198. } else {
  199. DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_DISABLED\n");
  200. bp->dcbx_port_params.app.enabled = false;
  201. for (index = 0 ; index < LLFC_DRIVER_TRAFFIC_TYPE_MAX; index++)
  202. ttp[index] = INVALID_TRAFFIC_TYPE_PRIORITY;
  203. }
  204. }
  205. static void bnx2x_dcbx_get_ets_feature(struct bnx2x *bp,
  206. struct dcbx_ets_feature *ets,
  207. u32 error) {
  208. int i = 0;
  209. u32 pg_pri_orginal_spread[DCBX_MAX_NUM_PG_BW_ENTRIES] = {0};
  210. struct pg_help_data pg_help_data;
  211. struct bnx2x_dcbx_cos_params *cos_params =
  212. bp->dcbx_port_params.ets.cos_params;
  213. memset(&pg_help_data, 0, sizeof(struct pg_help_data));
  214. if (GET_FLAGS(error, DCBX_LOCAL_ETS_ERROR))
  215. DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_ERROR\n");
  216. /* Clean up old settings of ets on COS */
  217. for (i = 0; i < E2_NUM_OF_COS ; i++) {
  218. cos_params[i].pauseable = false;
  219. cos_params[i].strict = BNX2X_DCBX_COS_NOT_STRICT;
  220. cos_params[i].bw_tbl = DCBX_INVALID_COS_BW;
  221. cos_params[i].pri_bitmask = DCBX_PFC_PRI_GET_NON_PAUSE(bp, 0);
  222. }
  223. if (bp->dcbx_port_params.app.enabled &&
  224. !GET_FLAGS(error, DCBX_LOCAL_ETS_ERROR) &&
  225. ets->enabled) {
  226. DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_ENABLE\n");
  227. bp->dcbx_port_params.ets.enabled = true;
  228. bnx2x_dcbx_get_ets_pri_pg_tbl(bp,
  229. pg_pri_orginal_spread,
  230. ets->pri_pg_tbl);
  231. bnx2x_dcbx_get_num_pg_traf_type(bp,
  232. pg_pri_orginal_spread,
  233. &pg_help_data);
  234. bnx2x_dcbx_fill_cos_params(bp, &pg_help_data,
  235. ets, pg_pri_orginal_spread);
  236. } else {
  237. DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_DISABLED\n");
  238. bp->dcbx_port_params.ets.enabled = false;
  239. ets->pri_pg_tbl[0] = 0;
  240. for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES ; i++)
  241. DCBX_PG_BW_SET(ets->pg_bw_tbl, i, 1);
  242. }
  243. }
  244. static void bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp,
  245. struct dcbx_pfc_feature *pfc, u32 error)
  246. {
  247. if (GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR))
  248. DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_ERROR\n");
  249. if (bp->dcbx_port_params.app.enabled &&
  250. !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR) &&
  251. pfc->enabled) {
  252. bp->dcbx_port_params.pfc.enabled = true;
  253. bp->dcbx_port_params.pfc.priority_non_pauseable_mask =
  254. ~(pfc->pri_en_bitmap);
  255. } else {
  256. DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_DISABLED\n");
  257. bp->dcbx_port_params.pfc.enabled = false;
  258. bp->dcbx_port_params.pfc.priority_non_pauseable_mask = 0;
  259. }
  260. }
  261. static void bnx2x_get_dcbx_drv_param(struct bnx2x *bp,
  262. struct dcbx_features *features,
  263. u32 error)
  264. {
  265. bnx2x_dcbx_get_ap_feature(bp, &features->app, error);
  266. bnx2x_dcbx_get_pfc_feature(bp, &features->pfc, error);
  267. bnx2x_dcbx_get_ets_feature(bp, &features->ets, error);
  268. }
  269. #define DCBX_LOCAL_MIB_MAX_TRY_READ (100)
  270. static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
  271. u32 *base_mib_addr,
  272. u32 offset,
  273. int read_mib_type)
  274. {
  275. int max_try_read = 0, i;
  276. u32 *buff, mib_size, prefix_seq_num, suffix_seq_num;
  277. struct lldp_remote_mib *remote_mib ;
  278. struct lldp_local_mib *local_mib;
  279. switch (read_mib_type) {
  280. case DCBX_READ_LOCAL_MIB:
  281. mib_size = sizeof(struct lldp_local_mib);
  282. break;
  283. case DCBX_READ_REMOTE_MIB:
  284. mib_size = sizeof(struct lldp_remote_mib);
  285. break;
  286. default:
  287. return 1; /*error*/
  288. }
  289. offset += BP_PORT(bp) * mib_size;
  290. do {
  291. buff = base_mib_addr;
  292. for (i = 0; i < mib_size; i += 4, buff++)
  293. *buff = REG_RD(bp, offset + i);
  294. max_try_read++;
  295. switch (read_mib_type) {
  296. case DCBX_READ_LOCAL_MIB:
  297. local_mib = (struct lldp_local_mib *) base_mib_addr;
  298. prefix_seq_num = local_mib->prefix_seq_num;
  299. suffix_seq_num = local_mib->suffix_seq_num;
  300. break;
  301. case DCBX_READ_REMOTE_MIB:
  302. remote_mib = (struct lldp_remote_mib *) base_mib_addr;
  303. prefix_seq_num = remote_mib->prefix_seq_num;
  304. suffix_seq_num = remote_mib->suffix_seq_num;
  305. break;
  306. default:
  307. return 1; /*error*/
  308. }
  309. } while ((prefix_seq_num != suffix_seq_num) &&
  310. (max_try_read < DCBX_LOCAL_MIB_MAX_TRY_READ));
  311. if (max_try_read >= DCBX_LOCAL_MIB_MAX_TRY_READ) {
  312. BNX2X_ERR("MIB could not be read\n");
  313. return 1;
  314. }
  315. return 0;
  316. }
  317. static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
  318. {
  319. if (CHIP_IS_E2(bp)) {
  320. if (BP_PORT(bp)) {
  321. BNX2X_ERR("4 port mode is not supported");
  322. return;
  323. }
  324. if (bp->dcbx_port_params.pfc.enabled)
  325. /* 1. Fills up common PFC structures if required.*/
  326. /* 2. Configure NIG, MAC and BRB via the elink:
  327. * elink must first check if BMAC is not in reset
  328. * and only then configures the BMAC
  329. * Or, configure EMAC.
  330. */
  331. bnx2x_pfc_set(bp);
  332. else
  333. bnx2x_pfc_clear(bp);
  334. }
  335. }
  336. static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
  337. {
  338. DP(NETIF_MSG_LINK, "sending STOP TRAFFIC\n");
  339. bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
  340. 0 /* connectionless */,
  341. 0 /* dataHi is zero */,
  342. 0 /* dataLo is zero */,
  343. 1 /* common */);
  344. }
  345. static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
  346. {
  347. bnx2x_pfc_fw_struct_e2(bp);
  348. DP(NETIF_MSG_LINK, "sending START TRAFFIC\n");
  349. bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC,
  350. 0, /* connectionless */
  351. U64_HI(bnx2x_sp_mapping(bp, pfc_config)),
  352. U64_LO(bnx2x_sp_mapping(bp, pfc_config)),
  353. 1 /* commmon */);
  354. }
  355. static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
  356. {
  357. struct bnx2x_dcbx_pg_params *ets = &(bp->dcbx_port_params.ets);
  358. u8 status = 0;
  359. bnx2x_ets_disabled(&bp->link_params);
  360. if (!ets->enabled)
  361. return;
  362. if ((ets->num_of_cos == 0) || (ets->num_of_cos > E2_NUM_OF_COS)) {
  363. BNX2X_ERR("illegal num of cos= %x", ets->num_of_cos);
  364. return;
  365. }
  366. /* valid COS entries */
  367. if (ets->num_of_cos == 1) /* no ETS */
  368. return;
  369. /* sanity */
  370. if (((BNX2X_DCBX_COS_NOT_STRICT == ets->cos_params[0].strict) &&
  371. (DCBX_INVALID_COS_BW == ets->cos_params[0].bw_tbl)) ||
  372. ((BNX2X_DCBX_COS_NOT_STRICT == ets->cos_params[1].strict) &&
  373. (DCBX_INVALID_COS_BW == ets->cos_params[1].bw_tbl))) {
  374. BNX2X_ERR("all COS should have at least bw_limit or strict"
  375. "ets->cos_params[0].strict= %x"
  376. "ets->cos_params[0].bw_tbl= %x"
  377. "ets->cos_params[1].strict= %x"
  378. "ets->cos_params[1].bw_tbl= %x",
  379. ets->cos_params[0].strict,
  380. ets->cos_params[0].bw_tbl,
  381. ets->cos_params[1].strict,
  382. ets->cos_params[1].bw_tbl);
  383. return;
  384. }
  385. /* If we join a group and there is bw_tbl and strict then bw rules */
  386. if ((DCBX_INVALID_COS_BW != ets->cos_params[0].bw_tbl) &&
  387. (DCBX_INVALID_COS_BW != ets->cos_params[1].bw_tbl)) {
  388. u32 bw_tbl_0 = ets->cos_params[0].bw_tbl;
  389. u32 bw_tbl_1 = ets->cos_params[1].bw_tbl;
  390. /* Do not allow 0-100 configuration
  391. * since PBF does not support it
  392. * force 1-99 instead
  393. */
  394. if (bw_tbl_0 == 0) {
  395. bw_tbl_0 = 1;
  396. bw_tbl_1 = 99;
  397. } else if (bw_tbl_1 == 0) {
  398. bw_tbl_1 = 1;
  399. bw_tbl_0 = 99;
  400. }
  401. bnx2x_ets_bw_limit(&bp->link_params, bw_tbl_0, bw_tbl_1);
  402. } else {
  403. if (ets->cos_params[0].strict == BNX2X_DCBX_COS_HIGH_STRICT)
  404. status = bnx2x_ets_strict(&bp->link_params, 0);
  405. else if (ets->cos_params[1].strict
  406. == BNX2X_DCBX_COS_HIGH_STRICT)
  407. status = bnx2x_ets_strict(&bp->link_params, 1);
  408. if (status)
  409. BNX2X_ERR("update_ets_params failed\n");
  410. }
  411. }
  412. #ifdef BCM_DCBNL
  413. static int bnx2x_dcbx_read_shmem_remote_mib(struct bnx2x *bp)
  414. {
  415. struct lldp_remote_mib remote_mib = {0};
  416. u32 dcbx_remote_mib_offset = SHMEM2_RD(bp, dcbx_remote_mib_offset);
  417. int rc;
  418. DP(NETIF_MSG_LINK, "dcbx_remote_mib_offset 0x%x\n",
  419. dcbx_remote_mib_offset);
  420. if (SHMEM_DCBX_REMOTE_MIB_NONE == dcbx_remote_mib_offset) {
  421. BNX2X_ERR("FW doesn't support dcbx_remote_mib_offset\n");
  422. return -EINVAL;
  423. }
  424. rc = bnx2x_dcbx_read_mib(bp, (u32 *)&remote_mib, dcbx_remote_mib_offset,
  425. DCBX_READ_REMOTE_MIB);
  426. if (rc) {
  427. BNX2X_ERR("Faild to read remote mib from FW\n");
  428. return rc;
  429. }
  430. /* save features and flags */
  431. bp->dcbx_remote_feat = remote_mib.features;
  432. bp->dcbx_remote_flags = remote_mib.flags;
  433. return 0;
  434. }
  435. #endif
  436. static int bnx2x_dcbx_read_shmem_neg_results(struct bnx2x *bp)
  437. {
  438. struct lldp_local_mib local_mib = {0};
  439. u32 dcbx_neg_res_offset = SHMEM2_RD(bp, dcbx_neg_res_offset);
  440. int rc;
  441. DP(NETIF_MSG_LINK, "dcbx_neg_res_offset 0x%x\n", dcbx_neg_res_offset);
  442. if (SHMEM_DCBX_NEG_RES_NONE == dcbx_neg_res_offset) {
  443. BNX2X_ERR("FW doesn't support dcbx_neg_res_offset\n");
  444. return -EINVAL;
  445. }
  446. rc = bnx2x_dcbx_read_mib(bp, (u32 *)&local_mib, dcbx_neg_res_offset,
  447. DCBX_READ_LOCAL_MIB);
  448. if (rc) {
  449. BNX2X_ERR("Faild to read local mib from FW\n");
  450. return rc;
  451. }
  452. /* save features and error */
  453. bp->dcbx_local_feat = local_mib.features;
  454. bp->dcbx_error = local_mib.error;
  455. return 0;
  456. }
  457. #ifdef BCM_DCBNL
  458. static inline
  459. u8 bnx2x_dcbx_dcbnl_app_up(struct dcbx_app_priority_entry *ent)
  460. {
  461. u8 pri;
  462. /* Choose the highest priority */
  463. for (pri = MAX_PFC_PRIORITIES - 1; pri > 0; pri--)
  464. if (ent->pri_bitmap & (1 << pri))
  465. break;
  466. return pri;
  467. }
  468. static inline
  469. u8 bnx2x_dcbx_dcbnl_app_idtype(struct dcbx_app_priority_entry *ent)
  470. {
  471. return ((ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) ==
  472. DCBX_APP_SF_PORT) ? DCB_APP_IDTYPE_PORTNUM :
  473. DCB_APP_IDTYPE_ETHTYPE;
  474. }
  475. static inline
  476. void bnx2x_dcbx_invalidate_local_apps(struct bnx2x *bp)
  477. {
  478. int i;
  479. for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
  480. bp->dcbx_local_feat.app.app_pri_tbl[i].appBitfield &=
  481. ~DCBX_APP_ENTRY_VALID;
  482. }
  483. int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall)
  484. {
  485. int i, err = 0;
  486. for (i = 0; i < DCBX_MAX_APP_PROTOCOL && err == 0; i++) {
  487. struct dcbx_app_priority_entry *ent =
  488. &bp->dcbx_local_feat.app.app_pri_tbl[i];
  489. if (ent->appBitfield & DCBX_APP_ENTRY_VALID) {
  490. u8 up = bnx2x_dcbx_dcbnl_app_up(ent);
  491. /* avoid invalid user-priority */
  492. if (up) {
  493. struct dcb_app app;
  494. app.selector = bnx2x_dcbx_dcbnl_app_idtype(ent);
  495. app.protocol = ent->app_id;
  496. app.priority = delall ? 0 : up;
  497. err = dcb_setapp(bp->dev, &app);
  498. }
  499. }
  500. }
  501. return err;
  502. }
  503. #endif
  504. void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
  505. {
  506. switch (state) {
  507. case BNX2X_DCBX_STATE_NEG_RECEIVED:
  508. #ifdef BCM_CNIC
  509. if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
  510. struct cnic_ops *c_ops;
  511. struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
  512. bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
  513. cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI_OOO;
  514. cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI;
  515. rcu_read_lock();
  516. c_ops = rcu_dereference(bp->cnic_ops);
  517. if (c_ops) {
  518. bnx2x_cnic_notify(bp, CNIC_CTL_STOP_ISCSI_CMD);
  519. rcu_read_unlock();
  520. return;
  521. }
  522. rcu_read_unlock();
  523. }
  524. /* fall through if no CNIC initialized */
  525. case BNX2X_DCBX_STATE_ISCSI_STOPPED:
  526. #endif
  527. {
  528. DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_NEG_RECEIVED\n");
  529. #ifdef BCM_DCBNL
  530. /**
  531. * Delete app tlvs from dcbnl before reading new
  532. * negotiation results
  533. */
  534. bnx2x_dcbnl_update_applist(bp, true);
  535. /* Read rmeote mib if dcbx is in the FW */
  536. if (bnx2x_dcbx_read_shmem_remote_mib(bp))
  537. return;
  538. #endif
  539. /* Read neg results if dcbx is in the FW */
  540. if (bnx2x_dcbx_read_shmem_neg_results(bp))
  541. return;
  542. bnx2x_dump_dcbx_drv_param(bp, &bp->dcbx_local_feat,
  543. bp->dcbx_error);
  544. bnx2x_get_dcbx_drv_param(bp, &bp->dcbx_local_feat,
  545. bp->dcbx_error);
  546. if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
  547. #ifdef BCM_DCBNL
  548. /**
  549. * Add new app tlvs to dcbnl
  550. */
  551. bnx2x_dcbnl_update_applist(bp, false);
  552. #endif
  553. bnx2x_dcbx_stop_hw_tx(bp);
  554. return;
  555. }
  556. /* fall through */
  557. #ifdef BCM_DCBNL
  558. /**
  559. * Invalidate the local app tlvs if they are not added
  560. * to the dcbnl app list to avoid deleting them from
  561. * the list later on
  562. */
  563. bnx2x_dcbx_invalidate_local_apps(bp);
  564. #endif
  565. }
  566. case BNX2X_DCBX_STATE_TX_PAUSED:
  567. DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_PAUSED\n");
  568. bnx2x_pfc_set_pfc(bp);
  569. bnx2x_dcbx_update_ets_params(bp);
  570. if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
  571. bnx2x_dcbx_resume_hw_tx(bp);
  572. return;
  573. }
  574. /* fall through */
  575. case BNX2X_DCBX_STATE_TX_RELEASED:
  576. DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_RELEASED\n");
  577. if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD)
  578. bnx2x_fw_command(bp, DRV_MSG_CODE_DCBX_PMF_DRV_OK, 0);
  579. return;
  580. default:
  581. BNX2X_ERR("Unknown DCBX_STATE\n");
  582. }
  583. }
  584. #define LLDP_STATS_OFFSET(bp) (BP_PORT(bp)*\
  585. sizeof(struct lldp_dcbx_stat))
  586. /* calculate struct offset in array according to chip information */
  587. #define LLDP_PARAMS_OFFSET(bp) (BP_PORT(bp)*sizeof(struct lldp_params))
  588. #define LLDP_ADMIN_MIB_OFFSET(bp) (PORT_MAX*sizeof(struct lldp_params) + \
  589. BP_PORT(bp)*sizeof(struct lldp_admin_mib))
  590. static void bnx2x_dcbx_lldp_updated_params(struct bnx2x *bp,
  591. u32 dcbx_lldp_params_offset)
  592. {
  593. struct lldp_params lldp_params = {0};
  594. u32 i = 0, *buff = NULL;
  595. u32 offset = dcbx_lldp_params_offset + LLDP_PARAMS_OFFSET(bp);
  596. DP(NETIF_MSG_LINK, "lldp_offset 0x%x\n", offset);
  597. if ((bp->lldp_config_params.overwrite_settings ==
  598. BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE)) {
  599. /* Read the data first */
  600. buff = (u32 *)&lldp_params;
  601. for (i = 0; i < sizeof(struct lldp_params); i += 4, buff++)
  602. *buff = REG_RD(bp, (offset + i));
  603. lldp_params.msg_tx_hold =
  604. (u8)bp->lldp_config_params.msg_tx_hold;
  605. lldp_params.msg_fast_tx_interval =
  606. (u8)bp->lldp_config_params.msg_fast_tx;
  607. lldp_params.tx_crd_max =
  608. (u8)bp->lldp_config_params.tx_credit_max;
  609. lldp_params.msg_tx_interval =
  610. (u8)bp->lldp_config_params.msg_tx_interval;
  611. lldp_params.tx_fast =
  612. (u8)bp->lldp_config_params.tx_fast;
  613. /* Write the data.*/
  614. buff = (u32 *)&lldp_params;
  615. for (i = 0; i < sizeof(struct lldp_params); i += 4, buff++)
  616. REG_WR(bp, (offset + i) , *buff);
  617. } else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
  618. bp->lldp_config_params.overwrite_settings)
  619. bp->lldp_config_params.overwrite_settings =
  620. BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
  621. }
  622. static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
  623. u32 dcbx_lldp_params_offset)
  624. {
  625. struct lldp_admin_mib admin_mib;
  626. u32 i, other_traf_type = PREDEFINED_APP_IDX_MAX, traf_type = 0;
  627. u32 *buff;
  628. u32 offset = dcbx_lldp_params_offset + LLDP_ADMIN_MIB_OFFSET(bp);
  629. /*shortcuts*/
  630. struct dcbx_features *af = &admin_mib.features;
  631. struct bnx2x_config_dcbx_params *dp = &bp->dcbx_config_params;
  632. memset(&admin_mib, 0, sizeof(struct lldp_admin_mib));
  633. buff = (u32 *)&admin_mib;
  634. /* Read the data first */
  635. for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
  636. *buff = REG_RD(bp, (offset + i));
  637. if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON)
  638. SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
  639. else
  640. RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
  641. if ((BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
  642. dp->overwrite_settings)) {
  643. RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_CEE_VERSION_MASK);
  644. admin_mib.ver_cfg_flags |=
  645. (dp->admin_dcbx_version << DCBX_CEE_VERSION_SHIFT) &
  646. DCBX_CEE_VERSION_MASK;
  647. af->ets.enabled = (u8)dp->admin_ets_enable;
  648. af->pfc.enabled = (u8)dp->admin_pfc_enable;
  649. /* FOR IEEE dp->admin_tc_supported_tx_enable */
  650. if (dp->admin_ets_configuration_tx_enable)
  651. SET_FLAGS(admin_mib.ver_cfg_flags,
  652. DCBX_ETS_CONFIG_TX_ENABLED);
  653. else
  654. RESET_FLAGS(admin_mib.ver_cfg_flags,
  655. DCBX_ETS_CONFIG_TX_ENABLED);
  656. /* For IEEE admin_ets_recommendation_tx_enable */
  657. if (dp->admin_pfc_tx_enable)
  658. SET_FLAGS(admin_mib.ver_cfg_flags,
  659. DCBX_PFC_CONFIG_TX_ENABLED);
  660. else
  661. RESET_FLAGS(admin_mib.ver_cfg_flags,
  662. DCBX_PFC_CONFIG_TX_ENABLED);
  663. if (dp->admin_application_priority_tx_enable)
  664. SET_FLAGS(admin_mib.ver_cfg_flags,
  665. DCBX_APP_CONFIG_TX_ENABLED);
  666. else
  667. RESET_FLAGS(admin_mib.ver_cfg_flags,
  668. DCBX_APP_CONFIG_TX_ENABLED);
  669. if (dp->admin_ets_willing)
  670. SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_ETS_WILLING);
  671. else
  672. RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_ETS_WILLING);
  673. /* For IEEE admin_ets_reco_valid */
  674. if (dp->admin_pfc_willing)
  675. SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_PFC_WILLING);
  676. else
  677. RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_PFC_WILLING);
  678. if (dp->admin_app_priority_willing)
  679. SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_APP_WILLING);
  680. else
  681. RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_APP_WILLING);
  682. for (i = 0 ; i < DCBX_MAX_NUM_PG_BW_ENTRIES; i++) {
  683. DCBX_PG_BW_SET(af->ets.pg_bw_tbl, i,
  684. (u8)dp->admin_configuration_bw_precentage[i]);
  685. DP(NETIF_MSG_LINK, "pg_bw_tbl[%d] = %02x\n",
  686. i, DCBX_PG_BW_GET(af->ets.pg_bw_tbl, i));
  687. }
  688. for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++) {
  689. DCBX_PRI_PG_SET(af->ets.pri_pg_tbl, i,
  690. (u8)dp->admin_configuration_ets_pg[i]);
  691. DP(NETIF_MSG_LINK, "pri_pg_tbl[%d] = %02x\n",
  692. i, DCBX_PRI_PG_GET(af->ets.pri_pg_tbl, i));
  693. }
  694. /*For IEEE admin_recommendation_bw_precentage
  695. *For IEEE admin_recommendation_ets_pg */
  696. af->pfc.pri_en_bitmap = (u8)dp->admin_pfc_bitmap;
  697. for (i = 0; i < 4; i++) {
  698. if (dp->admin_priority_app_table[i].valid) {
  699. struct bnx2x_admin_priority_app_table *table =
  700. dp->admin_priority_app_table;
  701. if ((ETH_TYPE_FCOE == table[i].app_id) &&
  702. (TRAFFIC_TYPE_ETH == table[i].traffic_type))
  703. traf_type = FCOE_APP_IDX;
  704. else if ((TCP_PORT_ISCSI == table[i].app_id) &&
  705. (TRAFFIC_TYPE_PORT == table[i].traffic_type))
  706. traf_type = ISCSI_APP_IDX;
  707. else
  708. traf_type = other_traf_type++;
  709. af->app.app_pri_tbl[traf_type].app_id =
  710. table[i].app_id;
  711. af->app.app_pri_tbl[traf_type].pri_bitmap =
  712. (u8)(1 << table[i].priority);
  713. af->app.app_pri_tbl[traf_type].appBitfield =
  714. (DCBX_APP_ENTRY_VALID);
  715. af->app.app_pri_tbl[traf_type].appBitfield |=
  716. (TRAFFIC_TYPE_ETH == table[i].traffic_type) ?
  717. DCBX_APP_SF_ETH_TYPE : DCBX_APP_SF_PORT;
  718. }
  719. }
  720. af->app.default_pri = (u8)dp->admin_default_priority;
  721. } else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
  722. dp->overwrite_settings)
  723. dp->overwrite_settings = BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
  724. /* Write the data. */
  725. buff = (u32 *)&admin_mib;
  726. for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
  727. REG_WR(bp, (offset + i), *buff);
  728. }
  729. void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled)
  730. {
  731. if (CHIP_IS_E2(bp) && !CHIP_MODE_IS_4_PORT(bp)) {
  732. bp->dcb_state = dcb_on;
  733. bp->dcbx_enabled = dcbx_enabled;
  734. } else {
  735. bp->dcb_state = false;
  736. bp->dcbx_enabled = BNX2X_DCBX_ENABLED_INVALID;
  737. }
  738. DP(NETIF_MSG_LINK, "DCB state [%s:%s]\n",
  739. dcb_on ? "ON" : "OFF",
  740. dcbx_enabled == BNX2X_DCBX_ENABLED_OFF ? "user-mode" :
  741. dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF ? "on-chip static" :
  742. dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON ?
  743. "on-chip with negotiation" : "invalid");
  744. }
  745. void bnx2x_dcbx_init_params(struct bnx2x *bp)
  746. {
  747. bp->dcbx_config_params.admin_dcbx_version = 0x0; /* 0 - CEE; 1 - IEEE */
  748. bp->dcbx_config_params.admin_ets_willing = 1;
  749. bp->dcbx_config_params.admin_pfc_willing = 1;
  750. bp->dcbx_config_params.overwrite_settings = 1;
  751. bp->dcbx_config_params.admin_ets_enable = 1;
  752. bp->dcbx_config_params.admin_pfc_enable = 1;
  753. bp->dcbx_config_params.admin_tc_supported_tx_enable = 1;
  754. bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
  755. bp->dcbx_config_params.admin_pfc_tx_enable = 1;
  756. bp->dcbx_config_params.admin_application_priority_tx_enable = 1;
  757. bp->dcbx_config_params.admin_ets_reco_valid = 1;
  758. bp->dcbx_config_params.admin_app_priority_willing = 1;
  759. bp->dcbx_config_params.admin_configuration_bw_precentage[0] = 00;
  760. bp->dcbx_config_params.admin_configuration_bw_precentage[1] = 50;
  761. bp->dcbx_config_params.admin_configuration_bw_precentage[2] = 50;
  762. bp->dcbx_config_params.admin_configuration_bw_precentage[3] = 0;
  763. bp->dcbx_config_params.admin_configuration_bw_precentage[4] = 0;
  764. bp->dcbx_config_params.admin_configuration_bw_precentage[5] = 0;
  765. bp->dcbx_config_params.admin_configuration_bw_precentage[6] = 0;
  766. bp->dcbx_config_params.admin_configuration_bw_precentage[7] = 0;
  767. bp->dcbx_config_params.admin_configuration_ets_pg[0] = 1;
  768. bp->dcbx_config_params.admin_configuration_ets_pg[1] = 0;
  769. bp->dcbx_config_params.admin_configuration_ets_pg[2] = 0;
  770. bp->dcbx_config_params.admin_configuration_ets_pg[3] = 2;
  771. bp->dcbx_config_params.admin_configuration_ets_pg[4] = 0;
  772. bp->dcbx_config_params.admin_configuration_ets_pg[5] = 0;
  773. bp->dcbx_config_params.admin_configuration_ets_pg[6] = 0;
  774. bp->dcbx_config_params.admin_configuration_ets_pg[7] = 0;
  775. bp->dcbx_config_params.admin_recommendation_bw_precentage[0] = 0;
  776. bp->dcbx_config_params.admin_recommendation_bw_precentage[1] = 1;
  777. bp->dcbx_config_params.admin_recommendation_bw_precentage[2] = 2;
  778. bp->dcbx_config_params.admin_recommendation_bw_precentage[3] = 0;
  779. bp->dcbx_config_params.admin_recommendation_bw_precentage[4] = 7;
  780. bp->dcbx_config_params.admin_recommendation_bw_precentage[5] = 5;
  781. bp->dcbx_config_params.admin_recommendation_bw_precentage[6] = 6;
  782. bp->dcbx_config_params.admin_recommendation_bw_precentage[7] = 7;
  783. bp->dcbx_config_params.admin_recommendation_ets_pg[0] = 0;
  784. bp->dcbx_config_params.admin_recommendation_ets_pg[1] = 1;
  785. bp->dcbx_config_params.admin_recommendation_ets_pg[2] = 2;
  786. bp->dcbx_config_params.admin_recommendation_ets_pg[3] = 3;
  787. bp->dcbx_config_params.admin_recommendation_ets_pg[4] = 4;
  788. bp->dcbx_config_params.admin_recommendation_ets_pg[5] = 5;
  789. bp->dcbx_config_params.admin_recommendation_ets_pg[6] = 6;
  790. bp->dcbx_config_params.admin_recommendation_ets_pg[7] = 7;
  791. bp->dcbx_config_params.admin_pfc_bitmap = 0x8; /* FCoE(3) enable */
  792. bp->dcbx_config_params.admin_priority_app_table[0].valid = 1;
  793. bp->dcbx_config_params.admin_priority_app_table[1].valid = 1;
  794. bp->dcbx_config_params.admin_priority_app_table[2].valid = 0;
  795. bp->dcbx_config_params.admin_priority_app_table[3].valid = 0;
  796. bp->dcbx_config_params.admin_priority_app_table[0].priority = 3;
  797. bp->dcbx_config_params.admin_priority_app_table[1].priority = 0;
  798. bp->dcbx_config_params.admin_priority_app_table[2].priority = 0;
  799. bp->dcbx_config_params.admin_priority_app_table[3].priority = 0;
  800. bp->dcbx_config_params.admin_priority_app_table[0].traffic_type = 0;
  801. bp->dcbx_config_params.admin_priority_app_table[1].traffic_type = 1;
  802. bp->dcbx_config_params.admin_priority_app_table[2].traffic_type = 0;
  803. bp->dcbx_config_params.admin_priority_app_table[3].traffic_type = 0;
  804. bp->dcbx_config_params.admin_priority_app_table[0].app_id = 0x8906;
  805. bp->dcbx_config_params.admin_priority_app_table[1].app_id = 3260;
  806. bp->dcbx_config_params.admin_priority_app_table[2].app_id = 0;
  807. bp->dcbx_config_params.admin_priority_app_table[3].app_id = 0;
  808. bp->dcbx_config_params.admin_default_priority =
  809. bp->dcbx_config_params.admin_priority_app_table[1].priority;
  810. }
  811. void bnx2x_dcbx_init(struct bnx2x *bp)
  812. {
  813. u32 dcbx_lldp_params_offset = SHMEM_LLDP_DCBX_PARAMS_NONE;
  814. if (bp->dcbx_enabled <= 0)
  815. return;
  816. /* validate:
  817. * chip of good for dcbx version,
  818. * dcb is wanted
  819. * the function is pmf
  820. * shmem2 contains DCBX support fields
  821. */
  822. DP(NETIF_MSG_LINK, "dcb_state %d bp->port.pmf %d\n",
  823. bp->dcb_state, bp->port.pmf);
  824. if (bp->dcb_state == BNX2X_DCB_STATE_ON && bp->port.pmf &&
  825. SHMEM2_HAS(bp, dcbx_lldp_params_offset)) {
  826. dcbx_lldp_params_offset =
  827. SHMEM2_RD(bp, dcbx_lldp_params_offset);
  828. DP(NETIF_MSG_LINK, "dcbx_lldp_params_offset 0x%x\n",
  829. dcbx_lldp_params_offset);
  830. if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) {
  831. bnx2x_dcbx_lldp_updated_params(bp,
  832. dcbx_lldp_params_offset);
  833. bnx2x_dcbx_admin_mib_updated_params(bp,
  834. dcbx_lldp_params_offset);
  835. /* set default configuration BC has */
  836. bnx2x_dcbx_set_params(bp,
  837. BNX2X_DCBX_STATE_NEG_RECEIVED);
  838. bnx2x_fw_command(bp,
  839. DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG, 0);
  840. }
  841. }
  842. }
  843. void bnx2x_dcb_init_intmem_pfc(struct bnx2x *bp)
  844. {
  845. struct priority_cos pricos[MAX_PFC_TRAFFIC_TYPES];
  846. u32 i = 0, addr;
  847. memset(pricos, 0, sizeof(pricos));
  848. /* Default initialization */
  849. for (i = 0; i < MAX_PFC_TRAFFIC_TYPES; i++)
  850. pricos[i].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
  851. /* Store per port struct to internal memory */
  852. addr = BAR_XSTRORM_INTMEM +
  853. XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
  854. offsetof(struct cmng_struct_per_port,
  855. traffic_type_to_priority_cos);
  856. __storm_memset_struct(bp, addr, sizeof(pricos), (u32 *)pricos);
  857. /* LLFC disabled.*/
  858. REG_WR8(bp , BAR_XSTRORM_INTMEM +
  859. XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
  860. offsetof(struct cmng_struct_per_port, llfc_mode),
  861. LLFC_MODE_NONE);
  862. /* DCBX disabled.*/
  863. REG_WR8(bp , BAR_XSTRORM_INTMEM +
  864. XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
  865. offsetof(struct cmng_struct_per_port, dcb_enabled),
  866. DCB_DISABLED);
  867. }
  868. static void
  869. bnx2x_dcbx_print_cos_params(struct bnx2x *bp,
  870. struct flow_control_configuration *pfc_fw_cfg)
  871. {
  872. u8 pri = 0;
  873. u8 cos = 0;
  874. DP(NETIF_MSG_LINK,
  875. "pfc_fw_cfg->dcb_version %x\n", pfc_fw_cfg->dcb_version);
  876. DP(NETIF_MSG_LINK,
  877. "pdev->params.dcbx_port_params.pfc."
  878. "priority_non_pauseable_mask %x\n",
  879. bp->dcbx_port_params.pfc.priority_non_pauseable_mask);
  880. for (cos = 0 ; cos < bp->dcbx_port_params.ets.num_of_cos ; cos++) {
  881. DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
  882. "cos_params[%d].pri_bitmask %x\n", cos,
  883. bp->dcbx_port_params.ets.cos_params[cos].pri_bitmask);
  884. DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
  885. "cos_params[%d].bw_tbl %x\n", cos,
  886. bp->dcbx_port_params.ets.cos_params[cos].bw_tbl);
  887. DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
  888. "cos_params[%d].strict %x\n", cos,
  889. bp->dcbx_port_params.ets.cos_params[cos].strict);
  890. DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
  891. "cos_params[%d].pauseable %x\n", cos,
  892. bp->dcbx_port_params.ets.cos_params[cos].pauseable);
  893. }
  894. for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
  895. DP(NETIF_MSG_LINK,
  896. "pfc_fw_cfg->traffic_type_to_priority_cos[%d]."
  897. "priority %x\n", pri,
  898. pfc_fw_cfg->traffic_type_to_priority_cos[pri].priority);
  899. DP(NETIF_MSG_LINK,
  900. "pfc_fw_cfg->traffic_type_to_priority_cos[%d].cos %x\n",
  901. pri, pfc_fw_cfg->traffic_type_to_priority_cos[pri].cos);
  902. }
  903. }
  904. /* fills help_data according to pg_info */
  905. static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp,
  906. u32 *pg_pri_orginal_spread,
  907. struct pg_help_data *help_data)
  908. {
  909. bool pg_found = false;
  910. u32 i, traf_type, add_traf_type, add_pg;
  911. u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
  912. struct pg_entry_help_data *data = help_data->data; /*shotcut*/
  913. /* Set to invalid */
  914. for (i = 0; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++)
  915. data[i].pg = DCBX_ILLEGAL_PG;
  916. for (add_traf_type = 0;
  917. add_traf_type < LLFC_DRIVER_TRAFFIC_TYPE_MAX; add_traf_type++) {
  918. pg_found = false;
  919. if (ttp[add_traf_type] < MAX_PFC_PRIORITIES) {
  920. add_pg = (u8)pg_pri_orginal_spread[ttp[add_traf_type]];
  921. for (traf_type = 0;
  922. traf_type < LLFC_DRIVER_TRAFFIC_TYPE_MAX;
  923. traf_type++) {
  924. if (data[traf_type].pg == add_pg) {
  925. if (!(data[traf_type].pg_priority &
  926. (1 << ttp[add_traf_type])))
  927. data[traf_type].
  928. num_of_dif_pri++;
  929. data[traf_type].pg_priority |=
  930. (1 << ttp[add_traf_type]);
  931. pg_found = true;
  932. break;
  933. }
  934. }
  935. if (false == pg_found) {
  936. data[help_data->num_of_pg].pg = add_pg;
  937. data[help_data->num_of_pg].pg_priority =
  938. (1 << ttp[add_traf_type]);
  939. data[help_data->num_of_pg].num_of_dif_pri = 1;
  940. help_data->num_of_pg++;
  941. }
  942. }
  943. DP(NETIF_MSG_LINK,
  944. "add_traf_type %d pg_found %s num_of_pg %d\n",
  945. add_traf_type, (false == pg_found) ? "NO" : "YES",
  946. help_data->num_of_pg);
  947. }
  948. }
  949. static void bnx2x_dcbx_ets_disabled_entry_data(struct bnx2x *bp,
  950. struct cos_help_data *cos_data,
  951. u32 pri_join_mask)
  952. {
  953. /* Only one priority than only one COS */
  954. cos_data->data[0].pausable =
  955. IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
  956. cos_data->data[0].pri_join_mask = pri_join_mask;
  957. cos_data->data[0].cos_bw = 100;
  958. cos_data->num_of_cos = 1;
  959. }
  960. static inline void bnx2x_dcbx_add_to_cos_bw(struct bnx2x *bp,
  961. struct cos_entry_help_data *data,
  962. u8 pg_bw)
  963. {
  964. if (data->cos_bw == DCBX_INVALID_COS_BW)
  965. data->cos_bw = pg_bw;
  966. else
  967. data->cos_bw += pg_bw;
  968. }
  969. static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
  970. struct cos_help_data *cos_data,
  971. u32 *pg_pri_orginal_spread,
  972. struct dcbx_ets_feature *ets)
  973. {
  974. u32 pri_tested = 0;
  975. u8 i = 0;
  976. u8 entry = 0;
  977. u8 pg_entry = 0;
  978. u8 num_of_pri = LLFC_DRIVER_TRAFFIC_TYPE_MAX;
  979. cos_data->data[0].pausable = true;
  980. cos_data->data[1].pausable = false;
  981. cos_data->data[0].pri_join_mask = cos_data->data[1].pri_join_mask = 0;
  982. for (i = 0 ; i < num_of_pri ; i++) {
  983. pri_tested = 1 << bp->dcbx_port_params.
  984. app.traffic_type_priority[i];
  985. if (pri_tested & DCBX_PFC_PRI_NON_PAUSE_MASK(bp)) {
  986. cos_data->data[1].pri_join_mask |= pri_tested;
  987. entry = 1;
  988. } else {
  989. cos_data->data[0].pri_join_mask |= pri_tested;
  990. entry = 0;
  991. }
  992. pg_entry = (u8)pg_pri_orginal_spread[bp->dcbx_port_params.
  993. app.traffic_type_priority[i]];
  994. /* There can be only one strict pg */
  995. if (pg_entry < DCBX_MAX_NUM_PG_BW_ENTRIES)
  996. bnx2x_dcbx_add_to_cos_bw(bp, &cos_data->data[entry],
  997. DCBX_PG_BW_GET(ets->pg_bw_tbl, pg_entry));
  998. else
  999. /* If we join a group and one is strict
  1000. * than the bw rulls */
  1001. cos_data->data[entry].strict =
  1002. BNX2X_DCBX_COS_HIGH_STRICT;
  1003. }
  1004. if ((0 == cos_data->data[0].pri_join_mask) &&
  1005. (0 == cos_data->data[1].pri_join_mask))
  1006. BNX2X_ERR("dcbx error: Both groups must have priorities\n");
  1007. }
  1008. #ifndef POWER_OF_2
  1009. #define POWER_OF_2(x) ((0 != x) && (0 == (x & (x-1))))
  1010. #endif
  1011. static void bxn2x_dcbx_single_pg_to_cos_params(struct bnx2x *bp,
  1012. struct pg_help_data *pg_help_data,
  1013. struct cos_help_data *cos_data,
  1014. u32 pri_join_mask,
  1015. u8 num_of_dif_pri)
  1016. {
  1017. u8 i = 0;
  1018. u32 pri_tested = 0;
  1019. u32 pri_mask_without_pri = 0;
  1020. u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
  1021. /*debug*/
  1022. if (num_of_dif_pri == 1) {
  1023. bnx2x_dcbx_ets_disabled_entry_data(bp, cos_data, pri_join_mask);
  1024. return;
  1025. }
  1026. /* single priority group */
  1027. if (pg_help_data->data[0].pg < DCBX_MAX_NUM_PG_BW_ENTRIES) {
  1028. /* If there are both pauseable and non-pauseable priorities,
  1029. * the pauseable priorities go to the first queue and
  1030. * the non-pauseable priorities go to the second queue.
  1031. */
  1032. if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
  1033. /* Pauseable */
  1034. cos_data->data[0].pausable = true;
  1035. /* Non pauseable.*/
  1036. cos_data->data[1].pausable = false;
  1037. if (2 == num_of_dif_pri) {
  1038. cos_data->data[0].cos_bw = 50;
  1039. cos_data->data[1].cos_bw = 50;
  1040. }
  1041. if (3 == num_of_dif_pri) {
  1042. if (POWER_OF_2(DCBX_PFC_PRI_GET_PAUSE(bp,
  1043. pri_join_mask))) {
  1044. cos_data->data[0].cos_bw = 33;
  1045. cos_data->data[1].cos_bw = 67;
  1046. } else {
  1047. cos_data->data[0].cos_bw = 67;
  1048. cos_data->data[1].cos_bw = 33;
  1049. }
  1050. }
  1051. } else if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask)) {
  1052. /* If there are only pauseable priorities,
  1053. * then one/two priorities go to the first queue
  1054. * and one priority goes to the second queue.
  1055. */
  1056. if (2 == num_of_dif_pri) {
  1057. cos_data->data[0].cos_bw = 50;
  1058. cos_data->data[1].cos_bw = 50;
  1059. } else {
  1060. cos_data->data[0].cos_bw = 67;
  1061. cos_data->data[1].cos_bw = 33;
  1062. }
  1063. cos_data->data[1].pausable = true;
  1064. cos_data->data[0].pausable = true;
  1065. /* All priorities except FCOE */
  1066. cos_data->data[0].pri_join_mask = (pri_join_mask &
  1067. ((u8)~(1 << ttp[LLFC_TRAFFIC_TYPE_FCOE])));
  1068. /* Only FCOE priority.*/
  1069. cos_data->data[1].pri_join_mask =
  1070. (1 << ttp[LLFC_TRAFFIC_TYPE_FCOE]);
  1071. } else
  1072. /* If there are only non-pauseable priorities,
  1073. * they will all go to the same queue.
  1074. */
  1075. bnx2x_dcbx_ets_disabled_entry_data(bp,
  1076. cos_data, pri_join_mask);
  1077. } else {
  1078. /* priority group which is not BW limited (PG#15):*/
  1079. if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
  1080. /* If there are both pauseable and non-pauseable
  1081. * priorities, the pauseable priorities go to the first
  1082. * queue and the non-pauseable priorities
  1083. * go to the second queue.
  1084. */
  1085. if (DCBX_PFC_PRI_GET_PAUSE(bp, pri_join_mask) >
  1086. DCBX_PFC_PRI_GET_NON_PAUSE(bp, pri_join_mask)) {
  1087. cos_data->data[0].strict =
  1088. BNX2X_DCBX_COS_HIGH_STRICT;
  1089. cos_data->data[1].strict =
  1090. BNX2X_DCBX_COS_LOW_STRICT;
  1091. } else {
  1092. cos_data->data[0].strict =
  1093. BNX2X_DCBX_COS_LOW_STRICT;
  1094. cos_data->data[1].strict =
  1095. BNX2X_DCBX_COS_HIGH_STRICT;
  1096. }
  1097. /* Pauseable */
  1098. cos_data->data[0].pausable = true;
  1099. /* Non pause-able.*/
  1100. cos_data->data[1].pausable = false;
  1101. } else {
  1102. /* If there are only pauseable priorities or
  1103. * only non-pauseable,* the lower priorities go
  1104. * to the first queue and the higherpriorities go
  1105. * to the second queue.
  1106. */
  1107. cos_data->data[0].pausable =
  1108. cos_data->data[1].pausable =
  1109. IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
  1110. for (i = 0 ; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++) {
  1111. pri_tested = 1 << bp->dcbx_port_params.
  1112. app.traffic_type_priority[i];
  1113. /* Remove priority tested */
  1114. pri_mask_without_pri =
  1115. (pri_join_mask & ((u8)(~pri_tested)));
  1116. if (pri_mask_without_pri < pri_tested)
  1117. break;
  1118. }
  1119. if (i == LLFC_DRIVER_TRAFFIC_TYPE_MAX)
  1120. BNX2X_ERR("Invalid value for pri_join_mask -"
  1121. " could not find a priority\n");
  1122. cos_data->data[0].pri_join_mask = pri_mask_without_pri;
  1123. cos_data->data[1].pri_join_mask = pri_tested;
  1124. /* Both queues are strict priority,
  1125. * and that with the highest priority
  1126. * gets the highest strict priority in the arbiter.
  1127. */
  1128. cos_data->data[0].strict = BNX2X_DCBX_COS_LOW_STRICT;
  1129. cos_data->data[1].strict = BNX2X_DCBX_COS_HIGH_STRICT;
  1130. }
  1131. }
  1132. }
  1133. static void bnx2x_dcbx_two_pg_to_cos_params(
  1134. struct bnx2x *bp,
  1135. struct pg_help_data *pg_help_data,
  1136. struct dcbx_ets_feature *ets,
  1137. struct cos_help_data *cos_data,
  1138. u32 *pg_pri_orginal_spread,
  1139. u32 pri_join_mask,
  1140. u8 num_of_dif_pri)
  1141. {
  1142. u8 i = 0;
  1143. u8 pg[E2_NUM_OF_COS] = {0};
  1144. /* If there are both pauseable and non-pauseable priorities,
  1145. * the pauseable priorities go to the first queue and
  1146. * the non-pauseable priorities go to the second queue.
  1147. */
  1148. if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
  1149. if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp,
  1150. pg_help_data->data[0].pg_priority) ||
  1151. IS_DCBX_PFC_PRI_MIX_PAUSE(bp,
  1152. pg_help_data->data[1].pg_priority)) {
  1153. /* If one PG contains both pauseable and
  1154. * non-pauseable priorities then ETS is disabled.
  1155. */
  1156. bnx2x_dcbx_separate_pauseable_from_non(bp, cos_data,
  1157. pg_pri_orginal_spread, ets);
  1158. bp->dcbx_port_params.ets.enabled = false;
  1159. return;
  1160. }
  1161. /* Pauseable */
  1162. cos_data->data[0].pausable = true;
  1163. /* Non pauseable. */
  1164. cos_data->data[1].pausable = false;
  1165. if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp,
  1166. pg_help_data->data[0].pg_priority)) {
  1167. /* 0 is pauseable */
  1168. cos_data->data[0].pri_join_mask =
  1169. pg_help_data->data[0].pg_priority;
  1170. pg[0] = pg_help_data->data[0].pg;
  1171. cos_data->data[1].pri_join_mask =
  1172. pg_help_data->data[1].pg_priority;
  1173. pg[1] = pg_help_data->data[1].pg;
  1174. } else {/* 1 is pauseable */
  1175. cos_data->data[0].pri_join_mask =
  1176. pg_help_data->data[1].pg_priority;
  1177. pg[0] = pg_help_data->data[1].pg;
  1178. cos_data->data[1].pri_join_mask =
  1179. pg_help_data->data[0].pg_priority;
  1180. pg[1] = pg_help_data->data[0].pg;
  1181. }
  1182. } else {
  1183. /* If there are only pauseable priorities or
  1184. * only non-pauseable, each PG goes to a queue.
  1185. */
  1186. cos_data->data[0].pausable = cos_data->data[1].pausable =
  1187. IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
  1188. cos_data->data[0].pri_join_mask =
  1189. pg_help_data->data[0].pg_priority;
  1190. pg[0] = pg_help_data->data[0].pg;
  1191. cos_data->data[1].pri_join_mask =
  1192. pg_help_data->data[1].pg_priority;
  1193. pg[1] = pg_help_data->data[1].pg;
  1194. }
  1195. /* There can be only one strict pg */
  1196. for (i = 0 ; i < E2_NUM_OF_COS; i++) {
  1197. if (pg[i] < DCBX_MAX_NUM_PG_BW_ENTRIES)
  1198. cos_data->data[i].cos_bw =
  1199. DCBX_PG_BW_GET(ets->pg_bw_tbl, pg[i]);
  1200. else
  1201. cos_data->data[i].strict = BNX2X_DCBX_COS_HIGH_STRICT;
  1202. }
  1203. }
  1204. static void bnx2x_dcbx_three_pg_to_cos_params(
  1205. struct bnx2x *bp,
  1206. struct pg_help_data *pg_help_data,
  1207. struct dcbx_ets_feature *ets,
  1208. struct cos_help_data *cos_data,
  1209. u32 *pg_pri_orginal_spread,
  1210. u32 pri_join_mask,
  1211. u8 num_of_dif_pri)
  1212. {
  1213. u8 i = 0;
  1214. u32 pri_tested = 0;
  1215. u8 entry = 0;
  1216. u8 pg_entry = 0;
  1217. bool b_found_strict = false;
  1218. u8 num_of_pri = LLFC_DRIVER_TRAFFIC_TYPE_MAX;
  1219. cos_data->data[0].pri_join_mask = cos_data->data[1].pri_join_mask = 0;
  1220. /* If there are both pauseable and non-pauseable priorities,
  1221. * the pauseable priorities go to the first queue and the
  1222. * non-pauseable priorities go to the second queue.
  1223. */
  1224. if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask))
  1225. bnx2x_dcbx_separate_pauseable_from_non(bp,
  1226. cos_data, pg_pri_orginal_spread, ets);
  1227. else {
  1228. /* If two BW-limited PG-s were combined to one queue,
  1229. * the BW is their sum.
  1230. *
  1231. * If there are only pauseable priorities or only non-pauseable,
  1232. * and there are both BW-limited and non-BW-limited PG-s,
  1233. * the BW-limited PG/s go to one queue and the non-BW-limited
  1234. * PG/s go to the second queue.
  1235. *
  1236. * If there are only pauseable priorities or only non-pauseable
  1237. * and all are BW limited, then two priorities go to the first
  1238. * queue and one priority goes to the second queue.
  1239. *
  1240. * We will join this two cases:
  1241. * if one is BW limited it will go to the secoend queue
  1242. * otherwise the last priority will get it
  1243. */
  1244. cos_data->data[0].pausable = cos_data->data[1].pausable =
  1245. IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
  1246. for (i = 0 ; i < num_of_pri; i++) {
  1247. pri_tested = 1 << bp->dcbx_port_params.
  1248. app.traffic_type_priority[i];
  1249. pg_entry = (u8)pg_pri_orginal_spread[bp->
  1250. dcbx_port_params.app.traffic_type_priority[i]];
  1251. if (pg_entry < DCBX_MAX_NUM_PG_BW_ENTRIES) {
  1252. entry = 0;
  1253. if (i == (num_of_pri-1) &&
  1254. false == b_found_strict)
  1255. /* last entry will be handled separately
  1256. * If no priority is strict than last
  1257. * enty goes to last queue.*/
  1258. entry = 1;
  1259. cos_data->data[entry].pri_join_mask |=
  1260. pri_tested;
  1261. bnx2x_dcbx_add_to_cos_bw(bp,
  1262. &cos_data->data[entry],
  1263. DCBX_PG_BW_GET(ets->pg_bw_tbl,
  1264. pg_entry));
  1265. } else {
  1266. b_found_strict = true;
  1267. cos_data->data[1].pri_join_mask |= pri_tested;
  1268. /* If we join a group and one is strict
  1269. * than the bw rulls */
  1270. cos_data->data[1].strict =
  1271. BNX2X_DCBX_COS_HIGH_STRICT;
  1272. }
  1273. }
  1274. }
  1275. }
  1276. static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
  1277. struct pg_help_data *help_data,
  1278. struct dcbx_ets_feature *ets,
  1279. u32 *pg_pri_orginal_spread)
  1280. {
  1281. struct cos_help_data cos_data ;
  1282. u8 i = 0;
  1283. u32 pri_join_mask = 0;
  1284. u8 num_of_dif_pri = 0;
  1285. memset(&cos_data, 0, sizeof(cos_data));
  1286. /* Validate the pg value */
  1287. for (i = 0; i < help_data->num_of_pg ; i++) {
  1288. if (DCBX_STRICT_PRIORITY != help_data->data[i].pg &&
  1289. DCBX_MAX_NUM_PG_BW_ENTRIES <= help_data->data[i].pg)
  1290. BNX2X_ERR("Invalid pg[%d] data %x\n", i,
  1291. help_data->data[i].pg);
  1292. pri_join_mask |= help_data->data[i].pg_priority;
  1293. num_of_dif_pri += help_data->data[i].num_of_dif_pri;
  1294. }
  1295. /* default settings */
  1296. cos_data.num_of_cos = 2;
  1297. for (i = 0; i < E2_NUM_OF_COS ; i++) {
  1298. cos_data.data[i].pri_join_mask = pri_join_mask;
  1299. cos_data.data[i].pausable = false;
  1300. cos_data.data[i].strict = BNX2X_DCBX_COS_NOT_STRICT;
  1301. cos_data.data[i].cos_bw = DCBX_INVALID_COS_BW;
  1302. }
  1303. switch (help_data->num_of_pg) {
  1304. case 1:
  1305. bxn2x_dcbx_single_pg_to_cos_params(
  1306. bp,
  1307. help_data,
  1308. &cos_data,
  1309. pri_join_mask,
  1310. num_of_dif_pri);
  1311. break;
  1312. case 2:
  1313. bnx2x_dcbx_two_pg_to_cos_params(
  1314. bp,
  1315. help_data,
  1316. ets,
  1317. &cos_data,
  1318. pg_pri_orginal_spread,
  1319. pri_join_mask,
  1320. num_of_dif_pri);
  1321. break;
  1322. case 3:
  1323. bnx2x_dcbx_three_pg_to_cos_params(
  1324. bp,
  1325. help_data,
  1326. ets,
  1327. &cos_data,
  1328. pg_pri_orginal_spread,
  1329. pri_join_mask,
  1330. num_of_dif_pri);
  1331. break;
  1332. default:
  1333. BNX2X_ERR("Wrong pg_help_data.num_of_pg\n");
  1334. bnx2x_dcbx_ets_disabled_entry_data(bp,
  1335. &cos_data, pri_join_mask);
  1336. }
  1337. for (i = 0; i < cos_data.num_of_cos ; i++) {
  1338. struct bnx2x_dcbx_cos_params *params =
  1339. &bp->dcbx_port_params.ets.cos_params[i];
  1340. params->pauseable = cos_data.data[i].pausable;
  1341. params->strict = cos_data.data[i].strict;
  1342. params->bw_tbl = cos_data.data[i].cos_bw;
  1343. if (params->pauseable) {
  1344. params->pri_bitmask =
  1345. DCBX_PFC_PRI_GET_PAUSE(bp,
  1346. cos_data.data[i].pri_join_mask);
  1347. DP(NETIF_MSG_LINK, "COS %d PAUSABLE prijoinmask 0x%x\n",
  1348. i, cos_data.data[i].pri_join_mask);
  1349. } else {
  1350. params->pri_bitmask =
  1351. DCBX_PFC_PRI_GET_NON_PAUSE(bp,
  1352. cos_data.data[i].pri_join_mask);
  1353. DP(NETIF_MSG_LINK, "COS %d NONPAUSABLE prijoinmask "
  1354. "0x%x\n",
  1355. i, cos_data.data[i].pri_join_mask);
  1356. }
  1357. }
  1358. bp->dcbx_port_params.ets.num_of_cos = cos_data.num_of_cos ;
  1359. }
  1360. static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
  1361. u32 *set_configuration_ets_pg,
  1362. u32 *pri_pg_tbl)
  1363. {
  1364. int i;
  1365. for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++) {
  1366. set_configuration_ets_pg[i] = DCBX_PRI_PG_GET(pri_pg_tbl, i);
  1367. DP(NETIF_MSG_LINK, "set_configuration_ets_pg[%d] = 0x%x\n",
  1368. i, set_configuration_ets_pg[i]);
  1369. }
  1370. }
  1371. static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp)
  1372. {
  1373. struct flow_control_configuration *pfc_fw_cfg = NULL;
  1374. u16 pri_bit = 0;
  1375. u8 cos = 0, pri = 0;
  1376. struct priority_cos *tt2cos;
  1377. u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
  1378. pfc_fw_cfg = (struct flow_control_configuration *)
  1379. bnx2x_sp(bp, pfc_config);
  1380. memset(pfc_fw_cfg, 0, sizeof(struct flow_control_configuration));
  1381. /*shortcut*/
  1382. tt2cos = pfc_fw_cfg->traffic_type_to_priority_cos;
  1383. /* Fw version should be incremented each update */
  1384. pfc_fw_cfg->dcb_version = ++bp->dcb_version;
  1385. pfc_fw_cfg->dcb_enabled = DCB_ENABLED;
  1386. /* Default initialization */
  1387. for (pri = 0; pri < MAX_PFC_TRAFFIC_TYPES ; pri++) {
  1388. tt2cos[pri].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
  1389. tt2cos[pri].cos = 0;
  1390. }
  1391. /* Fill priority parameters */
  1392. for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
  1393. tt2cos[pri].priority = ttp[pri];
  1394. pri_bit = 1 << tt2cos[pri].priority;
  1395. /* Fill COS parameters based on COS calculated to
  1396. * make it more generally for future use */
  1397. for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++)
  1398. if (bp->dcbx_port_params.ets.cos_params[cos].
  1399. pri_bitmask & pri_bit)
  1400. tt2cos[pri].cos = cos;
  1401. }
  1402. bnx2x_dcbx_print_cos_params(bp, pfc_fw_cfg);
  1403. }
  1404. /* DCB netlink */
  1405. #ifdef BCM_DCBNL
  1406. #define BNX2X_DCBX_CAPS (DCB_CAP_DCBX_LLD_MANAGED | \
  1407. DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_STATIC)
  1408. static inline bool bnx2x_dcbnl_set_valid(struct bnx2x *bp)
  1409. {
  1410. /* validate dcbnl call that may change HW state:
  1411. * DCB is on and DCBX mode was SUCCESSFULLY set by the user.
  1412. */
  1413. return bp->dcb_state && bp->dcbx_mode_uset;
  1414. }
  1415. static u8 bnx2x_dcbnl_get_state(struct net_device *netdev)
  1416. {
  1417. struct bnx2x *bp = netdev_priv(netdev);
  1418. DP(NETIF_MSG_LINK, "state = %d\n", bp->dcb_state);
  1419. return bp->dcb_state;
  1420. }
  1421. static u8 bnx2x_dcbnl_set_state(struct net_device *netdev, u8 state)
  1422. {
  1423. struct bnx2x *bp = netdev_priv(netdev);
  1424. DP(NETIF_MSG_LINK, "state = %s\n", state ? "on" : "off");
  1425. bnx2x_dcbx_set_state(bp, (state ? true : false), bp->dcbx_enabled);
  1426. return 0;
  1427. }
  1428. static void bnx2x_dcbnl_get_perm_hw_addr(struct net_device *netdev,
  1429. u8 *perm_addr)
  1430. {
  1431. struct bnx2x *bp = netdev_priv(netdev);
  1432. DP(NETIF_MSG_LINK, "GET-PERM-ADDR\n");
  1433. /* first the HW mac address */
  1434. memcpy(perm_addr, netdev->dev_addr, netdev->addr_len);
  1435. #ifdef BCM_CNIC
  1436. /* second SAN address */
  1437. memcpy(perm_addr+netdev->addr_len, bp->fip_mac, netdev->addr_len);
  1438. #endif
  1439. }
  1440. static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio,
  1441. u8 prio_type, u8 pgid, u8 bw_pct,
  1442. u8 up_map)
  1443. {
  1444. struct bnx2x *bp = netdev_priv(netdev);
  1445. DP(NETIF_MSG_LINK, "prio[%d] = %d\n", prio, pgid);
  1446. if (!bnx2x_dcbnl_set_valid(bp) || prio >= DCBX_MAX_NUM_PRI_PG_ENTRIES)
  1447. return;
  1448. /**
  1449. * bw_pct ingnored - band-width percentage devision between user
  1450. * priorities within the same group is not
  1451. * standard and hence not supported
  1452. *
  1453. * prio_type igonred - priority levels within the same group are not
  1454. * standard and hence are not supported. According
  1455. * to the standard pgid 15 is dedicated to strict
  1456. * prioirty traffic (on the port level).
  1457. *
  1458. * up_map ignored
  1459. */
  1460. bp->dcbx_config_params.admin_configuration_ets_pg[prio] = pgid;
  1461. bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
  1462. }
  1463. static void bnx2x_dcbnl_set_pg_bwgcfg_tx(struct net_device *netdev,
  1464. int pgid, u8 bw_pct)
  1465. {
  1466. struct bnx2x *bp = netdev_priv(netdev);
  1467. DP(NETIF_MSG_LINK, "pgid[%d] = %d\n", pgid, bw_pct);
  1468. if (!bnx2x_dcbnl_set_valid(bp) || pgid >= DCBX_MAX_NUM_PG_BW_ENTRIES)
  1469. return;
  1470. bp->dcbx_config_params.admin_configuration_bw_precentage[pgid] = bw_pct;
  1471. bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
  1472. }
  1473. static void bnx2x_dcbnl_set_pg_tccfg_rx(struct net_device *netdev, int prio,
  1474. u8 prio_type, u8 pgid, u8 bw_pct,
  1475. u8 up_map)
  1476. {
  1477. struct bnx2x *bp = netdev_priv(netdev);
  1478. DP(NETIF_MSG_LINK, "Nothing to set; No RX support\n");
  1479. }
  1480. static void bnx2x_dcbnl_set_pg_bwgcfg_rx(struct net_device *netdev,
  1481. int pgid, u8 bw_pct)
  1482. {
  1483. struct bnx2x *bp = netdev_priv(netdev);
  1484. DP(NETIF_MSG_LINK, "Nothing to set; No RX support\n");
  1485. }
  1486. static void bnx2x_dcbnl_get_pg_tccfg_tx(struct net_device *netdev, int prio,
  1487. u8 *prio_type, u8 *pgid, u8 *bw_pct,
  1488. u8 *up_map)
  1489. {
  1490. struct bnx2x *bp = netdev_priv(netdev);
  1491. DP(NETIF_MSG_LINK, "prio = %d\n", prio);
  1492. /**
  1493. * bw_pct ingnored - band-width percentage devision between user
  1494. * priorities within the same group is not
  1495. * standard and hence not supported
  1496. *
  1497. * prio_type igonred - priority levels within the same group are not
  1498. * standard and hence are not supported. According
  1499. * to the standard pgid 15 is dedicated to strict
  1500. * prioirty traffic (on the port level).
  1501. *
  1502. * up_map ignored
  1503. */
  1504. *up_map = *bw_pct = *prio_type = *pgid = 0;
  1505. if (!bp->dcb_state || prio >= DCBX_MAX_NUM_PRI_PG_ENTRIES)
  1506. return;
  1507. *pgid = DCBX_PRI_PG_GET(bp->dcbx_local_feat.ets.pri_pg_tbl, prio);
  1508. }
  1509. static void bnx2x_dcbnl_get_pg_bwgcfg_tx(struct net_device *netdev,
  1510. int pgid, u8 *bw_pct)
  1511. {
  1512. struct bnx2x *bp = netdev_priv(netdev);
  1513. DP(NETIF_MSG_LINK, "pgid = %d\n", pgid);
  1514. *bw_pct = 0;
  1515. if (!bp->dcb_state || pgid >= DCBX_MAX_NUM_PG_BW_ENTRIES)
  1516. return;
  1517. *bw_pct = DCBX_PG_BW_GET(bp->dcbx_local_feat.ets.pg_bw_tbl, pgid);
  1518. }
  1519. static void bnx2x_dcbnl_get_pg_tccfg_rx(struct net_device *netdev, int prio,
  1520. u8 *prio_type, u8 *pgid, u8 *bw_pct,
  1521. u8 *up_map)
  1522. {
  1523. struct bnx2x *bp = netdev_priv(netdev);
  1524. DP(NETIF_MSG_LINK, "Nothing to get; No RX support\n");
  1525. *prio_type = *pgid = *bw_pct = *up_map = 0;
  1526. }
  1527. static void bnx2x_dcbnl_get_pg_bwgcfg_rx(struct net_device *netdev,
  1528. int pgid, u8 *bw_pct)
  1529. {
  1530. struct bnx2x *bp = netdev_priv(netdev);
  1531. DP(NETIF_MSG_LINK, "Nothing to get; No RX support\n");
  1532. *bw_pct = 0;
  1533. }
  1534. static void bnx2x_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio,
  1535. u8 setting)
  1536. {
  1537. struct bnx2x *bp = netdev_priv(netdev);
  1538. DP(NETIF_MSG_LINK, "prio[%d] = %d\n", prio, setting);
  1539. if (!bnx2x_dcbnl_set_valid(bp) || prio >= MAX_PFC_PRIORITIES)
  1540. return;
  1541. bp->dcbx_config_params.admin_pfc_bitmap |= ((setting ? 1 : 0) << prio);
  1542. if (setting)
  1543. bp->dcbx_config_params.admin_pfc_tx_enable = 1;
  1544. }
  1545. static void bnx2x_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio,
  1546. u8 *setting)
  1547. {
  1548. struct bnx2x *bp = netdev_priv(netdev);
  1549. DP(NETIF_MSG_LINK, "prio = %d\n", prio);
  1550. *setting = 0;
  1551. if (!bp->dcb_state || prio >= MAX_PFC_PRIORITIES)
  1552. return;
  1553. *setting = (bp->dcbx_local_feat.pfc.pri_en_bitmap >> prio) & 0x1;
  1554. }
  1555. static u8 bnx2x_dcbnl_set_all(struct net_device *netdev)
  1556. {
  1557. struct bnx2x *bp = netdev_priv(netdev);
  1558. int rc = 0;
  1559. DP(NETIF_MSG_LINK, "SET-ALL\n");
  1560. if (!bnx2x_dcbnl_set_valid(bp))
  1561. return 1;
  1562. if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
  1563. netdev_err(bp->dev, "Handling parity error recovery. "
  1564. "Try again later\n");
  1565. return 1;
  1566. }
  1567. if (netif_running(bp->dev)) {
  1568. bnx2x_nic_unload(bp, UNLOAD_NORMAL);
  1569. rc = bnx2x_nic_load(bp, LOAD_NORMAL);
  1570. }
  1571. DP(NETIF_MSG_LINK, "set_dcbx_params done (%d)\n", rc);
  1572. if (rc)
  1573. return 1;
  1574. return 0;
  1575. }
  1576. static u8 bnx2x_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap)
  1577. {
  1578. struct bnx2x *bp = netdev_priv(netdev);
  1579. u8 rval = 0;
  1580. if (bp->dcb_state) {
  1581. switch (capid) {
  1582. case DCB_CAP_ATTR_PG:
  1583. *cap = true;
  1584. break;
  1585. case DCB_CAP_ATTR_PFC:
  1586. *cap = true;
  1587. break;
  1588. case DCB_CAP_ATTR_UP2TC:
  1589. *cap = false;
  1590. break;
  1591. case DCB_CAP_ATTR_PG_TCS:
  1592. *cap = 0x80; /* 8 priorities for PGs */
  1593. break;
  1594. case DCB_CAP_ATTR_PFC_TCS:
  1595. *cap = 0x80; /* 8 priorities for PFC */
  1596. break;
  1597. case DCB_CAP_ATTR_GSP:
  1598. *cap = true;
  1599. break;
  1600. case DCB_CAP_ATTR_BCN:
  1601. *cap = false;
  1602. break;
  1603. case DCB_CAP_ATTR_DCBX:
  1604. *cap = BNX2X_DCBX_CAPS;
  1605. break;
  1606. default:
  1607. rval = -EINVAL;
  1608. break;
  1609. }
  1610. } else
  1611. rval = -EINVAL;
  1612. DP(NETIF_MSG_LINK, "capid %d:%x\n", capid, *cap);
  1613. return rval;
  1614. }
  1615. static u8 bnx2x_dcbnl_get_numtcs(struct net_device *netdev, int tcid, u8 *num)
  1616. {
  1617. struct bnx2x *bp = netdev_priv(netdev);
  1618. u8 rval = 0;
  1619. DP(NETIF_MSG_LINK, "tcid %d\n", tcid);
  1620. if (bp->dcb_state) {
  1621. switch (tcid) {
  1622. case DCB_NUMTCS_ATTR_PG:
  1623. *num = E2_NUM_OF_COS;
  1624. break;
  1625. case DCB_NUMTCS_ATTR_PFC:
  1626. *num = E2_NUM_OF_COS;
  1627. break;
  1628. default:
  1629. rval = -EINVAL;
  1630. break;
  1631. }
  1632. } else
  1633. rval = -EINVAL;
  1634. return rval;
  1635. }
  1636. static u8 bnx2x_dcbnl_set_numtcs(struct net_device *netdev, int tcid, u8 num)
  1637. {
  1638. struct bnx2x *bp = netdev_priv(netdev);
  1639. DP(NETIF_MSG_LINK, "num tcs = %d; Not supported\n", num);
  1640. return -EINVAL;
  1641. }
  1642. static u8 bnx2x_dcbnl_get_pfc_state(struct net_device *netdev)
  1643. {
  1644. struct bnx2x *bp = netdev_priv(netdev);
  1645. DP(NETIF_MSG_LINK, "state = %d\n", bp->dcbx_local_feat.pfc.enabled);
  1646. if (!bp->dcb_state)
  1647. return 0;
  1648. return bp->dcbx_local_feat.pfc.enabled;
  1649. }
  1650. static void bnx2x_dcbnl_set_pfc_state(struct net_device *netdev, u8 state)
  1651. {
  1652. struct bnx2x *bp = netdev_priv(netdev);
  1653. DP(NETIF_MSG_LINK, "state = %s\n", state ? "on" : "off");
  1654. if (!bnx2x_dcbnl_set_valid(bp))
  1655. return;
  1656. bp->dcbx_config_params.admin_pfc_tx_enable =
  1657. bp->dcbx_config_params.admin_pfc_enable = (state ? 1 : 0);
  1658. }
  1659. static void bnx2x_admin_app_set_ent(
  1660. struct bnx2x_admin_priority_app_table *app_ent,
  1661. u8 idtype, u16 idval, u8 up)
  1662. {
  1663. app_ent->valid = 1;
  1664. switch (idtype) {
  1665. case DCB_APP_IDTYPE_ETHTYPE:
  1666. app_ent->traffic_type = TRAFFIC_TYPE_ETH;
  1667. break;
  1668. case DCB_APP_IDTYPE_PORTNUM:
  1669. app_ent->traffic_type = TRAFFIC_TYPE_PORT;
  1670. break;
  1671. default:
  1672. break; /* never gets here */
  1673. }
  1674. app_ent->app_id = idval;
  1675. app_ent->priority = up;
  1676. }
  1677. static bool bnx2x_admin_app_is_equal(
  1678. struct bnx2x_admin_priority_app_table *app_ent,
  1679. u8 idtype, u16 idval)
  1680. {
  1681. if (!app_ent->valid)
  1682. return false;
  1683. switch (idtype) {
  1684. case DCB_APP_IDTYPE_ETHTYPE:
  1685. if (app_ent->traffic_type != TRAFFIC_TYPE_ETH)
  1686. return false;
  1687. break;
  1688. case DCB_APP_IDTYPE_PORTNUM:
  1689. if (app_ent->traffic_type != TRAFFIC_TYPE_PORT)
  1690. return false;
  1691. break;
  1692. default:
  1693. return false;
  1694. }
  1695. if (app_ent->app_id != idval)
  1696. return false;
  1697. return true;
  1698. }
  1699. static int bnx2x_set_admin_app_up(struct bnx2x *bp, u8 idtype, u16 idval, u8 up)
  1700. {
  1701. int i, ff;
  1702. /* iterate over the app entries looking for idtype and idval */
  1703. for (i = 0, ff = -1; i < 4; i++) {
  1704. struct bnx2x_admin_priority_app_table *app_ent =
  1705. &bp->dcbx_config_params.admin_priority_app_table[i];
  1706. if (bnx2x_admin_app_is_equal(app_ent, idtype, idval))
  1707. break;
  1708. if (ff < 0 && !app_ent->valid)
  1709. ff = i;
  1710. }
  1711. if (i < 4)
  1712. /* if found overwrite up */
  1713. bp->dcbx_config_params.
  1714. admin_priority_app_table[i].priority = up;
  1715. else if (ff >= 0)
  1716. /* not found use first-free */
  1717. bnx2x_admin_app_set_ent(
  1718. &bp->dcbx_config_params.admin_priority_app_table[ff],
  1719. idtype, idval, up);
  1720. else
  1721. /* app table is full */
  1722. return -EBUSY;
  1723. /* up configured, if not 0 make sure feature is enabled */
  1724. if (up)
  1725. bp->dcbx_config_params.admin_application_priority_tx_enable = 1;
  1726. return 0;
  1727. }
  1728. static u8 bnx2x_dcbnl_set_app_up(struct net_device *netdev, u8 idtype,
  1729. u16 idval, u8 up)
  1730. {
  1731. struct bnx2x *bp = netdev_priv(netdev);
  1732. DP(NETIF_MSG_LINK, "app_type %d, app_id %x, prio bitmap %d\n",
  1733. idtype, idval, up);
  1734. if (!bnx2x_dcbnl_set_valid(bp))
  1735. return -EINVAL;
  1736. /* verify idtype */
  1737. switch (idtype) {
  1738. case DCB_APP_IDTYPE_ETHTYPE:
  1739. case DCB_APP_IDTYPE_PORTNUM:
  1740. break;
  1741. default:
  1742. return -EINVAL;
  1743. }
  1744. return bnx2x_set_admin_app_up(bp, idtype, idval, up);
  1745. }
  1746. static u8 bnx2x_dcbnl_get_dcbx(struct net_device *netdev)
  1747. {
  1748. struct bnx2x *bp = netdev_priv(netdev);
  1749. u8 state;
  1750. state = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_CEE;
  1751. if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF)
  1752. state |= DCB_CAP_DCBX_STATIC;
  1753. return state;
  1754. }
  1755. static u8 bnx2x_dcbnl_set_dcbx(struct net_device *netdev, u8 state)
  1756. {
  1757. struct bnx2x *bp = netdev_priv(netdev);
  1758. DP(NETIF_MSG_LINK, "state = %02x\n", state);
  1759. /* set dcbx mode */
  1760. if ((state & BNX2X_DCBX_CAPS) != state) {
  1761. BNX2X_ERR("Requested DCBX mode %x is beyond advertised "
  1762. "capabilities\n", state);
  1763. return 1;
  1764. }
  1765. if (bp->dcb_state != BNX2X_DCB_STATE_ON) {
  1766. BNX2X_ERR("DCB turned off, DCBX configuration is invalid\n");
  1767. return 1;
  1768. }
  1769. if (state & DCB_CAP_DCBX_STATIC)
  1770. bp->dcbx_enabled = BNX2X_DCBX_ENABLED_ON_NEG_OFF;
  1771. else
  1772. bp->dcbx_enabled = BNX2X_DCBX_ENABLED_ON_NEG_ON;
  1773. bp->dcbx_mode_uset = true;
  1774. return 0;
  1775. }
  1776. static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid,
  1777. u8 *flags)
  1778. {
  1779. struct bnx2x *bp = netdev_priv(netdev);
  1780. u8 rval = 0;
  1781. DP(NETIF_MSG_LINK, "featid %d\n", featid);
  1782. if (bp->dcb_state) {
  1783. *flags = 0;
  1784. switch (featid) {
  1785. case DCB_FEATCFG_ATTR_PG:
  1786. if (bp->dcbx_local_feat.ets.enabled)
  1787. *flags |= DCB_FEATCFG_ENABLE;
  1788. if (bp->dcbx_error & DCBX_LOCAL_ETS_ERROR)
  1789. *flags |= DCB_FEATCFG_ERROR;
  1790. break;
  1791. case DCB_FEATCFG_ATTR_PFC:
  1792. if (bp->dcbx_local_feat.pfc.enabled)
  1793. *flags |= DCB_FEATCFG_ENABLE;
  1794. if (bp->dcbx_error & (DCBX_LOCAL_PFC_ERROR |
  1795. DCBX_LOCAL_PFC_MISMATCH))
  1796. *flags |= DCB_FEATCFG_ERROR;
  1797. break;
  1798. case DCB_FEATCFG_ATTR_APP:
  1799. if (bp->dcbx_local_feat.app.enabled)
  1800. *flags |= DCB_FEATCFG_ENABLE;
  1801. if (bp->dcbx_error & (DCBX_LOCAL_APP_ERROR |
  1802. DCBX_LOCAL_APP_MISMATCH))
  1803. *flags |= DCB_FEATCFG_ERROR;
  1804. break;
  1805. default:
  1806. rval = -EINVAL;
  1807. break;
  1808. }
  1809. } else
  1810. rval = -EINVAL;
  1811. return rval;
  1812. }
  1813. static u8 bnx2x_dcbnl_set_featcfg(struct net_device *netdev, int featid,
  1814. u8 flags)
  1815. {
  1816. struct bnx2x *bp = netdev_priv(netdev);
  1817. u8 rval = 0;
  1818. DP(NETIF_MSG_LINK, "featid = %d flags = %02x\n", featid, flags);
  1819. /* ignore the 'advertise' flag */
  1820. if (bnx2x_dcbnl_set_valid(bp)) {
  1821. switch (featid) {
  1822. case DCB_FEATCFG_ATTR_PG:
  1823. bp->dcbx_config_params.admin_ets_enable =
  1824. flags & DCB_FEATCFG_ENABLE ? 1 : 0;
  1825. bp->dcbx_config_params.admin_ets_willing =
  1826. flags & DCB_FEATCFG_WILLING ? 1 : 0;
  1827. break;
  1828. case DCB_FEATCFG_ATTR_PFC:
  1829. bp->dcbx_config_params.admin_pfc_enable =
  1830. flags & DCB_FEATCFG_ENABLE ? 1 : 0;
  1831. bp->dcbx_config_params.admin_pfc_willing =
  1832. flags & DCB_FEATCFG_WILLING ? 1 : 0;
  1833. break;
  1834. case DCB_FEATCFG_ATTR_APP:
  1835. /* ignore enable, always enabled */
  1836. bp->dcbx_config_params.admin_app_priority_willing =
  1837. flags & DCB_FEATCFG_WILLING ? 1 : 0;
  1838. break;
  1839. default:
  1840. rval = -EINVAL;
  1841. break;
  1842. }
  1843. } else
  1844. rval = -EINVAL;
  1845. return rval;
  1846. }
  1847. static int bnx2x_peer_appinfo(struct net_device *netdev,
  1848. struct dcb_peer_app_info *info, u16* app_count)
  1849. {
  1850. int i;
  1851. struct bnx2x *bp = netdev_priv(netdev);
  1852. DP(NETIF_MSG_LINK, "APP-INFO\n");
  1853. info->willing = (bp->dcbx_remote_flags & DCBX_APP_REM_WILLING) ?: 0;
  1854. info->error = (bp->dcbx_remote_flags & DCBX_APP_RX_ERROR) ?: 0;
  1855. *app_count = 0;
  1856. for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
  1857. if (bp->dcbx_remote_feat.app.app_pri_tbl[i].appBitfield &
  1858. DCBX_APP_ENTRY_VALID)
  1859. (*app_count)++;
  1860. return 0;
  1861. }
  1862. static int bnx2x_peer_apptable(struct net_device *netdev,
  1863. struct dcb_app *table)
  1864. {
  1865. int i, j;
  1866. struct bnx2x *bp = netdev_priv(netdev);
  1867. DP(NETIF_MSG_LINK, "APP-TABLE\n");
  1868. for (i = 0, j = 0; i < DCBX_MAX_APP_PROTOCOL; i++) {
  1869. struct dcbx_app_priority_entry *ent =
  1870. &bp->dcbx_remote_feat.app.app_pri_tbl[i];
  1871. if (ent->appBitfield & DCBX_APP_ENTRY_VALID) {
  1872. table[j].selector = bnx2x_dcbx_dcbnl_app_idtype(ent);
  1873. table[j].priority = bnx2x_dcbx_dcbnl_app_up(ent);
  1874. table[j++].protocol = ent->app_id;
  1875. }
  1876. }
  1877. return 0;
  1878. }
  1879. static int bnx2x_cee_peer_getpg(struct net_device *netdev, struct cee_pg *pg)
  1880. {
  1881. int i;
  1882. struct bnx2x *bp = netdev_priv(netdev);
  1883. pg->willing = (bp->dcbx_remote_flags & DCBX_ETS_REM_WILLING) ?: 0;
  1884. for (i = 0; i < CEE_DCBX_MAX_PGS; i++) {
  1885. pg->pg_bw[i] =
  1886. DCBX_PG_BW_GET(bp->dcbx_remote_feat.ets.pg_bw_tbl, i);
  1887. pg->prio_pg[i] =
  1888. DCBX_PRI_PG_GET(bp->dcbx_remote_feat.ets.pri_pg_tbl, i);
  1889. }
  1890. return 0;
  1891. }
  1892. static int bnx2x_cee_peer_getpfc(struct net_device *netdev,
  1893. struct cee_pfc *pfc)
  1894. {
  1895. struct bnx2x *bp = netdev_priv(netdev);
  1896. pfc->tcs_supported = bp->dcbx_remote_feat.pfc.pfc_caps;
  1897. pfc->pfc_en = bp->dcbx_remote_feat.pfc.pri_en_bitmap;
  1898. return 0;
  1899. }
  1900. const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops = {
  1901. .getstate = bnx2x_dcbnl_get_state,
  1902. .setstate = bnx2x_dcbnl_set_state,
  1903. .getpermhwaddr = bnx2x_dcbnl_get_perm_hw_addr,
  1904. .setpgtccfgtx = bnx2x_dcbnl_set_pg_tccfg_tx,
  1905. .setpgbwgcfgtx = bnx2x_dcbnl_set_pg_bwgcfg_tx,
  1906. .setpgtccfgrx = bnx2x_dcbnl_set_pg_tccfg_rx,
  1907. .setpgbwgcfgrx = bnx2x_dcbnl_set_pg_bwgcfg_rx,
  1908. .getpgtccfgtx = bnx2x_dcbnl_get_pg_tccfg_tx,
  1909. .getpgbwgcfgtx = bnx2x_dcbnl_get_pg_bwgcfg_tx,
  1910. .getpgtccfgrx = bnx2x_dcbnl_get_pg_tccfg_rx,
  1911. .getpgbwgcfgrx = bnx2x_dcbnl_get_pg_bwgcfg_rx,
  1912. .setpfccfg = bnx2x_dcbnl_set_pfc_cfg,
  1913. .getpfccfg = bnx2x_dcbnl_get_pfc_cfg,
  1914. .setall = bnx2x_dcbnl_set_all,
  1915. .getcap = bnx2x_dcbnl_get_cap,
  1916. .getnumtcs = bnx2x_dcbnl_get_numtcs,
  1917. .setnumtcs = bnx2x_dcbnl_set_numtcs,
  1918. .getpfcstate = bnx2x_dcbnl_get_pfc_state,
  1919. .setpfcstate = bnx2x_dcbnl_set_pfc_state,
  1920. .setapp = bnx2x_dcbnl_set_app_up,
  1921. .getdcbx = bnx2x_dcbnl_get_dcbx,
  1922. .setdcbx = bnx2x_dcbnl_set_dcbx,
  1923. .getfeatcfg = bnx2x_dcbnl_get_featcfg,
  1924. .setfeatcfg = bnx2x_dcbnl_set_featcfg,
  1925. .peer_getappinfo = bnx2x_peer_appinfo,
  1926. .peer_getapptable = bnx2x_peer_apptable,
  1927. .cee_peer_getpg = bnx2x_cee_peer_getpg,
  1928. .cee_peer_getpfc = bnx2x_cee_peer_getpfc,
  1929. };
  1930. #endif /* BCM_DCBNL */