* RE: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688
From: Dan Williams @ 2009-10-01 18:00 UTC (permalink / raw)
To: Bing Zhao
Cc: libertas-dev@lists.infradead.org, linux-wireless@vger.kernel.org,
Amitkumar Karwar
In-Reply-To: <477F20668A386D41ADCC57781B1F704306DDA6C1B6@SC-VEXCH1.marvell.com>
On Mon, 2009-09-28 at 15:42 -0700, Bing Zhao wrote:
> Hi Dan,
>
> > -----Original Message-----
> > From: Dan Williams [mailto:dcbw@redhat.com]
> > Sent: Sunday, September 20, 2009 7:58 AM
> > To: Bing Zhao
> > Cc: libertas-dev@lists.infradead.org; linux-wireless@vger.kernel.org; Amitkumar Karwar
> > Subject: Re: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688
> >
> > On Tue, 2009-09-15 at 16:45 -0700, Bing Zhao wrote:
> > > From: Amitkumar Karwar <akarwar@marvell.com>
> > >
> > > Add timer based auto deep sleep feature in libertas driver which can be
> > > configured through debugfs interface. This is tested on SD8688, SD8686 cards
> > > with firmware versions 10.38.1.p25, 9.70.4.p0 respectively on 32-bit and 64-bit
> > > platforms. Tests have been done for USB/CS cards to make sure that the patch
> > > won't break USB/CS code. We didn't test the if_spi driver.
> >
> > So there's always:
> >
> > #define IW_POWER_SAVING 0x4000 /* Value is relative (how aggressive)*/
> >
> > iwconfig wlan0 power saving 10
> >
> > That seems quite a bit better than a new debugfs parameter, until we can
> > conver the driver over cfg80211 and do this properly. If the power
> > saving mode is higher than some number X, the chip gets put into deep
> > sleep mode, or it can be automatically placed in deep sleep mode by the
> > driver when there is no association like you have done with the timer
> > above. I think you should pick reasonable defaults, and perhaps if the
> > 'saving' value is larger, the timer value in the driver gets smaller.
> >
> > Does that sound like an OK approach? We really should be using debugfs
> > only for debugging stuff (obviously), and the real fix for this sort of
> > thing is to switch over to cfg80211 where we can actually extend the
> > configuration API instead of hacking it into debugfs/WEXT/etc.
> >
> > Dan
>
> Thanks for your suggestion.
>
> In latest kernel, IW_POWER_SAVING is not defined in include/linux/wireless.h.
> IW_POWER_PERIOD and IW_POWER_TIMEOUT are defined though.
You're right. wireless-tools apparently had it, but since WEXT is on
life-support, John removed most of the additions before WE-21 got
committed to the kernel. So it's not there.
> We are planning to remove debugfs for configurations and use the following commands instead.
> Please let us know if there is any concern.
>
> iwconfig wlan0 power period 0 -> enable deep sleep (enter deep sleep immediately)
> iwconfig wlan0 power period 5 -> enable auto deep sleep (enter deep sleep automatically after 5s idle time)
> iwconfig wlan0 power period -1 -> disable deep sleep / auto deep sleep
Sure, that seems fine to me.
dan
> By the way, there is a bug in iwconfig tool v29. It doesn’t take any values right after "period" or "timeout". The new version of Wireless Tools v30-pre8 (link below) fixed the bug:
>
> http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/wireless_tools.30.pre8.tar.gz
>
> Thanks,
>
> Bing
>
> >
> > > Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> > > Signed-off-by: Bing Zhao <bzhao@marvell.com>
> > > ---
> > > drivers/net/wireless/libertas/README | 28 +++++-
> > > drivers/net/wireless/libertas/cmd.c | 72 +++++++++++++-
> > > drivers/net/wireless/libertas/cmdresp.c | 12 +++
> > > drivers/net/wireless/libertas/debugfs.c | 160 +++++++++++++++++++++++++++++++
> > > drivers/net/wireless/libertas/decl.h | 4 +
> > > drivers/net/wireless/libertas/dev.h | 18 ++++
> > > drivers/net/wireless/libertas/host.h | 1 +
> > > drivers/net/wireless/libertas/if_cs.c | 3 +
> > > drivers/net/wireless/libertas/if_sdio.c | 56 +++++++++++
> > > drivers/net/wireless/libertas/if_sdio.h | 3 +-
> > > drivers/net/wireless/libertas/if_spi.c | 3 +
> > > drivers/net/wireless/libertas/if_usb.c | 3 +
> > > drivers/net/wireless/libertas/main.c | 111 +++++++++++++++++++---
> > > drivers/net/wireless/libertas/scan.c | 11 ++
> > > drivers/net/wireless/libertas/wext.c | 138 ++++++++++++++++++++++++++
> > > 15 files changed, 604 insertions(+), 19 deletions(-)
> > >
> > > diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README
> > > index ab6a2d5..059ce8c 100644
> > > --- a/drivers/net/wireless/libertas/README
> > > +++ b/drivers/net/wireless/libertas/README
> > > @@ -1,5 +1,5 @@
> > > ================================================================================
> > > - README for USB8388
> > > + README for Libertas
> > >
> > > (c) Copyright © 2003-2006, Marvell International Ltd.
> > > All Rights Reserved
> > > @@ -226,4 +226,30 @@ setuserscan
> > > All entries in the scan table (not just the new scan data when keep=1)
> > > will be displayed upon completion by use of the getscantable ioctl.
> > >
> > > +deepsleep
> > > +
> > > + This command is used to configure the station in deep sleep mode/auto
> > > + deep sleep mode. Command expects two parameters:
> > > + 'state' 'idle time period'
> > > +
> > > + The timer is implemented to monitor the activities (command, event,
> > > + data, etc.). When an activity is detected station will exit from deep
> > > + sleep mode automatically and restart the timer. At timer expiry (no
> > > + activity for defined time period) the deepsleep mode is entered
> > > + automatically.
> > > +
> > > + Note: this command is for SDIO interface only.
> > > +
> > > + Path: /sys/kernel/debug/libertas_wireless/ethX/
> > > +
> > > + Usage:
> > > + To read the current status of deep sleep do:
> > > + cat deepsleep
> > > + To enable deep sleep mode do:
> > > + echo '1 0' > deepsleep
> > > + To enable auto deep sleep mode with idle time period 5 seconds do:
> > > + echo '1 5000' > deepsleep
> > > + To disable deep sleep/auto deep sleep mode do:
> > > + echo '0 0' > deepsleep
> > > +
> > > ==============================================================================
> > > diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
> > > index 6850981..3a3e894 100644
> > > --- a/drivers/net/wireless/libertas/cmd.c
> > > +++ b/drivers/net/wireless/libertas/cmd.c
> > > @@ -17,7 +17,6 @@
> > >
> > > static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
> > >
> > > -
> > > /**
> > > * @brief Simple callback that copies response back into command
> > > *
> > > @@ -319,6 +318,60 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
> > > return 0;
> > > }
> > >
> > > +static int lbs_wait_for_ds_awake(struct lbs_private *priv)
> > > +{
> > > + int ret = 0;
> > > +
> > > + lbs_deb_enter(LBS_DEB_CMD);
> > > +
> > > + if (priv->is_deep_sleep) {
> > > + if (!wait_event_interruptible_timeout(priv->ds_awake_q,
> > > + !priv->is_deep_sleep, (10 * HZ))) {
> > > + lbs_pr_err("ds_awake_q: timer expired\n");
> > > + ret = -1;
> > > + }
> > > + }
> > > +
> > > + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
> > > + return ret;
> > > +}
> > > +
> > > +int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
> > > +{
> > > + int ret = 0;
> > > +
> > > + lbs_deb_enter(LBS_DEB_CMD);
> > > +
> > > + if (deep_sleep) {
> > > + if (priv->is_deep_sleep != 1) {
> > > + lbs_deb_cmd("deep sleep: sleep\n");
> > > + BUG_ON(!priv->enter_deep_sleep);
> > > + ret = priv->enter_deep_sleep(priv);
> > > + if (!ret) {
> > > + netif_stop_queue(priv->dev);
> > > + netif_carrier_off(priv->dev);
> > > + }
> > > + } else {
> > > + lbs_pr_err("deep sleep: already enabled\n");
> > > + }
> > > + } else {
> > > + if (priv->is_deep_sleep) {
> > > + lbs_deb_cmd("deep sleep: wakeup\n");
> > > + BUG_ON(!priv->exit_deep_sleep);
> > > + ret = priv->exit_deep_sleep(priv);
> > > + if (!ret) {
> > > + ret = lbs_wait_for_ds_awake(priv);
> > > + if (ret)
> > > + lbs_pr_err("deep sleep: wakeup"
> > > + "failed\n");
> > > + }
> > > + }
> > > + }
> > > +
> > > + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
> > > + return ret;
> > > +}
> > > +
> > > int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
> > > struct assoc_request *assoc)
> > > {
> > > @@ -1242,8 +1295,17 @@ static void lbs_submit_command(struct lbs_private *priv,
> > > timeo = HZ/4;
> > > }
> > >
> > > - /* Setup the timer after transmit command */
> > > - mod_timer(&priv->command_timer, jiffies + timeo);
> > > + if (command == CMD_802_11_DEEP_SLEEP) {
> > > + if (priv->is_auto_deep_sleep_enabled) {
> > > + priv->wakeup_dev_required = 1;
> > > + priv->dnld_sent = 0;
> > > + }
> > > + priv->is_deep_sleep = 1;
> > > + lbs_complete_command(priv, cmdnode, 0);
> > > + } else {
> > > + /* Setup the timer after transmit command */
> > > + mod_timer(&priv->command_timer, jiffies + timeo);
> > > + }
> > >
> > > lbs_deb_leave(LBS_DEB_HOST);
> > > }
> > > @@ -1505,6 +1567,10 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
> > > case CMD_802_11_BEACON_CTRL:
> > > ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
> > > break;
> > > + case CMD_802_11_DEEP_SLEEP:
> > > + cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP);
> > > + cmdptr->size = cpu_to_le16(S_DS_GEN);
> > > + break;
> > > default:
> > > lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
> > > ret = -1;
> > > diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
> > > index c42d3fa..47d2b19 100644
> > > --- a/drivers/net/wireless/libertas/cmdresp.c
> > > +++ b/drivers/net/wireless/libertas/cmdresp.c
> > > @@ -504,9 +504,21 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
> > >
> > > case MACREG_INT_CODE_HOST_AWAKE:
> > > lbs_deb_cmd("EVENT: host awake\n");
> > > + if (priv->reset_deep_sleep_wakeup)
> > > + priv->reset_deep_sleep_wakeup(priv);
> > > + priv->is_deep_sleep = 0;
> > > lbs_send_confirmwake(priv);
> > > break;
> > >
> > > + case MACREG_INT_CODE_DEEP_SLEEP_AWAKE:
> > > + if (priv->reset_deep_sleep_wakeup)
> > > + priv->reset_deep_sleep_wakeup(priv);
> > > + lbs_deb_cmd("EVENT: ds awake\n");
> > > + priv->is_deep_sleep = 0;
> > > + priv->wakeup_dev_required = 0;
> > > + wake_up_interruptible(&priv->ds_awake_q);
> > > + break;
> > > +
> > > case MACREG_INT_CODE_PS_AWAKE:
> > > lbs_deb_cmd("EVENT: ps awake\n");
> > > /* handle unexpected PS AWAKE event */
> > > diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
> > > index 893a55c..624a438 100644
> > > --- a/drivers/net/wireless/libertas/debugfs.c
> > > +++ b/drivers/net/wireless/libertas/debugfs.c
> > > @@ -117,6 +117,11 @@ static ssize_t lbs_sleepparams_write(struct file *file,
> > > if (!buf)
> > > return -ENOMEM;
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + goto out_unlock;
> > > + }
> > > +
> > > buf_size = min(count, len - 1);
> > > if (copy_from_user(buf, user_buf, buf_size)) {
> > > ret = -EFAULT;
> > > @@ -157,6 +162,11 @@ static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf,
> > > if (!buf)
> > > return -ENOMEM;
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + goto out_unlock;
> > > + }
> > > +
> > > ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp);
> > > if (ret)
> > > goto out_unlock;
> > > @@ -173,6 +183,118 @@ out_unlock:
> > > return ret;
> > > }
> > >
> > > +static ssize_t lbs_deepsleep_read(struct file *file, char __user *userbuf,
> > > + size_t count, loff_t *ppos)
> > > +{
> > > + struct lbs_private *priv = file->private_data;
> > > + ssize_t pos = 0;
> > > + int ret;
> > > + unsigned long addr = get_zeroed_page(GFP_KERNEL);
> > > + char *buf = (char *)addr;
> > > +
> > > + if (!buf)
> > > + return -ENOMEM;
> > > +
> > > + if (!priv->enter_deep_sleep) {
> > > + lbs_pr_err("deep sleep feature is not implemented "
> > > + "for this interface driver\n");
> > > + ret = -EINVAL;
> > > + goto out_ds;
> > > + }
> > > +
> > > + if (priv->is_auto_deep_sleep_enabled)
> > > + pos += snprintf(buf, len, "%d %d\n",
> > > + priv->is_auto_deep_sleep_enabled,
> > > + priv->auto_deep_sleep_timeout);
> > > + else if (priv->is_deep_sleep)
> > > + pos += snprintf(buf, len, "%d %d\n",
> > > + priv->is_deep_sleep,
> > > + priv->auto_deep_sleep_timeout);
> > > + else
> > > + pos += snprintf(buf, len, "%d %d\n",
> > > + priv->is_deep_sleep,
> > > + priv->auto_deep_sleep_timeout);
> > > +
> > > + ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
> > > +
> > > +out_ds:
> > > + free_page(addr);
> > > + return ret;
> > > +}
> > > +
> > > +static ssize_t lbs_deepsleep_write(struct file *file,
> > > + const char __user *userbuf,
> > > + size_t count, loff_t *ppos)
> > > +{
> > > + struct lbs_private *priv = file->private_data;
> > > + ssize_t res, buf_size;
> > > + int is_deep_sleep, auto_deep_sleep_timeout;
> > > + unsigned long addr = get_zeroed_page(GFP_KERNEL);
> > > + char *buf = (char *)addr;
> > > +
> > > + if (!buf)
> > > + return -ENOMEM;
> > > +
> > > + if (!priv->enter_deep_sleep) {
> > > + lbs_pr_err("deep sleep feature is not implemented "
> > > + "for this interface driver\n");
> > > + res = -EINVAL;
> > > + goto out_ds;
> > > + }
> > > +
> > > + if (priv->connect_status == LBS_CONNECTED) {
> > > + lbs_pr_err("can't use deep sleep cmd in connected "
> > > + "state\n");
> > > + res = -EINVAL;
> > > + goto out_ds;
> > > + }
> > > +
> > > + buf_size = min(count, len - 1);
> > > + if (copy_from_user(buf, userbuf, buf_size)) {
> > > + res = -EFAULT;
> > > + goto out_ds;
> > > + }
> > > +
> > > + res = sscanf(buf, "%d %d", &is_deep_sleep, &auto_deep_sleep_timeout);
> > > + if ((res != 2) || (!is_deep_sleep && auto_deep_sleep_timeout) ||
> > > + !((is_deep_sleep == 1) ||
> > > + (is_deep_sleep == 0))) {
> > > + lbs_pr_err("unknown option\n");
> > > + res = -EINVAL;
> > > + goto out_ds;
> > > + }
> > > +
> > > + if (auto_deep_sleep_timeout) {
> > > + if (!priv->is_auto_deep_sleep_enabled) {
> > > + priv->is_activity_detected = 0;
> > > + priv->auto_deep_sleep_timeout = auto_deep_sleep_timeout;
> > > + lbs_enter_auto_deep_sleep(priv);
> > > + } else {
> > > + priv->auto_deep_sleep_timeout = auto_deep_sleep_timeout;
> > > + lbs_deb_debugfs("auto deep sleep: already enabled\n");
> > > + }
> > > + } else {
> > > + if (priv->is_auto_deep_sleep_enabled) {
> > > + lbs_exit_auto_deep_sleep(priv);
> > > + /* Try to exit deep sleep if auto deep sleep disabled */
> > > + res = lbs_set_deep_sleep(priv, 0);
> > > + if (res)
> > > + goto out_ds;
> > > + }
> > > + if ((is_deep_sleep == 0) || (is_deep_sleep == 1)) {
> > > + res = lbs_set_deep_sleep(priv, is_deep_sleep);
> > > + if (res)
> > > + goto out_ds;
> > > + }
> > > + }
> > > +
> > > + res = count;
> > > +
> > > +out_ds:
> > > + free_page(addr);
> > > + return res;
> > > +}
> > > +
> > > /*
> > > * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
> > > * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
> > > @@ -223,6 +345,9 @@ static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask,
> > > u8 freq;
> > > int events = 0;
> > >
> > > + if (!lbs_is_cmd_allowed(priv))
> > > + return -EBUSY;
> > > +
> > > buf = (char *)get_zeroed_page(GFP_KERNEL);
> > > if (!buf)
> > > return -ENOMEM;
> > > @@ -275,6 +400,9 @@ static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
> > > char *buf;
> > > int ret;
> > >
> > > + if (!lbs_is_cmd_allowed(priv))
> > > + return -EBUSY;
> > > +
> > > buf = (char *)get_zeroed_page(GFP_KERNEL);
> > > if (!buf)
> > > return -ENOMEM;
> > > @@ -444,6 +572,11 @@ static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
> > > if (!buf)
> > > return -ENOMEM;
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + free_page(addr);
> > > + return -EBUSY;
> > > + }
> > > +
> > > offval.offset = priv->mac_offset;
> > > offval.value = 0;
> > >
> > > @@ -496,6 +629,11 @@ static ssize_t lbs_wrmac_write(struct file *file,
> > > if (!buf)
> > > return -ENOMEM;
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + res = -EBUSY;
> > > + goto out_unlock;
> > > + }
> > > +
> > > buf_size = min(count, len - 1);
> > > if (copy_from_user(buf, userbuf, buf_size)) {
> > > res = -EFAULT;
> > > @@ -532,6 +670,11 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
> > > if (!buf)
> > > return -ENOMEM;
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + free_page(addr);
> > > + return -EBUSY;
> > > + }
> > > +
> > > offval.offset = priv->bbp_offset;
> > > offval.value = 0;
> > >
> > > @@ -585,6 +728,11 @@ static ssize_t lbs_wrbbp_write(struct file *file,
> > > if (!buf)
> > > return -ENOMEM;
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + res = -EBUSY;
> > > + goto out_unlock;
> > > + }
> > > +
> > > buf_size = min(count, len - 1);
> > > if (copy_from_user(buf, userbuf, buf_size)) {
> > > res = -EFAULT;
> > > @@ -621,6 +769,11 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
> > > if (!buf)
> > > return -ENOMEM;
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + free_page(addr);
> > > + return -EBUSY;
> > > + }
> > > +
> > > offval.offset = priv->rf_offset;
> > > offval.value = 0;
> > >
> > > @@ -674,6 +827,11 @@ static ssize_t lbs_wrrf_write(struct file *file,
> > > if (!buf)
> > > return -ENOMEM;
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + res = -EBUSY;
> > > + goto out_unlock;
> > > + }
> > > +
> > > buf_size = min(count, len - 1);
> > > if (copy_from_user(buf, userbuf, buf_size)) {
> > > res = -EFAULT;
> > > @@ -717,6 +875,8 @@ static const struct lbs_debugfs_files debugfs_files[] = {
> > > write_file_dummy), },
> > > { "sleepparams", 0644, FOPS(lbs_sleepparams_read,
> > > lbs_sleepparams_write), },
> > > + { "deepsleep", 0644, FOPS(lbs_deepsleep_read,
> > > + lbs_deepsleep_write), },
> > > };
> > >
> > > static const struct lbs_debugfs_files debugfs_events_files[] = {
> > > diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
> > > index 0b84bdc..34b475f 100644
> > > --- a/drivers/net/wireless/libertas/decl.h
> > > +++ b/drivers/net/wireless/libertas/decl.h
> > > @@ -33,6 +33,10 @@ int lbs_execute_next_command(struct lbs_private *priv);
> > > int lbs_process_event(struct lbs_private *priv, u32 event);
> > > void lbs_queue_event(struct lbs_private *priv, u32 event);
> > > void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
> > > +int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep);
> > > +int lbs_is_cmd_allowed(struct lbs_private *priv);
> > > +int lbs_enter_auto_deep_sleep(struct lbs_private *priv);
> > > +int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
> > >
> > > u32 lbs_fw_index_to_data_rate(u8 index);
> > > u8 lbs_data_rate_to_fw_index(u32 rate);
> > > diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
> > > index 578c697..e2b4ef2 100644
> > > --- a/drivers/net/wireless/libertas/dev.h
> > > +++ b/drivers/net/wireless/libertas/dev.h
> > > @@ -129,6 +129,20 @@ struct lbs_private {
> > > u32 bbp_offset;
> > > u32 rf_offset;
> > >
> > > + /** Deep sleep flag */
> > > + int is_deep_sleep;
> > > + /** Auto deep sleep enabled flag */
> > > + int is_auto_deep_sleep_enabled;
> > > + /** Device wakeup required flag */
> > > + int wakeup_dev_required;
> > > + /** Auto deep sleep flag*/
> > > + int is_activity_detected;
> > > + /** Auto deep sleep timeout (in miliseconds) */
> > > + int auto_deep_sleep_timeout;
> > > +
> > > + /** Deep sleep wait queue */
> > > + wait_queue_head_t ds_awake_q;
> > > +
> > > /* Download sent:
> > > bit0 1/0=data_sent/data_tx_done,
> > > bit1 1/0=cmd_sent/cmd_tx_done,
> > > @@ -154,6 +168,9 @@ struct lbs_private {
> > > /** Hardware access */
> > > int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
> > > void (*reset_card) (struct lbs_private *priv);
> > > + int (*enter_deep_sleep) (struct lbs_private *priv);
> > > + int (*exit_deep_sleep) (struct lbs_private *priv);
> > > + int (*reset_deep_sleep_wakeup) (struct lbs_private *priv);
> > >
> > > /* Wake On LAN */
> > > uint32_t wol_criteria;
> > > @@ -204,6 +221,7 @@ struct lbs_private {
> > >
> > > /** Timers */
> > > struct timer_list command_timer;
> > > + struct timer_list auto_deepsleep_timer;
> > > int nr_retries;
> > > int cmd_timed_out;
> > >
> > > diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
> > > index fe8f0cb..c055daa 100644
> > > --- a/drivers/net/wireless/libertas/host.h
> > > +++ b/drivers/net/wireless/libertas/host.h
> > > @@ -57,6 +57,7 @@
> > > #define CMD_802_11_ENABLE_RSN 0x002f
> > > #define CMD_802_11_SET_AFC 0x003c
> > > #define CMD_802_11_GET_AFC 0x003d
> > > +#define CMD_802_11_DEEP_SLEEP 0x003e
> > > #define CMD_802_11_AD_HOC_STOP 0x0040
> > > #define CMD_802_11_HOST_SLEEP_CFG 0x0043
> > > #define CMD_802_11_WAKEUP_CONFIRM 0x0044
> > > diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
> > > index 6238176..465742f 100644
> > > --- a/drivers/net/wireless/libertas/if_cs.c
> > > +++ b/drivers/net/wireless/libertas/if_cs.c
> > > @@ -946,6 +946,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
> > > card->priv = priv;
> > > priv->card = card;
> > > priv->hw_host_to_card = if_cs_host_to_card;
> > > + priv->enter_deep_sleep = NULL;
> > > + priv->exit_deep_sleep = NULL;
> > > + priv->reset_deep_sleep_wakeup = NULL;
> > > priv->fw_ready = 1;
> > >
> > > /* Now actually get the IRQ */
> > > diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
> > > index 485a8d4..9716728 100644
> > > --- a/drivers/net/wireless/libertas/if_sdio.c
> > > +++ b/drivers/net/wireless/libertas/if_sdio.c
> > > @@ -831,6 +831,58 @@ out:
> > > return ret;
> > > }
> > >
> > > +static int if_sdio_enter_deep_sleep(struct lbs_private *priv)
> > > +{
> > > + int ret = -1;
> > > + struct cmd_header cmd;
> > > +
> > > + memset(&cmd, 0, sizeof(cmd));
> > > +
> > > + lbs_deb_sdio("send DEEP_SLEEP command\n");
> > > + ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd),
> > > + lbs_cmd_copyback, (unsigned long) &cmd);
> > > + if (ret)
> > > + lbs_pr_err("DEEP_SLEEP cmd failed\n");
> > > +
> > > + mdelay(200);
> > > + return ret;
> > > +}
> > > +
> > > +static int if_sdio_exit_deep_sleep(struct lbs_private *priv)
> > > +{
> > > + struct if_sdio_card *card = priv->card;
> > > + int ret = -1;
> > > +
> > > + lbs_deb_enter(LBS_DEB_SDIO);
> > > + sdio_claim_host(card->func);
> > > +
> > > + sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
> > > + if (ret)
> > > + lbs_pr_err("sdio_writeb failed!\n");
> > > +
> > > + sdio_release_host(card->func);
> > > + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
> > > + return ret;
> > > +}
> > > +
> > > +static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)
> > > +{
> > > + struct if_sdio_card *card = priv->card;
> > > + int ret = -1;
> > > +
> > > + lbs_deb_enter(LBS_DEB_SDIO);
> > > + sdio_claim_host(card->func);
> > > +
> > > + sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret);
> > > + if (ret)
> > > + lbs_pr_err("sdio_writeb failed!\n");
> > > +
> > > + sdio_release_host(card->func);
> > > + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
> > > + return ret;
> > > +
> > > +}
> > > +
> > > /*******************************************************************/
> > > /* SDIO callbacks */
> > > /*******************************************************************/
> > > @@ -859,6 +911,7 @@ static void if_sdio_interrupt(struct sdio_func *func)
> > > * Ignore the define name, this really means the card has
> > > * successfully received the command.
> > > */
> > > + card->priv->is_activity_detected = 1;
> > > if (cause & IF_SDIO_H_INT_DNLD)
> > > lbs_host_to_card_done(card->priv);
> > >
> > > @@ -998,6 +1051,9 @@ static int if_sdio_probe(struct sdio_func *func,
> > >
> > > priv->card = card;
> > > priv->hw_host_to_card = if_sdio_host_to_card;
> > > + priv->enter_deep_sleep = if_sdio_enter_deep_sleep;
> > > + priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
> > > + priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
> > >
> > > priv->fw_ready = 1;
> > >
> > > diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h
> > > index 60c9b2f..12179c1 100644
> > > --- a/drivers/net/wireless/libertas/if_sdio.h
> > > +++ b/drivers/net/wireless/libertas/if_sdio.h
> > > @@ -51,5 +51,6 @@
> > > #define IF_SDIO_EVENT 0x80fc
> > >
> > > #define IF_SDIO_BLOCK_SIZE 256
> > > -
> > > +#define CONFIGURATION_REG 0x03
> > > +#define HOST_POWER_UP (0x1U << 1)
> > > #endif
> > > diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
> > > index 446e327..e2fa657 100644
> > > --- a/drivers/net/wireless/libertas/if_spi.c
> > > +++ b/drivers/net/wireless/libertas/if_spi.c
> > > @@ -1117,6 +1117,9 @@ static int __devinit if_spi_probe(struct spi_device *spi)
> > > card->priv = priv;
> > > priv->card = card;
> > > priv->hw_host_to_card = if_spi_host_to_card;
> > > + priv->enter_deep_sleep = NULL;
> > > + priv->exit_deep_sleep = NULL;
> > > + priv->reset_deep_sleep_wakeup = NULL;
> > > priv->fw_ready = 1;
> > >
> > > /* Initialize interrupt handling stuff. */
> > > diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
> > > index 92bc8c5..a8262de 100644
> > > --- a/drivers/net/wireless/libertas/if_usb.c
> > > +++ b/drivers/net/wireless/libertas/if_usb.c
> > > @@ -300,6 +300,9 @@ static int if_usb_probe(struct usb_interface *intf,
> > > cardp->priv->fw_ready = 1;
> > >
> > > priv->hw_host_to_card = if_usb_host_to_card;
> > > + priv->enter_deep_sleep = NULL;
> > > + priv->exit_deep_sleep = NULL;
> > > + priv->reset_deep_sleep_wakeup = NULL;
> > > #ifdef CONFIG_OLPC
> > > if (machine_is_olpc())
> > > priv->reset_card = if_usb_reset_olpc_card;
> > > diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
> > > index 8df1cfd..3b14fcc 100644
> > > --- a/drivers/net/wireless/libertas/main.c
> > > +++ b/drivers/net/wireless/libertas/main.c
> > > @@ -574,8 +574,10 @@ void lbs_host_to_card_done(struct lbs_private *priv)
> > > priv->dnld_sent = DNLD_RES_RECEIVED;
> > >
> > > /* Wake main thread if commands are pending */
> > > - if (!priv->cur_cmd || priv->tx_pending_len > 0)
> > > - wake_up_interruptible(&priv->waitq);
> > > + if (!priv->cur_cmd || priv->tx_pending_len > 0) {
> > > + if (!priv->wakeup_dev_required)
> > > + wake_up_interruptible(&priv->waitq);
> > > + }
> > >
> > > spin_unlock_irqrestore(&priv->driver_lock, flags);
> > > lbs_deb_leave(LBS_DEB_THREAD);
> > > @@ -770,7 +772,8 @@ static int lbs_thread(void *data)
> > > shouldsleep = 0; /* We have a command response */
> > > else if (priv->cur_cmd)
> > > shouldsleep = 1; /* Can't send a command; one already running */
> > > - else if (!list_empty(&priv->cmdpendingq))
> > > + else if (!list_empty(&priv->cmdpendingq) &&
> > > + !(priv->wakeup_dev_required))
> > > shouldsleep = 0; /* We have a command to send */
> > > else if (__kfifo_len(priv->event_fifo))
> > > shouldsleep = 0; /* We have an event to process */
> > > @@ -822,6 +825,26 @@ static int lbs_thread(void *data)
> > > }
> > > spin_unlock_irq(&priv->driver_lock);
> > >
> > > + /* Process hardware events, e.g. card removed, link lost */
> > > + spin_lock_irq(&priv->driver_lock);
> > > + while (__kfifo_len(priv->event_fifo)) {
> > > + u32 event;
> > > + __kfifo_get(priv->event_fifo, (unsigned char *) &event,
> > > + sizeof(event));
> > > + spin_unlock_irq(&priv->driver_lock);
> > > + lbs_process_event(priv, event);
> > > + spin_lock_irq(&priv->driver_lock);
> > > + }
> > > + spin_unlock_irq(&priv->driver_lock);
> > > +
> > > + if (priv->wakeup_dev_required) {
> > > + lbs_deb_thread("Waking up device...\n");
> > > + /* Wake up device */
> > > + if (priv->exit_deep_sleep(priv))
> > > + lbs_deb_thread("Wakeup device failed\n");
> > > + continue;
> > > + }
> > > +
> > > /* command timeout stuff */
> > > if (priv->cmd_timed_out && priv->cur_cmd) {
> > > struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
> > > @@ -849,18 +872,7 @@ static int lbs_thread(void *data)
> > > }
> > > priv->cmd_timed_out = 0;
> > >
> > > - /* Process hardware events, e.g. card removed, link lost */
> > > - spin_lock_irq(&priv->driver_lock);
> > > - while (__kfifo_len(priv->event_fifo)) {
> > > - u32 event;
> > >
> > > - __kfifo_get(priv->event_fifo, (unsigned char *) &event,
> > > - sizeof(event));
> > > - spin_unlock_irq(&priv->driver_lock);
> > > - lbs_process_event(priv, event);
> > > - spin_lock_irq(&priv->driver_lock);
> > > - }
> > > - spin_unlock_irq(&priv->driver_lock);
> > >
> > > if (!priv->fw_ready)
> > > continue;
> > > @@ -894,6 +906,9 @@ static int lbs_thread(void *data)
> > > (priv->psstate == PS_STATE_PRE_SLEEP))
> > > continue;
> > >
> > > + if (priv->is_deep_sleep)
> > > + continue;
> > > +
> > > /* Execute the next command */
> > > if (!priv->dnld_sent && !priv->cur_cmd)
> > > lbs_execute_next_command(priv);
> > > @@ -928,6 +943,7 @@ static int lbs_thread(void *data)
> > > }
> > >
> > > del_timer(&priv->command_timer);
> > > + del_timer(&priv->auto_deepsleep_timer);
> > > wake_up_all(&priv->cmd_pending);
> > >
> > > lbs_deb_leave(LBS_DEB_THREAD);
> > > @@ -1050,6 +1066,60 @@ out:
> > > lbs_deb_leave(LBS_DEB_CMD);
> > > }
> > >
> > > +/**
> > > + * This function put the device back to deep sleep mode when timer expires
> > > + * and no activity (command, event, data etc.) is detected.
> > > + */
> > > +static void auto_deepsleep_timer_fn(unsigned long data)
> > > +{
> > > + struct lbs_private *priv = (struct lbs_private *)data;
> > > + int ret;
> > > +
> > > + lbs_deb_enter(LBS_DEB_CMD);
> > > +
> > > + if (priv->is_activity_detected) {
> > > + priv->is_activity_detected = 0;
> > > + } else {
> > > + if (priv->is_auto_deep_sleep_enabled &&
> > > + (!priv->wakeup_dev_required) &&
> > > + (priv->connect_status != LBS_CONNECTED)) {
> > > + lbs_deb_main("Entering auto deep sleep mode...\n");
> > > + ret = lbs_prepare_and_send_command(priv,
> > > + CMD_802_11_DEEP_SLEEP, 0,
> > > + 0, 0, NULL);
> > > + }
> > > + }
> > > + mod_timer(&priv->auto_deepsleep_timer , jiffies +
> > > + (priv->auto_deep_sleep_timeout * HZ)/1000);
> > > + lbs_deb_leave(LBS_DEB_CMD);
> > > +}
> > > +
> > > +int lbs_enter_auto_deep_sleep(struct lbs_private *priv)
> > > +{
> > > + lbs_deb_enter(LBS_DEB_SDIO);
> > > +
> > > + priv->is_auto_deep_sleep_enabled = 1;
> > > + if (priv->is_deep_sleep)
> > > + priv->wakeup_dev_required = 1;
> > > + mod_timer(&priv->auto_deepsleep_timer ,
> > > + jiffies + (priv->auto_deep_sleep_timeout * HZ)/1000);
> > > +
> > > + lbs_deb_leave(LBS_DEB_SDIO);
> > > + return 0;
> > > +}
> > > +
> > > +int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
> > > +{
> > > + lbs_deb_enter(LBS_DEB_SDIO);
> > > +
> > > + priv->is_auto_deep_sleep_enabled = 0;
> > > + priv->auto_deep_sleep_timeout = 0;
> > > + del_timer(&priv->auto_deepsleep_timer);
> > > +
> > > + lbs_deb_leave(LBS_DEB_SDIO);
> > > + return 0;
> > > +}
> > > +
> > > static void lbs_sync_channel_worker(struct work_struct *work)
> > > {
> > > struct lbs_private *priv = container_of(work, struct lbs_private,
> > > @@ -1099,11 +1169,17 @@ static int lbs_init_adapter(struct lbs_private *priv)
> > > priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
> > > priv->psmode = LBS802_11POWERMODECAM;
> > > priv->psstate = PS_STATE_FULL_POWER;
> > > + priv->is_deep_sleep = 0;
> > > + priv->is_auto_deep_sleep_enabled = 0;
> > > + priv->wakeup_dev_required = 0;
> > > + init_waitqueue_head(&priv->ds_awake_q);
> > >
> > > mutex_init(&priv->lock);
> > >
> > > setup_timer(&priv->command_timer, command_timer_fn,
> > > (unsigned long)priv);
> > > + setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn,
> > > + (unsigned long)priv);
> > >
> > > INIT_LIST_HEAD(&priv->cmdfreeq);
> > > INIT_LIST_HEAD(&priv->cmdpendingq);
> > > @@ -1142,6 +1218,7 @@ static void lbs_free_adapter(struct lbs_private *priv)
> > > if (priv->event_fifo)
> > > kfifo_free(priv->event_fifo);
> > > del_timer(&priv->command_timer);
> > > + del_timer(&priv->auto_deepsleep_timer);
> > > kfree(priv->networks);
> > > priv->networks = NULL;
> > >
> > > @@ -1272,6 +1349,11 @@ void lbs_remove_card(struct lbs_private *priv)
> > > wrqu.ap_addr.sa_family = ARPHRD_ETHER;
> > > wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
> > >
> > > + if (priv->is_deep_sleep) {
> > > + priv->is_deep_sleep = 0;
> > > + wake_up_interruptible(&priv->ds_awake_q);
> > > + }
> > > +
> > > /* Stop the thread servicing the interrupts */
> > > priv->surpriseremoved = 1;
> > > kthread_stop(priv->main_thread);
> > > @@ -1392,6 +1474,7 @@ void lbs_stop_card(struct lbs_private *priv)
> > >
> > > /* Delete the timeout of the currently processing command */
> > > del_timer_sync(&priv->command_timer);
> > > + del_timer_sync(&priv->auto_deepsleep_timer);
> > >
> > > /* Flush pending command nodes */
> > > spin_lock_irqsave(&priv->driver_lock, flags);
> > > diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
> > > index 6c95af3..e468e15 100644
> > > --- a/drivers/net/wireless/libertas/scan.c
> > > +++ b/drivers/net/wireless/libertas/scan.c
> > > @@ -950,6 +950,11 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + goto out;
> > > + }
> > > +
> > > if (!priv->radio_on) {
> > > ret = -EINVAL;
> > > goto out;
> > > @@ -1017,6 +1022,12 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + err = -EBUSY;
> > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
> > > + return err;
> > > + }
> > > +
> > > /* iwlist should wait until the current scan is finished */
> > > if (priv->scan_channel)
> > > return -EAGAIN;
> > > diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
> > > index be837a0..ef2b986 100644
> > > --- a/drivers/net/wireless/libertas/wext.c
> > > +++ b/drivers/net/wireless/libertas/wext.c
> > > @@ -45,6 +45,31 @@ static inline void lbs_cancel_association_work(struct lbs_private *priv)
> > > priv->pending_assoc_req = NULL;
> > > }
> > >
> > > +/**
> > > + * @brief This function checks if the command is allowed.
> > > + *
> > > + * @param priv A pointer to lbs_private structure
> > > + * @return allowed or not allowed.
> > > + */
> > > +
> > > +int lbs_is_cmd_allowed(struct lbs_private *priv)
> > > +{
> > > + int ret = 1;
> > > +
> > > + lbs_deb_enter(LBS_DEB_WEXT);
> > > +
> > > + if (!priv->is_auto_deep_sleep_enabled) {
> > > + if (priv->is_deep_sleep) {
> > > + lbs_deb_wext("IOCTLS called when station"
> > > + "is in deep sleep\n");
> > > + ret = 0;
> > > + }
> > > + }
> > > +
> > > + lbs_deb_leave(LBS_DEB_WEXT);
> > > + return ret;
> > > +}
> > > +
> > >
> > > /**
> > > * @brief Find the channel frequency power info with specific channel
> > > @@ -168,6 +193,11 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + lbs_deb_leave(LBS_DEB_WEXT);
> > > + return -EBUSY;
> > > + }
> > > +
> > > cfp = lbs_find_cfp_by_band_and_channel(priv, 0,
> > > priv->curbssparams.channel);
> > >
> > > @@ -278,6 +308,12 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> > > + return ret;
> > > + }
> > > +
> > > if (vwrq->disabled)
> > > val = MRVDRV_RTS_MAX_VALUE;
> > >
> > > @@ -299,6 +335,11 @@ static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + goto out;
> > > + }
> > > +
> > > ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val);
> > > if (ret)
> > > goto out;
> > > @@ -321,6 +362,12 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> > > + return ret;
> > > + }
> > > +
> > > if (vwrq->disabled)
> > > val = MRVDRV_FRAG_MAX_VALUE;
> > >
> > > @@ -342,6 +389,11 @@ static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + goto out;
> > > + }
> > > +
> > > ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val);
> > > if (ret)
> > > goto out;
> > > @@ -391,6 +443,11 @@ static int lbs_get_txpow(struct net_device *dev,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + goto out;
> > > + }
> > > +
> > > if (!priv->radio_on) {
> > > lbs_deb_wext("tx power off\n");
> > > vwrq->value = 0;
> > > @@ -424,6 +481,11 @@ static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + goto out;
> > > + }
> > > +
> > > if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
> > > return -EOPNOTSUPP;
> > >
> > > @@ -472,6 +534,11 @@ static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + goto out;
> > > + }
> > > +
> > > vwrq->disabled = 0;
> > >
> > > if (vwrq->flags & IW_RETRY_LONG) {
> > > @@ -712,6 +779,11 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + lbs_deb_leave(LBS_DEB_WEXT);
> > > + return -EBUSY;
> > > + }
> > > +
> > > if (!(priv->fwcapinfo & FW_CAPINFO_PS)) {
> > > if (vwrq->disabled)
> > > return 0;
> > > @@ -792,6 +864,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv))
> > > + return NULL;
> > > +
> > > priv->wstats.status = priv->mode;
> > >
> > > /* If we're not associated, all quality values are meaningless */
> > > @@ -892,6 +967,12 @@ static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> > > + return ret;
> > > + }
> > > +
> > > mutex_lock(&priv->lock);
> > > assoc_req = lbs_get_association_request(priv);
> > > if (!assoc_req) {
> > > @@ -1000,6 +1081,12 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
> > > u8 rates[MAX_RATES + 1];
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > > +
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + goto out;
> > > + }
> > > +
> > > lbs_deb_wext("vwrq->value %d\n", vwrq->value);
> > > lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed);
> > >
> > > @@ -1058,6 +1145,11 @@ static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + lbs_deb_leave(LBS_DEB_WEXT);
> > > + return -EBUSY;
> > > + }
> > > +
> > > if (priv->connect_status == LBS_CONNECTED) {
> > > vwrq->value = priv->cur_rate * 500000;
> > >
> > > @@ -1084,6 +1176,11 @@ static int lbs_set_mode(struct net_device *dev,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + goto out;
> > > + }
> > > +
> > > if ( (*uwrq != IW_MODE_ADHOC)
> > > && (*uwrq != IW_MODE_INFRA)
> > > && (*uwrq != IW_MODE_AUTO)) {
> > > @@ -1325,6 +1422,12 @@ static int lbs_set_encode(struct net_device *dev,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> > > + return ret;
> > > + }
> > > +
> > > mutex_lock(&priv->lock);
> > > assoc_req = lbs_get_association_request(priv);
> > > if (!assoc_req) {
> > > @@ -1508,6 +1611,12 @@ static int lbs_set_encodeext(struct net_device *dev,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> > > + return ret;
> > > + }
> > > +
> > > mutex_lock(&priv->lock);
> > > assoc_req = lbs_get_association_request(priv);
> > > if (!assoc_req) {
> > > @@ -1720,6 +1829,12 @@ static int lbs_set_auth(struct net_device *dev,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> > > + return ret;
> > > + }
> > > +
> > > mutex_lock(&priv->lock);
> > > assoc_req = lbs_get_association_request(priv);
> > > if (!assoc_req) {
> > > @@ -1822,6 +1937,12 @@ static int lbs_get_auth(struct net_device *dev,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> > > + return ret;
> > > + }
> > > +
> > > switch (dwrq->flags & IW_AUTH_INDEX) {
> > > case IW_AUTH_KEY_MGMT:
> > > dwrq->value = priv->secinfo.key_mgmt;
> > > @@ -1864,6 +1985,11 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info
> > *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + goto out;
> > > + }
> > > +
> > > if (vwrq->disabled) {
> > > lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0);
> > > goto out;
> > > @@ -1983,6 +2109,12 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info
> > *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> > > + return ret;
> > > + }
> > > +
> > > if (!priv->radio_on) {
> > > ret = -EINVAL;
> > > goto out;
> > > @@ -2110,6 +2242,12 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
> > >
> > > lbs_deb_enter(LBS_DEB_WEXT);
> > >
> > > + if (!lbs_is_cmd_allowed(priv)) {
> > > + ret = -EBUSY;
> > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> > > + return ret;
> > > + }
> > > +
> > > if (!priv->radio_on)
> > > return -EINVAL;
> > >
>
^ permalink raw reply
* Re: [PATCH] ar9170usb: LEDs are confused
From: Hin-Tak Leung @ 2009-10-01 18:06 UTC (permalink / raw)
To: Christian Lamparter
Cc: Malte Gell, linux-wireless, Luis R. Rodriguez, linville
In-Reply-To: <200910011654.10963.chunkeey@googlemail.com>
On Thu, Oct 1, 2009 at 3:54 PM, Christian Lamparter
<chunkeey@googlemail.com> wrote:
> On 2009-10-01 06:32 AM, Malte Gell wrote:
>>I first noticed the LEDs are confused,
> no, the LED colors is not _confused_ at all.
> This is simply different on.... well, you know: on a per-device base!
>
> For example: The Netgear uses a single bi-color LED for their WNDA3100 stick.
> It glows blue or/and orange depending on the selected band and current
> operation mode and state...
>
> No idea why they didn't stick to the usual red/green mix.
> Maybe because someone told the hw-devs about the existence of
> red/green colorblind people??!
>
> The original vendor driver (located: drivers/staging/otus/80211core/ledmgr.c)
> goes to great lengths to describe what's behind the variety of
> blinking signals. Which is nice, if you like expensive light shows...
This is just based on my brief look at the relevant code itself - I
think the driver actually enumerates how many LEDs the device has, so
the ONLY_ONE_LED construct is a bit bogus. Also I think the
0x0846:0x9001 is Malte's with swapped LEDs, not ONLY_ONE?
I had a look when Malte first wrote about the swap - the code
basically just do asoc/data-tx in enumeration order (first LED found
is assoc, 2nd is tx, which make sense if some variant only have a
LED).
As for the color - it is probably just a matter of commercial
interests (if they can get a particular color from a source cheaper)
or simply variety to catch some customers - as you say, some *do* like
expensive light shows, and there is a market for it and money to be
made that way.
Anyway, I am just writing regarding the ONLY_ONE_LED construct and its
association with 0x0846:0x9001 ...
>
>>when I ran my AVM Fritz USBN N under Windows,
>>where the LEDs had the right order. I made a little patch that put
>>the assoc and the tx LEDs in the right order.
> FYI: you can assign the LEDs under "/sys/class/leds/" with a different tigger
> without messing with the kernel source... An up-to-date README can be found in
> the kernel's documentation directory: Documentation/leds-class.txt ,
> or you can look it up online as well:
> http://www.mjmwired.net/kernel/Documentation/leds-class.txt (from 2.6.31)
>
> but back to the patch and the problem with the wide diversity of
> over-customized solutions for a direct feedback mechanism to the
> mindful human operator...
>
> what about the (inline) _attached_ approach?
> Sure, this idea needs some more code... but, it covers all/most
> possible scenarios from beloved "no, no, no" vendors.
> ---
> From: Christian Lamparter <chunkeey@googlemail.com>
> Subject: [PATCH] ar9170usb: flexible LED mapping
>
> This patch adds two more quirk flags which are useful to:
>
> - reduce the number of virtual/ghost LEDs
> ( for low-budget devices: Netgear WN111 v2 )
> - select an alternative LED mapping.
> ( for AVM FRITZ!WLAN USB Stick N )
>
> Reported-by: Malte Gell <malte.gell@gmx.de>
> Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
> ---
> diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h
> index ec034af..a451bb1 100644
> --- a/drivers/net/wireless/ath/ar9170/ar9170.h
> +++ b/drivers/net/wireless/ath/ar9170/ar9170.h
> @@ -155,6 +155,12 @@ struct ar9170_sta_tid {
> #define AR9170_NUM_TX_STATUS 128
> #define AR9170_NUM_TX_AGG_MAX 30
>
> +enum ar9170_quirks {
> + AR9170_REQ_FW1_ONLY = BIT(0),
> + AR9170_ONLY_ONE_LED = BIT(1),
> + AR9170_SWAPPED_LEDS = BIT(2),
> +};
> +
> struct ar9170 {
> struct ieee80211_hw *hw;
> struct ath_common common;
> @@ -241,6 +247,9 @@ struct ar9170 {
> /* (cached) HW A-MPDU settings */
> u8 global_ampdu_density;
> u8 global_ampdu_factor;
> +
> + /* device quirks */
> + unsigned long quirks;
> };
>
> struct ar9170_sta_info {
> diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c
> index 86c4e79..36ab738 100644
> --- a/drivers/net/wireless/ath/ar9170/led.c
> +++ b/drivers/net/wireless/ath/ar9170/led.c
> @@ -155,18 +155,30 @@ void ar9170_unregister_leds(struct ar9170 *ar)
> cancel_delayed_work_sync(&ar->led_work);
> }
>
> +const static int std_led_map[AR9170_NUM_LEDS] = { 0, 1 };
> +const static int avm_led_map[AR9170_NUM_LEDS] = { 1, 0 };
> +
> int ar9170_register_leds(struct ar9170 *ar)
> {
> + const int *led_map;
> int err;
>
> + if (ar->quirks & AR9170_SWAPPED_LEDS)
> + led_map = avm_led_map;
> + else
> + led_map = std_led_map;
> +
> INIT_DELAYED_WORK(&ar->led_work, ar9170_update_leds);
>
> - err = ar9170_register_led(ar, 0, "tx",
> + err = ar9170_register_led(ar, led_map[0], "tx",
> ieee80211_get_tx_led_name(ar->hw));
> if (err)
> goto fail;
>
> - err = ar9170_register_led(ar, 1, "assoc",
> + if (ar->quirks & AR9170_ONLY_ONE_LED)
> + return 0;
> +
> + err = ar9170_register_led(ar, led_map[1], "assoc",
> ieee80211_get_assoc_led_name(ar->hw));
> if (err)
> goto fail;
> diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
> index e974e58..3be19e4 100644
> --- a/drivers/net/wireless/ath/ar9170/usb.c
> +++ b/drivers/net/wireless/ath/ar9170/usb.c
> @@ -55,10 +55,6 @@ MODULE_FIRMWARE("ar9170.fw");
> MODULE_FIRMWARE("ar9170-1.fw");
> MODULE_FIRMWARE("ar9170-2.fw");
>
> -enum ar9170_requirements {
> - AR9170_REQ_FW1_ONLY = 1,
> -};
> -
> static struct usb_device_id ar9170_usb_ids[] = {
> /* Atheros 9170 */
> { USB_DEVICE(0x0cf3, 0x9170) },
> @@ -73,7 +69,7 @@ static struct usb_device_id ar9170_usb_ids[] = {
> /* Netgear WNDA3100 */
> { USB_DEVICE(0x0846, 0x9010) },
> /* Netgear WN111 v2 */
> - { USB_DEVICE(0x0846, 0x9001) },
> + { USB_DEVICE(0x0846, 0x9001), .driver_info = AR9170_ONLY_ONE_LED },
> /* Zydas ZD1221 */
> { USB_DEVICE(0x0ace, 0x1221) },
> /* ZyXEL NWD271N */
> @@ -89,7 +85,7 @@ static struct usb_device_id ar9170_usb_ids[] = {
> /* IO-Data WNGDNUS2 */
> { USB_DEVICE(0x04bb, 0x093f) },
> /* AVM FRITZ!WLAN USB Stick N */
> - { USB_DEVICE(0x057C, 0x8401) },
> + { USB_DEVICE(0x057C, 0x8401), .driver_info = AR9170_SWAPPED_LEDS },
> /* AVM FRITZ!WLAN USB Stick N 2.4 */
> { USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY },
>
> @@ -589,7 +585,7 @@ static int ar9170_usb_request_firmware(struct ar9170_usb *aru)
> return 0;
> }
>
> - if (aru->req_one_stage_fw) {
> + if (aru->common.quirks & AR9170_REQ_FW1_ONLY) {
> dev_err(&aru->udev->dev, "ar9170.fw firmware file "
> "not found and is required for this device\n");
> return -EINVAL;
> @@ -753,15 +749,6 @@ err_out:
> return err;
> }
>
> -static bool ar9170_requires_one_stage(const struct usb_device_id *id)
> -{
> - if (!id->driver_info)
> - return false;
> - if (id->driver_info == AR9170_REQ_FW1_ONLY)
> - return true;
> - return false;
> -}
> -
> static int ar9170_usb_probe(struct usb_interface *intf,
> const struct usb_device_id *id)
> {
> @@ -781,8 +768,7 @@ static int ar9170_usb_probe(struct usb_interface *intf,
> aru->udev = udev;
> aru->intf = intf;
> ar = &aru->common;
> -
> - aru->req_one_stage_fw = ar9170_requires_one_stage(id);
> + ar->quirks = id->driver_info;
>
> usb_set_intfdata(intf, aru);
> SET_IEEE80211_DEV(ar->hw, &intf->dev);
> diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h
> index d098f4d..714436d 100644
> --- a/drivers/net/wireless/ath/ar9170/usb.h
> +++ b/drivers/net/wireless/ath/ar9170/usb.h
> @@ -64,8 +64,6 @@ struct ar9170_usb {
> struct usb_anchor tx_pending;
> struct usb_anchor tx_submitted;
>
> - bool req_one_stage_fw;
> -
> spinlock_t tx_urb_lock;
> unsigned int tx_submitted_urbs;
> unsigned int tx_pending_urbs;
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* [PATCH] staging: Add proper selection of WIRELESS_EXT and WEXT_PRIV
From: Larry Finger @ 2009-10-01 18:22 UTC (permalink / raw)
To: John Linville; +Cc: Johannes Berg, Greg Kroah-Hartman, wireless
After the incorporation of the patch entitled "wext: refactor", some
of the wireless drivers in drivers/staging fail to build because they
need to have CONFIG_WIRELESS_EXT and CONFIG_WEXT_PRIV defined.
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
John,
I know that Greg K-H maintains staging, but I sent this to you because
your tree is the only one affected at the moment. Greg is Cc'd.
Larry
---
Index: wireless-testing/drivers/staging/rtl8187se/Kconfig
===================================================================
--- wireless-testing.orig/drivers/staging/rtl8187se/Kconfig
+++ wireless-testing/drivers/staging/rtl8187se/Kconfig
@@ -1,6 +1,7 @@
config RTL8187SE
tristate "RealTek RTL8187SE Wireless LAN NIC driver"
depends on PCI
- depends on WIRELESS_EXT
+ select WIRELESS_EXT
+ select WEXT_PRIV
default N
---help---
Index: wireless-testing/drivers/staging/rtl8192e/Kconfig
===================================================================
--- wireless-testing.orig/drivers/staging/rtl8192e/Kconfig
+++ wireless-testing/drivers/staging/rtl8192e/Kconfig
@@ -1,6 +1,7 @@
config RTL8192E
tristate "RealTek RTL8192E Wireless LAN NIC driver"
depends on PCI
- depends on WIRELESS_EXT
+ select WIRELESS_EXT
+ select WEXT_PRIV
default N
---help---
Index: wireless-testing/drivers/staging/vt6655/Kconfig
===================================================================
--- wireless-testing.orig/drivers/staging/vt6655/Kconfig
+++ wireless-testing/drivers/staging/vt6655/Kconfig
@@ -1,6 +1,8 @@
config VT6655
tristate "VIA Technologies VT6655 support"
- depends on WIRELESS_EXT && PCI
+ depends on PCI
+ select WIRELESS_EXT
+ select WEXT_PRIV
---help---
This is a vendor-written driver for VIA VT6655.
Index: wireless-testing/drivers/staging/vt6656/Kconfig
===================================================================
--- wireless-testing.orig/drivers/staging/vt6656/Kconfig
+++ wireless-testing/drivers/staging/vt6656/Kconfig
@@ -1,6 +1,8 @@
config VT6656
tristate "VIA Technologies VT6656 support"
- depends on WIRELESS_EXT && USB
+ depends on USB
+ select WIRELESS_EXT
+ select WEXT_PRIV
---help---
This is a vendor-written driver for VIA VT6656.
^ permalink raw reply
* Re: [RFC] libertas: first stab at cfg80211 support
From: Dan Williams @ 2009-10-01 18:23 UTC (permalink / raw)
To: Holger Schurig; +Cc: libertas-dev, linux-wireless
In-Reply-To: <200909281321.21600.h.schurig@mn-solutions.de>
On Mon, 2009-09-28 at 13:21 +0200, Holger Schurig wrote:
> Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de>
>
> ---
>
> This patch currently just create a wdev, so you can do "iw list".
>
> I'd like to get comments if the position where I create/destroy
> the wdev makes sense.
Yeah, that's probably more or less it. The mesh bits are interesting,
because they aren't really mac80211 mesh, they are "special" mesh.
Perhaps we eventually want to port that over to cfg80211, but there are
special semantics with the mesh stuff that might be a problem (notably,
all encryption and rate settings are shared with the wlanX interface).
Because of that, the mesh interface is really just a shadow interface of
the normal wlanX interface, but during some calls we need to know
whether the call was done on the mesh iface or the wlanX iface, and of
course they each have different rx/tx queues. Otherwise they share the
same private struct and whatnot. That's what the "ml_priv" bits are
for. I'd dearly love to find some other way of doing this though, since
the ml_priv stuff is really fragile.
Dan
> Index: linux-wl/drivers/net/wireless/Kconfig
> ===================================================================
> --- linux-wl.orig/drivers/net/wireless/Kconfig 2009-09-28 12:06:02.000000000 +0200
> +++ linux-wl/drivers/net/wireless/Kconfig 2009-09-28 12:06:30.000000000 +0200
> @@ -138,6 +138,7 @@ config LIBERTAS
> depends on WLAN_80211
> select WIRELESS_EXT
> select LIB80211
> + select CFG80211
> select FW_LOADER
> ---help---
> A library for Marvell Libertas 8xxx devices.
> Index: linux-wl/drivers/net/wireless/libertas/Makefile
> ===================================================================
> --- linux-wl.orig/drivers/net/wireless/libertas/Makefile 2009-09-28 12:06:02.000000000 +0200
> +++ linux-wl/drivers/net/wireless/libertas/Makefile 2009-09-28 12:06:30.000000000 +0200
> @@ -1,5 +1,5 @@
> libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o \
> - debugfs.o persistcfg.o ethtool.o assoc.o
> + debugfs.o persistcfg.o ethtool.o assoc.o cfg.o
>
> usb8xxx-objs += if_usb.o
> libertas_cs-objs += if_cs.o
> Index: linux-wl/drivers/net/wireless/libertas/dev.h
> ===================================================================
> --- linux-wl.orig/drivers/net/wireless/libertas/dev.h 2009-09-28 12:06:02.000000000 +0200
> +++ linux-wl/drivers/net/wireless/libertas/dev.h 2009-09-28 12:06:30.000000000 +0200
> @@ -100,6 +100,7 @@ struct lbs_mesh_stats {
>
> /** Private structure for the MV device */
> struct lbs_private {
> + struct wireless_dev *wdev;
> int mesh_open;
> int mesh_fw_ver;
> int infra_open;
> Index: linux-wl/drivers/net/wireless/libertas/cfg.h
> ===================================================================
> --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> +++ linux-wl/drivers/net/wireless/libertas/cfg.h 2009-09-28 12:07:23.000000000 +0200
> @@ -0,0 +1,9 @@
> +#ifndef __LBS_CFG80211_H__
> +#define __LBS_CFG80211_H__
> +
> +#include "dev.h"
> +
> +struct wireless_dev *lbs_wdev_alloc(int sizeof_priv, struct device *dev);
> +void lbs_wdev_free(struct lbs_private *lbs);
> +
> +#endif
> Index: linux-wl/drivers/net/wireless/libertas/cfg.c
> ===================================================================
> --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> +++ linux-wl/drivers/net/wireless/libertas/cfg.c 2009-09-28 12:09:06.000000000 +0200
> @@ -0,0 +1,160 @@
> +/*
> + * Implement cfg80211 ("iw") support.
> + *
> + * Copyright (C) 2009 M&N Solutions GmbH, 61191 Rosbach, Germany
> + * Holger Schurig <hs4233@mail.mn-solutions.de>
> + *
> + * Based on cfg80211.h:
> + * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
> + * Samuel Ortiz <samuel.ortiz@intel.com>
> + * Zhu Yi <yi.zhu@intel.com>
> + */
> +
> +#include <net/cfg80211.h>
> +
> +#include "cfg.h"
> +
> +
> +#define CHAN2G(_channel, _freq, _flags) { \
> + .band = IEEE80211_BAND_2GHZ, \
> + .center_freq = (_freq), \
> + .hw_value = (_channel), \
> + .flags = (_flags), \
> + .max_antenna_gain = 0, \
> + .max_power = 30, \
> +}
> +
> +static struct ieee80211_channel lbs_2ghz_channels[] = {
> + CHAN2G(1, 2412, 0),
> + CHAN2G(2, 2417, 0),
> + CHAN2G(3, 2422, 0),
> + CHAN2G(4, 2427, 0),
> + CHAN2G(5, 2432, 0),
> + CHAN2G(6, 2437, 0),
> + CHAN2G(7, 2442, 0),
> + CHAN2G(8, 2447, 0),
> + CHAN2G(9, 2452, 0),
> + CHAN2G(10, 2457, 0),
> + CHAN2G(11, 2462, 0),
> + CHAN2G(12, 2467, 0),
> + CHAN2G(13, 2472, 0),
> + CHAN2G(14, 2484, 0),
> +};
> +
> +#define RATETAB_ENT(_rate, _rateid, _flags) \
> + { \
> + .bitrate = (_rate), \
> + .hw_value = (_rateid), \
> + .flags = (_flags), \
> + }
> +
> +
> +static struct ieee80211_rate lbs_rates[] = {
> + RATETAB_ENT(10, 0x1, 0),
> + RATETAB_ENT(20, 0x2, 0),
> + RATETAB_ENT(55, 0x4, 0),
> + RATETAB_ENT(110, 0x8, 0),
> + RATETAB_ENT(60, 0x10, 0),
> + RATETAB_ENT(90, 0x20, 0),
> + RATETAB_ENT(120, 0x40, 0),
> + RATETAB_ENT(180, 0x80, 0),
> + RATETAB_ENT(240, 0x100, 0),
> + RATETAB_ENT(360, 0x200, 0),
> + RATETAB_ENT(480, 0x400, 0),
> + RATETAB_ENT(540, 0x800, 0),
> +};
> +
> +static struct ieee80211_supported_band lbs_band_2ghz = {
> + .channels = lbs_2ghz_channels,
> + .n_channels = ARRAY_SIZE(lbs_2ghz_channels),
> + .bitrates = lbs_rates,
> + .n_bitrates = ARRAY_SIZE(lbs_rates),
> +};
> +
> +
> +static const u32 cipher_suites[] = {
> + WLAN_CIPHER_SUITE_WEP40,
> + WLAN_CIPHER_SUITE_WEP104,
> + WLAN_CIPHER_SUITE_TKIP,
> + WLAN_CIPHER_SUITE_CCMP,
> +};
> +
> +
> +
> +static struct cfg80211_ops lbs_cfg80211_ops = {
> +/* TODO
> + .change_virtual_intf = iwm_cfg80211_change_iface,
> + .add_key = iwm_cfg80211_add_key,
> + .get_key = iwm_cfg80211_get_key,
> + .del_key = iwm_cfg80211_del_key,
> + .set_default_key = iwm_cfg80211_set_default_key,
> + .get_station = iwm_cfg80211_get_station,
> + .scan = iwm_cfg80211_scan,
> + .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
> + .connect = iwm_cfg80211_connect,
> + .disconnect = iwm_cfg80211_disconnect,
> + .join_ibss = iwm_cfg80211_join_ibss,
> + .leave_ibss = iwm_cfg80211_leave_ibss,
> + .set_tx_power = iwm_cfg80211_set_txpower,
> + .get_tx_power = iwm_cfg80211_get_txpower,
> + .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
> +*/
> +};
> +
> +struct wireless_dev *lbs_wdev_alloc(int sizeof_priv, struct device *dev)
> +{
> + int ret = 0;
> + struct wireless_dev *wdev;
> +
> + wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
> + if (!wdev) {
> + dev_err(dev, "Couldn't allocate wireless device\n");
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + wdev->wiphy = wiphy_new(&lbs_cfg80211_ops,
> + sizeof(struct lbs_private) + sizeof_priv);
> + if (!wdev->wiphy) {
> + dev_err(dev, "Couldn't allocate wiphy device\n");
> + ret = -ENOMEM;
> + goto out_err_new;
> + }
> +
> + set_wiphy_dev(wdev->wiphy, dev);
> + wdev->wiphy->max_scan_ssids = 1; /* TODO */
> + wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
> + BIT(NL80211_IFTYPE_ADHOC);
> + wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz;
> + wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
> + wdev->wiphy->cipher_suites = cipher_suites;
> + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
> +
> + ret = wiphy_register(wdev->wiphy);
> + if (ret < 0) {
> + dev_err(dev, "Couldn't register wiphy device\n");
> + goto out_err_register;
> + }
> +
> + return wdev;
> +
> + out_err_register:
> + wiphy_free(wdev->wiphy);
> +
> + out_err_new:
> + kfree(wdev);
> +
> + return ERR_PTR(ret);
> +}
> +
> +
> +void lbs_wdev_free(struct lbs_private *lbs)
> +{
> + struct wireless_dev *wdev = lbs->wdev;
> +
> + if (!wdev)
> + return;
> +
> + wiphy_unregister(wdev->wiphy);
> + wiphy_free(wdev->wiphy);
> + kfree(wdev);
> +}
> Index: linux-wl/drivers/net/wireless/libertas/main.c
> ===================================================================
> --- linux-wl.orig/drivers/net/wireless/libertas/main.c 2009-09-28 12:06:02.000000000 +0200
> +++ linux-wl/drivers/net/wireless/libertas/main.c 2009-09-28 12:11:22.000000000 +0200
> @@ -14,11 +14,13 @@
> #include <linux/stddef.h>
> #include <linux/ieee80211.h>
> #include <net/iw_handler.h>
> +#include <net/cfg80211.h>
>
> #include "host.h"
> #include "decl.h"
> #include "dev.h"
> #include "wext.h"
> +#include "cfg.h"
> #include "debugfs.h"
> #include "scan.h"
> #include "assoc.h"
> @@ -1168,31 +1170,42 @@ static const struct net_device_ops lbs_n
> */
> struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
> {
> - struct net_device *dev = NULL;
> + struct net_device *dev;
> + struct wireless_dev *wdev;
> struct lbs_private *priv = NULL;
>
> lbs_deb_enter(LBS_DEB_MAIN);
>
> /* Allocate an Ethernet device and register it */
> - dev = alloc_etherdev(sizeof(struct lbs_private));
> - if (!dev) {
> + wdev = lbs_wdev_alloc(sizeof(struct lbs_private), dmdev);
> + if (IS_ERR(wdev)) {
> lbs_pr_err("init wlanX device failed\n");
> goto done;
> }
> - priv = netdev_priv(dev);
> - dev->ml_priv = priv;
> + /* TODO? */
> + wdev->iftype = NL80211_IFTYPE_STATION;
> + priv = wdev_priv(wdev);
> + priv->wdev = wdev;
>
> if (lbs_init_adapter(priv)) {
> lbs_pr_err("failed to initialize adapter structure.\n");
> - goto err_init_adapter;
> + goto err_wdev;
> + }
> +
> + //TODO? dev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
> + dev = alloc_netdev(0, "wlan%d", ether_setup);
> + if (!dev) {
> + dev_err(dmdev, "no memory for network device instance\n");
> + goto err_adapter;
> }
>
> + dev->netdev_ops = &lbs_netdev_ops;
> + dev->ieee80211_ptr = wdev;
> + dev->ml_priv = priv;
> + SET_NETDEV_DEV(dev, dmdev);
> + wdev->netdev = dev;
> priv->dev = dev;
> - priv->card = card;
> - priv->mesh_open = 0;
> - priv->infra_open = 0;
>
> - /* Setup the OS Interface to our functions */
> dev->netdev_ops = &lbs_netdev_ops;
> dev->watchdog_timeo = 5 * HZ;
> dev->ethtool_ops = &lbs_ethtool_ops;
> @@ -1201,7 +1214,14 @@ struct lbs_private *lbs_add_card(void *c
> #endif
> dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
>
> - SET_NETDEV_DEV(dev, dmdev);
> +
> + // TODO: kzalloc + iwm_init_default_profile(iwm, iwm->umac_profile); ??
> +
> +
> + priv->card = card;
> + priv->mesh_open = 0;
> + priv->infra_open = 0;
> +
>
> priv->rtap_net_dev = NULL;
> strcpy(dev->name, "wlan%d");
> @@ -1211,7 +1231,7 @@ struct lbs_private *lbs_add_card(void *c
> priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main");
> if (IS_ERR(priv->main_thread)) {
> lbs_deb_thread("Error creating main thread.\n");
> - goto err_init_adapter;
> + goto err_ndev;
> }
>
> priv->work_thread = create_singlethread_workqueue("lbs_worker");
> @@ -1228,9 +1248,15 @@ struct lbs_private *lbs_add_card(void *c
>
> goto done;
>
> -err_init_adapter:
> - lbs_free_adapter(priv);
> + err_ndev:
> free_netdev(dev);
> +
> + err_adapter:
> + lbs_free_adapter(priv);
> +
> + err_wdev:
> + lbs_wdev_free(priv);
> +
> priv = NULL;
>
> done:
> @@ -1277,6 +1303,7 @@ void lbs_remove_card(struct lbs_private
> kthread_stop(priv->main_thread);
>
> lbs_free_adapter(priv);
> + lbs_wdev_free(priv);
>
> priv->dev = NULL;
> free_netdev(dev);
>
^ permalink raw reply
* Re: [PATCH v2] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688
From: Dan Williams @ 2009-10-01 18:27 UTC (permalink / raw)
To: Bing Zhao; +Cc: libertas-dev, Amitkumar Karwar, linux-wireless
In-Reply-To: <1254366278-15483-1-git-send-email-bzhao@marvell.com>
On Wed, 2009-09-30 at 20:04 -0700, Bing Zhao wrote:
> From: Amitkumar Karwar <akarwar@marvell.com>
>
> Add timer based auto deep sleep feature in libertas driver which can be
> configured using iwconfig command. This is tested on SD8688, SD8686 cards
> with firmware versions 10.38.1.p25, 9.70.4.p0 respectively on 32-bit and 64-bit
> platforms. Tests have been done for USB/CS cards to make sure that the patch
> won't break USB/CS code. We didn't test the if_spi driver.
>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> Signed-off-by: Bing Zhao <bzhao@marvell.com>
Acked-by: Dan Williams <dcbw@redhat.com>
Though I wonder if we could just put the lbs_is_cmd_allowed() check into
the actual command handling routines instead of sprinkling it around.
We did move away from the 'one-huge-switch' command submission model,
which makes it a bit harder to gate commands based on device state, but
I can't think of anything off the top of my head that would hurt by
doing it like that.
i.e. would putting the check in both __lbs_cmd_async() and
lbs_prepare_and_send_command() around where the priv->surprise_removed
check is work too?
Dan
> ---
> drivers/net/wireless/libertas/README | 26 ++++-
> drivers/net/wireless/libertas/cmd.c | 72 ++++++++++++-
> drivers/net/wireless/libertas/cmdresp.c | 12 ++
> drivers/net/wireless/libertas/debugfs.c | 46 ++++++++
> drivers/net/wireless/libertas/decl.h | 4 +
> drivers/net/wireless/libertas/dev.h | 18 +++
> drivers/net/wireless/libertas/host.h | 1 +
> drivers/net/wireless/libertas/if_cs.c | 3 +
> drivers/net/wireless/libertas/if_sdio.c | 56 +++++++++
> drivers/net/wireless/libertas/if_sdio.h | 3 +-
> drivers/net/wireless/libertas/if_spi.c | 3 +
> drivers/net/wireless/libertas/if_usb.c | 3 +
> drivers/net/wireless/libertas/main.c | 111 ++++++++++++++++---
> drivers/net/wireless/libertas/scan.c | 11 ++
> drivers/net/wireless/libertas/wext.c | 185 ++++++++++++++++++++++++++++++-
> 15 files changed, 533 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README
> index ab6a2d5..635002d 100644
> --- a/drivers/net/wireless/libertas/README
> +++ b/drivers/net/wireless/libertas/README
> @@ -1,5 +1,5 @@
> ================================================================================
> - README for USB8388
> + README for Libertas
>
> (c) Copyright © 2003-2006, Marvell International Ltd.
> All Rights Reserved
> @@ -226,4 +226,28 @@ setuserscan
> All entries in the scan table (not just the new scan data when keep=1)
> will be displayed upon completion by use of the getscantable ioctl.
>
> +========================
> +IWCONFIG COMMANDS
> +========================
> +power period
> +
> + This command is used to configure the station in deep sleep mode /
> + auto deep sleep mode.
> +
> + The timer is implemented to monitor the activities (command, event,
> + etc.). When an activity is detected station will exit from deep
> + sleep mode automatically and restart the timer. At timer expiry
> + (no activity for defined time period) the deep sleep mode is entered
> + automatically.
> +
> + Note: this command is for SDIO interface only.
> +
> + Usage:
> + To enable deep sleep mode do:
> + iwconfig wlan0 power period 0
> + To enable auto deep sleep mode with idle time period 5 seconds do:
> + iwconfig wlan0 power period 5
> + To disable deep sleep/auto deep sleep mode do:
> + iwconfig wlan0 power period -1
> +
> ==============================================================================
> diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
> index 6850981..3a3e894 100644
> --- a/drivers/net/wireless/libertas/cmd.c
> +++ b/drivers/net/wireless/libertas/cmd.c
> @@ -17,7 +17,6 @@
>
> static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
>
> -
> /**
> * @brief Simple callback that copies response back into command
> *
> @@ -319,6 +318,60 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
> return 0;
> }
>
> +static int lbs_wait_for_ds_awake(struct lbs_private *priv)
> +{
> + int ret = 0;
> +
> + lbs_deb_enter(LBS_DEB_CMD);
> +
> + if (priv->is_deep_sleep) {
> + if (!wait_event_interruptible_timeout(priv->ds_awake_q,
> + !priv->is_deep_sleep, (10 * HZ))) {
> + lbs_pr_err("ds_awake_q: timer expired\n");
> + ret = -1;
> + }
> + }
> +
> + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
> + return ret;
> +}
> +
> +int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
> +{
> + int ret = 0;
> +
> + lbs_deb_enter(LBS_DEB_CMD);
> +
> + if (deep_sleep) {
> + if (priv->is_deep_sleep != 1) {
> + lbs_deb_cmd("deep sleep: sleep\n");
> + BUG_ON(!priv->enter_deep_sleep);
> + ret = priv->enter_deep_sleep(priv);
> + if (!ret) {
> + netif_stop_queue(priv->dev);
> + netif_carrier_off(priv->dev);
> + }
> + } else {
> + lbs_pr_err("deep sleep: already enabled\n");
> + }
> + } else {
> + if (priv->is_deep_sleep) {
> + lbs_deb_cmd("deep sleep: wakeup\n");
> + BUG_ON(!priv->exit_deep_sleep);
> + ret = priv->exit_deep_sleep(priv);
> + if (!ret) {
> + ret = lbs_wait_for_ds_awake(priv);
> + if (ret)
> + lbs_pr_err("deep sleep: wakeup"
> + "failed\n");
> + }
> + }
> + }
> +
> + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
> + return ret;
> +}
> +
> int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
> struct assoc_request *assoc)
> {
> @@ -1242,8 +1295,17 @@ static void lbs_submit_command(struct lbs_private *priv,
> timeo = HZ/4;
> }
>
> - /* Setup the timer after transmit command */
> - mod_timer(&priv->command_timer, jiffies + timeo);
> + if (command == CMD_802_11_DEEP_SLEEP) {
> + if (priv->is_auto_deep_sleep_enabled) {
> + priv->wakeup_dev_required = 1;
> + priv->dnld_sent = 0;
> + }
> + priv->is_deep_sleep = 1;
> + lbs_complete_command(priv, cmdnode, 0);
> + } else {
> + /* Setup the timer after transmit command */
> + mod_timer(&priv->command_timer, jiffies + timeo);
> + }
>
> lbs_deb_leave(LBS_DEB_HOST);
> }
> @@ -1505,6 +1567,10 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
> case CMD_802_11_BEACON_CTRL:
> ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
> break;
> + case CMD_802_11_DEEP_SLEEP:
> + cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP);
> + cmdptr->size = cpu_to_le16(S_DS_GEN);
> + break;
> default:
> lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
> ret = -1;
> diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
> index c42d3fa..47d2b19 100644
> --- a/drivers/net/wireless/libertas/cmdresp.c
> +++ b/drivers/net/wireless/libertas/cmdresp.c
> @@ -504,9 +504,21 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
>
> case MACREG_INT_CODE_HOST_AWAKE:
> lbs_deb_cmd("EVENT: host awake\n");
> + if (priv->reset_deep_sleep_wakeup)
> + priv->reset_deep_sleep_wakeup(priv);
> + priv->is_deep_sleep = 0;
> lbs_send_confirmwake(priv);
> break;
>
> + case MACREG_INT_CODE_DEEP_SLEEP_AWAKE:
> + if (priv->reset_deep_sleep_wakeup)
> + priv->reset_deep_sleep_wakeup(priv);
> + lbs_deb_cmd("EVENT: ds awake\n");
> + priv->is_deep_sleep = 0;
> + priv->wakeup_dev_required = 0;
> + wake_up_interruptible(&priv->ds_awake_q);
> + break;
> +
> case MACREG_INT_CODE_PS_AWAKE:
> lbs_deb_cmd("EVENT: ps awake\n");
> /* handle unexpected PS AWAKE event */
> diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
> index 893a55c..8a7e931 100644
> --- a/drivers/net/wireless/libertas/debugfs.c
> +++ b/drivers/net/wireless/libertas/debugfs.c
> @@ -117,6 +117,11 @@ static ssize_t lbs_sleepparams_write(struct file *file,
> if (!buf)
> return -ENOMEM;
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + goto out_unlock;
> + }
> +
> buf_size = min(count, len - 1);
> if (copy_from_user(buf, user_buf, buf_size)) {
> ret = -EFAULT;
> @@ -157,6 +162,11 @@ static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf,
> if (!buf)
> return -ENOMEM;
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + goto out_unlock;
> + }
> +
> ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp);
> if (ret)
> goto out_unlock;
> @@ -223,6 +233,9 @@ static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask,
> u8 freq;
> int events = 0;
>
> + if (!lbs_is_cmd_allowed(priv))
> + return -EBUSY;
> +
> buf = (char *)get_zeroed_page(GFP_KERNEL);
> if (!buf)
> return -ENOMEM;
> @@ -275,6 +288,9 @@ static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
> char *buf;
> int ret;
>
> + if (!lbs_is_cmd_allowed(priv))
> + return -EBUSY;
> +
> buf = (char *)get_zeroed_page(GFP_KERNEL);
> if (!buf)
> return -ENOMEM;
> @@ -444,6 +460,11 @@ static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
> if (!buf)
> return -ENOMEM;
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + free_page(addr);
> + return -EBUSY;
> + }
> +
> offval.offset = priv->mac_offset;
> offval.value = 0;
>
> @@ -496,6 +517,11 @@ static ssize_t lbs_wrmac_write(struct file *file,
> if (!buf)
> return -ENOMEM;
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + res = -EBUSY;
> + goto out_unlock;
> + }
> +
> buf_size = min(count, len - 1);
> if (copy_from_user(buf, userbuf, buf_size)) {
> res = -EFAULT;
> @@ -532,6 +558,11 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
> if (!buf)
> return -ENOMEM;
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + free_page(addr);
> + return -EBUSY;
> + }
> +
> offval.offset = priv->bbp_offset;
> offval.value = 0;
>
> @@ -585,6 +616,11 @@ static ssize_t lbs_wrbbp_write(struct file *file,
> if (!buf)
> return -ENOMEM;
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + res = -EBUSY;
> + goto out_unlock;
> + }
> +
> buf_size = min(count, len - 1);
> if (copy_from_user(buf, userbuf, buf_size)) {
> res = -EFAULT;
> @@ -621,6 +657,11 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
> if (!buf)
> return -ENOMEM;
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + free_page(addr);
> + return -EBUSY;
> + }
> +
> offval.offset = priv->rf_offset;
> offval.value = 0;
>
> @@ -674,6 +715,11 @@ static ssize_t lbs_wrrf_write(struct file *file,
> if (!buf)
> return -ENOMEM;
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + res = -EBUSY;
> + goto out_unlock;
> + }
> +
> buf_size = min(count, len - 1);
> if (copy_from_user(buf, userbuf, buf_size)) {
> res = -EFAULT;
> diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
> index 0b84bdc..34b475f 100644
> --- a/drivers/net/wireless/libertas/decl.h
> +++ b/drivers/net/wireless/libertas/decl.h
> @@ -33,6 +33,10 @@ int lbs_execute_next_command(struct lbs_private *priv);
> int lbs_process_event(struct lbs_private *priv, u32 event);
> void lbs_queue_event(struct lbs_private *priv, u32 event);
> void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
> +int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep);
> +int lbs_is_cmd_allowed(struct lbs_private *priv);
> +int lbs_enter_auto_deep_sleep(struct lbs_private *priv);
> +int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
>
> u32 lbs_fw_index_to_data_rate(u8 index);
> u8 lbs_data_rate_to_fw_index(u32 rate);
> diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
> index 578c697..e2b4ef2 100644
> --- a/drivers/net/wireless/libertas/dev.h
> +++ b/drivers/net/wireless/libertas/dev.h
> @@ -129,6 +129,20 @@ struct lbs_private {
> u32 bbp_offset;
> u32 rf_offset;
>
> + /** Deep sleep flag */
> + int is_deep_sleep;
> + /** Auto deep sleep enabled flag */
> + int is_auto_deep_sleep_enabled;
> + /** Device wakeup required flag */
> + int wakeup_dev_required;
> + /** Auto deep sleep flag*/
> + int is_activity_detected;
> + /** Auto deep sleep timeout (in miliseconds) */
> + int auto_deep_sleep_timeout;
> +
> + /** Deep sleep wait queue */
> + wait_queue_head_t ds_awake_q;
> +
> /* Download sent:
> bit0 1/0=data_sent/data_tx_done,
> bit1 1/0=cmd_sent/cmd_tx_done,
> @@ -154,6 +168,9 @@ struct lbs_private {
> /** Hardware access */
> int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
> void (*reset_card) (struct lbs_private *priv);
> + int (*enter_deep_sleep) (struct lbs_private *priv);
> + int (*exit_deep_sleep) (struct lbs_private *priv);
> + int (*reset_deep_sleep_wakeup) (struct lbs_private *priv);
>
> /* Wake On LAN */
> uint32_t wol_criteria;
> @@ -204,6 +221,7 @@ struct lbs_private {
>
> /** Timers */
> struct timer_list command_timer;
> + struct timer_list auto_deepsleep_timer;
> int nr_retries;
> int cmd_timed_out;
>
> diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
> index fe8f0cb..c055daa 100644
> --- a/drivers/net/wireless/libertas/host.h
> +++ b/drivers/net/wireless/libertas/host.h
> @@ -57,6 +57,7 @@
> #define CMD_802_11_ENABLE_RSN 0x002f
> #define CMD_802_11_SET_AFC 0x003c
> #define CMD_802_11_GET_AFC 0x003d
> +#define CMD_802_11_DEEP_SLEEP 0x003e
> #define CMD_802_11_AD_HOC_STOP 0x0040
> #define CMD_802_11_HOST_SLEEP_CFG 0x0043
> #define CMD_802_11_WAKEUP_CONFIRM 0x0044
> diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
> index 6238176..465742f 100644
> --- a/drivers/net/wireless/libertas/if_cs.c
> +++ b/drivers/net/wireless/libertas/if_cs.c
> @@ -946,6 +946,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
> card->priv = priv;
> priv->card = card;
> priv->hw_host_to_card = if_cs_host_to_card;
> + priv->enter_deep_sleep = NULL;
> + priv->exit_deep_sleep = NULL;
> + priv->reset_deep_sleep_wakeup = NULL;
> priv->fw_ready = 1;
>
> /* Now actually get the IRQ */
> diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
> index 485a8d4..9716728 100644
> --- a/drivers/net/wireless/libertas/if_sdio.c
> +++ b/drivers/net/wireless/libertas/if_sdio.c
> @@ -831,6 +831,58 @@ out:
> return ret;
> }
>
> +static int if_sdio_enter_deep_sleep(struct lbs_private *priv)
> +{
> + int ret = -1;
> + struct cmd_header cmd;
> +
> + memset(&cmd, 0, sizeof(cmd));
> +
> + lbs_deb_sdio("send DEEP_SLEEP command\n");
> + ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd),
> + lbs_cmd_copyback, (unsigned long) &cmd);
> + if (ret)
> + lbs_pr_err("DEEP_SLEEP cmd failed\n");
> +
> + mdelay(200);
> + return ret;
> +}
> +
> +static int if_sdio_exit_deep_sleep(struct lbs_private *priv)
> +{
> + struct if_sdio_card *card = priv->card;
> + int ret = -1;
> +
> + lbs_deb_enter(LBS_DEB_SDIO);
> + sdio_claim_host(card->func);
> +
> + sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
> + if (ret)
> + lbs_pr_err("sdio_writeb failed!\n");
> +
> + sdio_release_host(card->func);
> + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
> + return ret;
> +}
> +
> +static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)
> +{
> + struct if_sdio_card *card = priv->card;
> + int ret = -1;
> +
> + lbs_deb_enter(LBS_DEB_SDIO);
> + sdio_claim_host(card->func);
> +
> + sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret);
> + if (ret)
> + lbs_pr_err("sdio_writeb failed!\n");
> +
> + sdio_release_host(card->func);
> + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
> + return ret;
> +
> +}
> +
> /*******************************************************************/
> /* SDIO callbacks */
> /*******************************************************************/
> @@ -859,6 +911,7 @@ static void if_sdio_interrupt(struct sdio_func *func)
> * Ignore the define name, this really means the card has
> * successfully received the command.
> */
> + card->priv->is_activity_detected = 1;
> if (cause & IF_SDIO_H_INT_DNLD)
> lbs_host_to_card_done(card->priv);
>
> @@ -998,6 +1051,9 @@ static int if_sdio_probe(struct sdio_func *func,
>
> priv->card = card;
> priv->hw_host_to_card = if_sdio_host_to_card;
> + priv->enter_deep_sleep = if_sdio_enter_deep_sleep;
> + priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
> + priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
>
> priv->fw_ready = 1;
>
> diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h
> index 60c9b2f..12179c1 100644
> --- a/drivers/net/wireless/libertas/if_sdio.h
> +++ b/drivers/net/wireless/libertas/if_sdio.h
> @@ -51,5 +51,6 @@
> #define IF_SDIO_EVENT 0x80fc
>
> #define IF_SDIO_BLOCK_SIZE 256
> -
> +#define CONFIGURATION_REG 0x03
> +#define HOST_POWER_UP (0x1U << 1)
> #endif
> diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
> index 446e327..e2fa657 100644
> --- a/drivers/net/wireless/libertas/if_spi.c
> +++ b/drivers/net/wireless/libertas/if_spi.c
> @@ -1117,6 +1117,9 @@ static int __devinit if_spi_probe(struct spi_device *spi)
> card->priv = priv;
> priv->card = card;
> priv->hw_host_to_card = if_spi_host_to_card;
> + priv->enter_deep_sleep = NULL;
> + priv->exit_deep_sleep = NULL;
> + priv->reset_deep_sleep_wakeup = NULL;
> priv->fw_ready = 1;
>
> /* Initialize interrupt handling stuff. */
> diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
> index 92bc8c5..a8262de 100644
> --- a/drivers/net/wireless/libertas/if_usb.c
> +++ b/drivers/net/wireless/libertas/if_usb.c
> @@ -300,6 +300,9 @@ static int if_usb_probe(struct usb_interface *intf,
> cardp->priv->fw_ready = 1;
>
> priv->hw_host_to_card = if_usb_host_to_card;
> + priv->enter_deep_sleep = NULL;
> + priv->exit_deep_sleep = NULL;
> + priv->reset_deep_sleep_wakeup = NULL;
> #ifdef CONFIG_OLPC
> if (machine_is_olpc())
> priv->reset_card = if_usb_reset_olpc_card;
> diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
> index 8df1cfd..3b14fcc 100644
> --- a/drivers/net/wireless/libertas/main.c
> +++ b/drivers/net/wireless/libertas/main.c
> @@ -574,8 +574,10 @@ void lbs_host_to_card_done(struct lbs_private *priv)
> priv->dnld_sent = DNLD_RES_RECEIVED;
>
> /* Wake main thread if commands are pending */
> - if (!priv->cur_cmd || priv->tx_pending_len > 0)
> - wake_up_interruptible(&priv->waitq);
> + if (!priv->cur_cmd || priv->tx_pending_len > 0) {
> + if (!priv->wakeup_dev_required)
> + wake_up_interruptible(&priv->waitq);
> + }
>
> spin_unlock_irqrestore(&priv->driver_lock, flags);
> lbs_deb_leave(LBS_DEB_THREAD);
> @@ -770,7 +772,8 @@ static int lbs_thread(void *data)
> shouldsleep = 0; /* We have a command response */
> else if (priv->cur_cmd)
> shouldsleep = 1; /* Can't send a command; one already running */
> - else if (!list_empty(&priv->cmdpendingq))
> + else if (!list_empty(&priv->cmdpendingq) &&
> + !(priv->wakeup_dev_required))
> shouldsleep = 0; /* We have a command to send */
> else if (__kfifo_len(priv->event_fifo))
> shouldsleep = 0; /* We have an event to process */
> @@ -822,6 +825,26 @@ static int lbs_thread(void *data)
> }
> spin_unlock_irq(&priv->driver_lock);
>
> + /* Process hardware events, e.g. card removed, link lost */
> + spin_lock_irq(&priv->driver_lock);
> + while (__kfifo_len(priv->event_fifo)) {
> + u32 event;
> + __kfifo_get(priv->event_fifo, (unsigned char *) &event,
> + sizeof(event));
> + spin_unlock_irq(&priv->driver_lock);
> + lbs_process_event(priv, event);
> + spin_lock_irq(&priv->driver_lock);
> + }
> + spin_unlock_irq(&priv->driver_lock);
> +
> + if (priv->wakeup_dev_required) {
> + lbs_deb_thread("Waking up device...\n");
> + /* Wake up device */
> + if (priv->exit_deep_sleep(priv))
> + lbs_deb_thread("Wakeup device failed\n");
> + continue;
> + }
> +
> /* command timeout stuff */
> if (priv->cmd_timed_out && priv->cur_cmd) {
> struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
> @@ -849,18 +872,7 @@ static int lbs_thread(void *data)
> }
> priv->cmd_timed_out = 0;
>
> - /* Process hardware events, e.g. card removed, link lost */
> - spin_lock_irq(&priv->driver_lock);
> - while (__kfifo_len(priv->event_fifo)) {
> - u32 event;
>
> - __kfifo_get(priv->event_fifo, (unsigned char *) &event,
> - sizeof(event));
> - spin_unlock_irq(&priv->driver_lock);
> - lbs_process_event(priv, event);
> - spin_lock_irq(&priv->driver_lock);
> - }
> - spin_unlock_irq(&priv->driver_lock);
>
> if (!priv->fw_ready)
> continue;
> @@ -894,6 +906,9 @@ static int lbs_thread(void *data)
> (priv->psstate == PS_STATE_PRE_SLEEP))
> continue;
>
> + if (priv->is_deep_sleep)
> + continue;
> +
> /* Execute the next command */
> if (!priv->dnld_sent && !priv->cur_cmd)
> lbs_execute_next_command(priv);
> @@ -928,6 +943,7 @@ static int lbs_thread(void *data)
> }
>
> del_timer(&priv->command_timer);
> + del_timer(&priv->auto_deepsleep_timer);
> wake_up_all(&priv->cmd_pending);
>
> lbs_deb_leave(LBS_DEB_THREAD);
> @@ -1050,6 +1066,60 @@ out:
> lbs_deb_leave(LBS_DEB_CMD);
> }
>
> +/**
> + * This function put the device back to deep sleep mode when timer expires
> + * and no activity (command, event, data etc.) is detected.
> + */
> +static void auto_deepsleep_timer_fn(unsigned long data)
> +{
> + struct lbs_private *priv = (struct lbs_private *)data;
> + int ret;
> +
> + lbs_deb_enter(LBS_DEB_CMD);
> +
> + if (priv->is_activity_detected) {
> + priv->is_activity_detected = 0;
> + } else {
> + if (priv->is_auto_deep_sleep_enabled &&
> + (!priv->wakeup_dev_required) &&
> + (priv->connect_status != LBS_CONNECTED)) {
> + lbs_deb_main("Entering auto deep sleep mode...\n");
> + ret = lbs_prepare_and_send_command(priv,
> + CMD_802_11_DEEP_SLEEP, 0,
> + 0, 0, NULL);
> + }
> + }
> + mod_timer(&priv->auto_deepsleep_timer , jiffies +
> + (priv->auto_deep_sleep_timeout * HZ)/1000);
> + lbs_deb_leave(LBS_DEB_CMD);
> +}
> +
> +int lbs_enter_auto_deep_sleep(struct lbs_private *priv)
> +{
> + lbs_deb_enter(LBS_DEB_SDIO);
> +
> + priv->is_auto_deep_sleep_enabled = 1;
> + if (priv->is_deep_sleep)
> + priv->wakeup_dev_required = 1;
> + mod_timer(&priv->auto_deepsleep_timer ,
> + jiffies + (priv->auto_deep_sleep_timeout * HZ)/1000);
> +
> + lbs_deb_leave(LBS_DEB_SDIO);
> + return 0;
> +}
> +
> +int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
> +{
> + lbs_deb_enter(LBS_DEB_SDIO);
> +
> + priv->is_auto_deep_sleep_enabled = 0;
> + priv->auto_deep_sleep_timeout = 0;
> + del_timer(&priv->auto_deepsleep_timer);
> +
> + lbs_deb_leave(LBS_DEB_SDIO);
> + return 0;
> +}
> +
> static void lbs_sync_channel_worker(struct work_struct *work)
> {
> struct lbs_private *priv = container_of(work, struct lbs_private,
> @@ -1099,11 +1169,17 @@ static int lbs_init_adapter(struct lbs_private *priv)
> priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
> priv->psmode = LBS802_11POWERMODECAM;
> priv->psstate = PS_STATE_FULL_POWER;
> + priv->is_deep_sleep = 0;
> + priv->is_auto_deep_sleep_enabled = 0;
> + priv->wakeup_dev_required = 0;
> + init_waitqueue_head(&priv->ds_awake_q);
>
> mutex_init(&priv->lock);
>
> setup_timer(&priv->command_timer, command_timer_fn,
> (unsigned long)priv);
> + setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn,
> + (unsigned long)priv);
>
> INIT_LIST_HEAD(&priv->cmdfreeq);
> INIT_LIST_HEAD(&priv->cmdpendingq);
> @@ -1142,6 +1218,7 @@ static void lbs_free_adapter(struct lbs_private *priv)
> if (priv->event_fifo)
> kfifo_free(priv->event_fifo);
> del_timer(&priv->command_timer);
> + del_timer(&priv->auto_deepsleep_timer);
> kfree(priv->networks);
> priv->networks = NULL;
>
> @@ -1272,6 +1349,11 @@ void lbs_remove_card(struct lbs_private *priv)
> wrqu.ap_addr.sa_family = ARPHRD_ETHER;
> wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
>
> + if (priv->is_deep_sleep) {
> + priv->is_deep_sleep = 0;
> + wake_up_interruptible(&priv->ds_awake_q);
> + }
> +
> /* Stop the thread servicing the interrupts */
> priv->surpriseremoved = 1;
> kthread_stop(priv->main_thread);
> @@ -1392,6 +1474,7 @@ void lbs_stop_card(struct lbs_private *priv)
>
> /* Delete the timeout of the currently processing command */
> del_timer_sync(&priv->command_timer);
> + del_timer_sync(&priv->auto_deepsleep_timer);
>
> /* Flush pending command nodes */
> spin_lock_irqsave(&priv->driver_lock, flags);
> diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
> index 6c95af3..e468e15 100644
> --- a/drivers/net/wireless/libertas/scan.c
> +++ b/drivers/net/wireless/libertas/scan.c
> @@ -950,6 +950,11 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + goto out;
> + }
> +
> if (!priv->radio_on) {
> ret = -EINVAL;
> goto out;
> @@ -1017,6 +1022,12 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + err = -EBUSY;
> + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
> + return err;
> + }
> +
> /* iwlist should wait until the current scan is finished */
> if (priv->scan_channel)
> return -EAGAIN;
> diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
> index be837a0..38a451e 100644
> --- a/drivers/net/wireless/libertas/wext.c
> +++ b/drivers/net/wireless/libertas/wext.c
> @@ -45,6 +45,31 @@ static inline void lbs_cancel_association_work(struct lbs_private *priv)
> priv->pending_assoc_req = NULL;
> }
>
> +/**
> + * @brief This function checks if the command is allowed.
> + *
> + * @param priv A pointer to lbs_private structure
> + * @return allowed or not allowed.
> + */
> +
> +int lbs_is_cmd_allowed(struct lbs_private *priv)
> +{
> + int ret = 1;
> +
> + lbs_deb_enter(LBS_DEB_WEXT);
> +
> + if (!priv->is_auto_deep_sleep_enabled) {
> + if (priv->is_deep_sleep) {
> + lbs_deb_wext("IOCTLS called when station"
> + "is in deep sleep\n");
> + ret = 0;
> + }
> + }
> +
> + lbs_deb_leave(LBS_DEB_WEXT);
> + return ret;
> +}
> +
>
> /**
> * @brief Find the channel frequency power info with specific channel
> @@ -168,6 +193,11 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + lbs_deb_leave(LBS_DEB_WEXT);
> + return -EBUSY;
> + }
> +
> cfp = lbs_find_cfp_by_band_and_channel(priv, 0,
> priv->curbssparams.channel);
>
> @@ -278,6 +308,12 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> + return ret;
> + }
> +
> if (vwrq->disabled)
> val = MRVDRV_RTS_MAX_VALUE;
>
> @@ -299,6 +335,11 @@ static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + goto out;
> + }
> +
> ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val);
> if (ret)
> goto out;
> @@ -321,6 +362,12 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> + return ret;
> + }
> +
> if (vwrq->disabled)
> val = MRVDRV_FRAG_MAX_VALUE;
>
> @@ -342,6 +389,11 @@ static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + goto out;
> + }
> +
> ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val);
> if (ret)
> goto out;
> @@ -391,6 +443,11 @@ static int lbs_get_txpow(struct net_device *dev,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + goto out;
> + }
> +
> if (!priv->radio_on) {
> lbs_deb_wext("tx power off\n");
> vwrq->value = 0;
> @@ -424,6 +481,11 @@ static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + goto out;
> + }
> +
> if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
> return -EOPNOTSUPP;
>
> @@ -472,6 +534,11 @@ static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + goto out;
> + }
> +
> vwrq->disabled = 0;
>
> if (vwrq->flags & IW_RETRY_LONG) {
> @@ -709,6 +776,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
> struct iw_param *vwrq, char *extra)
> {
> struct lbs_private *priv = dev->ml_priv;
> + int ret = 0;
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> @@ -737,8 +805,54 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
> "setting power timeout is not supported\n");
> return -EINVAL;
> } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
> - lbs_deb_wext("setting power period not supported\n");
> - return -EINVAL;
> + vwrq->value = vwrq->value / 1000;
> + if (!priv->enter_deep_sleep) {
> + lbs_pr_err("deep sleep feature is not implemented "
> + "for this interface driver\n");
> + return -EINVAL;
> + }
> +
> + if (priv->connect_status == LBS_CONNECTED) {
> + if ((priv->is_auto_deep_sleep_enabled) &&
> + (vwrq->value == -1000)) {
> + lbs_exit_auto_deep_sleep(priv);
> + return 0;
> + } else {
> + lbs_pr_err("can't use deep sleep cmd in "
> + "connected state\n");
> + return -EINVAL;
> + }
> + }
> +
> + if ((vwrq->value < 0) && (vwrq->value != -1000)) {
> + lbs_pr_err("unknown option\n");
> + return -EINVAL;
> + }
> +
> + if (vwrq->value > 0) {
> + if (!priv->is_auto_deep_sleep_enabled) {
> + priv->is_activity_detected = 0;
> + priv->auto_deep_sleep_timeout = vwrq->value;
> + lbs_enter_auto_deep_sleep(priv);
> + } else {
> + priv->auto_deep_sleep_timeout = vwrq->value;
> + lbs_deb_debugfs("auto deep sleep: "
> + "already enabled\n");
> + }
> + return 0;
> + } else {
> + if (priv->is_auto_deep_sleep_enabled) {
> + lbs_exit_auto_deep_sleep(priv);
> + /* Try to exit deep sleep if auto */
> + /*deep sleep disabled */
> + ret = lbs_set_deep_sleep(priv, 0);
> + }
> + if (vwrq->value == 0)
> + ret = lbs_set_deep_sleep(priv, 1);
> + else if (vwrq->value == -1000)
> + ret = lbs_set_deep_sleep(priv, 0);
> + return ret;
> + }
> }
>
> if (priv->psmode != LBS802_11POWERMODECAM) {
> @@ -752,6 +866,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
> }
>
> lbs_deb_leave(LBS_DEB_WEXT);
> +
> return 0;
> }
>
> @@ -792,6 +907,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv))
> + return NULL;
> +
> priv->wstats.status = priv->mode;
>
> /* If we're not associated, all quality values are meaningless */
> @@ -892,6 +1010,12 @@ static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> + return ret;
> + }
> +
> mutex_lock(&priv->lock);
> assoc_req = lbs_get_association_request(priv);
> if (!assoc_req) {
> @@ -1000,6 +1124,12 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
> u8 rates[MAX_RATES + 1];
>
> lbs_deb_enter(LBS_DEB_WEXT);
> +
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + goto out;
> + }
> +
> lbs_deb_wext("vwrq->value %d\n", vwrq->value);
> lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed);
>
> @@ -1058,6 +1188,11 @@ static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + lbs_deb_leave(LBS_DEB_WEXT);
> + return -EBUSY;
> + }
> +
> if (priv->connect_status == LBS_CONNECTED) {
> vwrq->value = priv->cur_rate * 500000;
>
> @@ -1084,6 +1219,11 @@ static int lbs_set_mode(struct net_device *dev,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + goto out;
> + }
> +
> if ( (*uwrq != IW_MODE_ADHOC)
> && (*uwrq != IW_MODE_INFRA)
> && (*uwrq != IW_MODE_AUTO)) {
> @@ -1325,6 +1465,12 @@ static int lbs_set_encode(struct net_device *dev,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> + return ret;
> + }
> +
> mutex_lock(&priv->lock);
> assoc_req = lbs_get_association_request(priv);
> if (!assoc_req) {
> @@ -1508,6 +1654,12 @@ static int lbs_set_encodeext(struct net_device *dev,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> + return ret;
> + }
> +
> mutex_lock(&priv->lock);
> assoc_req = lbs_get_association_request(priv);
> if (!assoc_req) {
> @@ -1720,6 +1872,12 @@ static int lbs_set_auth(struct net_device *dev,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> + return ret;
> + }
> +
> mutex_lock(&priv->lock);
> assoc_req = lbs_get_association_request(priv);
> if (!assoc_req) {
> @@ -1822,6 +1980,12 @@ static int lbs_get_auth(struct net_device *dev,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> + return ret;
> + }
> +
> switch (dwrq->flags & IW_AUTH_INDEX) {
> case IW_AUTH_KEY_MGMT:
> dwrq->value = priv->secinfo.key_mgmt;
> @@ -1864,6 +2028,11 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + goto out;
> + }
> +
> if (vwrq->disabled) {
> lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0);
> goto out;
> @@ -1983,6 +2152,12 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> + return ret;
> + }
> +
> if (!priv->radio_on) {
> ret = -EINVAL;
> goto out;
> @@ -2110,6 +2285,12 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
>
> lbs_deb_enter(LBS_DEB_WEXT);
>
> + if (!lbs_is_cmd_allowed(priv)) {
> + ret = -EBUSY;
> + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
> + return ret;
> + }
> +
> if (!priv->radio_on)
> return -EINVAL;
>
> _______________________________________________
> libertas-dev mailing list
> libertas-dev@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev
^ permalink raw reply
* pull request: wireless-2.6 2009-10-01
From: John W. Linville @ 2009-10-01 18:24 UTC (permalink / raw)
To: davem; +Cc: linux-wireless, netdev, linux-kernel
Dave,
A small collection of fixes for 2.6.32...
One is a brown paper bag fix for an uninitialized variable, another is a
USB ID. There is a beaconing fix for the mac80211_hwsim "fake" driver,
and a bug fix for AP mode related to buffering frames for stations in
power save mode.
The b43 fix looks a bit long, but it is more-or-less the same simple
fix applied in multiple places. It addresses a bug where "the last
bytes of data sent/received to/from PIO FIFOs on SDIO-based cards get
'swizzled' when its length is not multiple of 4 bytes."
Please let me know if there are problems!
Thanks,
John
---
Individual patches are available here:
http://www.kernel.org/pub/linux/kernel/people/linville/wireless-2.6/
---
The following changes since commit eb1cf0f8f7a9e5a6d573d5bd72c015686a042db0:
David S. Miller (1):
Merge branch 'master' of ssh://master.kernel.org/.../linville/wireless-2.6
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git master
Christian Lamparter (1):
ar9170: fix bug in iq-auto calibration value calculation
Igor Perminov (1):
mac80211: Fix [re]association power saving issue on AP side
Jouni Malinen (1):
mac80211_hwsim: Fix initial beacon timer configuration
Michael Buesch (1):
b43: Always use block-I/O for the PIO data registers
Michal Szalata (1):
rt2x00: Thrustmaster FunAccess WIFI USB and rt73usb
drivers/net/wireless/ath/ar9170/phy.c | 6 +--
drivers/net/wireless/b43/pio.c | 60 +++++++++++++++++++++------------
drivers/net/wireless/mac80211_hwsim.c | 3 ++
drivers/net/wireless/rt2x00/rt73usb.c | 1 +
net/mac80211/tx.c | 5 ++-
5 files changed, 48 insertions(+), 27 deletions(-)
diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c
index b3e5cf3..dbd488d 100644
--- a/drivers/net/wireless/ath/ar9170/phy.c
+++ b/drivers/net/wireless/ath/ar9170/phy.c
@@ -1141,7 +1141,8 @@ static int ar9170_set_freq_cal_data(struct ar9170 *ar,
u8 vpds[2][AR5416_PD_GAIN_ICEPTS];
u8 pwrs[2][AR5416_PD_GAIN_ICEPTS];
int chain, idx, i;
- u8 f;
+ u32 phy_data = 0;
+ u8 f, tmp;
switch (channel->band) {
case IEEE80211_BAND_2GHZ:
@@ -1208,9 +1209,6 @@ static int ar9170_set_freq_cal_data(struct ar9170 *ar,
}
for (i = 0; i < 76; i++) {
- u32 phy_data;
- u8 tmp;
-
if (i < 25) {
tmp = ar9170_interpolate_val(i, &pwrs[0][0],
&vpds[0][0]);
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index e96091b..9c13979 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -340,10 +340,15 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
q->mmio_base + B43_PIO_TXDATA,
sizeof(u16));
if (data_len & 1) {
+ u8 tail[2] = { 0, };
+
/* Write the last byte. */
ctl &= ~B43_PIO_TXCTL_WRITEHI;
b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
- b43_piotx_write16(q, B43_PIO_TXDATA, data[data_len - 1]);
+ tail[0] = data[data_len - 1];
+ ssb_block_write(dev->dev, tail, 2,
+ q->mmio_base + B43_PIO_TXDATA,
+ sizeof(u16));
}
return ctl;
@@ -386,26 +391,31 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
q->mmio_base + B43_PIO8_TXDATA,
sizeof(u32));
if (data_len & 3) {
- u32 value = 0;
+ u8 tail[4] = { 0, };
/* Write the last few bytes. */
ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
B43_PIO8_TXCTL_24_31);
- data = &(data[data_len - 1]);
switch (data_len & 3) {
case 3:
- ctl |= B43_PIO8_TXCTL_16_23;
- value |= (u32)(*data) << 16;
- data--;
+ ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
+ tail[0] = data[data_len - 3];
+ tail[1] = data[data_len - 2];
+ tail[2] = data[data_len - 1];
+ break;
case 2:
ctl |= B43_PIO8_TXCTL_8_15;
- value |= (u32)(*data) << 8;
- data--;
+ tail[0] = data[data_len - 2];
+ tail[1] = data[data_len - 1];
+ break;
case 1:
- value |= (u32)(*data);
+ tail[0] = data[data_len - 1];
+ break;
}
b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
- b43_piotx_write32(q, B43_PIO8_TXDATA, value);
+ ssb_block_write(dev->dev, tail, 4,
+ q->mmio_base + B43_PIO8_TXDATA,
+ sizeof(u32));
}
return ctl;
@@ -693,21 +703,25 @@ data_ready:
q->mmio_base + B43_PIO8_RXDATA,
sizeof(u32));
if (len & 3) {
- u32 value;
- char *data;
+ u8 tail[4] = { 0, };
/* Read the last few bytes. */
- value = b43_piorx_read32(q, B43_PIO8_RXDATA);
- data = &(skb->data[len + padding - 1]);
+ ssb_block_read(dev->dev, tail, 4,
+ q->mmio_base + B43_PIO8_RXDATA,
+ sizeof(u32));
switch (len & 3) {
case 3:
- *data = (value >> 16);
- data--;
+ skb->data[len + padding - 3] = tail[0];
+ skb->data[len + padding - 2] = tail[1];
+ skb->data[len + padding - 1] = tail[2];
+ break;
case 2:
- *data = (value >> 8);
- data--;
+ skb->data[len + padding - 2] = tail[0];
+ skb->data[len + padding - 1] = tail[1];
+ break;
case 1:
- *data = value;
+ skb->data[len + padding - 1] = tail[0];
+ break;
}
}
} else {
@@ -715,11 +729,13 @@ data_ready:
q->mmio_base + B43_PIO_RXDATA,
sizeof(u16));
if (len & 1) {
- u16 value;
+ u8 tail[2] = { 0, };
/* Read the last byte. */
- value = b43_piorx_read16(q, B43_PIO_RXDATA);
- skb->data[len + padding - 1] = value;
+ ssb_block_read(dev->dev, tail, 2,
+ q->mmio_base + B43_PIO_RXDATA,
+ sizeof(u16));
+ skb->data[len + padding - 1] = tail[0];
}
}
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 896f532..38cfd79 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -631,6 +631,9 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000;
if (WARN_ON(!data->beacon_int))
data->beacon_int = 1;
+ if (data->started)
+ mod_timer(&data->beacon_timer,
+ jiffies + data->beacon_int);
}
if (changed & BSS_CHANGED_ERP_CTS_PROT) {
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 1cbd9b4..b8f5ee3 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2381,6 +2381,7 @@ static struct usb_device_id rt73usb_device_table[] = {
/* Huawei-3Com */
{ USB_DEVICE(0x1472, 0x0009), USB_DEVICE_DATA(&rt73usb_ops) },
/* Hercules */
+ { USB_DEVICE(0x06f8, 0xe002), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x06f8, 0xe010), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x06f8, 0xe020), USB_DEVICE_DATA(&rt73usb_ops) },
/* Linksys */
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 5143d20..fd40282 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -367,7 +367,10 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
u32 staflags;
- if (unlikely(!sta || ieee80211_is_probe_resp(hdr->frame_control)))
+ if (unlikely(!sta || ieee80211_is_probe_resp(hdr->frame_control)
+ || ieee80211_is_auth(hdr->frame_control)
+ || ieee80211_is_assoc_resp(hdr->frame_control)
+ || ieee80211_is_reassoc_resp(hdr->frame_control)))
return TX_CONTINUE;
staflags = get_sta_flags(sta);
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply related
* Re: [PATCH] staging: Add proper selection of WIRELESS_EXT and WEXT_PRIV
From: John W. Linville @ 2009-10-01 18:28 UTC (permalink / raw)
To: Larry Finger; +Cc: Johannes Berg, Greg Kroah-Hartman, wireless
In-Reply-To: <4AC4F363.4080404@lwfinger.net>
On Thu, Oct 01, 2009 at 01:22:27PM -0500, Larry Finger wrote:
> After the incorporation of the patch entitled "wext: refactor", some
> of the wireless drivers in drivers/staging fail to build because they
> need to have CONFIG_WIRELESS_EXT and CONFIG_WEXT_PRIV defined.
>
> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
> ---
>
> John,
>
> I know that Greg K-H maintains staging, but I sent this to you because
> your tree is the only one affected at the moment. Greg is Cc'd.
>
> Larry
Hmmm...OK, I suppose I'll just carry this one -- I doubt if it will
cause a problem during the 2.6.33 merge window unless one of these
drivers actually disappears from staging anyway...
John
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply
* Re: VLAN traffic appearing on the wrong iface
From: Johannes Berg @ 2009-10-01 18:39 UTC (permalink / raw)
To: Blaž Bačnik; +Cc: linux-wireless
In-Reply-To: <57b62e7d0910010740t67a96d88h59b10161844f2836@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 325 bytes --]
Thanks for looking into the crash -- I can't explain it.
> - if (ieee80211_vif_is_mesh(&sdata->vif)) {
> + if (ieee80211_vif_is_mesh(&(*sta)->sdata->vif)) {
However, that doesn't make any sense, given
struct ieee80211_sub_if_data *sdata = (*sta)->sdata;
Could the compiler be playing tricks on us?
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH] net: fix NOHZ: local_softirq_pending 08
From: Johannes Berg @ 2009-10-01 18:42 UTC (permalink / raw)
To: Michael Buesch
Cc: David Miller, oliver, kalle.valo, linville, linux-wireless,
netdev
In-Reply-To: <200910011604.42916.mb@bu3sch.de>
[-- Attachment #1: Type: text/plain, Size: 460 bytes --]
On Thu, 2009-10-01 at 16:04 +0200, Michael Buesch wrote:
> On Thursday 01 October 2009 01:33:33 David Miller wrote:
>
> > I'm not applying this until all of these details are sorted out
>
> John, please apply my fix to wireless-testing to get rid of the regression.
> You can revert it later, if there's a better fix available.
I agree with davem, don't. Just fix the driver to local_bh_disable()
around the rx function if necessary.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH] net: fix NOHZ: local_softirq_pending 08
From: Michael Buesch @ 2009-10-01 19:10 UTC (permalink / raw)
To: Johannes Berg
Cc: David Miller, oliver, kalle.valo, linville, linux-wireless,
netdev
In-Reply-To: <1254422548.3959.24.camel@johannes.local>
On Thursday 01 October 2009 20:42:28 Johannes Berg wrote:
> On Thu, 2009-10-01 at 16:04 +0200, Michael Buesch wrote:
> > On Thursday 01 October 2009 01:33:33 David Miller wrote:
> >
> > > I'm not applying this until all of these details are sorted out
> >
> > John, please apply my fix to wireless-testing to get rid of the regression.
> > You can revert it later, if there's a better fix available.
>
> I agree with davem, don't. Just fix the driver to local_bh_disable()
> around the rx function if necessary.
For the benefit of a much bigger critical section? I don't get it why this would be any better.
I _am_ going to do one thing now, however. That is ignoring any regression bugreport.
(Yes, it _is_ a regression for b43)
--
Greetings, Michael.
^ permalink raw reply
* Re: [PATCH] net: fix NOHZ: local_softirq_pending 08
From: Johannes Berg @ 2009-10-01 19:26 UTC (permalink / raw)
To: Michael Buesch
Cc: David Miller, oliver, kalle.valo, linville, linux-wireless,
netdev
In-Reply-To: <200910012110.34216.mb@bu3sch.de>
[-- Attachment #1: Type: text/plain, Size: 489 bytes --]
On Thu, 2009-10-01 at 21:10 +0200, Michael Buesch wrote:
> > I agree with davem, don't. Just fix the driver to local_bh_disable()
> > around the rx function if necessary.
>
> For the benefit of a much bigger critical section? I don't get it why this would be any better.
And how do you know mac80211 is actually safe with this change? It uses
tasklets too. At the very least you'd have to require drivers to never
mix & match the regular/irqsafe functions at all.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH] net: fix NOHZ: local_softirq_pending 08
From: David Miller @ 2009-10-01 19:32 UTC (permalink / raw)
To: mb; +Cc: johannes, oliver, kalle.valo, linville, linux-wireless, netdev
In-Reply-To: <200910012110.34216.mb@bu3sch.de>
From: Michael Buesch <mb@bu3sch.de>
Date: Thu, 1 Oct 2009 21:10:32 +0200
> For the benefit of a much bigger critical section? I don't get it
> why this would be any better.
Think about what you are saying when you introduce things
like this into your code:
if (in_interrupt())
foo();
else
bar();
That thing there means you don't know anything about how you'll need
to do locking properly, because you have no idea about even the
context in which your code is executed.
Sure, you can lock for the most stringent case, but that's silly and
wasteful.
^ permalink raw reply
* Re: pull request: wireless-2.6 2009-10-01
From: David Miller @ 2009-10-01 19:43 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20091001182450.GD2895@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Thu, 1 Oct 2009 14:24:51 -0400
> One is a brown paper bag fix for an uninitialized variable, another is a
> USB ID. There is a beaconing fix for the mac80211_hwsim "fake" driver,
> and a bug fix for AP mode related to buffering frames for stations in
> power save mode.
>
> The b43 fix looks a bit long, but it is more-or-less the same simple
> fix applied in multiple places. It addresses a bug where "the last
> bytes of data sent/received to/from PIO FIFOs on SDIO-based cards get
> 'swizzled' when its length is not multiple of 4 bytes."
>
> Please let me know if there are problems!
Pulled, thanks a lot John.
I'll try to make sure the netif_rx_ni() et al. discussion keeps
making forward progress so that will get fixed too :-)
^ permalink raw reply
* Re: Linux-2.6.32-rc1/2] wext refactor needs wpasupplicant 0.7.0+?
From: Johannes Berg @ 2009-10-01 19:47 UTC (permalink / raw)
To: Sedat Dilek; +Cc: wireless
In-Reply-To: <2d0a357f0910010247jfda1199h5a9b873233b186ca@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 937 bytes --]
On Thu, 2009-10-01 at 11:47 +0200, Sedat Dilek wrote:
> a few hours ago I compiled a new kernel from upstream and put
> wireless-testing master-2009-09-30 on top of it.
>
> Last commit a1bec0ecfc76281d5e1ebd33435c67da7dd0fe71
> wext: refactor
>
> linux-2.6/master:
> 84d88d5: Merge branch 'sched-fixes-for-linus' of
> git://git./linux/kernel/git/tip/linux-2.6-tip
>
> After installation of the above described kernel, I could not connect
> to my AP using wext driver and wpasupplicant (0.6.9-3) from Debian/sid
> [1].
> With ath5k I could not establish a network connection neither via DHCP
> nor via static-IP to my AP (iwl3945 on a second machine works with
> self-debianized wpasupplicant 0.7.0+ and static-IP, same kernel).
>
> Just for clarification:
> Does wext refactor need a wpasupplicant >= 0.7.0 from hostap GIT repository [2]?
Should be ok. Can we see wpa_supplicant -ddt log please?
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: VLAN traffic appearing on the wrong iface
From: Blaž Bačnik @ 2009-10-01 19:55 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1254422380.3959.23.camel@johannes.local>
On Thu, Oct 1, 2009 at 8:39 PM, Johannes Berg <johannes@sipsolutions.net> wrote:
> Thanks for looking into the crash -- I can't explain it.
>
>> - if (ieee80211_vif_is_mesh(&sdata->vif)) {
>> + if (ieee80211_vif_is_mesh(&(*sta)->sdata->vif)) {
>
> However, that doesn't make any sense, given
>
> struct ieee80211_sub_if_data *sdata = (*sta)->sdata;
>
> Could the compiler be playing tricks on us?
There's the sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap)
in if-clause right in front of the ieee80211_vif_is_mesh and since
this is a vlan
interface that if-clause gets executed. This is done because we need to tell the
real, non-vlan interface what is going on. It changes sdata which is
understandable.
But I've really no idea why the new sdata (of non-vlan ap subiface)
does not have initialized vif member. Since this is the reason behind the oops:
trying to dereference a vif->type member of AP/VLAN's AP iface.
Basically, that if-clause changes sdata if iface type is AP/VLAN
(which it is), then tries
to do some stuff on the new sdata. And I think it should be doing it
on the old sdata --
this is what this patch does.
Regards, Blaz
^ permalink raw reply
* Re: VLAN traffic appearing on the wrong iface
From: Johannes Berg @ 2009-10-01 20:02 UTC (permalink / raw)
To: Blaž Bačnik; +Cc: linux-wireless
In-Reply-To: <57b62e7d0910011255r2ecf2bbex37422204add9a2b0@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 875 bytes --]
On Thu, 2009-10-01 at 21:55 +0200, Blaž Bačnik wrote:
> On Thu, Oct 1, 2009 at 8:39 PM, Johannes Berg <johannes@sipsolutions.net> wrote:
> > Thanks for looking into the crash -- I can't explain it.
> >
> >> - if (ieee80211_vif_is_mesh(&sdata->vif)) {
> >> + if (ieee80211_vif_is_mesh(&(*sta)->sdata->vif)) {
> >
> > However, that doesn't make any sense, given
> >
> > struct ieee80211_sub_if_data *sdata = (*sta)->sdata;
> >
> > Could the compiler be playing tricks on us?
>
> There's the sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap)
> in if-clause right in front of the ieee80211_vif_is_mesh and since
> this is a vlan interface that if-clause gets executed.
Ahh. hwsim has no sta_notify callback. I'll amend my other patch
appropriately, since your fix is, while correct, kinda hard to
understand.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* [PATCH v2 2.6.32] mac80211: fix vlan and optimise RX
From: Johannes Berg @ 2009-10-01 20:06 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Blaž Bačnik
In-Reply-To: <1254341893.3959.13.camel@johannes.local>
When receiving data frames, we can send them only to
the interface they belong to based on transmitting
station (this doesn't work for probe requests). Also,
don't try to handle other frames for AP_VLAN at all
since those interface should only receive data.
Additionally, the transmit side must check that the
station we're sending a frame to is actually on the
interface we're transmitting on, and not transmit
packets to functions that live on other interfaces,
so validate that as well.
Another bug fix is needed in sta_info.c where in the
VLAN case when adding/removing stations we overwrite
the sdata variable we still need.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: stable@kernel.org
---
net/mac80211/rx.c | 10 ++++++++--
net/mac80211/sta_info.c | 2 ++
net/mac80211/tx.c | 3 ++-
3 files changed, 12 insertions(+), 3 deletions(-)
--- wireless-testing.orig/net/mac80211/rx.c 2009-09-30 21:38:59.000000000 +0200
+++ wireless-testing/net/mac80211/rx.c 2009-09-30 22:09:54.000000000 +0200
@@ -2164,11 +2164,17 @@ static void __ieee80211_rx_handle_packet
skb = rx.skb;
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ if (rx.sdata && ieee80211_is_data(hdr->frame_control)) {
+ rx.flags |= IEEE80211_RX_RA_MATCH;
+ prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
+ if (prepares)
+ prev = rx.sdata;
+ } else list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (!netif_running(sdata->dev))
continue;
- if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
continue;
rx.flags |= IEEE80211_RX_RA_MATCH;
--- wireless-testing.orig/net/mac80211/tx.c 2009-09-30 21:49:34.000000000 +0200
+++ wireless-testing/net/mac80211/tx.c 2009-09-30 22:04:25.000000000 +0200
@@ -1704,7 +1704,8 @@ netdev_tx_t ieee80211_subif_start_xmit(s
if (!is_multicast_ether_addr(hdr.addr1)) {
rcu_read_lock();
sta = sta_info_get(local, hdr.addr1);
- if (sta)
+ /* XXX: in the future, use sdata to look up the sta */
+ if (sta && sta->sdata == sdata)
sta_flags = get_sta_flags(sta);
rcu_read_unlock();
}
--- wireless-testing.orig/net/mac80211/sta_info.c 2009-10-01 21:59:00.000000000 +0200
+++ wireless-testing/net/mac80211/sta_info.c 2009-10-01 22:05:00.000000000 +0200
@@ -361,6 +361,7 @@ int sta_info_insert(struct sta_info *sta
u.ap);
drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta);
+ sdata = sta->sdata;
}
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
@@ -496,6 +497,7 @@ static void __sta_info_unlink(struct sta
drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE,
&(*sta)->sta);
+ sdata = (*sta)->sdata;
}
if (ieee80211_vif_is_mesh(&sdata->vif)) {
^ permalink raw reply
* Re: [PATCH 0/2] cfg80211: firmware and hardware version
From: Inaky Perez-Gonzalez @ 2009-10-01 20:12 UTC (permalink / raw)
To: Luis R. Rodriguez
Cc: John W. Linville, Kalle Valo, linux-wireless@vger.kernel.org,
netdev@vger.kernel.org
In-Reply-To: <43e72e890910011256v18b30e7ck420ce80b5d35fdcb@mail.gmail.com>
On Thu, 2009-10-01 at 13:56 -0600, Luis R. Rodriguez wrote:
> On Thu, Oct 1, 2009 at 5:07 PM, John W. Linville <linville@tuxdriver.com> wrote:
>
> > I don't predict a huge problem if there are
> > valid extensions required for use by wireless drivers in the future.
> > But for now, I'd like to see us make use of some of the debugging
> > facilities available in the ethtool API -- hopefully the iwlwifi guys
> > are listening... ;-)
>
> Does the same apply to wimax then? Ethtool for 802.11 and wimax? Eh.
Not really -- WiMAX is not eth-frame based, but IP based.
The WiMAX stack doesn't require any type of framing/network device
typing requirement. That is left up to the device driver writer
(although yes, emulating eth is easier).
--
-- Inaky
^ permalink raw reply
* Re: [PATCH 0/2] cfg80211: firmware and hardware version
From: Luis R. Rodriguez @ 2009-10-01 19:56 UTC (permalink / raw)
To: John W. Linville, Perez-Gonzalez, Inaky
Cc: Kalle Valo, linux-wireless, netdev
In-Reply-To: <20091001170722.GC2895@tuxdriver.com>
On Thu, Oct 1, 2009 at 5:07 PM, John W. Linville <linville@tuxdriver.com> wrote:
> I don't predict a huge problem if there are
> valid extensions required for use by wireless drivers in the future.
> But for now, I'd like to see us make use of some of the debugging
> facilities available in the ethtool API -- hopefully the iwlwifi guys
> are listening... ;-)
Does the same apply to wimax then? Ethtool for 802.11 and wimax? Eh.
Luis
^ permalink raw reply
* Re: [PATCH] ar9170usb: LEDs are confused
From: Christian Lamparter @ 2009-10-01 20:34 UTC (permalink / raw)
To: Hin-Tak Leung; +Cc: Malte Gell, linux-wireless, Luis R. Rodriguez, linville
In-Reply-To: <3ace41890910011106p2609e928ycbc930a75ae2fb98@mail.gmail.com>
On Thursday 01 October 2009 20:06:35 Hin-Tak Leung wrote:
> On Thu, Oct 1, 2009 at 3:54 PM, Christian Lamparter
> <chunkeey@googlemail.com> wrote:
> > On 2009-10-01 06:32 AM, Malte Gell wrote:
> >>I first noticed the LEDs are confused,
> > no, the LED colors are not _confused_ at all.
> > This is simply different on.... well, you know: on a per-device base!
> >
> > For example: The Netgear uses a single bi-color LED for their WNDA3100 stick.
> > It glows blue or/and orange depending on the selected band and current
> > operation mode and state...
> >
> > No idea why they didn't stick to the usual red/green mix.
> > Maybe because someone told the hw-devs about the existence of
> > red/green colorblind people??!
> >
> > The original vendor driver (located: drivers/staging/otus/80211core/ledmgr.c)
> > goes to great lengths to describe what's behind the variety of
> > blinking signals. Which is nice, if you like expensive light shows...
>
> This is just based on my brief look at the relevant code itself - I
> think the driver actually enumerates how many LEDs the device has, so
> the ONLY_ONE_LED construct is a bit bogus. Also I think the
> 0x0846:0x9001 is Malte's with swapped LEDs, not ONLY_ONE?
?
0x0846:0x9001 is a Netgear WN111 v2.
(one LED reference: otus' ledmgr.c ~line 547)
and AFAIK: Malte uses an AVM FRITZ!WLAN Stick N (2.4?).
> I had a look when Malte first wrote about the swap - the code
> basically just do assoc/data-tx in enumeration order (first LED found
> is assoc, 2nd is tx, which make sense if some variant only have a
> LED).
Depends. I think it's more important to have some sort of an "an activity LED"
than a connection indicator, because most desktops-guis nowadays have lots
of fancy applets which are constantly monitoring your connection status and
start to bark as soon as it changes...
BTW: my laptop (with an IWL 5300) only has one LED assigned for wlan as well.
But, someone had the genius idea to put the activity LED into _inverted_
mode when the connection is established. It stays on after association
and flashes under TX activity... This is nice, but it has a downside:
two trigger _drive_ one LED => no real exclusive access anymore.
If you want to reassign the LEDs the clueless user has to be aware about
this trigger dependency, or he see some _blinking interference_.
> As for the color - it is probably just a matter of commercial
> interests (if they can get a particular color from a source cheaper)
unlikely, the bi-color LED is a super bright one.
> or simply variety to catch some customers - as you say, some *do* like
> expensive light shows, and there is a market for it and money to be
> made that way.
:-D
well to be fair, I think they tried to implement some sort of
complex blinking language code. You can tell apart if
the device is idling/scanning/connected/sending in the 5GHz or 2GHz
band just by looking at the blue and orange rhythms...
(maybe this visual feedback is indeed easier to comprehend for the generic
customer than any hard and honest numbers)
But back to the topic:
This elaborate morse code is clearly way beyond the scope and
abilities of ledclass. I think we should really stick to the
simple rule: one trigger corresponds to only one physical LED.
> Anyway, I am just writing regarding the ONLY_ONE_LED construct and its
> association with 0x0846:0x9001 ...
hmm, not sure what I should do here...
Do you think the driver should simply ignore the lack of a second LED (color)?
Or is it just that the ONLY_ONE_LED construct sounds really lame
and needs a more cunning name?
Regards,
Chr
^ permalink raw reply
* Re: Linux-2.6.32-rc1/2] wext refactor needs wpasupplicant 0.7.0+?
From: Sedat Dilek @ 2009-10-01 20:44 UTC (permalink / raw)
To: Johannes Berg; +Cc: wireless
In-Reply-To: <1254426421.3959.29.camel@johannes.local>
[-- Attachment #1: Type: text/plain, Size: 1215 bytes --]
Here the logs for wpasupplicant v06.9 and v0.7.0.
$ wpa_supplicant -v
$ /sbin/wpa_supplicant -ddt -B -P /var/run/wpa_supplicant.wlan0.pid -i
wlan0 -D wext -C /var/run/wpa_supplicant
- Sedat -
On Thu, Oct 1, 2009 at 9:47 PM, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Thu, 2009-10-01 at 11:47 +0200, Sedat Dilek wrote:
>
>> a few hours ago I compiled a new kernel from upstream and put
>> wireless-testing master-2009-09-30 on top of it.
>>
>> Last commit a1bec0ecfc76281d5e1ebd33435c67da7dd0fe71
>> wext: refactor
>>
>> linux-2.6/master:
>> 84d88d5: Merge branch 'sched-fixes-for-linus' of
>> git://git./linux/kernel/git/tip/linux-2.6-tip
>>
>> After installation of the above described kernel, I could not connect
>> to my AP using wext driver and wpasupplicant (0.6.9-3) from Debian/sid
>> [1].
>> With ath5k I could not establish a network connection neither via DHCP
>> nor via static-IP to my AP (iwl3945 on a second machine works with
>> self-debianized wpasupplicant 0.7.0+ and static-IP, same kernel).
>>
>> Just for clarification:
>> Does wext refactor need a wpasupplicant >= 0.7.0 from hostap GIT repository [2]?
>
> Should be ok. Can we see wpa_supplicant -ddt log please?
>
> johannes
>
[-- Attachment #2: wpasupplicant-069.txt --]
[-- Type: text/plain, Size: 3646 bytes --]
wpa_supplicant v0.6.9
Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi> and contributors
1254429474.982896: Initializing interface 'wlan0' conf 'N/A' driver 'wext' ctrl_interface '/var/run/wpa_supplicant' bridge 'N/A'
1254429475.079713: Interface wlan0 set UP - waiting a second for the driver to complete initialization
1254429476.080009: SIOCGIWRANGE: WE(compiled)=22 WE(source)=21 enc_capa=0xf
1254429476.080032: capabilities: key_mgmt 0xf enc 0xf flags 0x0
1254429476.084533: WEXT: Operstate: linkmode=1, operstate=5
1254429476.084633: Own MAC address: 00:05:4e:46:b4:1f
1254429476.084644: wpa_driver_wext_set_wpa
1254429476.084658: wpa_driver_wext_set_key: alg=0 key_idx=0 set_tx=0 seq_len=0 key_len=0
1254429476.084677: wpa_driver_wext_set_key: alg=0 key_idx=1 set_tx=0 seq_len=0 key_len=0
1254429476.084689: wpa_driver_wext_set_key: alg=0 key_idx=2 set_tx=0 seq_len=0 key_len=0
1254429476.084699: wpa_driver_wext_set_key: alg=0 key_idx=3 set_tx=0 seq_len=0 key_len=0
1254429476.084710: wpa_driver_wext_set_countermeasures
1254429476.084717: wpa_driver_wext_set_drop_unencrypted
1254429476.084724: RSN: flushing PMKID list in the driver
1254429476.084792: Setting scan request: 0 sec 100000 usec
1254429476.084849: WPS: UUID based on MAC address - hexdump(len=16): 55 2a 23 9b 14 1f 53 7a 89 c6 98 d8 83 ac a7 26
1254429476.084876: WPS: Build Beacon and Probe Response IEs
1254429476.084888: WPS: * Version
1254429476.084896: WPS: * Wi-Fi Protected Setup State (0)
1254429476.084904: WPS: * Version
1254429476.084908: WPS: * Wi-Fi Protected Setup State (0)
1254429476.084913: WPS: * Response Type (2)
1254429476.084921: WPS: * UUID-E
1254429476.084928: WPS: * Manufacturer
1254429476.084933: WPS: * Model Name
1254429476.084938: WPS: * Model Number
1254429476.084942: WPS: * Serial Number
1254429476.084946: WPS: * Primary Device Type
1254429476.084951: WPS: * Device Name
1254429476.084955: WPS: * Config Methods (0)
1254429476.084960: WPS: * RF Bands (3)
1254429476.088433: EAPOL: SUPP_PAE entering state DISCONNECTED
1254429476.088441: EAPOL: KEY_RX entering state NO_KEY_RECEIVE
1254429476.088448: EAPOL: SUPP_BE entering state INITIALIZE
1254429476.088458: EAP: EAP entering state DISABLED
1254429476.088486: Using existing control interface directory.
1254429476.088527: ctrl_iface bind(PF_UNIX) failed: Address already in use
1254429476.088543: ctrl_iface exists and seems to be in use - cannot override it
1254429476.088548: Delete '/var/run/wpa_supplicant/wlan0' manually if it is not used anymore
1254429476.088563: Failed to initialize control interface '/var/run/wpa_supplicant'.
You may have another wpa_supplicant process already running or the file was
left by an unclean termination of wpa_supplicant in which case you will need
to manually remove this file before starting wpa_supplicant again.
1254429476.088573: Failed to add interface wlan0
1254429476.088582: State: DISCONNECTED -> DISCONNECTED
1254429476.088592: wpa_driver_wext_set_operstate: operstate 0->0 (DORMANT)
1254429476.088599: WEXT: Operstate: linkmode=-1, operstate=5
1254429476.088615: No keys have been configured - skip key clearing
1254429476.088621: EAPOL: External notification - portEnabled=0
1254429476.088628: EAPOL: External notification - portValid=0
1254429476.088633: wpa_driver_wext_set_wpa
1254429476.088642: wpa_driver_wext_set_drop_unencrypted
1254429476.088649: wpa_driver_wext_set_countermeasures
1254429476.088655: No keys have been configured - skip key clearing
1254429476.089339: Cancelling scan request
1254429476.089349: Cancelling authentication timeout
1254429476.089411: WEXT: Operstate: linkmode=0, operstate=6
[-- Attachment #3: wpasupplicant-070.txt --]
[-- Type: text/plain, Size: 3961 bytes --]
wpa_supplicant v0.7.0
Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi> and contributors
1254429555.677208: Initializing interface 'wlan0' conf 'N/A' driver 'wext' ctrl_interface '/var/run/wpa_supplicant' bridge 'N/A'
1254429555.733937: Interface wlan0 set UP - waiting a second for the driver to complete initialization
1254429556.734139: SIOCGIWRANGE: WE(compiled)=22 WE(source)=21 enc_capa=0xf
1254429556.734160: capabilities: key_mgmt 0xf enc 0xf flags 0x0
1254429556.737759: WEXT: Operstate: linkmode=1, operstate=5
1254429556.737818: Own MAC address: 00:05:4e:46:b4:1f
1254429556.737825: wpa_driver_wext_set_wpa
1254429556.737831: wpa_driver_wext_set_key: alg=0 key_idx=0 set_tx=0 seq_len=0 key_len=0
1254429556.737841: wpa_driver_wext_set_key: alg=0 key_idx=1 set_tx=0 seq_len=0 key_len=0
1254429556.737846: wpa_driver_wext_set_key: alg=0 key_idx=2 set_tx=0 seq_len=0 key_len=0
1254429556.737851: wpa_driver_wext_set_key: alg=0 key_idx=3 set_tx=0 seq_len=0 key_len=0
1254429556.737855: wpa_driver_wext_set_countermeasures
1254429556.737858: wpa_driver_wext_set_drop_unencrypted
1254429556.737861: RSN: flushing PMKID list in the driver
1254429556.737879: Setting scan request: 0 sec 100000 usec
1254429556.737948: WPS: UUID based on MAC address - hexdump(len=16): 55 2a 23 9b 14 1f 53 7a 89 c6 98 d8 83 ac a7 26
1254429556.737959: WPS: Build Beacon and Probe Response IEs
1254429556.737965: WPS: * Version
1254429556.737968: WPS: * Wi-Fi Protected Setup State (0)
1254429556.737972: WPS: * Version
1254429556.737974: WPS: * Wi-Fi Protected Setup State (0)
1254429556.737977: WPS: * Response Type (2)
1254429556.737979: WPS: * UUID-E
1254429556.737982: WPS: * Manufacturer
1254429556.737984: WPS: * Model Name
1254429556.737986: WPS: * Model Number
1254429556.737988: WPS: * Serial Number
1254429556.737991: WPS: * Primary Device Type
1254429556.737993: WPS: * Device Name
1254429556.737995: WPS: * Config Methods (0)
1254429556.737997: WPS: * RF Bands (3)
1254429556.739312: EAPOL: SUPP_PAE entering state DISCONNECTED
1254429556.739316: EAPOL: Supplicant port status: Unauthorized
1254429556.739319: EAPOL: KEY_RX entering state NO_KEY_RECEIVE
1254429556.739321: EAPOL: SUPP_BE entering state INITIALIZE
1254429556.739325: EAP: EAP entering state DISABLED
1254429556.739328: EAPOL: Supplicant port status: Unauthorized
1254429556.739331: EAPOL: Supplicant port status: Unauthorized
1254429556.739343: Using existing control interface directory.
1254429556.739361: ctrl_iface bind(PF_UNIX) failed: Address already in use
1254429556.739371: ctrl_iface exists and seems to be in use - cannot override it
1254429556.739373: Delete '/var/run/wpa_supplicant/wlan0' manually if it is not used anymore
1254429556.739380: Failed to initialize control interface '/var/run/wpa_supplicant'.
You may have another wpa_supplicant process already running or the file was
left by an unclean termination of wpa_supplicant in which case you will need
to manually remove this file before starting wpa_supplicant again.
1254429556.739385: Failed to add interface wlan0
1254429556.739388: No keys have been configured - skip key clearing
1254429556.739391: State: DISCONNECTED -> DISCONNECTED
1254429556.739396: wpa_driver_wext_set_operstate: operstate 0->0 (DORMANT)
1254429556.739399: WEXT: Operstate: linkmode=-1, operstate=5
1254429556.739407: EAPOL: External notification - portEnabled=0
1254429556.739410: EAPOL: Supplicant port status: Unauthorized
1254429556.739412: EAPOL: External notification - portValid=0
1254429556.739415: EAPOL: Supplicant port status: Unauthorized
1254429556.739418: wpa_driver_wext_set_wpa
1254429556.739422: wpa_driver_wext_set_drop_unencrypted
1254429556.739425: wpa_driver_wext_set_countermeasures
1254429556.739428: No keys have been configured - skip key clearing
1254429556.739682: Cancelling scan request
1254429556.739686: Cancelling authentication timeout
1254429556.739704: WEXT: Operstate: linkmode=0, operstate=6
^ permalink raw reply
* Re: Linux-2.6.32-rc1/2] wext refactor needs wpasupplicant 0.7.0+?
From: Johannes Berg @ 2009-10-01 20:56 UTC (permalink / raw)
To: Sedat Dilek; +Cc: wireless
In-Reply-To: <2d0a357f0910011344u4306ecf6ha11410b0f5ed62e3@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 656 bytes --]
On Thu, 2009-10-01 at 22:44 +0200, Sedat Dilek wrote:
>
> 1254429476.088527: ctrl_iface bind(PF_UNIX) failed: Address already in use
> 1254429476.088543: ctrl_iface exists and seems to be in use - cannot override it
> 1254429476.088548: Delete '/var/run/wpa_supplicant/wlan0' manually if it is not used anymore
> 1254429476.088563: Failed to initialize control interface '/var/run/wpa_supplicant'.
> You may have another wpa_supplicant process already running or the file was
> left by an unclean termination of wpa_supplicant in which case you will need
> to manually remove this file before starting wpa_supplicant again.
Umm...
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: BUG: "wext: refactor" broke compilation
From: Johannes Berg @ 2009-10-01 21:14 UTC (permalink / raw)
To: Holger Schurig; +Cc: linux-wireless
In-Reply-To: <200910011139.30914.hs4233@mail.mn-solutions.de>
[-- Attachment #1: Type: text/plain, Size: 1176 bytes --]
On Thu, 2009-10-01 at 11:39 +0200, Holger Schurig wrote:
> LD net/wireless/built-in.o
> CC [M] net/wireless/core.o
> net/wireless/core.c: In function 'cfg80211_netdev_notifier_call':
> net/wireless/core.c:673: error: 'struct wireless_dev' has no member named 'wext'
> net/wireless/core.c:674: error: 'struct wireless_dev' has no member named 'wext'
> net/wireless/core.c:675: error: 'struct wireless_dev' has no member named 'wext'
> net/wireless/core.c:676: error: 'struct wireless_dev' has no member named 'wext'
> net/wireless/core.c:677: error: 'struct wireless_dev' has no member named 'wext'
> net/wireless/core.c:680: error: 'struct wireless_dev' has no member named 'wext'
> net/wireless/core.c:681: error: 'struct wireless_dev' has no member named 'wext'
> net/wireless/core.c:683: error: 'struct wireless_dev' has no member named 'wext'
>
> The reason is that currently two different Kconfig
> defines are used:
>
>
> in net/wireless/core.c:
>
> #ifdef CONFIG_WIRELESS_EXT
> wdev->wext.default_key = -1;
> ...
> #endif
Did you send a patch to change that to CONFIG_CFG80211_WEXT, or do I
need to?
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: 2.6.32-rc0-git: oops in wireless, iwl3945 related?
From: Johannes Berg @ 2009-10-01 21:16 UTC (permalink / raw)
To: Pavel Machek; +Cc: linux-kernel, yi.zhu, reinette.chatre, linux-wireless
In-Reply-To: <20090929171249.GB14405@elf.ucw.cz>
[-- Attachment #1: Type: text/plain, Size: 1014 bytes --]
On Tue, 2009-09-29 at 19:12 +0200, Pavel Machek wrote:
>
> Happened while playing with wireless.
>
> Kernel is:
>
> Linux version 2.6.31 (pavel@amd) (gcc version 4.3.3 (Debian 4.3.3-10)
> ) #72 SMP Thu Sep 10 21:56:19 CEST 2009
> KERNEL supported cpus:
>
> (Could we get kernels between release and -rc1 mark themselves
> somehow?)
CONFIG_LOCALVERSION_AUTO?
> Registered led device: iwl-phy0::radio
> Registered led device: iwl-phy0::assoc
> Registered led device: iwl-phy0::RX
> Registered led device: iwl-phy0::TX
> wlan0: Selected IBSS BSSID 02:18:41:de:3f:02 based on configured SSID
> wlan0: Trigger new scan to find an IBSS to join
> wlan0: Trigger new scan to find an IBSS to join
> wlan0: Creating new IBSS network, BSSID f2:d3:80:82:ed:6a
> wlan0: Creating new IBSS network, BSSID 52:17:bf:45:d6:9d
> skb_over_panic: text:c07b4113 len:130 put:36 head:e4c3edf0
This entire log is very odd ... can you reproduce this easily? printk
timestamps would be useful.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH] ar9170usb: LEDs are confused
From: Hin-Tak Leung @ 2009-10-01 21:24 UTC (permalink / raw)
To: Christian Lamparter
Cc: Malte Gell, linux-wireless, Luis R. Rodriguez, linville
In-Reply-To: <200910012234.33182.chunkeey@googlemail.com>
On Thu, Oct 1, 2009 at 9:34 PM, Christian Lamparter
<chunkeey@googlemail.com> wrote:
> On Thursday 01 October 2009 20:06:35 Hin-Tak Leung wrote:
>> On Thu, Oct 1, 2009 at 3:54 PM, Christian Lamparter
>> <chunkeey@googlemail.com> wrote:
>> > On 2009-10-01 06:32 AM, Malte Gell wrote:
>> >>I first noticed the LEDs are confused,
>> > no, the LED colors are not _confused_ at all.
>> > This is simply different on.... well, you know: on a per-device base!
>> >
>> > For example: The Netgear uses a single bi-color LED for their WNDA3100 stick.
>> > It glows blue or/and orange depending on the selected band and current
>> > operation mode and state...
>> >
>> > No idea why they didn't stick to the usual red/green mix.
>> > Maybe because someone told the hw-devs about the existence of
>> > red/green colorblind people??!
>> >
>> > The original vendor driver (located: drivers/staging/otus/80211core/ledmgr.c)
>> > goes to great lengths to describe what's behind the variety of
>> > blinking signals. Which is nice, if you like expensive light shows...
>>
>> This is just based on my brief look at the relevant code itself - I
>> think the driver actually enumerates how many LEDs the device has, so
>> the ONLY_ONE_LED construct is a bit bogus. Also I think the
>> 0x0846:0x9001 is Malte's with swapped LEDs, not ONLY_ONE?
> ?
>
> 0x0846:0x9001 is a Netgear WN111 v2.
> (one LED reference: otus' ledmgr.c ~line 547)
>
> and AFAIK: Malte uses an AVM FRITZ!WLAN Stick N (2.4?).
I just remember the ID from Malte's ndiswrapper-list posting. It is
not unthinkable of a rebranded device, or even vendor abusing the
system a bit and put out a device which is subtly different with the
same ids.
>
>> I had a look when Malte first wrote about the swap - the code
>> basically just do assoc/data-tx in enumeration order (first LED found
>> is assoc, 2nd is tx, which make sense if some variant only have a
>> LED).
> Depends. I think it's more important to have some sort of an "an activity LED"
> than a connection indicator, because most desktops-guis nowadays have lots
> of fancy applets which are constantly monitoring your connection status and
> start to bark as soon as it changes...
>
> BTW: my laptop (with an IWL 5300) only has one LED assigned for wlan as well.
> But, someone had the genius idea to put the activity LED into _inverted_
> mode when the connection is established. It stays on after association
> and flashes under TX activity... This is nice, but it has a downside:
> two trigger _drive_ one LED => no real exclusive access anymore.
> If you want to reassign the LEDs the clueless user has to be aware about
> this trigger dependency, or he see some _blinking interference_.
>
>> As for the color - it is probably just a matter of commercial
>> interests (if they can get a particular color from a source cheaper)
> unlikely, the bi-color LED is a super bright one.
>
>> or simply variety to catch some customers - as you say, some *do* like
>> expensive light shows, and there is a market for it and money to be
>> made that way.
> :-D
>
> well to be fair, I think they tried to implement some sort of
> complex blinking language code. You can tell apart if
> the device is idling/scanning/connected/sending in the 5GHz or 2GHz
> band just by looking at the blue and orange rhythms...
> (maybe this visual feedback is indeed easier to comprehend for the generic
> customer than any hard and honest numbers)
>
> But back to the topic:
> This elaborate morse code is clearly way beyond the scope and
> abilities of ledclass. I think we should really stick to the
> simple rule: one trigger corresponds to only one physical LED.
>
>> Anyway, I am just writing regarding the ONLY_ONE_LED construct and its
>> association with 0x0846:0x9001 ...
> hmm, not sure what I should do here...
> Do you think the driver should simply ignore the lack of a second LED (color)?
> Or is it just that the ONLY_ONE_LED construct sounds really lame
> and needs a more cunning name?
>
> Regards,
> Chr
>
Hmm, I mean the ONLY_ONE_LED config should not be a compiled in config
associated with an vid/pid, but dynamically determined from the
enumeration.
In the case of only one LED, the it sounds quite neat to represent
both assciation status and transmission status by blinking pattern
:-).
But one of them should take priority in case of conflict, and in this
regard it seems that you and I disagree on which should be.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox