diff options
author | Eilon Greenstein <eilong@broadcom.com> | 2009-02-12 03:36:43 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-16 02:31:15 -0500 |
commit | 1c06328c0345638ea7532b45cadfe713c9e9781e (patch) | |
tree | f0bc6c0986f22802655b347367ff5222074870dc | |
parent | 8a1c38d17d88c8df3dcbea1c01a390ab2087f8ad (diff) |
bnx2x: Flow control enhancement
Setting better HW thresholds and enabling FW capabilities for better
enforcement. Also set the HW to more efficiently use the internal buffers if
this is a single port design
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/bnx2x.h | 2 | ||||
-rw-r--r-- | drivers/net/bnx2x_fw_defs.h | 5 | ||||
-rw-r--r-- | drivers/net/bnx2x_hsi.h | 35 | ||||
-rw-r--r-- | drivers/net/bnx2x_main.c | 96 | ||||
-rw-r--r-- | drivers/net/bnx2x_reg.h | 29 |
5 files changed, 157 insertions, 10 deletions
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index b40d4f127d3c..8c2124e0eaea 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h | |||
@@ -846,7 +846,7 @@ struct bnx2x { | |||
846 | u32 flags; | 846 | u32 flags; |
847 | #define PCIX_FLAG 1 | 847 | #define PCIX_FLAG 1 |
848 | #define PCI_32BIT_FLAG 2 | 848 | #define PCI_32BIT_FLAG 2 |
849 | #define ONE_TDMA_FLAG 4 /* no longer used */ | 849 | #define ONE_PORT_FLAG 4 |
850 | #define NO_WOL_FLAG 8 | 850 | #define NO_WOL_FLAG 8 |
851 | #define USING_DAC_FLAG 0x10 | 851 | #define USING_DAC_FLAG 0x10 |
852 | #define USING_MSIX_FLAG 0x20 | 852 | #define USING_MSIX_FLAG 0x20 |
diff --git a/drivers/net/bnx2x_fw_defs.h b/drivers/net/bnx2x_fw_defs.h index 59bb13262585..f6dacb03bdd6 100644 --- a/drivers/net/bnx2x_fw_defs.h +++ b/drivers/net/bnx2x_fw_defs.h | |||
@@ -107,6 +107,9 @@ | |||
107 | #define USTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(function) \ | 107 | #define USTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(function) \ |
108 | (IS_E1H_OFFSET ? (0x9508 + ((function>>1) * 0x40) + \ | 108 | (IS_E1H_OFFSET ? (0x9508 + ((function>>1) * 0x40) + \ |
109 | ((function&1) * 0x100)) : (0x1908 + (function * 0x40))) | 109 | ((function&1) * 0x100)) : (0x1908 + (function * 0x40))) |
110 | #define USTORM_ETH_RING_PAUSE_DATA_OFFSET(port, clientId) \ | ||
111 | (IS_E1H_OFFSET ? (0x8020 + (port * 0x4b0) + (clientId * 0x30)) : \ | ||
112 | 0xffffffff) | ||
110 | #define USTORM_ETH_STATS_QUERY_ADDR_OFFSET(function) \ | 113 | #define USTORM_ETH_STATS_QUERY_ADDR_OFFSET(function) \ |
111 | (IS_E1H_OFFSET ? (0x2a50 + (function * 0x8)) : (0x1d98 + \ | 114 | (IS_E1H_OFFSET ? (0x2a50 + (function * 0x8)) : (0x1d98 + \ |
112 | (function * 0x8))) | 115 | (function * 0x8))) |
@@ -120,6 +123,8 @@ | |||
120 | #define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(function) \ | 123 | #define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(function) \ |
121 | (IS_E1H_OFFSET ? (0x2408 + (function * 0x8)) : (0x5308 + \ | 124 | (IS_E1H_OFFSET ? (0x2408 + (function * 0x8)) : (0x5308 + \ |
122 | (function * 0x8))) | 125 | (function * 0x8))) |
126 | #define USTORM_PAUSE_ENABLED_OFFSET(port) \ | ||
127 | (IS_E1H_OFFSET ? (0x2ad4 + (port * 0x8)) : 0xffffffff) | ||
123 | #define USTORM_PER_COUNTER_ID_STATS_OFFSET(port, stats_counter_id) \ | 128 | #define USTORM_PER_COUNTER_ID_STATS_OFFSET(port, stats_counter_id) \ |
124 | (IS_E1H_OFFSET ? (0x2450 + (port * 0x2d0) + (stats_counter_id * \ | 129 | (IS_E1H_OFFSET ? (0x2450 + (port * 0x2d0) + (stats_counter_id * \ |
125 | 0x28)) : (0x4740 + (port * 0x2d0) + (stats_counter_id * 0x28))) | 130 | 0x28)) : (0x4740 + (port * 0x2d0) + (stats_counter_id * 0x28))) |
diff --git a/drivers/net/bnx2x_hsi.h b/drivers/net/bnx2x_hsi.h index a4a6039ef8cf..b0f41d1f9ab4 100644 --- a/drivers/net/bnx2x_hsi.h +++ b/drivers/net/bnx2x_hsi.h | |||
@@ -2615,6 +2615,41 @@ struct tstorm_eth_tpa_exist { | |||
2615 | 2615 | ||
2616 | 2616 | ||
2617 | /* | 2617 | /* |
2618 | * rx rings pause data for E1h only | ||
2619 | */ | ||
2620 | struct ustorm_eth_rx_pause_data_e1h { | ||
2621 | #if defined(__BIG_ENDIAN) | ||
2622 | u16 bd_thr_low; | ||
2623 | u16 cqe_thr_low; | ||
2624 | #elif defined(__LITTLE_ENDIAN) | ||
2625 | u16 cqe_thr_low; | ||
2626 | u16 bd_thr_low; | ||
2627 | #endif | ||
2628 | #if defined(__BIG_ENDIAN) | ||
2629 | u16 cos; | ||
2630 | u16 sge_thr_low; | ||
2631 | #elif defined(__LITTLE_ENDIAN) | ||
2632 | u16 sge_thr_low; | ||
2633 | u16 cos; | ||
2634 | #endif | ||
2635 | #if defined(__BIG_ENDIAN) | ||
2636 | u16 bd_thr_high; | ||
2637 | u16 cqe_thr_high; | ||
2638 | #elif defined(__LITTLE_ENDIAN) | ||
2639 | u16 cqe_thr_high; | ||
2640 | u16 bd_thr_high; | ||
2641 | #endif | ||
2642 | #if defined(__BIG_ENDIAN) | ||
2643 | u16 reserved0; | ||
2644 | u16 sge_thr_high; | ||
2645 | #elif defined(__LITTLE_ENDIAN) | ||
2646 | u16 sge_thr_high; | ||
2647 | u16 reserved0; | ||
2648 | #endif | ||
2649 | }; | ||
2650 | |||
2651 | |||
2652 | /* | ||
2618 | * Three RX producers for ETH | 2653 | * Three RX producers for ETH |
2619 | */ | 2654 | */ |
2620 | struct ustorm_eth_rx_producers { | 2655 | struct ustorm_eth_rx_producers { |
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ce55e84c44da..77793bba7a9f 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c | |||
@@ -2165,6 +2165,19 @@ static void bnx2x_link_attn(struct bnx2x *bp) | |||
2165 | 2165 | ||
2166 | if (bp->link_vars.link_up) { | 2166 | if (bp->link_vars.link_up) { |
2167 | 2167 | ||
2168 | /* dropless flow control */ | ||
2169 | if (CHIP_IS_E1H(bp)) { | ||
2170 | int port = BP_PORT(bp); | ||
2171 | u32 pause_enabled = 0; | ||
2172 | |||
2173 | if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX) | ||
2174 | pause_enabled = 1; | ||
2175 | |||
2176 | REG_WR(bp, BAR_USTRORM_INTMEM + | ||
2177 | USTORM_PAUSE_ENABLED_OFFSET(port), | ||
2178 | pause_enabled); | ||
2179 | } | ||
2180 | |||
2168 | if (bp->link_vars.mac_type == MAC_TYPE_BMAC) { | 2181 | if (bp->link_vars.mac_type == MAC_TYPE_BMAC) { |
2169 | struct host_port_stats *pstats; | 2182 | struct host_port_stats *pstats; |
2170 | 2183 | ||
@@ -4909,6 +4922,38 @@ static void bnx2x_init_internal_func(struct bnx2x *bp) | |||
4909 | max_agg_size); | 4922 | max_agg_size); |
4910 | } | 4923 | } |
4911 | 4924 | ||
4925 | /* dropless flow control */ | ||
4926 | if (CHIP_IS_E1H(bp)) { | ||
4927 | struct ustorm_eth_rx_pause_data_e1h rx_pause = {0}; | ||
4928 | |||
4929 | rx_pause.bd_thr_low = 250; | ||
4930 | rx_pause.cqe_thr_low = 250; | ||
4931 | rx_pause.cos = 1; | ||
4932 | rx_pause.sge_thr_low = 0; | ||
4933 | rx_pause.bd_thr_high = 350; | ||
4934 | rx_pause.cqe_thr_high = 350; | ||
4935 | rx_pause.sge_thr_high = 0; | ||
4936 | |||
4937 | for_each_rx_queue(bp, i) { | ||
4938 | struct bnx2x_fastpath *fp = &bp->fp[i]; | ||
4939 | |||
4940 | if (!fp->disable_tpa) { | ||
4941 | rx_pause.sge_thr_low = 150; | ||
4942 | rx_pause.sge_thr_high = 250; | ||
4943 | } | ||
4944 | |||
4945 | |||
4946 | offset = BAR_USTRORM_INTMEM + | ||
4947 | USTORM_ETH_RING_PAUSE_DATA_OFFSET(port, | ||
4948 | fp->cl_id); | ||
4949 | for (j = 0; | ||
4950 | j < sizeof(struct ustorm_eth_rx_pause_data_e1h)/4; | ||
4951 | j++) | ||
4952 | REG_WR(bp, offset + j*4, | ||
4953 | ((u32 *)&rx_pause)[j]); | ||
4954 | } | ||
4955 | } | ||
4956 | |||
4912 | memset(&(bp->cmng), 0, sizeof(struct cmng_struct_per_port)); | 4957 | memset(&(bp->cmng), 0, sizeof(struct cmng_struct_per_port)); |
4913 | 4958 | ||
4914 | /* Init rate shaping and fairness contexts */ | 4959 | /* Init rate shaping and fairness contexts */ |
@@ -5437,14 +5482,6 @@ static int bnx2x_init_common(struct bnx2x *bp) | |||
5437 | } | 5482 | } |
5438 | 5483 | ||
5439 | bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END); | 5484 | bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END); |
5440 | if (CHIP_REV_IS_SLOW(bp)) { | ||
5441 | /* fix for emulation and FPGA for no pause */ | ||
5442 | REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0, 513); | ||
5443 | REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_1, 513); | ||
5444 | REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0, 0); | ||
5445 | REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_1, 0); | ||
5446 | } | ||
5447 | |||
5448 | bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END); | 5485 | bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END); |
5449 | REG_WR(bp, PRS_REG_A_PRSU_20, 0xf); | 5486 | REG_WR(bp, PRS_REG_A_PRSU_20, 0xf); |
5450 | /* set NIC mode */ | 5487 | /* set NIC mode */ |
@@ -5626,6 +5663,7 @@ static int bnx2x_init_common(struct bnx2x *bp) | |||
5626 | static int bnx2x_init_port(struct bnx2x *bp) | 5663 | static int bnx2x_init_port(struct bnx2x *bp) |
5627 | { | 5664 | { |
5628 | int port = BP_PORT(bp); | 5665 | int port = BP_PORT(bp); |
5666 | u32 low, high; | ||
5629 | u32 val; | 5667 | u32 val; |
5630 | 5668 | ||
5631 | DP(BNX2X_MSG_MCP, "starting port init port %x\n", port); | 5669 | DP(BNX2X_MSG_MCP, "starting port init port %x\n", port); |
@@ -5672,7 +5710,32 @@ static int bnx2x_init_port(struct bnx2x *bp) | |||
5672 | func ? TIMERS_PORT1_END : TIMERS_PORT0_END); | 5710 | func ? TIMERS_PORT1_END : TIMERS_PORT0_END); |
5673 | #endif | 5711 | #endif |
5674 | /* Port DQ comes here */ | 5712 | /* Port DQ comes here */ |
5675 | /* Port BRB1 comes here */ | 5713 | |
5714 | bnx2x_init_block(bp, (port ? BRB1_PORT1_START : BRB1_PORT0_START), | ||
5715 | (port ? BRB1_PORT1_END : BRB1_PORT0_END)); | ||
5716 | if (CHIP_REV_IS_SLOW(bp) && !CHIP_IS_E1H(bp)) { | ||
5717 | /* no pause for emulation and FPGA */ | ||
5718 | low = 0; | ||
5719 | high = 513; | ||
5720 | } else { | ||
5721 | if (IS_E1HMF(bp)) | ||
5722 | low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246); | ||
5723 | else if (bp->dev->mtu > 4096) { | ||
5724 | if (bp->flags & ONE_PORT_FLAG) | ||
5725 | low = 160; | ||
5726 | else { | ||
5727 | val = bp->dev->mtu; | ||
5728 | /* (24*1024 + val*4)/256 */ | ||
5729 | low = 96 + (val/64) + ((val % 64) ? 1 : 0); | ||
5730 | } | ||
5731 | } else | ||
5732 | low = ((bp->flags & ONE_PORT_FLAG) ? 80 : 160); | ||
5733 | high = low + 56; /* 14*1024/256 */ | ||
5734 | } | ||
5735 | REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0 + port*4, low); | ||
5736 | REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0 + port*4, high); | ||
5737 | |||
5738 | |||
5676 | /* Port PRS comes here */ | 5739 | /* Port PRS comes here */ |
5677 | /* Port TSDM comes here */ | 5740 | /* Port TSDM comes here */ |
5678 | /* Port CSDM comes here */ | 5741 | /* Port CSDM comes here */ |
@@ -5754,6 +5817,14 @@ static int bnx2x_init_port(struct bnx2x *bp) | |||
5754 | REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK_MF + port*4, | 5817 | REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK_MF + port*4, |
5755 | (IS_E1HMF(bp) ? 0x1 : 0x2)); | 5818 | (IS_E1HMF(bp) ? 0x1 : 0x2)); |
5756 | 5819 | ||
5820 | /* support pause requests from USDM, TSDM and BRB */ | ||
5821 | REG_WR(bp, NIG_REG_LLFC_EGRESS_SRC_ENABLE_0 + port*4, 0x7); | ||
5822 | |||
5823 | { | ||
5824 | REG_WR(bp, NIG_REG_LLFC_ENABLE_0 + port*4, 0); | ||
5825 | REG_WR(bp, NIG_REG_LLFC_OUT_EN_0 + port*4, 0); | ||
5826 | REG_WR(bp, NIG_REG_PAUSE_ENABLE_0 + port*4, 1); | ||
5827 | } | ||
5757 | } | 5828 | } |
5758 | 5829 | ||
5759 | /* Port MCP comes here */ | 5830 | /* Port MCP comes here */ |
@@ -7331,6 +7402,13 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) | |||
7331 | bp->link_params.chip_id = bp->common.chip_id; | 7402 | bp->link_params.chip_id = bp->common.chip_id; |
7332 | BNX2X_DEV_INFO("chip ID is 0x%x\n", id); | 7403 | BNX2X_DEV_INFO("chip ID is 0x%x\n", id); |
7333 | 7404 | ||
7405 | val = (REG_RD(bp, 0x2874) & 0x55); | ||
7406 | if ((bp->common.chip_id & 0x1) || | ||
7407 | (CHIP_IS_E1(bp) && val) || (CHIP_IS_E1H(bp) && (val == 0x55))) { | ||
7408 | bp->flags |= ONE_PORT_FLAG; | ||
7409 | BNX2X_DEV_INFO("single port device\n"); | ||
7410 | } | ||
7411 | |||
7334 | val = REG_RD(bp, MCP_REG_MCPR_NVM_CFG4); | 7412 | val = REG_RD(bp, MCP_REG_MCPR_NVM_CFG4); |
7335 | bp->common.flash_size = (NVRAM_1MB_SIZE << | 7413 | bp->common.flash_size = (NVRAM_1MB_SIZE << |
7336 | (val & MCPR_NVM_CFG4_FLASH_SIZE)); | 7414 | (val & MCPR_NVM_CFG4_FLASH_SIZE)); |
diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h index b654d5d2a92b..713b5f9ea1e2 100644 --- a/drivers/net/bnx2x_reg.h +++ b/drivers/net/bnx2x_reg.h | |||
@@ -30,8 +30,20 @@ | |||
30 | address BRB1_IND_FREE_LIST_PRS_CRDT+1 initialize free tail. At address | 30 | address BRB1_IND_FREE_LIST_PRS_CRDT+1 initialize free tail. At address |
31 | BRB1_IND_FREE_LIST_PRS_CRDT+2 initialize parser initial credit. */ | 31 | BRB1_IND_FREE_LIST_PRS_CRDT+2 initialize parser initial credit. */ |
32 | #define BRB1_REG_FREE_LIST_PRS_CRDT 0x60200 | 32 | #define BRB1_REG_FREE_LIST_PRS_CRDT 0x60200 |
33 | /* [RW 10] The number of free blocks above which the High_llfc signal to | ||
34 | interface #n is de-asserted. */ | ||
35 | #define BRB1_REG_HIGH_LLFC_HIGH_THRESHOLD_0 0x6014c | ||
36 | /* [RW 10] The number of free blocks below which the High_llfc signal to | ||
37 | interface #n is asserted. */ | ||
38 | #define BRB1_REG_HIGH_LLFC_LOW_THRESHOLD_0 0x6013c | ||
33 | /* [RW 23] LL RAM data. */ | 39 | /* [RW 23] LL RAM data. */ |
34 | #define BRB1_REG_LL_RAM 0x61000 | 40 | #define BRB1_REG_LL_RAM 0x61000 |
41 | /* [RW 10] The number of free blocks above which the Low_llfc signal to | ||
42 | interface #n is de-asserted. */ | ||
43 | #define BRB1_REG_LOW_LLFC_HIGH_THRESHOLD_0 0x6016c | ||
44 | /* [RW 10] The number of free blocks below which the Low_llfc signal to | ||
45 | interface #n is asserted. */ | ||
46 | #define BRB1_REG_LOW_LLFC_LOW_THRESHOLD_0 0x6015c | ||
35 | /* [R 24] The number of full blocks. */ | 47 | /* [R 24] The number of full blocks. */ |
36 | #define BRB1_REG_NUM_OF_FULL_BLOCKS 0x60090 | 48 | #define BRB1_REG_NUM_OF_FULL_BLOCKS 0x60090 |
37 | /* [ST 32] The number of cycles that the write_full signal towards MAC #0 | 49 | /* [ST 32] The number of cycles that the write_full signal towards MAC #0 |
@@ -1684,6 +1696,19 @@ | |||
1684 | /* [RW 4] led mode for port0: 0 MAC; 1-3 PHY1; 4 MAC2; 5-7 PHY4; 8-MAC3; | 1696 | /* [RW 4] led mode for port0: 0 MAC; 1-3 PHY1; 4 MAC2; 5-7 PHY4; 8-MAC3; |
1685 | 9-11PHY7; 12 MAC4; 13-15 PHY10; */ | 1697 | 9-11PHY7; 12 MAC4; 13-15 PHY10; */ |
1686 | #define NIG_REG_LED_MODE_P0 0x102f0 | 1698 | #define NIG_REG_LED_MODE_P0 0x102f0 |
1699 | /* [RW 3] for port0 enable for llfc ppp and pause. b0 - brb1 enable; b1- | ||
1700 | tsdm enable; b2- usdm enable */ | ||
1701 | #define NIG_REG_LLFC_EGRESS_SRC_ENABLE_0 0x16070 | ||
1702 | /* [RW 1] SAFC enable for port0. This register may get 1 only when | ||
1703 | ~ppp_enable.ppp_enable = 0 and pause_enable.pause_enable =0 for the same | ||
1704 | port */ | ||
1705 | #define NIG_REG_LLFC_ENABLE_0 0x16208 | ||
1706 | /* [RW 16] classes are high-priority for port0 */ | ||
1707 | #define NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_0 0x16058 | ||
1708 | /* [RW 16] classes are low-priority for port0 */ | ||
1709 | #define NIG_REG_LLFC_LOW_PRIORITY_CLASSES_0 0x16060 | ||
1710 | /* [RW 1] Output enable of message to LLFC BMAC IF for port0 */ | ||
1711 | #define NIG_REG_LLFC_OUT_EN_0 0x160c8 | ||
1687 | #define NIG_REG_LLH0_ACPI_PAT_0_CRC 0x1015c | 1712 | #define NIG_REG_LLH0_ACPI_PAT_0_CRC 0x1015c |
1688 | #define NIG_REG_LLH0_ACPI_PAT_6_LEN 0x10154 | 1713 | #define NIG_REG_LLH0_ACPI_PAT_6_LEN 0x10154 |
1689 | #define NIG_REG_LLH0_BRB1_DRV_MASK 0x10244 | 1714 | #define NIG_REG_LLH0_BRB1_DRV_MASK 0x10244 |
@@ -1754,6 +1779,10 @@ | |||
1754 | #define NIG_REG_NIG_INT_STS_1 0x103c0 | 1779 | #define NIG_REG_NIG_INT_STS_1 0x103c0 |
1755 | /* [R 32] Parity register #0 read */ | 1780 | /* [R 32] Parity register #0 read */ |
1756 | #define NIG_REG_NIG_PRTY_STS 0x103d0 | 1781 | #define NIG_REG_NIG_PRTY_STS 0x103d0 |
1782 | /* [RW 1] Pause enable for port0. This register may get 1 only when | ||
1783 | ~safc_enable.safc_enable = 0 and ppp_enable.ppp_enable =0 for the same | ||
1784 | port */ | ||
1785 | #define NIG_REG_PAUSE_ENABLE_0 0x160c0 | ||
1757 | /* [RW 1] Input enable for RX PBF LP IF */ | 1786 | /* [RW 1] Input enable for RX PBF LP IF */ |
1758 | #define NIG_REG_PBF_LB_IN_EN 0x100b4 | 1787 | #define NIG_REG_PBF_LB_IN_EN 0x100b4 |
1759 | /* [RW 1] Value of this register will be transmitted to port swap when | 1788 | /* [RW 1] Value of this register will be transmitted to port swap when |