headers: remove sched.h from interrupt.h
[safe/jmp/linux-2.6] / drivers / net / sungem.c
index 6f935cd..7019a0d 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
@@ -148,7 +149,7 @@ static u16 __phy_read(struct gem *gp, int phy_addr, int reg)
        cmd |= (MIF_FRAME_TAMSB);
        writel(cmd, gp->regs + MIF_FRAME);
 
-       while (limit--) {
+       while (--limit) {
                cmd = readl(gp->regs + MIF_FRAME);
                if (cmd & MIF_FRAME_TALSB)
                        break;
@@ -921,7 +922,7 @@ static int gem_poll(struct napi_struct *napi, int budget)
                gp->status = readl(gp->regs + GREG_STAT);
        } while (gp->status & GREG_STAT_NAPI);
 
-       __netif_rx_complete(dev, napi);
+       __napi_complete(napi);
        gem_enable_ints(gp);
 
        spin_unlock_irqrestore(&gp->lock, flags);
@@ -944,7 +945,7 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id)
 
        spin_lock_irqsave(&gp->lock, flags);
 
-       if (netif_rx_schedule_prep(dev, &gp->napi)) {
+       if (napi_schedule_prep(&gp->napi)) {
                u32 gem_status = readl(gp->regs + GREG_STAT);
 
                if (gem_status == 0) {
@@ -954,7 +955,7 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id)
                }
                gp->status = gem_status;
                gem_disable_ints(gp);
-               __netif_rx_schedule(dev, &gp->napi);
+               __napi_schedule(&gp->napi);
        }
 
        spin_unlock_irqrestore(&gp->lock, flags);
@@ -1015,7 +1016,8 @@ static __inline__ int gem_intme(int entry)
        return 0;
 }
 
-static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t gem_start_xmit(struct sk_buff *skb,
+                                 struct net_device *dev)
 {
        struct gem *gp = netdev_priv(dev);
        int entry;
@@ -1141,6 +1143,70 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
+static void gem_pcs_reset(struct gem *gp)
+{
+       int limit;
+       u32 val;
+
+       /* Reset PCS unit. */
+       val = readl(gp->regs + PCS_MIICTRL);
+       val |= PCS_MIICTRL_RST;
+       writel(val, gp->regs + PCS_MIICTRL);
+
+       limit = 32;
+       while (readl(gp->regs + PCS_MIICTRL) & PCS_MIICTRL_RST) {
+               udelay(100);
+               if (limit-- <= 0)
+                       break;
+       }
+       if (limit < 0)
+               printk(KERN_WARNING "%s: PCS reset bit would not clear.\n",
+                      gp->dev->name);
+}
+
+static void gem_pcs_reinit_adv(struct gem *gp)
+{
+       u32 val;
+
+       /* Make sure PCS is disabled while changing advertisement
+        * configuration.
+        */
+       val = readl(gp->regs + PCS_CFG);
+       val &= ~(PCS_CFG_ENABLE | PCS_CFG_TO);
+       writel(val, gp->regs + PCS_CFG);
+
+       /* Advertise all capabilities except assymetric
+        * pause.
+        */
+       val = readl(gp->regs + PCS_MIIADV);
+       val |= (PCS_MIIADV_FD | PCS_MIIADV_HD |
+               PCS_MIIADV_SP | PCS_MIIADV_AP);
+       writel(val, gp->regs + PCS_MIIADV);
+
+       /* Enable and restart auto-negotiation, disable wrapback/loopback,
+        * and re-enable PCS.
+        */
+       val = readl(gp->regs + PCS_MIICTRL);
+       val |= (PCS_MIICTRL_RAN | PCS_MIICTRL_ANE);
+       val &= ~PCS_MIICTRL_WB;
+       writel(val, gp->regs + PCS_MIICTRL);
+
+       val = readl(gp->regs + PCS_CFG);
+       val |= PCS_CFG_ENABLE;
+       writel(val, gp->regs + PCS_CFG);
+
+       /* Make sure serialink loopback is off.  The meaning
+        * of this bit is logically inverted based upon whether
+        * you are in Serialink or SERDES mode.
+        */
+       val = readl(gp->regs + PCS_SCTRL);
+       if (gp->phy_type == phy_serialink)
+               val &= ~PCS_SCTRL_LOOP;
+       else
+               val |= PCS_SCTRL_LOOP;
+       writel(val, gp->regs + PCS_SCTRL);
+}
+
 #define STOP_TRIES 32
 
 /* Must be invoked under gp->lock and gp->tx_lock. */
@@ -1165,8 +1231,11 @@ static void gem_reset(struct gem *gp)
                        break;
        } while (val & (GREG_SWRST_TXRST | GREG_SWRST_RXRST));
 
