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: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of Dan
> Williams
> Sent: Wednesday, November 21, 2007 9:48 AM
> To: [EMAIL PROTECTED]
> 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 <[EMAIL PROTECTED]>
> 
> 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@lists.laptop.org
> http://lists.laptop.org/listinfo/devel
_______________________________________________
Devel mailing list
Devel@lists.laptop.org
http://lists.laptop.org/listinfo/devel

Reply via email to