Skip to content

Commit

Permalink
orinoco: cache downloadable firmware image in memory for use during r…
Browse files Browse the repository at this point in the history
…esume

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>
  • Loading branch information
Andrey Borzenkov authored and John W. Linville committed Oct 31, 2008
1 parent 0df6cbb commit 4fb3078
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 7 deletions.
28 changes: 21 additions & 7 deletions drivers/net/wireless/orinoco.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -3532,6 +3541,8 @@ struct net_device
netif_carrier_off(dev);
priv->last_linkstatus = 0xffff;

priv->cached_fw = NULL;

return dev;
}

Expand All @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/wireless/orinoco.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ struct orinoco_rx_data {
struct list_head list;
};

struct firmware;

struct orinoco_private {
void *card; /* Pointer to card dependent structure */
struct device *dev;
Expand Down Expand Up @@ -164,6 +166,9 @@ struct orinoco_private {
unsigned int wpa_enabled:1;
unsigned int tkip_cm_active:1;
unsigned int key_mgmt:3;

/* Cached in memory firmware to use in ->resume */
const struct firmware *cached_fw;
};

#ifdef ORINOCO_DEBUG
Expand Down

0 comments on commit 4fb3078

Please sign in to comment.