Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-2.6.git] / drivers / net / skge.c
index a8a6358..f4be5c7 100644 (file)
@@ -43,6 +43,8 @@
 #include <linux/seq_file.h>
 #include <linux/mii.h>
 #include <linux/slab.h>
+#include <linux/dmi.h>
+#include <linux/prefetch.h>
 #include <asm/irq.h>
 
 #include "skge.h"
@@ -302,7 +304,7 @@ static int skge_get_settings(struct net_device *dev,
 
        ecmd->advertising = skge->advertising;
        ecmd->autoneg = skge->autoneg;
-       ecmd->speed = skge->speed;
+       ethtool_cmd_speed_set(ecmd, skge->speed);
        ecmd->duplex = skge->duplex;
        return 0;
 }
@@ -320,8 +322,9 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                skge->speed = -1;
        } else {
                u32 setting;
+               u32 speed = ethtool_cmd_speed(ecmd);
 
-               switch (ecmd->speed) {
+               switch (speed) {
                case SPEED_1000:
                        if (ecmd->duplex == DUPLEX_FULL)
                                setting = SUPPORTED_1000baseT_Full;
@@ -354,7 +357,7 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                if ((setting & supported) == 0)
                        return -EINVAL;
 
-               skge->speed = ecmd->speed;
+               skge->speed = speed;
                skge->duplex = ecmd->duplex;
        }
 
@@ -536,46 +539,6 @@ static int skge_nway_reset(struct net_device *dev)
        return 0;
 }
 
-static int skge_set_sg(struct net_device *dev, u32 data)
-{
-       struct skge_port *skge = netdev_priv(dev);
-       struct skge_hw *hw = skge->hw;
-
-       if (hw->chip_id == CHIP_ID_GENESIS && data)
-               return -EOPNOTSUPP;
-       return ethtool_op_set_sg(dev, data);
-}
-
-static int skge_set_tx_csum(struct net_device *dev, u32 data)
-{
-       struct skge_port *skge = netdev_priv(dev);
-       struct skge_hw *hw = skge->hw;
-
-       if (hw->chip_id == CHIP_ID_GENESIS && data)
-               return -EOPNOTSUPP;
-
-       return ethtool_op_set_tx_csum(dev, data);
-}
-
-static u32 skge_get_rx_csum(struct net_device *dev)
-{
-       struct skge_port *skge = netdev_priv(dev);
-
-       return skge->rx_csum;
-}
-
-/* Only Yukon supports checksum offload. */
-static int skge_set_rx_csum(struct net_device *dev, u32 data)
-{
-       struct skge_port *skge = netdev_priv(dev);
-
-       if (skge->hw->chip_id == CHIP_ID_GENESIS && data)
-               return -EOPNOTSUPP;
-
-       skge->rx_csum = data;
-       return 0;
-}
-
 static void skge_get_pauseparam(struct net_device *dev,
                                struct ethtool_pauseparam *ecmd)
 {
@@ -785,28 +748,27 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
 }
 
 /* blink LED's for finding board */
-static int skge_phys_id(struct net_device *dev, u32 data)
+static int skge_set_phys_id(struct net_device *dev,
+                           enum ethtool_phys_id_state state)
 {
        struct skge_port *skge = netdev_priv(dev);
-       unsigned long ms;
-       enum led_mode mode = LED_MODE_TST;
 
-       if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
-               ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT / HZ) * 1000;
-       else
-               ms = data * 1000;
+       switch (state) {
+       case ETHTOOL_ID_ACTIVE:
+               return 2;       /* cycle on/off twice per second */
 
-       while (ms > 0) {
-               skge_led(skge, mode);
-               mode ^= LED_MODE_TST;
+       case ETHTOOL_ID_ON:
+               skge_led(skge, LED_MODE_TST);
+               break;
 
-               if (msleep_interruptible(BLINK_MS))
-                       break;
-               ms -= BLINK_MS;
-       }
+       case ETHTOOL_ID_OFF:
+               skge_led(skge, LED_MODE_OFF);
+               break;
 
-       /* back to regular LED state */
-       skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF);
+       case ETHTOOL_ID_INACTIVE:
+               /* back to regular LED state */
+               skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF);
+       }
 
        return 0;
 }
@@ -924,12 +886,8 @@ static const struct ethtool_ops skge_ethtool_ops = {
        .set_pauseparam = skge_set_pauseparam,
        .get_coalesce   = skge_get_coalesce,
        .set_coalesce   = skge_set_coalesce,
-       .set_sg         = skge_set_sg,
-       .set_tx_csum    = skge_set_tx_csum,
-       .get_rx_csum    = skge_get_rx_csum,
-       .set_rx_csum    = skge_set_rx_csum,
        .get_strings    = skge_get_strings,
-       .phys_id        = skge_phys_id,
+       .set_phys_id    = skge_set_phys_id,
        .get_sset_count = skge_get_sset_count,
        .get_ethtool_stats = skge_get_ethtool_stats,
 };
