diff options
author | David Kilroy <kilroyd@googlemail.com> | 2008-11-22 05:37:28 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-11-26 09:47:47 -0500 |
commit | 39d1ffee57c7ce02c90ec8e9272df8aa8ddf600f (patch) | |
tree | e13cd6eef6b24084a54cd024c2af19c71f4d0e1f | |
parent | ac7cafd72261857278dff9f737e600b30088653b (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/Kconfig | 15 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco/orinoco.c | 57 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco/orinoco.h | 3 |
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 | ||
217 | config 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 | |||
217 | config APPLE_AIRPORT | 232 | config 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) | ||
715 | static void orinoco_cache_fw(struct orinoco_private *priv, int ap) | 717 | static 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) | ||
3112 | static 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 |