diff options
author | Michael Buesch <mb@bu3sch.de> | 2006-06-17 09:19:05 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-07-05 13:42:57 -0400 |
commit | a1d79aaaa564abc19b7bf3a024bb371fa7648a15 (patch) | |
tree | 95824af615a33102a058ebc2500416b31aafc7ec /drivers/net/wireless | |
parent | e8d596972221aea55ae7f5c2bb7d5895039f664d (diff) |
[PATCH] bcm43xx: workaround init_board vs. IRQ race
Place the Init-vs-IRQ workaround before any card register
access, because we might not have the wireless core mapped
at all times in init. So this will result in a Machine Check
caused by a bus error.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_main.c | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index d8f5600578b4..673ab11d92ab 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c | |||
@@ -1885,6 +1885,15 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re | |||
1885 | 1885 | ||
1886 | spin_lock(&bcm->irq_lock); | 1886 | spin_lock(&bcm->irq_lock); |
1887 | 1887 | ||
1888 | /* Only accept IRQs, if we are initialized properly. | ||
1889 | * This avoids an RX race while initializing. | ||
1890 | * We should probably not enable IRQs before we are initialized | ||
1891 | * completely, but some careful work is needed to fix this. I think it | ||
1892 | * is best to stay with this cheap workaround for now... . | ||
1893 | */ | ||
1894 | if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) | ||
1895 | goto out; | ||
1896 | |||
1888 | reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); | 1897 | reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); |
1889 | if (reason == 0xffffffff) { | 1898 | if (reason == 0xffffffff) { |
1890 | /* irq not for us (shared irq) */ | 1899 | /* irq not for us (shared irq) */ |
@@ -1906,19 +1915,11 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re | |||
1906 | 1915 | ||
1907 | bcm43xx_interrupt_ack(bcm, reason); | 1916 | bcm43xx_interrupt_ack(bcm, reason); |
1908 | 1917 | ||
1909 | /* Only accept IRQs, if we are initialized properly. | 1918 | /* disable all IRQs. They are enabled again in the bottom half. */ |
1910 | * This avoids an RX race while initializing. | 1919 | bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); |
1911 | * We should probably not enable IRQs before we are initialized | 1920 | /* save the reason code and call our bottom half. */ |
1912 | * completely, but some careful work is needed to fix this. I think it | 1921 | bcm->irq_reason = reason; |
1913 | * is best to stay with this cheap workaround for now... . | 1922 | tasklet_schedule(&bcm->isr_tasklet); |
1914 | */ | ||
1915 | if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) { | ||
1916 | /* disable all IRQs. They are enabled again in the bottom half. */ | ||
1917 | bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); | ||
1918 | /* save the reason code and call our bottom half. */ | ||
1919 | bcm->irq_reason = reason; | ||
1920 | tasklet_schedule(&bcm->isr_tasklet); | ||
1921 | } | ||
1922 | 1923 | ||
1923 | out: | 1924 | out: |
1924 | mmiowb(); | 1925 | mmiowb(); |