diff options
Diffstat (limited to 'drivers/net/smc91x.c')
| -rw-r--r-- | drivers/net/smc91x.c | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 1c70e999cc50..7567f510eff5 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c | |||
| @@ -196,21 +196,23 @@ static void PRINT_PKT(u_char *buf, int length) | |||
| 196 | /* this enables an interrupt in the interrupt mask register */ | 196 | /* this enables an interrupt in the interrupt mask register */ |
| 197 | #define SMC_ENABLE_INT(lp, x) do { \ | 197 | #define SMC_ENABLE_INT(lp, x) do { \ |
| 198 | unsigned char mask; \ | 198 | unsigned char mask; \ |
| 199 | spin_lock_irq(&lp->lock); \ | 199 | unsigned long smc_enable_flags; \ |
| 200 | spin_lock_irqsave(&lp->lock, smc_enable_flags); \ | ||
| 200 | mask = SMC_GET_INT_MASK(lp); \ | 201 | mask = SMC_GET_INT_MASK(lp); \ |
| 201 | mask |= (x); \ | 202 | mask |= (x); \ |
| 202 | SMC_SET_INT_MASK(lp, mask); \ | 203 | SMC_SET_INT_MASK(lp, mask); \ |
| 203 | spin_unlock_irq(&lp->lock); \ | 204 | spin_unlock_irqrestore(&lp->lock, smc_enable_flags); \ |
| 204 | } while (0) | 205 | } while (0) |
| 205 | 206 | ||
| 206 | /* this disables an interrupt from the interrupt mask register */ | 207 | /* this disables an interrupt from the interrupt mask register */ |
| 207 | #define SMC_DISABLE_INT(lp, x) do { \ | 208 | #define SMC_DISABLE_INT(lp, x) do { \ |
| 208 | unsigned char mask; \ | 209 | unsigned char mask; \ |
| 209 | spin_lock_irq(&lp->lock); \ | 210 | unsigned long smc_disable_flags; \ |
| 211 | spin_lock_irqsave(&lp->lock, smc_disable_flags); \ | ||
| 210 | mask = SMC_GET_INT_MASK(lp); \ | 212 | mask = SMC_GET_INT_MASK(lp); \ |
| 211 | mask &= ~(x); \ | 213 | mask &= ~(x); \ |
| 212 | SMC_SET_INT_MASK(lp, mask); \ | 214 | SMC_SET_INT_MASK(lp, mask); \ |
| 213 | spin_unlock_irq(&lp->lock); \ | 215 | spin_unlock_irqrestore(&lp->lock, smc_disable_flags); \ |
| 214 | } while (0) | 216 | } while (0) |
| 215 | 217 | ||
| 216 | /* | 218 | /* |
| @@ -520,21 +522,21 @@ static inline void smc_rcv(struct net_device *dev) | |||
| 520 | * any other concurrent access and C would always interrupt B. But life | 522 | * any other concurrent access and C would always interrupt B. But life |
| 521 | * isn't that easy in a SMP world... | 523 | * isn't that easy in a SMP world... |
| 522 | */ | 524 | */ |
| 523 | #define smc_special_trylock(lock) \ | 525 | #define smc_special_trylock(lock, flags) \ |
| 524 | ({ \ | 526 | ({ \ |
| 525 | int __ret; \ | 527 | int __ret; \ |
| 526 | local_irq_disable(); \ | 528 | local_irq_save(flags); \ |
| 527 | __ret = spin_trylock(lock); \ | 529 | __ret = spin_trylock(lock); \ |
| 528 | if (!__ret) \ | 530 | if (!__ret) \ |
| 529 | local_irq_enable(); \ | 531 | local_irq_restore(flags); \ |
| 530 | __ret; \ | 532 | __ret; \ |
| 531 | }) | 533 | }) |
| 532 | #define smc_special_lock(lock) spin_lock_irq(lock) | 534 | #define smc_special_lock(lock, flags) spin_lock_irqsave(lock, flags) |
| 533 | #define smc_special_unlock(lock) spin_unlock_irq(lock) | 535 | #define smc_special_unlock(lock, flags) spin_unlock_irqrestore(lock, flags) |
| 534 | #else | 536 | #else |
| 535 | #define smc_special_trylock(lock) (1) | 537 | #define smc_special_trylock(lock, flags) (1) |
| 536 | #define smc_special_lock(lock) do { } while (0) | 538 | #define smc_special_lock(lock, flags) do { } while (0) |
| 537 | #define smc_special_unlock(lock) do { } while (0) | 539 | #define smc_special_unlock(lock, flags) do { } while (0) |
| 538 | #endif | 540 | #endif |
| 539 | 541 | ||
| 540 | /* | 542 | /* |
| @@ -548,10 +550,11 @@ static void smc_hardware_send_pkt(unsigned long data) | |||
| 548 | struct sk_buff *skb; | 550 | struct sk_buff *skb; |
| 549 | unsigned int packet_no, len; | 551 | unsigned int packet_no, len; |
| 550 | unsigned char *buf; | 552 | unsigned char *buf; |
| 553 | unsigned long flags; | ||
| 551 | 554 | ||
| 552 | DBG(3, "%s: %s\n", dev->name, __func__); | 555 | DBG(3, "%s: %s\n", dev->name, __func__); |
| 553 | 556 | ||
| 554 | if (!smc_special_trylock(&lp->lock)) { | 557 | if (!smc_special_trylock(&lp->lock, flags)) { |
| 555 | netif_stop_queue(dev); | 558 | netif_stop_queue(dev); |
| 556 | tasklet_schedule(&lp->tx_task); | 559 | tasklet_schedule(&lp->tx_task); |
| 557 | return; | 560 | return; |
| @@ -559,7 +562,7 @@ static void smc_hardware_send_pkt(unsigned long data) | |||
| 559 | 562 | ||
| 560 | skb = lp->pending_tx_skb; | 563 | skb = lp->pending_tx_skb; |
| 561 | if (unlikely(!skb)) { | 564 | if (unlikely(!skb)) { |
| 562 | smc_special_unlock(&lp->lock); | 565 | smc_special_unlock(&lp->lock, flags); |
| 563 | return; | 566 | return; |
| 564 | } | 567 | } |
| 565 | lp->pending_tx_skb = NULL; | 568 | lp->pending_tx_skb = NULL; |
| @@ -569,7 +572,7 @@ static void smc_hardware_send_pkt(unsigned long data) | |||
| 569 | printk("%s: Memory allocation failed.\n", dev->name); | 572 | printk("%s: Memory allocation failed.\n", dev->name); |
| 570 | dev->stats.tx_errors++; | 573 | dev->stats.tx_errors++; |
| 571 | dev->stats.tx_fifo_errors++; | 574 | dev->stats.tx_fifo_errors++; |
| 572 | smc_special_unlock(&lp->lock); | 575 | smc_special_unlock(&lp->lock, flags); |
| 573 | goto done; | 576 | goto done; |
| 574 | } | 577 | } |
| 575 | 578 | ||
| @@ -608,7 +611,7 @@ static void smc_hardware_send_pkt(unsigned long data) | |||
| 608 | 611 | ||
| 609 | /* queue the packet for TX */ | 612 | /* queue the packet for TX */ |
| 610 | SMC_SET_MMU_CMD(lp, MC_ENQUEUE); | 613 | SMC_SET_MMU_CMD(lp, MC_ENQUEUE); |
| 611 | smc_special_unlock(&lp->lock); | 614 | smc_special_unlock(&lp->lock, flags); |
| 612 | 615 | ||
| 613 | dev->trans_start = jiffies; | 616 | dev->trans_start = jiffies; |
| 614 | dev->stats.tx_packets++; | 617 | dev->stats.tx_packets++; |
| @@ -633,6 +636,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 633 | struct smc_local *lp = netdev_priv(dev); | 636 | struct smc_local *lp = netdev_priv(dev); |
| 634 | void __iomem *ioaddr = lp->base; | 637 | void __iomem *ioaddr = lp->base; |
| 635 | unsigned int numPages, poll_count, status; | 638 | unsigned int numPages, poll_count, status; |
| 639 | unsigned long flags; | ||
| 636 | 640 | ||
| 637 | DBG(3, "%s: %s\n", dev->name, __func__); | 641 | DBG(3, "%s: %s\n", dev->name, __func__); |
| 638 | 642 | ||
| @@ -658,7 +662,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 658 | return 0; | 662 | return 0; |
| 659 | } | 663 | } |
| 660 | 664 | ||
| 661 | smc_special_lock(&lp->lock); | 665 | smc_special_lock(&lp->lock, flags); |
| 662 | 666 | ||
| 663 | /* now, try to allocate the memory */ | 667 | /* now, try to allocate the memory */ |
| 664 | SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages); | 668 | SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages); |
| @@ -676,7 +680,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 676 | } | 680 | } |
| 677 | } while (--poll_count); | 681 | } while (--poll_count); |
| 678 | 682 | ||
| 679 | smc_special_unlock(&lp->lock); | 683 | smc_special_unlock(&lp->lock, flags); |
| 680 | 684 | ||
| 681 | lp->pending_tx_skb = skb; | 685 | lp->pending_tx_skb = skb; |
| 682 | if (!poll_count) { | 686 | if (!poll_count) { |
