aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/benet/be_ethtool.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/net/benet/be_ethtool.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/net/benet/be_ethtool.c')
-rw-r--r--drivers/net/benet/be_ethtool.c443
1 files changed, 244 insertions, 199 deletions
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index 13f0abbc5205..facfe3ca5c40 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2005 - 2010 ServerEngines 2 * Copyright (C) 2005 - 2011 Emulex
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -8,11 +8,11 @@
8 * Public License is included in this distribution in the file called COPYING. 8 * Public License is included in this distribution in the file called COPYING.
9 * 9 *
10 * Contact Information: 10 * Contact Information:
11 * linux-drivers@serverengines.com 11 * linux-drivers@emulex.com
12 * 12 *
13 * ServerEngines 13 * Emulex
14 * 209 N. Fair Oaks Ave 14 * 3333 Susan Street
15 * Sunnyvale, CA 94085 15 * Costa Mesa, CA 92626
16 */ 16 */
17 17
18#include "be.h" 18#include "be.h"
@@ -26,21 +26,22 @@ struct be_ethtool_stat {
26 int offset; 26 int offset;
27}; 27};
28 28
29enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT, ERXSTAT}; 29enum {NETSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT,
30 DRVSTAT};
30#define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \ 31#define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \
31 offsetof(_struct, field) 32 offsetof(_struct, field)
32#define NETSTAT_INFO(field) #field, NETSTAT,\ 33#define NETSTAT_INFO(field) #field, NETSTAT,\
33 FIELDINFO(struct net_device_stats,\ 34 FIELDINFO(struct net_device_stats,\
34 field) 35 field)
35#define DRVSTAT_INFO(field) #field, DRVSTAT,\ 36#define DRVSTAT_TX_INFO(field) #field, DRVSTAT_TX,\
36 FIELDINFO(struct be_drvr_stats, field) 37 FIELDINFO(struct be_tx_stats, field)
37#define MISCSTAT_INFO(field) #field, MISCSTAT,\ 38#define DRVSTAT_RX_INFO(field) #field, DRVSTAT_RX,\
38 FIELDINFO(struct be_rxf_stats, field) 39 FIELDINFO(struct be_rx_stats, field)
39#define PORTSTAT_INFO(field) #field, PORTSTAT,\ 40#define ERXSTAT_INFO(field) #field, ERXSTAT,\
40 FIELDINFO(struct be_port_rxf_stats, \ 41 FIELDINFO(struct be_erx_stats_v1, field)
42#define DRVSTAT_INFO(field) #field, DRVSTAT,\
43 FIELDINFO(struct be_drv_stats, \
41 field) 44 field)
42#define ERXSTAT_INFO(field) #field, ERXSTAT,\
43 FIELDINFO(struct be_erx_stats, field)
44 45
45static const struct be_ethtool_stat et_stats[] = { 46static const struct be_ethtool_stat et_stats[] = {
46 {NETSTAT_INFO(rx_packets)}, 47 {NETSTAT_INFO(rx_packets)},
@@ -51,68 +52,70 @@ static const struct be_ethtool_stat et_stats[] = {
51 {NETSTAT_INFO(tx_errors)}, 52 {NETSTAT_INFO(tx_errors)},
52 {NETSTAT_INFO(rx_dropped)}, 53 {NETSTAT_INFO(rx_dropped)},
53 {NETSTAT_INFO(tx_dropped)}, 54 {NETSTAT_INFO(tx_dropped)},
54 {DRVSTAT_INFO(be_tx_reqs)}, 55 {DRVSTAT_TX_INFO(be_tx_rate)},
55 {DRVSTAT_INFO(be_tx_stops)}, 56 {DRVSTAT_TX_INFO(be_tx_reqs)},
56 {DRVSTAT_INFO(be_fwd_reqs)}, 57 {DRVSTAT_TX_INFO(be_tx_wrbs)},
57 {DRVSTAT_INFO(be_tx_wrbs)}, 58 {DRVSTAT_TX_INFO(be_tx_stops)},
58 {DRVSTAT_INFO(be_rx_polls)}, 59 {DRVSTAT_TX_INFO(be_tx_events)},
59 {DRVSTAT_INFO(be_tx_events)}, 60 {DRVSTAT_TX_INFO(be_tx_compl)},
60 {DRVSTAT_INFO(be_rx_events)}, 61 {DRVSTAT_INFO(rx_crc_errors)},
61 {DRVSTAT_INFO(be_tx_compl)}, 62 {DRVSTAT_INFO(rx_alignment_symbol_errors)},
62 {DRVSTAT_INFO(be_rx_compl)}, 63 {DRVSTAT_INFO(rx_pause_frames)},
63 {DRVSTAT_INFO(be_rx_mcast_pkt)}, 64 {DRVSTAT_INFO(rx_control_frames)},
64 {DRVSTAT_INFO(be_ethrx_post_fail)}, 65 {DRVSTAT_INFO(rx_in_range_errors)},
65 {DRVSTAT_INFO(be_802_3_dropped_frames)}, 66 {DRVSTAT_INFO(rx_out_range_errors)},
66 {DRVSTAT_INFO(be_802_3_malformed_frames)}, 67 {DRVSTAT_INFO(rx_frame_too_long)},
67 {DRVSTAT_INFO(be_tx_rate)}, 68 {DRVSTAT_INFO(rx_address_match_errors)},
68 {DRVSTAT_INFO(be_rx_rate)}, 69 {DRVSTAT_INFO(rx_dropped_too_small)},
69 {PORTSTAT_INFO(rx_unicast_frames)}, 70 {DRVSTAT_INFO(rx_dropped_too_short)},
70 {PORTSTAT_INFO(rx_multicast_frames)}, 71 {DRVSTAT_INFO(rx_dropped_header_too_small)},
71 {PORTSTAT_INFO(rx_broadcast_frames)}, 72 {DRVSTAT_INFO(rx_dropped_tcp_length)},
72 {PORTSTAT_INFO(rx_crc_errors)}, 73 {DRVSTAT_INFO(rx_dropped_runt)},
73 {PORTSTAT_INFO(rx_alignment_symbol_errors)}, 74 {DRVSTAT_INFO(rxpp_fifo_overflow_drop)},
74 {PORTSTAT_INFO(rx_pause_frames)}, 75 {DRVSTAT_INFO(rx_input_fifo_overflow_drop)},
75 {PORTSTAT_INFO(rx_control_frames)}, 76 {DRVSTAT_INFO(rx_ip_checksum_errs)},
76 {PORTSTAT_INFO(rx_in_range_errors)}, 77 {DRVSTAT_INFO(rx_tcp_checksum_errs)},
77 {PORTSTAT_INFO(rx_out_range_errors)}, 78 {DRVSTAT_INFO(rx_udp_checksum_errs)},
78 {PORTSTAT_INFO(rx_frame_too_long)}, 79 {DRVSTAT_INFO(rx_switched_unicast_packets)},
79 {PORTSTAT_INFO(rx_address_match_errors)}, 80 {DRVSTAT_INFO(rx_switched_multicast_packets)},
80 {PORTSTAT_INFO(rx_vlan_mismatch)}, 81 {DRVSTAT_INFO(rx_switched_broadcast_packets)},
81 {PORTSTAT_INFO(rx_dropped_too_small)}, 82 {DRVSTAT_INFO(tx_pauseframes)},
82 {PORTSTAT_INFO(rx_dropped_too_short)}, 83 {DRVSTAT_INFO(tx_controlframes)},
83 {PORTSTAT_INFO(rx_dropped_header_too_small)}, 84 {DRVSTAT_INFO(rx_priority_pause_frames)},
84 {PORTSTAT_INFO(rx_dropped_tcp_length)}, 85 {DRVSTAT_INFO(pmem_fifo_overflow_drop)},
85 {PORTSTAT_INFO(rx_dropped_runt)}, 86 {DRVSTAT_INFO(jabber_events)},
86 {PORTSTAT_INFO(rx_fifo_overflow)}, 87 {DRVSTAT_INFO(rx_drops_no_pbuf)},
87 {PORTSTAT_INFO(rx_input_fifo_overflow)}, 88 {DRVSTAT_INFO(rx_drops_no_txpb)},
88 {PORTSTAT_INFO(rx_ip_checksum_errs)}, 89 {DRVSTAT_INFO(rx_drops_no_erx_descr)},
89 {PORTSTAT_INFO(rx_tcp_checksum_errs)}, 90 {DRVSTAT_INFO(rx_drops_no_tpre_descr)},
90 {PORTSTAT_INFO(rx_udp_checksum_errs)}, 91 {DRVSTAT_INFO(rx_drops_too_many_frags)},
91 {PORTSTAT_INFO(rx_non_rss_packets)}, 92 {DRVSTAT_INFO(rx_drops_invalid_ring)},
92 {PORTSTAT_INFO(rx_ipv4_packets)}, 93 {DRVSTAT_INFO(forwarded_packets)},
93 {PORTSTAT_INFO(rx_ipv6_packets)}, 94 {DRVSTAT_INFO(rx_drops_mtu)},
94 {PORTSTAT_INFO(tx_unicastframes)}, 95 {DRVSTAT_INFO(eth_red_drops)},
95 {PORTSTAT_INFO(tx_multicastframes)}, 96 {DRVSTAT_INFO(be_on_die_temperature)}
96 {PORTSTAT_INFO(tx_broadcastframes)},
97 {PORTSTAT_INFO(tx_pauseframes)},
98 {PORTSTAT_INFO(tx_controlframes)},
99 {MISCSTAT_INFO(rx_drops_no_pbuf)},
100 {MISCSTAT_INFO(rx_drops_no_txpb)},
101 {MISCSTAT_INFO(rx_drops_no_erx_descr)},
102 {MISCSTAT_INFO(rx_drops_no_tpre_descr)},
103 {MISCSTAT_INFO(rx_drops_too_many_frags)},
104 {MISCSTAT_INFO(rx_drops_invalid_ring)},
105 {MISCSTAT_INFO(forwarded_packets)},
106 {MISCSTAT_INFO(rx_drops_mtu)},
107 {ERXSTAT_INFO(rx_drops_no_fragments)},
108}; 97};
109#define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats) 98#define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats)
110 99
100/* Stats related to multi RX queues */
101static const struct be_ethtool_stat et_rx_stats[] = {
102 {DRVSTAT_RX_INFO(rx_bytes)},
103 {DRVSTAT_RX_INFO(rx_pkts)},
104 {DRVSTAT_RX_INFO(rx_rate)},
105 {DRVSTAT_RX_INFO(rx_polls)},
106 {DRVSTAT_RX_INFO(rx_events)},
107 {DRVSTAT_RX_INFO(rx_compl)},
108 {DRVSTAT_RX_INFO(rx_mcast_pkts)},
109 {DRVSTAT_RX_INFO(rx_post_fail)},
110 {ERXSTAT_INFO(rx_drops_no_fragments)}
111};
112#define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats))
113
111static const char et_self_tests[][ETH_GSTRING_LEN] = { 114static const char et_self_tests[][ETH_GSTRING_LEN] = {
112 "MAC Loopback test", 115 "MAC Loopback test",
113 "PHY Loopback test", 116 "PHY Loopback test",
114 "External Loopback test", 117 "External Loopback test",
115 "DDR DMA test" 118 "DDR DMA test",
116 "Link test" 119 "Link test"
117}; 120};
118 121
@@ -137,10 +140,33 @@ be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
137} 140}
138 141
139static int 142static int
143be_get_reg_len(struct net_device *netdev)
144{
145 struct be_adapter *adapter = netdev_priv(netdev);
146 u32 log_size = 0;
147
148 if (be_physfn(adapter))
149 be_cmd_get_reg_len(adapter, &log_size);
150
151 return log_size;
152}
153
154static void
155be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
156{
157 struct be_adapter *adapter = netdev_priv(netdev);
158
159 if (be_physfn(adapter)) {
160 memset(buf, 0, regs->len);
161 be_cmd_get_regs(adapter, regs->len, buf);
162 }
163}
164
165static int
140be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) 166be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
141{ 167{
142 struct be_adapter *adapter = netdev_priv(netdev); 168 struct be_adapter *adapter = netdev_priv(netdev);
143 struct be_eq_obj *rx_eq = &adapter->rx_eq; 169 struct be_eq_obj *rx_eq = &adapter->rx_obj[0].rx_eq;
144 struct be_eq_obj *tx_eq = &adapter->tx_eq; 170 struct be_eq_obj *tx_eq = &adapter->tx_eq;
145 171
146 coalesce->rx_coalesce_usecs = rx_eq->cur_eqd; 172 coalesce->rx_coalesce_usecs = rx_eq->cur_eqd;
@@ -164,28 +190,50 @@ static int
164be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) 190be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
165{ 191{
166 struct be_adapter *adapter = netdev_priv(netdev); 192 struct be_adapter *adapter = netdev_priv(netdev);
167 struct be_eq_obj *rx_eq = &adapter->rx_eq; 193 struct be_rx_obj *rxo;
194 struct be_eq_obj *rx_eq;
168 struct be_eq_obj *tx_eq = &adapter->tx_eq; 195 struct be_eq_obj *tx_eq = &adapter->tx_eq;
169 u32 tx_max, tx_min, tx_cur;
170 u32 rx_max, rx_min, rx_cur; 196 u32 rx_max, rx_min, rx_cur;
171 int status = 0; 197 int status = 0, i;
198 u32 tx_cur;
172 199
173 if (coalesce->use_adaptive_tx_coalesce == 1) 200 if (coalesce->use_adaptive_tx_coalesce == 1)
174 return -EINVAL; 201 return -EINVAL;
175 202
176 /* if AIC is being turned on now, start with an EQD of 0 */ 203 for_all_rx_queues(adapter, rxo, i) {
177 if (rx_eq->enable_aic == 0 && 204 rx_eq = &rxo->rx_eq;
178 coalesce->use_adaptive_rx_coalesce == 1) { 205
179 rx_eq->cur_eqd = 0; 206 if (!rx_eq->enable_aic && coalesce->use_adaptive_rx_coalesce)
207 rx_eq->cur_eqd = 0;
208 rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce;
209
210 rx_max = coalesce->rx_coalesce_usecs_high;
211 rx_min = coalesce->rx_coalesce_usecs_low;
212 rx_cur = coalesce->rx_coalesce_usecs;
213
214 if (rx_eq->enable_aic) {
215 if (rx_max > BE_MAX_EQD)
216 rx_max = BE_MAX_EQD;
217 if (rx_min > rx_max)
218 rx_min = rx_max;
219 rx_eq->max_eqd = rx_max;
220 rx_eq->min_eqd = rx_min;
221 if (rx_eq->cur_eqd > rx_max)
222 rx_eq->cur_eqd = rx_max;
223 if (rx_eq->cur_eqd < rx_min)
224 rx_eq->cur_eqd = rx_min;
225 } else {
226 if (rx_cur > BE_MAX_EQD)
227 rx_cur = BE_MAX_EQD;
228 if (rx_eq->cur_eqd != rx_cur) {
229 status = be_cmd_modify_eqd(adapter, rx_eq->q.id,
230 rx_cur);
231 if (!status)
232 rx_eq->cur_eqd = rx_cur;
233 }
234 }
180 } 235 }
181 rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce;
182 236
183 rx_max = coalesce->rx_coalesce_usecs_high;
184 rx_min = coalesce->rx_coalesce_usecs_low;
185 rx_cur = coalesce->rx_coalesce_usecs;
186
187 tx_max = coalesce->tx_coalesce_usecs_high;
188 tx_min = coalesce->tx_coalesce_usecs_low;
189 tx_cur = coalesce->tx_coalesce_usecs; 237 tx_cur = coalesce->tx_coalesce_usecs;
190 238
191 if (tx_cur > BE_MAX_EQD) 239 if (tx_cur > BE_MAX_EQD)
@@ -196,46 +244,6 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
196 tx_eq->cur_eqd = tx_cur; 244 tx_eq->cur_eqd = tx_cur;
197 } 245 }
198 246
199 if (rx_eq->enable_aic) {
200 if (rx_max > BE_MAX_EQD)
201 rx_max = BE_MAX_EQD;
202 if (rx_min > rx_max)
203 rx_min = rx_max;
204 rx_eq->max_eqd = rx_max;
205 rx_eq->min_eqd = rx_min;
206 if (rx_eq->cur_eqd > rx_max)
207 rx_eq->cur_eqd = rx_max;
208 if (rx_eq->cur_eqd < rx_min)
209 rx_eq->cur_eqd = rx_min;
210 } else {
211 if (rx_cur > BE_MAX_EQD)
212 rx_cur = BE_MAX_EQD;
213 if (rx_eq->cur_eqd != rx_cur) {
214 status = be_cmd_modify_eqd(adapter, rx_eq->q.id,
215 rx_cur);
216 if (!status)
217 rx_eq->cur_eqd = rx_cur;
218 }
219 }
220 return 0;
221}
222
223static u32 be_get_rx_csum(struct net_device *netdev)
224{
225 struct be_adapter *adapter = netdev_priv(netdev);
226
227 return adapter->rx_csum;
228}
229
230static int be_set_rx_csum(struct net_device *netdev, uint32_t data)
231{
232 struct be_adapter *adapter = netdev_priv(netdev);
233
234 if (data)
235 adapter->rx_csum = true;
236 else
237 adapter->rx_csum = false;
238
239 return 0; 247 return 0;
240} 248}
241 249
@@ -244,32 +252,20 @@ be_get_ethtool_stats(struct net_device *netdev,
244 struct ethtool_stats *stats, uint64_t *data) 252 struct ethtool_stats *stats, uint64_t *data)
245{ 253{
246 struct be_adapter *adapter = netdev_priv(netdev); 254 struct be_adapter *adapter = netdev_priv(netdev);
247 struct be_drvr_stats *drvr_stats = &adapter->stats.drvr_stats; 255 struct be_rx_obj *rxo;
248 struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va);
249 struct be_rxf_stats *rxf_stats = &hw_stats->rxf;
250 struct be_port_rxf_stats *port_stats =
251 &rxf_stats->port[adapter->port_num];
252 struct net_device_stats *net_stats = &netdev->stats;
253 struct be_erx_stats *erx_stats = &hw_stats->erx;
254 void *p = NULL; 256 void *p = NULL;
255 int i; 257 int i, j;
256 258
257 for (i = 0; i < ETHTOOL_STATS_NUM; i++) { 259 for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
258 switch (et_stats[i].type) { 260 switch (et_stats[i].type) {
259 case NETSTAT: 261 case NETSTAT:
260 p = net_stats; 262 p = &netdev->stats;
261 break;
262 case DRVSTAT:
263 p = drvr_stats;
264 break; 263 break;
265 case PORTSTAT: 264 case DRVSTAT_TX:
266 p = port_stats; 265 p = &adapter->tx_stats;
267 break; 266 break;
268 case MISCSTAT: 267 case DRVSTAT:
269 p = rxf_stats; 268 p = &adapter->drv_stats;
270 break;
271 case ERXSTAT: /* Currently only one ERX stat is provided */
272 p = (u32 *)erx_stats + adapter->rx_obj.q.id;
273 break; 269 break;
274 } 270 }
275 271
@@ -277,19 +273,45 @@ be_get_ethtool_stats(struct net_device *netdev,
277 data[i] = (et_stats[i].size == sizeof(u64)) ? 273 data[i] = (et_stats[i].size == sizeof(u64)) ?
278 *(u64 *)p: *(u32 *)p; 274 *(u64 *)p: *(u32 *)p;
279 } 275 }
276
277 for_all_rx_queues(adapter, rxo, j) {
278 for (i = 0; i < ETHTOOL_RXSTATS_NUM; i++) {
279 switch (et_rx_stats[i].type) {
280 case DRVSTAT_RX:
281 p = (u8 *)&rxo->stats + et_rx_stats[i].offset;
282 break;
283 case ERXSTAT:
284 p = (u32 *)be_erx_stats_from_cmd(adapter) +
285 rxo->q.id;
286 break;
287 }
288 data[ETHTOOL_STATS_NUM + j * ETHTOOL_RXSTATS_NUM + i] =
289 (et_rx_stats[i].size == sizeof(u64)) ?
290 *(u64 *)p: *(u32 *)p;
291 }
292 }
280} 293}
281 294
282static void 295static void
283be_get_stat_strings(struct net_device *netdev, uint32_t stringset, 296be_get_stat_strings(struct net_device *netdev, uint32_t stringset,
284 uint8_t *data) 297 uint8_t *data)
285{ 298{
286 int i; 299 struct be_adapter *adapter = netdev_priv(netdev);
300 int i, j;
301
287 switch (stringset) { 302 switch (stringset) {
288 case ETH_SS_STATS: 303 case ETH_SS_STATS:
289 for (i = 0; i < ETHTOOL_STATS_NUM; i++) { 304 for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
290 memcpy(data, et_stats[i].desc, ETH_GSTRING_LEN); 305 memcpy(data, et_stats[i].desc, ETH_GSTRING_LEN);
291 data += ETH_GSTRING_LEN; 306 data += ETH_GSTRING_LEN;
292 } 307 }
308 for (i = 0; i < adapter->num_rx_qs; i++) {
309 for (j = 0; j < ETHTOOL_RXSTATS_NUM; j++) {
310 sprintf(data, "rxq%d: %s", i,
311 et_rx_stats[j].desc);
312 data += ETH_GSTRING_LEN;
313 }
314 }
293 break; 315 break;
294 case ETH_SS_TEST: 316 case ETH_SS_TEST:
295 for (i = 0; i < ETHTOOL_TESTS_NUM; i++) { 317 for (i = 0; i < ETHTOOL_TESTS_NUM; i++) {
@@ -302,11 +324,14 @@ be_get_stat_strings(struct net_device *netdev, uint32_t stringset,
302 324
303static int be_get_sset_count(struct net_device *netdev, int stringset) 325static int be_get_sset_count(struct net_device *netdev, int stringset)
304{ 326{
327 struct be_adapter *adapter = netdev_priv(netdev);
328
305 switch (stringset) { 329 switch (stringset) {
306 case ETH_SS_TEST: 330 case ETH_SS_TEST:
307 return ETHTOOL_TESTS_NUM; 331 return ETHTOOL_TESTS_NUM;
308 case ETH_SS_STATS: 332 case ETH_SS_STATS:
309 return ETHTOOL_STATS_NUM; 333 return ETHTOOL_STATS_NUM +
334 adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM;
310 default: 335 default:
311 return -EINVAL; 336 return -EINVAL;
312 } 337 }
@@ -325,26 +350,36 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
325 350
326 if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) { 351 if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) {
327 status = be_cmd_link_status_query(adapter, &link_up, 352 status = be_cmd_link_status_query(adapter, &link_up,
328 &mac_speed, &link_speed); 353 &mac_speed, &link_speed, 0);
329 354
330 be_link_status_update(adapter, link_up); 355 be_link_status_update(adapter, link_up);
331 /* link_speed is in units of 10 Mbps */ 356 /* link_speed is in units of 10 Mbps */
332 if (link_speed) { 357 if (link_speed) {
333 ecmd->speed = link_speed*10; 358 ethtool_cmd_speed_set(ecmd, link_speed*10);
334 } else { 359 } else {
335 switch (mac_speed) { 360 switch (mac_speed) {
361 case PHY_LINK_SPEED_10MBPS:
362 ethtool_cmd_speed_set(ecmd, SPEED_10);
363 break;
364 case PHY_LINK_SPEED_100MBPS:
365 ethtool_cmd_speed_set(ecmd, SPEED_100);
366 break;
336 case PHY_LINK_SPEED_1GBPS: 367 case PHY_LINK_SPEED_1GBPS:
337 ecmd->speed = SPEED_1000; 368 ethtool_cmd_speed_set(ecmd, SPEED_1000);
338 break; 369 break;
339 case PHY_LINK_SPEED_10GBPS: 370 case PHY_LINK_SPEED_10GBPS:
340 ecmd->speed = SPEED_10000; 371 ethtool_cmd_speed_set(ecmd, SPEED_10000);
372 break;
373 case PHY_LINK_SPEED_ZERO:
374 ethtool_cmd_speed_set(ecmd, 0);
341 break; 375 break;
342 } 376 }
343 } 377 }
344 378
345 phy_cmd.size = sizeof(struct be_cmd_req_get_phy_info); 379 phy_cmd.size = sizeof(struct be_cmd_req_get_phy_info);
346 phy_cmd.va = pci_alloc_consistent(adapter->pdev, phy_cmd.size, 380 phy_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
347 &phy_cmd.dma); 381 phy_cmd.size, &phy_cmd.dma,
382 GFP_KERNEL);
348 if (!phy_cmd.va) { 383 if (!phy_cmd.va) {
349 dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); 384 dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
350 return -ENOMEM; 385 return -ENOMEM;
@@ -379,14 +414,14 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
379 } 414 }
380 415
381 /* Save for future use */ 416 /* Save for future use */
382 adapter->link_speed = ecmd->speed; 417 adapter->link_speed = ethtool_cmd_speed(ecmd);
383 adapter->port_type = ecmd->port; 418 adapter->port_type = ecmd->port;
384 adapter->transceiver = ecmd->transceiver; 419 adapter->transceiver = ecmd->transceiver;
385 adapter->autoneg = ecmd->autoneg; 420 adapter->autoneg = ecmd->autoneg;
386 pci_free_consistent(adapter->pdev, phy_cmd.size, 421 dma_free_coherent(&adapter->pdev->dev, phy_cmd.size, phy_cmd.va,
387 phy_cmd.va, phy_cmd.dma); 422 phy_cmd.dma);
388 } else { 423 } else {
389 ecmd->speed = adapter->link_speed; 424 ethtool_cmd_speed_set(ecmd, adapter->link_speed);
390 ecmd->port = adapter->port_type; 425 ecmd->port = adapter->port_type;
391 ecmd->transceiver = adapter->transceiver; 426 ecmd->transceiver = adapter->transceiver;
392 ecmd->autoneg = adapter->autoneg; 427 ecmd->autoneg = adapter->autoneg;
@@ -421,10 +456,10 @@ be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
421{ 456{
422 struct be_adapter *adapter = netdev_priv(netdev); 457 struct be_adapter *adapter = netdev_priv(netdev);
423 458
424 ring->rx_max_pending = adapter->rx_obj.q.len; 459 ring->rx_max_pending = adapter->rx_obj[0].q.len;
425 ring->tx_max_pending = adapter->tx_obj.q.len; 460 ring->tx_max_pending = adapter->tx_obj.q.len;
426 461
427 ring->rx_pending = atomic_read(&adapter->rx_obj.q.used); 462 ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used);
428 ring->tx_pending = atomic_read(&adapter->tx_obj.q.used); 463 ring->tx_pending = atomic_read(&adapter->tx_obj.q.used);
429} 464}
430 465
@@ -457,29 +492,42 @@ be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
457} 492}
458 493
459static int 494static int
460be_phys_id(struct net_device *netdev, u32 data) 495be_set_phys_id(struct net_device *netdev,
496 enum ethtool_phys_id_state state)
461{ 497{
462 struct be_adapter *adapter = netdev_priv(netdev); 498 struct be_adapter *adapter = netdev_priv(netdev);
463 int status;
464 u32 cur;
465 499
466 be_cmd_get_beacon_state(adapter, adapter->port_num, &cur); 500 switch (state) {
501 case ETHTOOL_ID_ACTIVE:
502 be_cmd_get_beacon_state(adapter, adapter->hba_port_num,
503 &adapter->beacon_state);
504 return 1; /* cycle on/off once per second */
467 505
468 if (cur == BEACON_STATE_ENABLED) 506 case ETHTOOL_ID_ON:
469 return 0; 507 be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
508 BEACON_STATE_ENABLED);
509 break;
470 510
471 if (data < 2) 511 case ETHTOOL_ID_OFF:
472 data = 2; 512 be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
513 BEACON_STATE_DISABLED);
514 break;
473 515
474 status = be_cmd_set_beacon_state(adapter, adapter->port_num, 0, 0, 516 case ETHTOOL_ID_INACTIVE:
475 BEACON_STATE_ENABLED); 517 be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
476 set_current_state(TASK_INTERRUPTIBLE); 518 adapter->beacon_state);
477 schedule_timeout(data*HZ); 519 }
478 520
479 status = be_cmd_set_beacon_state(adapter, adapter->port_num, 0, 0, 521 return 0;
480 BEACON_STATE_DISABLED); 522}
481 523
482 return status; 524static bool
525be_is_wol_supported(struct be_adapter *adapter)
526{
527 if (!be_physfn(adapter))
528 return false;
529 else
530 return true;
483} 531}
484 532
485static void 533static void
@@ -487,7 +535,9 @@ be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
487{ 535{
488 struct be_adapter *adapter = netdev_priv(netdev); 536 struct be_adapter *adapter = netdev_priv(netdev);
489 537
490 wol->supported = WAKE_MAGIC; 538 if (be_is_wol_supported(adapter))
539 wol->supported = WAKE_MAGIC;
540
491 if (adapter->wol) 541 if (adapter->wol)
492 wol->wolopts = WAKE_MAGIC; 542 wol->wolopts = WAKE_MAGIC;
493 else 543 else
@@ -503,7 +553,7 @@ be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
503 if (wol->wolopts & ~WAKE_MAGIC) 553 if (wol->wolopts & ~WAKE_MAGIC)
504 return -EINVAL; 554 return -EINVAL;
505 555
506 if (wol->wolopts & WAKE_MAGIC) 556 if ((wol->wolopts & WAKE_MAGIC) && be_is_wol_supported(adapter))
507 adapter->wol = true; 557 adapter->wol = true;
508 else 558 else
509 adapter->wol = false; 559 adapter->wol = false;
@@ -516,11 +566,13 @@ be_test_ddr_dma(struct be_adapter *adapter)
516{ 566{
517 int ret, i; 567 int ret, i;
518 struct be_dma_mem ddrdma_cmd; 568 struct be_dma_mem ddrdma_cmd;
519 u64 pattern[2] = {0x5a5a5a5a5a5a5a5aULL, 0xa5a5a5a5a5a5a5a5ULL}; 569 static const u64 pattern[2] = {
570 0x5a5a5a5a5a5a5a5aULL, 0xa5a5a5a5a5a5a5a5ULL
571 };
520 572
521 ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test); 573 ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test);
522 ddrdma_cmd.va = pci_alloc_consistent(adapter->pdev, ddrdma_cmd.size, 574 ddrdma_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, ddrdma_cmd.size,
523 &ddrdma_cmd.dma); 575 &ddrdma_cmd.dma, GFP_KERNEL);
524 if (!ddrdma_cmd.va) { 576 if (!ddrdma_cmd.va) {
525 dev_err(&adapter->pdev->dev, "Memory allocation failure\n"); 577 dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
526 return -ENOMEM; 578 return -ENOMEM;
@@ -534,20 +586,20 @@ be_test_ddr_dma(struct be_adapter *adapter)
534 } 586 }
535 587
536err: 588err:
537 pci_free_consistent(adapter->pdev, ddrdma_cmd.size, 589 dma_free_coherent(&adapter->pdev->dev, ddrdma_cmd.size, ddrdma_cmd.va,
538 ddrdma_cmd.va, ddrdma_cmd.dma); 590 ddrdma_cmd.dma);
539 return ret; 591 return ret;
540} 592}
541 593
542static u64 be_loopback_test(struct be_adapter *adapter, u8 loopback_type, 594static u64 be_loopback_test(struct be_adapter *adapter, u8 loopback_type,
543 u64 *status) 595 u64 *status)
544{ 596{
545 be_cmd_set_loopback(adapter, adapter->port_num, 597 be_cmd_set_loopback(adapter, adapter->hba_port_num,
546 loopback_type, 1); 598 loopback_type, 1);
547 *status = be_cmd_loopback_test(adapter, adapter->port_num, 599 *status = be_cmd_loopback_test(adapter, adapter->hba_port_num,
548 loopback_type, 1500, 600 loopback_type, 1500,
549 2, 0xabc); 601 2, 0xabc);
550 be_cmd_set_loopback(adapter, adapter->port_num, 602 be_cmd_set_loopback(adapter, adapter->hba_port_num,
551 BE_NO_LOOPBACK, 1); 603 BE_NO_LOOPBACK, 1);
552 return *status; 604 return *status;
553} 605}
@@ -583,10 +635,11 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
583 } 635 }
584 636
585 if (be_cmd_link_status_query(adapter, &link_up, &mac_speed, 637 if (be_cmd_link_status_query(adapter, &link_up, &mac_speed,
586 &qos_link_speed) != 0) { 638 &qos_link_speed, 0) != 0) {
587 test->flags |= ETH_TEST_FL_FAILED; 639 test->flags |= ETH_TEST_FL_FAILED;
588 data[4] = -1; 640 data[4] = -1;
589 } else if (mac_speed) { 641 } else if (!mac_speed) {
642 test->flags |= ETH_TEST_FL_FAILED;
590 data[4] = 1; 643 data[4] = 1;
591 } 644 }
592} 645}
@@ -596,11 +649,9 @@ be_do_flash(struct net_device *netdev, struct ethtool_flash *efl)
596{ 649{
597 struct be_adapter *adapter = netdev_priv(netdev); 650 struct be_adapter *adapter = netdev_priv(netdev);
598 char file_name[ETHTOOL_FLASH_MAX_FILENAME]; 651 char file_name[ETHTOOL_FLASH_MAX_FILENAME];
599 u32 region;
600 652
601 file_name[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0; 653 file_name[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0;
602 strcpy(file_name, efl->data); 654 strcpy(file_name, efl->data);
603 region = efl->region;
604 655
605 return be_load_fw(adapter, file_name); 656 return be_load_fw(adapter, file_name);
606} 657}
@@ -627,8 +678,8 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
627 678
628 memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem)); 679 memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem));
629 eeprom_cmd.size = sizeof(struct be_cmd_req_seeprom_read); 680 eeprom_cmd.size = sizeof(struct be_cmd_req_seeprom_read);
630 eeprom_cmd.va = pci_alloc_consistent(adapter->pdev, eeprom_cmd.size, 681 eeprom_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, eeprom_cmd.size,
631 &eeprom_cmd.dma); 682 &eeprom_cmd.dma, GFP_KERNEL);
632 683
633 if (!eeprom_cmd.va) { 684 if (!eeprom_cmd.va) {
634 dev_err(&adapter->pdev->dev, 685 dev_err(&adapter->pdev->dev,
@@ -642,8 +693,8 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
642 resp = (struct be_cmd_resp_seeprom_read *) eeprom_cmd.va; 693 resp = (struct be_cmd_resp_seeprom_read *) eeprom_cmd.va;
643 memcpy(data, resp->seeprom_data + eeprom->offset, eeprom->len); 694 memcpy(data, resp->seeprom_data + eeprom->offset, eeprom->len);
644 } 695 }
645 pci_free_consistent(adapter->pdev, eeprom_cmd.size, eeprom_cmd.va, 696 dma_free_coherent(&adapter->pdev->dev, eeprom_cmd.size, eeprom_cmd.va,
646 eeprom_cmd.dma); 697 eeprom_cmd.dma);
647 698
648 return status; 699 return status;
649} 700}
@@ -661,18 +712,12 @@ const struct ethtool_ops be_ethtool_ops = {
661 .get_ringparam = be_get_ringparam, 712 .get_ringparam = be_get_ringparam,
662 .get_pauseparam = be_get_pauseparam, 713 .get_pauseparam = be_get_pauseparam,
663 .set_pauseparam = be_set_pauseparam, 714 .set_pauseparam = be_set_pauseparam,
664 .get_rx_csum = be_get_rx_csum,
665 .set_rx_csum = be_set_rx_csum,
666 .get_tx_csum = ethtool_op_get_tx_csum,
667 .set_tx_csum = ethtool_op_set_tx_hw_csum,
668 .get_sg = ethtool_op_get_sg,
669 .set_sg = ethtool_op_set_sg,
670 .get_tso = ethtool_op_get_tso,
671 .set_tso = ethtool_op_set_tso,
672 .get_strings = be_get_stat_strings, 715 .get_strings = be_get_stat_strings,
673 .phys_id = be_phys_id, 716 .set_phys_id = be_set_phys_id,
674 .get_sset_count = be_get_sset_count, 717 .get_sset_count = be_get_sset_count,
675 .get_ethtool_stats = be_get_ethtool_stats, 718 .get_ethtool_stats = be_get_ethtool_stats,
719 .get_regs_len = be_get_reg_len,
720 .get_regs = be_get_regs,
676 .flash_device = be_do_flash, 721 .flash_device = be_do_flash,
677 .self_test = be_self_test, 722 .self_test = be_self_test,
678}; 723};