Commit 121ba374 authored by Tim Gardner's avatar Tim Gardner Committed by Greg Kroah-Hartman

hostap: Protect against initialization interrupt

commit d6a574ff 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: default avatarTim Gardner <tim.gardner@canonical.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 8a16f471
......@@ -626,6 +626,7 @@ static int prism2_config(struct pcmcia_device *link)
int ret = 1;
int last_fn, last_ret;
struct hostap_cs_priv *hw_priv;
unsigned long flags;
PDEBUG(DEBUG_FLOW, "prism2_config()\n");
......@@ -660,6 +661,12 @@ static int prism2_config(struct pcmcia_device *link)
strcpy(hw_priv->node.dev_name, dev->name);
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
......@@ -686,6 +693,8 @@ static int prism2_config(struct pcmcia_device *link)
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);
......@@ -715,6 +724,7 @@ static int prism2_config(struct pcmcia_device *link)
return ret;
cs_failed:
spin_unlock_irqrestore(&local->irq_init_lock, flags);
cs_error(link, last_fn, last_ret);
failed:
......
......@@ -2621,6 +2621,18 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
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)) {
......@@ -3138,6 +3150,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
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)
......
......@@ -654,7 +654,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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment