Prev: [13/17] x86, Calgary: Limit the max PHB number to 256
Next: [05/17] cpmac: do not leak struct net_device on phy_connect errors
From: Greg KH on 30 Jul 2010 13:10 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Tim Gardner <tim.gardner(a)canonical.com> commit d6a574ff6bfb842bdb98065da053881ff527be46 upstream. Use an irq spinlock to hold off the IRQ handler until enough early card init is complete such that the handler can run without faulting. Signed-off-by: Tim Gardner <tim.gardner(a)canonical.com> Signed-off-by: John W. Linville <linville(a)tuxdriver.com> Signed-off-by: Greg Kroah-Hartman <gregkh(a)suse.de> --- drivers/net/wireless/hostap/hostap_cs.c | 10 ++++++++++ drivers/net/wireless/hostap/hostap_hw.c | 13 +++++++++++++ drivers/net/wireless/hostap/hostap_wlan.h | 2 +- 3 files changed, 24 insertions(+), 1 deletion(-) --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -557,6 +557,7 @@ static int prism2_config(struct pcmcia_d config_info_t conf; cistpl_cftable_entry_t dflt = { 0 }; struct hostap_cs_priv *hw_priv; + unsigned long flags; PDEBUG(DEBUG_FLOW, "prism2_config()\n"); @@ -688,6 +689,12 @@ static int prism2_config(struct pcmcia_d link->dev_node = &hw_priv->node; /* + * Make sure the IRQ handler cannot proceed until at least + * dev->base_addr is initialized. + */ + spin_lock_irqsave(&local->irq_init_lock, flags); + + /* * Allocate an interrupt line. Note that this does not assign a * handler to the interrupt, unless the 'Handler' member of the * irq structure is initialized. @@ -712,6 +719,8 @@ static int prism2_config(struct pcmcia_d dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; + spin_unlock_irqrestore(&local->irq_init_lock, flags); + /* Finally, report what we've done */ printk(KERN_INFO "%s: index 0x%02x: ", dev_info, link->conf.ConfigIndex); @@ -742,6 +751,7 @@ static int prism2_config(struct pcmcia_d return ret; cs_failed: + spin_unlock_irqrestore(&local->irq_init_lock, flags); cs_error(link, last_fn, last_ret); failed: --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -2631,6 +2631,18 @@ static irqreturn_t prism2_interrupt(int iface = netdev_priv(dev); local = iface->local; + /* Detect early interrupt before driver is fully configued */ + spin_lock(&local->irq_init_lock); + if (!dev->base_addr) { + if (net_ratelimit()) { + printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n", + dev->name); + } + spin_unlock(&local->irq_init_lock); + return IRQ_HANDLED; + } + spin_unlock(&local->irq_init_lock); + prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0); if (local->func->card_present && !local->func->card_present(local)) { @@ -3187,6 +3199,7 @@ prism2_init_local_data(struct prism2_hel spin_lock_init(&local->cmdlock); spin_lock_init(&local->baplock); spin_lock_init(&local->lock); + spin_lock_init(&local->irq_init_lock); mutex_init(&local->rid_bap_mtx); if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES) --- a/drivers/net/wireless/hostap/hostap_wlan.h +++ b/drivers/net/wireless/hostap/hostap_wlan.h @@ -653,7 +653,7 @@ struct local_info { rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock * when removing entries from the list. * TX and RX paths can use read lock. */ - spinlock_t cmdlock, baplock, lock; + spinlock_t cmdlock, baplock, lock, irq_init_lock; struct mutex rid_bap_mtx; u16 infofid; /* MAC buffer id for info frame */ /* txfid, intransmitfid, next_txtid, and next_alloc are protected by -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ |