aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/igbvf/ethtool.c
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2009-04-07 10:37:34 -0400
committerDavid S. Miller <davem@davemloft.net>2009-04-08 19:03:14 -0400
commitd4e0fe01a38a073568aee541a0247fe734095979 (patch)
treeeefc9d79a6e08d391111426d9acfa4c21135fa12 /drivers/net/igbvf/ethtool.c
parent93889d7574ec90bb4455929ad0536d8df74bc730 (diff)
igbvf: add new driver to support 82576 virtual functions
This adds an igbvf driver to handle virtual functions provided by the igb driver when SR-IOV has been enabled. A virtual function is a lightweight pci-e function that supports a single queue and shares resources with the 82576 physical function contained within the igb driver. To spawn virtual functions from the igb driver all that is needed is to enable CONFIG_PCI_IOV and have an 82576 Ethernet adapter on a system that supports SR-IOV in the BIOS. The virtual functions will appear after the interface is loaded. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/igbvf/ethtool.c')
-rw-r--r--drivers/net/igbvf/ethtool.c540
1 files changed, 540 insertions, 0 deletions
diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c
new file mode 100644
index 000000000000..1dcaa6905312
--- /dev/null
+++ b/drivers/net/igbvf/ethtool.c
@@ -0,0 +1,540 @@
1/*******************************************************************************
2
3 Intel(R) 82576 Virtual Function Linux driver
4 Copyright(c) 2009 Intel Corporation.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms and conditions of the GNU General Public License,
8 version 2, as published by the Free Software Foundation.
9
10 This program is distributed in the hope it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 more details.
14
15 You should have received a copy of the GNU General Public License along with
16 this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18
19 The full GNU General Public License is included in this distribution in
20 the file called "COPYING".
21
22 Contact Information:
23 e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
24 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
25
26*******************************************************************************/
27
28/* ethtool support for igbvf */
29
30#include <linux/netdevice.h>
31#include <linux/ethtool.h>
32#include <linux/pci.h>
33#include <linux/vmalloc.h>
34#include <linux/delay.h>
35
36#include "igbvf.h"
37#include <linux/if_vlan.h>
38
39
40struct igbvf_stats {
41 char stat_string[ETH_GSTRING_LEN];
42 int sizeof_stat;
43 int stat_offset;
44 int base_stat_offset;
45};
46
47#define IGBVF_STAT(current, base) \
48 sizeof(((struct igbvf_adapter *)0)->current), \
49 offsetof(struct igbvf_adapter, current), \
50 offsetof(struct igbvf_adapter, base)
51
52static const struct igbvf_stats igbvf_gstrings_stats[] = {
53 { "rx_packets", IGBVF_STAT(stats.gprc, stats.base_gprc) },
54 { "tx_packets", IGBVF_STAT(stats.gptc, stats.base_gptc) },
55 { "rx_bytes", IGBVF_STAT(stats.gorc, stats.base_gorc) },
56 { "tx_bytes", IGBVF_STAT(stats.gotc, stats.base_gotc) },
57 { "multicast", IGBVF_STAT(stats.mprc, stats.base_mprc) },
58 { "lbrx_bytes", IGBVF_STAT(stats.gorlbc, stats.base_gorlbc) },
59 { "lbrx_packets", IGBVF_STAT(stats.gprlbc, stats.base_gprlbc) },
60 { "tx_restart_queue", IGBVF_STAT(restart_queue, zero_base) },
61 { "rx_long_byte_count", IGBVF_STAT(stats.gorc, stats.base_gorc) },
62 { "rx_csum_offload_good", IGBVF_STAT(hw_csum_good, zero_base) },
63 { "rx_csum_offload_errors", IGBVF_STAT(hw_csum_err, zero_base) },
64 { "rx_header_split", IGBVF_STAT(rx_hdr_split, zero_base) },
65 { "alloc_rx_buff_failed", IGBVF_STAT(alloc_rx_buff_failed, zero_base) },
66};
67
68#define IGBVF_GLOBAL_STATS_LEN ARRAY_SIZE(igbvf_gstrings_stats)
69
70static const char igbvf_gstrings_test[][ETH_GSTRING_LEN] = {
71 "Link test (on/offline)"
72};
73
74#define IGBVF_TEST_LEN ARRAY_SIZE(igbvf_gstrings_test)
75
76static int igbvf_get_settings(struct net_device *netdev,
77 struct ethtool_cmd *ecmd)
78{
79 struct igbvf_adapter *adapter = netdev_priv(netdev);
80 struct e1000_hw *hw = &adapter->hw;
81 u32 status;
82
83 ecmd->supported = SUPPORTED_1000baseT_Full;
84
85 ecmd->advertising = ADVERTISED_1000baseT_Full;
86
87 ecmd->port = -1;
88 ecmd->transceiver = XCVR_DUMMY1;
89
90 status = er32(STATUS);
91 if (status & E1000_STATUS_LU) {
92 if (status & E1000_STATUS_SPEED_1000)
93 ecmd->speed = 1000;
94 else if (status & E1000_STATUS_SPEED_100)
95 ecmd->speed = 100;
96 else
97 ecmd->speed = 10;
98
99 if (status & E1000_STATUS_FD)
100 ecmd->duplex = DUPLEX_FULL;
101 else
102 ecmd->duplex = DUPLEX_HALF;
103 } else {
104 ecmd->speed = -1;
105 ecmd->duplex = -1;
106 }
107
108 ecmd->autoneg = AUTONEG_DISABLE;
109
110 return 0;
111}
112
113static u32 igbvf_get_link(struct net_device *netdev)
114{
115 return netif_carrier_ok(netdev);
116}
117
118static int igbvf_set_settings(struct net_device *netdev,
119 struct ethtool_cmd *ecmd)
120{
121 return -EOPNOTSUPP;
122}
123
124static void igbvf_get_pauseparam(struct net_device *netdev,
125 struct ethtool_pauseparam *pause)
126{
127 return;
128}
129
130static int igbvf_set_pauseparam(struct net_device *netdev,
131 struct ethtool_pauseparam *pause)
132{
133 return -EOPNOTSUPP;
134}
135
136static u32 igbvf_get_tx_csum(struct net_device *netdev)
137{
138 return ((netdev->features & NETIF_F_IP_CSUM) != 0);
139}
140
141static int igbvf_set_tx_csum(struct net_device *netdev, u32 data)
142{
143 if (data)
144 netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
145 else
146 netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
147 return 0;
148}
149
150static int igbvf_set_tso(struct net_device *netdev, u32 data)
151{
152 struct igbvf_adapter *adapter = netdev_priv(netdev);
153 int i;
154 struct net_device *v_netdev;
155
156 if (data) {
157 netdev->features |= NETIF_F_TSO;
158 netdev->features |= NETIF_F_TSO6;
159 } else {
160 netdev->features &= ~NETIF_F_TSO;
161 netdev->features &= ~NETIF_F_TSO6;
162 /* disable TSO on all VLANs if they're present */
163 if (!adapter->vlgrp)
164 goto tso_out;
165 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
166 v_netdev = vlan_group_get_device(adapter->vlgrp, i);
167 if (!v_netdev)
168 continue;
169
170 v_netdev->features &= ~NETIF_F_TSO;
171 v_netdev->features &= ~NETIF_F_TSO6;
172 vlan_group_set_device(adapter->vlgrp, i, v_netdev);
173 }
174 }
175
176tso_out:
177 dev_info(&adapter->pdev->dev, "TSO is %s\n",
178 data ? "Enabled" : "Disabled");
179 adapter->flags |= FLAG_TSO_FORCE;
180 return 0;
181}
182
183static u32 igbvf_get_msglevel(struct net_device *netdev)
184{
185 struct igbvf_adapter *adapter = netdev_priv(netdev);
186 return adapter->msg_enable;
187}
188
189static void igbvf_set_msglevel(struct net_device *netdev, u32 data)
190{
191 struct igbvf_adapter *adapter = netdev_priv(netdev);
192 adapter->msg_enable = data;
193}
194
195static int igbvf_get_regs_len(struct net_device *netdev)
196{
197#define IGBVF_REGS_LEN 8
198 return IGBVF_REGS_LEN * sizeof(u32);
199}
200
201static void igbvf_get_regs(struct net_device *netdev,
202 struct ethtool_regs *regs, void *p)
203{
204 struct igbvf_adapter *adapter = netdev_priv(netdev);
205 struct e1000_hw *hw = &adapter->hw;
206 u32 *regs_buff = p;
207 u8 revision_id;
208
209 memset(p, 0, IGBVF_REGS_LEN * sizeof(u32));
210
211 pci_read_config_byte(adapter->pdev, PCI_REVISION_ID, &revision_id);
212
213 regs->version = (1 << 24) | (revision_id << 16) | adapter->pdev->device;
214
215 regs_buff[0] = er32(CTRL);
216 regs_buff[1] = er32(STATUS);
217
218 regs_buff[2] = er32(RDLEN(0));
219 regs_buff[3] = er32(RDH(0));
220 regs_buff[4] = er32(RDT(0));
221
222 regs_buff[5] = er32(TDLEN(0));
223 regs_buff[6] = er32(TDH(0));
224 regs_buff[7] = er32(TDT(0));
225}
226
227static int igbvf_get_eeprom_len(struct net_device *netdev)
228{
229 return 0;
230}
231
232static int igbvf_get_eeprom(struct net_device *netdev,
233 struct ethtool_eeprom *eeprom, u8 *bytes)
234{
235 return -EOPNOTSUPP;
236}
237
238static int igbvf_set_eeprom(struct net_device *netdev,
239 struct ethtool_eeprom *eeprom, u8 *bytes)
240{
241 return -EOPNOTSUPP;
242}
243
244static void igbvf_get_drvinfo(struct net_device *netdev,
245 struct ethtool_drvinfo *drvinfo)
246{
247 struct igbvf_adapter *adapter = netdev_priv(netdev);
248 char firmware_version[32] = "N/A";
249
250 strncpy(drvinfo->driver, igbvf_driver_name, 32);
251 strncpy(drvinfo->version, igbvf_driver_version, 32);
252 strncpy(drvinfo->fw_version, firmware_version, 32);
253 strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
254 drvinfo->regdump_len = igbvf_get_regs_len(netdev);
255 drvinfo->eedump_len = igbvf_get_eeprom_len(netdev);
256}
257
258static void igbvf_get_ringparam(struct net_device *netdev,
259 struct ethtool_ringparam *ring)
260{
261 struct igbvf_adapter *adapter = netdev_priv(netdev);
262 struct igbvf_ring *tx_ring = adapter->tx_ring;
263 struct igbvf_ring *rx_ring = adapter->rx_ring;
264
265 ring->rx_max_pending = IGBVF_MAX_RXD;
266 ring->tx_max_pending = IGBVF_MAX_TXD;
267 ring->rx_mini_max_pending = 0;
268 ring->rx_jumbo_max_pending = 0;
269 ring->rx_pending = rx_ring->count;
270 ring->tx_pending = tx_ring->count;
271 ring->rx_mini_pending = 0;
272 ring->rx_jumbo_pending = 0;
273}
274
275static int igbvf_set_ringparam(struct net_device *netdev,
276 struct ethtool_ringparam *ring)
277{
278 struct igbvf_adapter *adapter = netdev_priv(netdev);
279 struct igbvf_ring *temp_ring;
280 int err;
281 u32 new_rx_count, new_tx_count;
282
283 if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
284 return -EINVAL;
285
286 new_rx_count = max(ring->rx_pending, (u32)IGBVF_MIN_RXD);
287 new_rx_count = min(new_rx_count, (u32)IGBVF_MAX_RXD);
288 new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);
289
290 new_tx_count = max(ring->tx_pending, (u32)IGBVF_MIN_TXD);
291 new_tx_count = min(new_tx_count, (u32)IGBVF_MAX_TXD);
292 new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
293
294 if ((new_tx_count == adapter->tx_ring->count) &&
295 (new_rx_count == adapter->rx_ring->count)) {
296 /* nothing to do */
297 return 0;
298 }
299
300 temp_ring = vmalloc(sizeof(struct igbvf_ring));
301 if (!temp_ring)
302 return -ENOMEM;
303
304 while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
305 msleep(1);
306
307 if (netif_running(adapter->netdev))
308 igbvf_down(adapter);
309
310 /*
311 * We can't just free everything and then setup again,
312 * because the ISRs in MSI-X mode get passed pointers
313 * to the tx and rx ring structs.
314 */
315 if (new_tx_count != adapter->tx_ring->count) {
316 memcpy(temp_ring, adapter->tx_ring, sizeof(struct igbvf_ring));
317
318 temp_ring->count = new_tx_count;
319 err = igbvf_setup_tx_resources(adapter, temp_ring);
320 if (err)
321 goto err_setup;
322
323 igbvf_free_tx_resources(adapter->tx_ring);
324
325 memcpy(adapter->tx_ring, temp_ring, sizeof(struct igbvf_ring));
326 }
327
328 if (new_rx_count != adapter->rx_ring->count) {
329 memcpy(temp_ring, adapter->rx_ring, sizeof(struct igbvf_ring));
330
331 temp_ring->count = new_rx_count;
332 err = igbvf_setup_rx_resources(adapter, temp_ring);
333 if (err)
334 goto err_setup;
335
336 igbvf_free_rx_resources(adapter->rx_ring);
337
338 memcpy(adapter->rx_ring, temp_ring,sizeof(struct igbvf_ring));
339 }
340
341 err = 0;
342err_setup:
343 if (netif_running(adapter->netdev))
344 igbvf_up(adapter);
345
346 clear_bit(__IGBVF_RESETTING, &adapter->state);
347 vfree(temp_ring);
348 return err;
349}
350
351static int igbvf_link_test(struct igbvf_adapter *adapter, u64 *data)
352{
353 struct e1000_hw *hw = &adapter->hw;
354 *data = 0;
355
356 hw->mac.ops.check_for_link(hw);
357
358 if (!(er32(STATUS) & E1000_STATUS_LU))
359 *data = 1;
360
361 return *data;
362}
363
364static int igbvf_get_self_test_count(struct net_device *netdev)
365{
366 return IGBVF_TEST_LEN;
367}
368
369static int igbvf_get_stats_count(struct net_device *netdev)
370{
371 return IGBVF_GLOBAL_STATS_LEN;
372}
373
374static void igbvf_diag_test(struct net_device *netdev,
375 struct ethtool_test *eth_test, u64 *data)
376{
377 struct igbvf_adapter *adapter = netdev_priv(netdev);
378
379 set_bit(__IGBVF_TESTING, &adapter->state);
380
381 /*
382 * Link test performed before hardware reset so autoneg doesn't
383 * interfere with test result
384 */
385 if (igbvf_link_test(adapter, &data[0]))
386 eth_test->flags |= ETH_TEST_FL_FAILED;
387
388 clear_bit(__IGBVF_TESTING, &adapter->state);
389 msleep_interruptible(4 * 1000);
390}
391
392static void igbvf_get_wol(struct net_device *netdev,
393 struct ethtool_wolinfo *wol)
394{
395 wol->supported = 0;
396 wol->wolopts = 0;
397
398 return;
399}
400
401static int igbvf_set_wol(struct net_device *netdev,
402 struct ethtool_wolinfo *wol)
403{
404 return -EOPNOTSUPP;
405}
406
407static int igbvf_phys_id(struct net_device *netdev, u32 data)
408{
409 return 0;
410}
411
412static int igbvf_get_coalesce(struct net_device *netdev,
413 struct ethtool_coalesce *ec)
414{
415 struct igbvf_adapter *adapter = netdev_priv(netdev);
416
417 if (adapter->itr_setting <= 3)
418 ec->rx_coalesce_usecs = adapter->itr_setting;
419 else
420 ec->rx_coalesce_usecs = adapter->itr_setting >> 2;
421
422 return 0;
423}
424
425static int igbvf_set_coalesce(struct net_device *netdev,
426 struct ethtool_coalesce *ec)
427{
428 struct igbvf_adapter *adapter = netdev_priv(netdev);
429 struct e1000_hw *hw = &adapter->hw;
430
431 if ((ec->rx_coalesce_usecs > IGBVF_MAX_ITR_USECS) ||
432 ((ec->rx_coalesce_usecs > 3) &&
433 (ec->rx_coalesce_usecs < IGBVF_MIN_ITR_USECS)) ||
434 (ec->rx_coalesce_usecs == 2))
435 return -EINVAL;
436
437 /* convert to rate of irq's per second */
438 if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) {
439 adapter->itr = IGBVF_START_ITR;
440 adapter->itr_setting = ec->rx_coalesce_usecs;
441 } else {
442 adapter->itr = ec->rx_coalesce_usecs << 2;
443 adapter->itr_setting = adapter->itr;
444 }
445
446 writel(adapter->itr,
447 hw->hw_addr + adapter->rx_ring[0].itr_register);
448
449 return 0;
450}
451
452static int igbvf_nway_reset(struct net_device *netdev)
453{
454 struct igbvf_adapter *adapter = netdev_priv(netdev);
455 if (netif_running(netdev))
456 igbvf_reinit_locked(adapter);
457 return 0;
458}
459
460
461static void igbvf_get_ethtool_stats(struct net_device *netdev,
462 struct ethtool_stats *stats,
463 u64 *data)
464{
465 struct igbvf_adapter *adapter = netdev_priv(netdev);
466 int i;
467
468 igbvf_update_stats(adapter);
469 for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
470 char *p = (char *)adapter +
471 igbvf_gstrings_stats[i].stat_offset;
472 char *b = (char *)adapter +
473 igbvf_gstrings_stats[i].base_stat_offset;
474 data[i] = ((igbvf_gstrings_stats[i].sizeof_stat ==
475 sizeof(u64)) ? (*(u64 *)p - *(u64 *)b) :
476 (*(u32 *)p - *(u32 *)b));
477 }
478
479}
480
481static void igbvf_get_strings(struct net_device *netdev, u32 stringset,
482 u8 *data)
483{
484 u8 *p = data;
485 int i;
486
487 switch (stringset) {
488 case ETH_SS_TEST:
489 memcpy(data, *igbvf_gstrings_test, sizeof(igbvf_gstrings_test));
490 break;
491 case ETH_SS_STATS:
492 for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
493 memcpy(p, igbvf_gstrings_stats[i].stat_string,
494 ETH_GSTRING_LEN);
495 p += ETH_GSTRING_LEN;
496 }
497 break;
498 }
499}
500
501static const struct ethtool_ops igbvf_ethtool_ops = {
502 .get_settings = igbvf_get_settings,
503 .set_settings = igbvf_set_settings,
504 .get_drvinfo = igbvf_get_drvinfo,
505 .get_regs_len = igbvf_get_regs_len,
506 .get_regs = igbvf_get_regs,
507 .get_wol = igbvf_get_wol,
508 .set_wol = igbvf_set_wol,
509 .get_msglevel = igbvf_get_msglevel,
510 .set_msglevel = igbvf_set_msglevel,
511 .nway_reset = igbvf_nway_reset,
512 .get_link = igbvf_get_link,
513 .get_eeprom_len = igbvf_get_eeprom_len,
514 .get_eeprom = igbvf_get_eeprom,
515 .set_eeprom = igbvf_set_eeprom,
516 .get_ringparam = igbvf_get_ringparam,
517 .set_ringparam = igbvf_set_ringparam,
518 .get_pauseparam = igbvf_get_pauseparam,
519 .set_pauseparam = igbvf_set_pauseparam,
520 .get_tx_csum = igbvf_get_tx_csum,
521 .set_tx_csum = igbvf_set_tx_csum,
522 .get_sg = ethtool_op_get_sg,
523 .set_sg = ethtool_op_set_sg,
524 .get_tso = ethtool_op_get_tso,
525 .set_tso = igbvf_set_tso,
526 .self_test = igbvf_diag_test,
527 .get_strings = igbvf_get_strings,
528 .phys_id = igbvf_phys_id,
529 .get_ethtool_stats = igbvf_get_ethtool_stats,
530 .self_test_count = igbvf_get_self_test_count,
531 .get_stats_count = igbvf_get_stats_count,
532 .get_coalesce = igbvf_get_coalesce,
533 .set_coalesce = igbvf_set_coalesce,
534};
535
536void igbvf_set_ethtool_ops(struct net_device *netdev)
537{
538 /* have to "undeclare" const on this struct to remove warnings */
539 SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&igbvf_ethtool_ops);
540}