sfc: 10Xpress: Report support for pause frames
[linux-2.6.git] / drivers / net / acenic.c
index 109eb7c..d82a9a9 100644 (file)
@@ -66,6 +66,7 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/sockios.h>
+#include <linux/firmware.h>
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 #include <linux/if_vlan.h>
@@ -186,8 +187,6 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
 #define MAX_RODATA_LEN 8*1024
 #define MAX_DATA_LEN   2*1024
 
-#include "acenic_firmware.h"
-
 #ifndef tigon2FwReleaseLocal
 #define tigon2FwReleaseLocal 0
 #endif
@@ -417,6 +416,10 @@ static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
 MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver");
+#ifndef CONFIG_ACENIC_OMIT_TIGON_I
+MODULE_FIRMWARE("acenic/tg1.bin");
+#endif
+MODULE_FIRMWARE("acenic/tg2.bin");
 
 module_param_array_named(link, link_state, int, NULL, 0);
 module_param_array(trace, int, NULL, 0);
@@ -434,7 +437,7 @@ MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descript
 MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)");
 
 
-static char version[] __devinitdata =
+static const char version[] __devinitconst =
   "acenic.c: v0.92 08/05/2002  Jes Sorensen, linux-acenic@SunSITE.dk\n"
   "                            http://home.cern.ch/~jes/gige/acenic.html\n";
 
@@ -450,6 +453,21 @@ static const struct ethtool_ops ace_ethtool_ops = {
 
 static void ace_watchdog(struct net_device *dev);
 
+static const struct net_device_ops ace_netdev_ops = {
+       .ndo_open               = ace_open,
+       .ndo_stop               = ace_close,
+       .ndo_tx_timeout         = ace_watchdog,
+       .ndo_get_stats          = ace_get_stats,
+       .ndo_start_xmit         = ace_start_xmit,
+       .ndo_set_multicast_list = ace_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = ace_set_mac_addr,
+       .ndo_change_mtu         = ace_change_mtu,
+#if ACENIC_DO_VLAN
+       .ndo_vlan_rx_register   = ace_vlan_rx_register,
+#endif
+};
+
 static int __devinit acenic_probe_one(struct pci_dev *pdev,
                const struct pci_device_id *id)
 {
@@ -473,20 +491,12 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev,
        dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
 #if ACENIC_DO_VLAN
        dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-       dev->vlan_rx_register = ace_vlan_rx_register;
 #endif
 
-       dev->tx_timeout = &ace_watchdog;
        dev->watchdog_timeo = 5*HZ;
 
-       dev->open = &ace_open;
-       dev->stop = &ace_close;
-       dev->hard_start_xmit = &ace_start_xmit;
-       dev->get_stats = &ace_get_stats;
-       dev->set_multicast_list = &ace_set_multicast_list;
+       dev->netdev_ops = &ace_netdev_ops;
        SET_ETHTOOL_OPS(dev, &ace_ethtool_ops);
-       dev->set_mac_address = &ace_set_mac_addr;
-       dev->change_mtu = &ace_change_mtu;
 
        /* we only display this string ONCE */
        if (!boards_found)
@@ -937,8 +947,8 @@ static int __devinit ace_init(struct net_device *dev)
        case 4:
        case 5:
                printk(KERN_INFO "  Tigon I  (Rev. %i), Firmware: %i.%i.%i, ",
-                      tig_ver, tigonFwReleaseMajor, tigonFwReleaseMinor,
-                      tigonFwReleaseFix);
+                      tig_ver, ap->firmware_major, ap->firmware_minor,
+                      ap->firmware_fix);
                writel(0, &regs->LocalCtrl);
                ap->version = 1;
                ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES;
@@ -946,8 +956,8 @@ static int __devinit ace_init(struct net_device *dev)
 #endif
        case 6:
                printk(KERN_INFO "  Tigon II (Rev. %i), Firmware: %i.%i.%i, ",
-                      tig_ver, tigon2FwReleaseMajor, tigon2FwReleaseMinor,
-                      tigon2FwReleaseFix);
+                      tig_ver, ap->firmware_major, ap->firmware_minor,
+                      ap->firmware_fix);
                writel(readl(&regs->CpuBCtrl) | CPU_HALT, &regs->CpuBCtrl);
                readl(&regs->CpuBCtrl);         /* PCI write posting */
                /*
@@ -1151,9 +1161,9 @@ static int __devinit ace_init(struct net_device *dev)
        /*
         * Configure DMA attributes.
         */
