lkml.org 
[lkml]   [2008]   [Oct]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
SubjectRe: rc9 + orinoco WPA patchset: BUG: scheduling while atomic loading firmware with PCMCIA adapter
Date
On Thursday 09 October 2008, Dan Williams wrote:
>
> On Thu, 2008-10-09 at 19:59 +0400, Andrey Borzenkov wrote:
> > On Thursday 09 October 2008, Matthew Wilcox wrote:
> > >
> > > On Thu, Oct 09, 2008 at 05:22:55PM +0400, Andrey Borzenkov wrote:
> > > > After loading orinoco and "inserting" adapter I get either BUG with
> > > > endless loop (attached) or kernel panic on NULL pointer dereference
> > > > (was not able capture). Adapter works fine with wlags49 driver.
> > >
> > > It looks like you've fallen off the bottom of the kernel stack. Do you
> > > have 4k stacks enabled in your config?
> > >
> >
> > You are right. Using 8K stacks load and runs fine. Hmm ... not nice
> > from it :p
>
> == driver bug; the driver should not require large stacks and this
> should get fixed.
>

The attached patch fixes 4K stack for me. I have not tested spectrum case.

-andrey
Subject: [PATCH] orinoco: reduce stack usage in firmware download path
From: Andrey Borzenkov <arvidjaar@mail.ru>

orinoco_dl_firmware and symbol_dl_mage allocate large local
variables (1K); at least orinoco fails with panic or hung
kernel if 4K stacks is enabled.

Allocate large buffers dynamically at run time.

Signed-off-by: Andrey Borzenkov <arvidjaar@mail.ru>

---
drivers/net/wireless/orinoco.c | 50 ++++++++++++++++++++++++++--------------
1 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 9a2fcc0..2b87d0b 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -458,7 +458,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
int ap)
{
/* Plug Data Area (PDA) */
- __le16 pda[512] = { 0 };
+ __le16 *pda;

hermes_t *hw = &priv->hw;
const struct firmware *fw_entry;
@@ -467,7 +467,11 @@ orinoco_dl_firmware(struct orinoco_private *priv,
const unsigned char *end;
const char *firmware;
struct net_device *dev = priv->ndev;
- int err;
+ int err = 0;
+
+ pda = kzalloc(fw->pda_size, GFP_KERNEL);
+ if (!pda)
+ return -ENOMEM;

if (ap)
firmware = fw->ap_fw;
@@ -478,17 +482,17 @@ orinoco_dl_firmware(struct orinoco_private *priv,
dev->name, firmware);

/* Read current plug data */
- err = hermes_read_pda(hw, pda, fw->pda_addr,
- min_t(u16, fw->pda_size, sizeof(pda)), 0);
+ err = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 0);
printk(KERN_DEBUG "%s: Read PDA returned %d\n", dev->name, err);
if (err)
- return err;
+ goto free;

err = request_firmware(&fw_entry, firmware, priv->dev);
if (err) {
printk(KERN_ERR "%s: Cannot find firmware %s\n",
dev->name, firmware);
- return -ENOENT;
+ err = -ENOENT;
+ goto free;
}

hdr = (const struct orinoco_fw_header *) fw_entry->data;
@@ -532,6 +536,9 @@ orinoco_dl_firmware(struct orinoco_private *priv,

abort:
release_firmware(fw_entry);
+
+free:
+ kfree(pda);
return err;
}

@@ -549,12 +556,16 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
int secondary)
{
hermes_t *hw = &priv->hw;
- int ret;
+ int ret = 0;
const unsigned char *ptr;
const unsigned char *first_block;

/* Plug Data Area (PDA) */
- __le16 pda[256];
+ __le16 *pda;
+
+ pda = kzalloc(fw->pda_size, GFP_KERNEL);
+ if (!pda)
+ return -ENOMEM;

/* Binary block begins after the 0x1A marker */
ptr = image;
@@ -563,22 +574,22 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,

/* Read the PDA from EEPROM */
if (secondary) {
- ret = hermes_read_pda(hw, pda, fw->pda_addr, sizeof(pda), 1);
+ ret = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 1);
if (ret)
- return ret;
+ goto free;
}

/* Stop the firmware, so that it can be safely rewritten */
if (priv->stop_fw) {
ret = priv->stop_fw(priv, 1);
if (ret)
- return ret;
+ goto free;
}

/* Program the adapter with new firmware */
ret = hermes_program(hw, first_block, end);
if (ret)
- return ret;
+ goto free;

/* Write the PDA to the adapter */
if (secondary) {
@@ -586,28 +597,31 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
ptr = first_block + len;
ret = hermes_apply_pda(hw, ptr, pda);
if (ret)
- return ret;
+ goto free;
}

/* Run the firmware */
if (priv->stop_fw) {
ret = priv->stop_fw(priv, 0);
if (ret)
- return ret;
+ goto free;
}

/* Reset hermes chip and make sure it responds */
ret = hermes_init(hw);

/* hermes_reset() should return 0 with the secondary firmware */
- if (secondary && ret != 0)
- return -ENODEV;
+ if (secondary && ret != 0) {
+ ret = -ENODEV;
+ goto free;
+ }

/* And this should work with any firmware */
if (!hermes_present(hw))
- return -ENODEV;
+ ret = -ENODEV;

- return 0;
+free:
+ return ret;
}

[unhandled content-type:application/pgp-signature]
\
 
 \ /
  Last update: 2008-10-09 21:25    [from the cache]
©2003-2011 Jasper Spaans