aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/b43legacy
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 22:54:01 +1100
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 22:54:01 +1100
commit0ba6c33bcddc64a54b5f1c25a696c4767dc76292 (patch)
tree62e616f97a4762d8e75bf732e4827af2d15d52c5 /drivers/net/wireless/b43legacy
parent21af0297c7e56024a5ccc4d8ad2a590f9ec371ba (diff)
parent85040bcb4643cba578839e953f25e2d1965d83d0 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25: (1470 commits) [IPV6] ADDRLABEL: Fix double free on label deletion. [PPP]: Sparse warning fixes. [IPV4] fib_trie: remove unneeded NULL check [IPV4] fib_trie: More whitespace cleanup. [NET_SCHED]: Use nla_policy for attribute validation in ematches [NET_SCHED]: Use nla_policy for attribute validation in actions [NET_SCHED]: Use nla_policy for attribute validation in classifiers [NET_SCHED]: Use nla_policy for attribute validation in packet schedulers [NET_SCHED]: sch_api: introduce constant for rate table size [NET_SCHED]: Use typeful attribute parsing helpers [NET_SCHED]: Use typeful attribute construction helpers [NET_SCHED]: Use NLA_PUT_STRING for string dumping [NET_SCHED]: Use nla_nest_start/nla_nest_end [NET_SCHED]: Propagate nla_parse return value [NET_SCHED]: act_api: use PTR_ERR in tcf_action_init/tcf_action_get [NET_SCHED]: act_api: use nlmsg_parse [NET_SCHED]: act_api: fix netlink API conversion bug [NET_SCHED]: sch_netem: use nla_parse_nested_compat [NET_SCHED]: sch_atm: fix format string warning [NETNS]: Add namespace for ICMP replying code. ...
Diffstat (limited to 'drivers/net/wireless/b43legacy')
-rw-r--r--drivers/net/wireless/b43legacy/Kconfig16
-rw-r--r--drivers/net/wireless/b43legacy/Makefile29
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h39
-rw-r--r--drivers/net/wireless/b43legacy/debugfs.c2
-rw-r--r--drivers/net/wireless/b43legacy/ilt.c2
-rw-r--r--drivers/net/wireless/b43legacy/leds.c417
-rw-r--r--drivers/net/wireless/b43legacy/leds.h61
-rw-r--r--drivers/net/wireless/b43legacy/main.c394
-rw-r--r--drivers/net/wireless/b43legacy/main.h2
-rw-r--r--drivers/net/wireless/b43legacy/phy.c75
-rw-r--r--drivers/net/wireless/b43legacy/phy.h16
-rw-r--r--drivers/net/wireless/b43legacy/radio.c36
-rw-r--r--drivers/net/wireless/b43legacy/radio.h4
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.c205
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.h59
-rw-r--r--drivers/net/wireless/b43legacy/xmit.c32
16 files changed, 784 insertions, 605 deletions
diff --git a/drivers/net/wireless/b43legacy/Kconfig b/drivers/net/wireless/b43legacy/Kconfig
index 7e23ec23fc9..6745579ba96 100644
--- a/drivers/net/wireless/b43legacy/Kconfig
+++ b/drivers/net/wireless/b43legacy/Kconfig
@@ -34,6 +34,22 @@ config B43LEGACY_PCICORE_AUTOSELECT
select SSB_DRIVER_PCICORE
default y
+# LED support
+# This config option automatically enables b43legacy LEDS support,
+# if it's possible.
+config B43LEGACY_LEDS
+ bool
+ depends on B43LEGACY && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43LEGACY)
+ default y
+
+# RFKILL support
+# This config option automatically enables b43legacy RFKILL support,
+# if it's possible.
+config B43LEGACY_RFKILL
+ bool
+ depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43LEGACY)
+ default y
+
config B43LEGACY_DEBUG
bool "Broadcom 43xx-legacy debugging"
depends on B43LEGACY
diff --git a/drivers/net/wireless/b43legacy/Makefile b/drivers/net/wireless/b43legacy/Makefile
index ec3a2482bba..80cdb73bd14 100644
--- a/drivers/net/wireless/b43legacy/Makefile
+++ b/drivers/net/wireless/b43legacy/Makefile
@@ -1,14 +1,19 @@
-obj-$(CONFIG_B43LEGACY) += b43legacy.o
-b43legacy-obj-$(CONFIG_B43LEGACY_DEBUG) += debugfs.o
+# b43legacy core
+b43legacy-y += main.o
+b43legacy-y += ilt.o
+b43legacy-y += phy.o
+b43legacy-y += radio.o
+b43legacy-y += sysfs.o
+b43legacy-y += xmit.o
+# b43 RFKILL button support
+b43legacy-$(CONFIG_B43LEGACY_RFKILL) += rfkill.o
+# b43legacy LED support
+b43legacy-$(CONFIG_B43LEGACY_LEDS) += leds.o
+# b43legacy debugging
+b43legacy-$(CONFIG_B43LEGACY_DEBUG) += debugfs.o
+# b43legacy DMA and PIO
+b43legacy-$(CONFIG_B43LEGACY_DMA) += dma.o
+b43legacy-$(CONFIG_B43LEGACY_PIO) += pio.o
-b43legacy-obj-$(CONFIG_B43LEGACY_DMA) += dma.o
-b43legacy-obj-$(CONFIG_B43LEGACY_PIO) += pio.o
+obj-$(CONFIG_B43LEGACY) += b43legacy.o
-b43legacy-objs := main.o \
- ilt.o \
- leds.o \
- phy.o \
- radio.o \
- sysfs.o \
- xmit.o \
- $(b43legacy-obj-y)
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index afe145cec06..93419adb925 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -19,6 +19,7 @@
#include "debugfs.h"
#include "leds.h"
+#include "rfkill.h"
#include "phy.h"
@@ -275,6 +276,8 @@
#define B43legacy_DEFAULT_SHORT_RETRY_LIMIT 7
#define B43legacy_DEFAULT_LONG_RETRY_LIMIT 4
+#define B43legacy_PHY_TX_BADNESS_LIMIT 1000
+
/* Max size of a security key */
#define B43legacy_SEC_KEYSIZE 16
/* Security algorithms. */
@@ -412,7 +415,6 @@ struct b43legacy_phy {
u8 calibrated:1;
u8 radio_rev; /* Radio revision */
- bool locked; /* Only used in b43legacy_phy_{un}lock() */
bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */
/* ACI (adjacent channel interference) flags. */
@@ -455,11 +457,6 @@ struct b43legacy_phy {
s16 lna_gain; /* LNA */
s16 pga_gain; /* PGA */
- /* PHY lock for core.rev < 3
- * This lock is only used by b43legacy_phy_{un}lock()
- */
- spinlock_t lock;
-
/* Desired TX power level (in dBm). This is set by the user and
* adjusted in b43legacy_phy_xmitpower(). */
u8 power_level;
@@ -483,9 +480,6 @@ struct b43legacy_phy {
u16 txpwr_offset;
};
-#ifdef CONFIG_B43LEGACY_DEBUG
- bool manual_txpower_control; /* Manual TX-power control enabled? */
-#endif
/* Current Interference Mitigation mode */
int interfmode;
/* Stack of saved values from the Interference Mitigation code.
@@ -510,6 +504,16 @@ struct b43legacy_phy {
u16 lofcal;
u16 initval;
+
+ /* PHY TX errors counter. */
+ atomic_t txerr_cnt;
+
+#if B43legacy_DEBUG
+ /* Manual TX-power control enabled? */
+ bool manual_txpower_control;
+ /* PHY registers locked by b43legacy_phy_lock()? */
+ bool phy_locked;
+#endif /* B43legacy_DEBUG */
};
/* Data structures for DMA transmission, per 80211 core. */
@@ -571,10 +575,7 @@ struct b43legacy_wl {
* at a time. General information about this interface follows.
*/
- /* Opaque ID of the operating interface from the ieee80211
- * subsystem. Do not modify.
- */
- int if_id;
+ struct ieee80211_vif *vif;
/* MAC address (can be NULL). */
u8 mac_addr[ETH_ALEN];
/* Current BSSID (can be NULL). */
@@ -592,9 +593,14 @@ struct b43legacy_wl {
u8 rng_initialized;
char rng_name[30 + 1];
+ /* The RF-kill button */
+ struct b43legacy_rfkill rfkill;
+
/* List of all wireless devices on this chip */
struct list_head devlist;
u8 nr_devs;
+
+ bool radiotap_enabled;
};
/* Pointers to the firmware data and meta information about it. */
@@ -663,8 +669,11 @@ struct b43legacy_wldev {
/* Various statistics about the physical device. */
struct b43legacy_stats stats;
-#define B43legacy_NR_LEDS 4
- struct b43legacy_led leds[B43legacy_NR_LEDS];
+ /* The device LEDs. */
+ struct b43legacy_led led_tx;
+ struct b43legacy_led led_rx;
+ struct b43legacy_led led_assoc;
+ struct b43legacy_led led_radio;
/* Reason code of the last interrupt. */
u32 irq_reason;
diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c
index 619b4534ef0..03ce0821a60 100644
--- a/drivers/net/wireless/b43legacy/debugfs.c
+++ b/drivers/net/wireless/b43legacy/debugfs.c
@@ -209,7 +209,7 @@ static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf,
struct b43legacy_wldev *dev;
struct b43legacy_debugfs_fops *dfops;
struct b43legacy_dfs_file *dfile;
- ssize_t ret = 0;
+ ssize_t uninitialized_var(ret);
char *buf;
const size_t bufsize = 1024 * 128;
const size_t buforder = get_order(bufsize);
diff --git a/drivers/net/wireless/b43legacy/ilt.c b/drivers/net/wireless/b43legacy/ilt.c
index 247fc780ffd..a849078aea6 100644
--- a/drivers/net/wireless/b43legacy/ilt.c
+++ b/drivers/net/wireless/b43legacy/ilt.c
@@ -3,7 +3,7 @@
Broadcom B43legacy wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Stefano Brivio <st3@riseup.net>
+ Stefano Brivio <stefano.brivio@polimi.it>
Michael Buesch <mbuesch@freenet.de>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
diff --git a/drivers/net/wireless/b43legacy/leds.c b/drivers/net/wireless/b43legacy/leds.c
index a584ea81050..cacb786d971 100644
--- a/drivers/net/wireless/b43legacy/leds.c
+++ b/drivers/net/wireless/b43legacy/leds.c
@@ -1,13 +1,13 @@
/*
- Broadcom B43legacy wireless driver
+ Broadcom B43 wireless driver
+ LED control
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Stefano Brivio <st3@riseup.net>
- Michael Buesch <mb@bu3sch.de>
- Danny van Dyk <kugelfang@gentoo.org>
- Andreas Jaggi <andreas.jaggi@waterwave.ch>
- Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
+ Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
+ Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
+ Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -26,273 +26,216 @@
*/
-#include "leds.h"
#include "b43legacy.h"
-#include "main.h"
-
-static void b43legacy_led_changestate(struct b43legacy_led *led)
-{
- struct b43legacy_wldev *dev = led->dev;
- const int index = led->index;
- u16 ledctl;
+#include "leds.h"
- B43legacy_WARN_ON(!(index >= 0 && index < B43legacy_NR_LEDS));
- B43legacy_WARN_ON(!led->blink_interval);
- ledctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
- ledctl ^= (1 << index);
- b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ledctl);
-}
-static void b43legacy_led_blink(unsigned long d)
+static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index,
+ bool activelow)
{
- struct b43legacy_led *led = (struct b43legacy_led *)d;
- struct b43legacy_wldev *dev = led->dev;
+ struct b43legacy_wl *wl = dev->wl;
unsigned long flags;
+ u16 ctl;
- spin_lock_irqsave(&dev->wl->leds_lock, flags);
- if (led->blink_interval) {
- b43legacy_led_changestate(led);
- mod_timer(&led->blink_timer, jiffies + led->blink_interval);
- }
- spin_unlock_irqrestore(&dev->wl->leds_lock, flags);
+ spin_lock_irqsave(&wl->leds_lock, flags);
+ ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
+ if (activelow)
+ ctl &= ~(1 << led_index);
+ else
+ ctl |= (1 << led_index);
+ b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
+ spin_unlock_irqrestore(&wl->leds_lock, flags);
}
-static void b43legacy_led_blink_start(struct b43legacy_led *led,
- unsigned long interval)
+static void b43legacy_led_turn_off(struct b43legacy_wldev *dev, u8 led_index,
+ bool activelow)
{
- if (led->blink_interval)
- return;
- led->blink_interval = interval;
- b43legacy_led_changestate(led);
- led->blink_timer.expires = jiffies + interval;
- add_timer(&led->blink_timer);
+ struct b43legacy_wl *wl = dev->wl;
+ unsigned long flags;
+ u16 ctl;
+
+ spin_lock_irqsave(&wl->leds_lock, flags);
+ ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
+ if (activelow)
+ ctl |= (1 << led_index);
+ else
+ ctl &= ~(1 << led_index);
+ b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
+ spin_unlock_irqrestore(&wl->leds_lock, flags);
}
-static void b43legacy_led_blink_stop(struct b43legacy_led *led, int sync)
+/* Callback from the LED subsystem. */
+static void b43legacy_led_brightness_set(struct led_classdev *led_dev,
+ enum led_brightness brightness)
{
+ struct b43legacy_led *led = container_of(led_dev, struct b43legacy_led,
+ led_dev);
struct b43legacy_wldev *dev = led->dev;
- const int index = led->index;
- u16 ledctl;
+ bool radio_enabled;
- if (!led->blink_interval)
- return;
- if (unlikely(sync))
- del_timer_sync(&led->blink_timer);
- else
- del_timer(&led->blink_timer);
- led->blink_interval = 0;
+ /* Checking the radio-enabled status here is slightly racy,
+ * but we want to avoid the locking overhead and we don't care
+ * whether the LED has the wrong state for a second. */
+ radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
- /* Make sure the LED is turned off. */
- B43legacy_WARN_ON(!(index >= 0 && index < B43legacy_NR_LEDS));
- ledctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
- if (led->activelow)
- ledctl |= (1 << index);
+ if (brightness == LED_OFF || !radio_enabled)
+ b43legacy_led_turn_off(dev, led->index, led->activelow);
else
- ledctl &= ~(1 << index);
- b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ledctl);
+ b43legacy_led_turn_on(dev, led->index, led->activelow);
}
-static void b43legacy_led_init_hardcoded(struct b43legacy_wldev *dev,
- struct b43legacy_led *led,
- int led_index)
+static int b43legacy_register_led(struct b43legacy_wldev *dev,
+ struct b43legacy_led *led,
+ const char *name, char *default_trigger,
+ u8 led_index, bool activelow)
{
- struct ssb_bus *bus = dev->dev->bus;
+ int err;
+
+ b43legacy_led_turn_off(dev, led_index, activelow);
+ if (led->dev)
+ return -EEXIST;
+ if (!default_trigger)
+ return -EINVAL;
+ led->dev = dev;
+ led->index = led_index;
+ led->activelow = activelow;
+ strncpy(led->name, name, sizeof(led->name));
+
+ led->led_dev.name = led->name;
+ led->led_dev.default_trigger = default_trigger;
+ led->led_dev.brightness_set = b43legacy_led_brightness_set;
+
+ err = led_classdev_register(dev->dev->dev, &led->led_dev);
+ if (err) {
+ b43legacywarn(dev->wl, "LEDs: Failed to register %s\n", name);
+ led->dev = NULL;
+ return err;
+ }
+ return 0;
+}
- /* This function is called, if the behaviour (and activelow)
- * information for a LED is missing in the SPROM.
- * We hardcode the behaviour values for various devices here.
- * Note that the B43legacy_LED_TEST_XXX behaviour values can
- * be used to figure out which led is mapped to which index.
- */
+static void b43legacy_unregister_led(struct b43legacy_led *led)
+{
+ if (!led->dev)
+ return;
+ led_classdev_unregister(&led->led_dev);
+ b43legacy_led_turn_off(led->dev, led->index, led->activelow);
+ led->dev = NULL;
+}
+
+static void b43legacy_map_led(struct b43legacy_wldev *dev,
+ u8 led_index,
+ enum b43legacy_led_behaviour behaviour,
+ bool activelow)
+{
+ struct ieee80211_hw *hw = dev->wl->hw;
+ char name[B43legacy_LED_MAX_NAME_LEN + 1];
- switch (led_index) {
- case 0:
- led->behaviour = B43legacy_LED_ACTIVITY;
- led->activelow = 1;
- if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
- led->behaviour = B43legacy_LED_RADIO_ALL;
+ /* Map the b43 specific LED behaviour value to the
+ * generic LED triggers. */
+ switch (behaviour) {
+ case B43legacy_LED_INACTIVE:
break;
- case 1:
- led->behaviour = B43legacy_LED_RADIO_B;
- if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
- led->behaviour = B43legacy_LED_ASSOC;
+ case B43legacy_LED_OFF:
+ b43legacy_led_turn_off(dev, led_index, activelow);
break;
- case 2:
- led->behaviour = B43legacy_LED_RADIO_A;
+ case B43legacy_LED_ON:
+ b43legacy_led_turn_on(dev, led_index, activelow);
break;
- case 3:
- led->behaviour = B43legacy_LED_OFF;
+ case B43legacy_LED_ACTIVITY:
+ case B43legacy_LED_TRANSFER:
+ case B43legacy_LED_APTRANSFER:
+ snprintf(name, sizeof(name),
+ "b43legacy-%s:tx", wiphy_name(hw->wiphy));
+ b43legacy_register_led(dev, &dev->led_tx, name,
+ ieee80211_get_tx_led_name(hw),
+ led_index, activelow);
+ snprintf(name, sizeof(name),
+ "b43legacy-%s:rx", wiphy_name(hw->wiphy));
+ b43legacy_register_led(dev, &dev->led_rx, name,
+ ieee80211_get_rx_led_name(hw),
+ led_index, activelow);
+ break;
+ case B43legacy_LED_RADIO_ALL:
+ case B43legacy_LED_RADIO_A:
+ case B43legacy_LED_RADIO_B:
+ case B43legacy_LED_MODE_BG:
+ snprintf(name, sizeof(name),
+ "b43legacy-%s:radio", wiphy_name(hw->wiphy));
+ b43legacy_register_led(dev, &dev->led_radio, name,
+ b43legacy_rfkill_led_name(dev),
+ led_index, activelow);
+ /* Sync the RF-kill LED state with the switch state. */
+ if (dev->radio_hw_enable)
+ b43legacy_led_turn_on(dev, led_index, activelow);
+ break;
+ case B43legacy_LED_WEIRD:
+ case B43legacy_LED_ASSOC:
+ snprintf(name, sizeof(name),
+ "b43legacy-%s:assoc", wiphy_name(hw->wiphy));
+ b43legacy_register_led(dev, &dev->led_assoc, name,
+ ieee80211_get_assoc_led_name(hw),
+ led_index, activelow);
break;
default:
- B43legacy_BUG_ON(1);
+ b43legacywarn(dev->wl, "LEDs: Unknown behaviour 0x%02X\n",
+ behaviour);
+ break;
}
}
-int b43legacy_leds_init(struct b43legacy_wldev *dev)
+void b43legacy_leds_init(struct b43legacy_wldev *dev)
{
- struct b43legacy_led *led;
+ struct ssb_bus *bus = dev->dev->bus;
u8 sprom[4];
int i;
-
- sprom[0] = dev->dev->bus->sprom.r1.gpio0;
- sprom[1] = dev->dev->bus->sprom.r1.gpio1;
- sprom[2] = dev->dev->bus->sprom.r1.gpio2;
- sprom[3] = dev->dev->bus->sprom.r1.gpio3;
-
- for (i = 0; i < B43legacy_NR_LEDS; i++) {
- led = &(dev->leds[i]);
- led->index = i;
- led->dev = dev;
- setup_timer(&led->blink_timer,
- b43legacy_led_blink,
- (unsigned long)led);
-
- if (sprom[i] == 0xFF)
- b43legacy_led_init_hardcoded(dev, led, i);
- else {
- led->behaviour = sprom[i] & B43legacy_LED_BEHAVIOUR;
- led->activelow = !!(sprom[i] &
- B43legacy_LED_ACTIVELOW);
+ enum b43legacy_led_behaviour behaviour;
+ bool activelow;
+
+ sprom[0] = bus->sprom.gpio0;
+ sprom[1] = bus->sprom.gpio1;
+ sprom[2] = bus->sprom.gpio2;
+ sprom[3] = bus->sprom.gpio3;
+
+ for (i = 0; i < 4; i++) {
+ if (sprom[i] == 0xFF) {
+ /* There is no LED information in the SPROM
+ * for this LED. Hardcode it here. */
+ activelow = 0;
+ switch (i) {
+ case 0:
+ behaviour = B43legacy_LED_ACTIVITY;
+ activelow = 1;
+ if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
+ behaviour = B43legacy_LED_RADIO_ALL;
+ break;
+ case 1:
+ behaviour = B43legacy_LED_RADIO_B;
+ if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
+ behaviour = B43legacy_LED_ASSOC;
+ break;
+ case 2:
+ behaviour = B43legacy_LED_RADIO_A;
+ break;
+ case 3:
+ behaviour = B43legacy_LED_OFF;
+ break;
+ default:
+ B43legacy_WARN_ON(1);
+ return;
+ }
+ } else {
+ behaviour = sprom[i] & B43legacy_LED_BEHAVIOUR;
+ activelow = !!(sprom[i] & B43legacy_LED_ACTIVELOW);
}
+ b43legacy_map_led(dev, i, behaviour, activelow);
}
-
- return 0;
}
void b43legacy_leds_exit(struct b43legacy_wldev *dev)
{
- struct b43legacy_led *led;
- int i;
-
- for (i = 0; i < B43legacy_NR_LEDS; i++) {
- led = &(dev->leds[i]);
- b43legacy_led_blink_stop(led, 1);
- }
- b43legacy_leds_switch_all(dev, 0);
-}
-
-void b43legacy_leds_update(struct b43legacy_wldev *dev, int activity)
-{
- struct b43legacy_led *led;
- struct b43legacy_phy *phy = &dev->phy;
- const int transferring = (jiffies - dev->stats.last_tx)
- < B43legacy_LED_XFER_THRES;
- int i;
- int turn_on;
- unsigned long interval = 0;
- u16 ledctl;
- unsigned long flags;
- bool radio_enabled = (phy->radio_on && dev->radio_hw_enable);
-
- spin_lock_irqsave(&dev->wl->leds_lock, flags);
- ledctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
- for (i = 0; i < B43legacy_NR_LEDS; i++) {
- led = &(dev->leds[i]);
-
- turn_on = 0;
- switch (led->behaviour) {
- case B43legacy_LED_INACTIVE:
- continue;
- case B43legacy_LED_OFF:
- break;
- case B43legacy_LED_ON:
- turn_on = 1;
- break;
- case B43legacy_LED_ACTIVITY:
- turn_on = activity;
- break;
- case B43legacy_LED_RADIO_ALL:
- turn_on = radio_enabled;
- break;
- case B43legacy_LED_RADIO_A:
- break;
- case B43legacy_LED_RADIO_B:
- turn_on = radio_enabled;
- break;
- case B43legacy_LED_MODE_BG:
- if (phy->type == B43legacy_PHYTYPE_G && radio_enabled)
- turn_on = 1;
- break;
- case B43legacy_LED_TRANSFER:
- if (transferring)
- b43legacy_led_blink_start(led,
- B43legacy_LEDBLINK_MEDIUM);
- else
- b43legacy_led_blink_stop(led, 0);
- continue;
- case B43legacy_LED_APTRANSFER:
- if (b43legacy_is_mode(dev->wl,
- IEEE80211_IF_TYPE_AP)) {
- if (transferring) {
- interval = B43legacy_LEDBLINK_FAST;
- turn_on = 1;
- }
- } else {
- turn_on = 1;
- if (transferring)
- interval = B43legacy_LEDBLINK_FAST;
- else
- turn_on = 0;
- }
- if (turn_on)
- b43legacy_led_blink_start(led, interval);
- else
- b43legacy_led_blink_stop(led, 0);
- continue;
- case B43legacy_LED_WEIRD:
- break;
- case B43legacy_LED_ASSOC:
- turn_on = 1;
-#ifdef CONFIG_B43LEGACY_DEBUG
- case B43legacy_LED_TEST_BLINKSLOW:
- b43legacy_led_blink_start(led, B43legacy_LEDBLINK_SLOW);
- continue;
- case B43legacy_LED_TEST_BLINKMEDIUM:
- b43legacy_led_blink_start(led,
- B43legacy_LEDBLINK_MEDIUM);
- continue;
- case B43legacy_LED_TEST_BLINKFAST:
- b43legacy_led_blink_start(led, B43legacy_LEDBLINK_FAST);
- continue;
-#endif /* CONFIG_B43LEGACY_DEBUG */
- default:
- B43legacy_BUG_ON(1);
- };
-
- if (led->activelow)
- turn_on = !turn_on;
- if (turn_on)
- ledctl |= (1 << i);
- else
- ledctl &= ~(1 << i);
- }
- b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ledctl);
- spin_unlock_irqrestore(&dev->wl->leds_lock, flags);
-}
-
-void b43legacy_leds_switch_all(struct b43legacy_wldev *dev, int on)
-{
- struct b43legacy_led *led;
- u16 ledctl;
- int i;
- int bit_on;
- unsigned long flags;
-
- spin_lock_irqsave(&dev->wl->leds_lock, flags);
- ledctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
- for (i = 0; i < B43legacy_NR_LEDS; i++) {
- led = &(dev->leds[i]);
- if (led->behaviour == B43legacy_LED_INACTIVE)
- continue;
- if (on)
- bit_on = led->activelow ? 0 : 1;
- else
- bit_on = led->activelow ? 1 : 0;
- if (bit_on)
- ledctl |= (1 << i);
- else
- ledctl &= ~(1 << i);
- }
- b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ledctl);
- spin_unlock_irqrestore(&dev->wl->leds_lock, flags);
+ b43legacy_unregister_led(&dev->led_tx);
+ b43legacy_unregister_led(&dev->led_rx);
+ b43legacy_unregister_led(&dev->led_assoc);
+ b43legacy_unregister_led(&dev->led_radio);
}
diff --git a/drivers/net/wireless/b43legacy/leds.h b/drivers/net/wireless/b43legacy/leds.h
index b989f503e68..82167a90088 100644
--- a/drivers/net/wireless/b43legacy/leds.h
+++ b/drivers/net/wireless/b43legacy/leds.h
@@ -1,30 +1,33 @@
#ifndef B43legacy_LEDS_H_
#define B43legacy_LEDS_H_
+struct b43legacy_wldev;
+
+#ifdef CONFIG_B43LEGACY_LEDS
+
#include <linux/types.h>
-#include <linux/timer.h>
+#include <linux/leds.h>
+#define B43legacy_LED_MAX_NAME_LEN 31
+
struct b43legacy_led {
- u8 behaviour;
- bool activelow;
- /* Index in the "leds" array in b43legacy_wldev */
- u8 index;
struct b43legacy_wldev *dev;
- struct timer_list blink_timer;
- unsigned long blink_interval;
+ /* The LED class device */
+ struct led_classdev led_dev;
+ /* The index number of the LED. */
+ u8 index;
+ /* If activelow is true, the LED is ON if the
+ * bit is switched off. */
+ bool activelow;
+ /* The unique name string for this LED device. */
+ char name[B43legacy_LED_MAX_NAME_LEN + 1];
};
-/* Delay between state changes when blinking in jiffies */
-#define B43legacy_LEDBLINK_SLOW (HZ / 1)
-#define B43legacy_LEDBLINK_MEDIUM (HZ / 4)
-#define B43legacy_LEDBLINK_FAST (HZ / 8)
-
-#define B43legacy_LED_XFER_THRES (HZ / 100)
-
#define B43legacy_LED_BEHAVIOUR 0x7F
#define B43legacy_LED_ACTIVELOW 0x80
-enum { /* LED behaviour values */
+/* LED behaviour values */
+enum b43legacy_led_behaviour {
B43legacy_LED_OFF,
B43legacy_LED_ON,
B43legacy_LED_ACTIVITY,
@@ -37,20 +40,24 @@ enum { /* LED behaviour values */
B43legacy_LED_WEIRD,
B43legacy_LED_ASSOC,
B43legacy_LED_INACTIVE,
-
- /* Behaviour values for testing.
- * With these values it is easier to figure out
- * the real behaviour of leds, in case the SPROM
- * is missing information.
- */
- B43legacy_LED_TEST_BLINKSLOW,
- B43legacy_LED_TEST_BLINKMEDIUM,
- B43legacy_LED_TEST_BLINKFAST,
};
-int b43legacy_leds_init(struct b43legacy_wldev *dev);
+void b43legacy_leds_init(struct b43legacy_wldev *dev);
void b43legacy_leds_exit(struct b43legacy_wldev *dev);
-void b43legacy_leds_update(struct b43legacy_wldev *dev, int activity);
-void b43legacy_leds_switch_all(struct b43legacy_wldev *dev, int on);
+
+#else /* CONFIG_B43EGACY_LEDS */
+/* LED support disabled */
+
+struct b43legacy_led {
+ /* empty */
+};
+
+static inline void b43legacy_leds_init(struct b43legacy_wldev *dev)
+{
+}
+static inline void b43legacy_leds_exit(struct b43legacy_wldev *dev)
+{
+}
+#endif /* CONFIG_B43LEGACY_LEDS */
#endif /* B43legacy_LEDS_H_ */
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 32d5e1785bd..4ed4243feea 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -3,7 +3,7 @@
* Broadcom B43legacy wireless driver
*
* Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
- * Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
+ * Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
* Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
* Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
* Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -75,18 +75,6 @@ module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames"
" Preemption");
-static int modparam_short_retry = B43legacy_DEFAULT_SHORT_RETRY_LIMIT;
-module_param_named(short_retry, modparam_short_retry, int, 0444);
-MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");
-
-static int modparam_long_retry = B43legacy_DEFAULT_LONG_RETRY_LIMIT;
-module_param_named(long_retry, modparam_long_retry, int, 0444);
-MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
-
-static int modparam_noleds;
-module_param_named(noleds, modparam_noleds, int, 0444);
-MODULE_PARM_DESC(noleds, "Turn off all LED activity");
-
static char modparam_fwpostfix[16];
module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444);
MODULE_PARM_DESC(fwpostfix, "Postfix for the firmware files to load.");
@@ -988,7 +976,7 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
plcp.data = 0;
b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->if_id,
+ dev->wl->vif,
size,
B43legacy_RATE_TO_100KBPS(rate));
/* Write PLCP in two parts and timing for packet transfer */
@@ -1054,7 +1042,7 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_RESP);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->if_id,
+ dev->wl->vif,
*dest_size,
B43legacy_RATE_TO_100KBPS(rate));
hdr->duration_id = dur;
@@ -1217,7 +1205,6 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
u32 dma_reason[ARRAY_SIZE(dev->dma_reason)];
u32 merged_dma_reason = 0;
int i;
- int activity = 0;
unsigned long flags;
spin_lock_irqsave(&dev->wl->irq_lock, flags);
@@ -1234,8 +1221,15 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
if (unlikely(reason & B43legacy_IRQ_MAC_TXERR))
b43legacyerr(dev->wl, "MAC transmission error\n");
- if (unlikely(reason & B43legacy_IRQ_PHY_TXERR))
+ if (unlikely(reason & B43legacy_IRQ_PHY_TXERR)) {
b43legacyerr(dev->wl, "PHY transmission error\n");
+ rmb();
+ if (unlikely(atomic_dec_and_test(&dev->phy.txerr_cnt))) {
+ b43legacyerr(dev->wl, "Too many PHY TX errors, "
+ "restarting the controller\n");
+ b43legacy_controller_restart(dev, "PHY TX errors");
+ }
+ }
if (unlikely(merged_dma_reason & (B43legacy_DMAIRQ_FATALMASK |
B43legacy_DMAIRQ_NONFATALMASK))) {
@@ -1281,7 +1275,6 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
b43legacy_pio_rx(dev->pio.queue0);
else
b43legacy_dma_rx(dev->dma.rx_ring0);
- /* We intentionally don't set "activity" to 1, here. */
}
B43legacy_WARN_ON(dma_reason[1] & B43legacy_DMAIRQ_RX_DONE);
B43legacy_WARN_ON(dma_reason[2] & B43legacy_DMAIRQ_RX_DONE);
@@ -1290,20 +1283,13 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
b43legacy_pio_rx(dev->pio.queue3);
else
b43legacy_dma_rx(dev->dma.rx_ring3);
- activity = 1;
}
B43legacy_WARN_ON(dma_reason[4] & B43legacy_DMAIRQ_RX_DONE);
B43legacy_WARN_ON(dma_reason[5] & B43legacy_DMAIRQ_RX_DONE);
- if (reason & B43legacy_IRQ_TX_OK) {
+ if (reason & B43legacy_IRQ_TX_OK)
handle_irq_transmit_status(dev);
- activity = 1;
- /* TODO: In AP mode, this also causes sending of powersave
- responses. */
- }
- if (!modparam_noleds)
- b43legacy_leds_update(dev, activity);
b43legacy_interrupt_enable(dev, dev->irq_savedstate);
mmiowb();
spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
@@ -1755,7 +1741,6 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev)
B43legacy_MMIO_STATUS_BITFIELD)
& 0xFFFF3FFF);
- b43legacy_leds_switch_all(dev, 0);
b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,
b43legacy_read16(dev,
B43legacy_MMIO_GPIO_MASK)
@@ -1767,7 +1752,7 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev)
mask |= 0x0060;
set |= 0x0060;
}
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_PACTRL) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_PACTRL) {
b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,
b43legacy_read16(dev,
B43legacy_MMIO_GPIO_MASK)
@@ -1811,6 +1796,7 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev)
{
dev->mac_suspended--;
B43legacy_WARN_ON(dev->mac_suspended < 0);
+ B43legacy_WARN_ON(irqs_disabled());
if (dev->mac_suspended == 0) {
b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
b43legacy_read32(dev,
@@ -1822,6 +1808,11 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev)
b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
b43legacy_power_saving_ctl_bits(dev, -1, -1);
+
+ /* Re-enable IRQs. */
+ spin_lock_irq(&dev->wl->irq_lock);
+ b43legacy_interrupt_enable(dev, dev->irq_savedstate);
+ spin_unlock_irq(&dev->wl->irq_lock);
}
}
@@ -1831,20 +1822,31 @@ void b43legacy_mac_suspend(struct b43legacy_wldev *dev)
int i;
u32 tmp;
+ might_sleep();
+ B43legacy_WARN_ON(irqs_disabled());
B43legacy_WARN_ON(dev->mac_suspended < 0);
+
if (dev->mac_suspended == 0) {
+ /* Mask IRQs before suspending MAC. Otherwise
+ * the MAC stays busy and won't suspend. */
+ spin_lock_irq(&dev->wl->irq_lock);
+ tmp = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL);
+ spin_unlock_irq(&dev->wl->irq_lock);
+ b43legacy_synchronize_irq(dev);
+ dev->irq_savedstate = tmp;
+
b43legacy_power_saving_ctl_bits(dev, -1, 1);
b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
b43legacy_read32(dev,
B43legacy_MMIO_STATUS_BITFIELD)
& ~B43legacy_SBF_MAC_ENABLED);
b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
- for (i = 10000; i; i--) {
+ for (i = 40; i; i--) {
tmp = b43legacy_read32(dev,
B43legacy_MMIO_GEN_IRQ_REASON);
if (tmp & B43legacy_IRQ_MAC_SUSPENDED)
goto out;
- udelay(1);
+ msleep(1);
}
b43legacyerr(dev->wl, "MAC suspend failed\n");
}
@@ -1989,27 +1991,10 @@ static void b43legacy_mgmtframe_txantenna(struct b43legacy_wldev *dev,
B43legacy_SHM_SH_PRPHYCTL, tmp);
}
-/* Returns TRUE, if the radio is enabled in hardware. */
-static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
-{
- if (dev->phy.rev >= 3) {
- if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
- & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
- return 1;
- } else {
- if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO)
- & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK)
- return 1;
- }
- return 0;
-}
-
/* This is the opposite of b43legacy_chip_init() */
static void b43legacy_chip_exit(struct b43legacy_wldev *dev)
{
- b43legacy_radio_turn_off(dev);
- if (!modparam_noleds)
- b43legacy_leds_exit(dev);
+ b43legacy_radio_turn_off(dev, 1);
b43legacy_gpio_cleanup(dev);
/* firmware is released later */
}
@@ -2039,9 +2024,10 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
err = b43legacy_gpio_init(dev);
if (err)
goto out; /* firmware is released later */
+
err = b43legacy_upload_initvals(dev);
if (err)
- goto err_gpio_cleanup;
+ goto err_gpio_clean;
b43legacy_radio_turn_on(dev);
b43legacy_write16(dev, 0x03E6, 0x0000);
@@ -2113,14 +2099,17 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
b43legacy_write16(dev, B43legacy_MMIO_POWERUP_DELAY,
dev->dev->bus->chipco.fast_pwrup_delay);
+ /* PHY TX errors counter. */
+ atomic_set(&phy->txerr_cnt, B43legacy_PHY_TX_BADNESS_LIMIT);
+
B43legacy_WARN_ON(err != 0);
b43legacydbg(dev->wl, "Chip initialized\n");
out:
return err;
err_radio_off:
- b43legacy_radio_turn_off(dev);
-err_gpio_cleanup:
+ b43legacy_radio_turn_off(dev, 1);
+err_gpio_clean:
b43legacy_gpio_cleanup(dev);
goto out;
}
@@ -2140,7 +2129,7 @@ static void b43legacy_periodic_every120sec(struct b43legacy_wldev *dev)
static void b43legacy_periodic_every60sec(struct b43legacy_wldev *dev)
{
b43legacy_phy_lo_mark_all_unused(dev);
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_RSSI) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI) {
b43legacy_mac_suspend(dev);
b43legacy_calc_nrssi_slope(dev);
b43legacy_mac_enable(dev);
@@ -2156,20 +2145,9 @@ static void b43legacy_periodic_every30sec(struct b43legacy_wldev *dev)
static void b43legacy_periodic_every15sec(struct b43legacy_wldev *dev)
{
b43legacy_phy_xmitpower(dev); /* FIXME: unless scanning? */
-}
-
-static void b43legacy_periodic_every1sec(struct b43legacy_wldev *dev)
-{
- bool radio_hw_enable;
- /* check if radio hardware enabled status changed */
- radio_hw_enable = b43legacy_is_hw_radio_enabled(dev);
- if (unlikely(dev->radio_hw_enable != radio_hw_enable)) {
- dev->radio_hw_enable = radio_hw_enable;
- b43legacyinfo(dev->wl, "Radio hardware status changed to %s\n",
- (radio_hw_enable) ? "enabled" : "disabled");
- b43legacy_leds_update(dev, 0);
- }
+ atomic_set(&dev->phy.txerr_cnt, B43legacy_PHY_TX_BADNESS_LIMIT);
+ wmb();
}
static void do_periodic_work(struct b43legacy_wldev *dev)
@@ -2177,94 +2155,45 @@ static void do_periodic_work(struct b43legacy_wldev *dev)
unsigned int state;
state = dev->periodic_state;
- if (state % 120 == 0)
+ if (state % 8 == 0)
b43legacy_periodic_every120sec(dev);
- if (state % 60 == 0)
+ if (state % 4 == 0)
b43legacy_periodic_every60sec(dev);
- if (state % 30 == 0)
+ if (state % 2 == 0)
b43legacy_periodic_every30sec(dev);
- if (state % 15 == 0)
- b43legacy_periodic_every15sec(dev);
- b43legacy_periodic_every1sec(dev);
+ b43legacy_periodic_every15sec(dev);
}
-/* Estimate a "Badness" value based on the periodic work
- * state-machine state. "Badness" is worse (bigger), if the
- * periodic work will take longer.
+/* Periodic work locking policy:
+ * The whole periodic work handler is protected by
+ * wl->mutex. If another lock is needed somewhere in the
+ * pwork callchain, it's aquired in-place, where it's needed.
*/
-static int estimate_periodic_work_badness(unsigned int state)
-{
- int badness = 0;
-
- if (state % 120 == 0) /* every 120 sec */
- badness += 10;
- if (state % 60 == 0) /* every 60 sec */
- badness += 5;
- if (state % 30 == 0) /* every 30 sec */
- badness += 1;
- if (state % 15 == 0) /* every 15 sec */
- badness += 1;
-
-#define BADNESS_LIMIT 4
- return badness;
-}
-
static void b43legacy_periodic_work_handler(struct work_struct *work)
{
- struct b43legacy_wldev *dev =
- container_of(work, struct b43legacy_wldev,
- periodic_work.work);
- unsigned long flags;
+ struct b43legacy_wldev *dev = container_of(work, struct b43legacy_wldev,
+ periodic_work.work);
+ struct b43legacy_wl *wl = dev->wl;
unsigned long delay;
- u32 savedirqs = 0;
- int badness;
- mutex_lock(&dev->wl->mutex);
+ mutex_lock(&wl->mutex);
if (unlikely(b43legacy_status(dev) != B43legacy_STAT_STARTED))
goto out;
if (b43legacy_debug(dev, B43legacy_DBG_PWORK_STOP))
goto out_requeue;
- badness = estimate_periodic_work_badness(dev->periodic_state);
- if (badness > BADNESS_LIMIT) {
- spin_lock_irqsave(&dev->wl->irq_lock, flags);
- /* Suspend TX as we don't want to transmit packets while
- * we recalibrate the hardware. */
- b43legacy_tx_suspend(dev);
- savedirqs = b43legacy_interrupt_disable(dev,
- B43legacy_IRQ_ALL);
- /* Periodic work will take a long time, so we want it to
- * be preemtible and release the spinlock. */
- spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
- b43legacy_synchronize_irq(dev);
-
- do_periodic_work(dev);
+ do_periodic_work(dev);
- spin_lock_irqsave(&dev->wl->irq_lock, flags);
- b43legacy_interrupt_enable(dev, savedirqs);
- b43legacy_tx_resume(dev);
- mmiowb();
- spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
- } else {
- /* Take the global driver lock. This will lock any operation. */
- spin_lock_irqsave(&dev->wl->irq_lock, flags);
-
- do_periodic_work(dev);
-
- mmiowb();
- spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
- }
dev->periodic_state++;
out_requeue:
if (b43legacy_debug(dev, B43legacy_DBG_PWORK_FAST))
delay = msecs_to_jiffies(50);
else
- delay = round_jiffies_relative(HZ);
- queue_delayed_work(dev->wl->hw->workqueue,
- &dev->periodic_work, delay);
+ delay = round_jiffies_relative(HZ * 15);
+ queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay);
out:
- mutex_unlock(&dev->wl->mutex);
+ mutex_unlock(&wl->mutex);
}
static void b43legacy_periodic_tasks_setup(struct b43legacy_wldev *dev)
@@ -2366,9 +2295,9 @@ static int b43legacy_rng_init(struct b43legacy_wl *wl)
return err;
}
-static int b43legacy_tx(struct ieee80211_hw *hw,
- struct sk_buff *skb,
- struct ieee80211_tx_control *ctl)
+static int b43legacy_op_tx(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct ieee80211_tx_control *ctl)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
@@ -2392,15 +2321,15 @@ out:
return NETDEV_TX_OK;
}
-static int b43legacy_conf_tx(struct ieee80211_hw *hw,
- int queue,
- const struct ieee80211_tx_queue_params *params)
+static int b43legacy_op_conf_tx(struct ieee80211_hw *hw,
+ int queue,
+ const struct ieee80211_tx_queue_params *params)
{
return 0;
}
-static int b43legacy_get_tx_stats(struct ieee80211_hw *hw,
- struct ieee80211_tx_queue_stats *stats)
+static int b43legacy_op_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
@@ -2422,8 +2351,8 @@ out:
return err;
}
-static int b43legacy_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats)
+static int b43legacy_op_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
unsigned long flags;
@@ -2572,8 +2501,8 @@ static int b43legacy_antenna_from_ieee80211(u8 antenna)
}
}
-static int b43legacy_dev_config(struct ieee80211_hw *hw,
- struct ieee80211_conf *conf)
+static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
+ struct ieee80211_conf *conf)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
@@ -2634,6 +2563,8 @@ static int b43legacy_dev_config(struct ieee80211_hw *hw,
b43legacy_short_slot_timing_disable(dev);
}
+ dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
+
/* Adjust the desired TX power level. */
if (conf->power_level != 0) {
if (conf->power_level != phy->power_level) {
@@ -2660,7 +2591,7 @@ static int b43legacy_dev_config(struct ieee80211_hw *hw,
" physically off. Press the"
" button to turn it on.\n");
} else {
- b43legacy_radio_turn_off(dev);
+ b43legacy_radio_turn_off(dev, 0);
b43legacyinfo(dev->wl, "Radio turned off by"
" software\n");
}
@@ -2676,37 +2607,11 @@ out_unlock_mutex:
return err;
}
-static int b43legacy_dev_set_key(struct ieee80211_hw *hw,
- enum set_key_cmd cmd,
- const u8 *local_addr, const u8 *addr,
- struct ieee80211_key_conf *key)
-{
- struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
- struct b43legacy_wldev *dev = wl->current_dev;
- unsigned long flags;
- int err = -EOPNOTSUPP;
- DECLARE_MAC_BUF(mac);
-
- if (!dev)
- return -ENODEV;
- mutex_lock(&wl->mutex);
- spin_lock_irqsave(&wl->irq_lock, flags);
-
- if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
- err = -ENODEV;
- }
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- mutex_unlock(&wl->mutex);
- b43legacydbg(wl, "Using software based encryption for "
- "mac: %s\n", print_mac(mac, addr));
- return err;
-}
-
-static void b43legacy_configure_filter(struct ieee80211_hw *hw,
- unsigned int changed,
- unsigned int *fflags,
- int mc_count,
- struct dev_addr_list *mc_list)
+static void b43legacy_op_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed,
+ unsigned int *fflags,
+ int mc_count,
+ struct dev_addr_list *mc_list)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
@@ -2741,9 +2646,9 @@ static void b43legacy_configure_filter(struct ieee80211_hw *hw,
spin_unlock_irqrestore(&wl->irq_lock, flags);
}
-static int b43legacy_config_interface(struct ieee80211_hw *hw,
- int if_id,
- struct ieee80211_if_conf *conf)
+static int b43legacy_op_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
@@ -2753,7 +2658,7 @@ static int b43legacy_config_interface(struct ieee80211_hw *hw,
return -ENODEV;
mutex_lock(&wl->mutex);
spin_lock_irqsave(&wl->irq_lock, flags);
- B43legacy_WARN_ON(wl->if_id != if_id);
+ B43legacy_WARN_ON(wl->vif != vif);
if (conf->bssid)
memcpy(wl->bssid, conf->bssid, ETH_ALEN);
else
@@ -2942,8 +2847,6 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev,
memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
- /* Flags */
- phy->locked = 0;
/* Assume the radio is enabled. If it's not enabled, the state will
* immediately get fixed on the first periodic work run. */
dev->radio_hw_enable = 1;
@@ -2976,7 +2879,6 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev,
phy->lofcal = 0xFFFF;
phy->initval = 0xFFFF;
- spin_lock_init(&phy->lock);
phy->interfmode = B43legacy_INTERFMODE_NONE;
phy->channel = 0xFF;
}
@@ -3029,6 +2931,20 @@ static void b43legacy_imcfglo_timeouts_workaround(struct b43legacy_wldev *dev)
#endif /* CONFIG_SSB_DRIVER_PCICORE */
}
+/* Write the short and long frame retry limit values. */
+static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev,
+ unsigned int short_retry,
+ unsigned int long_retry)
+{
+ /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
+ * the chip-internal counter. */
+ short_retry = min(short_retry, (unsigned int)0xF);
+ long_retry = min(long_retry, (unsigned int)0xF);
+
+ b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry);
+ b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
+}
+
/* Shutdown a wireless core */
/* Locking: wl->mutex */
static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
@@ -3047,11 +2963,12 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
cancel_work_sync(&dev->restart_work);
mutex_lock(&wl->mutex);
+ b43legacy_leds_exit(dev);
b43legacy_rng_exit(dev->wl);
b43legacy_pio_free(dev);
b43legacy_dma_free(dev);
b43legacy_chip_exit(dev);
- b43legacy_radio_turn_off(dev);
+ b43legacy_radio_turn_off(dev, 1);
b43legacy_switch_analog(dev, 0);
if (phy->dyn_tssi_tbl)
kfree(phy->tssi2dbm);
@@ -3093,7 +3010,6 @@ static void prepare_phy_data_for_init(struct b43legacy_wldev *dev)
/* Flags */
phy->calibrated = 0;
- phy->locked = 0;
if (phy->_lo_pairs)
memset(phy->_lo_pairs, 0,
@@ -3153,7 +3069,7 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
hf |= B43legacy_HF_SYMW;
if (phy->rev == 1)
hf |= B43legacy_HF_GDCW;
- if (sprom->r1.boardflags_lo & B43legacy_BFL_PACTRL)
+ if (sprom->boardflags_lo & B43legacy_BFL_PACTRL)
hf |= B43legacy_HF_OFDMPABOOST;
} else if (phy->type == B43legacy_PHYTYPE_B) {
hf |= B43legacy_HF_SYMW;
@@ -3162,16 +3078,9 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
}
b43legacy_hf_write(dev, hf);
- /* Short/Long Retry Limit.
- * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing
- * the chip-internal counter.
- */
- tmp = limit_value(modparam_short_retry, 0, 0xF);
- b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS,
- 0x0006, tmp);
- tmp = limit_value(modparam_long_retry, 0, 0xF);
- b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS,
- 0x0007, tmp);
+ b43legacy_set_retry_limits(dev,
+ B43legacy_DEFAULT_SHORT_RETRY_LIMIT,
+ B43legacy_DEFAULT_LONG_RETRY_LIMIT);
b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
0x0044, 3);
@@ -3223,6 +3132,7 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED);
+ b43legacy_leds_init(dev);
out:
return err;
@@ -3239,8 +3149,8 @@ err_kfree_lo_control:
return err;
}
-static int b43legacy_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
+static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
@@ -3263,7 +3173,7 @@ static int b43legacy_add_interface(struct ieee80211_hw *hw,
dev = wl->current_dev;
wl->operating = 1;
- wl->if_id = conf->if_id;
+ wl->vif = conf->vif;
wl->if_type = conf->type;
memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
@@ -3279,8 +3189,8 @@ static int b43legacy_add_interface(struct ieee80211_hw *hw,
return err;
}
-static void b43legacy_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
+static void b43legacy_op_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
@@ -3291,7 +3201,8 @@ static void b43legacy_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&wl->mutex);
B43legacy_WARN_ON(!wl->operating);
- B43legacy_WARN_ON(wl->if_id != conf->if_id);
+ B43legacy_WARN_ON(wl->vif != conf->vif);
+ wl->vif = NULL;
wl->operating = 0;
@@ -3304,13 +3215,17 @@ static void b43legacy_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&wl->mutex);
}
-static int b43legacy_start(struct ieee80211_hw *hw)
+static int b43legacy_op_start(struct ieee80211_hw *hw)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
int did_init = 0;
int err = 0;
+ /* First register RFkill.
+ * LEDs that are registered later depend on it. */
+ b43legacy_rfkill_init(dev);
+
mutex_lock(&wl->mutex);
if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
@@ -3335,11 +3250,13 @@ out_mutex_unlock:
return err;
}
-static void b43legacy_stop(struct ieee80211_hw *hw)
+static void b43legacy_op_stop(struct ieee80211_hw *hw)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
+ b43legacy_rfkill_exit(dev);
+
mutex_lock(&wl->mutex);
if (b43legacy_status(dev) >= B43legacy_STAT_STARTED)
b43legacy_wireless_core_stop(dev);
@@ -3347,20 +3264,41 @@ static void b43legacy_stop(struct ieee80211_hw *hw)
mutex_unlock(&wl->mutex);
}
+static int b43legacy_op_set_retry_limit(struct ieee80211_hw *hw,
+ u32 short_retry_limit,
+ u32 long_retry_limit)
+{
+ struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+ struct b43legacy_wldev *dev;
+ int err = 0;
+
+ mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+ if (unlikely(!dev ||
+ (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED))) {
+ err = -ENODEV;
+ goto out_unlock;
+ }
+ b43legacy_set_retry_limits(dev, short_retry_limit, long_retry_limit);
+out_unlock:
+ mutex_unlock(&wl->mutex);
+
+ return err;
+}
static const struct ieee80211_ops b43legacy_hw_ops = {
- .tx = b43legacy_tx,
- .conf_tx = b43legacy_conf_tx,
- .add_interface = b43legacy_add_interface,
- .remove_interface = b43legacy_remove_interface,
- .config = b43legacy_dev_config,
- .config_interface = b43legacy_config_interface,
- .set_key = b43legacy_dev_set_key,
- .configure_filter = b43legacy_configure_filter,
- .get_stats = b43legacy_get_stats,
- .get_tx_stats = b43legacy_get_tx_stats,
- .start = b43legacy_start,
- .stop = b43legacy_stop,
+ .tx = b43legacy_op_tx,
+ .conf_tx = b43legacy_op_conf_tx,
+ .add_interface = b43legacy_op_add_interface,
+ .remove_interface = b43legacy_op_remove_interface,
+ .config = b43legacy_op_dev_config,
+ .config_interface = b43legacy_op_config_interface,
+ .configure_filter = b43legacy_op_configure_filter,
+ .get_stats = b43legacy_op_get_stats,
+ .get_tx_stats = b43legacy_op_get_tx_stats,
+ .start = b43legacy_op_start,
+ .stop = b43legacy_op_stop,
+ .set_retry_limit = b43legacy_op_set_retry_limit,
};
/* Hard-reset the chip. Do not call this directly.
@@ -3498,18 +3436,13 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev)
else
have_bphy = 1;
- /* Initialize LEDs structs. */
- err = b43legacy_leds_init(dev);
- if (err)
- goto err_powerdown;
-
dev->phy.gmode = (have_gphy || have_bphy);
tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0;
b43legacy_wireless_core_reset(dev, tmp);
err = b43legacy_phy_versioning(dev);
if (err)
- goto err_leds_exit;
+ goto err_powerdown;
/* Check if this device supports multiband. */
if (!pdev ||
(pdev->device != 0x4312 &&
@@ -3535,17 +3468,17 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev)
err = b43legacy_validate_chipaccess(dev);
if (err)
- goto err_leds_exit;
+ goto err_powerdown;
err = b43legacy_setup_modes(dev, have_bphy, have_gphy);
if (err)
- goto err_leds_exit;
+ goto err_powerdown;
/* Now set some default "current_dev" */
if (!wl->current_dev)
wl->current_dev = dev;
INIT_WORK(&dev->restart_work, b43legacy_chip_reset);
- b43legacy_radio_turn_off(dev);
+ b43legacy_radio_turn_off(dev, 1);
b43legacy_switch_analog(dev, 0);
ssb_device_disable(dev->dev, 0);
ssb_bus_may_powerdown(bus);
@@ -3553,8 +3486,6 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev)
out:
return err;
-err_leds_exit:
- b43legacy_leds_exit(dev);
err_powerdown:
ssb_bus_may_powerdown(bus);
return err;
@@ -3637,12 +3568,7 @@ static void b43legacy_sprom_fixup(struct ssb_bus *bus)
if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
bus->boardinfo.type == 0x4E &&
bus->boardinfo.rev > 0x40)
- bus->sprom.r1.boardflags_lo |= B43legacy_BFL_PACTRL;
-
- /* Convert Antennagain values to Q5.2 */
- if (bus->sprom.r1.antenna_gain_bg == 0xFF)
- bus->sprom.r1.antenna_gain_bg = 2; /* if unset, use 2 dBm */
- bus->sprom.r1.antenna_gain_bg <<= 2;
+ bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL;
}
static void b43legacy_wireless_exit(struct ssb_device *dev,
@@ -3677,10 +3603,10 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
hw->max_noise = -110;
hw->queues = 1; /* FIXME: hardware has more queues */
SET_IEEE80211_DEV(hw, dev->dev);
- if (is_valid_ether_addr(sprom->r1.et1mac))
- SET_IEEE80211_PERM_ADDR(hw, sprom->r1.et1mac);
+ if (is_valid_ether_addr(sprom->et1mac))
+ SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
else
- SET_IEEE80211_PERM_ADDR(hw, sprom->r1.il0mac);
+ SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac);
/* Get and initialize struct b43legacy_wl */
wl = hw_to_b43legacy_wl(hw);
diff --git a/drivers/net/wireless/b43legacy/main.h b/drivers/net/wireless/b43legacy/main.h
index 68435c50d8e..1f0e2e379b0 100644
--- a/drivers/net/wireless/b43legacy/main.h
+++ b/drivers/net/wireless/b43legacy/main.h
@@ -3,7 +3,7 @@
Broadcom B43legacy wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
+ Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c
index 491e518e4ae..c16febbdbf5 100644
--- a/drivers/net/wireless/b43legacy/phy.c
+++ b/drivers/net/wireless/b43legacy/phy.c
@@ -3,7 +3,7 @@
Broadcom B43legacy wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Stefano Brivio <st3@riseup.net>
+ Stefano Brivio <stefano.brivio@polimi.it>
Michael Buesch <mbuesch@freenet.de>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -91,40 +91,36 @@ void b43legacy_voluntary_preempt(void)
#endif /* CONFIG_PREEMPT */
}
-void b43legacy_raw_phy_lock(struct b43legacy_wldev *dev)
+/* Lock the PHY registers against concurrent access from the microcode.
+ * This lock is nonrecursive. */
+void b43legacy_phy_lock(struct b43legacy_wldev *dev)
{
- struct b43legacy_phy *phy = &dev->phy;
+#if B43legacy_DEBUG
+ B43legacy_WARN_ON(dev->phy.phy_locked);
+ dev->phy.phy_locked = 1;
+#endif
- B43legacy_WARN_ON(!irqs_disabled());
- if (b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD) == 0) {
- phy->locked = 0;
- return;
- }
if (dev->dev->id.revision < 3) {
b43legacy_mac_suspend(dev);
- spin_lock(&phy->lock);
} else {
if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
b43legacy_power_saving_ctl_bits(dev, -1, 1);
}
- phy->locked = 1;
}
-void b43legacy_raw_phy_unlock(struct b43legacy_wldev *dev)
+void b43legacy_phy_unlock(struct b43legacy_wldev *dev)
{
- struct b43legacy_phy *phy = &dev->phy;
+#if B43legacy_DEBUG
+ B43legacy_WARN_ON(!dev->phy.phy_locked);
+ dev->phy.phy_locked = 0;
+#endif
- B43legacy_WARN_ON(!irqs_disabled());
if (dev->dev->id.revision < 3) {
- if (phy->locked) {
- spin_unlock(&phy->lock);
- b43legacy_mac_enable(dev);
- }
+ b43legacy_mac_enable(dev);
} else {
if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
b43legacy_power_saving_ctl_bits(dev, -1, -1);
}
- phy->locked = 0;
}
u16 b43legacy_phy_read(struct b43legacy_wldev *dev, u16 offset)
@@ -441,7 +437,7 @@ static void b43legacy_phy_inita(struct b43legacy_wldev *dev)
might_sleep();
b43legacy_phy_setupg(dev);
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_PACTRL)
+ if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_PACTRL)
b43legacy_phy_write(dev, 0x046E, 0x03CF);
}
@@ -543,7 +539,7 @@ static void b43legacy_phy_initb4(struct b43legacy_wldev *dev)
if (phy->radio_ver == 0x2050)
b43legacy_phy_write(dev, 0x002A, 0x88C2);
b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF);
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_RSSI) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI) {
b43legacy_calc_nrssi_slope(dev);
b43legacy_calc_nrssi_threshold(dev);
}
@@ -699,7 +695,7 @@ static void b43legacy_phy_initb6(struct b43legacy_wldev *dev)
b43legacy_radio_write16(dev, 0x005A, 0x0088);
b43legacy_radio_write16(dev, 0x005B, 0x006B);
b43legacy_radio_write16(dev, 0x005C, 0x000F);
- if (dev->dev->bus->sprom.r1.boardflags_lo & 0x8000) {
+ if (dev->dev->bus->sprom.boardflags_lo & 0x8000) {
b43legacy_radio_write16(dev, 0x005D, 0x00FA);
b43legacy_radio_write16(dev, 0x005E, 0x00D8);
} else {
@@ -797,7 +793,7 @@ static void b43legacy_phy_initb6(struct b43legacy_wldev *dev)
b43legacy_phy_write(dev, 0x0062, 0x0007);
b43legacy_radio_init2050(dev);
b43legacy_phy_lo_g_measure(dev);
- if (dev->dev->bus->sprom.r1.boardflags_lo &
+ if (dev->dev->bus->sprom.boardflags_lo &
B43legacy_BFL_RSSI) {
b43legacy_calc_nrssi_slope(dev);
b43legacy_calc_nrssi_threshold(dev);
@@ -921,7 +917,7 @@ static void b43legacy_calc_loopback_gain(struct b43legacy_wldev *dev)
b43legacy_phy_read(dev, 0x0811) | 0x0100);
b43legacy_phy_write(dev, 0x0812,
b43legacy_phy_read(dev, 0x0812) & 0xCFFF);
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_EXTLNA) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_EXTLNA) {
if (phy->rev >= 7) {
b43legacy_phy_write(dev, 0x0811,
b43legacy_phy_read(dev, 0x0811)
@@ -1072,7 +1068,7 @@ static void b43legacy_phy_initg(struct b43legacy_wldev *dev)
b43legacy_phy_write(dev, 0x0036,
(b43legacy_phy_read(dev, 0x0036)
& 0x0FFF) | (phy->txctl2 << 12));
- if (dev->dev->bus->sprom.r1.boardflags_lo &
+ if (dev->dev->bus->sprom.boardflags_lo &
B43legacy_BFL_PACTRL)
b43legacy_phy_write(dev, 0x002E, 0x8075);
else
@@ -1087,7 +1083,7 @@ static void b43legacy_phy_initg(struct b43legacy_wldev *dev)
b43legacy_phy_write(dev, 0x080F, 0x8078);
}
- if (!(dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_RSSI)) {
+ if (!(dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI)) {
/* The specs state to update the NRSSI LT with
* the value 0x7FFFFFFF here. I think that is some weird
* compiler optimization in the original driver.
@@ -1789,7 +1785,6 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
s16 baseband_att_delta;
s16 radio_attenuation;
s16 baseband_attenuation;
- unsigned long phylock_flags;
if (phy->savedpctlreg == 0xFFFF)
return;
@@ -1838,9 +1833,9 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
estimated_pwr = b43legacy_phy_estimate_power_out(dev, average);
- max_pwr = dev->dev->bus->sprom.r1.maxpwr_bg;
+ max_pwr = dev->dev->bus->sprom.maxpwr_bg;
- if ((dev->dev->bus->sprom.r1.boardflags_lo
+ if ((dev->dev->bus->sprom.boardflags_lo
& B43legacy_BFL_PACTRL) &&
(phy->type == B43legacy_PHYTYPE_G))
max_pwr -= 0x3;
@@ -1848,7 +1843,7 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
b43legacywarn(dev->wl, "Invalid max-TX-power value in SPROM."
"\n");
max_pwr = 74; /* fake it */
- dev->dev->bus->sprom.r1.maxpwr_bg = max_pwr;
+ dev->dev->bus->sprom.maxpwr_bg = max_pwr;
}
/* Use regulatory information to get the maximum power.
@@ -1858,7 +1853,8 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
* and 1.5 dBm (a safety factor??). The result is in Q5.2 format
* which accounts for the factor of 4 */
#define REG_MAX_PWR 20
- max_pwr = min(REG_MAX_PWR * 4 - dev->dev->bus->sprom.r1.antenna_gain_bg
+ max_pwr = min(REG_MAX_PWR * 4
+ - dev->dev->bus->sprom.antenna_gain.ghz24.a0
- 0x6, max_pwr);
/* find the desired power in Q5.2 - power_level is in dBm
@@ -1918,7 +1914,7 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
txpower = 3;
radio_attenuation += 2;
baseband_attenuation += 2;
- } else if (dev->dev->bus->sprom.r1.boardflags_lo
+ } else if (dev->dev->bus->sprom.boardflags_lo
& B43legacy_BFL_PACTRL) {
baseband_attenuation += 4 *
(radio_attenuation - 2);
@@ -1943,13 +1939,13 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
phy->bbatt = baseband_attenuation;
/* Adjust the hardware */
- b43legacy_phy_lock(dev, phylock_flags);
+ b43legacy_phy_lock(dev);
b43legacy_radio_lock(dev);
b43legacy_radio_set_txpower_bg(dev, baseband_attenuation,
radio_attenuation, txpower);
b43legacy_phy_lo_mark_current_used(dev);
b43legacy_radio_unlock(dev);
- b43legacy_phy_unlock(dev, phylock_flags);
+ b43legacy_phy_unlock(dev);
}
static inline
@@ -2000,9 +1996,9 @@ int b43legacy_phy_init_tssi2dbm_table(struct b43legacy_wldev *dev)
B43legacy_WARN_ON(!(phy->type == B43legacy_PHYTYPE_B ||
phy->type == B43legacy_PHYTYPE_G));
- pab0 = (s16)(dev->dev->bus->sprom.r1.pa0b0);
- pab1 = (s16)(dev->dev->bus->sprom.r1.pa0b1);
- pab2 = (s16)(dev->dev->bus->sprom.r1.pa0b2);
+ pab0 = (s16)(dev->dev->bus->sprom.pa0b0);
+ pab1 = (s16)(dev->dev->bus->sprom.pa0b1);
+ pab2 = (s16)(dev->dev->bus->sprom.pa0b2);
if ((dev->dev->bus->chip_id == 0x4301) && (phy->radio_ver != 0x2050)) {
phy->idle_tssi = 0x34;
@@ -2013,9 +2009,10 @@ int b43legacy_phy_init_tssi2dbm_table(struct b43legacy_wldev *dev)
if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
pab0 != -1 && pab1 != -1 && pab2 != -1) {
/* The pabX values are set in SPROM. Use them. */
- if ((s8)dev->dev->bus->sprom.r1.itssi_bg != 0 &&
- (s8)dev->dev->bus->sprom.r1.itssi_bg != -1)
- phy->idle_tssi = (s8)(dev->dev->bus->sprom.r1.itssi_bg);
+ if ((s8)dev->dev->bus->sprom.itssi_bg != 0 &&
+ (s8)dev->dev->bus->sprom.itssi_bg != -1)
+ phy->idle_tssi = (s8)(dev->dev->bus->sprom.
+ itssi_bg);
else
phy->idle_tssi = 62;
dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
diff --git a/drivers/net/wireless/b43legacy/phy.h b/drivers/net/wireless/b43legacy/phy.h
index f11b4271714..ecbe409f9a9 100644
--- a/drivers/net/wireless/b43legacy/phy.h
+++ b/drivers/net/wireless/b43legacy/phy.h
@@ -3,7 +3,7 @@
Broadcom B43legacy wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Stefano Brivio <st3@riseup.net>
+ Stefano Brivio <stefano.brivio@polimi.it>
Michael Buesch <mbuesch@freenet.de>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -171,18 +171,8 @@ void b43legacy_put_attenuation_into_ranges(int *_bbatt, int *_rfatt);
struct b43legacy_wldev;
-void b43legacy_raw_phy_lock(struct b43legacy_wldev *dev);
-#define b43legacy_phy_lock(bcm, flags) \
- do { \
- local_irq_save(flags); \
- b43legacy_raw_phy_lock(bcm); \
- } while (0)
-void b43legacy_raw_phy_unlock(struct b43legacy_wldev *dev);
-#define b43legacy_phy_unlock(bcm, flags) \
- do { \
- b43legacy_raw_phy_unlock(bcm); \
- local_irq_restore(flags); \
- } while (0)
+void b43legacy_phy_lock(struct b43legacy_wldev *dev);
+void b43legacy_phy_unlock(struct b43legacy_wldev *dev);
/* Card uses the loopback gain stuff */
#define has_loopback_gain(phy) \
diff --git a/drivers/net/wireless/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c
index a361dee664a..318a270cf9b 100644
--- a/drivers/net/wireless/b43legacy/radio.c
+++ b/drivers/net/wireless/b43legacy/radio.c
@@ -3,7 +3,7 @@
Broadcom B43legacy wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Stefano Brivio <st3@riseup.net>
+ Stefano Brivio <stefano.brivio@polimi.it>
Michael Buesch <mbuesch@freenet.de>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -92,6 +92,7 @@ void b43legacy_radio_lock(struct b43legacy_wldev *dev)
u32 status;
status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
+ B43legacy_WARN_ON(status & B43legacy_SBF_RADIOREG_LOCK);
status |= B43legacy_SBF_RADIOREG_LOCK;
b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
mmiowb();
@@ -104,6 +105,7 @@ void b43legacy_radio_unlock(struct b43legacy_wldev *dev)
b43legacy_read16(dev, B43legacy_MMIO_PHY_VER); /* dummy read */
status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
+ B43legacy_WARN_ON(!(status & B43legacy_SBF_RADIOREG_LOCK));
status &= ~B43legacy_SBF_RADIOREG_LOCK;
b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
mmiowb();
@@ -284,12 +286,11 @@ u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev)
unsigned int j;
unsigned int start;
unsigned int end;
- unsigned long phylock_flags;
if (!((phy->type == B43legacy_PHYTYPE_G) && (phy->rev > 0)))
return 0;
- b43legacy_phy_lock(dev, phylock_flags);
+ b43legacy_phy_lock(dev);
b43legacy_radio_lock(dev);
b43legacy_phy_write(dev, 0x0802,
b43legacy_phy_read(dev, 0x0802) & 0xFFFC);
@@ -323,7 +324,7 @@ u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev)
ret[j] = 1;
}
b43legacy_radio_unlock(dev);
- b43legacy_phy_unlock(dev, phylock_flags);
+ b43legacy_phy_unlock(dev);
return ret[channel - 1];
}
@@ -827,7 +828,7 @@ void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev)
case B43legacy_PHYTYPE_B: {
if (phy->radio_ver != 0x2050)
return;
- if (!(dev->dev->bus->sprom.r1.boardflags_lo &
+ if (!(dev->dev->bus->sprom.boardflags_lo &
B43legacy_BFL_RSSI))
return;
@@ -857,7 +858,7 @@ void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev)
}
case B43legacy_PHYTYPE_G:
if (!phy->gmode ||
- !(dev->dev->bus->sprom.r1.boardflags_lo &
+ !(dev->dev->bus->sprom.boardflags_lo &
B43legacy_BFL_RSSI)) {
tmp16 = b43legacy_nrssi_hw_read(dev, 0x20);
if (tmp16 >= 0x20)
@@ -1406,7 +1407,7 @@ static u16 b43legacy_get_812_value(struct b43legacy_wldev *dev, u8 lpd)
if (!phy->gmode)
return 0;
if (!has_loopback_gain(phy)) {
- if (phy->rev < 7 || !(dev->dev->bus->sprom.r1.boardflags_lo
+ if (phy->rev < 7 || !(dev->dev->bus->sprom.boardflags_lo
& B43legacy_BFL_EXTLNA)) {
switch (lpd) {
case LPD(0, 1, 1):
@@ -1459,7 +1460,7 @@ static u16 b43legacy_get_812_value(struct b43legacy_wldev *dev, u8 lpd)
}
loop_or = (loop << 8) | extern_lna_control;
- if (phy->rev >= 7 && dev->dev->bus->sprom.r1.boardflags_lo
+ if (phy->rev >= 7 && dev->dev->bus->sprom.boardflags_lo
& B43legacy_BFL_EXTLNA) {
if (extern_lna_control)
loop_or |= 0x8000;
@@ -1550,7 +1551,7 @@ u16 b43legacy_radio_init2050(struct b43legacy_wldev *dev)
b43legacy_get_812_value(dev,
LPD(0, 1, 1)));
if (phy->rev < 7 ||
- !(dev->dev->bus->sprom.r1.boardflags_lo
+ !(dev->dev->bus->sprom.boardflags_lo
& B43legacy_BFL_EXTLNA))
b43legacy_phy_write(dev, 0x0811, 0x01B3);
else
@@ -1786,7 +1787,7 @@ int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev,
channel2freq_bg(channel));
if (channel == 14) {
- if (dev->dev->bus->sprom.r1.country_code == 5) /* JAPAN) */
+ if (dev->dev->bus->sprom.country_code == 5) /* JAPAN) */
b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
B43legacy_UCODEFLAGS_OFFSET,
b43legacy_shm_read32(dev,
@@ -2113,21 +2114,25 @@ void b43legacy_radio_turn_on(struct b43legacy_wldev *dev)
B43legacy_BUG_ON(1);
}
phy->radio_on = 1;
- b43legacy_leds_update(dev, 0);
}
-void b43legacy_radio_turn_off(struct b43legacy_wldev *dev)
+void b43legacy_radio_turn_off(struct b43legacy_wldev *dev, bool force)
{
struct b43legacy_phy *phy = &dev->phy;
+ if (!phy->radio_on && !force)
+ return;
+
if (phy->type == B43legacy_PHYTYPE_G && dev->dev->id.revision >= 5) {
u16 rfover, rfoverval;
rfover = b43legacy_phy_read(dev, B43legacy_PHY_RFOVER);
rfoverval = b43legacy_phy_read(dev, B43legacy_PHY_RFOVERVAL);
- phy->radio_off_context.rfover = rfover;
- phy->radio_off_context.rfoverval = rfoverval;
- phy->radio_off_context.valid = 1;
+ if (!force) {
+ phy->radio_off_context.rfover = rfover;
+ phy->radio_off_context.rfoverval = rfoverval;
+ phy->radio_off_context.valid = 1;
+ }
b43legacy_phy_write(dev, B43legacy_PHY_RFOVER, rfover | 0x008C);
b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL,
rfoverval & 0xFF73);
@@ -2135,7 +2140,6 @@ void b43legacy_radio_turn_off(struct b43legacy_wldev *dev)
b43legacy_phy_write(dev, 0x0015, 0xAA00);
phy->radio_on = 0;
b43legacydbg(dev->wl, "Radio initialized\n");
- b43legacy_leds_update(dev, 0);
}
void b43legacy_radio_clear_tssi(struct b43legacy_wldev *dev)
diff --git a/drivers/net/wireless/b43legacy/radio.h b/drivers/net/wireless/b43legacy/radio.h
index 6c6a203439e..ec4de2811c5 100644
--- a/drivers/net/wireless/b43legacy/radio.h
+++ b/drivers/net/wireless/b43legacy/radio.h
@@ -3,7 +3,7 @@
Broadcom B43legacy wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Stefano Brivio <st3@riseup.net>
+ Stefano Brivio <stefano.brivio@polimi.it>
Michael Buesch <mbuesch@freenet.de>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -61,7 +61,7 @@ void b43legacy_radio_write16(struct b43legacy_wldev *dev, u16 offset, u16 val);
u16 b43legacy_radio_init2050(struct b43legacy_wldev *dev);
void b43legacy_radio_turn_on(struct b43legacy_wldev *dev);
-void b43legacy_radio_turn_off(struct b43legacy_wldev *dev);
+void b43legacy_radio_turn_off(struct b43legacy_wldev *dev, bool force);
int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev, u8 channel,
int synthetic_pu_workaround);
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c
new file mode 100644
index 00000000000..d178dfbb1c9
--- /dev/null
+++ b/drivers/net/wireless/b43legacy/rfkill.c
@@ -0,0 +1,205 @@
+/*
+
+ Broadcom B43 wireless driver
+ RFKILL support
+
+ Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "rfkill.h"
+#include "radio.h"
+#include "b43legacy.h"
+
+#include <linux/kmod.h>
+
+
+/* Returns TRUE, if the radio is enabled in hardware. */
+static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
+{
+ if (dev->phy.rev >= 3) {
+ if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
+ & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
+ return 1;
+ } else {
+ if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO)
+ & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK)
+ return 1;
+ }
+ return 0;
+}
+
+/* The poll callback for the hardware button. */
+static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev)
+{
+ struct b43legacy_wldev *dev = poll_dev->private;
+ struct b43legacy_wl *wl = dev->wl;
+ bool enabled;
+ bool report_change = 0;
+
+ mutex_lock(&wl->mutex);
+ if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) {
+ mutex_unlock(&wl->mutex);
+ return;
+ }
+ enabled = b43legacy_is_hw_radio_enabled(dev);
+ if (unlikely(enabled != dev->radio_hw_enable)) {
+ dev->radio_hw_enable = enabled;
+ report_change = 1;
+ b43legacyinfo(wl, "Radio hardware status changed to %s\n",
+ enabled ? "ENABLED" : "DISABLED");
+ }
+ mutex_unlock(&wl->mutex);
+
+ /* send the radio switch event to the system - note both a key press
+ * and a release are required */
+ if (unlikely(report_change)) {
+ input_report_key(poll_dev->input, KEY_WLAN, 1);
+ input_report_key(poll_dev->input, KEY_WLAN, 0);
+ }
+}
+
+/* Called when the RFKILL toggled in software.
+ * This is called without locking. */
+static int b43legacy_rfkill_soft_toggle(void *data, enum rfkill_state state)
+{
+ struct b43legacy_wldev *dev = data;
+ struct b43legacy_wl *wl = dev->wl;
+ int err = -EBUSY;
+
+ if (!wl->rfkill.registered)
+ return 0;
+
+ mutex_lock(&wl->mutex);
+ if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)
+ goto out_unlock;
+ err = 0;
+ switch (state) {
+ case RFKILL_STATE_ON:
+ if (!dev->radio_hw_enable) {
+ /* No luck. We can't toggle the hardware RF-kill
+ * button from software. */
+ err = -EBUSY;
+ goto out_unlock;
+ }
+ if (!dev->phy.radio_on)
+ b43legacy_radio_turn_on(dev);
+ break;
+ case RFKILL_STATE_OFF:
+ if (dev->phy.radio_on)
+ b43legacy_radio_turn_off(dev, 0);
+ break;
+ }
+
+out_unlock:
+ mutex_unlock(&wl->mutex);
+
+ return err;
+}
+
+char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
+{
+ struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
+
+ if (!rfk->registered)
+ return NULL;
+ return rfkill_get_led_name(rfk->rfkill);
+}
+
+void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
+{
+ struct b43legacy_wl *wl = dev->wl;
+ struct b43legacy_rfkill *rfk = &(wl->rfkill);
+ int err;
+
+ rfk->registered = 0;
+
+ rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
+ if (!rfk->rfkill)
+ goto out_error;
+ snprintf(rfk->name, sizeof(rfk->name),
+ "b43legacy-%s", wiphy_name(wl->hw->wiphy));
+ rfk->rfkill->name = rfk->name;
+ rfk->rfkill->state = RFKILL_STATE_ON;
+ rfk->rfkill->data = dev;
+ rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle;
+ rfk->rfkill->user_claim_unsupported = 1;
+
+ rfk->poll_dev = input_allocate_polled_device();
+ if (!rfk->poll_dev) {
+ rfkill_free(rfk->rfkill);
+ goto err_freed_rfk;
+ }
+
+ rfk->poll_dev->private = dev;
+ rfk->poll_dev->poll = b43legacy_rfkill_poll;
+ rfk->poll_dev->poll_interval = 1000; /* msecs */
+
+ rfk->poll_dev->input->name = rfk->name;
+ rfk->poll_dev->input->id.bustype = BUS_HOST;
+ rfk->poll_dev->input->id.vendor = dev->dev->bus->boardinfo.vendor;
+ rfk->poll_dev->input->evbit[0] = BIT(EV_KEY);
+ set_bit(KEY_WLAN, rfk->poll_dev->input->keybit);
+
+ err = rfkill_register(rfk->rfkill);
+ if (err)
+ goto err_free_polldev;
+
+#ifdef CONFIG_RFKILL_INPUT_MODULE
+ /* B43legacy RF-kill isn't useful without the rfkill-input subsystem.
+ * Try to load the module. */
+ err = request_module("rfkill-input");
+ if (err)
+ b43legacywarn(wl, "Failed to load the rfkill-input module."
+ "The built-in radio LED will not work.\n");
+#endif /* CONFIG_RFKILL_INPUT */
+
+ err = input_register_polled_device(rfk->poll_dev);
+ if (err)
+ goto err_unreg_rfk;
+
+ rfk->registered = 1;
+
+ return;
+err_unreg_rfk:
+ rfkill_unregister(rfk->rfkill);
+err_free_polldev:
+ input_free_polled_device(rfk->poll_dev);
+ rfk->poll_dev = NULL;
+err_freed_rfk:
+ rfk->rfkill = NULL;
+out_error:
+ rfk->registered = 0;
+ b43legacywarn(wl, "RF-kill button init failed\n");
+}
+
+void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
+{
+ struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
+
+ if (!rfk->registered)
+ return;
+ rfk->registered = 0;
+
+ input_unregister_polled_device(rfk->poll_dev);
+ rfkill_unregister(rfk->rfkill);
+ input_free_polled_device(rfk->poll_dev);
+ rfk->poll_dev = NULL;
+ rfk->rfkill = NULL;
+}
+
diff --git a/drivers/net/wireless/b43legacy/rfkill.h b/drivers/net/wireless/b43legacy/rfkill.h
new file mode 100644
index 00000000000..11150a8032f
--- /dev/null
+++ b/drivers/net/wireless/b43legacy/rfkill.h
@@ -0,0 +1,59 @@
+#ifndef B43legacy_RFKILL_H_
+#define B43legacy_RFKILL_H_
+
+struct b43legacy_wldev;
+
+#ifdef CONFIG_B43LEGACY_RFKILL
+
+#include <linux/rfkill.h>
+#include <linux/workqueue.h>
+#include <linux/input-polldev.h>
+
+
+
+struct b43legacy_rfkill {
+ /* The RFKILL subsystem data structure */
+ struct rfkill *rfkill;
+ /* The poll device for the RFKILL input button */
+ struct input_polled_dev *poll_dev;
+ /* Did initialization succeed? Used for freeing. */
+ bool registered;
+ /* The unique name of this rfkill switch */
+ char name[sizeof("b43legacy-phy4294967295")];
+};
+
+/* The init function returns void, because we are not interested
+ * in failing the b43 init process when rfkill init failed. */
+void b43legacy_rfkill_init(struct b43legacy_wldev *dev);
+void b43legacy_rfkill_exit(struct b43legacy_wldev *dev);
+
+char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev);
+
+
+#else /* CONFIG_B43LEGACY_RFKILL */
+/* No RFKILL support. */
+
+struct b43legacy_rfkill {
+ /* empty */
+};
+
+static inline void b43legacy_rfkill_alloc(struct b43legacy_wldev *dev)
+{
+}
+static inline void b43legacy_rfkill_free(struct b43legacy_wldev *dev)
+{
+}
+static inline void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
+{
+}
+static inline void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
+{
+}
+static inline char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
+{
+ return NULL;
+}
+
+#endif /* CONFIG_B43LEGACY_RFKILL */
+
+#endif /* B43legacy_RFKILL_H_ */
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index fa1e65687a6..e20c552442d 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -5,7 +5,7 @@
Transmission (TX/RX) related functions.
Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
- Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
+ Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de>
Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -223,7 +223,7 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
} else {
int fbrate_base100kbps = B43legacy_RATE_TO_100KBPS(rate_fb);
txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->if_id,
+ txctl->vif,
fragment_len,
fbrate_base100kbps);
}
@@ -290,6 +290,8 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
mac_ctl |= B43legacy_TX4_MAC_STMSDU;
if (rate_fb_ofdm)
mac_ctl |= B43legacy_TX4_MAC_FALLBACKOFDM;
+ if (txctl->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)
+ mac_ctl |= B43legacy_TX4_MAC_LONGFRAME;
/* Generate the RTS or CTS-to-self frame */
if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
@@ -310,7 +312,7 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
ieee80211_ctstoself_get(dev->wl->hw,
- dev->wl->if_id,
+ txctl->vif,
fragment_data,
fragment_len, txctl,
(struct ieee80211_cts *)
@@ -319,7 +321,7 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
len = sizeof(struct ieee80211_cts);
} else {
ieee80211_rts_get(dev->wl->hw,
- dev->wl->if_id,
+ txctl->vif,
fragment_data, fragment_len, txctl,
(struct ieee80211_rts *)
(txhdr->rts_frame));
@@ -335,7 +337,6 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
len, rts_rate_fb);
hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame);
txhdr->rts_dur_fb = hdr->duration_id;
- mac_ctl |= B43legacy_TX4_MAC_LONGFRAME;
}
/* Magic cookie */
@@ -378,7 +379,7 @@ static s8 b43legacy_rssi_postprocess(struct b43legacy_wldev *dev,
else
tmp -= 3;
} else {
- if (dev->dev->bus->sprom.r1.boardflags_lo
+ if (dev->dev->bus->sprom.boardflags_lo
& B43legacy_BFL_RSSI) {
if (in_rssi > 63)
in_rssi = 63;
@@ -531,7 +532,24 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
else
status.rate = b43legacy_plcp_get_bitrate_cck(plcp);
status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT);
- status.mactime = mactime;
+
+ /*
+ * If monitors are present get full 64-bit timestamp. This
+ * code assumes we get to process the packet within 16 bits
+ * of timestamp, i.e. about 65 milliseconds after the PHY
+ * received the first symbol.
+ */
+ if (dev->wl->radiotap_enabled) {
+ u16 low_mactime_now;
+
+ b43legacy_tsf_read(dev, &status.mactime);
+ low_mactime_now = status.mactime;
+ status.mactime = status.mactime & ~0xFFFFULL;
+ status.mactime += mactime;
+ if (low_mactime_now <= mactime)
+ status.mactime -= 0x10000;
+ status.flag |= RX_FLAG_TSFT;
+ }
chanid = (chanstat & B43legacy_RX_CHAN_ID) >>
B43legacy_RX_CHAN_ID_SHIFT;