diff options
author | Eilon Greenstein <eilong@broadcom.com> | 2009-08-12 04:22:08 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-13 02:02:12 -0400 |
commit | 2691d51d7243560aa0870dadbf5c6b98f647f751 (patch) | |
tree | b1d19b51005395517e35c632501715edf7e20c7c /drivers/net | |
parent | a1d58179d1337ff8f8530c9fac8b9e98b2f7761f (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')
-rw-r--r-- | drivers/net/bnx2x.h | 6 | ||||
-rw-r--r-- | drivers/net/bnx2x_hsi.h | 34 | ||||
-rw-r--r-- | drivers/net/bnx2x_main.c | 325 |
3 files changed, 268 insertions, 97 deletions
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 16ccba8dda1b..5864ae2faabc 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h | |||
@@ -128,6 +128,11 @@ | |||
128 | #define SHMEM_RD(bp, field) REG_RD(bp, SHMEM_ADDR(bp, field)) | 128 | #define SHMEM_RD(bp, field) REG_RD(bp, SHMEM_ADDR(bp, field)) |
129 | #define SHMEM_WR(bp, field, val) REG_WR(bp, SHMEM_ADDR(bp, field), val) | 129 | #define SHMEM_WR(bp, field, val) REG_WR(bp, SHMEM_ADDR(bp, field), val) |
130 | 130 | ||
131 | #define SHMEM2_ADDR(bp, field) (bp->common.shmem2_base + \ | ||
132 | offsetof(struct shmem2_region, field)) | ||
133 | #define SHMEM2_RD(bp, field) REG_RD(bp, SHMEM2_ADDR(bp, field)) | ||
134 | #define SHMEM2_WR(bp, field, val) REG_WR(bp, SHMEM2_ADDR(bp, field), val) | ||
135 | |||
131 | #define EMAC_RD(bp, reg) REG_RD(bp, emac_base + reg) | 136 | #define EMAC_RD(bp, reg) REG_RD(bp, emac_base + reg) |
132 | #define EMAC_WR(bp, reg, val) REG_WR(bp, emac_base + reg, val) | 137 | #define EMAC_WR(bp, reg, val) REG_WR(bp, emac_base + reg, val) |
133 | 138 | ||
@@ -535,6 +540,7 @@ struct bnx2x_common { | |||
535 | #define NVRAM_PAGE_SIZE 256 | 540 | #define NVRAM_PAGE_SIZE 256 |
536 | 541 | ||
537 | u32 shmem_base; | 542 | u32 shmem_base; |
543 | u32 shmem2_base; | ||
538 | 544 | ||
539 | u32 hw_config; | 545 | u32 hw_config; |
540 | 546 | ||
diff --git a/drivers/net/bnx2x_hsi.h b/drivers/net/bnx2x_hsi.h index da62cc5608d3..8e2261fad485 100644 --- a/drivers/net/bnx2x_hsi.h +++ b/drivers/net/bnx2x_hsi.h | |||
@@ -658,6 +658,8 @@ struct drv_func_mb { | |||
658 | #define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS 0x20010000 | 658 | #define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS 0x20010000 |
659 | #define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP 0x20020000 | 659 | #define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP 0x20020000 |
660 | #define DRV_MSG_CODE_UNLOAD_DONE 0x21000000 | 660 | #define DRV_MSG_CODE_UNLOAD_DONE 0x21000000 |
661 | #define DRV_MSG_CODE_DCC_OK 0x30000000 | ||
662 | #define DRV_MSG_CODE_DCC_FAILURE 0x31000000 | ||
661 | #define DRV_MSG_CODE_DIAG_ENTER_REQ 0x50000000 | 663 | #define DRV_MSG_CODE_DIAG_ENTER_REQ 0x50000000 |
662 | #define DRV_MSG_CODE_DIAG_EXIT_REQ 0x60000000 | 664 | #define DRV_MSG_CODE_DIAG_EXIT_REQ 0x60000000 |
663 | #define DRV_MSG_CODE_VALIDATE_KEY 0x70000000 | 665 | #define DRV_MSG_CODE_VALIDATE_KEY 0x70000000 |
@@ -692,6 +694,7 @@ struct drv_func_mb { | |||
692 | #define FW_MSG_CODE_DRV_UNLOAD_PORT 0x20110000 | 694 | #define FW_MSG_CODE_DRV_UNLOAD_PORT 0x20110000 |
693 | #define FW_MSG_CODE_DRV_UNLOAD_FUNCTION 0x20120000 | 695 | #define FW_MSG_CODE_DRV_UNLOAD_FUNCTION 0x20120000 |
694 | #define FW_MSG_CODE_DRV_UNLOAD_DONE 0x21100000 | 696 | #define FW_MSG_CODE_DRV_UNLOAD_DONE 0x21100000 |
697 | #define FW_MSG_CODE_DCC_DONE 0x30100000 | ||
695 | #define FW_MSG_CODE_DIAG_ENTER_DONE 0x50100000 | 698 | #define FW_MSG_CODE_DIAG_ENTER_DONE 0x50100000 |
696 | #define FW_MSG_CODE_DIAG_REFUSE 0x50200000 | 699 | #define FW_MSG_CODE_DIAG_REFUSE 0x50200000 |
697 | #define FW_MSG_CODE_DIAG_EXIT_DONE 0x60100000 | 700 | #define FW_MSG_CODE_DIAG_EXIT_DONE 0x60100000 |
@@ -742,6 +745,14 @@ struct drv_func_mb { | |||
742 | u32 drv_status; | 745 | u32 drv_status; |
743 | #define DRV_STATUS_PMF 0x00000001 | 746 | #define DRV_STATUS_PMF 0x00000001 |
744 | 747 | ||
748 | #define DRV_STATUS_DCC_EVENT_MASK 0x0000ff00 | ||
749 | #define DRV_STATUS_DCC_DISABLE_ENABLE_PF 0x00000100 | ||
750 | #define DRV_STATUS_DCC_BANDWIDTH_ALLOCATION 0x00000200 | ||
751 | #define DRV_STATUS_DCC_CHANGE_MAC_ADDRESS 0x00000400 | ||
752 | #define DRV_STATUS_DCC_RESERVED1 0x00000800 | ||
753 | #define DRV_STATUS_DCC_SET_PROTOCOL 0x00001000 | ||
754 | #define DRV_STATUS_DCC_SET_PRIORITY 0x00002000 | ||
755 | |||
745 | u32 virt_mac_upper; | 756 | u32 virt_mac_upper; |
746 | #define VIRT_MAC_SIGN_MASK 0xffff0000 | 757 | #define VIRT_MAC_SIGN_MASK 0xffff0000 |
747 | #define VIRT_MAC_SIGNATURE 0x564d0000 | 758 | #define VIRT_MAC_SIGNATURE 0x564d0000 |
@@ -778,10 +789,9 @@ struct shared_mf_cfg { | |||
778 | struct port_mf_cfg { | 789 | struct port_mf_cfg { |
779 | 790 | ||
780 | u32 dynamic_cfg; /* device control channel */ | 791 | u32 dynamic_cfg; /* device control channel */ |
781 | #define PORT_MF_CFG_OUTER_VLAN_TAG_MASK 0x0000ffff | 792 | #define PORT_MF_CFG_E1HOV_TAG_MASK 0x0000ffff |
782 | #define PORT_MF_CFG_OUTER_VLAN_TAG_SHIFT 0 | 793 | #define PORT_MF_CFG_E1HOV_TAG_SHIFT 0 |
783 | #define PORT_MF_CFG_DYNAMIC_CFG_ENABLED 0x00010000 | 794 | #define PORT_MF_CFG_E1HOV_TAG_DEFAULT PORT_MF_CFG_E1HOV_TAG_MASK |
784 | #define PORT_MF_CFG_DYNAMIC_CFG_DEFAULT 0x00000000 | ||
785 | 795 | ||
786 | u32 reserved[3]; | 796 | u32 reserved[3]; |
787 | 797 | ||
@@ -885,6 +895,22 @@ struct shmem_region { /* SharedMem Offset (size) */ | |||
885 | }; /* 0x6dc */ | 895 | }; /* 0x6dc */ |
886 | 896 | ||
887 | 897 | ||
898 | struct shmem2_region { | ||
899 | |||
900 | u32 size; | ||
901 | |||
902 | u32 dcc_support; | ||
903 | #define SHMEM_DCC_SUPPORT_NONE 0x00000000 | ||
904 | #define SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV 0x00000001 | ||
905 | #define SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV 0x00000004 | ||
906 | #define SHMEM_DCC_SUPPORT_CHANGE_MAC_ADDRESS_TLV 0x00000008 | ||
907 | #define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV 0x00000040 | ||
908 | #define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV 0x00000080 | ||
909 | #define SHMEM_DCC_SUPPORT_DEFAULT SHMEM_DCC_SUPPORT_NONE | ||
910 | |||
911 | }; | ||
912 | |||
913 | |||
888 | struct emac_stats { | 914 | struct emac_stats { |
889 | u32 rx_stat_ifhcinoctets; | 915 | u32 rx_stat_ifhcinoctets; |
890 | u32 rx_stat_ifhcinbadoctets; | 916 | u32 rx_stat_ifhcinbadoctets; |
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 | ||
2105 | static void bnx2x_link_report(struct bnx2x *bp) | 2105 | static 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 | */ | ||
2258 | static 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 | |||
2243 | static void bnx2x_init_vn_minmax(struct bnx2x *bp, int func) | 2289 | static 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 | ||
2384 | static void bnx2x__link_status_update(struct bnx2x *bp) | 2430 | static 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 */ | ||
2476 | u32 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 | |||
2512 | static void bnx2x_set_storm_rx_mode(struct bnx2x *bp); | ||
2513 | static void bnx2x_set_mac_addr_e1h(struct bnx2x *bp, int set); | ||
2514 | static void bnx2x_set_rx_mode(struct net_device *dev); | ||
2515 | |||
2516 | static 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 | |||
2537 | static 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 | |||
2552 | static 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 | |||
2586 | static 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 */ |
2425 | static int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, | 2622 | static 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 | */ | ||
4980 | static 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 | |||
5012 | static void bnx2x_init_internal_func(struct bnx2x *bp) | 5171 | static 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 */ | ||
6276 | u32 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 | |||
6313 | static void bnx2x_free_mem(struct bnx2x *bp) | 6434 | static 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 | ||
6999 | static 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 */ |
7002 | static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) | 7122 | static 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 | ||