[RFC PATCH] libertas: turn radio off when down
Ashish Shukla
ashishs at marvell.com
Wed Nov 21 00:45:04 EST 2007
Mesh forwarding is always on. Therefore, disabling radio when interface
in not up will disable mesh forwarding as well. Have you thought of
this?
Thanks
-Ashish
> -----Original Message-----
> From: devel-bounces at lists.laptop.org
[mailto:devel-bounces at lists.laptop.org] On Behalf Of Dan
> Williams
> Sent: Wednesday, November 21, 2007 9:48 AM
> To: devel at laptop.org
> Cc: Brajesh Dave; Andres Salomon
> Subject: [RFC PATCH] libertas: turn radio off when down
>
> Backport of a patch to olpc-2.6 I'm going to post to linux-wireless.
> When both interfaces are down (~IFF_UP), turn off the radio to save
> power. When either interface is opened (via iwconfig up or otherwise)
> turn the radio back on unless the radio was explicitly disabled by the
> user via 'iwconfig txpower off' which also is the previous behavior
> without this patch.
>
> This should allow NetworkManager to be told to go to sleep, at which
> point it will mark all devices down, and with this patch should turn
off
> the radio and save power.
>
> It also cleans up some of the mess that was *_open, the intent for
which
> (unless I'm reading that code wrong) was just to check whether the
> interface was up or not, since that's what open/close do.
>
> Comments?
>
> Signed-off-by: Dan Williams <dcbw at redhat.com>
>
> diff --git a/drivers/net/wireless/libertas/cmd.c
b/drivers/net/wireless/libertas/cmd.c
> index caf0b1c..5a15b56 100644
> --- a/drivers/net/wireless/libertas/cmd.c
> +++ b/drivers/net/wireless/libertas/cmd.c
> @@ -479,6 +479,8 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private *
priv,
> return 0;
> }
>
> +#define TURN_ON_RF 0x01
> +
> static int wlan_cmd_802_11_radio_control(wlan_private * priv,
> struct cmd_ds_command *cmd,
> int cmd_action)
> @@ -510,7 +512,7 @@ static int
wlan_cmd_802_11_radio_control(wlan_private * priv,
> break;
> }
>
> - if (adapter->radioon)
> + if (adapter->radio_on)
> pradiocontrol->control |= cpu_to_le16(TURN_ON_RF);
> else
> pradiocontrol->control &= cpu_to_le16(~TURN_ON_RF);
> @@ -1112,7 +1114,7 @@ int libertas_set_radio_control(wlan_private *
priv)
> CMD_OPTION_WAITFORRSP, 0, NULL);
>
> lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n",
> - priv->adapter->radioon, priv->adapter->preamble);
> + priv->adapter->radio_on, priv->adapter->preamble);
>
> lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
> return ret;
> diff --git a/drivers/net/wireless/libertas/cmdresp.c
b/drivers/net/wireless/libertas/cmdresp.c
> index d391391..433d481 100644
> --- a/drivers/net/wireless/libertas/cmdresp.c
> +++ b/drivers/net/wireless/libertas/cmdresp.c
> @@ -991,7 +991,7 @@ int libertas_process_event(wlan_private * priv)
> }
> lbs_pr_info("EVENT: MESH_AUTO_STARTED\n");
> adapter->mesh_connect_status = LIBERTAS_CONNECTED;
> - if (priv->mesh_open == 1) {
> + if (priv->mesh_dev->flags & IFF_UP) {
> netif_wake_queue(priv->mesh_dev);
> netif_carrier_on(priv->mesh_dev);
> }
> diff --git a/drivers/net/wireless/libertas/dev.h
b/drivers/net/wireless/libertas/dev.h
> index 404ca50..62c3e75 100644
> --- a/drivers/net/wireless/libertas/dev.h
> +++ b/drivers/net/wireless/libertas/dev.h
> @@ -100,9 +100,6 @@ struct wlan_mesh_stats {
>
> /** Private structure for the MV device */
> struct _wlan_private {
> - int open;
> - int mesh_open;
> - int infra_open;
> int mesh_autostart_enabled;
> __le16 boot2_version;
>
> @@ -339,7 +336,8 @@ struct _wlan_adapter {
> u16 nextSNRNF;
> u16 numSNRNF;
>
> - u8 radioon;
> + u8 user_radio_on;
> + u8 radio_on;
> u32 preamble;
>
> /** data rate stuff */
> diff --git a/drivers/net/wireless/libertas/host.h
b/drivers/net/wireless/libertas/host.h
> index 00d5675..eb516be 100644
> --- a/drivers/net/wireless/libertas/host.h
> +++ b/drivers/net/wireless/libertas/host.h
> @@ -183,10 +183,6 @@
> #define CMD_TYPE_SHORT_PREAMBLE 0x0002
> #define CMD_TYPE_LONG_PREAMBLE 0x0003
>
> -#define TURN_ON_RF 0x01
> -#define RADIO_ON 0x01
> -#define RADIO_OFF 0x00
> -
> #define SET_AUTO_PREAMBLE 0x05
> #define SET_SHORT_PREAMBLE 0x03
> #define SET_LONG_PREAMBLE 0x01
> diff --git a/drivers/net/wireless/libertas/main.c
b/drivers/net/wireless/libertas/main.c
> index 2b104d2..f07d5b4 100644
> --- a/drivers/net/wireless/libertas/main.c
> +++ b/drivers/net/wireless/libertas/main.c
> @@ -11,7 +11,9 @@
> #include <linux/netdevice.h>
> #include <linux/if_arp.h>
> #include <linux/kthread.h>
> +#if CONFIG_OLPC
> #include <asm/olpc.h>
> +#endif
>
> #include <net/iw_handler.h>
> #include <net/ieee80211.h>
> @@ -406,8 +408,6 @@ static int libertas_dev_open(struct net_device
*dev)
>
> lbs_deb_enter(LBS_DEB_NET);
>
> - priv->open = 1;
> -
> if (adapter->connect_status == LIBERTAS_CONNECTED) {
> netif_carrier_on(priv->dev);
> }
> @@ -433,20 +433,33 @@ static int libertas_dev_open(struct net_device
*dev)
> */
> static int libertas_mesh_open(struct net_device *dev)
> {
> - wlan_private *priv = (wlan_private *) dev->priv ;
> + wlan_private *priv = (wlan_private *) dev->priv;
> + int ret = -1;
> +
> + lbs_deb_enter(LBS_DEB_NET);
>
> if (pre_open_check(dev) == -1)
> - return -1;
> - priv->mesh_open = 1 ;
> + goto out;
> +
> + /* Turn the radio on unless it was turned off by the user */
> + if (priv->adapter->user_radio_on)
> + libertas_set_radio_on (priv, 1);
> +
> netif_wake_queue(priv->mesh_dev);
>
> - priv->adapter->mesh_connect_status = LIBERTAS_CONNECTED;
> + priv->adapter->mesh_connect_status = LIBERTAS_CONNECTED;
>
> netif_carrier_on(priv->mesh_dev);
> netif_wake_queue(priv->mesh_dev);
> - if (priv->infra_open == 0)
> - return libertas_dev_open(priv->dev) ;
> - return 0;
> +
> + if (!(priv->dev->flags & IFF_UP))
> + ret = libertas_dev_open(priv->dev);
> + else
> + ret = 0;
> +
> +out:
> + lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
> + return ret;
> }
>
> /**
> @@ -457,15 +470,28 @@ static int libertas_mesh_open(struct net_device
*dev)
> */
> static int libertas_open(struct net_device *dev)
> {
> - wlan_private *priv = (wlan_private *) dev->priv ;
> + wlan_private *priv = (wlan_private *) dev->priv;
> + int ret = -1;
> +
> + lbs_deb_enter(LBS_DEB_NET);
> +
> + if (pre_open_check(dev) == -1)
> + goto out;
> +
> + /* Turn the radio on unless it was turned off by the user */
> + if (priv->adapter->user_radio_on)
> + libertas_set_radio_on (priv, 1);
>
> - if(pre_open_check(dev) == -1)
> - return -1;
> - priv->infra_open = 1 ;
> netif_wake_queue(priv->dev);
> - if (priv->open == 0)
> - return libertas_dev_open(priv->dev) ;
> - return 0;
> +
> + if (!(priv->mesh_dev->flags & IFF_UP))
> + ret = libertas_dev_open(priv->dev);
> + else
> + ret = 0;
> +
> +out:
> + lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
> + return ret;
> }
>
> static int libertas_dev_close(struct net_device *dev)
> @@ -475,7 +501,6 @@ static int libertas_dev_close(struct net_device
*dev)
> lbs_deb_enter(LBS_DEB_NET);
>
> netif_carrier_off(priv->dev);
> - priv->open = 0;
>
> lbs_deb_leave(LBS_DEB_NET);
> return 0;
> @@ -491,12 +516,15 @@ static int libertas_mesh_close(struct net_device
*dev)
> {
> wlan_private *priv = (wlan_private *) (dev->priv);
>
> - priv->mesh_open = 0;
> netif_stop_queue(priv->mesh_dev);
> - if (priv->infra_open == 0)
> + if (!(priv->dev->flags & IFF_UP)) {
> + /* Turn the radio off if neither interface is up */
> + libertas_set_radio_on (priv, 0);
> +
> return libertas_dev_close(dev);
> - else
> - return 0;
> + }
> +
> + return 0;
> }
>
> /**
> @@ -510,11 +538,14 @@ static int libertas_close(struct net_device
*dev)
> wlan_private *priv = (wlan_private *) dev->priv;
>
> netif_stop_queue(dev);
> - priv->infra_open = 0;
> - if (priv->mesh_open == 0)
> + if (!(priv->mesh_dev->flags & IFF_UP)) {
> + /* Turn the radio off if neither interface is up */
> + libertas_set_radio_on (priv, 0);
> +
> return libertas_dev_close(dev);
> - else
> - return 0;
> + }
> +
> + return 0;
> }
>
>
> @@ -1148,7 +1179,8 @@ static void wlan_init_adapter(wlan_private *
priv)
> adapter->currentpacketfilter =
> CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
>
> - adapter->radioon = RADIO_ON;
> + adapter->radio_on = 1;
> + adapter->user_radio_on = adapter->radio_on;
>
> adapter->auto_rate = 1;
> adapter->cur_rate = 0;
> @@ -1234,8 +1266,6 @@ wlan_private *libertas_add_card(void *card,
struct device *dmdev)
>
> priv->dev = dev;
> priv->card = card;
> - priv->mesh_open = 0;
> - priv->infra_open = 0;
>
> SET_MODULE_OWNER(dev);
>
> diff --git a/drivers/net/wireless/libertas/wext.c
b/drivers/net/wireless/libertas/wext.c
> index 11f9389..61b31fa 100644
> --- a/drivers/net/wireless/libertas/wext.c
> +++ b/drivers/net/wireless/libertas/wext.c
> @@ -111,16 +111,18 @@ static struct chan_freq_power
*find_cfp_by_band_and_freq(wlan_adapter *
> adapter,
> * @option Radio Option
> * @return 0 --success, otherwise fail
> */
> -static int wlan_radio_ioctl(wlan_private * priv, u8 option)
> +int libertas_set_radio_on(wlan_private * priv, u8 on)
> {
> int ret = 0;
> wlan_adapter *adapter = priv->adapter;
>
> + on = on ? 0x01 : 0x00;
> +
> lbs_deb_enter(LBS_DEB_WEXT);
>
> - if (adapter->radioon != option) {
> - lbs_deb_wext("switching radio %s\n", option ? "on" :
"off");
> - adapter->radioon = option;
> + if (adapter->radio_on != on) {
> + lbs_deb_wext("turning radio %s\n", on ? "on" : "off");
> + adapter->radio_on = on;
>
> ret = libertas_prepare_and_send_command(priv,
> CMD_802_11_RADIO_CONTROL,
> @@ -451,7 +453,7 @@ static int wlan_get_txpow(struct net_device *dev,
> lbs_deb_wext("tx power level %d dbm\n", adapter->txpowerlevel);
> vwrq->value = adapter->txpowerlevel;
> vwrq->fixed = 1;
> - if (adapter->radioon) {
> + if (adapter->radio_on) {
> vwrq->disabled = 0;
> vwrq->flags = IW_TXPOW_DBM;
> } else {
> @@ -1885,19 +1887,20 @@ static int wlan_set_txpow(struct net_device
*dev, struct iw_request_info
> *info,
> int ret = 0;
> wlan_private *priv = dev->priv;
> wlan_adapter *adapter = priv->adapter;
> -
> u16 dbm;
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> if (vwrq->disabled) {
> - wlan_radio_ioctl(priv, RADIO_OFF);
> + adapter->user_radio_on = 0;
> + libertas_set_radio_on(priv, 0);
> return 0;
> }
>
> adapter->preamble = CMD_TYPE_AUTO_PREAMBLE;
> + adapter->user_radio_on = 1;
>
> - wlan_radio_ioctl(priv, RADIO_ON);
> + libertas_set_radio_on(priv, 1);
>
> /* Userspace check in iwrange if it should use dBm or mW,
> * therefore this should never happen... Jean II */
> diff --git a/drivers/net/wireless/libertas/wext.h
b/drivers/net/wireless/libertas/wext.h
> index e93853b..d01c54a 100644
> --- a/drivers/net/wireless/libertas/wext.h
> +++ b/drivers/net/wireless/libertas/wext.h
> @@ -67,5 +67,6 @@ struct wlan_ioctl_regrdwr {
> extern struct iw_handler_def libertas_handler_def;
> extern struct iw_handler_def mesh_handler_def;
> int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int
i);
> +int libertas_set_radio_on(wlan_private * priv, u8 on);
>
> #endif /* _WLAN_WEXT_H_ */
>
> _______________________________________________
> Devel mailing list
> Devel at lists.laptop.org
> http://lists.laptop.org/listinfo/devel
More information about the Devel
mailing list