[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20100730175137.385602192@clark.site>
Date: Fri, 30 Jul 2010 10:50:59 -0700
From: Greg KH <gregkh@...e.de>
To: linux-kernel@...r.kernel.org, stable@...nel.org
Cc: stable-review@...nel.org, torvalds@...ux-foundation.org,
akpm@...ux-foundation.org, alan@...rguk.ukuu.org.uk,
Tim Gardner <tim.gardner@...onical.com>,
"John W. Linville" <linville@...driver.com>
Subject: [042/205] hostap: Protect against initialization interrupt
2.6.34-stable review patch. If anyone has any objections, please let us know.
------------------
From: Tim Gardner <tim.gardner@...onical.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@...onical.com>
Signed-off-by: John W. Linville <linville@...driver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@...e.de>
---
drivers/net/wireless/hostap/hostap_cs.c | 15 +++++++++++++--
drivers/net/wireless/hostap/hostap_hw.c | 13 +++++++++++++
drivers/net/wireless/hostap/hostap_wlan.h | 2 +-
3 files changed, 27 insertions(+), 3 deletions(-)
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -603,6 +603,7 @@ static int prism2_config(struct pcmcia_d
local_info_t *local;
int ret = 1;
struct hostap_cs_priv *hw_priv;
+ unsigned long flags;
PDEBUG(DEBUG_FLOW, "prism2_config()\n");
@@ -637,6 +638,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.
@@ -646,7 +653,7 @@ static int prism2_config(struct pcmcia_d
link->irq.Handler = prism2_interrupt;
ret = pcmcia_request_irq(link, &link->irq);
if (ret)
- goto failed;
+ goto failed_unlock;
}
/*
@@ -656,11 +663,13 @@ static int prism2_config(struct pcmcia_d
*/
ret = pcmcia_request_configuration(link, &link->conf);
if (ret)
- goto failed;
+ goto failed_unlock;
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);
@@ -689,6 +698,8 @@ static int prism2_config(struct pcmcia_d
}
return ret;
+ failed_unlock:
+ spin_unlock_irqrestore(&local->irq_init_lock, flags);
failed:
kfree(hw_priv);
prism2_release((u_long)link);
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -2630,6 +2630,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)) {
@@ -3147,6 +3159,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
@@ -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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists