diff options
author | David S. Miller <davem@davemloft.net> | 2011-04-06 15:27:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-04-06 15:27:34 -0400 |
commit | 4c844d97d269a7ec4a6ba7d530aa876ac64dfb76 (patch) | |
tree | 67198ffbe0d8652f9a26548a7435f7514912a8cc | |
parent | 66ee33bfda6237b009b6fb0e48690e31800ff334 (diff) | |
parent | c5e129ac2fc72c119b85db79a629de66332f136d (diff) |
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next-2.6
-rw-r--r-- | drivers/net/sfc/efx.c | 20 | ||||
-rw-r--r-- | drivers/net/sfc/ethtool.c | 106 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 2 | ||||
-rw-r--r-- | drivers/net/sfc/nic.c | 6 | ||||
-rw-r--r-- | drivers/net/sfc/rx.c | 3 | ||||
-rw-r--r-- | include/linux/ethtool.h | 180 | ||||
-rw-r--r-- | net/core/ethtool.c | 55 |
7 files changed, 223 insertions, 149 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index d890679e4c4d..db72a6e054e1 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -1874,6 +1874,17 @@ static void efx_set_multicast_list(struct net_device *net_dev) | |||
1874 | /* Otherwise efx_start_port() will do this */ | 1874 | /* Otherwise efx_start_port() will do this */ |
1875 | } | 1875 | } |
1876 | 1876 | ||
1877 | static int efx_set_features(struct net_device *net_dev, u32 data) | ||
1878 | { | ||
1879 | struct efx_nic *efx = netdev_priv(net_dev); | ||
1880 | |||
1881 | /* If disabling RX n-tuple filtering, clear existing filters */ | ||
1882 | if (net_dev->features & ~data & NETIF_F_NTUPLE) | ||
1883 | efx_filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL); | ||
1884 | |||
1885 | return 0; | ||
1886 | } | ||
1887 | |||
1877 | static const struct net_device_ops efx_netdev_ops = { | 1888 | static const struct net_device_ops efx_netdev_ops = { |
1878 | .ndo_open = efx_net_open, | 1889 | .ndo_open = efx_net_open, |
1879 | .ndo_stop = efx_net_stop, | 1890 | .ndo_stop = efx_net_stop, |
@@ -1885,6 +1896,7 @@ static const struct net_device_ops efx_netdev_ops = { | |||
1885 | .ndo_change_mtu = efx_change_mtu, | 1896 | .ndo_change_mtu = efx_change_mtu, |
1886 | .ndo_set_mac_address = efx_set_mac_address, | 1897 | .ndo_set_mac_address = efx_set_mac_address, |
1887 | .ndo_set_multicast_list = efx_set_multicast_list, | 1898 | .ndo_set_multicast_list = efx_set_multicast_list, |
1899 | .ndo_set_features = efx_set_features, | ||
1888 | #ifdef CONFIG_NET_POLL_CONTROLLER | 1900 | #ifdef CONFIG_NET_POLL_CONTROLLER |
1889 | .ndo_poll_controller = efx_netpoll, | 1901 | .ndo_poll_controller = efx_netpoll, |
1890 | #endif | 1902 | #endif |
@@ -2269,7 +2281,6 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, | |||
2269 | strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name)); | 2281 | strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name)); |
2270 | 2282 | ||
2271 | efx->net_dev = net_dev; | 2283 | efx->net_dev = net_dev; |
2272 | efx->rx_checksum_enabled = true; | ||
2273 | spin_lock_init(&efx->stats_lock); | 2284 | spin_lock_init(&efx->stats_lock); |
2274 | mutex_init(&efx->mac_lock); | 2285 | mutex_init(&efx->mac_lock); |
2275 | efx->mac_op = type->default_mac_ops; | 2286 | efx->mac_op = type->default_mac_ops; |
@@ -2452,12 +2463,15 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, | |||
2452 | return -ENOMEM; | 2463 | return -ENOMEM; |
2453 | net_dev->features |= (type->offload_features | NETIF_F_SG | | 2464 | net_dev->features |= (type->offload_features | NETIF_F_SG | |
2454 | NETIF_F_HIGHDMA | NETIF_F_TSO | | 2465 | NETIF_F_HIGHDMA | NETIF_F_TSO | |
2455 | NETIF_F_GRO); | 2466 | NETIF_F_RXCSUM); |
2456 | if (type->offload_features & NETIF_F_V6_CSUM) | 2467 | if (type->offload_features & NETIF_F_V6_CSUM) |
2457 | net_dev->features |= NETIF_F_TSO6; | 2468 | net_dev->features |= NETIF_F_TSO6; |
2458 | /* Mask for features that also apply to VLAN devices */ | 2469 | /* Mask for features that also apply to VLAN devices */ |
2459 | net_dev->vlan_features |= (NETIF_F_ALL_CSUM | NETIF_F_SG | | 2470 | net_dev->vlan_features |= (NETIF_F_ALL_CSUM | NETIF_F_SG | |
2460 | NETIF_F_HIGHDMA | NETIF_F_TSO); | 2471 | NETIF_F_HIGHDMA | NETIF_F_ALL_TSO | |
2472 | NETIF_F_RXCSUM); | ||
2473 | /* All offloads can be toggled */ | ||
2474 | net_dev->hw_features = net_dev->features & ~NETIF_F_HIGHDMA; | ||
2461 | efx = netdev_priv(net_dev); | 2475 | efx = netdev_priv(net_dev); |
2462 | pci_set_drvdata(pci_dev, efx); | 2476 | pci_set_drvdata(pci_dev, efx); |
2463 | SET_NETDEV_DEV(net_dev, &pci_dev->dev); | 2477 | SET_NETDEV_DEV(net_dev, &pci_dev->dev); |
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 807178ef65ad..644f7c1d6e7b 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
@@ -178,19 +178,27 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = { | |||
178 | */ | 178 | */ |
179 | 179 | ||
180 | /* Identify device by flashing LEDs */ | 180 | /* Identify device by flashing LEDs */ |
181 | static int efx_ethtool_phys_id(struct net_device *net_dev, u32 count) | 181 | static int efx_ethtool_phys_id(struct net_device *net_dev, |
182 | enum ethtool_phys_id_state state) | ||
182 | { | 183 | { |
183 | struct efx_nic *efx = netdev_priv(net_dev); | 184 | struct efx_nic *efx = netdev_priv(net_dev); |
185 | enum efx_led_mode mode; | ||
184 | 186 | ||
185 | do { | 187 | switch (state) { |
186 | efx->type->set_id_led(efx, EFX_LED_ON); | 188 | case ETHTOOL_ID_ON: |
187 | schedule_timeout_interruptible(HZ / 2); | 189 | mode = EFX_LED_ON; |
188 | 190 | break; | |
189 | efx->type->set_id_led(efx, EFX_LED_OFF); | 191 | case ETHTOOL_ID_OFF: |
190 | schedule_timeout_interruptible(HZ / 2); | 192 | mode = EFX_LED_OFF; |
191 | } while (!signal_pending(current) && --count != 0); | 193 | break; |
194 | case ETHTOOL_ID_INACTIVE: | ||
195 | mode = EFX_LED_DEFAULT; | ||
196 | break; | ||
197 | default: | ||
198 | return -EINVAL; | ||
199 | } | ||
192 | 200 | ||
193 | efx->type->set_id_led(efx, EFX_LED_DEFAULT); | 201 | efx->type->set_id_led(efx, mode); |
194 | return 0; | 202 | return 0; |
195 | } | 203 | } |
196 | 204 | ||
@@ -518,72 +526,6 @@ static void efx_ethtool_get_stats(struct net_device *net_dev, | |||
518 | } | 526 | } |
519 | } | 527 | } |
520 | 528 | ||
521 | static int efx_ethtool_set_tso(struct net_device *net_dev, u32 enable) | ||
522 | { | ||
523 | struct efx_nic *efx __attribute__ ((unused)) = netdev_priv(net_dev); | ||
524 | u32 features; | ||
525 | |||
526 | features = NETIF_F_TSO; | ||
527 | if (efx->type->offload_features & NETIF_F_V6_CSUM) | ||
528 | features |= NETIF_F_TSO6; | ||
529 | |||
530 | if (enable) | ||
531 | net_dev->features |= features; | ||
532 | else | ||
533 | net_dev->features &= ~features; | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable) | ||
539 | { | ||
540 | struct efx_nic *efx = netdev_priv(net_dev); | ||
541 | u32 features = efx->type->offload_features & NETIF_F_ALL_CSUM; | ||
542 | |||
543 | if (enable) | ||
544 | net_dev->features |= features; | ||
545 | else | ||
546 | net_dev->features &= ~features; | ||
547 | |||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static int efx_ethtool_set_rx_csum(struct net_device *net_dev, u32 enable) | ||
552 | { | ||
553 | struct efx_nic *efx = netdev_priv(net_dev); | ||
554 | |||
555 | /* No way to stop the hardware doing the checks; we just | ||
556 | * ignore the result. | ||
557 | */ | ||
558 | efx->rx_checksum_enabled = !!enable; | ||
559 | |||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev) | ||
564 | { | ||
565 | struct efx_nic *efx = netdev_priv(net_dev); | ||
566 | |||
567 | return efx->rx_checksum_enabled; | ||
568 | } | ||
569 | |||
570 | static int efx_ethtool_set_flags(struct net_device *net_dev, u32 data) | ||
571 | { | ||
572 | struct efx_nic *efx = netdev_priv(net_dev); | ||
573 | u32 supported = (efx->type->offload_features & | ||
574 | (ETH_FLAG_RXHASH | ETH_FLAG_NTUPLE)); | ||
575 | int rc; | ||
576 | |||
577 | rc = ethtool_op_set_flags(net_dev, data, supported); | ||
578 | if (rc) | ||
579 | return rc; | ||
580 | |||
581 | if (!(data & ETH_FLAG_NTUPLE)) | ||
582 | efx_filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL); | ||
583 | |||
584 | return 0; | ||
585 | } | ||
586 | |||
587 | static void efx_ethtool_self_test(struct net_device *net_dev, | 529 | static void efx_ethtool_self_test(struct net_device *net_dev, |
588 | struct ethtool_test *test, u64 *data) | 530 | struct ethtool_test *test, u64 *data) |
589 | { | 531 | { |
@@ -1070,22 +1012,10 @@ const struct ethtool_ops efx_ethtool_ops = { | |||
1070 | .set_ringparam = efx_ethtool_set_ringparam, | 1012 | .set_ringparam = efx_ethtool_set_ringparam, |
1071 | .get_pauseparam = efx_ethtool_get_pauseparam, | 1013 | .get_pauseparam = efx_ethtool_get_pauseparam, |
1072 | .set_pauseparam = efx_ethtool_set_pauseparam, | 1014 | .set_pauseparam = efx_ethtool_set_pauseparam, |
1073 | .get_rx_csum = efx_ethtool_get_rx_csum, | ||
1074 | .set_rx_csum = efx_ethtool_set_rx_csum, | ||
1075 | .get_tx_csum = ethtool_op_get_tx_csum, | ||
1076 | /* Need to enable/disable IPv6 too */ | ||
1077 | .set_tx_csum = efx_ethtool_set_tx_csum, | ||
1078 | .get_sg = ethtool_op_get_sg, | ||
1079 | .set_sg = ethtool_op_set_sg, | ||
1080 | .get_tso = ethtool_op_get_tso, | ||
1081 | /* Need to enable/disable TSO-IPv6 too */ | ||
1082 | .set_tso = efx_ethtool_set_tso, | ||
1083 | .get_flags = ethtool_op_get_flags, | ||
1084 | .set_flags = efx_ethtool_set_flags, | ||
1085 | .get_sset_count = efx_ethtool_get_sset_count, | 1015 | .get_sset_count = efx_ethtool_get_sset_count, |
1086 | .self_test = efx_ethtool_self_test, | 1016 | .self_test = efx_ethtool_self_test, |
1087 | .get_strings = efx_ethtool_get_strings, | 1017 | .get_strings = efx_ethtool_get_strings, |
1088 | .phys_id = efx_ethtool_phys_id, | 1018 | .set_phys_id = efx_ethtool_phys_id, |
1089 | .get_ethtool_stats = efx_ethtool_get_stats, | 1019 | .get_ethtool_stats = efx_ethtool_get_stats, |
1090 | .get_wol = efx_ethtool_get_wol, | 1020 | .get_wol = efx_ethtool_get_wol, |
1091 | .set_wol = efx_ethtool_set_wol, | 1021 | .set_wol = efx_ethtool_set_wol, |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 215d5c51bfa0..f0f8ca535a4d 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -681,7 +681,6 @@ struct efx_filter_state; | |||
681 | * @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock | 681 | * @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock |
682 | * @port_initialized: Port initialized? | 682 | * @port_initialized: Port initialized? |
683 | * @net_dev: Operating system network device. Consider holding the rtnl lock | 683 | * @net_dev: Operating system network device. Consider holding the rtnl lock |
684 | * @rx_checksum_enabled: RX checksumming enabled | ||
685 | * @stats_buffer: DMA buffer for statistics | 684 | * @stats_buffer: DMA buffer for statistics |
686 | * @mac_op: MAC interface | 685 | * @mac_op: MAC interface |
687 | * @phy_type: PHY type | 686 | * @phy_type: PHY type |
@@ -771,7 +770,6 @@ struct efx_nic { | |||
771 | 770 | ||
772 | bool port_initialized; | 771 | bool port_initialized; |
773 | struct net_device *net_dev; | 772 | struct net_device *net_dev; |
774 | bool rx_checksum_enabled; | ||
775 | 773 | ||
776 | struct efx_buffer stats_buffer; | 774 | struct efx_buffer stats_buffer; |
777 | 775 | ||
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c index e8396614daf3..2594f39c3ba4 100644 --- a/drivers/net/sfc/nic.c +++ b/drivers/net/sfc/nic.c | |||
@@ -850,7 +850,6 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event) | |||
850 | unsigned expected_ptr; | 850 | unsigned expected_ptr; |
851 | bool rx_ev_pkt_ok, discard = false, checksummed; | 851 | bool rx_ev_pkt_ok, discard = false, checksummed; |
852 | struct efx_rx_queue *rx_queue; | 852 | struct efx_rx_queue *rx_queue; |
853 | struct efx_nic *efx = channel->efx; | ||
854 | 853 | ||
855 | /* Basic packet information */ | 854 | /* Basic packet information */ |
856 | rx_ev_byte_cnt = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_BYTE_CNT); | 855 | rx_ev_byte_cnt = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_BYTE_CNT); |
@@ -873,9 +872,8 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event) | |||
873 | * UDP/IP, then we can rely on the hardware checksum. | 872 | * UDP/IP, then we can rely on the hardware checksum. |
874 | */ | 873 | */ |
875 | checksummed = | 874 | checksummed = |
876 | likely(efx->rx_checksum_enabled) && | 875 | rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP || |
877 | (rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP || | 876 | rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP; |
878 | rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP); | ||
879 | } else { | 877 | } else { |
880 | efx_handle_rx_not_ok(rx_queue, event, &rx_ev_pkt_ok, &discard); | 878 | efx_handle_rx_not_ok(rx_queue, event, &rx_ev_pkt_ok, &discard); |
881 | checksummed = false; | 879 | checksummed = false; |
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index c0fdb59030fb..b7dc891b4461 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c | |||
@@ -605,6 +605,9 @@ void __efx_rx_packet(struct efx_channel *channel, | |||
605 | skb_record_rx_queue(skb, channel->channel); | 605 | skb_record_rx_queue(skb, channel->channel); |
606 | } | 606 | } |
607 | 607 | ||
608 | if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM))) | ||
609 | checksummed = false; | ||
610 | |||
608 | if (likely(checksummed || rx_buf->is_page)) { | 611 | if (likely(checksummed || rx_buf->is_page)) { |
609 | efx_rx_packet_gro(channel, rx_buf, eh, checksummed); | 612 | efx_rx_packet_gro(channel, rx_buf, eh, checksummed); |
610 | return; | 613 | return; |
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index c8fcbdd2b0e7..c04d1316d221 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h | |||
@@ -663,6 +663,22 @@ struct ethtool_rx_ntuple_list { | |||
663 | unsigned int count; | 663 | unsigned int count; |
664 | }; | 664 | }; |
665 | 665 | ||
666 | /** | ||
667 | * enum ethtool_phys_id_state - indicator state for physical identification | ||
668 | * @ETHTOOL_ID_INACTIVE: Physical ID indicator should be deactivated | ||
669 | * @ETHTOOL_ID_ACTIVE: Physical ID indicator should be activated | ||
670 | * @ETHTOOL_ID_ON: LED should be turned on (used iff %ETHTOOL_ID_ACTIVE | ||
671 | * is not supported) | ||
672 | * @ETHTOOL_ID_OFF: LED should be turned off (used iff %ETHTOOL_ID_ACTIVE | ||
673 | * is not supported) | ||
674 | */ | ||
675 | enum ethtool_phys_id_state { | ||
676 | ETHTOOL_ID_INACTIVE, | ||
677 | ETHTOOL_ID_ACTIVE, | ||
678 | ETHTOOL_ID_ON, | ||
679 | ETHTOOL_ID_OFF | ||
680 | }; | ||
681 | |||
666 | struct net_device; | 682 | struct net_device; |
667 | 683 | ||
668 | /* Some generic methods drivers may use in their ethtool_ops */ | 684 | /* Some generic methods drivers may use in their ethtool_ops */ |
@@ -683,63 +699,126 @@ void ethtool_ntuple_flush(struct net_device *dev); | |||
683 | bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); | 699 | bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); |
684 | 700 | ||
685 | /** | 701 | /** |
686 | * ðtool_ops - Alter and report network device settings | 702 | * struct ethtool_ops - optional netdev operations |
687 | * get_settings: Get device-specific settings | 703 | * @get_settings: Get various device settings including Ethernet link |
688 | * set_settings: Set device-specific settings | 704 | * settings. Returns a negative error code or zero. |
689 | * get_drvinfo: Report driver information | 705 | * @set_settings: Set various device settings including Ethernet link |
690 | * get_regs: Get device registers | 706 | * settings. Returns a negative error code or zero. |
691 | * get_wol: Report whether Wake-on-Lan is enabled | 707 | * @get_drvinfo: Report driver/device information. Should only set the |
692 | * set_wol: Turn Wake-on-Lan on or off | 708 | * @driver, @version, @fw_version and @bus_info fields. If not |
693 | * get_msglevel: Report driver message level | 709 | * implemented, the @driver and @bus_info fields will be filled in |
694 | * set_msglevel: Set driver message level | 710 | * according to the netdev's parent device. |
695 | * nway_reset: Restart autonegotiation | 711 | * @get_regs_len: Get buffer length required for @get_regs |
696 | * get_link: Get link status | 712 | * @get_regs: Get device registers |
697 | * get_eeprom: Read data from the device EEPROM | 713 | * @get_wol: Report whether Wake-on-Lan is enabled |
698 | * set_eeprom: Write data to the device EEPROM | 714 | * @set_wol: Turn Wake-on-Lan on or off. Returns a negative error code |
699 | * get_coalesce: Get interrupt coalescing parameters | 715 | * or zero. |
700 | * set_coalesce: Set interrupt coalescing parameters | 716 | * @get_msglevel: Report driver message level. This should be the value |
701 | * get_ringparam: Report ring sizes | 717 | * of the @msg_enable field used by netif logging functions. |
702 | * set_ringparam: Set ring sizes | 718 | * @set_msglevel: Set driver message level |
703 | * get_pauseparam: Report pause parameters | 719 | * @nway_reset: Restart autonegotiation. Returns a negative error code |
704 | * set_pauseparam: Set pause parameters | 720 | * or zero. |
705 | * get_rx_csum: Report whether receive checksums are turned on or off | 721 | * @get_link: Report whether physical link is up. Will only be called if |
706 | * set_rx_csum: Turn receive checksum on or off | 722 | * the netdev is up. Should usually be set to ethtool_op_get_link(), |
707 | * get_tx_csum: Report whether transmit checksums are turned on or off | 723 | * which uses netif_carrier_ok(). |
708 | * set_tx_csum: Turn transmit checksums on or off | 724 | * @get_eeprom: Read data from the device EEPROM. |
709 | * get_sg: Report whether scatter-gather is enabled | ||
710 | * set_sg: Turn scatter-gather on or off | ||
711 | * get_tso: Report whether TCP segmentation offload is enabled | ||
712 | * set_tso: Turn TCP segmentation offload on or off | ||
713 | * get_ufo: Report whether UDP fragmentation offload is enabled | ||
714 | * set_ufo: Turn UDP fragmentation offload on or off | ||
715 | * self_test: Run specified self-tests | ||
716 | * get_strings: Return a set of strings that describe the requested objects | ||
717 | * phys_id: Identify the device | ||
718 | * get_stats: Return statistics about the device | ||
719 | * get_flags: get 32-bit flags bitmap | ||
720 | * set_flags: set 32-bit flags bitmap | ||
721 | * | ||
722 | * Description: | ||
723 | * | ||
724 | * get_settings: | ||
725 | * @get_settings is passed an ðtool_cmd to fill in. It returns | ||
726 | * an negative errno or zero. | ||
727 | * | ||
728 | * set_settings: | ||
729 | * @set_settings is passed an ðtool_cmd and should attempt to set | ||
730 | * all the settings this device supports. It may return an error value | ||
731 | * if something goes wrong (otherwise 0). | ||
732 | * | ||
733 | * get_eeprom: | ||
734 | * Should fill in the magic field. Don't need to check len for zero | 725 | * Should fill in the magic field. Don't need to check len for zero |
735 | * or wraparound. Fill in the data argument with the eeprom values | 726 | * or wraparound. Fill in the data argument with the eeprom values |
736 | * from offset to offset + len. Update len to the amount read. | 727 | * from offset to offset + len. Update len to the amount read. |
737 | * Returns an error or zero. | 728 | * Returns an error or zero. |
738 | * | 729 | * @set_eeprom: Write data to the device EEPROM. |
739 | * set_eeprom: | ||
740 | * Should validate the magic field. Don't need to check len for zero | 730 | * Should validate the magic field. Don't need to check len for zero |
741 | * or wraparound. Update len to the amount written. Returns an error | 731 | * or wraparound. Update len to the amount written. Returns an error |
742 | * or zero. | 732 | * or zero. |
733 | * @get_coalesce: Get interrupt coalescing parameters. Returns a negative | ||
734 | * error code or zero. | ||
735 | * @set_coalesce: Set interrupt coalescing parameters. Returns a negative | ||
736 | * error code or zero. | ||
737 | * @get_ringparam: Report ring sizes | ||
738 | * @set_ringparam: Set ring sizes. Returns a negative error code or zero. | ||
739 | * @get_pauseparam: Report pause parameters | ||
740 | * @set_pauseparam: Set pause parameters. Returns a negative error code | ||
741 | * or zero. | ||
742 | * @get_rx_csum: Deprecated in favour of the netdev feature %NETIF_F_RXCSUM. | ||
743 | * Report whether receive checksums are turned on or off. | ||
744 | * @set_rx_csum: Deprecated in favour of generic netdev features. Turn | ||
745 | * receive checksum on or off. Returns a negative error code or zero. | ||
746 | * @get_tx_csum: Deprecated as redundant. Report whether transmit checksums | ||
747 | * are turned on or off. | ||
748 | * @set_tx_csum: Deprecated in favour of generic netdev features. Turn | ||
749 | * transmit checksums on or off. Returns a egative error code or zero. | ||
750 | * @get_sg: Deprecated as redundant. Report whether scatter-gather is | ||
751 | * enabled. | ||
752 | * @set_sg: Deprecated in favour of generic netdev features. Turn | ||
753 | * scatter-gather on or off. Returns a negative error code or zero. | ||
754 | * @get_tso: Deprecated as redundant. Report whether TCP segmentation | ||
755 | * offload is enabled. | ||
756 | * @set_tso: Deprecated in favour of generic netdev features. Turn TCP | ||
757 | * segmentation offload on or off. Returns a negative error code or zero. | ||
758 | * @self_test: Run specified self-tests | ||
759 | * @get_strings: Return a set of strings that describe the requested objects | ||
760 | * @set_phys_id: Identify the physical devices, e.g. by flashing an LED | ||
761 | * attached to it. The implementation may update the indicator | ||
762 | * asynchronously or synchronously, but in either case it must return | ||
763 | * quickly. It is initially called with the argument %ETHTOOL_ID_ACTIVE, | ||
764 | * and must either activate asynchronous updates or return -%EINVAL. | ||
765 | * If it returns -%EINVAL then it will be called again at intervals with | ||
766 | * argument %ETHTOOL_ID_ON or %ETHTOOL_ID_OFF and should set the state of | ||
767 | * the indicator accordingly. Finally, it is called with the argument | ||
768 | * %ETHTOOL_ID_INACTIVE and must deactivate the indicator. Returns a | ||
769 | * negative error code or zero. | ||
770 | * @phys_id: Deprecated in favour of @set_phys_id. | ||
771 | * Identify the physical device, e.g. by flashing an LED | ||
772 | * attached to it until interrupted by a signal or the given time | ||
773 | * (in seconds) elapses. If the given time is zero, use a default | ||
774 | * time limit. Returns a negative error code or zero. Being | ||
775 | * interrupted by a signal is not an error. | ||
776 | * @get_ethtool_stats: Return extended statistics about the device. | ||
777 | * This is only useful if the device maintains statistics not | ||
778 | * included in &struct rtnl_link_stats64. | ||
779 | * @begin: Function to be called before any other operation. Returns a | ||
780 | * negative error code or zero. | ||
781 | * @complete: Function to be called after any other operation except | ||
782 | * @begin. Will be called even if the other operation failed. | ||
783 | * @get_ufo: Deprecated as redundant. Report whether UDP fragmentation | ||
784 | * offload is enabled. | ||
785 | * @set_ufo: Deprecated in favour of generic netdev features. Turn UDP | ||
786 | * fragmentation offload on or off. Returns a negative error code or zero. | ||
787 | * @get_flags: Deprecated as redundant. Report features included in | ||
788 | * &enum ethtool_flags that are enabled. | ||
789 | * @set_flags: Deprecated in favour of generic netdev features. Turn | ||
790 | * features included in &enum ethtool_flags on or off. Returns a | ||
791 | * negative error code or zero. | ||
792 | * @get_priv_flags: Report driver-specific feature flags. | ||
793 | * @set_priv_flags: Set driver-specific feature flags. Returns a negative | ||
794 | * error code or zero. | ||
795 | * @get_sset_count: Get number of strings that @get_strings will write. | ||
796 | * @get_rxnfc: Get RX flow classification rules. Returns a negative | ||
797 | * error code or zero. | ||
798 | * @set_rxnfc: Set RX flow classification rules. Returns a negative | ||
799 | * error code or zero. | ||
800 | * @flash_device: Write a firmware image to device's flash memory. | ||
801 | * Returns a negative error code or zero. | ||
802 | * @reset: Reset (part of) the device, as specified by a bitmask of | ||
803 | * flags from &enum ethtool_reset_flags. Returns a negative | ||
804 | * error code or zero. | ||
805 | * @set_rx_ntuple: Set an RX n-tuple rule. Returns a negative error code | ||
806 | * or zero. | ||
807 | * @get_rx_ntuple: Deprecated. | ||
808 | * @get_rxfh_indir: Get the contents of the RX flow hash indirection table. | ||
809 | * Returns a negative error code or zero. | ||
810 | * @set_rxfh_indir: Set the contents of the RX flow hash indirection table. | ||
811 | * Returns a negative error code or zero. | ||
812 | * | ||
813 | * All operations are optional (i.e. the function pointer may be set | ||
814 | * to %NULL) and callers must take this into account. Callers must | ||
815 | * hold the RTNL, except that for @get_drvinfo the caller may or may | ||
816 | * not hold the RTNL. | ||
817 | * | ||
818 | * See the structures used by these operations for further documentation. | ||
819 | * | ||
820 | * See &struct net_device and &struct net_device_ops for documentation | ||
821 | * of the generic netdev features interface. | ||
743 | */ | 822 | */ |
744 | struct ethtool_ops { | 823 | struct ethtool_ops { |
745 | int (*get_settings)(struct net_device *, struct ethtool_cmd *); | 824 | int (*get_settings)(struct net_device *, struct ethtool_cmd *); |
@@ -778,6 +857,7 @@ struct ethtool_ops { | |||
778 | int (*set_tso)(struct net_device *, u32); | 857 | int (*set_tso)(struct net_device *, u32); |
779 | void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); | 858 | void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); |
780 | void (*get_strings)(struct net_device *, u32 stringset, u8 *); | 859 | void (*get_strings)(struct net_device *, u32 stringset, u8 *); |
860 | int (*set_phys_id)(struct net_device *, enum ethtool_phys_id_state); | ||
781 | int (*phys_id)(struct net_device *, u32); | 861 | int (*phys_id)(struct net_device *, u32); |
782 | void (*get_ethtool_stats)(struct net_device *, | 862 | void (*get_ethtool_stats)(struct net_device *, |
783 | struct ethtool_stats *, u64 *); | 863 | struct ethtool_stats *, u64 *); |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 719670ae199c..1b7fa984de7d 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
22 | #include <linux/vmalloc.h> | 22 | #include <linux/vmalloc.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/rtnetlink.h> | ||
25 | #include <linux/sched.h> | ||
24 | 26 | ||
25 | /* | 27 | /* |
26 | * Some useful ethtool_ops methods that're device independent. | 28 | * Some useful ethtool_ops methods that're device independent. |
@@ -1618,14 +1620,63 @@ out: | |||
1618 | static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) | 1620 | static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) |
1619 | { | 1621 | { |
1620 | struct ethtool_value id; | 1622 | struct ethtool_value id; |
1623 | static bool busy; | ||
1624 | int rc; | ||
1621 | 1625 | ||
1622 | if (!dev->ethtool_ops->phys_id) | 1626 | if (!dev->ethtool_ops->set_phys_id && !dev->ethtool_ops->phys_id) |
1623 | return -EOPNOTSUPP; | 1627 | return -EOPNOTSUPP; |
1624 | 1628 | ||
1629 | if (busy) | ||
1630 | return -EBUSY; | ||
1631 | |||
1625 | if (copy_from_user(&id, useraddr, sizeof(id))) | 1632 | if (copy_from_user(&id, useraddr, sizeof(id))) |
1626 | return -EFAULT; | 1633 | return -EFAULT; |
1627 | 1634 | ||
1628 | return dev->ethtool_ops->phys_id(dev, id.data); | 1635 | if (!dev->ethtool_ops->set_phys_id) |
1636 | /* Do it the old way */ | ||
1637 | return dev->ethtool_ops->phys_id(dev, id.data); | ||
1638 | |||
1639 | rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ACTIVE); | ||
1640 | if (rc && rc != -EINVAL) | ||
1641 | return rc; | ||
1642 | |||
1643 | /* Drop the RTNL lock while waiting, but prevent reentry or | ||
1644 | * removal of the device. | ||
1645 | */ | ||
1646 | busy = true; | ||
1647 | dev_hold(dev); | ||
1648 | rtnl_unlock(); | ||
1649 | |||
1650 | if (rc == 0) { | ||
1651 | /* Driver will handle this itself */ | ||
1652 | schedule_timeout_interruptible( | ||
1653 | id.data ? id.data : MAX_SCHEDULE_TIMEOUT); | ||
1654 | } else { | ||
1655 | /* Driver expects to be called periodically */ | ||
1656 | do { | ||
1657 | rtnl_lock(); | ||
1658 | rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ON); | ||
1659 | rtnl_unlock(); | ||
1660 | if (rc) | ||
1661 | break; | ||
1662 | schedule_timeout_interruptible(HZ / 2); | ||
1663 | |||
1664 | rtnl_lock(); | ||
1665 | rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_OFF); | ||
1666 | rtnl_unlock(); | ||
1667 | if (rc) | ||
1668 | break; | ||
1669 | schedule_timeout_interruptible(HZ / 2); | ||
1670 | } while (!signal_pending(current) && | ||
1671 | (id.data == 0 || --id.data != 0)); | ||
1672 | } | ||
1673 | |||
1674 | rtnl_lock(); | ||
1675 | dev_put(dev); | ||
1676 | busy = false; | ||
1677 | |||
1678 | (void)dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_INACTIVE); | ||
1679 | return rc; | ||
1629 | } | 1680 | } |
1630 | 1681 | ||
1631 | static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) | 1682 | static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) |