|
@@ -803,7 +803,7 @@ static int ns83820_setup_rx(struct net_device *ndev)
|
|
|
|
|
|
writel(dev->IMR_cache, dev->base + IMR);
|
|
writel(dev->IMR_cache, dev->base + IMR);
|
|
writel(1, dev->base + IER);
|
|
writel(1, dev->base + IER);
|
|
- spin_unlock_irq(&dev->misc_lock);
|
|
|
|
|
|
+ spin_unlock(&dev->misc_lock);
|
|
|
|
|
|
kick_rx(ndev);
|
|
kick_rx(ndev);
|
|
|
|
|
|
@@ -1012,8 +1012,6 @@ static void do_tx_done(struct net_device *ndev)
|
|
struct ns83820 *dev = PRIV(ndev);
|
|
struct ns83820 *dev = PRIV(ndev);
|
|
u32 cmdsts, tx_done_idx, *desc;
|
|
u32 cmdsts, tx_done_idx, *desc;
|
|
|
|
|
|
- spin_lock_irq(&dev->tx_lock);
|
|
|
|
-
|
|
|
|
dprintk("do_tx_done(%p)\n", ndev);
|
|
dprintk("do_tx_done(%p)\n", ndev);
|
|
tx_done_idx = dev->tx_done_idx;
|
|
tx_done_idx = dev->tx_done_idx;
|
|
desc = dev->tx_descs + (tx_done_idx * DESC_SIZE);
|
|
desc = dev->tx_descs + (tx_done_idx * DESC_SIZE);
|
|
@@ -1069,7 +1067,6 @@ static void do_tx_done(struct net_device *ndev)
|
|
netif_start_queue(ndev);
|
|
netif_start_queue(ndev);
|
|
netif_wake_queue(ndev);
|
|
netif_wake_queue(ndev);
|
|
}
|
|
}
|
|
- spin_unlock_irq(&dev->tx_lock);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static void ns83820_cleanup_tx(struct ns83820 *dev)
|
|
static void ns83820_cleanup_tx(struct ns83820 *dev)
|
|
@@ -1281,11 +1278,13 @@ static struct ethtool_ops ops = {
|
|
.get_link = ns83820_get_link
|
|
.get_link = ns83820_get_link
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+/* this function is called in irq context from the ISR */
|
|
static void ns83820_mib_isr(struct ns83820 *dev)
|
|
static void ns83820_mib_isr(struct ns83820 *dev)
|
|
{
|
|
{
|
|
- spin_lock(&dev->misc_lock);
|
|
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ spin_lock_irqsave(&dev->misc_lock, flags);
|
|
ns83820_update_stats(dev);
|
|
ns83820_update_stats(dev);
|
|
- spin_unlock(&dev->misc_lock);
|
|
|
|
|
|
+ spin_unlock_irqrestore(&dev->misc_lock, flags);
|
|
}
|
|
}
|
|
|
|
|
|
static void ns83820_do_isr(struct net_device *ndev, u32 isr);
|
|
static void ns83820_do_isr(struct net_device *ndev, u32 isr);
|
|
@@ -1307,6 +1306,8 @@ static irqreturn_t ns83820_irq(int foo, void *data, struct pt_regs *regs)
|
|
static void ns83820_do_isr(struct net_device *ndev, u32 isr)
|
|
static void ns83820_do_isr(struct net_device *ndev, u32 isr)
|
|
{
|
|
{
|
|
struct ns83820 *dev = PRIV(ndev);
|
|
struct ns83820 *dev = PRIV(ndev);
|
|
|
|
+ unsigned long flags;
|
|
|
|
+
|
|
#ifdef DEBUG
|
|
#ifdef DEBUG
|
|
if (isr & ~(ISR_PHY | ISR_RXDESC | ISR_RXEARLY | ISR_RXOK | ISR_RXERR | ISR_TXIDLE | ISR_TXOK | ISR_TXDESC))
|
|
if (isr & ~(ISR_PHY | ISR_RXDESC | ISR_RXEARLY | ISR_RXOK | ISR_RXERR | ISR_TXIDLE | ISR_TXOK | ISR_TXDESC))
|
|
Dprintk("odd isr? 0x%08x\n", isr);
|
|
Dprintk("odd isr? 0x%08x\n", isr);
|
|
@@ -1321,10 +1322,10 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr)
|
|
if ((ISR_RXDESC | ISR_RXOK) & isr) {
|
|
if ((ISR_RXDESC | ISR_RXOK) & isr) {
|
|
prefetch(dev->rx_info.next_rx_desc);
|
|
prefetch(dev->rx_info.next_rx_desc);
|
|
|
|
|
|
- spin_lock_irq(&dev->misc_lock);
|
|
|
|
|
|
+ spin_lock_irqsave(&dev->misc_lock, flags);
|
|
dev->IMR_cache &= ~(ISR_RXDESC | ISR_RXOK);
|
|
dev->IMR_cache &= ~(ISR_RXDESC | ISR_RXOK);
|
|
writel(dev->IMR_cache, dev->base + IMR);
|
|
writel(dev->IMR_cache, dev->base + IMR);
|
|
- spin_unlock_irq(&dev->misc_lock);
|
|
|
|
|
|
+ spin_unlock_irqrestore(&dev->misc_lock, flags);
|
|
|
|
|
|
tasklet_schedule(&dev->rx_tasklet);
|
|
tasklet_schedule(&dev->rx_tasklet);
|
|
//rx_irq(ndev);
|
|
//rx_irq(ndev);
|
|
@@ -1370,16 +1371,18 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr)
|
|
* work has accumulated
|
|
* work has accumulated
|
|
*/
|
|
*/
|
|
if ((ISR_TXDESC | ISR_TXIDLE | ISR_TXOK | ISR_TXERR) & isr) {
|
|
if ((ISR_TXDESC | ISR_TXIDLE | ISR_TXOK | ISR_TXERR) & isr) {
|
|
|
|
+ spin_lock_irqsave(&dev->tx_lock, flags);
|
|
do_tx_done(ndev);
|
|
do_tx_done(ndev);
|
|
|
|
+ spin_unlock_irqrestore(&dev->tx_lock, flags);
|
|
|
|
|
|
/* Disable TxOk if there are no outstanding tx packets.
|
|
/* Disable TxOk if there are no outstanding tx packets.
|
|
*/
|
|
*/
|
|
if ((dev->tx_done_idx == dev->tx_free_idx) &&
|
|
if ((dev->tx_done_idx == dev->tx_free_idx) &&
|
|
(dev->IMR_cache & ISR_TXOK)) {
|
|
(dev->IMR_cache & ISR_TXOK)) {
|
|
- spin_lock_irq(&dev->misc_lock);
|
|
|
|
|
|
+ spin_lock_irqsave(&dev->misc_lock, flags);
|
|
dev->IMR_cache &= ~ISR_TXOK;
|
|
dev->IMR_cache &= ~ISR_TXOK;
|
|
writel(dev->IMR_cache, dev->base + IMR);
|
|
writel(dev->IMR_cache, dev->base + IMR);
|
|
- spin_unlock_irq(&dev->misc_lock);
|
|
|
|
|
|
+ spin_unlock_irqrestore(&dev->misc_lock, flags);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1390,10 +1393,10 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr)
|
|
* nature are expected, we must enable TxOk.
|
|
* nature are expected, we must enable TxOk.
|
|
*/
|
|
*/
|
|
if ((ISR_TXIDLE & isr) && (dev->tx_done_idx != dev->tx_free_idx)) {
|
|
if ((ISR_TXIDLE & isr) && (dev->tx_done_idx != dev->tx_free_idx)) {
|
|
- spin_lock_irq(&dev->misc_lock);
|
|
|
|
|
|
+ spin_lock_irqsave(&dev->misc_lock, flags);
|
|
dev->IMR_cache |= ISR_TXOK;
|
|
dev->IMR_cache |= ISR_TXOK;
|
|
writel(dev->IMR_cache, dev->base + IMR);
|
|
writel(dev->IMR_cache, dev->base + IMR);
|
|
- spin_unlock_irq(&dev->misc_lock);
|
|
|
|
|
|
+ spin_unlock_irqrestore(&dev->misc_lock, flags);
|
|
}
|
|
}
|
|
|
|
|
|
/* MIB interrupt: one of the statistics counters is about to overflow */
|
|
/* MIB interrupt: one of the statistics counters is about to overflow */
|
|
@@ -1455,7 +1458,7 @@ static void ns83820_tx_timeout(struct net_device *ndev)
|
|
u32 tx_done_idx, *desc;
|
|
u32 tx_done_idx, *desc;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
|
|
- local_irq_save(flags);
|
|
|
|
|
|
+ spin_lock_irqsave(&dev->tx_lock, flags);
|
|
|
|
|
|
tx_done_idx = dev->tx_done_idx;
|
|
tx_done_idx = dev->tx_done_idx;
|
|
desc = dev->tx_descs + (tx_done_idx * DESC_SIZE);
|
|
desc = dev->tx_descs + (tx_done_idx * DESC_SIZE);
|
|
@@ -1482,7 +1485,7 @@ static void ns83820_tx_timeout(struct net_device *ndev)
|
|
ndev->name,
|
|
ndev->name,
|
|
tx_done_idx, dev->tx_free_idx, le32_to_cpu(desc[DESC_CMDSTS]));
|
|
tx_done_idx, dev->tx_free_idx, le32_to_cpu(desc[DESC_CMDSTS]));
|
|
|
|
|
|
- local_irq_restore(flags);
|
|
|
|
|
|
+ spin_unlock_irqrestore(&dev->tx_lock, flags);
|
|
}
|
|
}
|
|
|
|
|
|
static void ns83820_tx_watch(unsigned long data)
|
|
static void ns83820_tx_watch(unsigned long data)
|