[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