Commit 39d1ffee authored by David Kilroy's avatar David Kilroy Committed by John W. Linville

orinoco: Provide option to avoid unnecessary fw caching

Make firmware caching on startup optional, and make it default.

When the option is not selected and PM_SLEEP is configured, then
cache firmware in the suspend pm_notifier. This configuration saves
about 64k RAM in normal use, but can lead to a situation where the
driver is configured to use a different firmware.

Signed-off by: David Kilroy <kilroyd@googlemail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent ac7cafd7
......@@ -214,6 +214,21 @@ config HERMES
configure your card and that /etc/pcmcia/wireless.opts works :
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>
config HERMES_CACHE_FW_ON_INIT
bool "Cache Hermes firmware on driver initialisation"
depends on HERMES
default y
---help---
Say Y to cache any firmware required by the Hermes drivers
on startup. The firmware will remain cached until the
driver is unloaded. The cache uses 64K of RAM.
Otherwise load the firmware from userspace as required. In
this case the driver should be unloaded and restarted
whenever the firmware is changed.
If you are not sure, say Y.
config APPLE_AIRPORT
tristate "Apple Airport support (built-in)"
depends on PPC_PMAC && HERMES
......
......@@ -84,6 +84,7 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/firmware.h>
#include <linux/suspend.h>
#include <linux/if_arp.h>
#include <linux/wireless.h>
#include <linux/ieee80211.h>
......@@ -712,6 +713,7 @@ static int orinoco_download(struct orinoco_private *priv)
return err;
}
#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
static void orinoco_cache_fw(struct orinoco_private *priv, int ap)
{
const struct firmware *fw_entry = NULL;
......@@ -745,6 +747,10 @@ static void orinoco_uncache_fw(struct orinoco_private *priv)
priv->cached_pri_fw = NULL;
priv->cached_fw = NULL;
}
#else
#define orinoco_cache_fw(priv, ap)
#define orinoco_uncache_fw(priv)
#endif
/********************************************************************/
/* Device methods */
......@@ -3099,6 +3105,50 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
/********************************************************************/
/* Power management */
/********************************************************************/
#if defined(CONFIG_PM_SLEEP) && !defined(CONFIG_HERMES_CACHE_FW_ON_INIT)
static int orinoco_pm_notifier(struct notifier_block *notifier,
unsigned long pm_event,
void *unused)
{
struct orinoco_private *priv = container_of(notifier,
struct orinoco_private,
pm_notifier);
/* All we need to do is cache the firmware before suspend, and
* release it when we come out.
*
* Only need to do this if we're downloading firmware. */
if (!priv->do_fw_download)
return NOTIFY_DONE;
switch (pm_event) {
case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
orinoco_cache_fw(priv, 0);
break;
case PM_POST_RESTORE:
/* Restore from hibernation failed. We need to clean
* up in exactly the same way, so fall through. */
case PM_POST_HIBERNATION:
case PM_POST_SUSPEND:
orinoco_uncache_fw(priv);
break;
case PM_RESTORE_PREPARE:
default:
break;
}
return NOTIFY_DONE;
}
#else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */
#define orinoco_pm_notifier NULL
#endif
/********************************************************************/
/* Initialization */
/********************************************************************/
......@@ -3342,7 +3392,9 @@ static int orinoco_init(struct net_device *dev)
}
if (priv->do_fw_download) {
#ifdef CONFIG_HERMES_CACHE_FW_ON_INIT
orinoco_cache_fw(priv, 0);
#endif
err = orinoco_download(priv);
if (err)
......@@ -3583,6 +3635,10 @@ struct net_device
priv->cached_pri_fw = NULL;
priv->cached_fw = NULL;
/* Register PM notifiers */
priv->pm_notifier.notifier_call = orinoco_pm_notifier;
register_pm_notifier(&priv->pm_notifier);
return dev;
}
......@@ -3595,6 +3651,7 @@ void free_orinocodev(struct net_device *dev)
* emptying the list */
tasklet_kill(&priv->rx_tasklet);
unregister_pm_notifier(&priv->pm_notifier);
orinoco_uncache_fw(priv);
priv->wpa_ie_len = 0;
......
......@@ -10,6 +10,7 @@
#define DRIVER_VERSION "0.15"
#include <linux/interrupt.h>
#include <linux/suspend.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
......@@ -170,6 +171,8 @@ struct orinoco_private {
/* Cached in memory firmware to use during ->resume. */
const struct firmware *cached_pri_fw;
const struct firmware *cached_fw;
struct notifier_block pm_notifier;
};
#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