]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/sfc/ethtool.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / net / sfc / ethtool.c
index edb9d16b8b47b0f81f622bfd91b6e9fbf3a70f6a..ca886d98bdc78e6b5a2a618ee7afb6ee271b329e 100644 (file)
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
 #include <linux/rtnetlink.h>
+#include <linux/in.h>
 #include "net_driver.h"
 #include "workarounds.h"
 #include "selftest.h"
 #include "efx.h"
 #include "filter.h"
 #include "nic.h"
-#include "spi.h"
-#include "mdio_10g.h"
 
 struct ethtool_string {
        char name[ETH_GSTRING_LEN];
@@ -560,12 +559,8 @@ static int efx_ethtool_set_flags(struct net_device *net_dev, u32 data)
        if (rc)
                return rc;
 
-       if (!(data & ETH_FLAG_NTUPLE)) {
-               efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_IP,
-                                      EFX_FILTER_PRI_MANUAL);
-               efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_MAC,
-                                      EFX_FILTER_PRI_MANUAL);
-       }
+       if (!(data & ETH_FLAG_NTUPLE))
+               efx_filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL);
 
        return 0;
 }
@@ -574,9 +569,14 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
                                  struct ethtool_test *test, u64 *data)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
-       struct efx_self_tests efx_tests;
+       struct efx_self_tests *efx_tests;
        int already_up;
-       int rc;
+       int rc = -ENOMEM;
+
+       efx_tests = kzalloc(sizeof(*efx_tests), GFP_KERNEL);
+       if (!efx_tests)
+               goto fail;
+
 
        ASSERT_RTNL();
        if (efx->state != STATE_RUNNING) {
@@ -584,6 +584,9 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
                goto fail1;
        }
 