-       if (limit <= 0)
+       if (limit < 0)
                printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name);
+
+       if (gp->phy_type == phy_serialink || gp->phy_type == phy_serdes)
+               gem_pcs_reinit_adv(gp);
 }
 
 /* Must be invoked under gp->lock and gp->tx_lock. */
@@ -1323,7 +1392,7 @@ static int gem_set_link_modes(struct gem *gp)
                   gp->phy_type == phy_serdes) {
                u32 pcs_lpa = readl(gp->regs + PCS_MIILP);
 
-               if (pcs_lpa & PCS_MIIADV_FD)
+               if ((pcs_lpa & PCS_MIIADV_FD) || gp->phy_type == phy_serdes)
                        full_duplex = 1;
                speed = SPEED_1000;
        }
@@ -1487,6 +1556,9 @@ static void gem_link_timer(unsigned long data)
                        val = readl(gp->regs + PCS_MIISTAT);
 
                if ((val & PCS_MIISTAT_LS) != 0) {
+                       if (gp->lstate == link_up)
+                               goto restart;
+
                        gp->lstate = link_up;
                        netif_carrier_on(gp->dev);
                        (void)gem_set_link_modes(gp);
@@ -1707,61 +1779,8 @@ static void gem_init_phy(struct gem *gp)
                if (gp->phy_mii.def && gp->phy_mii.def->ops->init)
                        gp->phy_mii.def->ops->init(&gp->phy_mii);
        } else {
-               u32 val;
-               int limit;
-
-               /* Reset PCS unit. */
-               val = readl(gp->regs + PCS_MIICTRL);
-               val |= PCS_MIICTRL_RST;
-               writel(val, gp->regs + PCS_MIICTRL);
-
-               limit = 32;
-               while (readl(gp->regs + PCS_MIICTRL) & PCS_MIICTRL_RST) {
-                       udelay(100);
-                       if (limit-- <= 0)
-                               break;
-               }
-               if (limit <= 0)
-                       printk(KERN_WARNING "%s: PCS reset bit would not clear.\n",
-                              gp->dev->name);
-
-               /* Make sure PCS is disabled while changing advertisement
-                * configuration.
-                */
-               val = readl(gp->regs + PCS_CFG);
-               val &= ~(PCS_CFG_ENABLE | PCS_CFG_TO);
-               writel(val, gp->regs + PCS_CFG);
-
-               /* Advertise all capabilities except assymetric
-                * pause.
-                */
-               val = readl(gp->regs + PCS_MIIADV);
-               val |= (PCS_MIIADV_FD | PCS_MIIADV_HD |
-                       PCS_MIIADV_SP | PCS_MIIADV_AP);
-               writel(val, gp->regs + PCS_MIIADV);
-
-               /* Enable and restart auto-negotiation, disable wrapback/loopback,
-                * and re-enable PCS.
-                */
-               val = readl(gp->regs + PCS_MIICTRL);
-               val |= (PCS_MIICTRL_RAN | PCS_MIICTRL_ANE);
-               val &= ~PCS_MIICTRL_WB;
-               writel(val, gp->regs + PCS_MIICTRL);
-
-               val = readl(gp->regs + PCS_CFG);
-               val |= PCS_CFG_ENABLE;
-               writel(val, gp->regs + PCS_CFG);
-
-               /* Make sure serialink loopback is off.  The meaning
-                * of this bit is logically inverted based upon whether
-                * you are in Serialink or SERDES mode.
-                */
-               val = readl(gp->regs + PCS_SCTRL);
-               if (gp->phy_type == phy_serialink)
-                       val &= ~PCS_SCTRL_LOOP;
-               else
-                       val |= PCS_SCTRL_LOOP;
-               writel(val, gp->regs + PCS_SCTRL);
+               gem_pcs_reset(gp);
+               gem_pcs_reinit_adv(gp);
        }
 
        /* Default aneg parameters */
@@ -2204,6 +2223,8 @@ static int gem_do_start(struct net_device *dev)
 
        gp->running = 1;
 
