fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / net / ioc3-eth.c
index e16f8b2..f0d30cf 100644 (file)
@@ -28,9 +28,8 @@
  */
 
 #define IOC3_NAME      "ioc3-eth"
-#define IOC3_VERSION   "2.6.3-3"
+#define IOC3_VERSION   "2.6.3-4"
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
+#include <linux/dma-mapping.h>
 
 #ifdef CONFIG_SERIAL_8250
-#include <linux/serial.h>
-#include <asm/serial.h>
-#define IOC3_BAUD (22000000 / (3*16))
-#define IOC3_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
 #endif
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/skbuff.h>
-#include <linux/dp83840.h>
 #include <net/ip.h>
 
 #include <asm/byteorder.h>
-#include <asm/checksum.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -118,7 +114,7 @@ static inline void ioc3_stop(struct ioc3_private *ip);
 static void ioc3_init(struct net_device *dev);
 
 static const char ioc3_str[] = "IOC3 Ethernet";
-static struct ethtool_ops ioc3_ethtool_ops;
+static const struct ethtool_ops ioc3_ethtool_ops;
 
 /* We use this to acquire receive skb's that we can DMA directly into. */
 
@@ -147,7 +143,7 @@ static inline struct sk_buff * ioc3_alloc_skb(unsigned long length,
 static inline unsigned long ioc3_map(void *ptr, unsigned long vdev)
 {
 #ifdef CONFIG_SGI_IP27
-       vdev <<= 58;   /* Shift to PCI64_ATTR_VIRTUAL */
+       vdev <<= 57;   /* Shift to PCI64_ATTR_VIRTUAL */
 
        return vdev | (0xaUL << PCI64_ATTR_TARG_SHFT) | PCI64_ATTR_PREF |
               ((unsigned long)ptr & TO_PHYS_MASK);
@@ -463,6 +459,29 @@ static void ioc3_get_eaddr(struct ioc3_private *ip)
        printk(".\n");
 }
 
+static void __ioc3_set_mac_address(struct net_device *dev)
+{
+       struct ioc3_private *ip = netdev_priv(dev);
+       struct ioc3 *ioc3 = ip->regs;
+
+       ioc3_w_emar_h((dev->dev_addr[5] <<  8) | dev->dev_addr[4]);
+       ioc3_w_emar_l((dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) |
+                     (dev->dev_addr[1] <<  8) | dev->dev_addr[0]);
+}
+
+static int ioc3_set_mac_address(struct net_device *dev, void *addr)
+{
+       struct ioc3_private *ip = netdev_priv(dev);
+       struct sockaddr *sa = addr;
+
+       memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+
+       spin_lock_irq(&ip->ioc3_lock);
+       __ioc3_set_mac_address(dev);
+       spin_unlock_irq(&ip->ioc3_lock);
+
+       return 0;
+}
 
 /*
  * Caller must hold the ioc3_lock ever for MII readers.  This is also
@@ -477,7 +496,7 @@ static int ioc3_mdio_read(struct net_device *dev, int phy, int reg)
        ioc3_w_micr((phy << MICR_PHYADDR_SHIFT) | reg | MICR_READTRIG);
        while (ioc3_r_micr() & MICR_BUSY);
 
-       return ioc3_r_micr() & MIDR_DATA_MASK;
+       return ioc3_r_midr_r() & MIDR_DATA_MASK;
 }
 
 static void ioc3_mdio_write(struct net_device *dev, int phy, int reg, int data)
@@ -730,7 +749,7 @@ static void ioc3_error(struct ioc3_private *ip, u32 eisr)
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread.  */
-static irqreturn_t ioc3_interrupt(int irq, void *_dev, struct pt_regs *regs)
+static irqreturn_t ioc3_interrupt(int irq, void *_dev)
 {
        struct net_device *dev = (struct net_device *)_dev;
        struct ioc3_private *ip = netdev_priv(dev);
@@ -997,7 +1016,7 @@ static void ioc3_init(struct net_device *dev)
        struct ioc3_private *ip = netdev_priv(dev);
        struct ioc3 *ioc3 = ip->regs;
 
-       del_timer(&ip->ioc3_timer);             /* Kill if running      */
+       del_timer_sync(&ip->ioc3_timer);        /* Kill if running      */
 
        ioc3_w_emcr(EMCR_RST);                  /* Reset                */
        (void) ioc3_r_emcr();                   /* Flush WB             */
@@ -1014,9 +1033,7 @@ static void ioc3_init(struct net_device *dev)
        (void) ioc3_r_etcdc();                  /* Clear on read */
        ioc3_w_ercsr(15);                       /* RX low watermark  */
        ioc3_w_ertr(0);                         /* Interrupt immediately */
-       ioc3_w_emar_h((dev->dev_addr[5] <<  8) | dev->dev_addr[4]);
-       ioc3_w_emar_l((dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) |
-                     (dev->dev_addr[1] <<  8) | dev->dev_addr[0]);
+       __ioc3_set_mac_address(dev);
        ioc3_w_ehar_h(ip->ehar_h);
        ioc3_w_ehar_l(ip->ehar_l);
        ioc3_w_ersr(42);                        /* XXX should be random */
@@ -1045,7 +1062,7 @@ static int ioc3_open(struct net_device *dev)
 {
        struct ioc3_private *ip = netdev_priv(dev);
 
-       if (request_irq(dev->irq, ioc3_interrupt, SA_SHIRQ, ioc3_str, dev)) {
+       if (request_irq(dev->irq, ioc3_interrupt, IRQF_SHARED, ioc3_str, dev)) {
                printk(KERN_ERR "%s: Can't get irq %d\n", dev->name, dev->irq);
 
                return -EAGAIN;
@@ -1063,7 +1080,7 @@ static int ioc3_close(struct net_device *dev)
 {
        struct ioc3_private *ip = netdev_priv(dev);
 
-       del_timer(&ip->ioc3_timer);
+       del_timer_sync(&ip->ioc3_timer);
 
        netif_stop_queue(dev);
 
@@ -1100,6 +1117,7 @@ static inline int ioc3_is_menet(struct pci_dev *pdev)
               && dev->device == PCI_DEVICE_ID_SGI_IOC3;
 }
 
+#ifdef CONFIG_SERIAL_8250
 /*
  * Note about serial ports and consoles:
  * For console output, everyone uses the IOC3 UARTA (offset 0x178)
@@ -1121,17 +1139,15 @@ static inline int ioc3_is_menet(struct pci_dev *pdev)
  * "device" routine referred to in this console structure
  * (ip27prom_console_dev).
  *
- * Also look in ip27-pci.c:pci_fixuop_ioc3() for some comments on working
+ * Also look in ip27-pci.c:pci_fixup_ioc3() for some comments on working
  * around ioc3 oddities in this respect.
  *
  * The IOC3 serials use a 22MHz clock rate with an additional divider by 3.
- * (IOC3_BAUD = (22000000 / (3*16)))
  */
 
-static inline void ioc3_serial_probe(struct pci_dev *pdev,
-                               struct ioc3 *ioc3)
+static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
 {
-       struct serial_struct req;
+       struct uart_port port;
 
        /*
         * We need to recognice and treat the fourth MENET serial as it
@@ -1145,24 +1161,29 @@ static inline void ioc3_serial_probe(struct pci_dev *pdev,
        if (ioc3_is_menet(pdev) && PCI_SLOT(pdev->devfn) == 3)
                return;
 
-       /* Register to interrupt zero because we share the interrupt with
-          the serial driver which we don't properly support yet.  */
-       memset(&req, 0, sizeof(req));
-       req.irq             = 0;
-       req.flags           = IOC3_COM_FLAGS;
-       req.io_type         = SERIAL_IO_MEM;
-       req.iomem_reg_shift = 0;
-       req.baud_base       = IOC3_BAUD;
-
-       req.iomem_base      = (unsigned char *) &ioc3->sregs.uarta;
-       register_serial(&req);
-
-       req.iomem_base      = (unsigned char *) &ioc3->sregs.uartb;
-       register_serial(&req);
+       /*
+        * Register to interrupt zero because we share the interrupt with
+        * the serial driver which we don't properly support yet.
+        *
+        * Can't use UPF_IOREMAP as the whole of IOC3 resources have already
+        * been registered.
+        */
+       memset(&port, 0, sizeof(port));
+       port.irq      = 0;
+       port.flags    = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+       port.iotype   = UPIO_MEM;
+       port.regshift = 0;
+       port.uartclk  = 22000000 / 3;
+
+       port.membase  = (unsigned char *) &ioc3->sregs.uarta;
+       serial8250_register_port(&port);
+
+       port.membase  = (unsigned char *) &ioc3->sregs.uartb;
+       serial8250_register_port(&port);
 }
+#endif
 
-static int __devinit ioc3_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        unsigned int sw_physid1, sw_physid2;
        struct net_device *dev = NULL;
@@ -1170,11 +1191,39 @@ static int __devinit ioc3_probe(struct pci_dev *pdev,
        struct ioc3 *ioc3;
        unsigned long ioc3_base, ioc3_size;
        u32 vendor, model, rev;
-       int err;
+       int err, pci_using_dac;
+
+       /* Configure DMA attributes. */
+       err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+       if (!err) {
+               pci_using_dac = 1;
+               err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+               if (err < 0) {
+                       printk(KERN_ERR "%s: Unable to obtain 64 bit DMA "
+                              "for consistent allocations\n", pci_name(pdev));
+                       goto out;
+               }
+       } else {
+               err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+               if (err) {
+                       printk(KERN_ERR "%s: No usable DMA configuration, "
+                              "aborting.\n", pci_name(pdev));
+                       goto out;
+               }
+               pci_using_dac = 0;
+       }
+
+       if (pci_enable_device(pdev))
+               return -ENODEV;
 
        dev = alloc_etherdev(sizeof(struct ioc3_private));
-       if (!dev)
-               return -ENOMEM;
+       if (!dev) {
+               err = -ENOMEM;
+               goto out_disable;
+       }
+
+       if (pci_using_dac)
+               dev->features |= NETIF_F_HIGHDMA;
 
        err = pci_request_regions(pdev, "ioc3");
        if (err)
@@ -1237,12 +1286,12 @@ static int __devinit ioc3_probe(struct pci_dev *pdev,
        dev->get_stats          = ioc3_get_stats;
        dev->do_ioctl           = ioc3_ioctl;
        dev->set_multicast_list = ioc3_set_multicast_list;
+       dev->set_mac_address    = ioc3_set_mac_address;
        dev->ethtool_ops        = &ioc3_ethtool_ops;
 #ifdef CONFIG_SGI_IOC3_ETH_HW_TX_CSUM
        dev->features           = NETIF_F_IP_CSUM;
 #endif
 
-       ioc3_setup_duplex(ip);
        sw_physid1 = ioc3_mdio_read(dev, ip->mii.phy_id, MII_PHYSID1);
        sw_physid2 = ioc3_mdio_read(dev, ip->mii.phy_id, MII_PHYSID2);
 
@@ -1251,6 +1300,7 @@ static int __devinit ioc3_probe(struct pci_dev *pdev,
                goto out_stop;
 
        mii_check_media(&ip->mii, 1, 1);
+       ioc3_setup_duplex(ip);
 
        vendor = (sw_physid1 << 12) | (sw_physid2 >> 4);
        model  = (sw_physid2 >> 4) & 0x3f;
@@ -1269,6 +1319,12 @@ out_res:
        pci_release_regions(pdev);
 out_free:
        free_netdev(dev);
+out_disable:
+       /*
+        * We should call pci_disable_device(pdev); here if the IOC3 wasn't
+        * such a weird device ...
+        */
+out:
        return err;
 }
 
@@ -1282,6 +1338,10 @@ static void __devexit ioc3_remove_one (struct pci_dev *pdev)
        iounmap(ioc3);
        pci_release_regions(pdev);
        free_netdev(dev);
+       /*
+        * We should call pci_disable_device(pdev); here if the IOC3 wasn't
+        * such a weird device ...
+        */
 }
 
 static struct pci_device_id ioc3_pci_tbl[] = {
@@ -1299,7 +1359,7 @@ static struct pci_driver ioc3_driver = {
 
 static int __init ioc3_init_module(void)
 {
-       return pci_module_init(&ioc3_driver);
+       return pci_register_driver(&ioc3_driver);
 }
 
 static void __exit ioc3_cleanup_module(void)
@@ -1326,7 +1386,7 @@ static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev)
         * MAC header which should not be summed and the TCP/UDP pseudo headers
         * manually.
         */
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                int proto = ntohs(skb->nh.iph->protocol);
                unsigned int csoff;
                struct iphdr *ih = skb->nh.iph;
@@ -1465,7 +1525,7 @@ static void ioc3_get_drvinfo (struct net_device *dev,
        struct ethtool_drvinfo *info)
 {
        struct ioc3_private *ip = netdev_priv(dev);
-                                                                                
+
         strcpy (info->driver, IOC3_NAME);
         strcpy (info->version, IOC3_VERSION);
         strcpy (info->bus_info, pci_name(ip->pdev));
@@ -1491,7 +1551,7 @@ static int ioc3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        spin_lock_irq(&ip->ioc3_lock);
        rc = mii_ethtool_sset(&ip->mii, cmd);
        spin_unlock_irq(&ip->ioc3_lock);
-                                                                        
+
        return rc;
 }
 
@@ -1519,7 +1579,7 @@ static u32 ioc3_get_link(struct net_device *dev)
        return rc;
 }
 
-static struct ethtool_ops ioc3_ethtool_ops = {
+static const struct ethtool_ops ioc3_ethtool_ops = {
        .get_drvinfo            = ioc3_get_drvinfo,
        .get_settings           = ioc3_get_settings,
        .set_settings           = ioc3_set_settings,
@@ -1550,8 +1610,6 @@ static void ioc3_set_multicast_list(struct net_device *dev)
        netif_stop_queue(dev);                          /* Lock out others. */
 
        if (dev->flags & IFF_PROMISC) {                 /* Set promiscuous.  */
-               /* Unconditionally log net taps.  */
-               printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
                ip->emcr |= EMCR_PROMISC;
                ioc3_w_emcr(ip->emcr);
                (void) ioc3_r_emcr();