diff options
author | Anton Vorontsov <avorontsov@ru.mvista.com> | 2008-05-16 15:04:51 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-05-22 06:19:27 -0400 |
commit | 7fa0cba330af3a24f43ac85e14b0b5fed557cdab (patch) | |
tree | 37fdfdaa8ef3ff09a2f56ab783c15ee31bba5185 /drivers | |
parent | 7f80202bb964dd9c5b408af8100c7f0fd39a15c7 (diff) |
uli526x: add support for netpoll
This patch adds netpoll support for the uli526x ethernet driver --
simply call the interrupt handler for polling.
To do this without disable_irq()/enable_irq() pair we should fully
protect the handler. Luckily, it's already using irqsave spinlock,
the only unprotected place is interrupts re-enabling write. It was
safe to re-enable interrupts without holding the spinlock, but with
netpoll possibility now it doesn't seem so.
Patch was tested using netconsole and KGDBoE.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/tulip/uli526x.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 2511ca7a12aa..e9e628621639 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c | |||
@@ -225,6 +225,9 @@ static void uli526x_set_filter_mode(struct net_device *); | |||
225 | static const struct ethtool_ops netdev_ethtool_ops; | 225 | static const struct ethtool_ops netdev_ethtool_ops; |
226 | static u16 read_srom_word(long, int); | 226 | static u16 read_srom_word(long, int); |
227 | static irqreturn_t uli526x_interrupt(int, void *); | 227 | static irqreturn_t uli526x_interrupt(int, void *); |
228 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
229 | static void uli526x_poll(struct net_device *dev); | ||
230 | #endif | ||
228 | static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long); | 231 | static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long); |
229 | static void allocate_rx_buffer(struct uli526x_board_info *); | 232 | static void allocate_rx_buffer(struct uli526x_board_info *); |
230 | static void update_cr6(u32, unsigned long); | 233 | static void update_cr6(u32, unsigned long); |
@@ -339,6 +342,9 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev, | |||
339 | dev->get_stats = &uli526x_get_stats; | 342 | dev->get_stats = &uli526x_get_stats; |
340 | dev->set_multicast_list = &uli526x_set_filter_mode; | 343 | dev->set_multicast_list = &uli526x_set_filter_mode; |
341 | dev->ethtool_ops = &netdev_ethtool_ops; | 344 | dev->ethtool_ops = &netdev_ethtool_ops; |
345 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
346 | dev->poll_controller = &uli526x_poll; | ||
347 | #endif | ||
342 | spin_lock_init(&db->lock); | 348 | spin_lock_init(&db->lock); |
343 | 349 | ||
344 | 350 | ||
@@ -681,8 +687,9 @@ static irqreturn_t uli526x_interrupt(int irq, void *dev_id) | |||
681 | db->cr5_data = inl(ioaddr + DCR5); | 687 | db->cr5_data = inl(ioaddr + DCR5); |
682 | outl(db->cr5_data, ioaddr + DCR5); | 688 | outl(db->cr5_data, ioaddr + DCR5); |
683 | if ( !(db->cr5_data & 0x180c1) ) { | 689 | if ( !(db->cr5_data & 0x180c1) ) { |
684 | spin_unlock_irqrestore(&db->lock, flags); | 690 | /* Restore CR7 to enable interrupt mask */ |
685 | outl(db->cr7_data, ioaddr + DCR7); | 691 | outl(db->cr7_data, ioaddr + DCR7); |
692 | spin_unlock_irqrestore(&db->lock, flags); | ||
686 | return IRQ_HANDLED; | 693 | return IRQ_HANDLED; |
687 | } | 694 | } |
688 | 695 | ||
@@ -715,6 +722,13 @@ static irqreturn_t uli526x_interrupt(int irq, void *dev_id) | |||
715 | return IRQ_HANDLED; | 722 | return IRQ_HANDLED; |
716 | } | 723 | } |
717 | 724 | ||
725 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
726 | static void uli526x_poll(struct net_device *dev) | ||
727 | { | ||
728 | /* ISR grabs the irqsave lock, so this should be safe */ | ||
729 | uli526x_interrupt(dev->irq, dev); | ||
730 | } | ||
731 | #endif | ||
718 | 732 | ||
719 | /* | 733 | /* |
720 | * Free TX resource after TX complete | 734 | * Free TX resource after TX complete |