diff options
author | Andrey Borzenkov <arvidjaar@mail.ru> | 2008-10-19 12:06:11 +0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-10-31 19:02:34 -0400 |
commit | 4fb30784c720b863203957f76e3fde0d53932746 (patch) | |
tree | 9fe63bca9701dcc2a5ee6e6d492e022cbadfb6e5 /drivers/net/wireless/orinoco.c | |
parent | 0df6cbb7d8a0a8fea69138e9e463671a8ad99f16 (diff) |
orinoco: cache downloadable firmware image in memory for use during resume
If card is using downloadable firmware (like Agere 9.x), firmware has
to be reloaded during resume. It is not possible to use request_firmware
for that, because tasks are still frozen, so request_firmware will
just timeout and fail. So cache firmware image in memory for later
reuse in ->resume method.
Signed-off-by: Andrey Borzenkov <arvidjaar@mail.ru>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/orinoco.c')
-rw-r--r-- | drivers/net/wireless/orinoco.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 7bd1559e871..5a39166e2a0 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -487,12 +487,17 @@ orinoco_dl_firmware(struct orinoco_private *priv, if (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); - err = -ENOENT; - goto free; + if (priv->cached_fw) + fw_entry = priv->cached_fw; + else { + err = request_firmware(&fw_entry, firmware, priv->dev); + if (err) { + printk(KERN_ERR "%s: Cannot find firmware %s\n", + dev->name, firmware); + err = -ENOENT; + goto free; + } + priv->cached_fw = fw_entry; } hdr = (const struct orinoco_fw_header *) fw_entry->data; @@ -535,7 +540,11 @@ orinoco_dl_firmware(struct orinoco_private *priv, dev->name, hermes_present(hw)); abort: - release_firmware(fw_entry); + /* In case of error, assume firmware was bogus and release it */ + if (err) { + priv->cached_fw = NULL; + release_firmware(fw_entry); + } free: kfree(pda); @@ -3532,6 +3541,8 @@ struct net_device netif_carrier_off(dev); priv->last_linkstatus = 0xffff; + priv->cached_fw = NULL; + return dev; } @@ -3543,6 +3554,9 @@ void free_orinocodev(struct net_device *dev) * when we call tasklet_kill it will run one final time, * emptying the list */ tasklet_kill(&priv->rx_tasklet); + if (priv->cached_fw) + release_firmware(priv->cached_fw); + priv->cached_fw = NULL; priv->wpa_ie_len = 0; kfree(priv->wpa_ie); orinoco_mic_free(priv); |