-       if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
                ap->pci_using_dac = 1;
-       } else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+       } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
                ap->pci_using_dac = 0;
        } else {
                ecode = -ENODEV;
@@ -1199,7 +1209,10 @@ static int __devinit ace_init(struct net_device *dev)
        memset(ap->info, 0, sizeof(struct ace_info));
        memset(ap->skb, 0, sizeof(struct ace_skb));
 
-       ace_load_firmware(dev);
+       ecode = ace_load_firmware(dev);
+       if (ecode)
+               goto init_error;
+
        ap->fw_running = 0;
 
        tmp_ptr = ap->info_dma;
@@ -1435,10 +1448,7 @@ static int __devinit ace_init(struct net_device *dev)
        if (ap->version >= 2)
                writel(tmp, &regs->TuneFastLink);
 
-       if (ACE_IS_TIGON_I(ap))
-               writel(tigonFwStartAddr, &regs->Pc);
-       if (ap->version == 2)
-               writel(tigon2FwStartAddr, &regs->Pc);
+       writel(ap->firmware_start, &regs->Pc);
 
        writel(0, &regs->Mb0Lo);
 
@@ -2455,7 +2465,8 @@ ace_load_tx_bd(struct ace_private *ap, struct tx_desc *desc, u64 addr,
 }
 
 
-static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t ace_start_xmit(struct sk_buff *skb,
+                                 struct net_device *dev)
 {
        struct ace_private *ap = netdev_priv(dev);
        struct ace_regs __iomem *regs = ap->regs;
@@ -2564,7 +2575,6 @@ restart:
                        netif_wake_queue(dev);
        }
 
-       dev->trans_start = jiffies;
        return NETDEV_TX_OK;
 
 overflow:
@@ -2755,8 +2765,8 @@ static void ace_get_drvinfo(struct net_device *dev,
 
        strlcpy(info->driver, "acenic", sizeof(info->driver));
        snprintf(info->version, sizeof(info->version), "%i.%i.%i",
-               tigonFwReleaseMajor, tigonFwReleaseMinor,
-               tigonFwReleaseFix);
+                ap->firmware_major, ap->firmware_minor,
+                ap->firmware_fix);
 
        if (ap->pdev)
                strlcpy(info->bus_info, pci_name(ap->pdev),
@@ -2863,11 +2873,10 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev)
 }
 
 
-static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src,
-                           u32 dest, int size)
+static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
+                              u32 dest, int size)
 {
        void __iomem *tdest;
-       u32 *wsrc;
        short tsize, i;
 
        if (size <= 0)
@@ -2879,20 +2888,15 @@ static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src,
                tdest = (void __iomem *) &regs->Window +
                        (dest & (ACE_WINDOW_SIZE - 1));
                writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->WinBase);
-               /*
-                * This requires byte swapping on big endian, however
-                * writel does that for us
-                */
-               wsrc = src;
                for (i = 0; i < (tsize / 4); i++) {
-                       writel(wsrc[i], tdest + i*4);
+                       /* Firmware is big-endian */
+                       writel(be32_to_cpup(src), tdest);
+                       src++;
+                       tdest += 4;
+                       dest += 4;
+                       size -= 4;
                }
-               dest += tsize;
-               src += tsize;
-               size -= tsize;
        }
-
-       return;
 }
 
 
