aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Kilroy <kilroyd@googlemail.com>2008-11-22 05:37:28 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-11-26 09:47:47 -0500
commit39d1ffee57c7ce02c90ec8e9272df8aa8ddf600f (patch)
treee13cd6eef6b24084a54cd024c2af19c71f4d0e1f
parentac7cafd72261857278dff9f737e600b30088653b (diff)
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: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/Kconfig15
-rw-r--r--drivers/net/wireless/orinoco/orinoco.c57
-rw-r--r--drivers/net/wireless/orinoco/orinoco.h3
3 files changed, 75 insertions, 0 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 7ea916b257e4..ea543fcf2687 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -214,6 +214,21 @@ config HERMES
214 configure your card and that /etc/pcmcia/wireless.opts works : 214 configure your card and that /etc/pcmcia/wireless.opts works :
215 <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html> 215 <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>
216 216
217config HERMES_CACHE_FW_ON_INIT
218 bool "Cache Hermes firmware on driver initialisation"
219 depends on HERMES
220 default y
221 ---help---
222 Say Y to cache any firmware required by the Hermes drivers
223 on startup. The firmware will remain cached until the
224 driver is unloaded. The cache uses 64K of RAM.
225
226 Otherwise load the firmware from userspace as required. In
227 this case the driver should be unloaded and restarted
228 whenever the firmware is changed.
229
230 If you are not sure, say Y.
231
217config APPLE_AIRPORT 232config APPLE_AIRPORT
218 tristate "Apple Airport support (built-in)" 233 tristate "Apple Airport support (built-in)"
219 depends on PPC_PMAC && HERMES 234 depends on PPC_PMAC && HERMES
diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c
index 09eec7f620bc..171bfa03868e 100644
--- a/drivers/net/wireless/orinoco/orinoco.c
+++ b/drivers/net/wireless/orinoco/orinoco.c
@@ -84,6 +84,7 @@
84#include <linux/etherdevice.h> 84#include <linux/etherdevice.h>
85#include <linux/ethtool.h> 85#include <linux/ethtool.h>
86#include <linux/firmware.h> 86#include <linux/firmware.h>
87#include <linux/suspend.h>
87#include <linux/if_arp.h> 88#include <linux/if_arp.h>
88#include <linux/wireless.h> 89#include <linux/wireless.h>
89#include <linux/ieee80211.h> 90#include <linux/ieee80211.h>
@@ -712,6 +713,7 @@ static int orinoco_download(struct orinoco_private *priv)
712 return err; 713 return err;
713} 714}
714 715
716#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
715static void orinoco_cache_fw(struct orinoco_private *priv, int ap) 717static void orinoco_cache_fw(struct orinoco_private *priv, int ap)
716{ 718{
717 const struct firmware *fw_entry = NULL; 719 const struct firmware *fw_entry = NULL;
@@ -745,6 +747,10 @@ static void orinoco_uncache_fw(struct orinoco_private *priv)
745 priv->cached_pri_fw = NULL; 747 priv->cached_pri_fw = NULL;
746 priv->cached_fw = NULL; 748 priv->cached_fw = NULL;
747} 749}
750#else
751#define orinoco_cache_fw(priv, ap)
752#define orinoco_uncache_fw(priv)
753#endif
748 754
749/********************************************************************/ 755/********************************************************************/
750/* Device methods */ 756/* Device methods */
@@ -3100,6 +3106,50 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id)
3100} 3106}
3101 3107
3102/********************************************************************/ 3108/********************************************************************/
3109/* Power management */
3110/********************************************************************/
3111#if defined(CONFIG_PM_SLEEP) && !defined(CONFIG_HERMES_CACHE_FW_ON_INIT)
3112static int orinoco_pm_notifier(struct notifier_block *notifier,
3113 unsigned long pm_event,
3114 void *unused)
3115{
3116 struct orinoco_private *priv = container_of(notifier,
3117 struct orinoco_private,
3118 pm_notifier);
3119
3120 /* All we need to do is cache the firmware before suspend, and
3121 * release it when we come out.
3122 *
3123 * Only need to do this if we're downloading firmware. */
3124 if (!priv->do_fw_download)
3125 return NOTIFY_DONE;
3126
3127 switch (pm_event) {
3128 case PM_HIBERNATION_PREPARE:
3129 case PM_SUSPEND_PREPARE:
3130 orinoco_cache_fw(priv, 0);
3131 break;
3132
3133 case PM_POST_RESTORE:
3134 /* Restore from hibernation failed. We need to clean
3135 * up in exactly the same way, so fall through. */
3136 case PM_POST_HIBERNATION:
3137 case PM_POST_SUSPEND:
3138 orinoco_uncache_fw(priv);
3139 break;
3140
3141 case PM_RESTORE_PREPARE:
3142 default:
3143 break;
3144 }
3145
3146 return NOTIFY_DONE;
3147}
3148#else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */
3149#define orinoco_pm_notifier NULL
3150#endif
3151
3152/********************************************************************/
3103/* Initialization */ 3153/* Initialization */
3104/********************************************************************/ 3154/********************************************************************/
3105 3155
@@ -3342,7 +3392,9 @@ static int orinoco_init(struct net_device *dev)
3342 } 3392 }
3343 3393
3344 if (priv->do_fw_download) { 3394 if (priv->do_fw_download) {
3395#ifdef CONFIG_HERMES_CACHE_FW_ON_INIT
3345 orinoco_cache_fw(priv, 0); 3396 orinoco_cache_fw(priv, 0);
3397#endif
3346 3398
3347 err = orinoco_download(priv); 3399 err = orinoco_download(priv);
3348 if (err) 3400 if (err)
@@ -3583,6 +3635,10 @@ struct net_device
3583 priv->cached_pri_fw = NULL; 3635 priv->cached_pri_fw = NULL;
3584 priv->cached_fw = NULL; 3636 priv->cached_fw = NULL;
3585 3637
3638 /* Register PM notifiers */
3639 priv->pm_notifier.notifier_call = orinoco_pm_notifier;
3640 register_pm_notifier(&priv->pm_notifier);
3641
3586 return dev; 3642 return dev;
3587} 3643}
3588 3644
@@ -3595,6 +3651,7 @@ void free_orinocodev(struct net_device *dev)
3595 * emptying the list */ 3651 * emptying the list */
3596 tasklet_kill(&priv->rx_tasklet); 3652 tasklet_kill(&priv->rx_tasklet);
3597 3653
3654 unregister_pm_notifier(&priv->pm_notifier);
3598 orinoco_uncache_fw(priv); 3655 orinoco_uncache_fw(priv);
3599 3656
3600 priv->wpa_ie_len = 0; 3657 priv->wpa_ie_len = 0;
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
index f6eaea98db53..00750c8ba7db 100644
--- a/drivers/net/wireless/orinoco/orinoco.h
+++ b/drivers/net/wireless/orinoco/orinoco.h
@@ -10,6 +10,7 @@
10#define DRIVER_VERSION "0.15" 10#define DRIVER_VERSION "0.15"
11 11
12#include <linux/interrupt.h> 12#include <linux/interrupt.h>
13#include <linux/suspend.h>
13#include <linux/netdevice.h> 14#include <linux/netdevice.h>
14#include <linux/wireless.h> 15#include <linux/wireless.h>
15#include <net/iw_handler.h> 16#include <net/iw_handler.h>
@@ -170,6 +171,8 @@ struct orinoco_private {
170 /* Cached in memory firmware to use during ->resume. */ 171 /* Cached in memory firmware to use during ->resume. */
171 const struct firmware *cached_pri_fw; 172 const struct firmware *cached_pri_fw;
172 const struct firmware *cached_fw; 173 const struct firmware *cached_fw;
174
175 struct notifier_block pm_notifier;
173}; 176};
174 177
175#ifdef ORINOCO_DEBUG 178#ifdef ORINOCO_DEBUG