]> git.hungrycats.org Git - linux/commitdiff
[SUNGEM]: Add tx_lock
authorEric Lemoine <eric.lemoine@gmail.com>
Wed, 15 Sep 2004 01:16:44 +0000 (18:16 -0700)
committerDavid S. Miller <davem@nuts.davemloft.net>
Wed, 15 Sep 2004 01:16:44 +0000 (18:16 -0700)
Using tx_lock in SunGEM makes the driver logic in conformance
with tg3 and e1000, easing maintainance.

Signed-off-by: Eric Lemoine <eric.lemoine@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/sungem.c
drivers/net/sungem.h

index 1d63097d57856622902192af802f3dd472478c69..b40f15bc2c5d01296db1bf9ea841ff1d7eb3085b 100644 (file)
@@ -832,7 +832,9 @@ static int gem_poll(struct net_device *dev, int *budget)
                }
 
                /* Run TX completion thread */
+               spin_lock(&gp->tx_lock);
                gem_tx(dev, gp, gp->status);
+               spin_unlock(&gp->tx_lock);
 
                spin_unlock_irqrestore(&gp->lock, flags);
 
@@ -917,10 +919,12 @@ static void gem_tx_timeout(struct net_device *dev)
               readl(gp->regs + MAC_RXCFG));
 
        spin_lock_irq(&gp->lock);
+       spin_lock(&gp->tx_lock);
 
        gp->reset_task_pending = 2;
        schedule_work(&gp->reset_task);
 
+       spin_unlock(&gp->tx_lock);
        spin_unlock_irq(&gp->lock);
 }
 
@@ -951,12 +955,12 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        (csum_stuff_off << 21));
        }
 
-       spin_lock_irq(&gp->lock);
+       spin_lock_irq(&gp->tx_lock);
 
        /* This is a hard error, log it. */
        if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) {
                netif_stop_queue(dev);
-               spin_unlock_irq(&gp->lock);
+               spin_unlock_irq(&gp->tx_lock);
                printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
                       dev->name);
                return 1;
@@ -1043,7 +1047,7 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
                       dev->name, entry, skb->len);
        mb();
        writel(gp->tx_new, gp->regs + TXDMA_KICK);
-       spin_unlock_irq(&gp->lock);
+       spin_unlock_irq(&gp->tx_lock);
 
        dev->trans_start = jiffies;
 
@@ -1074,9 +1078,11 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu)
        }
 
        spin_lock_irq(&gp->lock);
+       spin_lock(&gp->tx_lock);
        dev->mtu = new_mtu;
        gp->reset_task_pending = 1;
        schedule_work(&gp->reset_task);
+       spin_unlock(&gp->tx_lock);
        spin_unlock_irq(&gp->lock);
 
        flush_scheduled_work();
@@ -1086,7 +1092,7 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu)
 
 #define STOP_TRIES 32
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_stop(struct gem *gp)
 {
        int limit;
@@ -1112,7 +1118,7 @@ static void gem_stop(struct gem *gp)
                printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name);
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_start_dma(struct gem *gp)
 {
        unsigned long val;
@@ -1137,7 +1143,7 @@ static void gem_start_dma(struct gem *gp)
 }
 
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 // XXX dbl check what that function should do when called on PCS PHY
 static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep)
 {
@@ -1224,7 +1230,7 @@ non_mii:
 /* A link-up condition has occurred, initialize and enable the
  * rest of the chip.
  *
- * Must be invoked under gp->lock.
+ * Must be invoked under gp->lock and gp->tx_lock.
  */
 static int gem_set_link_modes(struct gem *gp)
 {
@@ -1331,7 +1337,7 @@ static int gem_set_link_modes(struct gem *gp)
        return 0;
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static int gem_mdio_link_not_up(struct gem *gp)
 {
        switch (gp->lstate) {
@@ -1389,6 +1395,7 @@ static void gem_reset_task(void *data)
 
        netif_poll_disable(gp->dev);
        spin_lock_irq(&gp->lock);
+       spin_lock(&gp->tx_lock);
 
        if (gp->hw_running && gp->opened) {
                netif_stop_queue(gp->dev);
@@ -1404,6 +1411,7 @@ static void gem_reset_task(void *data)
        }
        gp->reset_task_pending = 0;
 
+       spin_unlock(&gp->tx_lock);
        spin_unlock_irq(&gp->lock);
        netif_poll_enable(gp->dev);
 }
@@ -1417,6 +1425,7 @@ static void gem_link_timer(unsigned long data)
                return;
 
        spin_lock_irq(&gp->lock);
+       spin_lock(&gp->tx_lock);
 
        /* If the link of task is still pending, we just
         * reschedule the link timer
@@ -1486,10 +1495,11 @@ static void gem_link_timer(unsigned long data)
 restart:
        mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
 out_unlock:
+       spin_unlock(&gp->tx_lock);
        spin_unlock_irq(&gp->lock);
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_clean_rings(struct gem *gp)
 {
        struct gem_init_block *gb = gp->init_block;
@@ -1540,7 +1550,7 @@ static void gem_clean_rings(struct gem *gp)
        }
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_rings(struct gem *gp)
 {
        struct gem_init_block *gb = gp->init_block;
@@ -1590,7 +1600,7 @@ static void gem_init_rings(struct gem *gp)
        wmb();
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_phy(struct gem *gp)
 {
        u32 mifcfg;
@@ -1728,7 +1738,7 @@ static void gem_init_phy(struct gem *gp)
        }
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_dma(struct gem *gp)
 {
        u64 desc_dma = (u64) gp->gblock_dvma;
@@ -1766,7 +1776,7 @@ static void gem_init_dma(struct gem *gp)
                       gp->regs + RXDMA_BLANK);
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static u32
 gem_setup_multicast(struct gem *gp)
 {
@@ -1809,7 +1819,7 @@ gem_setup_multicast(struct gem *gp)
        return rxcfg;
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_mac(struct gem *gp)
 {
        unsigned char *e = &gp->dev->dev_addr[0];
@@ -1887,7 +1897,7 @@ static void gem_init_mac(struct gem *gp)
        writel(0xffffffff, gp->regs + MAC_MCMASK);
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_pause_thresholds(struct gem *gp)
 {
                u32 cfg;
@@ -2023,7 +2033,7 @@ static int gem_check_invariants(struct gem *gp)
        return 0;
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_hw(struct gem *gp, int restart_link)
 {
        /* On Apple's gmac, I initialize the PHY only after
@@ -2121,9 +2131,11 @@ static void gem_stop_phy(struct gem *gp)
 
        if (!gp->wake_on_lan) {
                spin_lock_irqsave(&gp->lock, flags);
+               spin_lock(&gp->tx_lock);
                gem_stop(gp);
                writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST);
                writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);
+               spin_unlock(&gp->tx_lock);
                spin_unlock_irqrestore(&gp->lock, flags);
        }
 
@@ -2171,8 +2183,10 @@ static void gem_shutdown(struct gem *gp)
                unsigned long flags;
 
                spin_lock_irqsave(&gp->lock, flags);
+               spin_lock(&gp->tx_lock);
                gem_stop(gp);
-               spin_unlock_irqrestore(&gp->lock, flags);       
+               spin_unlock(&gp->tx_lock);
+               spin_unlock_irqrestore(&gp->lock, flags);
        }
 }
 
@@ -2232,7 +2246,9 @@ static int gem_open(struct net_device *dev)
 
                /* Reset the chip */
                spin_lock_irq(&gp->lock);
+               spin_lock(&gp->tx_lock);
                gem_stop(gp);
+               spin_unlock(&gp->tx_lock);
                spin_unlock_irq(&gp->lock);
 
                gp->hw_running = 1;
@@ -2246,6 +2262,7 @@ static int gem_open(struct net_device *dev)
                printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name);
 
                spin_lock_irq(&gp->lock);
+               spin_lock(&gp->tx_lock);
 #ifdef CONFIG_PPC_PMAC
                if (!hw_was_up && gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
                        gem_apple_powerdown(gp);
@@ -2254,12 +2271,14 @@ static int gem_open(struct net_device *dev)
                gp->pm_timer.expires = jiffies + 10*HZ;
                add_timer(&gp->pm_timer);
                up(&gp->pm_sem);
+               spin_unlock(&gp->tx_lock);
                spin_unlock_irq(&gp->lock);
 
                return -EAGAIN;
        }
 
                spin_lock_irq(&gp->lock);
+       spin_lock(&gp->tx_lock);
 
        /* Allocate & setup ring buffers */
        gem_init_rings(gp);
@@ -2269,6 +2288,7 @@ static int gem_open(struct net_device *dev)
 
        gp->opened = 1;
 
+       spin_unlock(&gp->tx_lock);
        spin_unlock_irq(&gp->lock);
 
        up(&gp->pm_sem);
@@ -2289,6 +2309,7 @@ static int gem_close(struct net_device *dev)
 
        /* Stop traffic, mark us closed */
        spin_lock_irq(&gp->lock);
+       spin_lock(&gp->tx_lock);
 
        gp->opened = 0; 
 
@@ -2303,6 +2324,7 @@ static int gem_close(struct net_device *dev)
        /* Bye, the pm timer will finish the job */
        free_irq(gp->pdev->irq, (void *) dev);
 
+       spin_unlock(&gp->tx_lock);
        spin_unlock_irq(&gp->lock);
 
        /* Fire the PM timer that will shut us down in about 10 seconds */
@@ -2333,6 +2355,7 @@ static int gem_suspend(struct pci_dev *pdev, u32 state)
        /* If the driver is opened, we stop the DMA */
        if (gp->opened) {
                spin_lock_irq(&gp->lock);
+               spin_lock(&gp->tx_lock);
 
                /* Stop traffic, mark us closed */
                netif_device_detach(dev);
@@ -2343,6 +2366,7 @@ static int gem_suspend(struct pci_dev *pdev, u32 state)
                /* Get rid of ring buffers */
                gem_clean_rings(gp);
 
+               spin_unlock(&gp->tx_lock);
                spin_unlock_irq(&gp->lock);
 
                if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
@@ -2376,12 +2400,14 @@ static int gem_resume(struct pci_dev *pdev)
                }
 #endif /* CONFIG_PPC_PMAC */
                spin_lock_irq(&gp->lock);
+               spin_lock(&gp->tx_lock);
 
                gem_stop(gp);
                gp->hw_running = 1;
                gem_init_rings(gp);
                gem_init_hw(gp, 1);
 
+               spin_unlock(&gp->tx_lock);
                spin_unlock_irq(&gp->lock);
 
                netif_device_attach(dev);
@@ -2402,6 +2428,7 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
        struct net_device_stats *stats = &gp->net_stats;
 
        spin_lock_irq(&gp->lock);
+       spin_lock(&gp->tx_lock);
 
        if (gp->hw_running) {
                stats->rx_crc_errors += readl(gp->regs + MAC_FCSERR);
@@ -2421,6 +2448,7 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
                writel(0, gp->regs + MAC_LCOLL);
        }
 
+       spin_unlock(&gp->tx_lock);
        spin_unlock_irq(&gp->lock);
 
        return &gp->net_stats;
@@ -2436,6 +2464,7 @@ static void gem_set_multicast(struct net_device *dev)
                return;
                
        spin_lock_irq(&gp->lock);
+       spin_lock(&gp->tx_lock);
 
        netif_stop_queue(dev);
 
@@ -2460,6 +2489,7 @@ static void gem_set_multicast(struct net_device *dev)
 
        netif_wake_queue(dev);
 
+       spin_unlock(&gp->tx_lock);
        spin_unlock_irq(&gp->lock);
 }
 
@@ -2491,6 +2521,7 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 
                /* Return current PHY settings */
                spin_lock_irq(&gp->lock);
+               spin_lock(&gp->tx_lock);
                cmd->autoneg = gp->want_autoneg;
                cmd->speed = gp->phy_mii.speed;
                cmd->duplex = gp->phy_mii.duplex;                       
@@ -2502,6 +2533,7 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                 */
                if (cmd->advertising == 0)
                        cmd->advertising = cmd->supported;
+               spin_unlock(&gp->tx_lock);
                spin_unlock_irq(&gp->lock);
        } else { // XXX PCS ?
                cmd->supported =
@@ -2541,7 +2573,9 @@ static int gem_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
              
        /* Apply settings and restart link process. */
        spin_lock_irq(&gp->lock);
+       spin_lock(&gp->tx_lock);
        gem_begin_auto_negotiation(gp, cmd);
+       spin_unlock(&gp->tx_lock);
        spin_unlock_irq(&gp->lock);
 
        return 0;
@@ -2556,7 +2590,9 @@ static int gem_nway_reset(struct net_device *dev)
 
        /* Restart link process. */
        spin_lock_irq(&gp->lock);
+       spin_lock(&gp->tx_lock);
        gem_begin_auto_negotiation(gp, NULL);
+       spin_unlock(&gp->tx_lock);
        spin_unlock_irq(&gp->lock);
 
        return 0;
@@ -2808,6 +2844,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
        gp->msg_enable = DEFAULT_MSG;
 
        spin_lock_init(&gp->lock);
+       spin_lock_init(&gp->tx_lock);
        init_MUTEX(&gp->pm_sem);
 
        init_timer(&gp->link_timer);
@@ -2843,7 +2880,9 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
                gem_apple_powerup(gp);
 #endif
        spin_lock_irq(&gp->lock);
+       spin_lock(&gp->tx_lock);
        gem_stop(gp);
+       spin_unlock(&gp->tx_lock);
        spin_unlock_irq(&gp->lock);
 
        /* Fill up the mii_phy structure (even if we won't use it) */
@@ -2906,9 +2945,11 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
 
        /* Detect & init PHY, start autoneg */
        spin_lock_irq(&gp->lock);
+       spin_lock(&gp->tx_lock);
        gp->hw_running = 1;
        gem_init_phy(gp);
        gem_begin_auto_negotiation(gp, NULL);
+       spin_unlock(&gp->tx_lock);
        spin_unlock_irq(&gp->lock);
 
        if (gp->phy_type == phy_mii_mdio0 ||
index 8bbc104d848f0a1126341439badc29c6b7eb4f98..00343226fb71e9a004189fdaeb6df5f1273006cc 100644 (file)
@@ -953,6 +953,7 @@ enum link_state {
 
 struct gem {
        spinlock_t lock;
+       spinlock_t tx_lock;
        void __iomem *regs;
        int rx_new, rx_old;
        int tx_new, tx_old;