Here is today's batch -- I'm still playing "catch-up" in the
wireless-dev tree. Please bear with me...
---
The following changes since commit 0888451bf4108fbaa07b221649b1289d8f79ef0f:
John W. Linville:
Merge branch 'from-linus'
are found in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git
David Kimdon:
d80211: fix multiple device ap support
d80211: Fix type of prism2_hostapd_param crypt.alg
d80211: allow vlan interfaces to receive ToDS frames
Hong Liu:
d80211: fix wpa_supplicant reassoc problem
d80211: add hardware scan callback
d80211: fix "iwconfig key [x]" behavior
Ivo van Doorn:
rt2x00: remove hardware button support
Jiri Benc:
d80211: fix invalid pointer dereference
Johannes Berg:
d80211: use BUILD_BUG_ON
d80211: clean up those huge else if statements
d80211: use list_for_each_entry{,_safe}
d80211: LED triggers
John W. Linville:
Merge branch 'fixes-for-linville' of http://bu3sch.de/git/wireless-dev
Merge branch 'up' of rsync://rsync.kernel.org/.../jbenc/dscape
mabbas:
d80211: diplay supported rates in readable format
Michael Buesch:
ssb: fix init sprom read/write race
add bcm43xx-d80211 MAINTAINERS entry
Michael Wu:
d80211: fix WEP on big endian cpus
Mohamed Abbas:
d80211: getting wrong freq value if we did hardware scan
MAINTAINERS | 8 +
drivers/misc/ssb.c | 29 +++--
drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c | 6 +
drivers/net/wireless/d80211/rt2x00/Kconfig | 27 -----
drivers/net/wireless/d80211/rt2x00/rt2400pci.c | 36 ------
drivers/net/wireless/d80211/rt2x00/rt2500pci.c | 36 ------
drivers/net/wireless/d80211/rt2x00/rt2x00.h | 8 -
drivers/net/wireless/d80211/rt2x00/rt2x00pci.h | 111 --------------------
drivers/net/wireless/d80211/rt2x00/rt61pci.c | 36 ------
include/linux/ssb.h | 15 +++
include/net/d80211.h | 46 ++++++--
net/d80211/Kconfig | 9 ++
net/d80211/Makefile | 10 +-
net/d80211/hostapd_ioctl.h | 2
net/d80211/ieee80211.c | 73 +++++--------
net/d80211/ieee80211_dev.c | 7 +
net/d80211/ieee80211_i.h | 6 +
net/d80211/ieee80211_iface.c | 2
net/d80211/ieee80211_ioctl.c | 108 ++++++++++---------
net/d80211/ieee80211_led.c | 93 ++++++++++++++---
net/d80211/ieee80211_led.h | 32 ++++++
net/d80211/ieee80211_sta.c | 107 +++++++++++--------
net/d80211/sta_info.c | 26 ++---
net/d80211/wep.c | 10 +-
24 files changed, 371 insertions(+), 472 deletions(-)
create mode 100644 net/d80211/ieee80211_led.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 3748cb1..2f06c7c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -464,6 +464,14 @@ L: [email protected]
W: http://www.baycom.org/~tom/ham/ham.html
S: Maintained
+BCM43XX WIRELESS DRIVER (DEVICESCAPE BASED VERSION)
+P: Michael Buesch
+M: [EMAIL PROTECTED]
+P: Stefano Brivio
+M: [EMAIL PROTECTED]
+W: http://bcm43xx.berlios.de/
+S: Maintained
+
BCM43XX WIRELESS DRIVER (SOFTMAC BASED VERSION)
P: Larry Finger
M: [EMAIL PROTECTED]
diff --git a/drivers/misc/ssb.c b/drivers/misc/ssb.c
index 44ab647..6087977 100644
--- a/drivers/misc/ssb.c
+++ b/drivers/misc/ssb.c
@@ -516,8 +516,6 @@ int ssb_init(struct ssb *ssb,
int (*device_suspend)(struct ssb *ssb),
int (*device_resume)(struct ssb *ssb))
{
- int err;
-
if (!ssb || !pci_dev || !mmio ||
!device_suspend || !device_resume)
return -EINVAL;
@@ -535,19 +533,12 @@ int ssb_init(struct ssb *ssb,
list_add(&ssb->list, &ssb_list);
mutex_unlock(&ssb_list_mutex);
- err = device_create_file(&pci_dev->dev, &dev_attr_ssb_sprom);
- if (err)
- goto out;
-
-out:
- return err;
+ return 0;
}
EXPORT_SYMBOL_GPL(ssb_init);
void ssb_exit(struct ssb *ssb)
{
- device_remove_file(&ssb->pci_dev->dev, &dev_attr_ssb_sprom);
-
mutex_lock(&ssb_list_mutex);
list_del(&ssb->list);
mutex_unlock(&ssb_list_mutex);
@@ -558,6 +549,24 @@ void ssb_exit(struct ssb *ssb)
}
EXPORT_SYMBOL_GPL(ssb_exit);
+int ssb_start(struct ssb *ssb)
+{
+ int err;
+
+ err = device_create_file(&ssb->pci_dev->dev,
+ &dev_attr_ssb_sprom);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(ssb_start);
+
+void ssb_stop(struct ssb *ssb)
+{
+ device_remove_file(&ssb->pci_dev->dev,
+ &dev_attr_ssb_sprom);
+}
+EXPORT_SYMBOL_GPL(ssb_stop);
+
static int do_switch_core(struct ssb *ssb, u8 coreidx)
{
int err;
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
index d71d797..82f1fd1 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
@@ -2600,6 +2600,7 @@ static int bcm43xx_shutdown_all_wireless
/* This is the opposite of bcm43xx_init_board() */
static void bcm43xx_free_board(struct bcm43xx_private *bcm)
{
+ ssb_stop(&bcm->ssb);
bcm43xx_sysfs_unregister(bcm);
bcm43xx_periodic_tasks_delete(bcm);
@@ -3189,12 +3190,17 @@ static int bcm43xx_init_board(struct bcm
err = bcm43xx_sysfs_register(bcm);
if (err)
goto err_wlshutdown;
+ err = ssb_start(&bcm->ssb);
+ if (err)
+ goto err_sysfs_unreg;
bcm43xx_periodic_tasks_setup(bcm);
out:
mutex_unlock(&bcm->mutex);
return err;
+err_sysfs_unreg:
+ bcm43xx_sysfs_unregister(bcm);
err_wlshutdown:
bcm43xx_shutdown_all_wireless_cores(bcm);
err_crystal_off:
diff --git a/drivers/net/wireless/d80211/rt2x00/Kconfig
b/drivers/net/wireless/d80211/rt2x00/Kconfig
index d9b97f1..66bbb16 100644
--- a/drivers/net/wireless/d80211/rt2x00/Kconfig
+++ b/drivers/net/wireless/d80211/rt2x00/Kconfig
@@ -15,15 +15,6 @@ config RT2400PCI
When compiled as a module, this driver will be called "rt2400pci.ko".
-config RT2400PCI_BUTTON
- bool "Ralink rt2400 hardware button support"
- depends on RT2400PCI && X86
- ---help---
- In some notebooks the rt2400 chipset is integrated in the machine,
- with this option enabled the device will periodically poll the
- the status of this button and will send and ACPI event when
- the button has been pressed.
-
config RT2400PCI_DEBUG
bool "Ralink rt2400 debug output"
depends on RT2400PCI
@@ -38,15 +29,6 @@ config RT2500PCI
When compiled as a module, this driver will be called "rt2500pci.ko".
-config RT2500PCI_BUTTON
- bool "Ralink rt2500 hardware button support"
- depends on RT2500PCI && X86
- ---help---
- In some notebooks the rt2500 chipset is integrated in the machine,
- with this option enabled the device will periodically poll the
- the status of this button and will send and ACPI event when
- the button has been pressed.
-
config RT2500PCI_DEBUG
bool "Ralink rt2500 debug output"
depends on RT2500PCI
@@ -61,15 +43,6 @@ config RT61PCI
When compiled as a module, this driver will be called "rt61pci.ko".
-config RT61PCI_BUTTON
- bool "Ralink rt61 hardware button support"
- depends on RT61PCI && X86
- ---help---
- In some notebooks the rt61 chipset is integrated in the machine,
- with this option enabled the device will periodically poll the
- the status of this button and will send and ACPI event when
- the button has been pressed.
-
config RT61PCI_DEBUG
bool "Ralink rt61 debug output"
depends on RT61PCI
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
index 59163bf..a46b8b8 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
@@ -51,10 +51,6 @@ #ifdef CONFIG_RT2400PCI_DEBUG
#define CONFIG_RT2X00_DEBUG
#endif /* CONFIG_RT2400PCI_DEBUG */
-#ifdef CONFIG_RT2400PCI_BUTTON
-#define CONFIG_RT2X00_BUTTON
-#endif /* CONFIG_RT2400PCI_BUTTON */
-
#include "rt2x00.h"
#include "rt2x00pci.h"
#include "rt2400pci.h"
@@ -346,23 +342,6 @@ static void rt2x00_eeprom_multiread(cons
rt2x00_eeprom_read(rt2x00dev, word + i, data++);
}
-#ifdef CONFIG_RT2400PCI_BUTTON
-/*
- * Hardware button poll handler.
- */
-static void rt2400pci_button_poll(unsigned long data)
-{
- struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
- u32 reg;
-
- rt2x00_register_read(rt2x00dev, GPIOCSR, ®);
- rt2x00pci_button_status(
- rt2x00dev, rt2x00_get_field32(reg, GPIOCSR_BIT0));
-}
-#else /* CONFIG_RT2400PCI_BUTTON */
-static void rt2400pci_button_poll(unsigned long data){}
-#endif /* CONFIG_RT2400PCI_BUTTON */
-
/*
* Ethtool handlers.
*/
@@ -2750,11 +2729,6 @@ static void rt2400pci_free_dev(struct ne
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
/*
- * Shutdown poll_timer for hardware button.
- */
- rt2x00pci_button_stop(rt2x00dev);
-
- /*
* Free ring structures.
*/
kfree(rt2x00dev->ring);
@@ -2838,11 +2812,6 @@ static int rt2400pci_alloc_dev(struct pc
goto exit;
}
- /*
- * If required start hardware button polling.
- */
- rt2x00pci_button_start(rt2x00dev, rt2400pci_button_poll);
-
return 0;
exit:
@@ -3048,11 +3017,6 @@ module_param_named(debug, rt2x00_debug_l
MODULE_PARM_DESC(debug, "Set this parameter to 1 to enable debug output.");
#endif /* CONFIG_RT2400PCI_DEBUG */
-#ifdef CONFIG_RT2400PCI_BUTTON
-module_param_named(poll_delay, rt2x00_poll_delay, short, S_IRUGO);
-MODULE_PARM_DESC(debug, "Delay between WiFi button pollings (in 100ms).");
-#endif /* CONFIG_RT2400PCI_BUTTON */
-
static struct pci_driver rt2400pci_driver = {
.name = DRV_NAME,
.id_table = rt2400pci_device_table,
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
b/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
index 651fbec..c08b076 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
@@ -51,10 +51,6 @@ #ifdef CONFIG_RT2500PCI_DEBUG
#define CONFIG_RT2X00_DEBUG
#endif /* CONFIG_RT2500PCI_DEBUG */
-#ifdef CONFIG_RT2500PCI_BUTTON
-#define CONFIG_RT2X00_BUTTON
-#endif /* CONFIG_RT2500PCI_BUTTON */
-
#include "rt2x00.h"
#include "rt2x00pci.h"
#include "rt2500pci.h"
@@ -346,23 +342,6 @@ static void rt2x00_eeprom_multiread(cons
rt2x00_eeprom_read(rt2x00dev, word + i, data++);
}
-#ifdef CONFIG_RT2500PCI_BUTTON
-/*
- * Hardware button poll handler.
- */
-static void rt2500pci_button_poll(unsigned long data)
-{
- struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
- u32 reg;
-
- rt2x00_register_read(rt2x00dev, GPIOCSR, ®);
- rt2x00pci_button_status(
- rt2x00dev, rt2x00_get_field32(reg, GPIOCSR_BIT0));
-}
-#else /* CONFIG_RT2500PCI_BUTTON */
-static void rt2500pci_button_poll(unsigned long data){}
-#endif /* CONFIG_RT2500PCI_BUTTON */
-
/*
* Ethtool handlers.
*/
@@ -3035,11 +3014,6 @@ static void rt2500pci_free_dev(struct ne
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
/*
- * Shutdown poll_timer for hardware button.
- */
- rt2x00pci_button_stop(rt2x00dev);
-
- /*
* Free ring structures.
*/
kfree(rt2x00dev->ring);
@@ -3123,11 +3097,6 @@ static int rt2500pci_alloc_dev(struct pc
goto exit;
}
- /*
- * If required start hardware button polling.
- */
- rt2x00pci_button_start(rt2x00dev, rt2500pci_button_poll);
-
return 0;
exit:
@@ -3333,11 +3302,6 @@ module_param_named(debug, rt2x00_debug_l
MODULE_PARM_DESC(debug, "Set this parameter to 1 to enable debug output.");
#endif /* CONFIG_RT2500PCI_DEBUG */
-#ifdef CONFIG_RT2500PCI_BUTTON
-module_param_named(poll_delay, rt2x00_poll_delay, short, S_IRUGO);
-MODULE_PARM_DESC(debug, "Delay between WiFi button pollings (in 100ms).");
-#endif /* CONFIG_RT2500PCI_BUTTON */
-
static struct pci_driver rt2500pci_driver = {
.name = DRV_NAME,
.id_table = rt2500pci_device_table,
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2x00.h
b/drivers/net/wireless/d80211/rt2x00/rt2x00.h
index e0ae5fe..76845c8 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2x00.h
@@ -866,14 +866,6 @@ #define CONFIG_DISABLE_BBP_TUNING 0x0002
struct ieee80211_hw hw;
/*
- * If enabled, the structure for the
- * hardware button control.
- */
-#ifdef CONFIG_RT2X00_BUTTON
- struct rfkill rfkill;
-#endif /* CONFIG_RT2X00_BUTTON */
-
- /*
* Queue for deferred work.
*/
struct workqueue_struct *workqueue;
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
b/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
index fe6f833..bd39395 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
@@ -44,115 +44,4 @@ #define EEPROM_WIDTH_93C66 8
#define EEPROM_WRITE_OPCODE 0x05
#define EEPROM_READ_OPCODE 0x06
-/*
- * HW button structure.
- */
-#ifdef CONFIG_RT2X00_BUTTON
-#include <acpi/acpi_bus.h>
-
-struct rt2x00_button {
- /*
- * ACPI device for generation of ACPI events.
- */
- struct acpi_device acpi_dev;
-
- /*
- * Timer for register polling.
- */
- struct timer_list poll_timer;
-
- /*
- * Timer delay.
- */
- short poll_delay;
-
- /*
- * Current status of button.
- */
- short button_status:1;
- short active_poll:1;
- short __pad:14;
-};
-#endif /* CONFIG_RT2X00_BUTTON */
-
-/*
- * HW button variables & functions.
- * The delay between each poll is set by the module parameter.
- */
-#ifdef CONFIG_RT2X00_BUTTON
-/*
- * Module parameter.
- */
-static short rt2x00_poll_delay = 0;
-
-static inline void rt2x00pci_button_status(struct rt2x00_dev *rt2x00dev,
- char status)
-{
- struct rt2x00_button *button = &rt2x00dev->button;
-
- if (!button->active_poll)
- return;
-
- if (status != button->button_status) {
- button->button_status = status;
- acpi_bus_generate_event(
- &button->acpi_dev, ACPI_TYPE_EVENT, status);
- }
-
- button->poll_timer.expires = jiffies + button->poll_delay;
-
- if (button->active_poll)
- add_timer(&button->poll_timer);
-}
-
-static inline void rt2x00pci_button_start(struct rt2x00_dev *rt2x00dev,
- void (*handler)(unsigned long data))
-{
- struct rt2x00_button *button = &rt2x00dev->button;
-
- /*
- * Only enable polling when the user has
- * set the poll delay module parameter,
- * and the device contains a hardware button.
- */
- if(!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON) ||
- !rt2x00_poll_delay)
- return;
-
- strcpy(acpi_device_class(&button->acpi_dev), DRV_NAME "_button");
- strcpy(acpi_device_bid(&button->acpi_dev), DRV_NAME);
- strcpy(acpi_device_name(&button->acpi_dev), DRV_NAME);
-
- init_timer(&button->poll_timer);
-
- button->poll_delay = rt2x00_poll_delay * (HZ / 10);
- button->button_status = 0;
- button->active_poll = 1;
-
- button->poll_timer.function = handler;
- button->poll_timer.data = (unsigned long)rt2x00dev;
- button->poll_timer.expires = jiffies + button->poll_delay;
-
- add_timer(&button->poll_timer);
-}
-
-static inline void rt2x00pci_button_stop(struct rt2x00_dev *rt2x00dev)
-{
- /*
- * Shutdown poll_timer for hardware button,
- * make sure only to disable polling when
- * it was enabled in the first place.
- */
- if(!rt2x00dev->button.active_poll)
- return;
-
- rt2x00dev->button.active_poll = 0;
- del_timer_sync(&rt2x00dev->button.poll_timer);
-}
-#else /* CONFIG_RT2X00_BUTTON */
-static inline void rt2x00pci_button_start(struct rt2x00_dev *rt2x00dev,
- void (*handler)(unsigned long data)){}
-static inline void rt2x00pci_button_stop(struct rt2x00_dev *rt2x00dev){}
-#endif /* CONFIG_RT2X00_BUTTON */
-
#endif /* RT2X00PCI_H */
diff --git a/drivers/net/wireless/d80211/rt2x00/rt61pci.c
b/drivers/net/wireless/d80211/rt2x00/rt61pci.c
index 9a0462a..3e1a702 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt61pci.c
@@ -52,10 +52,6 @@ #ifdef CONFIG_RT61PCI_DEBUG
#define CONFIG_RT2X00_DEBUG
#endif /* CONFIG_RT61PCI_DEBUG */
-#ifdef CONFIG_RT61PCI_BUTTON
-#define CONFIG_RT2X00_BUTTON
-#endif /* CONFIG_RT61PCI_BUTTON */
-
#include "rt2x00.h"
#include "rt2x00pci.h"
#include "rt2x00crc.h"
@@ -377,23 +373,6 @@ static void rt2x00_eeprom_multiread(cons
rt2x00_eeprom_read(rt2x00dev, word + i, data++);
}
-#ifdef CONFIG_RT61PCI_BUTTON
-/*
- * Hardware button poll handler.
- */
-static void rt61pci_button_poll(unsigned long data)
-{
- struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
- u32 reg;
-
- rt2x00_register_read(rt2x00dev, MAC_CSR13, ®);
- rt2x00pci_button_status(
- rt2x00dev, rt2x00_get_field32(reg, MAC_CSR13_BIT5));
-}
-#else /* CONFIG_RT61PCI_BUTTON */
-static void rt61pci_button_poll(unsigned long data){}
-#endif /* CONFIG_RT61PCI_BUTTON */
-
/*
* Ethtool handlers.
*/
@@ -3547,11 +3526,6 @@ static void rt61pci_free_dev(struct net_
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
/*
- * Shutdown poll_timer for hardware button.
- */
- rt2x00pci_button_stop(rt2x00dev);
-
- /*
* Free ring structures.
*/
kfree(rt2x00dev->ring);
@@ -3640,11 +3614,6 @@ static int rt61pci_alloc_dev(struct pci_
goto exit;
}
- /*
- * If required start hardware button polling.
- */
- rt2x00pci_button_start(rt2x00dev, rt61pci_button_poll);
-
return 0;
exit:
@@ -3856,11 +3825,6 @@ module_param_named(debug, rt2x00_debug_l
MODULE_PARM_DESC(debug, "Set this parameter to 1 to enable debug output.");
#endif /* CONFIG_RT61PCI_DEBUG */
-#ifdef CONFIG_RT61PCI_BUTTON
-module_param_named(poll_delay, rt2x00_poll_delay, short, S_IRUGO);
-MODULE_PARM_DESC(debug, "Delay between WiFi button pollings (in 100ms).");
-#endif /* CONFIG_RT61PCI_BUTTON */
-
static struct pci_driver rt61pci_driver = {
.name = DRV_NAME,
.id_table = rt61pci_device_table,
diff --git a/include/linux/ssb.h b/include/linux/ssb.h
index a36dd75..09c28a8 100644
--- a/include/linux/ssb.h
+++ b/include/linux/ssb.h
@@ -504,7 +504,7 @@ #endif
/**
* ssb_init - Initialize struct ssb.
- * This does not init hardware. May fail and return NULL.
+ * Call this before initializing the hardware.
* @ssb: Pointer to struct ssb to init. This will usually
* be embedded in the device's private struct.
* @pci_dev: Pointer to the PCI device.
@@ -521,6 +521,19 @@ int ssb_init(struct ssb *ssb,
void ssb_exit(struct ssb *ssb);
/**
+ * ssb_start - Start the ssb operation.
+ * Call this after initializing the hardware.
+ * @ssb: Pointer to struct ssb.
+ */
+int ssb_start(struct ssb *ssb);
+/**
+ * ssb_stop - Stop the ssb operation.
+ * Call this before shutting down the hardware.
+ * @ssb: Pointer to struct ssb.
+ */
+void ssb_stop(struct ssb *ssb);
+
+/**
* struct ssb_nrcores_elem - Array element of the
* "number of cores" fallback array.
* This array is browsed, if there is no ChipCommon rev >= 4
diff --git a/include/net/d80211.h b/include/net/d80211.h
index 42fdbf7..a80f48b 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -600,6 +600,10 @@ struct ieee80211_hw {
int (*passive_scan)(struct net_device *dev, int state,
struct ieee80211_scan_conf *conf);
+ /* Ask the hardware to service the scan request, no need to start
+ * the scan state machine in stack. */
+ int (*hw_scan)(struct net_device *dev, u8 *ssid, size_t len);
+
/* return low-level statistics */
int (*get_stats)(struct net_device *dev,
struct ieee80211_low_level_stats *stats);
@@ -699,6 +703,36 @@ struct net_device *ieee80211_alloc_hw(si
* function. */
int ieee80211_register_hw(struct net_device *dev, struct ieee80211_hw *hw);
+/* driver can use this and ieee80211_get_rx_led_name to get the
+ * name of the registered LEDs after ieee80211_register_hw
+ * was called.
+ * This is useful to set the default trigger on the LED class
+ * device that your driver should export for each LED the device
+ * has, that way the default behaviour will be as expected but
+ * the user can still change it/turn off the LED etc.
+ */
+#ifdef CONFIG_D80211_LEDS
+extern char *__ieee80211_get_tx_led_name(struct net_device *dev);
+extern char *__ieee80211_get_rx_led_name(struct net_device *dev);
+#endif
+static inline char *ieee80211_get_tx_led_name(struct net_device *dev)
+{
+#ifdef CONFIG_D80211_LEDS
+ return __ieee80211_get_tx_led_name(dev);
+#else
+ return NULL;
+#endif
+}
+
+static inline char *ieee80211_get_rx_led_name(struct net_device *dev)
+{
+#ifdef CONFIG_D80211_LEDS
+ return __ieee80211_get_rx_led_name(dev);
+#else
+ return NULL;
+#endif
+}
+
/* This function is allowed to update hardware configuration (e.g., list of
* supported operation modes and rates). */
int ieee80211_update_hw(struct net_device *dev, struct ieee80211_hw *hw);
@@ -863,6 +897,8 @@ struct dev_mc_list *ieee80211_get_mc_lis
struct ieee80211_conf *
ieee80211_get_hw_conf(struct net_device *dev);
+/* called by driver to notify scan status completed */
+void ieee80211_scan_completed(struct net_device *dev);
/* Return a pointer to the low-level private data area for the given device. */
void * ieee80211_dev_hw_data(struct net_device *dev);
@@ -897,16 +933,6 @@ enum {
IEEE80211_TEST_PARAM_TX_ANT_SEL_RAW = 5,
};
-/* ieee80211_tx_led called with state == 1 when the first frame is queued
- * with state == 0 when the last frame is transmitted and tx queue is empty
- */
-void ieee80211_tx_led(int state, struct net_device *dev);
-/* ieee80211_rx_led is called each time frame is received, state is not used
- * (== 2)
- */
-void ieee80211_rx_led(int state, struct net_device *dev);
-
-
/* IEEE 802.11 defines */
#define FCS_LEN 4
diff --git a/net/d80211/Kconfig b/net/d80211/Kconfig
index 2f3c0a3..0f07d41 100644
--- a/net/d80211/Kconfig
+++ b/net/d80211/Kconfig
@@ -7,6 +7,15 @@ config D80211
This option enables the hardware independent IEEE 802.11
networking stack.
+config D80211_LEDS
+ bool "Enable LED triggers"
+ depends on D80211
+ select NEW_LEDS
+ select LEDS_TRIGGERS
+ ---help---
+ This option enables a few LED triggers for different
+ packet receive/transmit events.
+
config D80211_DEBUG
bool "Enable debugging output"
depends on D80211
diff --git a/net/d80211/Makefile b/net/d80211/Makefile
index c21e882..2a2a0c6 100644
--- a/net/d80211/Makefile
+++ b/net/d80211/Makefile
@@ -1,5 +1,7 @@
obj-$(CONFIG_D80211) += 80211.o rate_control.o
+80211-objs-$(CONFIG_D80211_LEDS) += ieee80211_led.o
+
80211-objs := \
ieee80211.o \
ieee80211_ioctl.o \
@@ -15,13 +17,9 @@ obj-$(CONFIG_D80211) += 80211.o rate_con
michael.o \
tkip.o \
aes_ccm.o \
- wme.o
+ wme.o \
+ $(80211-objs-y)
ifeq ($(CONFIG_NET_SCHED),)
80211-objs += fifo_qdisc.o
endif
-
-ifeq ($(CONFIG_D80211_LEDS),y)
- 80211-objs += ieee80211_led.o
-endif
-
diff --git a/net/d80211/hostapd_ioctl.h b/net/d80211/hostapd_ioctl.h
index 7c7305c..d302790 100644
--- a/net/d80211/hostapd_ioctl.h
+++ b/net/d80211/hostapd_ioctl.h
@@ -207,7 +207,7 @@ #define IEEE80211_STA_DYNAMIC_ENC BIT(0)
u32 last_ack_rssi;
} get_info_sta;
struct {
- u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN];
+ char alg[HOSTAP_CRYPT_ALG_NAME_LEN];
u32 flags;
u32 err;
u8 idx;
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 320272c..1ef2707 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -31,7 +31,7 @@ #include "wpa.h"
#include "tkip.h"
#include "wme.h"
#include "aes_ccm.h"
-
+#include "ieee80211_led.h"
/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
@@ -945,13 +945,12 @@ static void purge_old_ps_buffers(struct
{
int total = 0, purged = 0;
struct sk_buff *skb;
- struct list_head *ptr;
+ struct ieee80211_sub_if_data *sdata;
+ struct sta_info *sta;
spin_lock_bh(&local->sub_if_lock);
- list_for_each(ptr, &local->sub_if_list) {
+ list_for_each_entry(sdata, &local->sub_if_list, list) {
struct ieee80211_if_ap *ap;
- struct ieee80211_sub_if_data *sdata =
- list_entry(ptr, struct ieee80211_sub_if_data, list);
if (sdata->dev == local->mdev ||
sdata->type != IEEE80211_IF_TYPE_AP)
continue;
@@ -966,9 +965,7 @@ static void purge_old_ps_buffers(struct
spin_unlock_bh(&local->sub_if_lock);
spin_lock_bh(&local->sta_lock);
- list_for_each(ptr, &local->sta_list) {
- struct sta_info *sta =
- list_entry(ptr, struct sta_info, list);
+ list_for_each_entry(sta, &local->sta_list, list) {
skb = skb_dequeue(&sta->ps_tx_buf);
if (skb) {
purged++;
@@ -1183,11 +1180,7 @@ static int __ieee80211_tx(struct ieee802
ret = local->hw->tx(local->mdev, skb, control);
if (ret)
return IEEE80211_TX_AGAIN;
-#ifdef IEEE80211_LEDS
- if (local->tx_led_counter++ == 0) {
- ieee80211_tx_led(1, local->mdev);
- }
-#endif /* IEEE80211_LEDS */
+ ieee80211_led_tx(local, 1);
}
if (tx->u.tx.extra_frag) {
control->use_rts_cts = 0;
@@ -1212,11 +1205,7 @@ #endif /* IEEE80211_LEDS */
control);
if (ret)
return IEEE80211_TX_FRAG_AGAIN;
-#ifdef IEEE80211_LEDS
- if (local->tx_led_counter++ == 0) {
- ieee80211_tx_led(1, local->mdev);
- }
-#endif /* IEEE80211_LEDS */
+ ieee80211_led_tx(local, 1);
tx->u.tx.extra_frag[i] = NULL;
}
kfree(tx->u.tx.extra_frag);
@@ -2374,7 +2363,8 @@ ieee80211_rx_h_data(struct ieee80211_txr
memcpy(dst, hdr->addr3, ETH_ALEN);
memcpy(src, hdr->addr2, ETH_ALEN);
- if (unlikely(sdata->type != IEEE80211_IF_TYPE_AP)) {
+ if (unlikely(sdata->type != IEEE80211_IF_TYPE_AP &&
+ sdata->type != IEEE80211_IF_TYPE_VLAN)) {
printk(KERN_DEBUG "%s: dropped ToDS frame (BSSID="
MAC_FMT " SA=" MAC_FMT " DA=" MAC_FMT ")\n",
dev->name, MAC_ARG(hdr->addr1),
@@ -3000,10 +2990,8 @@ ieee80211_rx_h_defragment(struct ieee802
rx->sta->rx_packets++;
if (is_multicast_ether_addr(hdr->addr1))
rx->local->dot11MulticastReceivedFrameCount++;
-#ifdef IEEE80211_LEDS
else
- ieee80211_rx_led(2, rx->dev);
-#endif /* IEEE80211_LEDS */
+ ieee80211_led_rx(rx->local);
return TXRX_CONTINUE;
}
@@ -3828,16 +3816,15 @@ ieee80211_rx_h_if_stats(struct ieee80211
static void ieee80211_stat_refresh(unsigned long data)
{
struct ieee80211_local *local = (struct ieee80211_local *) data;
- struct list_head *ptr, *n;
+ struct sta_info *sta;
+ struct ieee80211_sub_if_data *sdata;
if (!local->stat_time)
return;
/* go through all stations */
spin_lock_bh(&local->sta_lock);
- list_for_each(ptr, &local->sta_list) {
- struct sta_info *sta =
- list_entry(ptr, struct sta_info, list);
+ list_for_each_entry(sta, &local->sta_list, list) {
sta->channel_use = (sta->channel_use_raw / local->stat_time) /
CHAN_UTIL_PER_10MS;
sta->channel_use_raw = 0;
@@ -3845,14 +3832,11 @@ static void ieee80211_stat_refresh(unsig
spin_unlock_bh(&local->sta_lock);
/* go through all subinterfaces */
- list_for_each_safe(ptr, n, &local->sub_if_list) {
- struct ieee80211_sub_if_data *sdata =
- list_entry(ptr, struct ieee80211_sub_if_data, list);
+ list_for_each_entry(sdata, &local->sub_if_list, list) {
sdata->channel_use = (sdata->channel_use_raw /
local->stat_time) / CHAN_UTIL_PER_10MS;
sdata->channel_use_raw = 0;
-
- }
+ }
/* hardware interface */
local->channel_use = (local->channel_use_raw /
@@ -4106,11 +4090,8 @@ void ieee80211_tx_status(struct net_devi
rate_control_tx_status(dev, skb, status);
}
-#ifdef IEEE80211_LEDS
- if (local->tx_led_counter && (local->tx_led_counter-- == 1)) {
- ieee80211_tx_led(0, dev);
- }
-#endif /* IEEE80211_LEDS */
+ ieee80211_led_tx(local, 0);
+
/* SNMP counters
* Fragments are passed to low-level drivers as separate skbs, so these
* are actually fragments, not frames. Update frame counters only for
@@ -4507,6 +4488,8 @@ int ieee80211_register_hw(struct net_dev
local->reg_state = IEEE80211_DEV_REGISTERED;
rtnl_unlock();
+ ieee80211_led_init(local);
+
return 0;
fail_rate_attrs:
@@ -4562,7 +4545,7 @@ EXPORT_SYMBOL(ieee80211_update_hw);
void ieee80211_unregister_hw(struct net_device *dev)
{
struct ieee80211_local *local = dev->ieee80211_ptr;
- struct list_head *ptr, *n;
+ struct ieee80211_sub_if_data *sdata, *tmp;
int i;
tasklet_disable(&local->tasklet);
@@ -4575,11 +4558,9 @@ void ieee80211_unregister_hw(struct net_
sysfs_remove_link(&local->class_dev.kobj, "master");
- list_for_each_safe(ptr, n, &local->sub_if_list) {
- struct ieee80211_sub_if_data *sdata =
- list_entry(ptr, struct ieee80211_sub_if_data, list);
+ list_for_each_entry_safe(sdata, tmp, &local->sub_if_list, list)
__ieee80211_if_del(local, sdata);
- }
+
rtnl_unlock();
if (local->rate_limit)
@@ -4615,6 +4596,7 @@ void ieee80211_unregister_hw(struct net_
skb_queue_purge(&local->skb_queue_unreliable);
ieee80211_dev_free_index(local);
+ ieee80211_led_exit(local);
}
EXPORT_SYMBOL(ieee80211_unregister_hw);
@@ -4799,13 +4781,8 @@ static int __init ieee80211_init(void)
struct sk_buff *skb;
int ret;
- if (sizeof(struct ieee80211_tx_packet_data) > (sizeof(skb->cb))) {
- printk("80211: ieee80211_tx_packet_data is bigger "
- "than the skb->cb (%d > %d)\n",
- (int) sizeof(struct ieee80211_tx_packet_data),
- (int) sizeof(skb->cb));
- return -EINVAL;
- }
+ BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));
+
if ((ret = ieee80211_sysfs_init())) {
printk(KERN_WARNING "ieee80211_init: sysfs initialization "
"failed\n");
diff --git a/net/d80211/ieee80211_dev.c b/net/d80211/ieee80211_dev.c
index 6c6ca91..48a5e56 100644
--- a/net/d80211/ieee80211_dev.c
+++ b/net/d80211/ieee80211_dev.c
@@ -13,6 +13,7 @@ #include <linux/if_ether.h>
#include <linux/netdevice.h>
#include <net/d80211.h>
#include "ieee80211_i.h"
+#include "ieee80211_led.h"
struct ieee80211_dev_list {
struct list_head list;
@@ -38,7 +39,6 @@ static struct ieee80211_dev_list *__ieee
int ieee80211_dev_alloc_index(struct ieee80211_local *local)
{
- struct list_head *i;
struct ieee80211_dev_list *dev_item, *new;
int index = 0;
@@ -47,14 +47,13 @@ int ieee80211_dev_alloc_index(struct iee
return -ENOMEM;
new->local = local;
spin_lock(&dev_list_lock);
- list_for_each(i, &dev_list) {
- dev_item = list_entry(i, struct ieee80211_dev_list, list);
+ list_for_each_entry(dev_item, &dev_list, list) {
if (index < dev_item->dev_index)
break;
index++;
}
new->dev_index = index;
- list_add_tail(&new->list, i);
+ list_add_tail(&new->list, &dev_item->list);
spin_unlock(&dev_list_lock);
local->dev_index = index;
return index;
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 0d2d79d..425fc9b 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -459,7 +459,11 @@ #endif /* CONFIG_HOSTAPD_WPA_TESTING */
u32 dot11TransmittedFrameCount;
u32 dot11WEPUndecryptableCount;
- int tx_led_counter;
+#ifdef CONFIG_D80211_LEDS
+ int tx_led_counter, rx_led_counter;
+ struct led_trigger *tx_led, *rx_led;
+ char tx_led_name[32], rx_led_name[32];
+#endif
u32 channel_use;
u32 channel_use_raw;
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index bdff4cd..0a10c86 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -122,7 +122,7 @@ int ieee80211_if_add_mgmt(struct net_dev
if (!ndev)
return -ENOMEM;
ret = dev_alloc_name(ndev, "wmgmt%d");
- if (ret)
+ if (ret < 0)
goto fail;
ndev->ieee80211_ptr = local;
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 89a58e3..445adad 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -1000,11 +1000,13 @@ static int ieee80211_ioctl_add_if(struct
int left = param_len - ((u8 *) pos - (u8 *) param);
struct net_device *new_dev;
int res;
+ struct hostapd_if_wds *wds;
+ struct hostapd_if_bss *bss;
printk(KERN_WARNING "PRISM2_HOSTAPD_ADD_IF ioctl is deprecated!");
- if (param->u.if_info.type == HOSTAP_IF_WDS) {
- struct hostapd_if_wds *wds =
- (struct hostapd_if_wds *) param->u.if_info.data;
+ switch (param->u.if_info.type) {
+ case HOSTAP_IF_WDS:
+ wds = (struct hostapd_if_wds *) param->u.if_info.data;
if (left < sizeof(struct hostapd_if_wds))
return -EPROTO;
@@ -1018,7 +1020,7 @@ static int ieee80211_ioctl_add_if(struct
__ieee80211_if_del(dev->ieee80211_ptr,
IEEE80211_DEV_TO_SUB_IF(new_dev));
return res;
- } else if (param->u.if_info.type == HOSTAP_IF_VLAN) {
+ case HOSTAP_IF_VLAN:
if (left < sizeof(struct hostapd_if_vlan))
return -EPROTO;
@@ -1033,9 +1035,8 @@ #if 0
IEEE80211_DEV_TO_SUB_IF(new_dev));
#endif
return res;
- } else if (param->u.if_info.type == HOSTAP_IF_BSS) {
- struct hostapd_if_bss *bss =
- (struct hostapd_if_bss *) param->u.if_info.data;
+ case HOSTAP_IF_BSS:
+ bss = (struct hostapd_if_bss *) param->u.if_info.data;
if (left < sizeof(struct hostapd_if_bss))
return -EPROTO;
@@ -1046,12 +1047,7 @@ #endif
ieee80211_if_set_type(new_dev, IEEE80211_IF_TYPE_AP);
memcpy(new_dev->dev_addr, bss->bssid, ETH_ALEN);
return 0;
- } else if (param->u.if_info.type == HOSTAP_IF_STA) {
-#if 0
- struct hostapd_if_sta *sta =
- (struct hostapd_if_sta *) param->u.if_info.data;
-#endif
-
+ case HOSTAP_IF_STA:
if (left < sizeof(struct hostapd_if_sta))
return -EPROTO;
@@ -1060,34 +1056,38 @@ #endif
return res;
ieee80211_if_set_type(new_dev, IEEE80211_IF_TYPE_STA);
return 0;
- } else
- return -EINVAL;
+ default:
+ return -EINVAL;
+ }
return 0;
}
-
static int ieee80211_ioctl_remove_if(struct net_device *dev,
struct prism2_hostapd_param *param)
{
unsigned int type;
- if (param->u.if_info.type == HOSTAP_IF_WDS) {
+ switch (param->u.if_info.type) {
+ case HOSTAP_IF_WDS:
type = IEEE80211_IF_TYPE_WDS;
- } else if (param->u.if_info.type == HOSTAP_IF_VLAN) {
+ break;
+ case HOSTAP_IF_VLAN:
type = IEEE80211_IF_TYPE_VLAN;
- } else if (param->u.if_info.type == HOSTAP_IF_BSS) {
+ break;
+ case HOSTAP_IF_BSS:
type = IEEE80211_IF_TYPE_AP;
- } else if (param->u.if_info.type == HOSTAP_IF_STA) {
+ break;
+ case HOSTAP_IF_STA:
type = IEEE80211_IF_TYPE_STA;
- } else {
+ break;
+ default:
return -EINVAL;
}
return ieee80211_if_remove(dev, param->u.if_info.name, type);
}
-
static int ieee80211_ioctl_update_if(struct net_device *dev,
struct prism2_hostapd_param *param,
int param_len)
@@ -2174,23 +2174,21 @@ static int ieee80211_ioctl_clear_keys(st
{
struct ieee80211_local *local = dev->ieee80211_ptr;
struct ieee80211_key_conf key;
- struct list_head *ptr;
int i;
u8 addr[ETH_ALEN];
struct ieee80211_key_conf *keyconf;
+ struct ieee80211_sub_if_data *sdata;
+ struct sta_info *sta;
memset(addr, 0xff, ETH_ALEN);
- list_for_each(ptr, &local->sub_if_list) {
- struct ieee80211_sub_if_data *sdata =
- list_entry(ptr, struct ieee80211_sub_if_data, list);
+ list_for_each_entry(sdata, &local->sub_if_list, list) {
for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
keyconf = NULL;
if (sdata->keys[i] &&
!sdata->keys[i]->force_sw_encrypt &&
local->hw->set_key &&
(keyconf = ieee80211_key_data2conf(local,
- sdata->keys[i]))
- != NULL)
+ sdata->keys[i])))
local->hw->set_key(dev, DISABLE_KEY, addr,
keyconf, 0);
kfree(keyconf);
@@ -2201,14 +2199,11 @@ static int ieee80211_ioctl_clear_keys(st
}
spin_lock_bh(&local->sta_lock);
- list_for_each(ptr, &local->sta_list) {
- struct sta_info *sta =
- list_entry(ptr, struct sta_info, list);
+ list_for_each_entry(sta, &local->sta_list, list) {
keyconf = NULL;
if (sta->key && !sta->key->force_sw_encrypt &&
local->hw->set_key &&
- (keyconf = ieee80211_key_data2conf(local, sta->key))
- != NULL)
+ (keyconf = ieee80211_key_data2conf(local, sta->key)))
local->hw->set_key(dev, DISABLE_KEY, sta->addr,
keyconf, sta->aid);
kfree(keyconf);
@@ -2324,22 +2319,17 @@ static int ieee80211_ioctl_default_wep_o
int value)
{
int i;
- struct list_head *ptr;
+ struct ieee80211_sub_if_data *sdata;
local->default_wep_only = value;
- list_for_each(ptr, &local->sub_if_list) {
- struct ieee80211_sub_if_data *sdata =
- list_entry(ptr, struct ieee80211_sub_if_data, list);
- for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
- if (value) {
+ list_for_each_entry(sdata, &local->sub_if_list, list)
+ for (i = 0; i < NUM_DEFAULT_KEYS; i++)
+ if (value)
ieee80211_key_enable_hwaccel(local,
sdata->keys[i]);
- } else {
+ else
ieee80211_key_disable_hwaccel(local,
sdata->keys[i]);
- }
- }
- }
return 0;
}
@@ -2867,9 +2857,10 @@ static int ieee80211_ioctl_siwencode(str
if (!sdata->default_key)
idx = 0;
else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
- if (sdata->default_key == sdata->keys[i])
+ if (sdata->default_key == sdata->keys[i]) {
idx = i;
- break;
+ break;
+ }
}
if (idx < 0)
return -EINVAL;
@@ -2880,16 +2871,21 @@ static int ieee80211_ioctl_siwencode(str
alg = ALG_NONE;
else if (erq->length == 0) {
/* No key data - just set the default TX key index */
- sdata->default_key = sdata->keys[idx];
+ if (sdata->default_key != sdata->keys[idx]) {
+ if (sdata->default_key)
+ ieee80211_key_sysfs_remove_default(sdata);
+ sdata->default_key = sdata->keys[idx];
+ if (sdata->default_key)
+ ieee80211_key_sysfs_add_default(sdata);
+ }
+ return 0;
}
return ieee80211_set_encryption(
dev, bcaddr,
- idx, erq->length == 0 ? ALG_NONE : ALG_WEP,
+ idx, alg,
!sdata->default_key,
NULL, keybuf, erq->length);
-
- return 0;
}
@@ -2908,9 +2904,10 @@ static int ieee80211_ioctl_giwencode(str
if (!sdata->default_key)
idx = 0;
else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
- if (sdata->default_key == sdata->keys[i])
+ if (sdata->default_key == sdata->keys[i]) {
idx = i;
- break;
+ break;
+ }
}
if (idx < 0)
return -EINVAL;
@@ -2925,7 +2922,9 @@ static int ieee80211_ioctl_giwencode(str
return 0;
}
- erq->length = 0;
+ memcpy(key, sdata->keys[idx]->key,
+ min((int)erq->length, sdata->keys[idx]->keylen));
+ erq->length = sdata->keys[idx]->keylen;
erq->flags |= IW_ENCODE_ENABLED;
return 0;
@@ -3054,9 +3053,10 @@ static int ieee80211_ioctl_siwencodeext(
if (!sdata->default_key)
idx = 0;
else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
- if (sdata->default_key == sdata->keys[i])
+ if (sdata->default_key == sdata->keys[i]) {
idx = i;
- break;
+ break;
+ }
}
if (idx < 0)
return -EINVAL;
diff --git a/net/d80211/ieee80211_led.c b/net/d80211/ieee80211_led.c
index de3f52c..073092a 100644
--- a/net/d80211/ieee80211_led.c
+++ b/net/d80211/ieee80211_led.c
@@ -1,32 +1,91 @@
/*
- * Copyright 2002-2004, Instant802 Networks, Inc.
+ * Copyright 2006, Johannes Berg <[EMAIL PROTECTED]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#include <linux/config.h>
-#include <linux/netdevice.h>
-#include <linux/types.h>
+/* just for IFNAMSIZ */
+#include <linux/if.h>
+#include "ieee80211_led.h"
-#ifdef CONFIG_OAP_LEDS_WLAN
-extern void leds_wlan_set(int unit, int tx, int state);
-#endif
+void ieee80211_led_rx(struct ieee80211_local *local)
+{
+ if (unlikely(!local->rx_led))
+ return;
+ if (local->rx_led_counter++ % 2 == 0)
+ led_trigger_event(local->rx_led, LED_OFF);
+ else
+ led_trigger_event(local->rx_led, LED_FULL);
+}
+
+/* q is 1 if a packet was enqueued, 0 if it has been transmitted */
+void ieee80211_led_tx(struct ieee80211_local *local, int q)
+{
+ if (unlikely(!local->tx_led))
+ return;
+ /* not sure how this is supposed to work ... */
+ local->tx_led_counter += 2*q-1;
+ if (local->tx_led_counter % 2 == 0)
+ led_trigger_event(local->tx_led, LED_OFF);
+ else
+ led_trigger_event(local->tx_led, LED_FULL);
+}
-void ieee80211_rx_led(int state, struct net_device *dev) {
-#ifdef CONFIG_OAP_LEDS_WLAN
- static unsigned int count = 0;
+void ieee80211_led_init(struct ieee80211_local *local)
+{
+ local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+ if (!local->rx_led)
+ return;
+ snprintf(local->rx_led_name, sizeof(local->rx_led_name),
+ "wiphy%drx", local->dev_index);
+ local->rx_led->name = local->rx_led_name;
+ if (led_trigger_register(local->rx_led)) {
+ kfree(local->rx_led);
+ local->rx_led = NULL;
+ }
- if (state == 2) {
- leds_wlan_set(0, 0, (++count) & 1);
+ local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+ if (!local->tx_led)
+ return;
+ snprintf(local->tx_led_name, sizeof(local->tx_led_name),
+ "wiphy%dtx", local->dev_index);
+ local->tx_led->name = local->tx_led_name;
+ if (led_trigger_register(local->tx_led)) {
+ kfree(local->tx_led);
+ local->tx_led = NULL;
}
-#endif
}
-void ieee80211_tx_led(int state, struct net_device *dev) {
-#ifdef CONFIG_OAP_LEDS_WLAN
- leds_wlan_set(0, 1, state);
-#endif
+void ieee80211_led_exit(struct ieee80211_local *local)
+{
+ if (local->tx_led) {
+ led_trigger_unregister(local->tx_led);
+ kfree(local->tx_led);
+ }
+ if (local->rx_led) {
+ led_trigger_unregister(local->rx_led);
+ kfree(local->rx_led);
+ }
}
+char *__ieee80211_get_tx_led_name(struct net_device *dev)
+{
+ struct ieee80211_local *local = dev->ieee80211_ptr;
+
+ if (local->tx_led)
+ return local->tx_led_name;
+ return NULL;
+}
+EXPORT_SYMBOL(__ieee80211_get_tx_led_name);
+
+char *__ieee80211_get_rx_led_name(struct net_device *dev)
+{
+ struct ieee80211_local *local = dev->ieee80211_ptr;
+
+ if (local->rx_led)
+ return local->rx_led_name;
+ return NULL;
+}
+EXPORT_SYMBOL(__ieee80211_get_rx_led_name);
diff --git a/net/d80211/ieee80211_led.h b/net/d80211/ieee80211_led.h
new file mode 100644
index 0000000..2a539af
--- /dev/null
+++ b/net/d80211/ieee80211_led.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2006, Johannes Berg <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/leds.h>
+#include "ieee80211_i.h"
+
+#ifdef CONFIG_D80211_LEDS
+extern void ieee80211_led_rx(struct ieee80211_local *local);
+extern void ieee80211_led_tx(struct ieee80211_local *local, int q);
+extern void ieee80211_led_init(struct ieee80211_local *local);
+extern void ieee80211_led_exit(struct ieee80211_local *local);
+#else
+static inline void ieee80211_led_rx(struct ieee80211_local *local)
+{
+}
+static inline void ieee80211_led_tx(struct ieee80211_local *local, int q)
+{
+}
+static inline void ieee80211_led_init(struct ieee80211_local *local)
+{
+}
+static inline void ieee80211_led_exit(struct ieee80211_local *local)
+{
+}
+#endif
diff --git a/net/d80211/ieee80211_sta.c b/net/d80211/ieee80211_sta.c
index a933d92..dd95ce8 100644
--- a/net/d80211/ieee80211_sta.c
+++ b/net/d80211/ieee80211_sta.c
@@ -710,6 +710,8 @@ static void ieee80211_associated(struct
"range\n",
dev->name, MAC_ARG(ifsta->bssid));
disassoc = 1;
+ sta_info_free(sta, 0);
+ ifsta->probereq_poll = 0;
} else {
ieee80211_send_probe_req(dev, ifsta->bssid,
local->scan_ssid,
@@ -1539,12 +1541,12 @@ #endif
}
- bss->hw_mode = local->conf.phymode;
+ bss->hw_mode = rx_status->phymode;
bss->channel = channel;
- bss->freq = local->conf.freq;
- if (channel != local->conf.channel &&
- (local->conf.phymode == MODE_IEEE80211G ||
- local->conf.phymode == MODE_IEEE80211B) &&
+ bss->freq = rx_status->freq;
+ if (channel != rx_status->channel &&
+ (bss->hw_mode == MODE_IEEE80211G ||
+ bss->hw_mode == MODE_IEEE80211B) &&
channel >= 1 && channel <= 14) {
static const int freq_list[] = {
2412, 2417, 2422, 2427, 2432, 2437, 2442,
@@ -1789,13 +1791,11 @@ void ieee80211_sta_rx_scan(struct net_de
static int ieee80211_sta_active_ibss(struct net_device *dev)
{
struct ieee80211_local *local = dev->ieee80211_ptr;
- struct list_head *ptr;
int active = 0;
struct sta_info *sta;
spin_lock_bh(&local->sta_lock);
- list_for_each(ptr, &local->sta_list) {
- sta = list_entry(ptr, struct sta_info, list);
+ list_for_each_entry(sta, &local->sta_list, list) {
if (sta->dev == dev &&
time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
jiffies)) {
@@ -1812,19 +1812,16 @@ static int ieee80211_sta_active_ibss(str
static void ieee80211_sta_expire(struct net_device *dev)
{
struct ieee80211_local *local = dev->ieee80211_ptr;
- struct list_head *ptr, *n;
- struct sta_info *sta;
+ struct sta_info *sta, *tmp;
spin_lock_bh(&local->sta_lock);
- list_for_each_safe(ptr, n, &local->sta_list) {
- sta = list_entry(ptr, struct sta_info, list);
+ list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
if (time_after(jiffies, sta->last_rx +
IEEE80211_IBSS_INACTIVITY_LIMIT)) {
printk(KERN_DEBUG "%s: expiring inactive STA " MAC_FMT
"\n", dev->name, MAC_ARG(sta->addr));
sta_info_free(sta, 1);
}
- }
spin_unlock_bh(&local->sta_lock);
}
@@ -2179,7 +2176,6 @@ static int ieee80211_sta_find_ibss(struc
struct ieee80211_sta_bss *bss;
int found = 0;
u8 bssid[ETH_ALEN];
- struct list_head *ptr;
int active_ibss;
if (ifsta->ssid_len == 0)
@@ -2191,8 +2187,7 @@ #ifdef CONFIG_D80211_IBSS_DEBUG
dev->name, active_ibss);
#endif /* CONFIG_D80211_IBSS_DEBUG */
spin_lock_bh(&local->sta_bss_lock);
- list_for_each(ptr, &local->sta_bss_list) {
- bss = list_entry(ptr, struct ieee80211_sta_bss, list);
+ list_for_each_entry(bss, &local->sta_bss_list, list) {
if (ifsta->ssid_len != bss->ssid_len ||
memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0
|| !(bss->capability & WLAN_CAPABILITY_IBSS))
@@ -2408,6 +2403,29 @@ static int ieee80211_active_scan(struct
}
+void ieee80211_scan_completed(struct net_device *dev)
+{
+ struct ieee80211_local *local = dev->ieee80211_ptr;
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ union iwreq_data wrqu;
+
+ printk(KERN_DEBUG "%s: scan completed\n", dev->name);
+ local->sta_scanning = 0;
+ local->last_scan_completed = jiffies;
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
+
+ if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+ if (!ifsta->bssid_set ||
+ (!ifsta->state == IEEE80211_IBSS_JOINED &&
+ !ieee80211_sta_active_ibss(dev)))
+ ieee80211_sta_find_ibss(dev, ifsta);
+ }
+}
+EXPORT_SYMBOL(ieee80211_scan_completed);
+
static void ieee80211_sta_scan_work(void *ptr)
{
struct net_device *dev = ptr;
@@ -2416,7 +2434,6 @@ static void ieee80211_sta_scan_work(void
struct ieee80211_hw_modes *mode;
struct ieee80211_channel *chan;
int skip;
- union iwreq_data wrqu;
unsigned long next_delay = 0;
if (!local->sta_scanning)
@@ -2433,20 +2450,8 @@ static void ieee80211_sta_scan_work(void
"operational channel after scan\n",
dev->name);
}
- printk(KERN_DEBUG "%s: scan completed\n", dev->name);
- local->sta_scanning = 0;
- local->last_scan_completed = jiffies;
- memset(&wrqu, 0, sizeof(wrqu));
- wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
- if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
- struct ieee80211_sub_if_data *sdata =
- IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
- if (!ifsta->bssid_set ||
- (ifsta->state == IEEE80211_IBSS_JOINED &&
- !ieee80211_sta_active_ibss(dev)))
- ieee80211_sta_find_ibss(dev, ifsta);
- }
+
+ ieee80211_scan_completed(dev);
return;
}
skip = !(local->enabled_modes & (1 << mode->mode));
@@ -2547,6 +2552,13 @@ int ieee80211_sta_req_scan(struct net_de
printk(KERN_DEBUG "%s: starting scan\n", dev->name);
+ if (local->hw->hw_scan) {
+ int rc = local->hw->hw_scan(dev, ssid, ssid_len);
+ if (!rc)
+ local->sta_scanning = 1;
+ return rc;
+ }
+
ieee80211_sta_save_oper_chan(dev);
local->sta_scanning = 1;
@@ -2714,15 +2726,21 @@ ieee80211_sta_scan_result(struct net_dev
current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
buf);
- p = buf;
- p += sprintf(p, "supp_rates=");
- for (i = 0; i < bss->supp_rates_len; i++)
- p+= sprintf(p, "%02x", bss->supp_rates[i]);
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = strlen(buf);
- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
- buf);
+ /* dispaly all support rates in readable format */
+ p = current_ev + IW_EV_LCP_LEN;
+ iwe.cmd = SIOCGIWRATE;
+ /* Those two flags are ignored... */
+ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+
+ for (i = 0; i < bss->supp_rates_len; i++) {
+ iwe.u.bitrate.value = ((bss->supp_rates[i] &
+ 0x7f) * 500000);
+ p = iwe_stream_add_value(current_ev, p,
+ end_buf, &iwe, IW_EV_PARAM_LEN);
+ }
+ /* Check if we added any rate */
+ if((p - current_ev) > IW_EV_LCP_LEN)
+ current_ev = p;
kfree(buf);
break;
@@ -2735,14 +2753,12 @@ ieee80211_sta_scan_result(struct net_dev
int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len)
{
struct ieee80211_local *local = dev->ieee80211_ptr;
- struct list_head *ptr;
char *current_ev = buf;
char *end_buf = buf + len;
struct ieee80211_sta_bss *bss;
spin_lock_bh(&local->sta_bss_lock);
- list_for_each(ptr, &local->sta_bss_list) {
- bss = list_entry(ptr, struct ieee80211_sta_bss, list);
+ list_for_each_entry(bss, &local->sta_bss_list, list) {
if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
spin_unlock_bh(&local->sta_bss_lock);
return -E2BIG;
@@ -2784,7 +2800,6 @@ struct sta_info * ieee80211_ibss_add_sta
u8 *addr)
{
struct ieee80211_local *local = dev->ieee80211_ptr;
- struct list_head *ptr;
struct sta_info *sta;
struct ieee80211_sub_if_data *sdata = NULL;
struct net_device *sta_dev = NULL;
@@ -2800,14 +2815,12 @@ struct sta_info * ieee80211_ibss_add_sta
}
spin_lock_bh(&local->sub_if_lock);
- list_for_each(ptr, &local->sub_if_list) {
- sdata = list_entry(ptr, struct ieee80211_sub_if_data, list);
+ list_for_each_entry(sdata, &local->sub_if_list, list)
if (sdata->type == IEEE80211_IF_TYPE_IBSS &&
memcmp(bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
sta_dev = sdata->dev;
break;
}
- }
spin_unlock_bh(&local->sub_if_lock);
if (!sta_dev)
diff --git a/net/d80211/sta_info.c b/net/d80211/sta_info.c
index 622b234..a326c4a 100644
--- a/net/d80211/sta_info.c
+++ b/net/d80211/sta_info.c
@@ -197,6 +197,12 @@ #ifdef CONFIG_D80211_VERBOSE_DEBUG
local->mdev->name, MAC_ARG(sta->addr));
#endif /* CONFIG_D80211_VERBOSE_DEBUG */
+ if (sta->key) {
+ ieee80211_key_sysfs_remove(sta->key);
+ ieee80211_key_free(sta->key);
+ sta->key = NULL;
+ }
+
rate_control_remove_sta_attrs(local, sta->rate_ctrl_priv, &sta->kobj);
ieee80211_sta_sysfs_remove(sta);
@@ -244,8 +250,6 @@ void sta_info_free(struct sta_info *sta,
kfree(key);
}
}
- ieee80211_key_free(sta->key);
- sta->key = NULL;
} else if (sta->key_idx_compression != HW_KEY_IDX_INVALID) {
struct ieee80211_key_conf conf;
memset(&conf, 0, sizeof(conf));
@@ -333,8 +337,7 @@ static void sta_info_cleanup(unsigned lo
static void sta_info_proc_add_task(void *data)
{
struct ieee80211_local *local = data;
- struct list_head *ptr;
- struct sta_info *sta;
+ struct sta_info *sta, *tmp;
while (1) {
spin_lock_bh(&local->sta_lock);
@@ -351,14 +354,14 @@ static void sta_info_proc_add_task(void
}
while (1) {
+ sta = NULL;
spin_lock_bh(&local->sta_lock);
- list_for_each(ptr, &local->sta_list) {
- sta = list_entry(ptr, struct sta_info, list);
- if (!sta->sysfs_registered) {
+ list_for_each_entry(tmp, &local->sta_list, list) {
+ if (!tmp->sysfs_registered) {
+ sta = tmp;
__sta_info_get(sta);
break;
}
- sta = NULL;
}
spin_unlock_bh(&local->sta_lock);
@@ -441,14 +444,11 @@ void sta_info_remove_aid_ptr(struct sta_
*/
void sta_info_flush(struct ieee80211_local *local, struct net_device *dev)
{
- struct list_head *ptr, *n;
+ struct sta_info *sta, *tmp;
spin_lock_bh(&local->sta_lock);
-
- list_for_each_safe(ptr, n, &local->sta_list) {
- struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+ list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
if (!dev || dev == sta->dev)
sta_info_free(sta, 1);
- }
spin_unlock_bh(&local->sta_lock);
}
diff --git a/net/d80211/wep.c b/net/d80211/wep.c
index c3e4728..22c2e53 100644
--- a/net/d80211/wep.c
+++ b/net/d80211/wep.c
@@ -120,10 +120,10 @@ void ieee80211_wep_encrypt_data(struct c
size_t klen, u8 *data, size_t data_len)
{
struct scatterlist sg;
- u32 *icv;
+ __le32 *icv;
- icv = (u32 *)(data + data_len);
- *icv = ~crc32_le(~0, data, data_len);
+ icv = (__le32 *)(data + data_len);
+ *icv = cpu_to_le32(~crc32_le(~0, data, data_len));
crypto_cipher_setkey(tfm, rc4key, klen);
sg.page = virt_to_page(data);
@@ -187,7 +187,7 @@ int ieee80211_wep_decrypt_data(struct cr
size_t klen, u8 *data, size_t data_len)
{
struct scatterlist sg;
- u32 crc;
+ __le32 crc;
crypto_cipher_setkey(tfm, rc4key, klen);
sg.page = virt_to_page(data);
@@ -195,7 +195,7 @@ int ieee80211_wep_decrypt_data(struct cr
sg.length = data_len + WEP_ICV_LEN;
crypto_cipher_decrypt(tfm, &sg, &sg, sg.length);
- crc = ~crc32_le(~0, data, data_len);
+ crc = cpu_to_le32(~crc32_le(~0, data, data_len));
if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0)
/* ICV mismatch */
return -1;
--
John W. Linville
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html