+       napi_enable(&gp->napi);
+
        if (gp->lstate == link_up) {
                netif_carrier_on(gp->dev);
                gem_set_link_modes(gp);
@@ -2221,6 +2242,8 @@ static int gem_do_start(struct net_device *dev)
                spin_lock_irqsave(&gp->lock, flags);
                spin_lock(&gp->tx_lock);
 
+               napi_disable(&gp->napi);
+
                gp->running =  0;
                gem_reset(gp);
                gem_clean_rings(gp);
@@ -2321,8 +2344,6 @@ static int gem_open(struct net_device *dev)
        if (!gp->asleep)
                rc = gem_do_start(dev);
        gp->opened = (rc == 0);
-       if (gp->opened)
-               napi_enable(&gp->napi);
 
        mutex_unlock(&gp->pm_mutex);
 
@@ -2459,8 +2480,6 @@ static int gem_resume(struct pci_dev *pdev)
 
                /* Re-attach net device */
                netif_device_attach(dev);
-
-               napi_enable(&gp->napi);
        }
 
        spin_lock_irqsave(&gp->lock, flags);
@@ -2679,6 +2698,21 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                cmd->speed = 0;
                cmd->duplex = cmd->port = cmd->phy_address =
                        cmd->transceiver = cmd->autoneg = 0;
+
+               /* serdes means usually a Fibre connector, with most fixed */
+               if (gp->phy_type == phy_serdes) {
+                       cmd->port = PORT_FIBRE;
+                       cmd->supported = (SUPPORTED_1000baseT_Half |
+                               SUPPORTED_1000baseT_Full |
+                               SUPPORTED_FIBRE | SUPPORTED_Autoneg |
+                               SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+                       cmd->advertising = cmd->supported;
+                       cmd->transceiver = XCVR_INTERNAL;
+                       if (gp->lstate == link_up)
+                               cmd->speed = SPEED_1000;
+                       cmd->duplex = DUPLEX_FULL;
+                       cmd->autoneg = 1;
+               }
        }
        cmd->maxtxpkt = cmd->maxrxpkt = 0;
 
@@ -2819,9 +2853,7 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                break;
 
        case SIOCSMIIREG:               /* Write MII PHY register. */
-               if (!capable(CAP_NET_ADMIN))
-                       rc = -EPERM;
-               else if (!gp->running)
+               if (!gp->running)
                        rc = -EAGAIN;
                else {
                        __phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f,
@@ -2957,6 +2989,22 @@ static void gem_remove_one(struct pci_dev *pdev)
        }
 }
 
+static const struct net_device_ops gem_netdev_ops = {
+       .ndo_open               = gem_open,
+       .ndo_stop               = gem_close,
+       .ndo_start_xmit         = gem_start_xmit,
+       .ndo_get_stats          = gem_get_stats,
+       .ndo_set_multicast_list = gem_set_multicast,
+       .ndo_do_ioctl           = gem_ioctl,
+       .ndo_tx_timeout         = gem_tx_timeout,
+       .ndo_change_mtu         = gem_change_mtu,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = gem_set_mac_address,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = gem_poll_controller,
+#endif
+};
+
 static int __devinit gem_init_one(struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
 {
@@ -2994,10 +3042,10 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
         */
        if (pdev->vendor == PCI_VENDOR_ID_SUN &&
            pdev->device == PCI_DEVICE_ID_SUN_GEM &&
-           !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+           !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
                pci_using_dac = 1;
        } else {
-               err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+               err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
                if (err) {
                        printk(KERN_ERR PFX "No usable DMA configuration, "
                               "aborting.\n");
@@ -3110,23 +3158,12 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
        if (gem_get_device_address(gp))
                goto err_out_free_consistent;
 
-       dev->open = gem_open;
-       dev->stop = gem_close;
-       dev->hard_start_xmit = gem_start_xmit;
-       dev->get_stats = gem_get_stats;
-       dev->set_multicast_list = gem_set_multicast;
-       dev->do_ioctl = gem_ioctl;
+       dev->netdev_ops = &gem_netdev_ops;
        netif_napi_add(dev, &gp->napi, gem_poll, 64);
        dev->ethtool_ops = &gem_ethtool_ops;
-       dev->tx_timeout = gem_tx_timeout;
        dev->watchdog_timeo = 5 * HZ;
-       dev->change_mtu = gem_change_mtu;
        dev->irq = pdev->irq;
        dev->dma = 0;
-       dev->set_mac_address = gem_set_mac_address;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       dev->poll_controller = gem_poll_controller;
-#endif
 
        /* Set that now, in case PM kicks in now */
        pci_set_drvdata(pdev, dev);