X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fgianfar.c;fp=drivers%2Fnet%2Fgianfar.c;h=0e8e3fcde9ff9dc865a9c2170a5a4154aea52264;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=ebbbd6ca6204e28ba605cd980d8b6d5e1a408047;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index ebbbd6ca6..0e8e3fcde 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -64,6 +64,7 @@ * The driver then cleans up the buffer. */ +#include #include #include #include @@ -192,12 +193,8 @@ static int gfar_probe(struct platform_device *pdev) priv->interruptTransmit = platform_get_irq_byname(pdev, "tx"); priv->interruptReceive = platform_get_irq_byname(pdev, "rx"); priv->interruptError = platform_get_irq_byname(pdev, "error"); - if (priv->interruptTransmit < 0 || priv->interruptReceive < 0 || priv->interruptError < 0) - goto regs_fail; } else { priv->interruptTransmit = platform_get_irq(pdev, 0); - if (priv->interruptTransmit < 0) - goto regs_fail; } /* get a pointer to the register memory */ @@ -209,8 +206,7 @@ static int gfar_probe(struct platform_device *pdev) goto regs_fail; } - spin_lock_init(&priv->txlock); - spin_lock_init(&priv->rxlock); + spin_lock_init(&priv->lock); platform_set_drvdata(pdev, dev); @@ -515,13 +511,11 @@ void stop_gfar(struct net_device *dev) phy_stop(priv->phydev); /* Lock it down */ - spin_lock_irqsave(&priv->txlock, flags); - spin_lock(&priv->rxlock); + spin_lock_irqsave(&priv->lock, flags); gfar_halt(dev); - spin_unlock(&priv->rxlock); - spin_unlock_irqrestore(&priv->txlock, flags); + spin_unlock_irqrestore(&priv->lock, flags); /* Free the IRQs */ if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { @@ -607,15 +601,14 @@ void gfar_start(struct net_device *dev) tempval |= DMACTRL_INIT_SETTINGS; gfar_write(&priv->regs->dmactrl, tempval); + /* Clear THLT, so that the DMA starts polling now */ + gfar_write(®s->tstat, TSTAT_CLEAR_THALT); + /* Make sure we aren't stopped */ tempval = gfar_read(&priv->regs->dmactrl); tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); gfar_write(&priv->regs->dmactrl, tempval); - /* Clear THLT/RHLT, so that the DMA starts polling now */ - gfar_write(®s->tstat, TSTAT_CLEAR_THALT); - gfar_write(®s->rstat, RSTAT_CLEAR_RHALT); - /* Unmask the interrupts we look for */ gfar_write(®s->imask, IMASK_DEFAULT); } @@ -931,13 +924,12 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) struct txfcb *fcb = NULL; struct txbd8 *txbdp; u16 status; - unsigned long flags; /* Update transmit stats */ priv->stats.tx_bytes += skb->len; /* Lock priv now */ - spin_lock_irqsave(&priv->txlock, flags); + spin_lock_irq(&priv->lock); /* Point at the first free tx descriptor */ txbdp = priv->cur_tx; @@ -1008,7 +1000,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT); /* Unlock priv */ - spin_unlock_irqrestore(&priv->txlock, flags); + spin_unlock_irq(&priv->lock); return 0; } @@ -1053,7 +1045,7 @@ static void gfar_vlan_rx_register(struct net_device *dev, unsigned long flags; u32 tempval; - spin_lock_irqsave(&priv->rxlock, flags); + spin_lock_irqsave(&priv->lock, flags); priv->vlgrp = grp; @@ -1080,7 +1072,7 @@ static void gfar_vlan_rx_register(struct net_device *dev, gfar_write(&priv->regs->rctrl, tempval); } - spin_unlock_irqrestore(&priv->rxlock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } @@ -1089,12 +1081,12 @@ static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) struct gfar_private *priv = netdev_priv(dev); unsigned long flags; - spin_lock_irqsave(&priv->rxlock, flags); + spin_lock_irqsave(&priv->lock, flags); if (priv->vlgrp) priv->vlgrp->vlan_devices[vid] = NULL; - spin_unlock_irqrestore(&priv->rxlock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } @@ -1183,7 +1175,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs) gfar_write(&priv->regs->ievent, IEVENT_TX_MASK); /* Lock priv */ - spin_lock(&priv->txlock); + spin_lock(&priv->lock); bdp = priv->dirty_tx; while ((bdp->status & TXBD_READY) == 0) { /* If dirty_tx and cur_tx are the same, then either the */ @@ -1228,7 +1220,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs) else gfar_write(&priv->regs->txic, 0); - spin_unlock(&priv->txlock); + spin_unlock(&priv->lock); return IRQ_HANDLED; } @@ -1309,10 +1301,9 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; struct gfar_private *priv = netdev_priv(dev); + #ifdef CONFIG_GFAR_NAPI u32 tempval; -#else - unsigned long flags; #endif /* Clear IEVENT, so rx interrupt isn't called again @@ -1335,7 +1326,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) } #else - spin_lock_irqsave(&priv->rxlock, flags); + spin_lock(&priv->lock); gfar_clean_rx_ring(dev, priv->rx_ring_size); /* If we are coalescing interrupts, update the timer */ @@ -1346,7 +1337,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) else gfar_write(&priv->regs->rxic, 0); - spin_unlock_irqrestore(&priv->rxlock, flags); + spin_unlock(&priv->lock); #endif return IRQ_HANDLED; @@ -1495,6 +1486,13 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) /* Update the current rxbd pointer to be the next one */ priv->cur_rx = bdp; + /* If no packets have arrived since the + * last one we processed, clear the IEVENT RX and + * BSY bits so that another interrupt won't be + * generated when we set IMASK */ + if (bdp->status & RXBD_EMPTY) + gfar_write(&priv->regs->ievent, IEVENT_RX_MASK); + return howmany; } @@ -1514,7 +1512,7 @@ static int gfar_poll(struct net_device *dev, int *budget) rx_work_limit -= howmany; *budget -= howmany; - if (rx_work_limit > 0) { + if (rx_work_limit >= 0) { netif_rx_complete(dev); /* Clear the halt bit in RSTAT */ @@ -1531,8 +1529,7 @@ static int gfar_poll(struct net_device *dev, int *budget) gfar_write(&priv->regs->rxic, 0); } - /* Return 1 if there's more work to do */ - return (rx_work_limit > 0) ? 0 : 1; + return (rx_work_limit < 0) ? 1 : 0; } #endif @@ -1628,7 +1625,7 @@ static void adjust_link(struct net_device *dev) struct phy_device *phydev = priv->phydev; int new_state = 0; - spin_lock_irqsave(&priv->txlock, flags); + spin_lock_irqsave(&priv->lock, flags); if (phydev->link) { u32 tempval = gfar_read(®s->maccfg2); u32 ecntrl = gfar_read(®s->ecntrl); @@ -1693,7 +1690,7 @@ static void adjust_link(struct net_device *dev) if (new_state && netif_msg_link(priv)) phy_print_status(phydev); - spin_unlock_irqrestore(&priv->txlock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } /* Update the hash table based on the current list of multicast