Commit d6a574ff authored by Tim Gardner's avatar Tim Gardner Committed by John W. Linville

hostap: Protect against initialization interrupt

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>
Cc: stable@kernel.org
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a69b03e9
......@@ -594,6 +594,7 @@ static int prism2_config(struct pcmcia_device *link)
local_info_t *local;
int ret = 1;
struct hostap_cs_priv *hw_priv;
unsigned long flags;
PDEBUG(DEBUG_FLOW, "prism2_config()\n");
......@@ -625,9 +626,15 @@ static int prism2_config(struct pcmcia_device *link)
local->hw_priv = hw_priv;
hw_priv->link = link;
/*
* Make sure the IRQ handler cannot proceed until at least
* dev->base_addr is initialized.
*/
spin_lock_irqsave(&local->irq_init_lock, flags);
ret = pcmcia_request_irq(link, prism2_interrupt);
if (ret)
goto failed;
goto failed_unlock;
/*
* This actually configures the PCMCIA socket -- setting up
......@@ -636,11 +643,13 @@ static int prism2_config(struct pcmcia_device *link)
*/
ret = pcmcia_request_configuration(link, &link->conf);
if (ret)
goto failed;
goto failed_unlock;
dev->irq = link->irq;
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);
......@@ -667,6 +676,8 @@ static int prism2_config(struct pcmcia_device *link)
return ret;
failed_unlock:
spin_unlock_irqrestore(&local->irq_init_lock, flags);
failed:
kfree(hw_priv);
prism2_release((u_long)link);
......
......@@ -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