Commit ecea2e46 authored by Eric Lemoine's avatar Eric Lemoine Committed by David S. Miller

[SUNGEM]: Add tx_lock

Using tx_lock in SunGEM makes the driver logic in conformance
with tg3 and e1000, easing maintainance.
Signed-off-by: default avatarEric Lemoine <eric.lemoine@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ba2f2520
......@@ -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 @@ static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep)
/* 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,7 +2183,9 @@ 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(&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 ||
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment