diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/net/bnx2x/bnx2x_ethtool.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/net/bnx2x/bnx2x_ethtool.c')
-rw-r--r-- | drivers/net/bnx2x/bnx2x_ethtool.c | 958 |
1 files changed, 563 insertions, 395 deletions
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index 8b75b05e34c5..727fe89ff37f 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* bnx2x_ethtool.c: Broadcom Everest network driver. | 1 | /* bnx2x_ethtool.c: Broadcom Everest network driver. |
2 | * | 2 | * |
3 | * Copyright (c) 2007-2010 Broadcom Corporation | 3 | * Copyright (c) 2007-2011 Broadcom Corporation |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -24,71 +24,181 @@ | |||
24 | #include "bnx2x.h" | 24 | #include "bnx2x.h" |
25 | #include "bnx2x_cmn.h" | 25 | #include "bnx2x_cmn.h" |
26 | #include "bnx2x_dump.h" | 26 | #include "bnx2x_dump.h" |
27 | #include "bnx2x_init.h" | ||
27 | 28 | ||
29 | /* Note: in the format strings below %s is replaced by the queue-name which is | ||
30 | * either its index or 'fcoe' for the fcoe queue. Make sure the format string | ||
31 | * length does not exceed ETH_GSTRING_LEN - MAX_QUEUE_NAME_LEN + 2 | ||
32 | */ | ||
33 | #define MAX_QUEUE_NAME_LEN 4 | ||
34 | static const struct { | ||
35 | long offset; | ||
36 | int size; | ||
37 | char string[ETH_GSTRING_LEN]; | ||
38 | } bnx2x_q_stats_arr[] = { | ||
39 | /* 1 */ { Q_STATS_OFFSET32(total_bytes_received_hi), 8, "[%s]: rx_bytes" }, | ||
40 | { Q_STATS_OFFSET32(error_bytes_received_hi), | ||
41 | 8, "[%s]: rx_error_bytes" }, | ||
42 | { Q_STATS_OFFSET32(total_unicast_packets_received_hi), | ||
43 | 8, "[%s]: rx_ucast_packets" }, | ||
44 | { Q_STATS_OFFSET32(total_multicast_packets_received_hi), | ||
45 | 8, "[%s]: rx_mcast_packets" }, | ||
46 | { Q_STATS_OFFSET32(total_broadcast_packets_received_hi), | ||
47 | 8, "[%s]: rx_bcast_packets" }, | ||
48 | { Q_STATS_OFFSET32(no_buff_discard_hi), 8, "[%s]: rx_discards" }, | ||
49 | { Q_STATS_OFFSET32(rx_err_discard_pkt), | ||
50 | 4, "[%s]: rx_phy_ip_err_discards"}, | ||
51 | { Q_STATS_OFFSET32(rx_skb_alloc_failed), | ||
52 | 4, "[%s]: rx_skb_alloc_discard" }, | ||
53 | { Q_STATS_OFFSET32(hw_csum_err), 4, "[%s]: rx_csum_offload_errors" }, | ||
54 | |||
55 | /* 10 */{ Q_STATS_OFFSET32(total_bytes_transmitted_hi), 8, "[%s]: tx_bytes" }, | ||
56 | { Q_STATS_OFFSET32(total_unicast_packets_transmitted_hi), | ||
57 | 8, "[%s]: tx_ucast_packets" }, | ||
58 | { Q_STATS_OFFSET32(total_multicast_packets_transmitted_hi), | ||
59 | 8, "[%s]: tx_mcast_packets" }, | ||
60 | { Q_STATS_OFFSET32(total_broadcast_packets_transmitted_hi), | ||
61 | 8, "[%s]: tx_bcast_packets" } | ||
62 | }; | ||
63 | |||
64 | #define BNX2X_NUM_Q_STATS ARRAY_SIZE(bnx2x_q_stats_arr) | ||
65 | |||
66 | static const struct { | ||
67 | long offset; | ||
68 | int size; | ||
69 | u32 flags; | ||
70 | #define STATS_FLAGS_PORT 1 | ||
71 | #define STATS_FLAGS_FUNC 2 | ||
72 | #define STATS_FLAGS_BOTH (STATS_FLAGS_FUNC | STATS_FLAGS_PORT) | ||
73 | char string[ETH_GSTRING_LEN]; | ||
74 | } bnx2x_stats_arr[] = { | ||
75 | /* 1 */ { STATS_OFFSET32(total_bytes_received_hi), | ||
76 | 8, STATS_FLAGS_BOTH, "rx_bytes" }, | ||
77 | { STATS_OFFSET32(error_bytes_received_hi), | ||
78 | 8, STATS_FLAGS_BOTH, "rx_error_bytes" }, | ||
79 | { STATS_OFFSET32(total_unicast_packets_received_hi), | ||
80 | 8, STATS_FLAGS_BOTH, "rx_ucast_packets" }, | ||
81 | { STATS_OFFSET32(total_multicast_packets_received_hi), | ||
82 | 8, STATS_FLAGS_BOTH, "rx_mcast_packets" }, | ||
83 | { STATS_OFFSET32(total_broadcast_packets_received_hi), | ||
84 | 8, STATS_FLAGS_BOTH, "rx_bcast_packets" }, | ||
85 | { STATS_OFFSET32(rx_stat_dot3statsfcserrors_hi), | ||
86 | 8, STATS_FLAGS_PORT, "rx_crc_errors" }, | ||
87 | { STATS_OFFSET32(rx_stat_dot3statsalignmenterrors_hi), | ||
88 | 8, STATS_FLAGS_PORT, "rx_align_errors" }, | ||
89 | { STATS_OFFSET32(rx_stat_etherstatsundersizepkts_hi), | ||
90 | 8, STATS_FLAGS_PORT, "rx_undersize_packets" }, | ||
91 | { STATS_OFFSET32(etherstatsoverrsizepkts_hi), | ||
92 | 8, STATS_FLAGS_PORT, "rx_oversize_packets" }, | ||
93 | /* 10 */{ STATS_OFFSET32(rx_stat_etherstatsfragments_hi), | ||
94 | 8, STATS_FLAGS_PORT, "rx_fragments" }, | ||
95 | { STATS_OFFSET32(rx_stat_etherstatsjabbers_hi), | ||
96 | 8, STATS_FLAGS_PORT, "rx_jabbers" }, | ||
97 | { STATS_OFFSET32(no_buff_discard_hi), | ||
98 | 8, STATS_FLAGS_BOTH, "rx_discards" }, | ||
99 | { STATS_OFFSET32(mac_filter_discard), | ||
100 | 4, STATS_FLAGS_PORT, "rx_filtered_packets" }, | ||
101 | { STATS_OFFSET32(xxoverflow_discard), | ||
102 | 4, STATS_FLAGS_PORT, "rx_fw_discards" }, | ||
103 | { STATS_OFFSET32(brb_drop_hi), | ||
104 | 8, STATS_FLAGS_PORT, "rx_brb_discard" }, | ||
105 | { STATS_OFFSET32(brb_truncate_hi), | ||
106 | 8, STATS_FLAGS_PORT, "rx_brb_truncate" }, | ||
107 | { STATS_OFFSET32(pause_frames_received_hi), | ||
108 | 8, STATS_FLAGS_PORT, "rx_pause_frames" }, | ||
109 | { STATS_OFFSET32(rx_stat_maccontrolframesreceived_hi), | ||
110 | 8, STATS_FLAGS_PORT, "rx_mac_ctrl_frames" }, | ||
111 | { STATS_OFFSET32(nig_timer_max), | ||
112 | 4, STATS_FLAGS_PORT, "rx_constant_pause_events" }, | ||
113 | /* 20 */{ STATS_OFFSET32(rx_err_discard_pkt), | ||
114 | 4, STATS_FLAGS_BOTH, "rx_phy_ip_err_discards"}, | ||
115 | { STATS_OFFSET32(rx_skb_alloc_failed), | ||
116 | 4, STATS_FLAGS_BOTH, "rx_skb_alloc_discard" }, | ||
117 | { STATS_OFFSET32(hw_csum_err), | ||
118 | 4, STATS_FLAGS_BOTH, "rx_csum_offload_errors" }, | ||
119 | |||
120 | { STATS_OFFSET32(total_bytes_transmitted_hi), | ||
121 | 8, STATS_FLAGS_BOTH, "tx_bytes" }, | ||
122 | { STATS_OFFSET32(tx_stat_ifhcoutbadoctets_hi), | ||
123 | 8, STATS_FLAGS_PORT, "tx_error_bytes" }, | ||
124 | { STATS_OFFSET32(total_unicast_packets_transmitted_hi), | ||
125 | 8, STATS_FLAGS_BOTH, "tx_ucast_packets" }, | ||
126 | { STATS_OFFSET32(total_multicast_packets_transmitted_hi), | ||
127 | 8, STATS_FLAGS_BOTH, "tx_mcast_packets" }, | ||
128 | { STATS_OFFSET32(total_broadcast_packets_transmitted_hi), | ||
129 | 8, STATS_FLAGS_BOTH, "tx_bcast_packets" }, | ||
130 | { STATS_OFFSET32(tx_stat_dot3statsinternalmactransmiterrors_hi), | ||
131 | 8, STATS_FLAGS_PORT, "tx_mac_errors" }, | ||
132 | { STATS_OFFSET32(rx_stat_dot3statscarriersenseerrors_hi), | ||
133 | 8, STATS_FLAGS_PORT, "tx_carrier_errors" }, | ||
134 | /* 30 */{ STATS_OFFSET32(tx_stat_dot3statssinglecollisionframes_hi), | ||
135 | 8, STATS_FLAGS_PORT, "tx_single_collisions" }, | ||
136 | { STATS_OFFSET32(tx_stat_dot3statsmultiplecollisionframes_hi), | ||
137 | 8, STATS_FLAGS_PORT, "tx_multi_collisions" }, | ||
138 | { STATS_OFFSET32(tx_stat_dot3statsdeferredtransmissions_hi), | ||
139 | 8, STATS_FLAGS_PORT, "tx_deferred" }, | ||
140 | { STATS_OFFSET32(tx_stat_dot3statsexcessivecollisions_hi), | ||
141 | 8, STATS_FLAGS_PORT, "tx_excess_collisions" }, | ||
142 | { STATS_OFFSET32(tx_stat_dot3statslatecollisions_hi), | ||
143 | 8, STATS_FLAGS_PORT, "tx_late_collisions" }, | ||
144 | { STATS_OFFSET32(tx_stat_etherstatscollisions_hi), | ||
145 | 8, STATS_FLAGS_PORT, "tx_total_collisions" }, | ||
146 | { STATS_OFFSET32(tx_stat_etherstatspkts64octets_hi), | ||
147 | 8, STATS_FLAGS_PORT, "tx_64_byte_packets" }, | ||
148 | { STATS_OFFSET32(tx_stat_etherstatspkts65octetsto127octets_hi), | ||
149 | 8, STATS_FLAGS_PORT, "tx_65_to_127_byte_packets" }, | ||
150 | { STATS_OFFSET32(tx_stat_etherstatspkts128octetsto255octets_hi), | ||
151 | 8, STATS_FLAGS_PORT, "tx_128_to_255_byte_packets" }, | ||
152 | { STATS_OFFSET32(tx_stat_etherstatspkts256octetsto511octets_hi), | ||
153 | 8, STATS_FLAGS_PORT, "tx_256_to_511_byte_packets" }, | ||
154 | /* 40 */{ STATS_OFFSET32(tx_stat_etherstatspkts512octetsto1023octets_hi), | ||
155 | 8, STATS_FLAGS_PORT, "tx_512_to_1023_byte_packets" }, | ||
156 | { STATS_OFFSET32(etherstatspkts1024octetsto1522octets_hi), | ||
157 | 8, STATS_FLAGS_PORT, "tx_1024_to_1522_byte_packets" }, | ||
158 | { STATS_OFFSET32(etherstatspktsover1522octets_hi), | ||
159 | 8, STATS_FLAGS_PORT, "tx_1523_to_9022_byte_packets" }, | ||
160 | { STATS_OFFSET32(pause_frames_sent_hi), | ||
161 | 8, STATS_FLAGS_PORT, "tx_pause_frames" } | ||
162 | }; | ||
163 | |||
164 | #define BNX2X_NUM_STATS ARRAY_SIZE(bnx2x_stats_arr) | ||
28 | 165 | ||
29 | static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 166 | static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
30 | { | 167 | { |
31 | struct bnx2x *bp = netdev_priv(dev); | 168 | struct bnx2x *bp = netdev_priv(dev); |
169 | int cfg_idx = bnx2x_get_link_cfg_idx(bp); | ||
32 | 170 | ||
33 | cmd->supported = bp->port.supported; | 171 | /* Dual Media boards present all available port types */ |
34 | cmd->advertising = bp->port.advertising; | 172 | cmd->supported = bp->port.supported[cfg_idx] | |
173 | (bp->port.supported[cfg_idx ^ 1] & | ||
174 | (SUPPORTED_TP | SUPPORTED_FIBRE)); | ||
175 | cmd->advertising = bp->port.advertising[cfg_idx]; | ||
35 | 176 | ||
36 | if ((bp->state == BNX2X_STATE_OPEN) && | 177 | if ((bp->state == BNX2X_STATE_OPEN) && |
37 | !(bp->flags & MF_FUNC_DIS) && | 178 | !(bp->flags & MF_FUNC_DIS) && |
38 | (bp->link_vars.link_up)) { | 179 | (bp->link_vars.link_up)) { |
39 | cmd->speed = bp->link_vars.line_speed; | 180 | ethtool_cmd_speed_set(cmd, bp->link_vars.line_speed); |
40 | cmd->duplex = bp->link_vars.duplex; | 181 | cmd->duplex = bp->link_vars.duplex; |
41 | if (IS_E1HMF(bp)) { | ||
42 | u16 vn_max_rate; | ||
43 | |||
44 | vn_max_rate = | ||
45 | ((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >> | ||
46 | FUNC_MF_CFG_MAX_BW_SHIFT) * 100; | ||
47 | if (vn_max_rate < cmd->speed) | ||
48 | cmd->speed = vn_max_rate; | ||
49 | } | ||
50 | } else { | 182 | } else { |
51 | cmd->speed = -1; | 183 | ethtool_cmd_speed_set( |
52 | cmd->duplex = -1; | 184 | cmd, bp->link_params.req_line_speed[cfg_idx]); |
185 | cmd->duplex = bp->link_params.req_duplex[cfg_idx]; | ||
53 | } | 186 | } |
54 | 187 | ||
55 | if (bp->link_params.switch_cfg == SWITCH_CFG_10G) { | 188 | if (IS_MF(bp)) |
56 | u32 ext_phy_type = | 189 | ethtool_cmd_speed_set(cmd, bnx2x_get_mf_speed(bp)); |
57 | XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config); | ||
58 | |||
59 | switch (ext_phy_type) { | ||
60 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: | ||
61 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: | ||
62 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: | ||
63 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: | ||
64 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: | ||
65 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: | ||
66 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727: | ||
67 | cmd->port = PORT_FIBRE; | ||
68 | break; | ||
69 | |||
70 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: | ||
71 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481: | ||
72 | cmd->port = PORT_TP; | ||
73 | break; | ||
74 | 190 | ||
75 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE: | 191 | if (bp->port.supported[cfg_idx] & SUPPORTED_TP) |
76 | BNX2X_ERR("XGXS PHY Failure detected 0x%x\n", | ||
77 | bp->link_params.ext_phy_config); | ||
78 | break; | ||
79 | |||
80 | default: | ||
81 | DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n", | ||
82 | bp->link_params.ext_phy_config); | ||
83 | break; | ||
84 | } | ||
85 | } else | ||
86 | cmd->port = PORT_TP; | 192 | cmd->port = PORT_TP; |
193 | else if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE) | ||
194 | cmd->port = PORT_FIBRE; | ||
195 | else | ||
196 | BNX2X_ERR("XGXS PHY Failure detected\n"); | ||
87 | 197 | ||
88 | cmd->phy_address = bp->mdio.prtad; | 198 | cmd->phy_address = bp->mdio.prtad; |
89 | cmd->transceiver = XCVR_INTERNAL; | 199 | cmd->transceiver = XCVR_INTERNAL; |
90 | 200 | ||
91 | if (bp->link_params.req_line_speed == SPEED_AUTO_NEG) | 201 | if (bp->link_params.req_line_speed[cfg_idx] == SPEED_AUTO_NEG) |
92 | cmd->autoneg = AUTONEG_ENABLE; | 202 | cmd->autoneg = AUTONEG_ENABLE; |
93 | else | 203 | else |
94 | cmd->autoneg = AUTONEG_DISABLE; | 204 | cmd->autoneg = AUTONEG_DISABLE; |
@@ -97,10 +207,11 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
97 | cmd->maxrxpkt = 0; | 207 | cmd->maxrxpkt = 0; |
98 | 208 | ||
99 | DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n" | 209 | DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n" |
100 | DP_LEVEL " supported 0x%x advertising 0x%x speed %d\n" | 210 | DP_LEVEL " supported 0x%x advertising 0x%x speed %u\n" |
101 | DP_LEVEL " duplex %d port %d phy_address %d transceiver %d\n" | 211 | DP_LEVEL " duplex %d port %d phy_address %d transceiver %d\n" |
102 | DP_LEVEL " autoneg %d maxtxpkt %d maxrxpkt %d\n", | 212 | DP_LEVEL " autoneg %d maxtxpkt %d maxrxpkt %d\n", |
103 | cmd->cmd, cmd->supported, cmd->advertising, cmd->speed, | 213 | cmd->cmd, cmd->supported, cmd->advertising, |
214 | ethtool_cmd_speed(cmd), | ||
104 | cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver, | 215 | cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver, |
105 | cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt); | 216 | cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt); |
106 | 217 | ||
@@ -110,39 +221,129 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
110 | static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 221 | static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
111 | { | 222 | { |
112 | struct bnx2x *bp = netdev_priv(dev); | 223 | struct bnx2x *bp = netdev_priv(dev); |
113 | u32 advertising; | 224 | u32 advertising, cfg_idx, old_multi_phy_config, new_multi_phy_config; |
225 | u32 speed; | ||
114 | 226 | ||
115 | if (IS_E1HMF(bp)) | 227 | if (IS_MF_SD(bp)) |
116 | return 0; | 228 | return 0; |
117 | 229 | ||
118 | DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n" | 230 | DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n" |
119 | DP_LEVEL " supported 0x%x advertising 0x%x speed %d\n" | 231 | " supported 0x%x advertising 0x%x speed %u\n" |
120 | DP_LEVEL " duplex %d port %d phy_address %d transceiver %d\n" | 232 | " duplex %d port %d phy_address %d transceiver %d\n" |
121 | DP_LEVEL " autoneg %d maxtxpkt %d maxrxpkt %d\n", | 233 | " autoneg %d maxtxpkt %d maxrxpkt %d\n", |
122 | cmd->cmd, cmd->supported, cmd->advertising, cmd->speed, | 234 | cmd->cmd, cmd->supported, cmd->advertising, |
235 | ethtool_cmd_speed(cmd), | ||
123 | cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver, | 236 | cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver, |
124 | cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt); | 237 | cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt); |
125 | 238 | ||
239 | speed = ethtool_cmd_speed(cmd); | ||
240 | |||
241 | if (IS_MF_SI(bp)) { | ||
242 | u32 part; | ||
243 | u32 line_speed = bp->link_vars.line_speed; | ||
244 | |||
245 | /* use 10G if no link detected */ | ||
246 | if (!line_speed) | ||
247 | line_speed = 10000; | ||
248 | |||
249 | if (bp->common.bc_ver < REQ_BC_VER_4_SET_MF_BW) { | ||
250 | BNX2X_DEV_INFO("To set speed BC %X or higher " | ||
251 | "is required, please upgrade BC\n", | ||
252 | REQ_BC_VER_4_SET_MF_BW); | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | part = (speed * 100) / line_speed; | ||
257 | |||
258 | if (line_speed < speed || !part) { | ||
259 | BNX2X_DEV_INFO("Speed setting should be in a range " | ||
260 | "from 1%% to 100%% " | ||
261 | "of actual line speed\n"); | ||
262 | return -EINVAL; | ||
263 | } | ||
264 | |||
265 | if (bp->state != BNX2X_STATE_OPEN) | ||
266 | /* store value for following "load" */ | ||
267 | bp->pending_max = part; | ||
268 | else | ||
269 | bnx2x_update_max_mf_config(bp, part); | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | cfg_idx = bnx2x_get_link_cfg_idx(bp); | ||
275 | old_multi_phy_config = bp->link_params.multi_phy_config; | ||
276 | switch (cmd->port) { | ||
277 | case PORT_TP: | ||
278 | if (bp->port.supported[cfg_idx] & SUPPORTED_TP) | ||
279 | break; /* no port change */ | ||
280 | |||
281 | if (!(bp->port.supported[0] & SUPPORTED_TP || | ||
282 | bp->port.supported[1] & SUPPORTED_TP)) { | ||
283 | DP(NETIF_MSG_LINK, "Unsupported port type\n"); | ||
284 | return -EINVAL; | ||
285 | } | ||
286 | bp->link_params.multi_phy_config &= | ||
287 | ~PORT_HW_CFG_PHY_SELECTION_MASK; | ||
288 | if (bp->link_params.multi_phy_config & | ||
289 | PORT_HW_CFG_PHY_SWAPPED_ENABLED) | ||
290 | bp->link_params.multi_phy_config |= | ||
291 | PORT_HW_CFG_PHY_SELECTION_SECOND_PHY; | ||
292 | else | ||
293 | bp->link_params.multi_phy_config |= | ||
294 | PORT_HW_CFG_PHY_SELECTION_FIRST_PHY; | ||
295 | break; | ||
296 | case PORT_FIBRE: | ||
297 | if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE) | ||
298 | break; /* no port change */ | ||
299 | |||
300 | if (!(bp->port.supported[0] & SUPPORTED_FIBRE || | ||
301 | bp->port.supported[1] & SUPPORTED_FIBRE)) { | ||
302 | DP(NETIF_MSG_LINK, "Unsupported port type\n"); | ||
303 | return -EINVAL; | ||
304 | } | ||
305 | bp->link_params.multi_phy_config &= | ||
306 | ~PORT_HW_CFG_PHY_SELECTION_MASK; | ||
307 | if (bp->link_params.multi_phy_config & | ||
308 | PORT_HW_CFG_PHY_SWAPPED_ENABLED) | ||
309 | bp->link_params.multi_phy_config |= | ||
310 | PORT_HW_CFG_PHY_SELECTION_FIRST_PHY; | ||
311 | else | ||
312 | bp->link_params.multi_phy_config |= | ||
313 | PORT_HW_CFG_PHY_SELECTION_SECOND_PHY; | ||
314 | break; | ||
315 | default: | ||
316 | DP(NETIF_MSG_LINK, "Unsupported port type\n"); | ||
317 | return -EINVAL; | ||
318 | } | ||
319 | /* Save new config in case command complete successuly */ | ||
320 | new_multi_phy_config = bp->link_params.multi_phy_config; | ||
321 | /* Get the new cfg_idx */ | ||
322 | cfg_idx = bnx2x_get_link_cfg_idx(bp); | ||
323 | /* Restore old config in case command failed */ | ||
324 | bp->link_params.multi_phy_config = old_multi_phy_config; | ||
325 | DP(NETIF_MSG_LINK, "cfg_idx = %x\n", cfg_idx); | ||
326 | |||
126 | if (cmd->autoneg == AUTONEG_ENABLE) { | 327 | if (cmd->autoneg == AUTONEG_ENABLE) { |
127 | if (!(bp->port.supported & SUPPORTED_Autoneg)) { | 328 | if (!(bp->port.supported[cfg_idx] & SUPPORTED_Autoneg)) { |
128 | DP(NETIF_MSG_LINK, "Autoneg not supported\n"); | 329 | DP(NETIF_MSG_LINK, "Autoneg not supported\n"); |
129 | return -EINVAL; | 330 | return -EINVAL; |
130 | } | 331 | } |
131 | 332 | ||
132 | /* advertise the requested speed and duplex if supported */ | 333 | /* advertise the requested speed and duplex if supported */ |
133 | cmd->advertising &= bp->port.supported; | 334 | cmd->advertising &= bp->port.supported[cfg_idx]; |
134 | 335 | ||
135 | bp->link_params.req_line_speed = SPEED_AUTO_NEG; | 336 | bp->link_params.req_line_speed[cfg_idx] = SPEED_AUTO_NEG; |
136 | bp->link_params.req_duplex = DUPLEX_FULL; | 337 | bp->link_params.req_duplex[cfg_idx] = DUPLEX_FULL; |
137 | bp->port.advertising |= (ADVERTISED_Autoneg | | 338 | bp->port.advertising[cfg_idx] |= (ADVERTISED_Autoneg | |
138 | cmd->advertising); | 339 | cmd->advertising); |
139 | 340 | ||
140 | } else { /* forced speed */ | 341 | } else { /* forced speed */ |
141 | /* advertise the requested speed and duplex if supported */ | 342 | /* advertise the requested speed and duplex if supported */ |
142 | switch (cmd->speed) { | 343 | switch (speed) { |
143 | case SPEED_10: | 344 | case SPEED_10: |
144 | if (cmd->duplex == DUPLEX_FULL) { | 345 | if (cmd->duplex == DUPLEX_FULL) { |
145 | if (!(bp->port.supported & | 346 | if (!(bp->port.supported[cfg_idx] & |
146 | SUPPORTED_10baseT_Full)) { | 347 | SUPPORTED_10baseT_Full)) { |
147 | DP(NETIF_MSG_LINK, | 348 | DP(NETIF_MSG_LINK, |
148 | "10M full not supported\n"); | 349 | "10M full not supported\n"); |
@@ -152,7 +353,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
152 | advertising = (ADVERTISED_10baseT_Full | | 353 | advertising = (ADVERTISED_10baseT_Full | |
153 | ADVERTISED_TP); | 354 | ADVERTISED_TP); |
154 | } else { | 355 | } else { |
155 | if (!(bp->port.supported & | 356 | if (!(bp->port.supported[cfg_idx] & |
156 | SUPPORTED_10baseT_Half)) { | 357 | SUPPORTED_10baseT_Half)) { |
157 | DP(NETIF_MSG_LINK, | 358 | DP(NETIF_MSG_LINK, |
158 | "10M half not supported\n"); | 359 | "10M half not supported\n"); |
@@ -166,7 +367,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
166 | 367 | ||
167 | case SPEED_100: | 368 | case SPEED_100: |
168 | if (cmd->duplex == DUPLEX_FULL) { | 369 | if (cmd->duplex == DUPLEX_FULL) { |
169 | if (!(bp->port.supported & | 370 | if (!(bp->port.supported[cfg_idx] & |
170 | SUPPORTED_100baseT_Full)) { | 371 | SUPPORTED_100baseT_Full)) { |
171 | DP(NETIF_MSG_LINK, | 372 | DP(NETIF_MSG_LINK, |
172 | "100M full not supported\n"); | 373 | "100M full not supported\n"); |
@@ -176,7 +377,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
176 | advertising = (ADVERTISED_100baseT_Full | | 377 | advertising = (ADVERTISED_100baseT_Full | |
177 | ADVERTISED_TP); | 378 | ADVERTISED_TP); |
178 | } else { | 379 | } else { |
179 | if (!(bp->port.supported & | 380 | if (!(bp->port.supported[cfg_idx] & |
180 | SUPPORTED_100baseT_Half)) { | 381 | SUPPORTED_100baseT_Half)) { |
181 | DP(NETIF_MSG_LINK, | 382 | DP(NETIF_MSG_LINK, |
182 | "100M half not supported\n"); | 383 | "100M half not supported\n"); |
@@ -194,7 +395,8 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
194 | return -EINVAL; | 395 | return -EINVAL; |
195 | } | 396 | } |
196 | 397 | ||
197 | if (!(bp->port.supported & SUPPORTED_1000baseT_Full)) { | 398 | if (!(bp->port.supported[cfg_idx] & |
399 | SUPPORTED_1000baseT_Full)) { | ||
198 | DP(NETIF_MSG_LINK, "1G full not supported\n"); | 400 | DP(NETIF_MSG_LINK, "1G full not supported\n"); |
199 | return -EINVAL; | 401 | return -EINVAL; |
200 | } | 402 | } |
@@ -210,7 +412,8 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
210 | return -EINVAL; | 412 | return -EINVAL; |
211 | } | 413 | } |
212 | 414 | ||
213 | if (!(bp->port.supported & SUPPORTED_2500baseX_Full)) { | 415 | if (!(bp->port.supported[cfg_idx] |
416 | & SUPPORTED_2500baseX_Full)) { | ||
214 | DP(NETIF_MSG_LINK, | 417 | DP(NETIF_MSG_LINK, |
215 | "2.5G full not supported\n"); | 418 | "2.5G full not supported\n"); |
216 | return -EINVAL; | 419 | return -EINVAL; |
@@ -226,7 +429,8 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
226 | return -EINVAL; | 429 | return -EINVAL; |
227 | } | 430 | } |
228 | 431 | ||
229 | if (!(bp->port.supported & SUPPORTED_10000baseT_Full)) { | 432 | if (!(bp->port.supported[cfg_idx] |
433 | & SUPPORTED_10000baseT_Full)) { | ||
230 | DP(NETIF_MSG_LINK, "10G full not supported\n"); | 434 | DP(NETIF_MSG_LINK, "10G full not supported\n"); |
231 | return -EINVAL; | 435 | return -EINVAL; |
232 | } | 436 | } |
@@ -236,20 +440,23 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
236 | break; | 440 | break; |
237 | 441 | ||
238 | default: | 442 | default: |
239 | DP(NETIF_MSG_LINK, "Unsupported speed\n"); | 443 | DP(NETIF_MSG_LINK, "Unsupported speed %u\n", speed); |
240 | return -EINVAL; | 444 | return -EINVAL; |
241 | } | 445 | } |
242 | 446 | ||
243 | bp->link_params.req_line_speed = cmd->speed; | 447 | bp->link_params.req_line_speed[cfg_idx] = speed; |
244 | bp->link_params.req_duplex = cmd->duplex; | 448 | bp->link_params.req_duplex[cfg_idx] = cmd->duplex; |
245 | bp->port.advertising = advertising; | 449 | bp->port.advertising[cfg_idx] = advertising; |
246 | } | 450 | } |
247 | 451 | ||
248 | DP(NETIF_MSG_LINK, "req_line_speed %d\n" | 452 | DP(NETIF_MSG_LINK, "req_line_speed %d\n" |
249 | DP_LEVEL " req_duplex %d advertising 0x%x\n", | 453 | DP_LEVEL " req_duplex %d advertising 0x%x\n", |
250 | bp->link_params.req_line_speed, bp->link_params.req_duplex, | 454 | bp->link_params.req_line_speed[cfg_idx], |
251 | bp->port.advertising); | 455 | bp->link_params.req_duplex[cfg_idx], |
456 | bp->port.advertising[cfg_idx]); | ||
252 | 457 | ||
458 | /* Set new config */ | ||
459 | bp->link_params.multi_phy_config = new_multi_phy_config; | ||
253 | if (netif_running(dev)) { | 460 | if (netif_running(dev)) { |
254 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); | 461 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); |
255 | bnx2x_link_set(bp); | 462 | bnx2x_link_set(bp); |
@@ -260,12 +467,13 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
260 | 467 | ||
261 | #define IS_E1_ONLINE(info) (((info) & RI_E1_ONLINE) == RI_E1_ONLINE) | 468 | #define IS_E1_ONLINE(info) (((info) & RI_E1_ONLINE) == RI_E1_ONLINE) |
262 | #define IS_E1H_ONLINE(info) (((info) & RI_E1H_ONLINE) == RI_E1H_ONLINE) | 469 | #define IS_E1H_ONLINE(info) (((info) & RI_E1H_ONLINE) == RI_E1H_ONLINE) |
470 | #define IS_E2_ONLINE(info) (((info) & RI_E2_ONLINE) == RI_E2_ONLINE) | ||
263 | 471 | ||
264 | static int bnx2x_get_regs_len(struct net_device *dev) | 472 | static int bnx2x_get_regs_len(struct net_device *dev) |
265 | { | 473 | { |
266 | struct bnx2x *bp = netdev_priv(dev); | 474 | struct bnx2x *bp = netdev_priv(dev); |
267 | int regdump_len = 0; | 475 | int regdump_len = 0; |
268 | int i; | 476 | int i, j, k; |
269 | 477 | ||
270 | if (CHIP_IS_E1(bp)) { | 478 | if (CHIP_IS_E1(bp)) { |
271 | for (i = 0; i < REGS_COUNT; i++) | 479 | for (i = 0; i < REGS_COUNT; i++) |
@@ -277,7 +485,7 @@ static int bnx2x_get_regs_len(struct net_device *dev) | |||
277 | regdump_len += wreg_addrs_e1[i].size * | 485 | regdump_len += wreg_addrs_e1[i].size * |
278 | (1 + wreg_addrs_e1[i].read_regs_count); | 486 | (1 + wreg_addrs_e1[i].read_regs_count); |
279 | 487 | ||
280 | } else { /* E1H */ | 488 | } else if (CHIP_IS_E1H(bp)) { |
281 | for (i = 0; i < REGS_COUNT; i++) | 489 | for (i = 0; i < REGS_COUNT; i++) |
282 | if (IS_E1H_ONLINE(reg_addrs[i].info)) | 490 | if (IS_E1H_ONLINE(reg_addrs[i].info)) |
283 | regdump_len += reg_addrs[i].size; | 491 | regdump_len += reg_addrs[i].size; |
@@ -286,6 +494,24 @@ static int bnx2x_get_regs_len(struct net_device *dev) | |||
286 | if (IS_E1H_ONLINE(wreg_addrs_e1h[i].info)) | 494 | if (IS_E1H_ONLINE(wreg_addrs_e1h[i].info)) |
287 | regdump_len += wreg_addrs_e1h[i].size * | 495 | regdump_len += wreg_addrs_e1h[i].size * |
288 | (1 + wreg_addrs_e1h[i].read_regs_count); | 496 | (1 + wreg_addrs_e1h[i].read_regs_count); |
497 | } else if (CHIP_IS_E2(bp)) { | ||
498 | for (i = 0; i < REGS_COUNT; i++) | ||
499 | if (IS_E2_ONLINE(reg_addrs[i].info)) | ||
500 | regdump_len += reg_addrs[i].size; | ||
501 | |||
502 | for (i = 0; i < WREGS_COUNT_E2; i++) | ||
503 | if (IS_E2_ONLINE(wreg_addrs_e2[i].info)) | ||
504 | regdump_len += wreg_addrs_e2[i].size * | ||
505 | (1 + wreg_addrs_e2[i].read_regs_count); | ||
506 | |||
507 | for (i = 0; i < PAGE_MODE_VALUES_E2; i++) | ||
508 | for (j = 0; j < PAGE_WRITE_REGS_E2; j++) { | ||
509 | for (k = 0; k < PAGE_READ_REGS_E2; k++) | ||
510 | if (IS_E2_ONLINE(page_read_regs_e2[k]. | ||
511 | info)) | ||
512 | regdump_len += | ||
513 | page_read_regs_e2[k].size; | ||
514 | } | ||
289 | } | 515 | } |
290 | regdump_len *= 4; | 516 | regdump_len *= 4; |
291 | regdump_len += sizeof(struct dump_hdr); | 517 | regdump_len += sizeof(struct dump_hdr); |
@@ -293,6 +519,23 @@ static int bnx2x_get_regs_len(struct net_device *dev) | |||
293 | return regdump_len; | 519 | return regdump_len; |
294 | } | 520 | } |
295 | 521 | ||
522 | static inline void bnx2x_read_pages_regs_e2(struct bnx2x *bp, u32 *p) | ||
523 | { | ||
524 | u32 i, j, k, n; | ||
525 | |||
526 | for (i = 0; i < PAGE_MODE_VALUES_E2; i++) { | ||
527 | for (j = 0; j < PAGE_WRITE_REGS_E2; j++) { | ||
528 | REG_WR(bp, page_write_regs_e2[j], page_vals_e2[i]); | ||
529 | for (k = 0; k < PAGE_READ_REGS_E2; k++) | ||
530 | if (IS_E2_ONLINE(page_read_regs_e2[k].info)) | ||
531 | for (n = 0; n < | ||
532 | page_read_regs_e2[k].size; n++) | ||
533 | *p++ = REG_RD(bp, | ||
534 | page_read_regs_e2[k].addr + n*4); | ||
535 | } | ||
536 | } | ||
537 | } | ||
538 | |||
296 | static void bnx2x_get_regs(struct net_device *dev, | 539 | static void bnx2x_get_regs(struct net_device *dev, |
297 | struct ethtool_regs *regs, void *_p) | 540 | struct ethtool_regs *regs, void *_p) |
298 | { | 541 | { |
@@ -306,13 +549,26 @@ static void bnx2x_get_regs(struct net_device *dev, | |||
306 | if (!netif_running(bp->dev)) | 549 | if (!netif_running(bp->dev)) |
307 | return; | 550 | return; |
308 | 551 | ||
552 | /* Disable parity attentions as long as following dump may | ||
553 | * cause false alarms by reading never written registers. We | ||
554 | * will re-enable parity attentions right after the dump. | ||
555 | */ | ||
556 | bnx2x_disable_blocks_parity(bp); | ||
557 | |||
309 | dump_hdr.hdr_size = (sizeof(struct dump_hdr) / 4) - 1; | 558 | dump_hdr.hdr_size = (sizeof(struct dump_hdr) / 4) - 1; |
310 | dump_hdr.dump_sign = dump_sign_all; | 559 | dump_hdr.dump_sign = dump_sign_all; |
311 | dump_hdr.xstorm_waitp = REG_RD(bp, XSTORM_WAITP_ADDR); | 560 | dump_hdr.xstorm_waitp = REG_RD(bp, XSTORM_WAITP_ADDR); |
312 | dump_hdr.tstorm_waitp = REG_RD(bp, TSTORM_WAITP_ADDR); | 561 | dump_hdr.tstorm_waitp = REG_RD(bp, TSTORM_WAITP_ADDR); |
313 | dump_hdr.ustorm_waitp = REG_RD(bp, USTORM_WAITP_ADDR); | 562 | dump_hdr.ustorm_waitp = REG_RD(bp, USTORM_WAITP_ADDR); |
314 | dump_hdr.cstorm_waitp = REG_RD(bp, CSTORM_WAITP_ADDR); | 563 | dump_hdr.cstorm_waitp = REG_RD(bp, CSTORM_WAITP_ADDR); |
315 | dump_hdr.info = CHIP_IS_E1(bp) ? RI_E1_ONLINE : RI_E1H_ONLINE; | 564 | |
565 | if (CHIP_IS_E1(bp)) | ||
566 | dump_hdr.info = RI_E1_ONLINE; | ||
567 | else if (CHIP_IS_E1H(bp)) | ||
568 | dump_hdr.info = RI_E1H_ONLINE; | ||
569 | else if (CHIP_IS_E2(bp)) | ||
570 | dump_hdr.info = RI_E2_ONLINE | | ||
571 | (BP_PATH(bp) ? RI_PATH1_DUMP : RI_PATH0_DUMP); | ||
316 | 572 | ||
317 | memcpy(p, &dump_hdr, sizeof(struct dump_hdr)); | 573 | memcpy(p, &dump_hdr, sizeof(struct dump_hdr)); |
318 | p += dump_hdr.hdr_size + 1; | 574 | p += dump_hdr.hdr_size + 1; |
@@ -324,16 +580,29 @@ static void bnx2x_get_regs(struct net_device *dev, | |||
324 | *p++ = REG_RD(bp, | 580 | *p++ = REG_RD(bp, |
325 | reg_addrs[i].addr + j*4); | 581 | reg_addrs[i].addr + j*4); |
326 | 582 | ||
327 | } else { /* E1H */ | 583 | } else if (CHIP_IS_E1H(bp)) { |
328 | for (i = 0; i < REGS_COUNT; i++) | 584 | for (i = 0; i < REGS_COUNT; i++) |
329 | if (IS_E1H_ONLINE(reg_addrs[i].info)) | 585 | if (IS_E1H_ONLINE(reg_addrs[i].info)) |
330 | for (j = 0; j < reg_addrs[i].size; j++) | 586 | for (j = 0; j < reg_addrs[i].size; j++) |
331 | *p++ = REG_RD(bp, | 587 | *p++ = REG_RD(bp, |
332 | reg_addrs[i].addr + j*4); | 588 | reg_addrs[i].addr + j*4); |
589 | |||
590 | } else if (CHIP_IS_E2(bp)) { | ||
591 | for (i = 0; i < REGS_COUNT; i++) | ||
592 | if (IS_E2_ONLINE(reg_addrs[i].info)) | ||
593 | for (j = 0; j < reg_addrs[i].size; j++) | ||
594 | *p++ = REG_RD(bp, | ||
595 | reg_addrs[i].addr + j*4); | ||
596 | |||
597 | bnx2x_read_pages_regs_e2(bp, p); | ||
333 | } | 598 | } |
599 | /* Re-enable parity attentions */ | ||
600 | bnx2x_clear_blocks_parity(bp); | ||
601 | if (CHIP_PARITY_ENABLED(bp)) | ||
602 | bnx2x_enable_blocks_parity(bp); | ||
334 | } | 603 | } |
335 | 604 | ||
336 | #define PHY_FW_VER_LEN 10 | 605 | #define PHY_FW_VER_LEN 20 |
337 | 606 | ||
338 | static void bnx2x_get_drvinfo(struct net_device *dev, | 607 | static void bnx2x_get_drvinfo(struct net_device *dev, |
339 | struct ethtool_drvinfo *info) | 608 | struct ethtool_drvinfo *info) |
@@ -436,7 +705,7 @@ static u32 bnx2x_get_link(struct net_device *dev) | |||
436 | { | 705 | { |
437 | struct bnx2x *bp = netdev_priv(dev); | 706 | struct bnx2x *bp = netdev_priv(dev); |
438 | 707 | ||
439 | if (bp->flags & MF_FUNC_DIS) | 708 | if (bp->flags & MF_FUNC_DIS || (bp->state != BNX2X_STATE_OPEN)) |
440 | return 0; | 709 | return 0; |
441 | 710 | ||
442 | return bp->link_vars.link_up; | 711 | return bp->link_vars.link_up; |
@@ -811,7 +1080,7 @@ static int bnx2x_set_eeprom(struct net_device *dev, | |||
811 | struct bnx2x *bp = netdev_priv(dev); | 1080 | struct bnx2x *bp = netdev_priv(dev); |
812 | int port = BP_PORT(bp); | 1081 | int port = BP_PORT(bp); |
813 | int rc = 0; | 1082 | int rc = 0; |
814 | 1083 | u32 ext_phy_config; | |
815 | if (!netif_running(dev)) | 1084 | if (!netif_running(dev)) |
816 | return -EAGAIN; | 1085 | return -EAGAIN; |
817 | 1086 | ||
@@ -827,6 +1096,10 @@ static int bnx2x_set_eeprom(struct net_device *dev, | |||
827 | !bp->port.pmf) | 1096 | !bp->port.pmf) |
828 | return -EINVAL; | 1097 | return -EINVAL; |
829 | 1098 | ||
1099 | ext_phy_config = | ||
1100 | SHMEM_RD(bp, | ||
1101 | dev_info.port_hw_config[port].external_phy_config); | ||
1102 | |||
830 | if (eeprom->magic == 0x50485950) { | 1103 | if (eeprom->magic == 0x50485950) { |
831 | /* 'PHYP' (0x50485950): prepare phy for FW upgrade */ | 1104 | /* 'PHYP' (0x50485950): prepare phy for FW upgrade */ |
832 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); | 1105 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); |
@@ -834,7 +1107,7 @@ static int bnx2x_set_eeprom(struct net_device *dev, | |||
834 | bnx2x_acquire_phy_lock(bp); | 1107 | bnx2x_acquire_phy_lock(bp); |
835 | rc |= bnx2x_link_reset(&bp->link_params, | 1108 | rc |= bnx2x_link_reset(&bp->link_params, |
836 | &bp->link_vars, 0); | 1109 | &bp->link_vars, 0); |
837 | if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) == | 1110 | if (XGXS_EXT_PHY_TYPE(ext_phy_config) == |
838 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) | 1111 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) |
839 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, | 1112 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, |
840 | MISC_REGISTERS_GPIO_HIGH, port); | 1113 | MISC_REGISTERS_GPIO_HIGH, port); |
@@ -855,10 +1128,8 @@ static int bnx2x_set_eeprom(struct net_device *dev, | |||
855 | } | 1128 | } |
856 | } else if (eeprom->magic == 0x53985943) { | 1129 | } else if (eeprom->magic == 0x53985943) { |
857 | /* 'PHYC' (0x53985943): PHY FW upgrade completed */ | 1130 | /* 'PHYC' (0x53985943): PHY FW upgrade completed */ |
858 | if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) == | 1131 | if (XGXS_EXT_PHY_TYPE(ext_phy_config) == |
859 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) { | 1132 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) { |
860 | u8 ext_phy_addr = | ||
861 | XGXS_EXT_PHY_ADDR(bp->link_params.ext_phy_config); | ||
862 | 1133 | ||
863 | /* DSP Remove Download Mode */ | 1134 | /* DSP Remove Download Mode */ |
864 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, | 1135 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, |
@@ -866,7 +1137,8 @@ static int bnx2x_set_eeprom(struct net_device *dev, | |||
866 | 1137 | ||
867 | bnx2x_acquire_phy_lock(bp); | 1138 | bnx2x_acquire_phy_lock(bp); |
868 | 1139 | ||
869 | bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr); | 1140 | bnx2x_sfx7101_sp_sw_reset(bp, |
1141 | &bp->link_params.phy[EXT_PHY1]); | ||
870 | 1142 | ||
871 | /* wait 0.5 sec to allow it to run */ | 1143 | /* wait 0.5 sec to allow it to run */ |
872 | msleep(500); | 1144 | msleep(500); |
@@ -879,6 +1151,7 @@ static int bnx2x_set_eeprom(struct net_device *dev, | |||
879 | 1151 | ||
880 | return rc; | 1152 | return rc; |
881 | } | 1153 | } |
1154 | |||
882 | static int bnx2x_get_coalesce(struct net_device *dev, | 1155 | static int bnx2x_get_coalesce(struct net_device *dev, |
883 | struct ethtool_coalesce *coal) | 1156 | struct ethtool_coalesce *coal) |
884 | { | 1157 | { |
@@ -920,7 +1193,14 @@ static void bnx2x_get_ringparam(struct net_device *dev, | |||
920 | ering->rx_mini_max_pending = 0; | 1193 | ering->rx_mini_max_pending = 0; |
921 | ering->rx_jumbo_max_pending = 0; | 1194 | ering->rx_jumbo_max_pending = 0; |
922 | 1195 | ||
923 | ering->rx_pending = bp->rx_ring_size; | 1196 | if (bp->rx_ring_size) |
1197 | ering->rx_pending = bp->rx_ring_size; | ||
1198 | else | ||
1199 | if (bp->state == BNX2X_STATE_OPEN && bp->num_queues) | ||
1200 | ering->rx_pending = MAX_RX_AVAIL/bp->num_queues; | ||
1201 | else | ||
1202 | ering->rx_pending = MAX_RX_AVAIL; | ||
1203 | |||
924 | ering->rx_mini_pending = 0; | 1204 | ering->rx_mini_pending = 0; |
925 | ering->rx_jumbo_pending = 0; | 1205 | ering->rx_jumbo_pending = 0; |
926 | 1206 | ||
@@ -940,6 +1220,8 @@ static int bnx2x_set_ringparam(struct net_device *dev, | |||
940 | } | 1220 | } |
941 | 1221 | ||
942 | if ((ering->rx_pending > MAX_RX_AVAIL) || | 1222 | if ((ering->rx_pending > MAX_RX_AVAIL) || |
1223 | (ering->rx_pending < (bp->disable_tpa ? MIN_RX_SIZE_NONTPA : | ||
1224 | MIN_RX_SIZE_TPA)) || | ||
943 | (ering->tx_pending > MAX_TX_AVAIL) || | 1225 | (ering->tx_pending > MAX_TX_AVAIL) || |
944 | (ering->tx_pending <= MAX_SKB_FRAGS + 4)) | 1226 | (ering->tx_pending <= MAX_SKB_FRAGS + 4)) |
945 | return -EINVAL; | 1227 | return -EINVAL; |
@@ -959,10 +1241,9 @@ static void bnx2x_get_pauseparam(struct net_device *dev, | |||
959 | struct ethtool_pauseparam *epause) | 1241 | struct ethtool_pauseparam *epause) |
960 | { | 1242 | { |
961 | struct bnx2x *bp = netdev_priv(dev); | 1243 | struct bnx2x *bp = netdev_priv(dev); |
962 | 1244 | int cfg_idx = bnx2x_get_link_cfg_idx(bp); | |
963 | epause->autoneg = (bp->link_params.req_flow_ctrl == | 1245 | epause->autoneg = (bp->link_params.req_flow_ctrl[cfg_idx] == |
964 | BNX2X_FLOW_CTRL_AUTO) && | 1246 | BNX2X_FLOW_CTRL_AUTO); |
965 | (bp->link_params.req_line_speed == SPEED_AUTO_NEG); | ||
966 | 1247 | ||
967 | epause->rx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) == | 1248 | epause->rx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) == |
968 | BNX2X_FLOW_CTRL_RX); | 1249 | BNX2X_FLOW_CTRL_RX); |
@@ -978,37 +1259,39 @@ static int bnx2x_set_pauseparam(struct net_device *dev, | |||
978 | struct ethtool_pauseparam *epause) | 1259 | struct ethtool_pauseparam *epause) |
979 | { | 1260 | { |
980 | struct bnx2x *bp = netdev_priv(dev); | 1261 | struct bnx2x *bp = netdev_priv(dev); |
981 | 1262 | u32 cfg_idx = bnx2x_get_link_cfg_idx(bp); | |
982 | if (IS_E1HMF(bp)) | 1263 | if (IS_MF(bp)) |
983 | return 0; | 1264 | return 0; |
984 | 1265 | ||
985 | DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n" | 1266 | DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n" |
986 | DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n", | 1267 | DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n", |
987 | epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause); | 1268 | epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause); |
988 | 1269 | ||
989 | bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO; | 1270 | bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_AUTO; |
990 | 1271 | ||
991 | if (epause->rx_pause) | 1272 | if (epause->rx_pause) |
992 | bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_RX; | 1273 | bp->link_params.req_flow_ctrl[cfg_idx] |= BNX2X_FLOW_CTRL_RX; |
993 | 1274 | ||
994 | if (epause->tx_pause) | 1275 | if (epause->tx_pause) |
995 | bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_TX; | 1276 | bp->link_params.req_flow_ctrl[cfg_idx] |= BNX2X_FLOW_CTRL_TX; |
996 | 1277 | ||
997 | if (bp->link_params.req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) | 1278 | if (bp->link_params.req_flow_ctrl[cfg_idx] == BNX2X_FLOW_CTRL_AUTO) |
998 | bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_NONE; | 1279 | bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_NONE; |
999 | 1280 | ||
1000 | if (epause->autoneg) { | 1281 | if (epause->autoneg) { |
1001 | if (!(bp->port.supported & SUPPORTED_Autoneg)) { | 1282 | if (!(bp->port.supported[cfg_idx] & SUPPORTED_Autoneg)) { |
1002 | DP(NETIF_MSG_LINK, "autoneg not supported\n"); | 1283 | DP(NETIF_MSG_LINK, "autoneg not supported\n"); |
1003 | return -EINVAL; | 1284 | return -EINVAL; |
1004 | } | 1285 | } |
1005 | 1286 | ||
1006 | if (bp->link_params.req_line_speed == SPEED_AUTO_NEG) | 1287 | if (bp->link_params.req_line_speed[cfg_idx] == SPEED_AUTO_NEG) { |
1007 | bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO; | 1288 | bp->link_params.req_flow_ctrl[cfg_idx] = |
1289 | BNX2X_FLOW_CTRL_AUTO; | ||
1290 | } | ||
1008 | } | 1291 | } |
1009 | 1292 | ||
1010 | DP(NETIF_MSG_LINK, | 1293 | DP(NETIF_MSG_LINK, |
1011 | "req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl); | 1294 | "req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl[cfg_idx]); |
1012 | 1295 | ||
1013 | if (netif_running(dev)) { | 1296 | if (netif_running(dev)) { |
1014 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); | 1297 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); |
@@ -1018,92 +1301,6 @@ static int bnx2x_set_pauseparam(struct net_device *dev, | |||
1018 | return 0; | 1301 | return 0; |
1019 | } | 1302 | } |
1020 | 1303 | ||
1021 | static int bnx2x_set_flags(struct net_device *dev, u32 data) | ||
1022 | { | ||
1023 | struct bnx2x *bp = netdev_priv(dev); | ||
1024 | int changed = 0; | ||
1025 | int rc = 0; | ||
1026 | |||
1027 | if (data & ~(ETH_FLAG_LRO | ETH_FLAG_RXHASH)) | ||
1028 | return -EINVAL; | ||
1029 | |||
1030 | if (bp->recovery_state != BNX2X_RECOVERY_DONE) { | ||
1031 | printk(KERN_ERR "Handling parity error recovery. Try again later\n"); | ||
1032 | return -EAGAIN; | ||
1033 | } | ||
1034 | |||
1035 | /* TPA requires Rx CSUM offloading */ | ||
1036 | if ((data & ETH_FLAG_LRO) && bp->rx_csum) { | ||
1037 | if (!bp->disable_tpa) { | ||
1038 | if (!(dev->features & NETIF_F_LRO)) { | ||
1039 | dev->features |= NETIF_F_LRO; | ||
1040 | bp->flags |= TPA_ENABLE_FLAG; | ||
1041 | changed = 1; | ||
1042 | } | ||
1043 | } else | ||
1044 | rc = -EINVAL; | ||
1045 | } else if (dev->features & NETIF_F_LRO) { | ||
1046 | dev->features &= ~NETIF_F_LRO; | ||
1047 | bp->flags &= ~TPA_ENABLE_FLAG; | ||
1048 | changed = 1; | ||
1049 | } | ||
1050 | |||
1051 | if (data & ETH_FLAG_RXHASH) | ||
1052 | dev->features |= NETIF_F_RXHASH; | ||
1053 | else | ||
1054 | dev->features &= ~NETIF_F_RXHASH; | ||
1055 | |||
1056 | if (changed && netif_running(dev)) { | ||
1057 | bnx2x_nic_unload(bp, UNLOAD_NORMAL); | ||
1058 | rc = bnx2x_nic_load(bp, LOAD_NORMAL); | ||
1059 | } | ||
1060 | |||
1061 | return rc; | ||
1062 | } | ||
1063 | |||
1064 | static u32 bnx2x_get_rx_csum(struct net_device *dev) | ||
1065 | { | ||
1066 | struct bnx2x *bp = netdev_priv(dev); | ||
1067 | |||
1068 | return bp->rx_csum; | ||
1069 | } | ||
1070 | |||
1071 | static int bnx2x_set_rx_csum(struct net_device *dev, u32 data) | ||
1072 | { | ||
1073 | struct bnx2x *bp = netdev_priv(dev); | ||
1074 | int rc = 0; | ||
1075 | |||
1076 | if (bp->recovery_state != BNX2X_RECOVERY_DONE) { | ||
1077 | printk(KERN_ERR "Handling parity error recovery. Try again later\n"); | ||
1078 | return -EAGAIN; | ||
1079 | } | ||
1080 | |||
1081 | bp->rx_csum = data; | ||
1082 | |||
1083 | /* Disable TPA, when Rx CSUM is disabled. Otherwise all | ||
1084 | TPA'ed packets will be discarded due to wrong TCP CSUM */ | ||
1085 | if (!data) { | ||
1086 | u32 flags = ethtool_op_get_flags(dev); | ||
1087 | |||
1088 | rc = bnx2x_set_flags(dev, (flags & ~ETH_FLAG_LRO)); | ||
1089 | } | ||
1090 | |||
1091 | return rc; | ||
1092 | } | ||
1093 | |||
1094 | static int bnx2x_set_tso(struct net_device *dev, u32 data) | ||
1095 | { | ||
1096 | if (data) { | ||
1097 | dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN); | ||
1098 | dev->features |= NETIF_F_TSO6; | ||
1099 | } else { | ||
1100 | dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO_ECN); | ||
1101 | dev->features &= ~NETIF_F_TSO6; | ||
1102 | } | ||
1103 | |||
1104 | return 0; | ||
1105 | } | ||
1106 | |||
1107 | static const struct { | 1304 | static const struct { |
1108 | char string[ETH_GSTRING_LEN]; | 1305 | char string[ETH_GSTRING_LEN]; |
1109 | } bnx2x_tests_str_arr[BNX2X_NUM_TESTS] = { | 1306 | } bnx2x_tests_str_arr[BNX2X_NUM_TESTS] = { |
@@ -1185,13 +1382,17 @@ static int bnx2x_test_registers(struct bnx2x *bp) | |||
1185 | 1382 | ||
1186 | for (i = 0; reg_tbl[i].offset0 != 0xffffffff; i++) { | 1383 | for (i = 0; reg_tbl[i].offset0 != 0xffffffff; i++) { |
1187 | u32 offset, mask, save_val, val; | 1384 | u32 offset, mask, save_val, val; |
1385 | if (CHIP_IS_E2(bp) && | ||
1386 | reg_tbl[i].offset0 == HC_REG_AGG_INT_0) | ||
1387 | continue; | ||
1188 | 1388 | ||
1189 | offset = reg_tbl[i].offset0 + port*reg_tbl[i].offset1; | 1389 | offset = reg_tbl[i].offset0 + port*reg_tbl[i].offset1; |
1190 | mask = reg_tbl[i].mask; | 1390 | mask = reg_tbl[i].mask; |
1191 | 1391 | ||
1192 | save_val = REG_RD(bp, offset); | 1392 | save_val = REG_RD(bp, offset); |
1193 | 1393 | ||
1194 | REG_WR(bp, offset, (wr_val & mask)); | 1394 | REG_WR(bp, offset, wr_val & mask); |
1395 | |||
1195 | val = REG_RD(bp, offset); | 1396 | val = REG_RD(bp, offset); |
1196 | 1397 | ||
1197 | /* Restore the original register's value */ | 1398 | /* Restore the original register's value */ |
@@ -1236,20 +1437,33 @@ static int bnx2x_test_memory(struct bnx2x *bp) | |||
1236 | u32 offset; | 1437 | u32 offset; |
1237 | u32 e1_mask; | 1438 | u32 e1_mask; |
1238 | u32 e1h_mask; | 1439 | u32 e1h_mask; |
1440 | u32 e2_mask; | ||
1239 | } prty_tbl[] = { | 1441 | } prty_tbl[] = { |
1240 | { "CCM_PRTY_STS", CCM_REG_CCM_PRTY_STS, 0x3ffc0, 0 }, | 1442 | { "CCM_PRTY_STS", CCM_REG_CCM_PRTY_STS, 0x3ffc0, 0, 0 }, |
1241 | { "CFC_PRTY_STS", CFC_REG_CFC_PRTY_STS, 0x2, 0x2 }, | 1443 | { "CFC_PRTY_STS", CFC_REG_CFC_PRTY_STS, 0x2, 0x2, 0 }, |
1242 | { "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS, 0, 0 }, | 1444 | { "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS, 0, 0, 0 }, |
1243 | { "TCM_PRTY_STS", TCM_REG_TCM_PRTY_STS, 0x3ffc0, 0 }, | 1445 | { "TCM_PRTY_STS", TCM_REG_TCM_PRTY_STS, 0x3ffc0, 0, 0 }, |
1244 | { "UCM_PRTY_STS", UCM_REG_UCM_PRTY_STS, 0x3ffc0, 0 }, | 1446 | { "UCM_PRTY_STS", UCM_REG_UCM_PRTY_STS, 0x3ffc0, 0, 0 }, |
1245 | { "XCM_PRTY_STS", XCM_REG_XCM_PRTY_STS, 0x3ffc1, 0 }, | 1447 | { "XCM_PRTY_STS", XCM_REG_XCM_PRTY_STS, 0x3ffc1, 0, 0 }, |
1246 | 1448 | ||
1247 | { NULL, 0xffffffff, 0, 0 } | 1449 | { NULL, 0xffffffff, 0, 0, 0 } |
1248 | }; | 1450 | }; |
1249 | 1451 | ||
1250 | if (!netif_running(bp->dev)) | 1452 | if (!netif_running(bp->dev)) |
1251 | return rc; | 1453 | return rc; |
1252 | 1454 | ||
1455 | /* pre-Check the parity status */ | ||
1456 | for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) { | ||
1457 | val = REG_RD(bp, prty_tbl[i].offset); | ||
1458 | if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) || | ||
1459 | (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask))) || | ||
1460 | (CHIP_IS_E2(bp) && (val & ~(prty_tbl[i].e2_mask)))) { | ||
1461 | DP(NETIF_MSG_HW, | ||
1462 | "%s is 0x%x\n", prty_tbl[i].name, val); | ||
1463 | goto test_mem_exit; | ||
1464 | } | ||
1465 | } | ||
1466 | |||
1253 | /* Go through all the memories */ | 1467 | /* Go through all the memories */ |
1254 | for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) | 1468 | for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) |
1255 | for (j = 0; j < mem_tbl[i].size; j++) | 1469 | for (j = 0; j < mem_tbl[i].size; j++) |
@@ -1259,7 +1473,8 @@ static int bnx2x_test_memory(struct bnx2x *bp) | |||
1259 | for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) { | 1473 | for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) { |
1260 | val = REG_RD(bp, prty_tbl[i].offset); | 1474 | val = REG_RD(bp, prty_tbl[i].offset); |
1261 | if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) || | 1475 | if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) || |
1262 | (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask)))) { | 1476 | (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask))) || |
1477 | (CHIP_IS_E2(bp) && (val & ~(prty_tbl[i].e2_mask)))) { | ||
1263 | DP(NETIF_MSG_HW, | 1478 | DP(NETIF_MSG_HW, |
1264 | "%s is 0x%x\n", prty_tbl[i].name, val); | 1479 | "%s is 0x%x\n", prty_tbl[i].name, val); |
1265 | goto test_mem_exit; | 1480 | goto test_mem_exit; |
@@ -1272,12 +1487,12 @@ test_mem_exit: | |||
1272 | return rc; | 1487 | return rc; |
1273 | } | 1488 | } |
1274 | 1489 | ||
1275 | static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up) | 1490 | static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up, u8 is_serdes) |
1276 | { | 1491 | { |
1277 | int cnt = 1000; | 1492 | int cnt = 1400; |
1278 | 1493 | ||
1279 | if (link_up) | 1494 | if (link_up) |
1280 | while (bnx2x_link_test(bp) && cnt--) | 1495 | while (bnx2x_link_test(bp, is_serdes) && cnt--) |
1281 | msleep(10); | 1496 | msleep(10); |
1282 | } | 1497 | } |
1283 | 1498 | ||
@@ -1293,7 +1508,8 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) | |||
1293 | u16 pkt_prod, bd_prod; | 1508 | u16 pkt_prod, bd_prod; |
1294 | struct sw_tx_bd *tx_buf; | 1509 | struct sw_tx_bd *tx_buf; |
1295 | struct eth_tx_start_bd *tx_start_bd; | 1510 | struct eth_tx_start_bd *tx_start_bd; |
1296 | struct eth_tx_parse_bd *pbd = NULL; | 1511 | struct eth_tx_parse_bd_e1x *pbd_e1x = NULL; |
1512 | struct eth_tx_parse_bd_e2 *pbd_e2 = NULL; | ||
1297 | dma_addr_t mapping; | 1513 | dma_addr_t mapping; |
1298 | union eth_rx_cqe *cqe; | 1514 | union eth_rx_cqe *cqe; |
1299 | u8 cqe_fp_flags; | 1515 | u8 cqe_fp_flags; |
@@ -1304,7 +1520,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) | |||
1304 | /* check the loopback mode */ | 1520 | /* check the loopback mode */ |
1305 | switch (loopback_mode) { | 1521 | switch (loopback_mode) { |
1306 | case BNX2X_PHY_LOOPBACK: | 1522 | case BNX2X_PHY_LOOPBACK: |
1307 | if (bp->link_params.loopback_mode != LOOPBACK_XGXS_10) | 1523 | if (bp->link_params.loopback_mode != LOOPBACK_XGXS) |
1308 | return -EINVAL; | 1524 | return -EINVAL; |
1309 | break; | 1525 | break; |
1310 | case BNX2X_MAC_LOOPBACK: | 1526 | case BNX2X_MAC_LOOPBACK: |
@@ -1318,7 +1534,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) | |||
1318 | /* prepare the loopback packet */ | 1534 | /* prepare the loopback packet */ |
1319 | pkt_size = (((bp->dev->mtu < ETH_MAX_PACKET_SIZE) ? | 1535 | pkt_size = (((bp->dev->mtu < ETH_MAX_PACKET_SIZE) ? |
1320 | bp->dev->mtu : ETH_MAX_PACKET_SIZE) + ETH_HLEN); | 1536 | bp->dev->mtu : ETH_MAX_PACKET_SIZE) + ETH_HLEN); |
1321 | skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size); | 1537 | skb = netdev_alloc_skb(bp->dev, fp_rx->rx_buf_size); |
1322 | if (!skb) { | 1538 | if (!skb) { |
1323 | rc = -ENOMEM; | 1539 | rc = -ENOMEM; |
1324 | goto test_loopback_exit; | 1540 | goto test_loopback_exit; |
@@ -1349,16 +1565,23 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) | |||
1349 | tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); | 1565 | tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping)); |
1350 | tx_start_bd->nbd = cpu_to_le16(2); /* start + pbd */ | 1566 | tx_start_bd->nbd = cpu_to_le16(2); /* start + pbd */ |
1351 | tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb)); | 1567 | tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb)); |
1352 | tx_start_bd->vlan = cpu_to_le16(pkt_prod); | 1568 | tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod); |
1353 | tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD; | 1569 | tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD; |
1354 | tx_start_bd->general_data = ((UNICAST_ADDRESS << | 1570 | SET_FLAG(tx_start_bd->general_data, |
1355 | ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT) | 1); | 1571 | ETH_TX_START_BD_ETH_ADDR_TYPE, |
1572 | UNICAST_ADDRESS); | ||
1573 | SET_FLAG(tx_start_bd->general_data, | ||
1574 | ETH_TX_START_BD_HDR_NBDS, | ||
1575 | 1); | ||
1356 | 1576 | ||
1357 | /* turn on parsing and get a BD */ | 1577 | /* turn on parsing and get a BD */ |
1358 | bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); | 1578 | bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); |
1359 | pbd = &fp_tx->tx_desc_ring[bd_prod].parse_bd; | ||
1360 | 1579 | ||
1361 | memset(pbd, 0, sizeof(struct eth_tx_parse_bd)); | 1580 | pbd_e1x = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e1x; |
1581 | pbd_e2 = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e2; | ||
1582 | |||
1583 | memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2)); | ||
1584 | memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x)); | ||
1362 | 1585 | ||
1363 | wmb(); | 1586 | wmb(); |
1364 | 1587 | ||
@@ -1377,6 +1600,20 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) | |||
1377 | if (tx_idx != tx_start_idx + num_pkts) | 1600 | if (tx_idx != tx_start_idx + num_pkts) |
1378 | goto test_loopback_exit; | 1601 | goto test_loopback_exit; |
1379 | 1602 | ||
1603 | /* Unlike HC IGU won't generate an interrupt for status block | ||
1604 | * updates that have been performed while interrupts were | ||
1605 | * disabled. | ||
1606 | */ | ||
1607 | if (bp->common.int_block == INT_BLOCK_IGU) { | ||
1608 | /* Disable local BHes to prevent a dead-lock situation between | ||
1609 | * sch_direct_xmit() and bnx2x_run_loopback() (calling | ||
1610 | * bnx2x_tx_int()), as both are taking netif_tx_lock(). | ||
1611 | */ | ||
1612 | local_bh_disable(); | ||
1613 | bnx2x_tx_int(fp_tx); | ||
1614 | local_bh_enable(); | ||
1615 | } | ||
1616 | |||
1380 | rx_idx = le16_to_cpu(*fp_rx->rx_cons_sb); | 1617 | rx_idx = le16_to_cpu(*fp_rx->rx_cons_sb); |
1381 | if (rx_idx != rx_start_idx + num_pkts) | 1618 | if (rx_idx != rx_start_idx + num_pkts) |
1382 | goto test_loopback_exit; | 1619 | goto test_loopback_exit; |
@@ -1460,9 +1697,7 @@ static int bnx2x_test_nvram(struct bnx2x *bp) | |||
1460 | { 0x100, 0x350 }, /* manuf_info */ | 1697 | { 0x100, 0x350 }, /* manuf_info */ |
1461 | { 0x450, 0xf0 }, /* feature_info */ | 1698 | { 0x450, 0xf0 }, /* feature_info */ |
1462 | { 0x640, 0x64 }, /* upgrade_key_info */ | 1699 | { 0x640, 0x64 }, /* upgrade_key_info */ |
1463 | { 0x6a4, 0x64 }, | ||
1464 | { 0x708, 0x70 }, /* manuf_key_info */ | 1700 | { 0x708, 0x70 }, /* manuf_key_info */ |
1465 | { 0x778, 0x70 }, | ||
1466 | { 0, 0 } | 1701 | { 0, 0 } |
1467 | }; | 1702 | }; |
1468 | __be32 buf[0x350 / 4]; | 1703 | __be32 buf[0x350 / 4]; |
@@ -1519,18 +1754,17 @@ static int bnx2x_test_intr(struct bnx2x *bp) | |||
1519 | 1754 | ||
1520 | config->hdr.length = 0; | 1755 | config->hdr.length = 0; |
1521 | if (CHIP_IS_E1(bp)) | 1756 | if (CHIP_IS_E1(bp)) |
1522 | /* use last unicast entries */ | 1757 | config->hdr.offset = (BP_PORT(bp) ? 32 : 0); |
1523 | config->hdr.offset = (BP_PORT(bp) ? 63 : 31); | ||
1524 | else | 1758 | else |
1525 | config->hdr.offset = BP_FUNC(bp); | 1759 | config->hdr.offset = BP_FUNC(bp); |
1526 | config->hdr.client_id = bp->fp->cl_id; | 1760 | config->hdr.client_id = bp->fp->cl_id; |
1527 | config->hdr.reserved1 = 0; | 1761 | config->hdr.reserved1 = 0; |
1528 | 1762 | ||
1529 | bp->set_mac_pending++; | 1763 | bp->set_mac_pending = 1; |
1530 | smp_wmb(); | 1764 | smp_wmb(); |
1531 | rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0, | 1765 | rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0, |
1532 | U64_HI(bnx2x_sp_mapping(bp, mac_config)), | 1766 | U64_HI(bnx2x_sp_mapping(bp, mac_config)), |
1533 | U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0); | 1767 | U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1); |
1534 | if (rc == 0) { | 1768 | if (rc == 0) { |
1535 | for (i = 0; i < 10; i++) { | 1769 | for (i = 0; i < 10; i++) { |
1536 | if (!bp->set_mac_pending) | 1770 | if (!bp->set_mac_pending) |
@@ -1549,7 +1783,7 @@ static void bnx2x_self_test(struct net_device *dev, | |||
1549 | struct ethtool_test *etest, u64 *buf) | 1783 | struct ethtool_test *etest, u64 *buf) |
1550 | { | 1784 | { |
1551 | struct bnx2x *bp = netdev_priv(dev); | 1785 | struct bnx2x *bp = netdev_priv(dev); |
1552 | 1786 | u8 is_serdes; | |
1553 | if (bp->recovery_state != BNX2X_RECOVERY_DONE) { | 1787 | if (bp->recovery_state != BNX2X_RECOVERY_DONE) { |
1554 | printk(KERN_ERR "Handling parity error recovery. Try again later\n"); | 1788 | printk(KERN_ERR "Handling parity error recovery. Try again later\n"); |
1555 | etest->flags |= ETH_TEST_FL_FAILED; | 1789 | etest->flags |= ETH_TEST_FL_FAILED; |
@@ -1562,8 +1796,9 @@ static void bnx2x_self_test(struct net_device *dev, | |||
1562 | return; | 1796 | return; |
1563 | 1797 | ||
1564 | /* offline tests are not supported in MF mode */ | 1798 | /* offline tests are not supported in MF mode */ |
1565 | if (IS_E1HMF(bp)) | 1799 | if (IS_MF(bp)) |
1566 | etest->flags &= ~ETH_TEST_FL_OFFLINE; | 1800 | etest->flags &= ~ETH_TEST_FL_OFFLINE; |
1801 | is_serdes = (bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) > 0; | ||
1567 | 1802 | ||
1568 | if (etest->flags & ETH_TEST_FL_OFFLINE) { | 1803 | if (etest->flags & ETH_TEST_FL_OFFLINE) { |
1569 | int port = BP_PORT(bp); | 1804 | int port = BP_PORT(bp); |
@@ -1575,11 +1810,12 @@ static void bnx2x_self_test(struct net_device *dev, | |||
1575 | /* disable input for TX port IF */ | 1810 | /* disable input for TX port IF */ |
1576 | REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, 0); | 1811 | REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, 0); |
1577 | 1812 | ||
1578 | link_up = (bnx2x_link_test(bp) == 0); | 1813 | link_up = bp->link_vars.link_up; |
1814 | |||
1579 | bnx2x_nic_unload(bp, UNLOAD_NORMAL); | 1815 | bnx2x_nic_unload(bp, UNLOAD_NORMAL); |
1580 | bnx2x_nic_load(bp, LOAD_DIAG); | 1816 | bnx2x_nic_load(bp, LOAD_DIAG); |
1581 | /* wait until link state is restored */ | 1817 | /* wait until link state is restored */ |
1582 | bnx2x_wait_for_link(bp, link_up); | 1818 | bnx2x_wait_for_link(bp, link_up, is_serdes); |
1583 | 1819 | ||
1584 | if (bnx2x_test_registers(bp) != 0) { | 1820 | if (bnx2x_test_registers(bp) != 0) { |
1585 | buf[0] = 1; | 1821 | buf[0] = 1; |
@@ -1589,6 +1825,7 @@ static void bnx2x_self_test(struct net_device *dev, | |||
1589 | buf[1] = 1; | 1825 | buf[1] = 1; |
1590 | etest->flags |= ETH_TEST_FL_FAILED; | 1826 | etest->flags |= ETH_TEST_FL_FAILED; |
1591 | } | 1827 | } |
1828 | |||
1592 | buf[2] = bnx2x_test_loopback(bp, link_up); | 1829 | buf[2] = bnx2x_test_loopback(bp, link_up); |
1593 | if (buf[2] != 0) | 1830 | if (buf[2] != 0) |
1594 | etest->flags |= ETH_TEST_FL_FAILED; | 1831 | etest->flags |= ETH_TEST_FL_FAILED; |
@@ -1600,7 +1837,7 @@ static void bnx2x_self_test(struct net_device *dev, | |||
1600 | 1837 | ||
1601 | bnx2x_nic_load(bp, LOAD_NORMAL); | 1838 | bnx2x_nic_load(bp, LOAD_NORMAL); |
1602 | /* wait until link state is restored */ | 1839 | /* wait until link state is restored */ |
1603 | bnx2x_wait_for_link(bp, link_up); | 1840 | bnx2x_wait_for_link(bp, link_up, is_serdes); |
1604 | } | 1841 | } |
1605 | if (bnx2x_test_nvram(bp) != 0) { | 1842 | if (bnx2x_test_nvram(bp) != 0) { |
1606 | buf[3] = 1; | 1843 | buf[3] = 1; |
@@ -1610,150 +1847,22 @@ static void bnx2x_self_test(struct net_device *dev, | |||
1610 | buf[4] = 1; | 1847 | buf[4] = 1; |
1611 | etest->flags |= ETH_TEST_FL_FAILED; | 1848 | etest->flags |= ETH_TEST_FL_FAILED; |
1612 | } | 1849 | } |
1613 | if (bp->port.pmf) | 1850 | |
1614 | if (bnx2x_link_test(bp) != 0) { | 1851 | if (bnx2x_link_test(bp, is_serdes) != 0) { |
1615 | buf[5] = 1; | 1852 | buf[5] = 1; |
1616 | etest->flags |= ETH_TEST_FL_FAILED; | 1853 | etest->flags |= ETH_TEST_FL_FAILED; |
1617 | } | 1854 | } |
1618 | 1855 | ||
1619 | #ifdef BNX2X_EXTRA_DEBUG | 1856 | #ifdef BNX2X_EXTRA_DEBUG |
1620 | bnx2x_panic_dump(bp); | 1857 | bnx2x_panic_dump(bp); |
1621 | #endif | 1858 | #endif |
1622 | } | 1859 | } |
1623 | 1860 | ||
1624 | static const struct { | ||
1625 | long offset; | ||
1626 | int size; | ||
1627 | u8 string[ETH_GSTRING_LEN]; | ||
1628 | } bnx2x_q_stats_arr[BNX2X_NUM_Q_STATS] = { | ||
1629 | /* 1 */ { Q_STATS_OFFSET32(total_bytes_received_hi), 8, "[%d]: rx_bytes" }, | ||
1630 | { Q_STATS_OFFSET32(error_bytes_received_hi), | ||
1631 | 8, "[%d]: rx_error_bytes" }, | ||
1632 | { Q_STATS_OFFSET32(total_unicast_packets_received_hi), | ||
1633 | 8, "[%d]: rx_ucast_packets" }, | ||
1634 | { Q_STATS_OFFSET32(total_multicast_packets_received_hi), | ||
1635 | 8, "[%d]: rx_mcast_packets" }, | ||
1636 | { Q_STATS_OFFSET32(total_broadcast_packets_received_hi), | ||
1637 | 8, "[%d]: rx_bcast_packets" }, | ||
1638 | { Q_STATS_OFFSET32(no_buff_discard_hi), 8, "[%d]: rx_discards" }, | ||
1639 | { Q_STATS_OFFSET32(rx_err_discard_pkt), | ||
1640 | 4, "[%d]: rx_phy_ip_err_discards"}, | ||
1641 | { Q_STATS_OFFSET32(rx_skb_alloc_failed), | ||
1642 | 4, "[%d]: rx_skb_alloc_discard" }, | ||
1643 | { Q_STATS_OFFSET32(hw_csum_err), 4, "[%d]: rx_csum_offload_errors" }, | ||
1644 | |||
1645 | /* 10 */{ Q_STATS_OFFSET32(total_bytes_transmitted_hi), 8, "[%d]: tx_bytes" }, | ||
1646 | { Q_STATS_OFFSET32(total_unicast_packets_transmitted_hi), | ||
1647 | 8, "[%d]: tx_ucast_packets" }, | ||
1648 | { Q_STATS_OFFSET32(total_multicast_packets_transmitted_hi), | ||
1649 | 8, "[%d]: tx_mcast_packets" }, | ||
1650 | { Q_STATS_OFFSET32(total_broadcast_packets_transmitted_hi), | ||
1651 | 8, "[%d]: tx_bcast_packets" } | ||
1652 | }; | ||
1653 | |||
1654 | static const struct { | ||
1655 | long offset; | ||
1656 | int size; | ||
1657 | u32 flags; | ||
1658 | #define STATS_FLAGS_PORT 1 | ||
1659 | #define STATS_FLAGS_FUNC 2 | ||
1660 | #define STATS_FLAGS_BOTH (STATS_FLAGS_FUNC | STATS_FLAGS_PORT) | ||
1661 | u8 string[ETH_GSTRING_LEN]; | ||
1662 | } bnx2x_stats_arr[BNX2X_NUM_STATS] = { | ||
1663 | /* 1 */ { STATS_OFFSET32(total_bytes_received_hi), | ||
1664 | 8, STATS_FLAGS_BOTH, "rx_bytes" }, | ||
1665 | { STATS_OFFSET32(error_bytes_received_hi), | ||
1666 | 8, STATS_FLAGS_BOTH, "rx_error_bytes" }, | ||
1667 | { STATS_OFFSET32(total_unicast_packets_received_hi), | ||
1668 | 8, STATS_FLAGS_BOTH, "rx_ucast_packets" }, | ||
1669 | { STATS_OFFSET32(total_multicast_packets_received_hi), | ||
1670 | 8, STATS_FLAGS_BOTH, "rx_mcast_packets" }, | ||
1671 | { STATS_OFFSET32(total_broadcast_packets_received_hi), | ||
1672 | 8, STATS_FLAGS_BOTH, "rx_bcast_packets" }, | ||
1673 | { STATS_OFFSET32(rx_stat_dot3statsfcserrors_hi), | ||
1674 | 8, STATS_FLAGS_PORT, "rx_crc_errors" }, | ||
1675 | { STATS_OFFSET32(rx_stat_dot3statsalignmenterrors_hi), | ||
1676 | 8, STATS_FLAGS_PORT, "rx_align_errors" }, | ||
1677 | { STATS_OFFSET32(rx_stat_etherstatsundersizepkts_hi), | ||
1678 | 8, STATS_FLAGS_PORT, "rx_undersize_packets" }, | ||
1679 | { STATS_OFFSET32(etherstatsoverrsizepkts_hi), | ||
1680 | 8, STATS_FLAGS_PORT, "rx_oversize_packets" }, | ||
1681 | /* 10 */{ STATS_OFFSET32(rx_stat_etherstatsfragments_hi), | ||
1682 | 8, STATS_FLAGS_PORT, "rx_fragments" }, | ||
1683 | { STATS_OFFSET32(rx_stat_etherstatsjabbers_hi), | ||
1684 | 8, STATS_FLAGS_PORT, "rx_jabbers" }, | ||
1685 | { STATS_OFFSET32(no_buff_discard_hi), | ||
1686 | 8, STATS_FLAGS_BOTH, "rx_discards" }, | ||
1687 | { STATS_OFFSET32(mac_filter_discard), | ||
1688 | 4, STATS_FLAGS_PORT, "rx_filtered_packets" }, | ||
1689 | { STATS_OFFSET32(xxoverflow_discard), | ||
1690 | 4, STATS_FLAGS_PORT, "rx_fw_discards" }, | ||
1691 | { STATS_OFFSET32(brb_drop_hi), | ||
1692 | 8, STATS_FLAGS_PORT, "rx_brb_discard" }, | ||
1693 | { STATS_OFFSET32(brb_truncate_hi), | ||
1694 | 8, STATS_FLAGS_PORT, "rx_brb_truncate" }, | ||
1695 | { STATS_OFFSET32(pause_frames_received_hi), | ||
1696 | 8, STATS_FLAGS_PORT, "rx_pause_frames" }, | ||
1697 | { STATS_OFFSET32(rx_stat_maccontrolframesreceived_hi), | ||
1698 | 8, STATS_FLAGS_PORT, "rx_mac_ctrl_frames" }, | ||
1699 | { STATS_OFFSET32(nig_timer_max), | ||
1700 | 4, STATS_FLAGS_PORT, "rx_constant_pause_events" }, | ||
1701 | /* 20 */{ STATS_OFFSET32(rx_err_discard_pkt), | ||
1702 | 4, STATS_FLAGS_BOTH, "rx_phy_ip_err_discards"}, | ||
1703 | { STATS_OFFSET32(rx_skb_alloc_failed), | ||
1704 | 4, STATS_FLAGS_BOTH, "rx_skb_alloc_discard" }, | ||
1705 | { STATS_OFFSET32(hw_csum_err), | ||
1706 | 4, STATS_FLAGS_BOTH, "rx_csum_offload_errors" }, | ||
1707 | |||
1708 | { STATS_OFFSET32(total_bytes_transmitted_hi), | ||
1709 | 8, STATS_FLAGS_BOTH, "tx_bytes" }, | ||
1710 | { STATS_OFFSET32(tx_stat_ifhcoutbadoctets_hi), | ||
1711 | 8, STATS_FLAGS_PORT, "tx_error_bytes" }, | ||
1712 | { STATS_OFFSET32(total_unicast_packets_transmitted_hi), | ||
1713 | 8, STATS_FLAGS_BOTH, "tx_ucast_packets" }, | ||
1714 | { STATS_OFFSET32(total_multicast_packets_transmitted_hi), | ||
1715 | 8, STATS_FLAGS_BOTH, "tx_mcast_packets" }, | ||
1716 | { STATS_OFFSET32(total_broadcast_packets_transmitted_hi), | ||
1717 | 8, STATS_FLAGS_BOTH, "tx_bcast_packets" }, | ||
1718 | { STATS_OFFSET32(tx_stat_dot3statsinternalmactransmiterrors_hi), | ||
1719 | 8, STATS_FLAGS_PORT, "tx_mac_errors" }, | ||
1720 | { STATS_OFFSET32(rx_stat_dot3statscarriersenseerrors_hi), | ||
1721 | 8, STATS_FLAGS_PORT, "tx_carrier_errors" }, | ||
1722 | /* 30 */{ STATS_OFFSET32(tx_stat_dot3statssinglecollisionframes_hi), | ||
1723 | 8, STATS_FLAGS_PORT, "tx_single_collisions" }, | ||
1724 | { STATS_OFFSET32(tx_stat_dot3statsmultiplecollisionframes_hi), | ||
1725 | 8, STATS_FLAGS_PORT, "tx_multi_collisions" }, | ||
1726 | { STATS_OFFSET32(tx_stat_dot3statsdeferredtransmissions_hi), | ||
1727 | 8, STATS_FLAGS_PORT, "tx_deferred" }, | ||
1728 | { STATS_OFFSET32(tx_stat_dot3statsexcessivecollisions_hi), | ||
1729 | 8, STATS_FLAGS_PORT, "tx_excess_collisions" }, | ||
1730 | { STATS_OFFSET32(tx_stat_dot3statslatecollisions_hi), | ||
1731 | 8, STATS_FLAGS_PORT, "tx_late_collisions" }, | ||
1732 | { STATS_OFFSET32(tx_stat_etherstatscollisions_hi), | ||
1733 | 8, STATS_FLAGS_PORT, "tx_total_collisions" }, | ||
1734 | { STATS_OFFSET32(tx_stat_etherstatspkts64octets_hi), | ||
1735 | 8, STATS_FLAGS_PORT, "tx_64_byte_packets" }, | ||
1736 | { STATS_OFFSET32(tx_stat_etherstatspkts65octetsto127octets_hi), | ||
1737 | 8, STATS_FLAGS_PORT, "tx_65_to_127_byte_packets" }, | ||
1738 | { STATS_OFFSET32(tx_stat_etherstatspkts128octetsto255octets_hi), | ||
1739 | 8, STATS_FLAGS_PORT, "tx_128_to_255_byte_packets" }, | ||
1740 | { STATS_OFFSET32(tx_stat_etherstatspkts256octetsto511octets_hi), | ||
1741 | 8, STATS_FLAGS_PORT, "tx_256_to_511_byte_packets" }, | ||
1742 | /* 40 */{ STATS_OFFSET32(tx_stat_etherstatspkts512octetsto1023octets_hi), | ||
1743 | 8, STATS_FLAGS_PORT, "tx_512_to_1023_byte_packets" }, | ||
1744 | { STATS_OFFSET32(etherstatspkts1024octetsto1522octets_hi), | ||
1745 | 8, STATS_FLAGS_PORT, "tx_1024_to_1522_byte_packets" }, | ||
1746 | { STATS_OFFSET32(etherstatspktsover1522octets_hi), | ||
1747 | 8, STATS_FLAGS_PORT, "tx_1523_to_9022_byte_packets" }, | ||
1748 | { STATS_OFFSET32(pause_frames_sent_hi), | ||
1749 | 8, STATS_FLAGS_PORT, "tx_pause_frames" } | ||
1750 | }; | ||
1751 | |||
1752 | #define IS_PORT_STAT(i) \ | 1861 | #define IS_PORT_STAT(i) \ |
1753 | ((bnx2x_stats_arr[i].flags & STATS_FLAGS_BOTH) == STATS_FLAGS_PORT) | 1862 | ((bnx2x_stats_arr[i].flags & STATS_FLAGS_BOTH) == STATS_FLAGS_PORT) |
1754 | #define IS_FUNC_STAT(i) (bnx2x_stats_arr[i].flags & STATS_FLAGS_FUNC) | 1863 | #define IS_FUNC_STAT(i) (bnx2x_stats_arr[i].flags & STATS_FLAGS_FUNC) |
1755 | #define IS_E1HMF_MODE_STAT(bp) \ | 1864 | #define IS_MF_MODE_STAT(bp) \ |
1756 | (IS_E1HMF(bp) && !(bp->msg_enable & BNX2X_MSG_STATS)) | 1865 | (IS_MF(bp) && !(bp->msg_enable & BNX2X_MSG_STATS)) |
1757 | 1866 | ||
1758 | static int bnx2x_get_sset_count(struct net_device *dev, int stringset) | 1867 | static int bnx2x_get_sset_count(struct net_device *dev, int stringset) |
1759 | { | 1868 | { |
@@ -1763,11 +1872,12 @@ static int bnx2x_get_sset_count(struct net_device *dev, int stringset) | |||
1763 | switch (stringset) { | 1872 | switch (stringset) { |
1764 | case ETH_SS_STATS: | 1873 | case ETH_SS_STATS: |
1765 | if (is_multi(bp)) { | 1874 | if (is_multi(bp)) { |
1766 | num_stats = BNX2X_NUM_Q_STATS * bp->num_queues; | 1875 | num_stats = BNX2X_NUM_STAT_QUEUES(bp) * |
1767 | if (!IS_E1HMF_MODE_STAT(bp)) | 1876 | BNX2X_NUM_Q_STATS; |
1877 | if (!IS_MF_MODE_STAT(bp)) | ||
1768 | num_stats += BNX2X_NUM_STATS; | 1878 | num_stats += BNX2X_NUM_STATS; |
1769 | } else { | 1879 | } else { |
1770 | if (IS_E1HMF_MODE_STAT(bp)) { | 1880 | if (IS_MF_MODE_STAT(bp)) { |
1771 | num_stats = 0; | 1881 | num_stats = 0; |
1772 | for (i = 0; i < BNX2X_NUM_STATS; i++) | 1882 | for (i = 0; i < BNX2X_NUM_STATS; i++) |
1773 | if (IS_FUNC_STAT(i)) | 1883 | if (IS_FUNC_STAT(i)) |
@@ -1789,25 +1899,35 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf) | |||
1789 | { | 1899 | { |
1790 | struct bnx2x *bp = netdev_priv(dev); | 1900 | struct bnx2x *bp = netdev_priv(dev); |
1791 | int i, j, k; | 1901 | int i, j, k; |
1902 | char queue_name[MAX_QUEUE_NAME_LEN+1]; | ||
1792 | 1903 | ||
1793 | switch (stringset) { | 1904 | switch (stringset) { |
1794 | case ETH_SS_STATS: | 1905 | case ETH_SS_STATS: |
1795 | if (is_multi(bp)) { | 1906 | if (is_multi(bp)) { |
1796 | k = 0; | 1907 | k = 0; |
1797 | for_each_queue(bp, i) { | 1908 | for_each_napi_queue(bp, i) { |
1909 | memset(queue_name, 0, sizeof(queue_name)); | ||
1910 | |||
1911 | if (IS_FCOE_IDX(i)) | ||
1912 | sprintf(queue_name, "fcoe"); | ||
1913 | else | ||
1914 | sprintf(queue_name, "%d", i); | ||
1915 | |||
1798 | for (j = 0; j < BNX2X_NUM_Q_STATS; j++) | 1916 | for (j = 0; j < BNX2X_NUM_Q_STATS; j++) |
1799 | sprintf(buf + (k + j)*ETH_GSTRING_LEN, | 1917 | snprintf(buf + (k + j)*ETH_GSTRING_LEN, |
1800 | bnx2x_q_stats_arr[j].string, i); | 1918 | ETH_GSTRING_LEN, |
1919 | bnx2x_q_stats_arr[j].string, | ||
1920 | queue_name); | ||
1801 | k += BNX2X_NUM_Q_STATS; | 1921 | k += BNX2X_NUM_Q_STATS; |
1802 | } | 1922 | } |
1803 | if (IS_E1HMF_MODE_STAT(bp)) | 1923 | if (IS_MF_MODE_STAT(bp)) |
1804 | break; | 1924 | break; |
1805 | for (j = 0; j < BNX2X_NUM_STATS; j++) | 1925 | for (j = 0; j < BNX2X_NUM_STATS; j++) |
1806 | strcpy(buf + (k + j)*ETH_GSTRING_LEN, | 1926 | strcpy(buf + (k + j)*ETH_GSTRING_LEN, |
1807 | bnx2x_stats_arr[j].string); | 1927 | bnx2x_stats_arr[j].string); |
1808 | } else { | 1928 | } else { |
1809 | for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) { | 1929 | for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) { |
1810 | if (IS_E1HMF_MODE_STAT(bp) && IS_PORT_STAT(i)) | 1930 | if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i)) |
1811 | continue; | 1931 | continue; |
1812 | strcpy(buf + j*ETH_GSTRING_LEN, | 1932 | strcpy(buf + j*ETH_GSTRING_LEN, |
1813 | bnx2x_stats_arr[i].string); | 1933 | bnx2x_stats_arr[i].string); |
@@ -1831,7 +1951,7 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev, | |||
1831 | 1951 | ||
1832 | if (is_multi(bp)) { | 1952 | if (is_multi(bp)) { |
1833 | k = 0; | 1953 | k = 0; |
1834 | for_each_queue(bp, i) { | 1954 | for_each_napi_queue(bp, i) { |
1835 | hw_stats = (u32 *)&bp->fp[i].eth_q_stats; | 1955 | hw_stats = (u32 *)&bp->fp[i].eth_q_stats; |
1836 | for (j = 0; j < BNX2X_NUM_Q_STATS; j++) { | 1956 | for (j = 0; j < BNX2X_NUM_Q_STATS; j++) { |
1837 | if (bnx2x_q_stats_arr[j].size == 0) { | 1957 | if (bnx2x_q_stats_arr[j].size == 0) { |
@@ -1851,7 +1971,7 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev, | |||
1851 | } | 1971 | } |
1852 | k += BNX2X_NUM_Q_STATS; | 1972 | k += BNX2X_NUM_Q_STATS; |
1853 | } | 1973 | } |
1854 | if (IS_E1HMF_MODE_STAT(bp)) | 1974 | if (IS_MF_MODE_STAT(bp)) |
1855 | return; | 1975 | return; |
1856 | hw_stats = (u32 *)&bp->eth_stats; | 1976 | hw_stats = (u32 *)&bp->eth_stats; |
1857 | for (j = 0; j < BNX2X_NUM_STATS; j++) { | 1977 | for (j = 0; j < BNX2X_NUM_STATS; j++) { |
@@ -1872,7 +1992,7 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev, | |||
1872 | } else { | 1992 | } else { |
1873 | hw_stats = (u32 *)&bp->eth_stats; | 1993 | hw_stats = (u32 *)&bp->eth_stats; |
1874 | for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) { | 1994 | for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) { |
1875 | if (IS_E1HMF_MODE_STAT(bp) && IS_PORT_STAT(i)) | 1995 | if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i)) |
1876 | continue; | 1996 | continue; |
1877 | if (bnx2x_stats_arr[i].size == 0) { | 1997 | if (bnx2x_stats_arr[i].size == 0) { |
1878 | /* skip this counter */ | 1998 | /* skip this counter */ |
@@ -1894,36 +2014,91 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev, | |||
1894 | } | 2014 | } |
1895 | } | 2015 | } |
1896 | 2016 | ||
1897 | static int bnx2x_phys_id(struct net_device *dev, u32 data) | 2017 | static int bnx2x_set_phys_id(struct net_device *dev, |
2018 | enum ethtool_phys_id_state state) | ||
1898 | { | 2019 | { |
1899 | struct bnx2x *bp = netdev_priv(dev); | 2020 | struct bnx2x *bp = netdev_priv(dev); |
1900 | int i; | ||
1901 | 2021 | ||
1902 | if (!netif_running(dev)) | 2022 | if (!netif_running(dev)) |
1903 | return 0; | 2023 | return -EAGAIN; |
1904 | 2024 | ||
1905 | if (!bp->port.pmf) | 2025 | if (!bp->port.pmf) |
1906 | return 0; | 2026 | return -EOPNOTSUPP; |
1907 | 2027 | ||
1908 | if (data == 0) | 2028 | switch (state) { |
1909 | data = 2; | 2029 | case ETHTOOL_ID_ACTIVE: |
2030 | return 1; /* cycle on/off once per second */ | ||
1910 | 2031 | ||
1911 | for (i = 0; i < (data * 2); i++) { | 2032 | case ETHTOOL_ID_ON: |
1912 | if ((i % 2) == 0) | 2033 | bnx2x_set_led(&bp->link_params, &bp->link_vars, |
1913 | bnx2x_set_led(&bp->link_params, LED_MODE_OPER, | 2034 | LED_MODE_ON, SPEED_1000); |
1914 | SPEED_1000); | 2035 | break; |
1915 | else | ||
1916 | bnx2x_set_led(&bp->link_params, LED_MODE_OFF, 0); | ||
1917 | 2036 | ||
1918 | msleep_interruptible(500); | 2037 | case ETHTOOL_ID_OFF: |
1919 | if (signal_pending(current)) | 2038 | bnx2x_set_led(&bp->link_params, &bp->link_vars, |
1920 | break; | 2039 | LED_MODE_FRONT_PANEL_OFF, 0); |
1921 | } | 2040 | |
2041 | break; | ||
1922 | 2042 | ||
1923 | if (bp->link_vars.link_up) | 2043 | case ETHTOOL_ID_INACTIVE: |
1924 | bnx2x_set_led(&bp->link_params, LED_MODE_OPER, | 2044 | bnx2x_set_led(&bp->link_params, &bp->link_vars, |
2045 | LED_MODE_OPER, | ||
1925 | bp->link_vars.line_speed); | 2046 | bp->link_vars.line_speed); |
2047 | } | ||
2048 | |||
2049 | return 0; | ||
2050 | } | ||
2051 | |||
2052 | static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, | ||
2053 | void *rules __always_unused) | ||
2054 | { | ||
2055 | struct bnx2x *bp = netdev_priv(dev); | ||
2056 | |||
2057 | switch (info->cmd) { | ||
2058 | case ETHTOOL_GRXRINGS: | ||
2059 | info->data = BNX2X_NUM_ETH_QUEUES(bp); | ||
2060 | return 0; | ||
2061 | |||
2062 | default: | ||
2063 | return -EOPNOTSUPP; | ||
2064 | } | ||
2065 | } | ||
2066 | |||
2067 | static int bnx2x_get_rxfh_indir(struct net_device *dev, | ||
2068 | struct ethtool_rxfh_indir *indir) | ||
2069 | { | ||
2070 | struct bnx2x *bp = netdev_priv(dev); | ||
2071 | size_t copy_size = | ||
2072 | min_t(size_t, indir->size, TSTORM_INDIRECTION_TABLE_SIZE); | ||
2073 | |||
2074 | if (bp->multi_mode == ETH_RSS_MODE_DISABLED) | ||
2075 | return -EOPNOTSUPP; | ||
2076 | |||
2077 | indir->size = TSTORM_INDIRECTION_TABLE_SIZE; | ||
2078 | memcpy(indir->ring_index, bp->rx_indir_table, | ||
2079 | copy_size * sizeof(bp->rx_indir_table[0])); | ||
2080 | return 0; | ||
2081 | } | ||
2082 | |||
2083 | static int bnx2x_set_rxfh_indir(struct net_device *dev, | ||
2084 | const struct ethtool_rxfh_indir *indir) | ||
2085 | { | ||
2086 | struct bnx2x *bp = netdev_priv(dev); | ||
2087 | size_t i; | ||
2088 | |||
2089 | if (bp->multi_mode == ETH_RSS_MODE_DISABLED) | ||
2090 | return -EOPNOTSUPP; | ||
2091 | |||
2092 | /* Validate size and indices */ | ||
2093 | if (indir->size != TSTORM_INDIRECTION_TABLE_SIZE) | ||
2094 | return -EINVAL; | ||
2095 | for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++) | ||
2096 | if (indir->ring_index[i] >= BNX2X_NUM_ETH_QUEUES(bp)) | ||
2097 | return -EINVAL; | ||
1926 | 2098 | ||
2099 | memcpy(bp->rx_indir_table, indir->ring_index, | ||
2100 | indir->size * sizeof(bp->rx_indir_table[0])); | ||
2101 | bnx2x_push_indir_table(bp); | ||
1927 | return 0; | 2102 | return 0; |
1928 | } | 2103 | } |
1929 | 2104 | ||
@@ -1948,21 +2123,14 @@ static const struct ethtool_ops bnx2x_ethtool_ops = { | |||
1948 | .set_ringparam = bnx2x_set_ringparam, | 2123 | .set_ringparam = bnx2x_set_ringparam, |
1949 | .get_pauseparam = bnx2x_get_pauseparam, | 2124 | .get_pauseparam = bnx2x_get_pauseparam, |
1950 | .set_pauseparam = bnx2x_set_pauseparam, | 2125 | .set_pauseparam = bnx2x_set_pauseparam, |
1951 | .get_rx_csum = bnx2x_get_rx_csum, | ||
1952 | .set_rx_csum = bnx2x_set_rx_csum, | ||
1953 | .get_tx_csum = ethtool_op_get_tx_csum, | ||
1954 | .set_tx_csum = ethtool_op_set_tx_hw_csum, | ||
1955 | .set_flags = bnx2x_set_flags, | ||
1956 | .get_flags = ethtool_op_get_flags, | ||
1957 | .get_sg = ethtool_op_get_sg, | ||
1958 | .set_sg = ethtool_op_set_sg, | ||
1959 | .get_tso = ethtool_op_get_tso, | ||
1960 | .set_tso = bnx2x_set_tso, | ||
1961 | .self_test = bnx2x_self_test, | 2126 | .self_test = bnx2x_self_test, |
1962 | .get_sset_count = bnx2x_get_sset_count, | 2127 | .get_sset_count = bnx2x_get_sset_count, |
1963 | .get_strings = bnx2x_get_strings, | 2128 | .get_strings = bnx2x_get_strings, |
1964 | .phys_id = bnx2x_phys_id, | 2129 | .set_phys_id = bnx2x_set_phys_id, |
1965 | .get_ethtool_stats = bnx2x_get_ethtool_stats, | 2130 | .get_ethtool_stats = bnx2x_get_ethtool_stats, |
2131 | .get_rxnfc = bnx2x_get_rxnfc, | ||
2132 | .get_rxfh_indir = bnx2x_get_rxfh_indir, | ||
2133 | .set_rxfh_indir = bnx2x_set_rxfh_indir, | ||
1966 | }; | 2134 | }; |
1967 | 2135 | ||
1968 | void bnx2x_set_ethtool_ops(struct net_device *netdev) | 2136 | void bnx2x_set_ethtool_ops(struct net_device *netdev) |