aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2x_main.c
diff options
context:
space:
mode:
authorEilon Greenstein <eilong@broadcom.com>2009-08-12 04:22:08 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-13 02:02:12 -0400
commit2691d51d7243560aa0870dadbf5c6b98f647f751 (patch)
treeb1d19b51005395517e35c632501715edf7e20c7c /drivers/net/bnx2x_main.c
parenta1d58179d1337ff8f8530c9fac8b9e98b2f7761f (diff)
bnx2x: Supporting Device Control Channel
In multi-function mode, the FW can receive special management control commands to set the Min/Max BW and the the function link state Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2x_main.c')
-rw-r--r--drivers/net/bnx2x_main.c325
1 files changed, 232 insertions, 93 deletions
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index 762f37a7d038..8abce3c182e0 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -2104,6 +2104,12 @@ static void bnx2x_calc_fc_adv(struct bnx2x *bp)
2104 2104
2105static void bnx2x_link_report(struct bnx2x *bp) 2105static void bnx2x_link_report(struct bnx2x *bp)
2106{ 2106{
2107 if (bp->state == BNX2X_STATE_DISABLED) {
2108 netif_carrier_off(bp->dev);
2109 printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name);
2110 return;
2111 }
2112
2107 if (bp->link_vars.link_up) { 2113 if (bp->link_vars.link_up) {
2108 if (bp->state == BNX2X_STATE_OPEN) 2114 if (bp->state == BNX2X_STATE_OPEN)
2109 netif_carrier_on(bp->dev); 2115 netif_carrier_on(bp->dev);
@@ -2240,6 +2246,46 @@ static void bnx2x_init_port_minmax(struct bnx2x *bp)
2240 bp->cmng.fair_vars.fairness_timeout = fair_periodic_timeout_usec / 4; 2246 bp->cmng.fair_vars.fairness_timeout = fair_periodic_timeout_usec / 4;
2241} 2247}
2242 2248
2249/* Calculates the sum of vn_min_rates.
2250 It's needed for further normalizing of the min_rates.
2251 Returns:
2252 sum of vn_min_rates.
2253 or
2254 0 - if all the min_rates are 0.
2255 In the later case fainess algorithm should be deactivated.
2256 If not all min_rates are zero then those that are zeroes will be set to 1.
2257 */
2258static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
2259{
2260 int all_zero = 1;
2261 int port = BP_PORT(bp);
2262 int vn;
2263
2264 bp->vn_weight_sum = 0;
2265 for (vn = VN_0; vn < E1HVN_MAX; vn++) {
2266 int func = 2*vn + port;
2267 u32 vn_cfg = SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
2268 u32 vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
2269 FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
2270
2271 /* Skip hidden vns */
2272 if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE)
2273 continue;
2274
2275 /* If min rate is zero - set it to 1 */
2276 if (!vn_min_rate)
2277 vn_min_rate = DEF_MIN_RATE;
2278 else
2279 all_zero = 0;
2280
2281 bp->vn_weight_sum += vn_min_rate;
2282 }
2283
2284 /* ... only if all min rates are zeros - disable fairness */
2285 if (all_zero)
2286 bp->vn_weight_sum = 0;
2287}
2288
2243static void bnx2x_init_vn_minmax(struct bnx2x *bp, int func) 2289static void bnx2x_init_vn_minmax(struct bnx2x *bp, int func)
2244{ 2290{
2245 struct rate_shaping_vars_per_vn m_rs_vn; 2291 struct rate_shaping_vars_per_vn m_rs_vn;
@@ -2383,6 +2429,8 @@ static void bnx2x_link_attn(struct bnx2x *bp)
2383 2429
2384static void bnx2x__link_status_update(struct bnx2x *bp) 2430static void bnx2x__link_status_update(struct bnx2x *bp)
2385{ 2431{
2432 int func = BP_FUNC(bp);
2433
2386 if (bp->state != BNX2X_STATE_OPEN) 2434 if (bp->state != BNX2X_STATE_OPEN)
2387 return; 2435 return;
2388 2436
@@ -2393,6 +2441,9 @@ static void bnx2x__link_status_update(struct bnx2x *bp)
2393 else 2441 else
2394 bnx2x_stats_handle(bp, STATS_EVENT_STOP); 2442 bnx2x_stats_handle(bp, STATS_EVENT_STOP);
2395 2443
2444 bp->mf_config = SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
2445 bnx2x_calc_vn_weight_sum(bp);
2446
2396 /* indicate link status */ 2447 /* indicate link status */
2397 bnx2x_link_report(bp); 2448 bnx2x_link_report(bp);
2398} 2449}
@@ -2421,6 +2472,152 @@ static void bnx2x_pmf_update(struct bnx2x *bp)
2421 * General service functions 2472 * General service functions
2422 */ 2473 */
2423 2474
2475/* send the MCP a request, block until there is a reply */
2476u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
2477{
2478 int func = BP_FUNC(bp);
2479 u32 seq = ++bp->fw_seq;
2480 u32 rc = 0;
2481 u32 cnt = 1;
2482 u8 delay = CHIP_REV_IS_SLOW(bp) ? 100 : 10;
2483
2484 SHMEM_WR(bp, func_mb[func].drv_mb_header, (command | seq));
2485 DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq));
2486
2487 do {
2488 /* let the FW do it's magic ... */
2489 msleep(delay);
2490
2491 rc = SHMEM_RD(bp, func_mb[func].fw_mb_header);
2492
2493 /* Give the FW up to 2 second (200*10ms) */
2494 } while ((seq != (rc & FW_MSG_SEQ_NUMBER_MASK)) && (cnt++ < 200));
2495
2496 DP(BNX2X_MSG_MCP, "[after %d ms] read (%x) seq is (%x) from FW MB\n",
2497 cnt*delay, rc, seq);
2498
2499 /* is this a reply to our command? */
2500 if (seq == (rc & FW_MSG_SEQ_NUMBER_MASK))
2501 rc &= FW_MSG_CODE_MASK;
2502 else {
2503 /* FW BUG! */
2504 BNX2X_ERR("FW failed to respond!\n");
2505 bnx2x_fw_dump(bp);
2506 rc = 0;
2507 }
2508
2509 return rc;
2510}
2511
2512static void bnx2x_set_storm_rx_mode(struct bnx2x *bp);
2513static void bnx2x_set_mac_addr_e1h(struct bnx2x *bp, int set);
2514static void bnx2x_set_rx_mode(struct net_device *dev);
2515
2516static void bnx2x_e1h_disable(struct bnx2x *bp)
2517{
2518 int port = BP_PORT(bp);
2519 int i;
2520
2521 bp->rx_mode = BNX2X_RX_MODE_NONE;
2522 bnx2x_set_storm_rx_mode(bp);
2523
2524 netif_tx_disable(bp->dev);
2525 bp->dev->trans_start = jiffies; /* prevent tx timeout */
2526
2527 REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
2528
2529 bnx2x_set_mac_addr_e1h(bp, 0);
2530
2531 for (i = 0; i < MC_HASH_SIZE; i++)
2532 REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
2533
2534 netif_carrier_off(bp->dev);
2535}
2536
2537static void bnx2x_e1h_enable(struct bnx2x *bp)
2538{
2539 int port = BP_PORT(bp);
2540
2541 REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1);
2542
2543 bnx2x_set_mac_addr_e1h(bp, 1);
2544
2545 /* Tx queue should be only reenabled */
2546 netif_tx_wake_all_queues(bp->dev);
2547
2548 /* Initialize the receive filter. */
2549 bnx2x_set_rx_mode(bp->dev);
2550}
2551
2552static void bnx2x_update_min_max(struct bnx2x *bp)
2553{
2554 int port = BP_PORT(bp);
2555 int vn, i;
2556
2557 /* Init rate shaping and fairness contexts */
2558 bnx2x_init_port_minmax(bp);
2559
2560 bnx2x_calc_vn_weight_sum(bp);
2561
2562 for (vn = VN_0; vn < E1HVN_MAX; vn++)
2563 bnx2x_init_vn_minmax(bp, 2*vn + port);
2564
2565 if (bp->port.pmf) {
2566 int func;
2567
2568 /* Set the attention towards other drivers on the same port */
2569 for (vn = VN_0; vn < E1HVN_MAX; vn++) {
2570 if (vn == BP_E1HVN(bp))
2571 continue;
2572
2573 func = ((vn << 1) | port);
2574 REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_0 +
2575 (LINK_SYNC_ATTENTION_BIT_FUNC_0 + func)*4, 1);
2576 }
2577
2578 /* Store it to internal memory */
2579 for (i = 0; i < sizeof(struct cmng_struct_per_port) / 4; i++)
2580 REG_WR(bp, BAR_XSTRORM_INTMEM +
2581 XSTORM_CMNG_PER_PORT_VARS_OFFSET(port) + i*4,
2582 ((u32 *)(&bp->cmng))[i]);
2583 }
2584}
2585
2586static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event)
2587{
2588 int func = BP_FUNC(bp);
2589
2590 DP(BNX2X_MSG_MCP, "dcc_event 0x%x\n", dcc_event);
2591 bp->mf_config = SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
2592
2593 if (dcc_event & DRV_STATUS_DCC_DISABLE_ENABLE_PF) {
2594
2595 if (bp->mf_config & FUNC_MF_CFG_FUNC_DISABLED) {
2596 DP(NETIF_MSG_IFDOWN, "mf_cfg function disabled\n");
2597 bp->state = BNX2X_STATE_DISABLED;
2598
2599 bnx2x_e1h_disable(bp);
2600 } else {
2601 DP(NETIF_MSG_IFUP, "mf_cfg function enabled\n");
2602 bp->state = BNX2X_STATE_OPEN;
2603
2604 bnx2x_e1h_enable(bp);
2605 }
2606 dcc_event &= ~DRV_STATUS_DCC_DISABLE_ENABLE_PF;
2607 }
2608 if (dcc_event & DRV_STATUS_DCC_BANDWIDTH_ALLOCATION) {
2609
2610 bnx2x_update_min_max(bp);
2611 dcc_event &= ~DRV_STATUS_DCC_BANDWIDTH_ALLOCATION;
2612 }
2613
2614 /* Report results to MCP */
2615 if (dcc_event)
2616 bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_FAILURE);
2617 else
2618 bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_OK);
2619}
2620
2424/* the slow path queue is odd since completions arrive on the fastpath ring */ 2621/* the slow path queue is odd since completions arrive on the fastpath ring */
2425static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, 2622static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
2426 u32 data_hi, u32 data_lo, int common) 2623 u32 data_hi, u32 data_lo, int common)
@@ -2806,9 +3003,12 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
2806 int func = BP_FUNC(bp); 3003 int func = BP_FUNC(bp);
2807 3004
2808 REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0); 3005 REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
3006 val = SHMEM_RD(bp, func_mb[func].drv_status);
3007 if (val & DRV_STATUS_DCC_EVENT_MASK)
3008 bnx2x_dcc_event(bp,
3009 (val & DRV_STATUS_DCC_EVENT_MASK));
2809 bnx2x__link_status_update(bp); 3010 bnx2x__link_status_update(bp);
2810 if (SHMEM_RD(bp, func_mb[func].drv_status) & 3011 if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF))
2811 DRV_STATUS_PMF)
2812 bnx2x_pmf_update(bp); 3012 bnx2x_pmf_update(bp);
2813 3013
2814 } else if (attn & BNX2X_MC_ASSERT_BITS) { 3014 } else if (attn & BNX2X_MC_ASSERT_BITS) {
@@ -4968,47 +5168,6 @@ static void bnx2x_init_internal_port(struct bnx2x *bp)
4968 REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_HC_BTR_OFFSET(port), BNX2X_BTR); 5168 REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_HC_BTR_OFFSET(port), BNX2X_BTR);
4969} 5169}
4970 5170
4971/* Calculates the sum of vn_min_rates.
4972 It's needed for further normalizing of the min_rates.
4973 Returns:
4974 sum of vn_min_rates.
4975 or
4976 0 - if all the min_rates are 0.
4977 In the later case fainess algorithm should be deactivated.
4978 If not all min_rates are zero then those that are zeroes will be set to 1.
4979 */
4980static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
4981{
4982 int all_zero = 1;
4983 int port = BP_PORT(bp);
4984 int vn;
4985
4986 bp->vn_weight_sum = 0;
4987 for (vn = VN_0; vn < E1HVN_MAX; vn++) {
4988 int func = 2*vn + port;
4989 u32 vn_cfg =
4990 SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
4991 u32 vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
4992 FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
4993
4994 /* Skip hidden vns */
4995 if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE)
4996 continue;
4997
4998 /* If min rate is zero - set it to 1 */
4999 if (!vn_min_rate)
5000 vn_min_rate = DEF_MIN_RATE;
5001 else
5002 all_zero = 0;
5003
5004 bp->vn_weight_sum += vn_min_rate;
5005 }
5006
5007 /* ... only if all min rates are zeros - disable fairness */
5008 if (all_zero)
5009 bp->vn_weight_sum = 0;
5010}
5011
5012static void bnx2x_init_internal_func(struct bnx2x *bp) 5171static void bnx2x_init_internal_func(struct bnx2x *bp)
5013{ 5172{
5014 struct tstorm_eth_function_common_config tstorm_config = {0}; 5173 struct tstorm_eth_function_common_config tstorm_config = {0};
@@ -6272,44 +6431,6 @@ init_hw_err:
6272 return rc; 6431 return rc;
6273} 6432}
6274 6433
6275/* send the MCP a request, block until there is a reply */
6276u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
6277{
6278 int func = BP_FUNC(bp);
6279 u32 seq = ++bp->fw_seq;
6280 u32 rc = 0;
6281 u32 cnt = 1;
6282 u8 delay = CHIP_REV_IS_SLOW(bp) ? 100 : 10;
6283
6284 SHMEM_WR(bp, func_mb[func].drv_mb_header, (command | seq));
6285 DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq));
6286
6287 do {
6288 /* let the FW do it's magic ... */
6289 msleep(delay);
6290
6291 rc = SHMEM_RD(bp, func_mb[func].fw_mb_header);
6292
6293 /* Give the FW up to 2 second (200*10ms) */
6294 } while ((seq != (rc & FW_MSG_SEQ_NUMBER_MASK)) && (cnt++ < 200));
6295
6296 DP(BNX2X_MSG_MCP, "[after %d ms] read (%x) seq is (%x) from FW MB\n",
6297 cnt*delay, rc, seq);
6298
6299 /* is this a reply to our command? */
6300 if (seq == (rc & FW_MSG_SEQ_NUMBER_MASK)) {
6301 rc &= FW_MSG_CODE_MASK;
6302
6303 } else {
6304 /* FW BUG! */
6305 BNX2X_ERR("FW failed to respond!\n");
6306 bnx2x_fw_dump(bp);
6307 rc = 0;
6308 }
6309
6310 return rc;
6311}
6312
6313static void bnx2x_free_mem(struct bnx2x *bp) 6434static void bnx2x_free_mem(struct bnx2x *bp)
6314{ 6435{
6315 6436
@@ -6996,7 +7117,6 @@ static int bnx2x_set_int_mode(struct bnx2x *bp)
6996 return rc; 7117 return rc;
6997} 7118}
6998 7119
6999static void bnx2x_set_rx_mode(struct net_device *dev);
7000 7120
7001/* must be called with rtnl_lock */ 7121/* must be called with rtnl_lock */
7002static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) 7122static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
@@ -7103,6 +7223,12 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
7103 /* Setup NIC internals and enable interrupts */ 7223 /* Setup NIC internals and enable interrupts */
7104 bnx2x_nic_init(bp, load_code); 7224 bnx2x_nic_init(bp, load_code);
7105 7225
7226 if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) &&
7227 (bp->common.shmem2_base))
7228 SHMEM2_WR(bp, dcc_support,
7229 (SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV |
7230 SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV));
7231
7106 /* Send LOAD_DONE command to MCP */ 7232 /* Send LOAD_DONE command to MCP */
7107 if (!BP_NOMCP(bp)) { 7233 if (!BP_NOMCP(bp)) {
7108 load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE); 7234 load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE);
@@ -7735,8 +7861,10 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
7735 bp->common.flash_size, bp->common.flash_size); 7861 bp->common.flash_size, bp->common.flash_size);
7736 7862
7737 bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR); 7863 bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
7864 bp->common.shmem2_base = REG_RD(bp, MISC_REG_GENERIC_CR_0);
7738 bp->link_params.shmem_base = bp->common.shmem_base; 7865 bp->link_params.shmem_base = bp->common.shmem_base;
7739 BNX2X_DEV_INFO("shmem offset is 0x%x\n", bp->common.shmem_base); 7866 BNX2X_DEV_INFO("shmem offset 0x%x shmem2 offset 0x%x\n",
7867 bp->common.shmem_base, bp->common.shmem2_base);
7740 7868
7741 if (!bp->common.shmem_base || 7869 if (!bp->common.shmem_base ||
7742 (bp->common.shmem_base < 0xA0000) || 7870 (bp->common.shmem_base < 0xA0000) ||
@@ -8290,22 +8418,33 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
8290 bp->mf_config = 8418 bp->mf_config =
8291 SHMEM_RD(bp, mf_cfg.func_mf_config[func].config); 8419 SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
8292 8420
8293 val = (SHMEM_RD(bp, mf_cfg.func_mf_config[func].e1hov_tag) & 8421 val = (SHMEM_RD(bp, mf_cfg.func_mf_config[FUNC_0].e1hov_tag) &
8294 FUNC_MF_CFG_E1HOV_TAG_MASK); 8422 FUNC_MF_CFG_E1HOV_TAG_MASK);
8295 if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) { 8423 if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT)
8296
8297 bp->e1hov = val;
8298 bp->e1hmf = 1; 8424 bp->e1hmf = 1;
8299 BNX2X_DEV_INFO("MF mode E1HOV for func %d is %d " 8425 BNX2X_DEV_INFO("%s function mode\n",
8300 "(0x%04x)\n", 8426 IS_E1HMF(bp) ? "multi" : "single");
8301 func, bp->e1hov, bp->e1hov); 8427
8302 } else { 8428 if (IS_E1HMF(bp)) {
8303 BNX2X_DEV_INFO("single function mode\n"); 8429 val = (SHMEM_RD(bp, mf_cfg.func_mf_config[func].
8304 if (BP_E1HVN(bp)) { 8430 e1hov_tag) &
8431 FUNC_MF_CFG_E1HOV_TAG_MASK);
8432 if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
8433 bp->e1hov = val;
8434 BNX2X_DEV_INFO("E1HOV for func %d is %d "
8435 "(0x%04x)\n",
8436 func, bp->e1hov, bp->e1hov);
8437 } else {
8305 BNX2X_ERR("!!! No valid E1HOV for func %d," 8438 BNX2X_ERR("!!! No valid E1HOV for func %d,"
8306 " aborting\n", func); 8439 " aborting\n", func);
8307 rc = -EPERM; 8440 rc = -EPERM;
8308 } 8441 }
8442 } else {
8443 if (BP_E1HVN(bp)) {
8444 BNX2X_ERR("!!! VN %d in single function mode,"
8445 " aborting\n", BP_E1HVN(bp));
8446 rc = -EPERM;
8447 }
8309 } 8448 }
8310 } 8449 }
8311 8450