diff options
author | Francois Romieu <romieu@fr.zoreil.com> | 2006-09-08 14:15:38 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-09-11 09:05:37 -0400 |
commit | 0bb3cf726b37c13abce9f9134a68b94aa10e8803 (patch) | |
tree | 52a1fe8fdd08bdc088c1fb95957ecf5e698b8def /drivers | |
parent | 40c0d87948ab635e814f45664259d4cc193651a1 (diff) |
[PATCH] Defer tulip_select_media() to process context
Move tulip_select_media() processing to a workqueue, instead of
delaying in interrupt context, edited by Kyle McMartin to use kevent
thread, instead of creating its own workqueue.
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
Signed-off-by: Valerie Henson <val_henson@linux.intel.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/tulip/21142.c | 4 | ||||
-rw-r--r-- | drivers/net/tulip/timer.c | 14 | ||||
-rw-r--r-- | drivers/net/tulip/tulip.h | 19 | ||||
-rw-r--r-- | drivers/net/tulip/tulip_core.c | 64 |
4 files changed, 60 insertions, 41 deletions
diff --git a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c index 937025f8b5a1..fa3a2bb105ad 100644 --- a/drivers/net/tulip/21142.c +++ b/drivers/net/tulip/21142.c | |||
@@ -26,9 +26,9 @@ static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; | |||
26 | 26 | ||
27 | /* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list | 27 | /* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list |
28 | of available transceivers. */ | 28 | of available transceivers. */ |
29 | void t21142_timer(unsigned long data) | 29 | void t21142_media_task(void *data) |
30 | { | 30 | { |
31 | struct net_device *dev = (struct net_device *)data; | 31 | struct net_device *dev = data; |
32 | struct tulip_private *tp = netdev_priv(dev); | 32 | struct tulip_private *tp = netdev_priv(dev); |
33 | void __iomem *ioaddr = tp->base_addr; | 33 | void __iomem *ioaddr = tp->base_addr; |
34 | int csr12 = ioread32(ioaddr + CSR12); | 34 | int csr12 = ioread32(ioaddr + CSR12); |
diff --git a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c index f75bc5ecd73c..066e5d6bcbd8 100644 --- a/drivers/net/tulip/timer.c +++ b/drivers/net/tulip/timer.c | |||
@@ -18,13 +18,14 @@ | |||
18 | #include "tulip.h" | 18 | #include "tulip.h" |
19 | 19 | ||
20 | 20 | ||
21 | void tulip_timer(unsigned long data) | 21 | void tulip_media_task(void *data) |
22 | { | 22 | { |
23 | struct net_device *dev = (struct net_device *)data; | 23 | struct net_device *dev = data; |
24 | struct tulip_private *tp = netdev_priv(dev); | 24 | struct tulip_private *tp = netdev_priv(dev); |
25 | void __iomem *ioaddr = tp->base_addr; | 25 | void __iomem *ioaddr = tp->base_addr; |
26 | u32 csr12 = ioread32(ioaddr + CSR12); | 26 | u32 csr12 = ioread32(ioaddr + CSR12); |
27 | int next_tick = 2*HZ; | 27 | int next_tick = 2*HZ; |
28 | unsigned long flags; | ||
28 | 29 | ||
29 | if (tulip_debug > 2) { | 30 | if (tulip_debug > 2) { |
30 | printk(KERN_DEBUG "%s: Media selection tick, %s, status %8.8x mode" | 31 | printk(KERN_DEBUG "%s: Media selection tick, %s, status %8.8x mode" |
@@ -126,6 +127,15 @@ void tulip_timer(unsigned long data) | |||
126 | } | 127 | } |
127 | break; | 128 | break; |
128 | } | 129 | } |
130 | |||
131 | |||
132 | spin_lock_irqsave(&tp->lock, flags); | ||
133 | if (tp->timeout_recovery) { | ||
134 | tulip_tx_timeout_complete(tp, ioaddr); | ||
135 | tp->timeout_recovery = 0; | ||
136 | } | ||
137 | spin_unlock_irqrestore(&tp->lock, flags); | ||
138 | |||
129 | /* mod_timer synchronizes us with potential add_timer calls | 139 | /* mod_timer synchronizes us with potential add_timer calls |
130 | * from interrupts. | 140 | * from interrupts. |
131 | */ | 141 | */ |
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h index 3bcfbf3d23ed..64d443a80d8c 100644 --- a/drivers/net/tulip/tulip.h +++ b/drivers/net/tulip/tulip.h | |||
@@ -44,7 +44,8 @@ struct tulip_chip_table { | |||
44 | int io_size; | 44 | int io_size; |
45 | int valid_intrs; /* CSR7 interrupt enable settings */ | 45 | int valid_intrs; /* CSR7 interrupt enable settings */ |
46 | int flags; | 46 | int flags; |
47 | void (*media_timer) (unsigned long data); | 47 | void (*media_timer) (unsigned long); |
48 | void (*media_task) (void *); | ||
48 | }; | 49 | }; |
49 | 50 | ||
50 | 51 | ||
@@ -366,6 +367,7 @@ struct tulip_private { | |||
366 | unsigned int medialock:1; /* Don't sense media type. */ | 367 | unsigned int medialock:1; /* Don't sense media type. */ |
367 | unsigned int mediasense:1; /* Media sensing in progress. */ | 368 | unsigned int mediasense:1; /* Media sensing in progress. */ |
368 | unsigned int nway:1, nwayset:1; /* 21143 internal NWay. */ | 369 | unsigned int nway:1, nwayset:1; /* 21143 internal NWay. */ |
370 | unsigned int timeout_recovery:1; | ||
369 | unsigned int csr0; /* CSR0 setting. */ | 371 | unsigned int csr0; /* CSR0 setting. */ |
370 | unsigned int csr6; /* Current CSR6 control settings. */ | 372 | unsigned int csr6; /* Current CSR6 control settings. */ |
371 | unsigned char eeprom[EEPROM_SIZE]; /* Serial EEPROM contents. */ | 373 | unsigned char eeprom[EEPROM_SIZE]; /* Serial EEPROM contents. */ |
@@ -384,6 +386,7 @@ struct tulip_private { | |||
384 | void __iomem *base_addr; | 386 | void __iomem *base_addr; |
385 | int csr12_shadow; | 387 | int csr12_shadow; |
386 | int pad0; /* Used for 8-byte alignment */ | 388 | int pad0; /* Used for 8-byte alignment */ |
389 | struct work_struct media_work; | ||
387 | }; | 390 | }; |
388 | 391 | ||
389 | 392 | ||
@@ -398,7 +401,7 @@ struct eeprom_fixup { | |||
398 | 401 | ||
399 | /* 21142.c */ | 402 | /* 21142.c */ |
400 | extern u16 t21142_csr14[]; | 403 | extern u16 t21142_csr14[]; |
401 | void t21142_timer(unsigned long data); | 404 | void t21142_media_task(void *data); |
402 | void t21142_start_nway(struct net_device *dev); | 405 | void t21142_start_nway(struct net_device *dev); |
403 | void t21142_lnk_change(struct net_device *dev, int csr5); | 406 | void t21142_lnk_change(struct net_device *dev, int csr5); |
404 | 407 | ||
@@ -436,7 +439,7 @@ void pnic_lnk_change(struct net_device *dev, int csr5); | |||
436 | void pnic_timer(unsigned long data); | 439 | void pnic_timer(unsigned long data); |
437 | 440 | ||
438 | /* timer.c */ | 441 | /* timer.c */ |
439 | void tulip_timer(unsigned long data); | 442 | void tulip_media_task(void *data); |
440 | void mxic_timer(unsigned long data); | 443 | void mxic_timer(unsigned long data); |
441 | void comet_timer(unsigned long data); | 444 | void comet_timer(unsigned long data); |
442 | 445 | ||
@@ -485,4 +488,14 @@ static inline void tulip_restart_rxtx(struct tulip_private *tp) | |||
485 | tulip_start_rxtx(tp); | 488 | tulip_start_rxtx(tp); |
486 | } | 489 | } |
487 | 490 | ||
491 | static inline void tulip_tx_timeout_complete(struct tulip_private *tp, void __iomem *ioaddr) | ||
492 | { | ||
493 | /* Stop and restart the chip's Tx processes. */ | ||
494 | tulip_restart_rxtx(tp); | ||
495 | /* Trigger an immediate transmit demand. */ | ||
496 | iowrite32(0, ioaddr + CSR1); | ||
497 | |||
498 | tp->stats.tx_errors++; | ||
499 | } | ||
500 | |||
488 | #endif /* __NET_TULIP_H__ */ | 501 | #endif /* __NET_TULIP_H__ */ |
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 6a7ca8695ff2..7e1ca3cae1ee 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c | |||
@@ -130,7 +130,14 @@ int tulip_debug = TULIP_DEBUG; | |||
130 | int tulip_debug = 1; | 130 | int tulip_debug = 1; |
131 | #endif | 131 | #endif |
132 | 132 | ||
133 | static void tulip_timer(unsigned long data) | ||
134 | { | ||
135 | struct net_device *dev = (struct net_device *)data; | ||
136 | struct tulip_private *tp = netdev_priv(dev); | ||
133 | 137 | ||
138 | if (netif_running(dev)) | ||
139 | schedule_work(&tp->media_work); | ||
140 | } | ||
134 | 141 | ||
135 | /* | 142 | /* |
136 | * This table use during operation for capabilities and media timer. | 143 | * This table use during operation for capabilities and media timer. |
@@ -144,59 +151,60 @@ struct tulip_chip_table tulip_tbl[] = { | |||
144 | 151 | ||
145 | /* DC21140 */ | 152 | /* DC21140 */ |
146 | { "Digital DS21140 Tulip", 128, 0x0001ebef, | 153 | { "Digital DS21140 Tulip", 128, 0x0001ebef, |
147 | HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_PCI_MWI, tulip_timer }, | 154 | HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_PCI_MWI, tulip_timer, |
155 | tulip_media_task }, | ||
148 | 156 | ||
149 | /* DC21142, DC21143 */ | 157 | /* DC21142, DC21143 */ |
150 | { "Digital DS21142/43 Tulip", 128, 0x0801fbff, | 158 | { "Digital DS21142/43 Tulip", 128, 0x0801fbff, |
151 | HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY | 159 | HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY |
152 | | HAS_INTR_MITIGATION | HAS_PCI_MWI, t21142_timer }, | 160 | | HAS_INTR_MITIGATION | HAS_PCI_MWI, tulip_timer, t21142_media_task }, |
153 | 161 | ||
154 | /* LC82C168 */ | 162 | /* LC82C168 */ |
155 | { "Lite-On 82c168 PNIC", 256, 0x0001fbef, | 163 | { "Lite-On 82c168 PNIC", 256, 0x0001fbef, |
156 | HAS_MII | HAS_PNICNWAY, pnic_timer }, | 164 | HAS_MII | HAS_PNICNWAY, pnic_timer, }, |
157 | 165 | ||
158 | /* MX98713 */ | 166 | /* MX98713 */ |
159 | { "Macronix 98713 PMAC", 128, 0x0001ebef, | 167 | { "Macronix 98713 PMAC", 128, 0x0001ebef, |
160 | HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer }, | 168 | HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer, }, |
161 | 169 | ||
162 | /* MX98715 */ | 170 | /* MX98715 */ |
163 | { "Macronix 98715 PMAC", 256, 0x0001ebef, | 171 | { "Macronix 98715 PMAC", 256, 0x0001ebef, |
164 | HAS_MEDIA_TABLE, mxic_timer }, | 172 | HAS_MEDIA_TABLE, mxic_timer, }, |
165 | 173 | ||
166 | /* MX98725 */ | 174 | /* MX98725 */ |
167 | { "Macronix 98725 PMAC", 256, 0x0001ebef, | 175 | { "Macronix 98725 PMAC", 256, 0x0001ebef, |
168 | HAS_MEDIA_TABLE, mxic_timer }, | 176 | HAS_MEDIA_TABLE, mxic_timer, }, |
169 | 177 | ||
170 | /* AX88140 */ | 178 | /* AX88140 */ |
171 | { "ASIX AX88140", 128, 0x0001fbff, | 179 | { "ASIX AX88140", 128, 0x0001fbff, |
172 | HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY | 180 | HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY |
173 | | IS_ASIX, tulip_timer }, | 181 | | IS_ASIX, tulip_timer, tulip_media_task }, |
174 | 182 | ||
175 | /* PNIC2 */ | 183 | /* PNIC2 */ |
176 | { "Lite-On PNIC-II", 256, 0x0801fbff, | 184 | { "Lite-On PNIC-II", 256, 0x0801fbff, |
177 | HAS_MII | HAS_NWAY | HAS_8023X | HAS_PCI_MWI, pnic2_timer }, | 185 | HAS_MII | HAS_NWAY | HAS_8023X | HAS_PCI_MWI, pnic2_timer, }, |
178 | 186 | ||
179 | /* COMET */ | 187 | /* COMET */ |
180 | { "ADMtek Comet", 256, 0x0001abef, | 188 | { "ADMtek Comet", 256, 0x0001abef, |
181 | HAS_MII | MC_HASH_ONLY | COMET_MAC_ADDR, comet_timer }, | 189 | HAS_MII | MC_HASH_ONLY | COMET_MAC_ADDR, comet_timer, }, |
182 | 190 | ||
183 | /* COMPEX9881 */ | 191 | /* COMPEX9881 */ |
184 | { "Compex 9881 PMAC", 128, 0x0001ebef, | 192 | { "Compex 9881 PMAC", 128, 0x0001ebef, |
185 | HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer }, | 193 | HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer, }, |
186 | 194 | ||
187 | /* I21145 */ | 195 | /* I21145 */ |
188 | { "Intel DS21145 Tulip", 128, 0x0801fbff, | 196 | { "Intel DS21145 Tulip", 128, 0x0801fbff, |
189 | HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | 197 | HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI |
190 | | HAS_NWAY | HAS_PCI_MWI, t21142_timer }, | 198 | | HAS_NWAY | HAS_PCI_MWI, tulip_timer, tulip_media_task }, |
191 | 199 | ||
192 | /* DM910X */ | 200 | /* DM910X */ |
193 | { "Davicom DM9102/DM9102A", 128, 0x0001ebef, | 201 | { "Davicom DM9102/DM9102A", 128, 0x0001ebef, |
194 | HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI, | 202 | HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI, |
195 | tulip_timer }, | 203 | tulip_timer, tulip_media_task }, |
196 | 204 | ||
197 | /* RS7112 */ | 205 | /* RS7112 */ |
198 | { "Conexant LANfinity", 256, 0x0001ebef, | 206 | { "Conexant LANfinity", 256, 0x0001ebef, |
199 | HAS_MII | HAS_ACPI, tulip_timer }, | 207 | HAS_MII | HAS_ACPI, tulip_timer, tulip_media_task }, |
200 | 208 | ||
201 | }; | 209 | }; |
202 | 210 | ||
@@ -524,20 +532,9 @@ static void tulip_tx_timeout(struct net_device *dev) | |||
524 | "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n", | 532 | "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n", |
525 | dev->name, ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12), | 533 | dev->name, ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12), |
526 | ioread32(ioaddr + CSR13), ioread32(ioaddr + CSR14), ioread32(ioaddr + CSR15)); | 534 | ioread32(ioaddr + CSR13), ioread32(ioaddr + CSR14), ioread32(ioaddr + CSR15)); |
527 | if ( ! tp->medialock && tp->mtable) { | 535 | tp->timeout_recovery = 1; |
528 | do | 536 | schedule_work(&tp->media_work); |
529 | --tp->cur_index; | 537 | goto out_unlock; |
530 | while (tp->cur_index >= 0 | ||
531 | && (tulip_media_cap[tp->mtable->mleaf[tp->cur_index].media] | ||
532 | & MediaIsFD)); | ||
533 | if (--tp->cur_index < 0) { | ||
534 | /* We start again, but should instead look for default. */ | ||
535 | tp->cur_index = tp->mtable->leafcount - 1; | ||
536 | } | ||
537 | tulip_select_media(dev, 0); | ||
538 | printk(KERN_WARNING "%s: transmit timed out, switching to %s " | ||
539 | "media.\n", dev->name, medianame[dev->if_port]); | ||
540 | } | ||
541 | } else if (tp->chip_id == PNIC2) { | 538 | } else if (tp->chip_id == PNIC2) { |
542 | printk(KERN_WARNING "%s: PNIC2 transmit timed out, status %8.8x, " | 539 | printk(KERN_WARNING "%s: PNIC2 transmit timed out, status %8.8x, " |
543 | "CSR6/7 %8.8x / %8.8x CSR12 %8.8x, resetting...\n", | 540 | "CSR6/7 %8.8x / %8.8x CSR12 %8.8x, resetting...\n", |
@@ -577,14 +574,9 @@ static void tulip_tx_timeout(struct net_device *dev) | |||
577 | } | 574 | } |
578 | #endif | 575 | #endif |
579 | 576 | ||
580 | /* Stop and restart the chip's Tx processes . */ | 577 | tulip_tx_timeout_complete(tp, ioaddr); |
581 | |||
582 | tulip_restart_rxtx(tp); | ||
583 | /* Trigger an immediate transmit demand. */ | ||
584 | iowrite32(0, ioaddr + CSR1); | ||
585 | |||
586 | tp->stats.tx_errors++; | ||
587 | 578 | ||
579 | out_unlock: | ||
588 | spin_unlock_irqrestore (&tp->lock, flags); | 580 | spin_unlock_irqrestore (&tp->lock, flags); |
589 | dev->trans_start = jiffies; | 581 | dev->trans_start = jiffies; |
590 | netif_wake_queue (dev); | 582 | netif_wake_queue (dev); |
@@ -734,6 +726,8 @@ static void tulip_down (struct net_device *dev) | |||
734 | void __iomem *ioaddr = tp->base_addr; | 726 | void __iomem *ioaddr = tp->base_addr; |
735 | unsigned long flags; | 727 | unsigned long flags; |
736 | 728 | ||
729 | flush_scheduled_work(); | ||
730 | |||
737 | del_timer_sync (&tp->timer); | 731 | del_timer_sync (&tp->timer); |
738 | #ifdef CONFIG_TULIP_NAPI | 732 | #ifdef CONFIG_TULIP_NAPI |
739 | del_timer_sync (&tp->oom_timer); | 733 | del_timer_sync (&tp->oom_timer); |
@@ -1400,6 +1394,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, | |||
1400 | tp->timer.data = (unsigned long)dev; | 1394 | tp->timer.data = (unsigned long)dev; |
1401 | tp->timer.function = tulip_tbl[tp->chip_id].media_timer; | 1395 | tp->timer.function = tulip_tbl[tp->chip_id].media_timer; |
1402 | 1396 | ||
1397 | INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task, dev); | ||
1398 | |||
1403 | dev->base_addr = (unsigned long)ioaddr; | 1399 | dev->base_addr = (unsigned long)ioaddr; |
1404 | 1400 | ||
1405 | #ifdef CONFIG_TULIP_MWI | 1401 | #ifdef CONFIG_TULIP_MWI |