* [PATCH 18/22] wl1271: Support for IPv4 ARP filtering
From: Luciano Coelho @ 2009-10-13 9:47 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Juuso Oikarinen, Janne Ylälehto
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>
From: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Add support for IPv4 ARP filtering in the driver. This will dramatically
reduce the number of unnecessary interrupts by the device in conqested
networks.
This patch is based on a similar patch to wl1251 by Janne Ylälehto.
Cc: Janne Ylälehto <janne.ylalehto@nokia.com>
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
drivers/net/wireless/wl12xx/wl1271.h | 2 +
drivers/net/wireless/wl12xx/wl1271_acx.c | 38 +++++++++++
drivers/net/wireless/wl12xx/wl1271_acx.h | 17 +++++
drivers/net/wireless/wl12xx/wl1271_main.c | 100 +++++++++++++++++++++++++++++
4 files changed, 157 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 79a7324..1e399a2 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -441,6 +441,8 @@ struct wl1271 {
/* Current chipset configuration */
struct conf_drv_settings conf;
+
+ struct list_head list;
};
int wl1271_plt_start(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index 44a1237..e891cd5 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -1092,3 +1092,41 @@ out:
kfree(acx);
return ret;
}
+
+int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address,
+ u8 version)
+{
+ struct wl1271_acx_arp_filter *acx;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable);
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->version = version;
+ acx->enable = enable;
+
+ if (enable == true) {
+ if (version == ACX_IPV4_VERSION)
+ memcpy(acx->address, address, ACX_IPV4_ADDR_SIZE);
+ else if (version == ACX_IPV6_VERSION)
+ memcpy(acx->address, address, sizeof(acx->address));
+ else
+ wl1271_error("Invalid IP version");
+ }
+
+ ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER,
+ acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("failed to set arp ip filter: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 29fd363..1580314 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -955,6 +955,21 @@ struct wl1271_acx_bet_enable {
u8 padding[2];
} __attribute__ ((packed));
+#define ACX_IPV4_VERSION 4
+#define ACX_IPV6_VERSION 6
+#define ACX_IPV4_ADDR_SIZE 4
+struct wl1271_acx_arp_filter {
+ struct acx_header header;
+ u8 version; /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */
+ u8 enable; /* 1 to enable ARP filtering, 0 to disable */
+ u8 padding[2];
+ u8 address[16]; /* The configured device IP address - all ARP
+ requests directed to this IP address will pass
+ through. For IPv4, the first four bytes are
+ used. */
+} __attribute__((packed));
+
+
enum {
ACX_WAKE_UP_CONDITIONS = 0x0002,
ACX_MEM_CFG = 0x0003,
@@ -1064,5 +1079,7 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl);
int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
int wl1271_acx_smart_reflex(struct wl1271 *wl);
int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable);
+int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address,
+ u8 version);
#endif /* __WL1271_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index d6d1a4c..7d70f41 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -32,6 +32,7 @@
#include <linux/etherdevice.h>
#include <linux/vmalloc.h>
#include <linux/spi/wl12xx.h>
+#include <linux/inetdevice.h>
#include "wl1271.h"
#include "wl12xx_80211.h"
@@ -325,6 +326,8 @@ static struct conf_drv_settings default_conf = {
}
};
+static LIST_HEAD(wl_list);
+
static void wl1271_conf_init(struct wl1271 *wl)
{
@@ -843,6 +846,93 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
return NETDEV_TX_OK;
}
+static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
+ void *arg)
+{
+ struct net_device *dev;
+ struct wireless_dev *wdev;
+ struct wiphy *wiphy;
+ struct ieee80211_hw *hw;
+ struct wl1271 *wl;
+ struct wl1271 *wl_temp;
+ struct in_device *idev;
+ struct in_ifaddr *ifa = arg;
+ int ret = 0;
+
+ /* FIXME: this ugly function should probably be implemented in the
+ * mac80211, and here should only be a simple callback handling actual
+ * setting of the filters. Now we need to dig up references to
+ * various structures to gain access to what we need.
+ * Also, because of this, there is no "initial" setting of the filter
+ * in "op_start", because we don't want to dig up struct net_device
+ * there - the filter will be set upon first change of the interface
+ * IP address. */
+
+ dev = ifa->ifa_dev->dev;
+
+ wdev = dev->ieee80211_ptr;
+ if (wdev == NULL)
+ return -ENODEV;
+
+ wiphy = wdev->wiphy;
+ if (wiphy == NULL)
+ return -ENODEV;
+
+ hw = wiphy_priv(wiphy);
+ if (hw == NULL)
+ return -ENODEV;
+
+ /* Check that the interface is one supported by this driver. */
+ wl_temp = hw->priv;
+ list_for_each_entry(wl, &wl_list, list) {
+ if (wl == wl_temp)
+ break;
+ }
+ if (wl == NULL)
+ return -ENODEV;
+
+ /* Get the interface IP address for the device. "ifa" will become
+ NULL if:
+ - there is no IPV4 protocol address configured
+ - there are multiple (virtual) IPV4 addresses configured
+ When "ifa" is NULL, filtering will be disabled.
+ */
+ ifa = NULL;
+ idev = dev->ip_ptr;
+ if (idev)
+ ifa = idev->ifa_list;
+
+ if (ifa && ifa->ifa_next)
+ ifa = NULL;
+
+ mutex_lock(&wl->mutex);
+
+ if (wl->state == WL1271_STATE_OFF)
+ goto out;
+
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+ if (ifa)
+ ret = wl1271_acx_arp_ip_filter(wl, true,
+ (u8 *)&ifa->ifa_address,
+ ACX_IPV4_VERSION);
+ else
+ ret = wl1271_acx_arp_ip_filter(wl, false, NULL,
+ ACX_IPV4_VERSION);
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+
+ return ret;
+}
+
+static struct notifier_block wl1271_dev_notifier = {
+ .notifier_call = wl1271_dev_notify,
+};
+
+
static int wl1271_op_start(struct ieee80211_hw *hw)
{
struct wl1271 *wl = hw->priv;
@@ -886,6 +976,11 @@ out_power_off:
out:
mutex_unlock(&wl->mutex);
+ if (!ret) {
+ list_add(&wl->list, &wl_list);
+ register_inetaddr_notifier(&wl1271_dev_notifier);
+ }
+
return ret;
}
@@ -906,6 +1001,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl->filter_params = NULL;
spin_unlock_irqrestore(&wl->wl_lock, flags);
+ unregister_inetaddr_notifier(&wl1271_dev_notifier);
+ list_del(&wl->list);
+
mutex_lock(&wl->mutex);
WARN_ON(wl->state != WL1271_STATE_ON);
@@ -1754,6 +1852,8 @@ static int __devinit wl1271_probe(struct spi_device *spi)
wl = hw->priv;
memset(wl, 0, sizeof(*wl));
+ INIT_LIST_HEAD(&wl->list);
+
wl->hw = hw;
dev_set_drvdata(&spi->dev, wl);
wl->spi = spi;
--
1.5.6.5
^ permalink raw reply related
* [PATCH 22/22] wl1271: Fix filter configuration
From: Luciano Coelho @ 2009-10-13 9:47 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>
From: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Fix the filter configuration to properly work with the two phase filter
configuration (prepare_multicast/configure_filter.)
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
drivers/net/wireless/wl12xx/wl1271.h | 3 -
drivers/net/wireless/wl12xx/wl1271_main.c | 157 +++++++++-------------------
2 files changed, 51 insertions(+), 109 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index fca5968..1309b20 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -363,9 +363,6 @@ struct wl1271 {
struct work_struct tx_work;
- struct work_struct filter_work;
- struct wl1271_filter_params *filter_params;
-
/* Pending TX frames */
struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS];
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 7b8d279..ee7ffaf 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -675,74 +675,6 @@ out:
return ret;
}
-struct wl1271_filter_params {
- unsigned int filters;
- unsigned int changed;
- int mc_list_length;
- u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
-};
-
-#define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
- FIF_ALLMULTI | \
- FIF_FCSFAIL | \
- FIF_BCN_PRBRESP_PROMISC | \
- FIF_CONTROL | \
- FIF_OTHER_BSS)
-
-static void wl1271_filter_work(struct work_struct *work)
-{
- struct wl1271 *wl =
- container_of(work, struct wl1271, filter_work);
- struct wl1271_filter_params *fp;
- unsigned long flags;
- bool enabled = true;
- int ret;
-
- /* first, get the filter parameters */
- spin_lock_irqsave(&wl->wl_lock, flags);
- fp = wl->filter_params;
- wl->filter_params = NULL;
- spin_unlock_irqrestore(&wl->wl_lock, flags);
-
- if (!fp)
- return;
-
- /* then, lock the mutex without risk of lock-up */
- mutex_lock(&wl->mutex);
-
- if (wl->state == WL1271_STATE_OFF)
- goto out;
-
- ret = wl1271_ps_elp_wakeup(wl, false);
- if (ret < 0)
- goto out;
-
- /* configure the mc filter regardless of the changed flags */
- if (fp->filters & FIF_ALLMULTI)
- enabled = false;
-
- ret = wl1271_acx_group_address_tbl(wl, enabled,
- fp->mc_list, fp->mc_list_length);
- if (ret < 0)
- goto out_sleep;
-
- /* determine, whether supported filter values have changed */
- if (fp->changed == 0)
- goto out;
-
- /* apply configured filters */
- ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
- if (ret < 0)
- goto out_sleep;
-
-out_sleep:
- wl1271_ps_elp_sleep(wl);
-
-out:
- mutex_unlock(&wl->mutex);
- kfree(fp);
-}
-
int wl1271_plt_start(struct wl1271 *wl)
{
int ret;
@@ -993,20 +925,12 @@ out:
static void wl1271_op_stop(struct ieee80211_hw *hw)
{
struct wl1271 *wl = hw->priv;
- unsigned long flags;
int i;
wl1271_info("down");
wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
- /* complete/cancel ongoing work */
- cancel_work_sync(&wl->filter_work);
- spin_lock_irqsave(&wl->wl_lock, flags);
- kfree(wl->filter_params);
- wl->filter_params = NULL;
- spin_unlock_irqrestore(&wl->wl_lock, flags);
-
unregister_inetaddr_notifier(&wl1271_dev_notifier);
list_del(&wl->list);
@@ -1029,7 +953,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
cancel_work_sync(&wl->irq_work);
cancel_work_sync(&wl->tx_work);
- cancel_work_sync(&wl->filter_work);
mutex_lock(&wl->mutex);
@@ -1252,19 +1175,18 @@ out:
return ret;
}
+struct wl1271_filter_params {
+ bool enabled;
+ int mc_list_length;
+ u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
+};
+
static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
struct dev_addr_list *mc_list)
{
- struct wl1271 *wl = hw->priv;
struct wl1271_filter_params *fp;
- unsigned long flags;
int i;
- /*
- * FIXME: we should return a hash that will be passed to
- * configure_filter() instead of saving everything in the context.
- */
-
fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
if (!fp) {
wl1271_error("Out of memory setting filters.");
@@ -1272,9 +1194,10 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
}
/* update multicast filtering parameters */
+ fp->enabled = true;
if (mc_count > ACX_MC_ADDRESS_GROUP_MAX) {
mc_count = 0;
- fp->filters |= FIF_ALLMULTI;
+ fp->enabled = false;
}
fp->mc_list_length = 0;
@@ -1288,42 +1211,65 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
mc_list = mc_list->next;
}
- /* FIXME: We still need to set our filters properly */
-
- spin_lock_irqsave(&wl->wl_lock, flags);
- kfree(wl->filter_params);
- wl->filter_params = fp;
- spin_unlock_irqrestore(&wl->wl_lock, flags);
-
- return 1;
+ return (u64)(unsigned long)fp;
}
+#define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
+ FIF_ALLMULTI | \
+ FIF_FCSFAIL | \
+ FIF_BCN_PRBRESP_PROMISC | \
+ FIF_CONTROL | \
+ FIF_OTHER_BSS)
+
static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed,
unsigned int *total, u64 multicast)
{
+ struct wl1271_filter_params *fp = (void *)(unsigned long)multicast;
struct wl1271 *wl = hw->priv;
+ int ret;
wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter");
+ mutex_lock(&wl->mutex);
+
+ if (wl->state == WL1271_STATE_OFF)
+ goto out;
+
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+
*total &= WL1271_SUPPORTED_FILTERS;
changed &= WL1271_SUPPORTED_FILTERS;
- if (!multicast)
- return;
+ if (*total & FIF_ALLMULTI)
+ ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0);
+ else if (fp)
+ ret = wl1271_acx_group_address_tbl(wl, fp->enabled,
+ fp->mc_list,
+ fp->mc_list_length);
+ if (ret < 0)
+ goto out_sleep;
- /*
- * FIXME: for now we are still using a workqueue for filter
- * configuration, but with the new mac80211, this is not needed,
- * since configure_filter can now sleep. We now have
- * prepare_multicast, which needs to be atomic instead.
- */
+ kfree(fp);
+
+ /* FIXME: We still need to set our filters properly */
- /* store current filter config */
- wl->filter_params->filters = *total;
- wl->filter_params->changed = changed;
+ /* determine, whether supported filter values have changed */
+ if (changed == 0)
+ goto out_sleep;
- ieee80211_queue_work(wl->hw, &wl->filter_work);
+ /* apply configured filters */
+ ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
+ if (ret < 0)
+ goto out_sleep;
+
+out_sleep:
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
}
static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
@@ -1866,7 +1812,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
skb_queue_head_init(&wl->tx_queue);
- INIT_WORK(&wl->filter_work, wl1271_filter_work);
INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
wl->channel = WL1271_DEFAULT_CHANNEL;
wl->scanning = false;
--
1.5.6.5
^ permalink raw reply related
* [PATCH 03/22] wl1271: Add config structure for RX path parameters
From: Luciano Coelho @ 2009-10-13 9:47 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>
From: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Add a configuration structure for RX path parameters, and set default
configuration values there.
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
drivers/net/wireless/wl12xx/wl1271_acx.c | 20 ++++----
drivers/net/wireless/wl12xx/wl1271_acx.h | 43 +--------------
drivers/net/wireless/wl12xx/wl1271_conf.h | 85 +++++++++++++++++++++++++++++
drivers/net/wireless/wl12xx/wl1271_init.c | 4 +-
drivers/net/wireless/wl12xx/wl1271_main.c | 12 ++++
5 files changed, 110 insertions(+), 54 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index d19d860..63aa646 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -198,7 +198,7 @@ int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map,
return 0;
}
-int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time)
+int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl)
{
struct acx_rx_msdu_lifetime *acx;
int ret;
@@ -211,7 +211,7 @@ int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time)
goto out;
}
- acx->lifetime = life_time;
+ acx->lifetime = wl->conf.rx.rx_msdu_life_time;
ret = wl1271_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
acx, sizeof(*acx));
if (ret < 0) {
@@ -265,7 +265,7 @@ int wl1271_acx_pd_threshold(struct wl1271 *wl)
goto out;
}
- /* FIXME: threshold value not set */
+ pd->threshold = wl->conf.rx.packet_detection_threshold;
ret = wl1271_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
if (ret < 0) {
@@ -349,8 +349,8 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl)
wl1271_debug(DEBUG_ACX, "acx service period timeout");
- rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF;
- rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF;
+ rx_timeout->ps_poll_timeout = wl->conf.rx.ps_poll_timeout;
+ rx_timeout->upsd_timeout = wl->conf.rx.upsd_timeout;
ret = wl1271_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
rx_timeout, sizeof(*rx_timeout));
@@ -557,7 +557,7 @@ int wl1271_acx_cca_threshold(struct wl1271 *wl)
goto out;
}
- detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
+ detection->rx_cca_threshold = wl->conf.rx.rx_cca_threshold;
detection->tx_energy_detection = 0;
ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD,
@@ -966,10 +966,10 @@ int wl1271_acx_init_rx_interrupt(struct wl1271 *wl)
goto out;
}
- rx_conf->threshold = WL1271_RX_INTR_THRESHOLD_DEF;
- rx_conf->timeout = WL1271_RX_INTR_TIMEOUT_DEF;
- rx_conf->mblk_threshold = USHORT_MAX; /* Disabled */
- rx_conf->queue_type = RX_QUEUE_TYPE_RX_LOW_PRIORITY;
+ rx_conf->threshold = wl->conf.rx.irq_pkt_threshold;
+ rx_conf->timeout = wl->conf.rx.irq_timeout;
+ rx_conf->mblk_threshold = wl->conf.rx.irq_blk_threshold;
+ rx_conf->queue_type = wl->conf.rx.queue_type;
ret = wl1271_cmd_configure(wl, ACX_RX_CONFIG_OPT, rx_conf,
sizeof(*rx_conf));
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 8e3b97c..1fbd4e5 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -314,35 +314,13 @@ struct acx_dot11_grp_addr_tbl {
u8 mac_table[ADDRESS_GROUP_MAX_LEN];
} __attribute__ ((packed));
-#define RX_TIMEOUT_PS_POLL_MIN 0
-#define RX_TIMEOUT_PS_POLL_MAX (200000)
-#define RX_TIMEOUT_PS_POLL_DEF (15)
-#define RX_TIMEOUT_UPSD_MIN 0
-#define RX_TIMEOUT_UPSD_MAX (200000)
-#define RX_TIMEOUT_UPSD_DEF (15)
-
struct acx_rx_timeout {
struct acx_header header;
- /*
- * The longest time the STA will wait to receive
- * traffic from the AP after a PS-poll has been
- * transmitted.
- */
u16 ps_poll_timeout;
-
- /*
- * The longest time the STA will wait to receive
- * traffic from the AP after a frame has been sent
- * from an UPSD enabled queue.
- */
u16 upsd_timeout;
} __attribute__ ((packed));
-#define RTS_THRESHOLD_MIN 0
-#define RTS_THRESHOLD_MAX 4096
-#define RTS_THRESHOLD_DEF 2347
-
struct acx_rts_threshold {
struct acx_header header;
@@ -510,9 +488,6 @@ struct acx_bt_wlan_coex_param {
u8 padding[3];
} __attribute__ ((packed));
-#define CCA_THRSH_ENABLE_ENERGY_D 0x140A
-#define CCA_THRSH_DISABLE_ENERGY_D 0xFFEF
-
struct acx_energy_detection {
struct acx_header header;
@@ -1017,22 +992,6 @@ struct wl1271_acx_mem_map {
void *tx_ctrl;
} __attribute__ ((packed));
-enum wl1271_acx_rx_queue_type {
- RX_QUEUE_TYPE_RX_LOW_PRIORITY, /* All except the high priority */
- RX_QUEUE_TYPE_RX_HIGH_PRIORITY, /* Management and voice packets */
- RX_QUEUE_TYPE_NUM,
- RX_QUEUE_TYPE_MAX = USHORT_MAX
-};
-
-#define WL1271_RX_INTR_THRESHOLD_DEF 0 /* no pacing, send interrupt on
- * every event */
-#define WL1271_RX_INTR_THRESHOLD_MIN 0
-#define WL1271_RX_INTR_THRESHOLD_MAX 15
-
-#define WL1271_RX_INTR_TIMEOUT_DEF 5
-#define WL1271_RX_INTR_TIMEOUT_MIN 1
-#define WL1271_RX_INTR_TIMEOUT_MAX 100
-
struct wl1271_acx_rx_config_opt {
struct acx_header header;
@@ -1122,7 +1081,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power);
int wl1271_acx_feature_cfg(struct wl1271 *wl);
int wl1271_acx_mem_map(struct wl1271 *wl,
struct acx_header *mem_map, size_t len);
-int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time);
+int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl);
int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter);
int wl1271_acx_pd_threshold(struct wl1271 *wl);
int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time);
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
index 1d6a44b..8bf8bff 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -171,8 +171,93 @@ struct conf_sg_settings {
s8 rate_adaptation_snr;
};
+enum conf_rx_queue_type {
+ CONF_RX_QUEUE_TYPE_LOW_PRIORITY, /* All except the high priority */
+ CONF_RX_QUEUE_TYPE_HIGH_PRIORITY, /* Management and voice packets */
+};
+
+struct conf_rx_settings {
+ /*
+ * The maximum amount of time, in TU, before the
+ * firmware discards the MSDU.
+ *
+ * Range: 0 - 0xFFFFFFFF
+ */
+ u32 rx_msdu_life_time;
+
+ /*
+ * Packet detection threshold in the PHY.
+ *
+ * FIXME: details unknown.
+ */
+ u32 packet_detection_threshold;
+
+ /*
+ * The longest time the STA will wait to receive traffic from the AP
+ * after a PS-poll has been transmitted.
+ *
+ * Range: 0 - 200000
+ */
+ u16 ps_poll_timeout;
+ /*
+ * The longest time the STA will wait to receive traffic from the AP
+ * after a frame has been sent from an UPSD enabled queue.
+ *
+ * Range: 0 - 200000
+ */
+ u16 upsd_timeout;
+
+ /*
+ * The number of octets in an MPDU, below which an RTS/CTS
+ * handshake is not performed.
+ *
+ * Range: 0 - 4096
+ */
+ u16 rts_threshold;
+
+ /*
+ * The RX Clear Channel Assessment threshold in the PHY
+ * (the energy threshold).
+ *
+ * Range: ENABLE_ENERGY_D == 0x140A
+ * DISABLE_ENERGY_D == 0xFFEF
+ */
+ u16 rx_cca_threshold;
+
+ /*
+ * Occupied Rx mem-blocks number which requires interrupting the host
+ * (0 = no buffering, 0xffff = disabled).
+ *
+ * Range: u16
+ */
+ u16 irq_blk_threshold;
+
+ /*
+ * Rx packets number which requires interrupting the host
+ * (0 = no buffering).
+ *
+ * Range: u16
+ */
+ u16 irq_pkt_threshold;
+
+ /*
+ * Max time in msec the FW may delay RX-Complete interrupt.
+ *
+ * Range: 1 - 100
+ */
+ u16 irq_timeout;
+
+ /*
+ * The RX queue type.
+ *
+ * Range: RX_QUEUE_TYPE_RX_LOW_PRIORITY, RX_QUEUE_TYPE_RX_HIGH_PRIORITY,
+ */
+ u8 queue_type;
+};
+
struct conf_drv_settings {
struct conf_sg_settings sg;
+ struct conf_rx_settings rx;
};
#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 9abe062..5738263 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -94,7 +94,7 @@ static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
{
int ret;
- ret = wl1271_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF);
+ ret = wl1271_acx_rx_msdu_life_time(wl);
if (ret < 0)
return ret;
@@ -125,7 +125,7 @@ static int wl1271_init_phy_config(struct wl1271 *wl)
if (ret < 0)
return ret;
- ret = wl1271_acx_rts_threshold(wl, RTS_THRESHOLD_DEF);
+ ret = wl1271_acx_rts_threshold(wl, wl->conf.rx.rts_threshold);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 69bc929..d04706d 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -61,6 +61,18 @@ static void wl1271_conf_init(struct wl1271 *wl)
.beacon_miss_threshold = 60,
.rate_adaptation_threshold = CONF_HW_BIT_RATE_12MBPS,
.rate_adaptation_snr = 0
+ },
+ .rx = {
+ .rx_msdu_life_time = 512000,
+ .packet_detection_threshold = 0,
+ .ps_poll_timeout = 15,
+ .upsd_timeout = 15,
+ .rts_threshold = 2347,
+ .rx_cca_threshold = 0xFFEF,
+ .irq_blk_threshold = 0,
+ .irq_pkt_threshold = USHORT_MAX,
+ .irq_timeout = 5,
+ .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
}
};
--
1.5.6.5
^ permalink raw reply related
* [PATCH 14/22] wl1271: Added 5 GHz support to join and rx
From: Luciano Coelho @ 2009-10-13 9:47 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Teemu Paasikivi
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>
From: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Added support to assiociate and use connection on 5 GHz band (802.11a).
Signed-off-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
drivers/net/wireless/wl12xx/wl1271_cmd.c | 13 ++++++-
drivers/net/wireless/wl12xx/wl1271_cmd.h | 1 +
drivers/net/wireless/wl12xx/wl1271_rx.c | 57 ++++++++++++++++++++++++------
3 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 6d7a40c..fe4f1e6 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -219,6 +219,7 @@ int wl1271_cmd_join(struct wl1271 *wl)
join->rx_config_options = wl->rx_config;
join->rx_filter_options = wl->rx_filter;
+ join->bss_type = wl->bss_type;
/*
* FIXME: disable temporarily all filters because after commit
@@ -229,12 +230,20 @@ int wl1271_cmd_join(struct wl1271 *wl)
join->rx_config_options = 0;
join->rx_filter_options = WL1271_DEFAULT_RX_FILTER;
- join->basic_rate_set = CONF_HW_BIT_RATE_1MBPS | CONF_HW_BIT_RATE_2MBPS |
+ if (wl->band == IEEE80211_BAND_2GHZ)
+ join->basic_rate_set =
+ CONF_HW_BIT_RATE_1MBPS | CONF_HW_BIT_RATE_2MBPS |
CONF_HW_BIT_RATE_5_5MBPS | CONF_HW_BIT_RATE_11MBPS;
+ else {
+ join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
+ join->basic_rate_set =
+ CONF_HW_BIT_RATE_6MBPS | CONF_HW_BIT_RATE_12MBPS |
+ CONF_HW_BIT_RATE_24MBPS;
+ }
join->beacon_interval = WL1271_DEFAULT_BEACON_INT;
join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD;
- join->bss_type = wl->bss_type;
+
join->channel = wl->channel;
join->ssid_len = wl->ssid_len;
memcpy(join->ssid, wl->ssid, wl->ssid_len);
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index 3308940..15254fa 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -198,6 +198,7 @@ enum {
#define WL1271_JOIN_CMD_CTRL_TX_FLUSH 0x80 /* Firmware flushes all Tx */
#define WL1271_JOIN_CMD_TX_SESSION_OFFSET 1
+#define WL1271_JOIN_CMD_BSS_TYPE_5GHZ 0x10
struct wl1271_cmd_join {
struct wl1271_cmd_header header;
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index 66b83e9..1dd8458 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -70,6 +70,36 @@ static u8 wl1271_rx_rate_to_idx[] = {
0 /* WL1271_RATE_1 */
};
+/* The values of this table must match the wl1271_rates[] array */
+static u8 wl1271_5_ghz_rx_rate_to_idx[] = {
+ /* MCS rates are used only with 11n */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */
+
+ 7, /* WL1271_RATE_54 */
+ 6, /* WL1271_RATE_48 */
+ 5, /* WL1271_RATE_36 */
+ 4, /* WL1271_RATE_24 */
+
+ /* TI-specific rate */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */
+
+ 3, /* WL1271_RATE_18 */
+ 2, /* WL1271_RATE_12 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_11 */
+ 1, /* WL1271_RATE_9 */
+ 0, /* WL1271_RATE_6 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_5_5 */
+ WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_2 */
+ WL1271_RX_RATE_UNSUPPORTED /* WL1271_RATE_1 */
+};
+
static void wl1271_rx_status(struct wl1271 *wl,
struct wl1271_rx_descriptor *desc,
struct ieee80211_rx_status *status,
@@ -77,15 +107,21 @@ static void wl1271_rx_status(struct wl1271 *wl,
{
memset(status, 0, sizeof(struct ieee80211_rx_status));
- if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG)
+ if ((desc->flags & WL1271_RX_DESC_BAND_MASK) ==
+ WL1271_RX_DESC_BAND_BG) {
status->band = IEEE80211_BAND_2GHZ;
- else if ((desc->flags & WL1271_RX_DESC_BAND_MASK) ==
- WL1271_RX_DESC_BAND_A)
+ status->rate_idx = wl1271_rx_rate_to_idx[desc->rate];
+ } else if ((desc->flags & WL1271_RX_DESC_BAND_MASK) ==
+ WL1271_RX_DESC_BAND_A) {
status->band = IEEE80211_BAND_5GHZ;
- else
+ status->rate_idx = wl1271_5_ghz_rx_rate_to_idx[desc->rate];
+ } else
wl1271_warning("unsupported band 0x%x",
desc->flags & WL1271_RX_DESC_BAND_MASK);
+ if (unlikely(status->rate_idx == WL1271_RX_RATE_UNSUPPORTED))
+ wl1271_warning("unsupported rate");
+
/*
* FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the
* timestamp from the beacon (acx_tsf_info). In BSS mode (infra) we
@@ -108,15 +144,14 @@ static void wl1271_rx_status(struct wl1271 *wl,
if (likely(!(desc->flags & WL1271_RX_DESC_DECRYPT_FAIL)))
status->flag |= RX_FLAG_DECRYPTED;
-
+ /* FIXME: Flag should be also set when using 5 GHz band.
+ * At the moment chip reports MIC failed on all packets,
+ * so flag is silently discarded.
+ */
if (unlikely(desc->flags & WL1271_RX_DESC_MIC_FAIL))
- status->flag |= RX_FLAG_MMIC_ERROR;
+ if (status->band != IEEE80211_BAND_5GHZ)
+ status->flag |= RX_FLAG_MMIC_ERROR;
}
-
- status->rate_idx = wl1271_rx_rate_to_idx[desc->rate];
-
- if (status->rate_idx == WL1271_RX_RATE_UNSUPPORTED)
- wl1271_warning("unsupported rate");
}
static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
--
1.5.6.5
^ permalink raw reply related
* [PATCH 10/22] wl1271: Remove busy-word checking
From: Luciano Coelho @ 2009-10-13 9:47 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>
From: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Remove busy-word checking to work around an SPI bug. To reduce the
chance of chipset-busy scenarios, increment the number of fixed busy
words.
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
drivers/net/wireless/wl12xx/wl1271.h | 6 ++++--
drivers/net/wireless/wl12xx/wl1271_spi.c | 6 +++---
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 648223f..e0ebb1f 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -115,9 +115,11 @@ enum {
/*
* FIXME: for the wl1271, a busy word count of 1 here will result in a more
* optimal SPI interface. There is some SPI bug however, causing RXS time outs
- * with this mode occasionally on boot, so lets have two for now.
+ * with this mode occasionally on boot, so lets have three for now. A value of
+ * three should make sure, that the chipset will always be ready, though this
+ * will impact throughput and latencies slightly.
*/
-#define WL1271_BUSY_WORD_CNT 2
+#define WL1271_BUSY_WORD_CNT 3
#define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32))
#define WL1271_ELP_HW_STATE_ASLEEP 0
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index 4800fdf..3c5aa58 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -294,9 +294,9 @@ void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
spi_sync(wl->spi, &m);
- /* Check busy words */
- if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1))
- wl1271_spi_read_busy(wl, buf, len);
+ /* FIXME: Check busy words, removed due to SPI bug */
+ /* if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1))
+ wl1271_spi_read_busy(wl, buf, len); */
wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
--
1.5.6.5
^ permalink raw reply related
* [PATCH 16/22] wl1271: Fix multicast list handling
From: Luciano Coelho @ 2009-10-13 9:47 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>
From: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Fixes bugs in the multicast list handling:
- Use atomic memory allocation in non-sleepable context
- Increment address pointer when iterating list of MC addresses
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index ae41a70..19dbdb1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1160,7 +1160,7 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
* configure_filter() instead of saving everything in the context.
*/
- fp = kzalloc(sizeof(*fp), GFP_KERNEL);
+ fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
if (!fp) {
wl1271_error("Out of memory setting filters.");
return 0;
@@ -1180,6 +1180,7 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
fp->mc_list_length++;
} else
wl1271_warning("Unknown mc address length.");
+ mc_list = mc_list->next;
}
/* FIXME: We still need to set our filters properly */
--
1.5.6.5
^ permalink raw reply related
* [PATCH 12/22] wl1271: Scan only enabled channels
From: Luciano Coelho @ 2009-10-13 9:47 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Teemu Paasikivi
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>
From: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Added checking of whether channel is enabled or disabled by mac80211
stack to scan. Disabled channels are not scanned.
Signed-off-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
drivers/net/wireless/wl12xx/wl1271_cmd.c | 33 +++++++++++++++++++----------
1 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index f38e3e0..204e872 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -515,12 +515,16 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
struct wl1271_cmd_trigger_scan_to *trigger = NULL;
struct wl1271_cmd_scan *params = NULL;
- int i, ret;
+ struct ieee80211_channel *channels;
+ int i, j, n_ch, ret;
u16 scan_options = 0;
if (wl->scanning)
return -EINVAL;
+ channels = wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels;
+ n_ch = wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->n_channels;
+
params = kzalloc(sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;
@@ -535,24 +539,29 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
scan_options |= WL1271_SCAN_OPT_PRIORITY_HIGH;
params->params.scan_options = scan_options;
- params->params.num_channels = num_channels;
params->params.num_probe_requests = probe_requests;
params->params.tx_rate = cpu_to_le32(CONF_HW_BIT_RATE_2MBPS);
params->params.tid_trigger = 0;
params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
- for (i = 0; i < num_channels; i++) {
- params->channels[i].min_duration =
- cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
- params->channels[i].max_duration =
- cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
- memset(¶ms->channels[i].bssid_lsb, 0xff, 4);
- memset(¶ms->channels[i].bssid_msb, 0xff, 2);
- params->channels[i].early_termination = 0;
- params->channels[i].tx_power_att = WL1271_SCAN_CURRENT_TX_PWR;
- params->channels[i].channel = i + 1;
+ for (i = 0, j = 0; i < n_ch && i < WL1271_SCAN_MAX_CHANNELS; i++) {
+ if (!(channels[i].flags & IEEE80211_CHAN_DISABLED)) {
+ params->channels[j].min_duration =
+ cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
+ params->channels[j].max_duration =
+ cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
+ memset(¶ms->channels[j].bssid_lsb, 0xff, 4);
+ memset(¶ms->channels[j].bssid_msb, 0xff, 2);
+ params->channels[j].early_termination = 0;
+ params->channels[j].tx_power_att =
+ WL1271_SCAN_CURRENT_TX_PWR;
+ params->channels[j].channel = channels[i].hw_value;
+ j++;
+ }
}
+ params->params.num_channels = j;
+
if (len && ssid) {
params->params.ssid_len = len;
memcpy(params->params.ssid, ssid, len);
--
1.5.6.5
^ permalink raw reply related
* [PATCH 20/22] wl1271: Correct memory handling for FW boot
From: Luciano Coelho @ 2009-10-13 9:47 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>
From: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Several memory allocation related failure cases were not properly
handled by the driver - the result was that in low memory conditions
booting of a corrupted FW could be attempted - and user space would not
get proper failure code.
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
drivers/net/wireless/wl12xx/wl1271_boot.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index b8a37a8..41a3050 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -134,7 +134,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
}
chunk = kmalloc(CHUNK_SIZE, GFP_KERNEL);
- if (!buf) {
+ if (!chunk) {
wl1271_error("allocation for firmware upload chunk failed");
return -ENOMEM;
}
@@ -184,6 +184,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
static int wl1271_boot_upload_firmware(struct wl1271 *wl)
{
u32 chunks, addr, len;
+ int ret = 0;
u8 *fw;
fw = wl->fw;
@@ -204,11 +205,13 @@ static int wl1271_boot_upload_firmware(struct wl1271 *wl)
}
wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u",
chunks, addr, len);
- wl1271_boot_upload_firmware_chunk(wl, fw, len, addr);
+ ret = wl1271_boot_upload_firmware_chunk(wl, fw, len, addr);
+ if (ret != 0)
+ break;
fw += len;
}
- return 0;
+ return ret;
}
static int wl1271_boot_upload_nvs(struct wl1271 *wl)
@@ -284,6 +287,8 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
/* Copy the NVS tables to a new block to ensure alignment */
nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
+ if (!nvs_aligned)
+ return -ENOMEM;
/* And finally we upload the NVS tables */
/* FIXME: In wl1271, we upload everything at once.
--
1.5.6.5
^ permalink raw reply related
* [PATCH 15/22] wl1271: Checking of rx descriptor status fixed
From: Luciano Coelho @ 2009-10-13 9:47 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, Teemu Paasikivi
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>
From: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Fixed checking of status of the received packet. On wl1251 status is in the
flags field of the descriptor, on wl1271 there is a separate status field.
Signed-off-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
drivers/net/wireless/wl12xx/wl1271_rx.c | 11 +++--------
1 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index 1dd8458..1ea3f41 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -142,15 +142,10 @@ static void wl1271_rx_status(struct wl1271 *wl,
if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) {
status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
- if (likely(!(desc->flags & WL1271_RX_DESC_DECRYPT_FAIL)))
+ if (likely(!(desc->status & WL1271_RX_DESC_DECRYPT_FAIL)))
status->flag |= RX_FLAG_DECRYPTED;
- /* FIXME: Flag should be also set when using 5 GHz band.
- * At the moment chip reports MIC failed on all packets,
- * so flag is silently discarded.
- */
- if (unlikely(desc->flags & WL1271_RX_DESC_MIC_FAIL))
- if (status->band != IEEE80211_BAND_5GHZ)
- status->flag |= RX_FLAG_MMIC_ERROR;
+ if (unlikely(desc->status & WL1271_RX_DESC_MIC_FAIL))
+ status->flag |= RX_FLAG_MMIC_ERROR;
}
}
--
1.5.6.5
^ permalink raw reply related
* Current status of rt2800usb and staging/rt2870
From: Ozan Çağlayan @ 2009-10-13 11:24 UTC (permalink / raw)
To: linux-wireless, linux-kernel
Hi,
In 2.6.31, there are USB device IDs common between both drivers. Should
a distribution enable both drivers? What do you suggest? Are there any
*known issues* stuff for one of them?
Regards, thanks
Ozan Caglayan
^ permalink raw reply
* [PATCH] cfg80211: remove warning in deauth case
From: Holger Schurig @ 2009-10-13 11:45 UTC (permalink / raw)
To: linux-wireless, John W. Linville; +Cc: Johannes Berg
It might be the case that __cfg80211_disconnected() has already
cleaned up wdev->current_bss() for us. The old code didn't catch
that situation and didn't warn needlessly.
Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de>
---
For more info, see mail "cfg80211 / libertas: an unusual race"
in the linux-wireless mailing list.
--- linux-wl.orig/net/wireless/mlme.c
+++ linux-wl/net/wireless/mlme.c
@@ -130,7 +130,6 @@
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
const u8 *bssid = mgmt->bssid;
int i;
- bool done = false;
ASSERT_WDEV_LOCK(wdev);
@@ -138,7 +137,6 @@
if (wdev->current_bss &&
memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
- done = true;
cfg80211_unhold_bss(wdev->current_bss);
cfg80211_put_bss(&wdev->current_bss->pub);
wdev->current_bss = NULL;
@@ -148,7 +146,6 @@
cfg80211_unhold_bss(wdev->auth_bsses[i]);
cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
wdev->auth_bsses[i] = NULL;
- done = true;
break;
}
if (wdev->authtry_bsses[i] &&
@@ -156,13 +153,10 @@
cfg80211_unhold_bss(wdev->authtry_bsses[i]);
cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
wdev->authtry_bsses[i] = NULL;
- done = true;
break;
}
}
- WARN_ON(!done);
-
if (wdev->sme_state == CFG80211_SME_CONNECTED) {
u16 reason_code;
bool from_ap;
--
http://www.holgerschurig.de
^ permalink raw reply
* [PATCH] rt73usb.c : more ids
From: Xose Vazquez Perez @ 2009-10-13 11:47 UTC (permalink / raw)
To: linux-wireless, users, IvDoorn
[-- Attachment #1: Type: text/plain, Size: 410 bytes --]
hi,
stolen from windows inf file(07/17/2009, 1.03.05.0000)
Ovislink 0x1b75, 0x7318
MSI 0x0db0, 0x4600
WideTell 0x7167, 0x3840
-thanks-
regards,
--
«Allá muevan feroz guerra, ciegos reyes por un palmo más de tierra;
que yo aquí tengo por mío cuanto abarca el mar bravío, a quien nadie
impuso leyes. Y no hay playa, sea cualquiera, ni bandera de esplendor,
que no sienta mi derecho y dé pecho a mi valor.»
[-- Attachment #2: new_id-73usb.diff --]
[-- Type: text/plain, Size: 1205 bytes --]
--- o/drivers/net/wireless/rt73usb.c 2009-10-13 12:58:32.042380351 +0200
+++ n/drivers/net/wireless/rt73usb.c 2009-10-13 13:01:01.073379225 +0200
@@ -2389,10 +2389,13 @@
{ USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) },
/* MSI */
+ { USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) },
+ /* Ovislink */
+ { USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
/* Ralink */
{ USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) },
@@ -2420,6 +2423,8 @@
/* Planex */
{ USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) },
+ /* WideTell */
+ { USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) },
/* Zcom */
{ USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) },
/* ZyXEL */
^ permalink raw reply
* Re: [PATCH V3] iwlwifi: use paged Rx
From: Stanislaw Gruszka @ 2009-10-13 11:51 UTC (permalink / raw)
To: Zhu Yi; +Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org
In-Reply-To: <1255421948.3719.363.camel@debian>
On Tue, Oct 13, 2009 at 04:19:08PM +0800, Zhu Yi wrote:
> > > Finally, mac80211 doesn't support paged Rx yet. So we linearize the skb
> > > for all the management frames and software decryption or defragmentation
> > > required data frames before handed to mac80211. For all the other frames,
> > > we __pskb_pull_tail 64 bytes in the linear area of the skb for mac80211
> > > to handle them properly.
> >
> > This seems to be big overhead, but since there is no way to avoid it ...
>
> Which case? The linear one is the same as the current implementation.
Considering swcrypt for example. This patch make things worse as we still
need to do the same skb allocation as before, plus additional pages allocation,
plus additional memcpy. No ?
Cheers
Stanislaw
^ permalink raw reply
* Error Installing 'iw'
From: Pramono Tunggul @ 2009-10-13 18:53 UTC (permalink / raw)
To: linux-wireless
Guyz, when I try to start airmon-ng, it said that I have to install iw,
so I download and install iw but I have never succeed to install iw,
PACKAGE_CONFIG_PATH=/usr/lib
export PACKAGE_CONFIG_PATH
make
CC iw.o
In file included from /usr/local/include/netlink/netlink.h:23,
from /usr/include/netlink/genl/genl.h:15,
from iw.c:17:
/usr/local/include/netlink/netlink-kernel.h:222: error: expected
specifier-qualifier-list before ‘__u32’
/usr/local/include/netlink/netlink-kernel.h:232: error: expected
specifier-qualifier-list before ‘__u16’
In file included from /usr/local/include/netlink/netlink.h:24,
from /usr/include/netlink/genl/genl.h:15,
from iw.c:17:
/usr/local/include/netlink/rtnetlink-kernel.h:281: error: expected
specifier-qualifier-list before ‘__u32’
/usr/local/include/netlink/rtnetlink-kernel.h:342: error: expected
specifier-qualifier-list before ‘__u8’
/usr/local/include/netlink/rtnetlink-kernel.h:403: error: expected
specifier-qualifier-list before ‘__u32’
/usr/local/include/netlink/rtnetlink-kernel.h:431: error: expected
specifier-qualifier-list before ‘__u16’
/usr/local/include/netlink/rtnetlink-kernel.h:477: error: expected
specifier-qualifier-list before ‘__u32’
/usr/local/include/netlink/rtnetlink-kernel.h:498: error: expected
specifier-qualifier-list before ‘__u64’
/usr/local/include/netlink/rtnetlink-kernel.h:533: error: expected
specifier-qualifier-list before ‘__u8’
/usr/local/include/netlink/rtnetlink-kernel.h:540: error: expected
specifier-qualifier-list before ‘__u16’
/usr/local/include/netlink/rtnetlink-kernel.h:622: error: expected
specifier-qualifier-list before ‘__u32’
/usr/local/include/netlink/rtnetlink-kernel.h:629: error: expected
specifier-qualifier-list before ‘__u32’
/usr/local/include/netlink/rtnetlink-kernel.h:663: error: expected
specifier-qualifier-list before ‘__u64’
/usr/local/include/netlink/rtnetlink-kernel.h:751: error: expected
specifier-qualifier-list before ‘__u32’
/usr/local/include/netlink/rtnetlink-kernel.h:767: error: expected
specifier-qualifier-list before ‘__u32’
iw.c: In function ‘error_handler’:
iw.c:237: error: ‘NL_STOP’ undeclared (first use in this function)
iw.c:237: error: (Each undeclared identifier is reported only once
iw.c:237: error: for each function it appears in.)
iw.c: In function ‘ack_handler’:
iw.c:251: error: ‘NL_STOP’ undeclared (first use in this function)
iw.c: In function ‘__handle_cmd’:
iw.c:367: error: implicit declaration of function ‘nlmsg_alloc’
iw.c:367: warning: assignment makes pointer from integer without a cast
iw.c:373: error: implicit declaration of function ‘nl_cb_alloc’
iw.c:373: warning: assignment makes pointer from integer without a cast
iw.c:411: error: implicit declaration of function ‘nl_cb_put’
make: *** [iw.o] Error 1
Would you mind telling me how to install iw??
Thank you
Regards,
Pramono Tunggul
^ permalink raw reply
* Re: [PATCH] rt2800pci.c : more ids
From: Xose Vazquez Perez @ 2009-10-13 12:12 UTC (permalink / raw)
Cc: linux-wireless, users, IvDoorn
In-Reply-To: <4AD434B6.3090903@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 498 bytes --]
On 10/13/2009 10:05 AM, Xose Vazquez Perez wrote:
> stolen from windows inf file(09/05/2009, 1.04.07.0000)
>
> 0x1814, 0x3060
apply this one instead,
got 0x1462,0x89a from linux driver(2009_0903_RT3090_Linux_STA_v2.2.0.1)
-thanks-
--
«Allá muevan feroz guerra, ciegos reyes por un palmo más de tierra;
que yo aquí tengo por mío cuanto abarca el mar bravío, a quien nadie
impuso leyes. Y no hay playa, sea cualquiera, ni bandera de esplendor,
que no sienta mi derecho y dé pecho a mi valor.»
[-- Attachment #2: new_id-2800pci-v2.diff --]
[-- Type: text/plain, Size: 1273 bytes --]
--- o/drivers/net/wireless/rt2800pci.c 2009-10-13 09:57:37.523379731 +0200
+++ n/drivers/net/wireless/rt2800pci.c 2009-10-13 14:10:12.785378782 +0200
@@ -3225,6 +3225,8 @@
* RT2800pci module information.
*/
static struct pci_device_id rt2800pci_device_table[] = {
+ /* ??? */
+ { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) },
/* Edimax */
{ PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) },
@@ -3233,10 +3235,12 @@
{ PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) },
+ /* Ralink */
{ PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) },
+ { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) },
{ PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) },
^ permalink raw reply
* RE: [PATCH V3] iwlwifi: use paged Rx
From: Zhu, Yi @ 2009-10-13 12:44 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org
In-Reply-To: <20091013115110.GA2639@dhcp-lab-161.englab.brq.redhat.com>
> From: Stanislaw Gruszka [mailto:sgruszka@redhat.com]
> > Which case? The linear one is the same as the current implementation.
>
> Considering swcrypt for example. This patch make things worse as we still
> need to do the same skb allocation as before, plus additional pages allocation,
> plus additional memcpy. No ?
Yes. But software encryption is only used for debugging purpose by iwlagn.
Thanks,
-yi
^ permalink raw reply
* Re: [rt2x00-users] [PATCH] rt73usb.c : more ids
From: John W. Linville @ 2009-10-13 14:56 UTC (permalink / raw)
To: rt2x00 Users List; +Cc: linux-wireless
In-Reply-To: <880c1630910130520p30c06846k8692634ec277340@mail.gmail.com>
On Tue, Oct 13, 2009 at 01:20:17PM +0100, Luis Correia wrote:
> Hi Xose,
>
> 2009/10/13 Xose Vazquez Perez <xose.vazquez@gmail.com>
>
> > hi,
> >
> > stolen from windows inf file(07/17/2009, 1.03.05.0000)
> > Ovislink 0x1b75, 0x7318
> > MSI 0x0db0, 0x4600
> > WideTell 0x7167, 0x3840
> >
> >
> > -thanks-
> >
> > regards,
> >
>
> Are you absolutely sure that these devices are really rt73usb?
>
> By being in the windows inf file doesn't mean they would work in Linux.
>
> Luis Correia,
> rt2x00 project admin
Please also post patches in the correct format (especially including
the Signed-off-by):
http://linux.yyz.us/patch-format.html
--
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
* pull request: wireless-2.6 2009-10-13
From: John W. Linville @ 2009-10-13 15:05 UTC (permalink / raw)
To: davem; +Cc: linux-wireless, netdev, linux-kernel
Dave,
Here are a few (almost-)one-liners for 2.6.32. Included are fixes for
a use-after-free, a missing "!" in front of a memcmp when comparing
BSSIDs, a race when using hardware-based scanning, the ieee80211_rx
context problem, a related documentation change, and a minor build
issue.
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 10c435f18b8cb78a5870c08d52955594f5ec9c31:
David S. Miller (1):
net: Link in PHY drivers before others.
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git master
Alan Cox (1):
libertas: fix build
Felix Fietkau (1):
mac80211: fix logic error ibss merge bssid check
Johannes Berg (3):
mac80211: fix ibss race
b43: fix ieee80211_rx() context
mac80211: document ieee80211_rx() context requirement
Wey-Yi Guy (1):
iwlwifi: change the order of freeing memory
drivers/net/wireless/b43/xmit.c | 3 +++
drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +-
drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +-
drivers/net/wireless/libertas/cmdresp.c | 1 +
include/net/mac80211.h | 2 ++
net/mac80211/ibss.c | 4 ++--
net/mac80211/rx.c | 2 ++
7 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 892573b..f4e9695 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -690,7 +690,10 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
}
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+
+ local_bh_disable();
ieee80211_rx(dev->wl->hw, skb);
+ local_bh_enable();
#if B43_DEBUG
dev->rx_count++;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index cdc07c4..9b5ea8b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3105,8 +3105,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
out_pci_disable_device:
pci_disable_device(pdev);
out_ieee80211_free_hw:
- ieee80211_free_hw(priv->hw);
iwl_free_traffic_mem(priv);
+ ieee80211_free_hw(priv->hw);
out:
return err;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index c390dbd..837a193 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -4096,8 +4096,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
out_ieee80211_free_hw:
- ieee80211_free_hw(priv->hw);
iwl_free_traffic_mem(priv);
+ ieee80211_free_hw(priv->hw);
out:
return err;
}
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index c42d3fa..23f6843 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -3,6 +3,7 @@
* responses as well as events generated by firmware.
*/
#include <linux/delay.h>
+#include <linux/sched.h>
#include <linux/if_arp.h>
#include <linux/netdevice.h>
#include <asm/unaligned.h>
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 466859b..c75b960 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1669,6 +1669,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw);
* to this function and ieee80211_rx_irqsafe() may not be mixed for a
* single hardware.
*
+ * Note that right now, this function must be called with softirqs disabled.
+ *
* @hw: the hardware this frame came in on
* @skb: the buffer to receive, owned by mac80211 after this call
*/
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 920ec87..6eaf698 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -544,7 +544,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
"%pM\n", bss->cbss.bssid, ifibss->bssid);
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
- if (bss && memcmp(ifibss->bssid, bss->cbss.bssid, ETH_ALEN)) {
+ if (bss && !memcmp(ifibss->bssid, bss->cbss.bssid, ETH_ALEN)) {
printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM"
" based on configured SSID\n",
sdata->dev->name, bss->cbss.bssid);
@@ -829,7 +829,7 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
if (!sdata->u.ibss.ssid_len)
continue;
sdata->u.ibss.last_scan_completed = jiffies;
- ieee80211_sta_find_ibss(sdata);
+ mod_timer(&sdata->u.ibss.timer, 0);
}
mutex_unlock(&local->iflist_mtx);
}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 865fbc0..7170bf4 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2453,6 +2453,8 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
struct ieee80211_supported_band *sband;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+ WARN_ON_ONCE(softirq_count() == 0);
+
if (WARN_ON(status->band < 0 ||
status->band >= IEEE80211_NUM_BANDS))
goto drop;
--
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: Current status of rt2800usb and staging/rt2870
From: Ivo van Doorn @ 2009-10-13 15:52 UTC (permalink / raw)
To: Ozan Çağlayan; +Cc: linux-wireless, linux-kernel
In-Reply-To: <4AD46380.9020308@pardus.org.tr>
Hi,
> In 2.6.31, there are USB device IDs common between both drivers.
That is because they are drivers for the same hardware.
> Should a distribution enable both drivers? What do you suggest? Are there any
> *known issues* stuff for one of them?
The staging/rt2870 should actually be removed from the kernel tree,
I am going to merge rt2800pci soon as well and after that I'll send a patch
to remove all Ralink drivers from the staging tree.
As for known issues:
- staging/rt2870 is a piece of crap which apparently works for some people
but isn't generally stable or reliable
- wireless/rt2800usb follows the kernel coding style/rules and uses mac80211
but isn't showing a high quality for usability.
Ivo
^ permalink raw reply
* Re: Current status of rt2800usb and staging/rt2870
From: Bartlomiej Zolnierkiewicz @ 2009-10-13 16:44 UTC (permalink / raw)
To: Ozan Çağlayan; +Cc: linux-wireless, linux-kernel
In-Reply-To: <4AD46380.9020308@pardus.org.tr>
Hi,
On Tuesday 13 October 2009 13:24:48 Ozan Çağlayan wrote:
> Hi,
>
> In 2.6.31, there are USB device IDs common between both drivers. Should
> a distribution enable both drivers? What do you suggest? Are there any
> *known issues* stuff for one of them?
My advice to distributions for such situations is to ship both but make
one driver the default one. This provides users with better overall
hardware coverage and flexibility. Additionally by providing the ability
for direct comparison of both drivers it makes driver authors/maintainers
try really hard at making the final solution work for everybody (instead
of just making it work for their needs only etc.).
Best regards,
Bartlomiej
^ permalink raw reply
* Re: 2.6.32-rc4 ipw2200: oops on missing firmware
From: Frans Pop @ 2009-10-13 16:55 UTC (permalink / raw)
To: Ferenc Wagner
Cc: linux-kernel, ipw2100-devel, linux-wireless, Reinette Chatre
In-Reply-To: <87hbu3h023.fsf@tac.ki.iif.hu>
Adding relevant CCs. Original message follows.
==============
Hi,
See the screenshot at http://apt.niif.hu/ipw_oops.png. During bootup,
initramfs-tools tried to load the ipw2200 module, but nobody fed it
the necessary firmware, so request_firmware timed out and the module
unload cleanup oopsed in device_pm_remove:
void device_pm_remove(struct device *dev)
{
pr_debug("PM: Removing info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus",
kobject_name(&dev->kobj));
mutex_lock(&dpm_list_mtx);
list_del_init(&dev->power.entry);
mutex_unlock(&dpm_list_mtx);
pm_runtime_remove(dev);
}
00000a0a <device_pm_remove>:
a0a: 55 push %ebp
a0b: 89 e5 mov %esp,%ebp
a0d: 53 push %ebx
a0e: 89 c3 mov %eax,%ebx
a10: b8 08 00 00 00 mov $0x8,%eax
a15: e8 fc ff ff ff call a16 <device_pm_remove+0xc>
a1a: 8d 4b 5c lea 0x5c(%ebx),%ecx
a1d: 8b 53 5c mov 0x5c(%ebx),%edx
a20: 8b 43 60 mov 0x60(%ebx),%eax
a23: 89 42 04 mov %eax,0x4(%edx)
a26: 89 10 mov %edx,(%eax)
a28: 89 4b 5c mov %ecx,0x5c(%ebx)
a2b: 89 4b 60 mov %ecx,0x60(%ebx)
a2e: b8 08 00 00 00 mov $0x8,%eax
a33: e8 fc ff ff ff call a34 <device_pm_remove+0x2a>
a38: 89 d8 mov %ebx,%eax
a3a: e8 fc ff ff ff call a3b <device_pm_remove+0x31>
a3f: 5b pop %ebx
a40: 5d pop %ebp
a41: c3 ret
The offending IP translates to line a23, so the problem is edx being 0
at that point. I'm not sure which struct device field has offset
0x5c, maybe power, but I'm lost at this point anyway.
I don't know whether it's a new bug or not, never did such insane
things previously. rmmod ipw2200 definitely worked under 2.6.31, and
it's possible that it works under 2.6.32-rc4 too, I forgot to check
that (but will do so tonight).
--
Regards,
Feri.
^ permalink raw reply
* [PATCH] rx51: add wl1251 wlan driver support
From: Kalle Valo @ 2009-10-13 16:58 UTC (permalink / raw)
To: linux-omap; +Cc: linux-wireless
From: Kalle Valo <kalle.valo@nokia.com>
wl1251 is connected to the SPI bus in rx51, add support for this.
Signed-off-by: Kalle Valo <kalle.valo@nokia.com>
---
arch/arm/mach-omap2/board-rx51-peripherals.c | 85 ++++++++++++++++++++++++++
1 files changed, 85 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index c1af532..ccb8656 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/spi/spi.h>
+#include <linux/spi/wl12xx.h>
#include <linux/i2c.h>
#include <linux/i2c/twl4030.h>
#include <linux/clk.h>
@@ -36,6 +37,37 @@
#define SYSTEM_REV_B_USES_VAUX3 0x1699
#define SYSTEM_REV_S_USES_VAUX3 0x8
+#define RX51_WL1251_POWER_GPIO 87
+#define RX51_WL1251_IRQ_GPIO 42
+
+static void rx51_wl1251_set_power(bool enable);
+
+static struct wl12xx_platform_data wl1251_pdata = {
+ .set_power = rx51_wl1251_set_power,
+};
+
+static struct omap2_mcspi_device_config wl1251_mcspi_config = {
+ .turbo_mode = 0,
+ .single_channel = 1,
+};
+
+/* list all spi devices here */
+enum {
+ RX51_SPI_WL1251,
+};
+
+static struct spi_board_info rx51_peripherals_spi_board_info[] = {
+ [RX51_SPI_WL1251] = {
+ .modalias = "wl1251",
+ .bus_num = 4,
+ .chip_select = 0,
+ .max_speed_hz = 48000000,
+ .mode = SPI_MODE_2,
+ .controller_data = &wl1251_mcspi_config,
+ .platform_data = &wl1251_pdata,
+ },
+};
+
static int board_keymap[] = {
KEY(0, 0, KEY_Q),
KEY(0, 1, KEY_O),
@@ -257,6 +289,55 @@ static struct regulator_init_data rx51_vdac = {
},
};
+static void rx51_wl1251_set_power(bool enable)
+{
+ gpio_set_value(RX51_WL1251_POWER_GPIO, enable);
+}
+
+static void __init rx51_init_wl1251(void)
+{
+ int irq, ret;
+
+ ret = gpio_request(RX51_WL1251_POWER_GPIO, "wl1251 power");
+ if (ret < 0)
+ goto error;
+
+ ret = gpio_direction_output(RX51_WL1251_POWER_GPIO, 0);
+ if (ret < 0)
+ goto err_power;
+
+ ret = gpio_request(RX51_WL1251_IRQ_GPIO, "wl1251 irq");
+ if (ret < 0)
+ goto err_power;
+
+ ret = gpio_direction_input(RX51_WL1251_IRQ_GPIO);
+ if (ret < 0)
+ goto err_irq;
+
+ irq = gpio_to_irq(RX51_WL1251_IRQ_GPIO);
+ if (irq < 0)
+ goto err_irq;
+
+ rx51_peripherals_spi_board_info[RX51_SPI_WL1251].irq = irq;
+
+ return;
+
+err_irq:
+ gpio_free(RX51_WL1251_IRQ_GPIO);
+
+err_power:
+ gpio_free(RX51_WL1251_POWER_GPIO);
+
+error:
+ printk(KERN_ERR "wl1251 board initialisation failed\n");
+ wl1251_pdata.set_power = NULL;
+
+ /*
+ * Now rx51_peripherals_spi_board_info[1].irq is zero and
+ * set_power is null, and wl1251_probe() will fail.
+ */
+}
+
static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n)
{
/* FIXME this gpio setup is just a placeholder for now */
@@ -538,6 +619,10 @@ static inline void board_smc91x_init(void)
void __init rx51_peripherals_init(void)
{
+ rx51_init_wl1251();
+
+ spi_register_board_info(rx51_peripherals_spi_board_info,
+ ARRAY_SIZE(rx51_peripherals_spi_board_info));
rx51_i2c_init();
board_onenand_init();
board_smc91x_init();
^ permalink raw reply related
* Re: [ipw3945-devel] [PATCH 02/17 v2.6.32] iwl3945: update iwl3945_apm_init()
From: reinette chatre @ 2009-10-13 16:59 UTC (permalink / raw)
To: Vedran Rodic
Cc: John W. Linville, Cahill, Ben M, linux-wireless@vger.kernel.org,
ipw3945-devel@lists.sourceforge.net
In-Reply-To: <8ccf2e9c0910130211j6f522d1ia4dc3a764896f974@mail.gmail.com>
On Tue, 2009-10-13 at 02:11 -0700, Vedran Rodic wrote:
> I don't have sophisticated power measurement devices to confirm these
> fixes, and I've only tried patch 2/17, reporting back it on bug
> http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2094 that the
> problem is still not fixed with this patch applied only.
That is why I did not provide this bug number to John :) There appears
to be two issues here, one of which we have resolved with these patches.
We know that that bug is still open.
> Can you describe your testing methodoloy? Are you testing just the
> mini PCI card usage? Are you comparing to Windows XP or Vista drivers?
What these patches fix is the power consumption when the interface is
brought down. Before this work, if the interface was already up and then
brought down then the power used the device is only reset, not stopped.
We are still investigating an issue of power consumption before the
interface is brought up in the first place. We are not comparing to
other OS, just looking at power consumption.
Reinette
^ permalink raw reply
* Re: [PATCH] libertas: Check return status of command functions
From: Dan Williams @ 2009-10-13 17:26 UTC (permalink / raw)
To: Bing Zhao; +Cc: libertas-dev, linux-wireless, Amitkumar Karwar
In-Reply-To: <1255055925-2013-1-git-send-email-bzhao@marvell.com>
On Thu, 2009-10-08 at 19:38 -0700, Bing Zhao wrote:
> From: Amitkumar Karwar <akarwar@marvell.com>
>
> Return status of lbs_prepare_and_send_command and lbs_cmd_with_response
> functions is not checked at some places. Those checks are added.
Some of those look OK, but others didn't check the return value because
it wasn't a big deal if the calls failed. For example, updating the
RSSI in get_wireless_stats. I don't really have a strong feeling either
way.
Acked-by: Dan Williams <dcbw@redhat.com>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> Signed-off-by: Bing Zhao <bzhao@marvell.com>
> ---
> drivers/net/wireless/libertas/debugfs.c | 27 ++++++++++++++++++---------
> drivers/net/wireless/libertas/main.c | 2 ++
> drivers/net/wireless/libertas/scan.c | 11 +++++++----
> drivers/net/wireless/libertas/wext.c | 10 +++++++---
> 4 files changed, 34 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
> index 893a55c..587b0cb 100644
> --- a/drivers/net/wireless/libertas/debugfs.c
> +++ b/drivers/net/wireless/libertas/debugfs.c
> @@ -451,10 +451,12 @@ static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
> CMD_MAC_REG_ACCESS, 0,
> CMD_OPTION_WAITFORRSP, 0, &offval);
> mdelay(10);
> - pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
> + if (!ret) {
> + pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
> priv->mac_offset, priv->offsetvalue.value);
>
> - ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
> + ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
> + }
> free_page(addr);
> return ret;
> }
> @@ -514,7 +516,8 @@ static ssize_t lbs_wrmac_write(struct file *file,
> CMD_OPTION_WAITFORRSP, 0, &offval);
> mdelay(10);
>
> - res = count;
> + if (!res)
> + res = count;
> out_unlock:
> free_page(addr);
> return res;
> @@ -539,10 +542,12 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
> CMD_BBP_REG_ACCESS, 0,
> CMD_OPTION_WAITFORRSP, 0, &offval);
> mdelay(10);
> - pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
> + if (!ret) {
> + pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
> priv->bbp_offset, priv->offsetvalue.value);
>
> - ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
> + ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
> + }
> free_page(addr);
>
> return ret;
> @@ -603,7 +608,8 @@ static ssize_t lbs_wrbbp_write(struct file *file,
> CMD_OPTION_WAITFORRSP, 0, &offval);
> mdelay(10);
>
> - res = count;
> + if (!res)
> + res = count;
> out_unlock:
> free_page(addr);
> return res;
> @@ -628,10 +634,12 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
> CMD_RF_REG_ACCESS, 0,
> CMD_OPTION_WAITFORRSP, 0, &offval);
> mdelay(10);
> - pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
> + if (!ret) {
> + pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
> priv->rf_offset, priv->offsetvalue.value);
>
> - ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
> + ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
> + }
> free_page(addr);
>
> return ret;
> @@ -692,7 +700,8 @@ static ssize_t lbs_wrrf_write(struct file *file,
> CMD_OPTION_WAITFORRSP, 0, &offval);
> mdelay(10);
>
> - res = count;
> + if (!res)
> + res = count;
> out_unlock:
> free_page(addr);
> return res;
> diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
> index 3b14fcc..bce752c 100644
> --- a/drivers/net/wireless/libertas/main.c
> +++ b/drivers/net/wireless/libertas/main.c
> @@ -1087,6 +1087,8 @@ static void auto_deepsleep_timer_fn(unsigned long data)
> ret = lbs_prepare_and_send_command(priv,
> CMD_802_11_DEEP_SLEEP, 0,
> 0, 0, NULL);
> + if (ret)
> + lbs_pr_err("Enter Deep Sleep command failed\n");
> }
> }
> mod_timer(&priv->auto_deepsleep_timer , jiffies +
> diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
> index 6c95af3..d8fc2b8 100644
> --- a/drivers/net/wireless/libertas/scan.c
> +++ b/drivers/net/wireless/libertas/scan.c
> @@ -1022,9 +1022,12 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
> return -EAGAIN;
>
> /* Update RSSI if current BSS is a locally created ad-hoc BSS */
> - if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate)
> - lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
> - CMD_OPTION_WAITFORRSP, 0, NULL);
> + if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) {
> + err = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
> + CMD_OPTION_WAITFORRSP, 0, NULL);
> + if (err)
> + goto out;
> + }
>
> mutex_lock(&priv->lock);
> list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
> @@ -1058,7 +1061,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
>
> dwrq->length = (ev - extra);
> dwrq->flags = 0;
> -
> +out:
> lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
> return err;
> }
> diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
> index 69dd19b..4594841 100644
> --- a/drivers/net/wireless/libertas/wext.c
> +++ b/drivers/net/wireless/libertas/wext.c
> @@ -832,7 +832,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
> u32 rssi_qual;
> u32 tx_qual;
> u32 quality = 0;
> - int stats_valid = 0;
> + int ret, stats_valid = 0;
> u8 rssi;
> u32 tx_retries;
> struct cmd_ds_802_11_get_log log;
> @@ -881,7 +881,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
>
> memset(&log, 0, sizeof(log));
> log.hdr.size = cpu_to_le16(sizeof(log));
> - lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
> + ret = lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
> + if (ret)
> + goto out;
>
> tx_retries = le32_to_cpu(log.retry);
>
> @@ -909,8 +911,10 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
> stats_valid = 1;
>
> /* update stats asynchronously for future calls */
> - lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
> + ret = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
> 0, 0, NULL);
> + if (ret)
> + lbs_pr_err("RSSI command failed\n");
> out:
> if (!stats_valid) {
> priv->wstats.miss.beacon = 0;
^ permalink raw reply
* Re: Current status of rt2800usb and staging/rt2870
From: Bartlomiej Zolnierkiewicz @ 2009-10-13 17:27 UTC (permalink / raw)
To: Ivo van Doorn; +Cc: Ozan Çağlayan, linux-wireless, linux-kernel
In-Reply-To: <200910131752.52589.IvDoorn@gmail.com>
On Tuesday 13 October 2009 17:52:52 Ivo van Doorn wrote:
> I am going to merge rt2800pci soon as well and after that I'll send a patch
Great, I've been waiting for this for a long time.
> to remove all Ralink drivers from the staging tree.
Till new drivers obtain support for all hardware currently covered by
the unified staging drivers the latter shouldn't be removed as they
serve well their role as a temporary solution allowing real Linux users
to user their real hardware and as a reference material for developers
willing to work on adding the missing bits to new drivers.
Best regards,
Bartlomiej
^ 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