* The driver then cleans up the buffer.
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
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 */
goto regs_fail;
}
- spin_lock_init(&priv->txlock);
- spin_lock_init(&priv->rxlock);
+ spin_lock_init(&priv->lock);
platform_set_drvdata(pdev, 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) {
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);
}
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;
gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);
/* Unlock priv */
- spin_unlock_irqrestore(&priv->txlock, flags);
+ spin_unlock_irq(&priv->lock);
return 0;
}
unsigned long flags;
u32 tempval;
- spin_lock_irqsave(&priv->rxlock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
priv->vlgrp = grp;
gfar_write(&priv->regs->rctrl, tempval);
}
- spin_unlock_irqrestore(&priv->rxlock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
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);
}
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 */
else
gfar_write(&priv->regs->txic, 0);
- spin_unlock(&priv->txlock);
+ spin_unlock(&priv->lock);
return IRQ_HANDLED;
}
{
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
}
#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 */
else
gfar_write(&priv->regs->rxic, 0);
- spin_unlock_irqrestore(&priv->rxlock, flags);
+ spin_unlock(&priv->lock);
#endif
return IRQ_HANDLED;
/* 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;
}
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 */
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
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);
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