aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/benet/be_ethtool.c
diff options
context:
space:
mode:
authorSathya Perla <sathya.perla@emulex.com>2010-10-04 01:12:27 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-04 01:12:27 -0400
commit3abcdeda59c1d4cf2bf83311ed2d544355ec7c2d (patch)
treec259d095b583f7fd2183e3eec43f1a5668468248 /drivers/net/benet/be_ethtool.c
parent72829071269b19381173a13ea1b2ca2f4f9d4cec (diff)
be2net: add multiple RX queue support
This patch adds multiple RX queue support to be2net. There are upto 4 extra rx-queues per port into which TCP/UDP traffic can be hashed into. Some of the ethtool stats are now displayed on a per queue basis. Signed-off-by: Sathya Perla <sathya.perla@emulex.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/benet/be_ethtool.c')
-rw-r--r--drivers/net/benet/be_ethtool.c174
1 files changed, 102 insertions, 72 deletions
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index d92063420c25..0f46366ecc48 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -26,14 +26,16 @@ struct be_ethtool_stat {
26 int offset; 26 int offset;
27}; 27};
28 28
29enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT, ERXSTAT}; 29enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT};
30#define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \ 30#define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \
31 offsetof(_struct, field) 31 offsetof(_struct, field)
32#define NETSTAT_INFO(field) #field, NETSTAT,\ 32#define NETSTAT_INFO(field) #field, NETSTAT,\
33 FIELDINFO(struct net_device_stats,\ 33 FIELDINFO(struct net_device_stats,\
34 field) 34 field)
35#define DRVSTAT_INFO(field) #field, DRVSTAT,\ 35#define DRVSTAT_TX_INFO(field) #field, DRVSTAT_TX,\
36 FIELDINFO(struct be_drvr_stats, field) 36 FIELDINFO(struct be_tx_stats, field)
37#define DRVSTAT_RX_INFO(field) #field, DRVSTAT_RX,\
38 FIELDINFO(struct be_rx_stats, field)
37#define MISCSTAT_INFO(field) #field, MISCSTAT,\ 39#define MISCSTAT_INFO(field) #field, MISCSTAT,\
38 FIELDINFO(struct be_rxf_stats, field) 40 FIELDINFO(struct be_rxf_stats, field)
39#define PORTSTAT_INFO(field) #field, PORTSTAT,\ 41#define PORTSTAT_INFO(field) #field, PORTSTAT,\
@@ -51,21 +53,12 @@ static const struct be_ethtool_stat et_stats[] = {
51 {NETSTAT_INFO(tx_errors)}, 53 {NETSTAT_INFO(tx_errors)},
52 {NETSTAT_INFO(rx_dropped)}, 54 {NETSTAT_INFO(rx_dropped)},
53 {NETSTAT_INFO(tx_dropped)}, 55 {NETSTAT_INFO(tx_dropped)},
54 {DRVSTAT_INFO(be_tx_reqs)}, 56 {DRVSTAT_TX_INFO(be_tx_rate)},
55 {DRVSTAT_INFO(be_tx_stops)}, 57 {DRVSTAT_TX_INFO(be_tx_reqs)},
56 {DRVSTAT_INFO(be_fwd_reqs)}, 58 {DRVSTAT_TX_INFO(be_tx_wrbs)},
57 {DRVSTAT_INFO(be_tx_wrbs)}, 59 {DRVSTAT_TX_INFO(be_tx_stops)},
58 {DRVSTAT_INFO(be_rx_polls)}, 60 {DRVSTAT_TX_INFO(be_tx_events)},
59 {DRVSTAT_INFO(be_tx_events)}, 61 {DRVSTAT_TX_INFO(be_tx_compl)},
60 {DRVSTAT_INFO(be_rx_events)},
61 {DRVSTAT_INFO(be_tx_compl)},
62 {DRVSTAT_INFO(be_rx_compl)},
63 {DRVSTAT_INFO(be_rx_mcast_pkt)},
64 {DRVSTAT_INFO(be_ethrx_post_fail)},
65 {DRVSTAT_INFO(be_802_3_dropped_frames)},
66 {DRVSTAT_INFO(be_802_3_malformed_frames)},
67 {DRVSTAT_INFO(be_tx_rate)},
68 {DRVSTAT_INFO(be_rx_rate)},
69 {PORTSTAT_INFO(rx_unicast_frames)}, 62 {PORTSTAT_INFO(rx_unicast_frames)},
70 {PORTSTAT_INFO(rx_multicast_frames)}, 63 {PORTSTAT_INFO(rx_multicast_frames)},
71 {PORTSTAT_INFO(rx_broadcast_frames)}, 64 {PORTSTAT_INFO(rx_broadcast_frames)},
@@ -106,11 +99,24 @@ static const struct be_ethtool_stat et_stats[] = {
106 {MISCSTAT_INFO(rx_drops_too_many_frags)}, 99 {MISCSTAT_INFO(rx_drops_too_many_frags)},
107 {MISCSTAT_INFO(rx_drops_invalid_ring)}, 100 {MISCSTAT_INFO(rx_drops_invalid_ring)},
108 {MISCSTAT_INFO(forwarded_packets)}, 101 {MISCSTAT_INFO(forwarded_packets)},
109 {MISCSTAT_INFO(rx_drops_mtu)}, 102 {MISCSTAT_INFO(rx_drops_mtu)}
110 {ERXSTAT_INFO(rx_drops_no_fragments)},
111}; 103};
112#define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats) 104#define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats)
113 105
106/* Stats related to multi RX queues */
107static const struct be_ethtool_stat et_rx_stats[] = {
108 {DRVSTAT_RX_INFO(rx_bytes)},
109 {DRVSTAT_RX_INFO(rx_pkts)},
110 {DRVSTAT_RX_INFO(rx_rate)},
111 {DRVSTAT_RX_INFO(rx_polls)},
112 {DRVSTAT_RX_INFO(rx_events)},
113 {DRVSTAT_RX_INFO(rx_compl)},
114 {DRVSTAT_RX_INFO(rx_mcast_pkts)},
115 {DRVSTAT_RX_INFO(rx_post_fail)},
116 {ERXSTAT_INFO(rx_drops_no_fragments)}
117};
118#define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats))
119
114static const char et_self_tests[][ETH_GSTRING_LEN] = { 120static const char et_self_tests[][ETH_GSTRING_LEN] = {
115 "MAC Loopback test", 121 "MAC Loopback test",
116 "PHY Loopback test", 122 "PHY Loopback test",
@@ -143,7 +149,7 @@ static int
143be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) 149be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
144{ 150{
145 struct be_adapter *adapter = netdev_priv(netdev); 151 struct be_adapter *adapter = netdev_priv(netdev);
146 struct be_eq_obj *rx_eq = &adapter->rx_eq; 152 struct be_eq_obj *rx_eq = &adapter->rx_obj[0].rx_eq;
147 struct be_eq_obj *tx_eq = &adapter->tx_eq; 153 struct be_eq_obj *tx_eq = &adapter->tx_eq;
148 154
149 coalesce->rx_coalesce_usecs = rx_eq->cur_eqd; 155 coalesce->rx_coalesce_usecs = rx_eq->cur_eqd;
@@ -167,25 +173,49 @@ static int
167be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) 173be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
168{ 174{
169 struct be_adapter *adapter = netdev_priv(netdev); 175 struct be_adapter *adapter = netdev_priv(netdev);
170 struct be_eq_obj *rx_eq = &adapter->rx_eq; 176 struct be_rx_obj *rxo;
177 struct be_eq_obj *rx_eq;
171 struct be_eq_obj *tx_eq = &adapter->tx_eq; 178 struct be_eq_obj *tx_eq = &adapter->tx_eq;
172 u32 tx_max, tx_min, tx_cur; 179 u32 tx_max, tx_min, tx_cur;
173 u32 rx_max, rx_min, rx_cur; 180 u32 rx_max, rx_min, rx_cur;
174 int status = 0; 181 int status = 0, i;
175 182
176 if (coalesce->use_adaptive_tx_coalesce == 1) 183 if (coalesce->use_adaptive_tx_coalesce == 1)
177 return -EINVAL; 184 return -EINVAL;
178 185
179 /* if AIC is being turned on now, start with an EQD of 0 */ 186 for_all_rx_queues(adapter, rxo, i) {
180 if (rx_eq->enable_aic == 0 && 187 rx_eq = &rxo->rx_eq;
181 coalesce->use_adaptive_rx_coalesce == 1) { 188
182 rx_eq->cur_eqd = 0; 189 if (!rx_eq->enable_aic && coalesce->use_adaptive_rx_coalesce)
190 rx_eq->cur_eqd = 0;
191 rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce;
192
193 rx_max = coalesce->rx_coalesce_usecs_high;
194 rx_min = coalesce->rx_coalesce_usecs_low;
195 rx_cur = coalesce->rx_coalesce_usecs;
196
197 if (rx_eq->enable_aic) {
198 if (rx_max > BE_MAX_EQD)
199 rx_max = BE_MAX_EQD;
200 if (rx_min > rx_max)
201 rx_min = rx_max;
202 rx_eq->max_eqd = rx_max;
203 rx_eq->min_eqd = rx_min;
204 if (rx_eq->cur_eqd > rx_max)
205 rx_eq->cur_eqd = rx_max;
206 if (rx_eq->cur_eqd < rx_min)
207 rx_eq->cur_eqd = rx_min;
208 } else {
209 if (rx_cur > BE_MAX_EQD)
210 rx_cur = BE_MAX_EQD;
211 if (rx_eq->cur_eqd != rx_cur) {
212 status = be_cmd_modify_eqd(adapter, rx_eq->q.id,
213 rx_cur);
214 if (!status)
215 rx_eq->cur_eqd = rx_cur;
216 }
217 }
183 } 218 }
184 rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce;
185
186 rx_max = coalesce->rx_coalesce_usecs_high;
187 rx_min = coalesce->rx_coalesce_usecs_low;
188 rx_cur = coalesce->rx_coalesce_usecs;
189 219
190 tx_max = coalesce->tx_coalesce_usecs_high; 220 tx_max = coalesce->tx_coalesce_usecs_high;
191 tx_min = coalesce->tx_coalesce_usecs_low; 221 tx_min = coalesce->tx_coalesce_usecs_low;
@@ -199,27 +229,6 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
199 tx_eq->cur_eqd = tx_cur; 229 tx_eq->cur_eqd = tx_cur;
200 } 230 }
201 231
202 if (rx_eq->enable_aic) {
203 if (rx_max > BE_MAX_EQD)
204 rx_max = BE_MAX_EQD;
205 if (rx_min > rx_max)
206 rx_min = rx_max;
207 rx_eq->max_eqd = rx_max;
208 rx_eq->min_eqd = rx_min;
209 if (rx_eq->cur_eqd > rx_max)
210 rx_eq->cur_eqd = rx_max;
211 if (rx_eq->cur_eqd < rx_min)
212 rx_eq->cur_eqd = rx_min;
213 } else {
214 if (rx_cur > BE_MAX_EQD)
215 rx_cur = BE_MAX_EQD;
216 if (rx_eq->cur_eqd != rx_cur) {
217 status = be_cmd_modify_eqd(adapter, rx_eq->q.id,
218 rx_cur);
219 if (!status)
220 rx_eq->cur_eqd = rx_cur;
221 }
222 }
223 return 0; 232 return 0;
224} 233}
225 234
@@ -247,32 +256,25 @@ be_get_ethtool_stats(struct net_device *netdev,
247 struct ethtool_stats *stats, uint64_t *data) 256 struct ethtool_stats *stats, uint64_t *data)
248{ 257{
249 struct be_adapter *adapter = netdev_priv(netdev); 258 struct be_adapter *adapter = netdev_priv(netdev);
250 struct be_drvr_stats *drvr_stats = &adapter->stats.drvr_stats; 259 struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats_cmd.va);
251 struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va);
252 struct be_rxf_stats *rxf_stats = &hw_stats->rxf;
253 struct be_port_rxf_stats *port_stats =
254 &rxf_stats->port[adapter->port_num];
255 struct net_device_stats *net_stats = &netdev->stats;
256 struct be_erx_stats *erx_stats = &hw_stats->erx; 260 struct be_erx_stats *erx_stats = &hw_stats->erx;
261 struct be_rx_obj *rxo;
257 void *p = NULL; 262 void *p = NULL;
258 int i; 263 int i, j;
259 264
260 for (i = 0; i < ETHTOOL_STATS_NUM; i++) { 265 for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
261 switch (et_stats[i].type) { 266 switch (et_stats[i].type) {
262 case NETSTAT: 267 case NETSTAT:
263 p = net_stats; 268 p = &netdev->stats;
264 break; 269 break;
265 case DRVSTAT: 270 case DRVSTAT_TX:
266 p = drvr_stats; 271 p = &adapter->tx_stats;
267 break; 272 break;
268 case PORTSTAT: 273 case PORTSTAT:
269 p = port_stats; 274 p = &hw_stats->rxf.port[adapter->port_num];
270 break; 275 break;
271 case MISCSTAT: 276 case MISCSTAT:
272 p = rxf_stats; 277 p = &hw_stats->rxf;
273 break;
274 case ERXSTAT: /* Currently only one ERX stat is provided */
275 p = (u32 *)erx_stats + adapter->rx_obj.q.id;
276 break; 278 break;
277 } 279 }
278 280
@@ -280,19 +282,44 @@ be_get_ethtool_stats(struct net_device *netdev,
280 data[i] = (et_stats[i].size == sizeof(u64)) ? 282 data[i] = (et_stats[i].size == sizeof(u64)) ?
281 *(u64 *)p: *(u32 *)p; 283 *(u64 *)p: *(u32 *)p;
282 } 284 }
285
286 for_all_rx_queues(adapter, rxo, j) {
287 for (i = 0; i < ETHTOOL_RXSTATS_NUM; i++) {
288 switch (et_rx_stats[i].type) {
289 case DRVSTAT_RX:
290 p = (u8 *)&rxo->stats + et_rx_stats[i].offset;
291 break;
292 case ERXSTAT:
293 p = (u32 *)erx_stats + rxo->q.id;
294 break;
295 }
296 data[ETHTOOL_STATS_NUM + j * ETHTOOL_RXSTATS_NUM + i] =
297 (et_rx_stats[i].size == sizeof(u64)) ?
298 *(u64 *)p: *(u32 *)p;
299 }
300 }
283} 301}
284 302
285static void 303static void
286be_get_stat_strings(struct net_device *netdev, uint32_t stringset, 304be_get_stat_strings(struct net_device *netdev, uint32_t stringset,
287 uint8_t *data) 305 uint8_t *data)
288{ 306{
289 int i; 307 struct be_adapter *adapter = netdev_priv(netdev);
308 int i, j;
309
290 switch (stringset) { 310 switch (stringset) {
291 case ETH_SS_STATS: 311 case ETH_SS_STATS:
292 for (i = 0; i < ETHTOOL_STATS_NUM; i++) { 312 for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
293 memcpy(data, et_stats[i].desc, ETH_GSTRING_LEN); 313 memcpy(data, et_stats[i].desc, ETH_GSTRING_LEN);
294 data += ETH_GSTRING_LEN; 314 data += ETH_GSTRING_LEN;
295 } 315 }
316 for (i = 0; i < adapter->num_rx_qs; i++) {
317 for (j = 0; j < ETHTOOL_RXSTATS_NUM; j++) {
318 sprintf(data, "rxq%d: %s", i,
319 et_rx_stats[j].desc);
320 data += ETH_GSTRING_LEN;
321 }
322 }
296 break; 323 break;
297 case ETH_SS_TEST: 324 case ETH_SS_TEST:
298 for (i = 0; i < ETHTOOL_TESTS_NUM; i++) { 325 for (i = 0; i < ETHTOOL_TESTS_NUM; i++) {
@@ -305,11 +332,14 @@ be_get_stat_strings(struct net_device *netdev, uint32_t stringset,
305 332
306static int be_get_sset_count(struct net_device *netdev, int stringset) 333static int be_get_sset_count(struct net_device *netdev, int stringset)
307{ 334{
335 struct be_adapter *adapter = netdev_priv(netdev);
336
308 switch (stringset) { 337 switch (stringset) {
309 case ETH_SS_TEST: 338 case ETH_SS_TEST:
310 return ETHTOOL_TESTS_NUM; 339 return ETHTOOL_TESTS_NUM;
311 case ETH_SS_STATS: 340 case ETH_SS_STATS:
312 return ETHTOOL_STATS_NUM; 341 return ETHTOOL_STATS_NUM +
342 adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM;
313 default: 343 default:
314 return -EINVAL; 344 return -EINVAL;
315 } 345 }
@@ -424,10 +454,10 @@ be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
424{ 454{
425 struct be_adapter *adapter = netdev_priv(netdev); 455 struct be_adapter *adapter = netdev_priv(netdev);
426 456
427 ring->rx_max_pending = adapter->rx_obj.q.len; 457 ring->rx_max_pending = adapter->rx_obj[0].q.len;
428 ring->tx_max_pending = adapter->tx_obj.q.len; 458 ring->tx_max_pending = adapter->tx_obj.q.len;
429 459
430 ring->rx_pending = atomic_read(&adapter->rx_obj.q.used); 460 ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used);
431 ring->tx_pending = atomic_read(&adapter->tx_obj.q.used); 461 ring->tx_pending = atomic_read(&adapter->tx_obj.q.used);
432} 462}
433 463