+       netif_info(efx, drv, efx->net_dev, "starting %sline testing\n",
+                  (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on");
+
        /* We need rx buffers and interrupts. */
        already_up = (efx->net_dev->flags & IFF_UP);
        if (!already_up) {
@@ -591,25 +594,24 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
                if (rc) {
                        netif_err(efx, drv, efx->net_dev,
                                  "failed opening device.\n");
-                       goto fail2;
+                       goto fail1;
                }
        }
 
-       memset(&efx_tests, 0, sizeof(efx_tests));
-
-       rc = efx_selftest(efx, &efx_tests, test->flags);
+       rc = efx_selftest(efx, efx_tests, test->flags);
 
        if (!already_up)
                dev_close(efx->net_dev);
 
-       netif_dbg(efx, drv, efx->net_dev, "%s %sline self-tests\n",
-                 rc == 0 ? "passed" : "failed",
-                 (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on");
+       netif_info(efx, drv, efx->net_dev, "%s %sline self-tests\n",
+                  rc == 0 ? "passed" : "failed",
+                  (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on");
 
- fail2:
- fail1:
+fail1:
        /* Fill ethtool results structures */
-       efx_ethtool_fill_self_tests(efx, &efx_tests, NULL, data);
+       efx_ethtool_fill_self_tests(efx, efx_tests, NULL, data);
+       kfree(efx_tests);
+fail:
        if (rc)
                test->flags |= ETH_TEST_FL_FAILED;
 }
@@ -622,68 +624,6 @@ static int efx_ethtool_nway_reset(struct net_device *net_dev)
        return mdio45_nway_restart(&efx->mdio);
 }
 
-static u32 efx_ethtool_get_link(struct net_device *net_dev)
-{
-       struct efx_nic *efx = netdev_priv(net_dev);
-
-       return efx->link_state.up;
-}
-
-static int efx_ethtool_get_eeprom_len(struct net_device *net_dev)
-{
-       struct efx_nic *efx = netdev_priv(net_dev);
-       struct efx_spi_device *spi = efx->spi_eeprom;
-
-       if (!spi)
-               return 0;
-       return min(spi->size, EFX_EEPROM_BOOTCONFIG_END) -
-               min(spi->size, EFX_EEPROM_BOOTCONFIG_START);
-}
-
-static int efx_ethtool_get_eeprom(struct net_device *net_dev,
-                                 struct ethtool_eeprom *eeprom, u8 *buf)
-{
-       struct efx_nic *efx = netdev_priv(net_dev);
-       struct efx_spi_device *spi = efx->spi_eeprom;
-       size_t len;
-       int rc;
-
-       rc = mutex_lock_interruptible(&efx->spi_lock);
-       if (rc)
-               return rc;
-       rc = falcon_spi_read(efx, spi,
-                            eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
-                            eeprom->len, &len, buf);
-       mutex_unlock(&efx->spi_lock);
-
-       eeprom->magic = EFX_ETHTOOL_EEPROM_MAGIC;
-       eeprom->len = len;
-       return rc;
-}
-
-static int efx_ethtool_set_eeprom(struct net_device *net_dev,
-                                 struct ethtool_eeprom *eeprom, u8 *buf)
-{
-       struct efx_nic *efx = netdev_priv(net_dev);
-       struct efx_spi_device *spi = efx->spi_eeprom;
-       size_t len;
-       int rc;
-
-       if (eeprom->magic != EFX_ETHTOOL_EEPROM_MAGIC)
-               return -EINVAL;
-
-       rc = mutex_lock_interruptible(&efx->spi_lock);
-       if (rc)
-               return rc;
-       rc = falcon_spi_write(efx, spi,
-                             eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
-                             eeprom->len, &len, buf);
-       mutex_unlock(&efx->spi_lock);
-
-       eeprom->len = len;
-       return rc;
-}
-
 static int efx_ethtool_get_coalesce(struct net_device *net_dev,
                                    struct ethtool_coalesce *coalesce)
 {
@@ -978,6 +918,7 @@ static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
        struct ethhdr *mac_entry = &ntuple->fs.h_u.ether_spec;
        struct ethhdr *mac_mask = &ntuple->fs.m_u.ether_spec;
        struct efx_filter_spec filter;
+       int rc;
 
        /* Range-check action */
        if (ntuple->fs.action < ETHTOOL_RXNTUPLE_ACTION_CLEAR ||
@@ -987,9 +928,16 @@ static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
        if (~ntuple->fs.data_mask)
                return -EINVAL;
 
+       efx_filter_init_rx(&filter, EFX_FILTER_PRI_MANUAL, 0,
+                          (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP) ?
+                          0xfff : ntuple->fs.action);
+
        switch (ntuple->fs.flow_type) {
        case TCP_V4_FLOW:
-       case UDP_V4_FLOW:
+       case UDP_V4_FLOW: {
+               u8 proto = (ntuple->fs.flow_type == TCP_V4_FLOW ?
+                           IPPROTO_TCP : IPPROTO_UDP);
+
                /* Must match all of destination, */
                if (ip_mask->ip4dst | ip_mask->pdst)
                        return -EINVAL;
@@ -1001,7 +949,22 @@ static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
                /* and nothing else */
                if ((u8)~ip_mask->tos | (u16)~ntuple->fs.vlan_tag_mask)
                        return -EINVAL;
+
+               if (!ip_mask->ip4src)
+                       rc = efx_filter_set_ipv4_full(&filter, proto,
+                                                     ip_entry->ip4dst,
+                                                     ip_entry->pdst,
+                                                     ip_entry->ip4src,
+                                                     ip_entry->psrc);
+               else
+                       rc = efx_filter_set_ipv4_local(&filter, proto,
+                                                      ip_entry->ip4dst,
+                                                      ip_entry->pdst);
+               if (rc)
+                       return rc;
                break;
+       }
+
        case ETHER_FLOW:
                /* Must match all of destination, */
                if (!is_zero_ether_addr(mac_mask->h_dest))
@@ -1014,58 +977,24 @@ static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
                if (!is_broadcast_ether_addr(mac_mask->h_source) ||
                    mac_mask->h_proto != htons(0xffff))
                        return -EINVAL;
+
+               rc = efx_filter_set_eth_local(
+                       &filter,
+                       (ntuple->fs.vlan_tag_mask == 0xf000) ?
+                       ntuple->fs.vlan_tag : EFX_FILTER_VID_UNSPEC,
+                       mac_entry->h_dest);
+               if (rc)
+                       return rc;
                break;
+
        default:
                return -EINVAL;
        }
 
-       filter.priority = EFX_FILTER_PRI_MANUAL;
-       filter.flags = 0;
-
-       switch (ntuple->fs.flow_type) {
-       case TCP_V4_FLOW:
-               if (!ip_mask->ip4src)
-                       efx_filter_set_rx_tcp_full(&filter,
-                                                  htonl(ip_entry->ip4src),
-                                                  htons(ip_entry->psrc),
-                                                  htonl(ip_entry->ip4dst),
-                                                  htons(ip_entry->pdst));
-               else
-                       efx_filter_set_rx_tcp_wild(&filter,
-                                                  htonl(ip_entry->ip4dst),
-                                                  htons(ip_entry->pdst));
-               break;
-       case UDP_V4_FLOW:
-               if (!ip_mask->ip4src)
-                       efx_filter_set_rx_udp_full(&filter,
-                                                  htonl(ip_entry->ip4src),
-                                                  htons(ip_entry->psrc),
-                                                  htonl(ip_entry->ip4dst),
-                                                  htons(ip_entry->pdst));
-               else
-                       efx_filter_set_rx_udp_wild(&filter,
-                                                  htonl(ip_entry->ip4dst),
-                                                  htons(ip_entry->pdst));
-               break;
-       case ETHER_FLOW:
-               if (ntuple->fs.vlan_tag_mask == 0xf000)
-                       efx_filter_set_rx_mac_full(&filter,
-                                                  ntuple->fs.vlan_tag & 0xfff,
-                                                  mac_entry->h_dest);
-               else
-                       efx_filter_set_rx_mac_wild(&filter, mac_entry->h_dest);
-               break;
-       }
-
-       if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_CLEAR) {
+       if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_CLEAR)
                return efx_filter_remove_filter(efx, &filter);
-       } else {
-               if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
-                       filter.dmaq_id = 0xfff;
-               else
-                       filter.dmaq_id = ntuple->fs.action;
+       else
                return efx_filter_insert_filter(efx, &filter, true);
-       }
 }
 
 static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev,
@@ -1115,10 +1044,7 @@ const struct ethtool_ops efx_ethtool_ops = {
        .get_msglevel           = efx_ethtool_get_msglevel,
        .set_msglevel           = efx_ethtool_set_msglevel,
        .nway_reset             = efx_ethtool_nway_reset,
-       .get_link               = efx_ethtool_get_link,
-       .get_eeprom_len         = efx_ethtool_get_eeprom_len,
-       .get_eeprom             = efx_ethtool_get_eeprom,
-       .set_eeprom             = efx_ethtool_set_eeprom,
+       .get_link               = ethtool_op_get_link,
        .get_coalesce           = efx_ethtool_get_coalesce,
        .set_coalesce           = efx_ethtool_set_coalesce,
        .get_ringparam          = efx_ethtool_get_ringparam,