@@ -2931,8 +2935,13 @@ static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int siz
  */
 static int __devinit ace_load_firmware(struct net_device *dev)
 {
+       const struct firmware *fw;
+       const char *fw_name = "acenic/tg2.bin";
        struct ace_private *ap = netdev_priv(dev);
        struct ace_regs __iomem *regs = ap->regs;
+       const __be32 *fw_data;
+       u32 load_addr;
+       int ret;
 
        if (!(readl(&regs->CpuCtrl) & CPU_HALTED)) {
                printk(KERN_ERR "%s: trying to download firmware while the "
@@ -2940,28 +2949,52 @@ static int __devinit ace_load_firmware(struct net_device *dev)
                return -EFAULT;
        }
 
+       if (ACE_IS_TIGON_I(ap))
+               fw_name = "acenic/tg1.bin";
+
+       ret = request_firmware(&fw, fw_name, &ap->pdev->dev);
+       if (ret) {
+               printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n",
+                      ap->name, fw_name);
+               return ret;
+       }
+
+       fw_data = (void *)fw->data;
+
+       /* Firmware blob starts with version numbers, followed by
+          load and start address. Remainder is the blob to be loaded
+          contiguously from load address. We don't bother to represent
+          the BSS/SBSS sections any more, since we were clearing the
+          whole thing anyway. */
+       ap->firmware_major = fw->data[0];
+       ap->firmware_minor = fw->data[1];
+       ap->firmware_fix = fw->data[2];
+
+       ap->firmware_start = be32_to_cpu(fw_data[1]);
+       if (ap->firmware_start < 0x4000 || ap->firmware_start >= 0x80000) {
+               printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n",
+                      ap->name, ap->firmware_start, fw_name);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       load_addr = be32_to_cpu(fw_data[2]);
+       if (load_addr < 0x4000 || load_addr >= 0x80000) {
+               printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n",
+                      ap->name, load_addr, fw_name);
+               ret = -EINVAL;
+               goto out;
+       }
+
        /*
-        * Do not try to clear more than 512KB or we end up seeing
-        * funny things on NICs with only 512KB SRAM
+        * Do not try to clear more than 512KiB or we end up seeing
+        * funny things on NICs with only 512KiB SRAM
         */
        ace_clear(regs, 0x2000, 0x80000-0x2000);
-       if (ACE_IS_TIGON_I(ap)) {
-               ace_copy(regs, tigonFwText, tigonFwTextAddr, tigonFwTextLen);
-               ace_copy(regs, tigonFwData, tigonFwDataAddr, tigonFwDataLen);
-               ace_copy(regs, tigonFwRodata, tigonFwRodataAddr,
-                        tigonFwRodataLen);
-               ace_clear(regs, tigonFwBssAddr, tigonFwBssLen);
-               ace_clear(regs, tigonFwSbssAddr, tigonFwSbssLen);
-       }else if (ap->version == 2) {
-               ace_clear(regs, tigon2FwBssAddr, tigon2FwBssLen);
-               ace_clear(regs, tigon2FwSbssAddr, tigon2FwSbssLen);
-               ace_copy(regs, tigon2FwText, tigon2FwTextAddr,tigon2FwTextLen);
-               ace_copy(regs, tigon2FwRodata, tigon2FwRodataAddr,
-                        tigon2FwRodataLen);
-               ace_copy(regs, tigon2FwData, tigon2FwDataAddr,tigon2FwDataLen);
-       }
-
-       return 0;
+       ace_copy(regs, &fw_data[3], load_addr, fw->size-12);
+ out:
+       release_firmware(fw);
+       return ret;
 }
 
 
@@ -3218,10 +3251,3 @@ static int __devinit read_eeprom_byte(struct net_device *dev,
               ap->name, offset);
        goto out;
 }
-
-
-/*
- * Local variables:
- * compile-command: "gcc -D__SMP__ -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h   -c -o acenic.o acenic.c"
- * End:
- */