@@ -1190,7 +1148,7 @@ static void genesis_init(struct skge_hw *hw)
 
 static void genesis_reset(struct skge_hw *hw, int port)
 {
-       const u8 zero[8]  = { 0 };
+       static const u8 zero[8]  = { 0 };
        u32 reg;
 
        skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
@@ -1556,7 +1514,7 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
        int jumbo = hw->dev[port]->mtu > ETH_DATA_LEN;
        int i;
        u32 r;
-       const u8 zero[6]  = { 0 };
+       static const u8 zero[6]  = { 0 };
 
        for (i = 0; i < 10; i++) {
                skge_write16(hw, SK_REG(port, TX_MFF_CTRL1),
@@ -2763,7 +2721,7 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
        td->dma_hi = map >> 32;
 
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
-               const int offset = skb_transport_offset(skb);
+               const int offset = skb_checksum_start_offset(skb);
 
                /* This seems backwards, but it is what the sk98lin
                 * does.  Looks like hardware is wrong?
@@ -3084,7 +3042,8 @@ static struct sk_buff *skge_rx_get(struct net_device *dev,
        }
 
        skb_put(skb, len);
-       if (skge->rx_csum) {
+
+       if (dev->features & NETIF_F_RXCSUM) {
                skb->csum = csum;
                skb->ip_summed = CHECKSUM_COMPLETE;
        }
@@ -3846,19 +3805,15 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
        setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge);
 
        if (hw->chip_id != CHIP_ID_GENESIS) {
-               dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
-               skge->rx_csum = 1;
+               dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
+                                  NETIF_F_RXCSUM;
+               dev->features |= dev->hw_features;
        }
-       dev->features |= NETIF_F_GRO;
 
        /* read the mac address */
        memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN);
        memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
-       /* device is off until link detection */
-       netif_carrier_off(dev);
-       netif_stop_queue(dev);
-
        return dev;
 }
 
@@ -3869,6 +3824,8 @@ static void __devinit skge_show_addr(struct net_device *dev)
        netif_info(skge, probe, skge->netdev, "addr %pM\n", dev->dev_addr);
 }
 
+static int only_32bit_dma;
+
 static int __devinit skge_probe(struct pci_dev *pdev,
                                const struct pci_device_id *ent)
 {
@@ -3890,7 +3847,7 @@ static int __devinit skge_probe(struct pci_dev *pdev,
 
        pci_set_master(pdev);
 
-       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+       if (!only_32bit_dma && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
                using_dac = 1;
                err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
        } else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
@@ -4010,8 +3967,6 @@ static void __devexit skge_remove(struct pci_dev *pdev)
        if (!hw)
                return;
 
-       flush_scheduled_work();
-
        dev1 = hw->dev[1];
        if (dev1)
                unregister_netdev(dev1);
@@ -4042,53 +3997,40 @@ static void __devexit skge_remove(struct pci_dev *pdev)
 }
 
 #ifdef CONFIG_PM
-static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
+static int skge_suspend(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
        struct skge_hw *hw  = pci_get_drvdata(pdev);
-       int i, err, wol = 0;
+       int i;
 
        if (!hw)
                return 0;
 
-       err = pci_save_state(pdev);
-       if (err)
-               return err;
-
        for (i = 0; i < hw->ports; i++) {
                struct net_device *dev = hw->dev[i];
                struct skge_port *skge = netdev_priv(dev);
 
                if (netif_running(dev))
                        skge_down(dev);
+
                if (skge->wol)
                        skge_wol_init(skge);
-
-               wol |= skge->wol;
        }
 
        skge_write32(hw, B0_IMSK, 0);
 
-       pci_prepare_to_sleep(pdev);
-
        return 0;
 }
 
-static int skge_resume(struct pci_dev *pdev)
+static int skge_resume(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
        struct skge_hw *hw  = pci_get_drvdata(pdev);
        int i, err;
 
        if (!hw)
                return 0;
 
-       err = pci_back_from_sleep(pdev);
-       if (err)
-               goto out;
-
-       err = pci_restore_state(pdev);
-       if (err)
-               goto out;
-
        err = skge_reset(hw);
        if (err)
                goto out;
@@ -4109,12 +4051,19 @@ static int skge_resume(struct pci_dev *pdev)
 out:
        return err;
 }
+
+static SIMPLE_DEV_PM_OPS(skge_pm_ops, skge_suspend, skge_resume);
+#define SKGE_PM_OPS (&skge_pm_ops)
+
+#else
+
+#define SKGE_PM_OPS NULL
 #endif
 
 static void skge_shutdown(struct pci_dev *pdev)
 {
        struct skge_hw *hw  = pci_get_drvdata(pdev);
-       int i, wol = 0;
+       int i;
 
        if (!hw)
                return;
@@ -4125,15 +4074,10 @@ static void skge_shutdown(struct pci_dev *pdev)
 
                if (skge->wol)
                        skge_wol_init(skge);
-               wol |= skge->wol;
        }
 
-       if (pci_enable_wake(pdev, PCI_D3cold, wol))
-               pci_enable_wake(pdev, PCI_D3hot, wol);
-
-       pci_disable_device(pdev);
+       pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev));
        pci_set_power_state(pdev, PCI_D3hot);
-
 }
 
 static struct pci_driver skge_driver = {
@@ -4141,15 +4085,25 @@ static struct pci_driver skge_driver = {
        .id_table =     skge_id_table,
        .probe =        skge_probe,
        .remove =       __devexit_p(skge_remove),
-#ifdef CONFIG_PM
-       .suspend =      skge_suspend,
-       .resume =       skge_resume,
-#endif
        .shutdown =     skge_shutdown,
+       .driver.pm =    SKGE_PM_OPS,
+};
+
+static struct dmi_system_id skge_32bit_dma_boards[] = {
+       {
+               .ident = "Gigabyte nForce boards",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co"),
+                       DMI_MATCH(DMI_BOARD_NAME, "nForce"),
+               },
+       },
+       {}
 };
 
 static int __init skge_init_module(void)
 {
+       if (dmi_check_system(skge_32bit_dma_boards))
+               only_32bit_dma = 1;
        skge_debug_init();
        return pci_register_driver(&skge_driver);
 }