Skip to content

Commit

Permalink
orinoco: Provide option to avoid unnecessary fw caching
Browse files Browse the repository at this point in the history
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: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
David Kilroy authored and John W. Linville committed Nov 26, 2008
1 parent ac7cafd commit 39d1ffe
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 0 deletions.
15 changes: 15 additions & 0 deletions drivers/net/wireless/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
57 changes: 57 additions & 0 deletions drivers/net/wireless/orinoco/orinoco.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
/********************************************************************/
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/wireless/orinoco/orinoco.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 39d1ffe

Please sign in to comment.