Commit 4fb30784 authored by Andrey Borzenkov's avatar Andrey Borzenkov Committed by John W. Linville

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: default avatarAndrey Borzenkov <arvidjaar@mail.ru>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 0df6cbb7
...@@ -487,12 +487,17 @@ orinoco_dl_firmware(struct orinoco_private *priv, ...@@ -487,12 +487,17 @@ orinoco_dl_firmware(struct orinoco_private *priv,
if (err) if (err)
goto free; goto free;
err = request_firmware(&fw_entry, firmware, priv->dev); if (priv->cached_fw)
if (err) { fw_entry = priv->cached_fw;
printk(KERN_ERR "%s: Cannot find firmware %s\n", else {
dev->name, firmware); err = request_firmware(&fw_entry, firmware, priv->dev);
err = -ENOENT; if (err) {
goto free; 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; hdr = (const struct orinoco_fw_header *) fw_entry->data;
...@@ -535,7 +540,11 @@ orinoco_dl_firmware(struct orinoco_private *priv, ...@@ -535,7 +540,11 @@ orinoco_dl_firmware(struct orinoco_private *priv,
dev->name, hermes_present(hw)); dev->name, hermes_present(hw));
abort: 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: free:
kfree(pda); kfree(pda);
...@@ -3532,6 +3541,8 @@ struct net_device ...@@ -3532,6 +3541,8 @@ struct net_device
netif_carrier_off(dev); netif_carrier_off(dev);
priv->last_linkstatus = 0xffff; priv->last_linkstatus = 0xffff;
priv->cached_fw = NULL;
return dev; return dev;
} }
...@@ -3543,6 +3554,9 @@ void free_orinocodev(struct net_device *dev) ...@@ -3543,6 +3554,9 @@ void free_orinocodev(struct net_device *dev)
* when we call tasklet_kill it will run one final time, * when we call tasklet_kill it will run one final time,
* emptying the list */ * emptying the list */
tasklet_kill(&priv->rx_tasklet); tasklet_kill(&priv->rx_tasklet);
if (priv->cached_fw)
release_firmware(priv->cached_fw);
priv->cached_fw = NULL;
priv->wpa_ie_len = 0; priv->wpa_ie_len = 0;
kfree(priv->wpa_ie); kfree(priv->wpa_ie);
orinoco_mic_free(priv); orinoco_mic_free(priv);
......
...@@ -66,6 +66,8 @@ struct orinoco_rx_data { ...@@ -66,6 +66,8 @@ struct orinoco_rx_data {
struct list_head list; struct list_head list;
}; };
struct firmware;
struct orinoco_private { struct orinoco_private {
void *card; /* Pointer to card dependent structure */ void *card; /* Pointer to card dependent structure */
struct device *dev; struct device *dev;
...@@ -164,6 +166,9 @@ struct orinoco_private { ...@@ -164,6 +166,9 @@ struct orinoco_private {
unsigned int wpa_enabled:1; unsigned int wpa_enabled:1;
unsigned int tkip_cm_active:1; unsigned int tkip_cm_active:1;
unsigned int key_mgmt:3; unsigned int key_mgmt:3;
/* Cached in memory firmware to use in ->resume */
const struct firmware *cached_fw;
}; };
#ifdef ORINOCO_DEBUG #ifdef ORINOCO_DEBUG
......
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