summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS20
-rw-r--r--drivers/bluetooth/Kconfig12
-rw-r--r--drivers/bluetooth/Makefile1
-rw-r--r--drivers/bluetooth/bcm203x.c3
-rw-r--r--drivers/bluetooth/bpa10x.c2
-rw-r--r--drivers/bluetooth/btmrvl_debugfs.c2
-rw-r--r--drivers/bluetooth/btmrvl_drv.h5
-rw-r--r--drivers/bluetooth/btmrvl_main.c5
-rw-r--r--drivers/bluetooth/btmrvl_sdio.c111
-rw-r--r--drivers/bluetooth/btusb.c13
-rw-r--r--drivers/bluetooth/dtl1_cs.c2
-rw-r--r--drivers/bluetooth/hci_ath.c235
-rw-r--r--drivers/bluetooth/hci_bcsp.c4
-rw-r--r--drivers/bluetooth/hci_h4.c107
-rw-r--r--drivers/bluetooth/hci_ldisc.c20
-rw-r--r--drivers/bluetooth/hci_ll.c6
-rw-r--r--drivers/bluetooth/hci_uart.h15
-rw-r--r--drivers/net/wireless/adm8211.c53
-rw-r--r--drivers/net/wireless/at76c50x-usb.c168
-rw-r--r--drivers/net/wireless/ath/ar9170/cmd.c7
-rw-r--r--drivers/net/wireless/ath/ar9170/led.c4
-rw-r--r--drivers/net/wireless/ath/ar9170/main.c191
-rw-r--r--drivers/net/wireless/ath/ar9170/phy.c8
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_phy.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c21
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c13
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c601
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.h89
-rw-r--r--drivers/net/wireless/ath/ath9k/virtual.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c20
-rw-r--r--drivers/net/wireless/ipw2x00/libipw.h1
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_tx.c16
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_wx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.c64
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c225
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rx.c167
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c141
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h55
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c65
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c18
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c22
-rw-r--r--drivers/net/wireless/libertas/cfg.c197
-rw-r--r--drivers/net/wireless/libertas/cfg.h6
-rw-r--r--drivers/net/wireless/libertas/cmd.c718
-rw-r--r--drivers/net/wireless/libertas/cmd.h25
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c179
-rw-r--r--drivers/net/wireless/libertas/debugfs.c67
-rw-r--r--drivers/net/wireless/libertas/decl.h5
-rw-r--r--drivers/net/wireless/libertas/defs.h18
-rw-r--r--drivers/net/wireless/libertas/dev.h6
-rw-r--r--drivers/net/wireless/libertas/host.h142
-rw-r--r--drivers/net/wireless/libertas/if_usb.c4
-rw-r--r--drivers/net/wireless/libertas/main.c35
-rw-r--r--drivers/net/wireless/libertas/mesh.c216
-rw-r--r--drivers/net/wireless/libertas/mesh.h14
-rw-r--r--drivers/net/wireless/libertas/tx.c2
-rw-r--r--drivers/net/wireless/libertas_tf/libertas_tf.h3
-rw-r--r--drivers/net/wireless/libertas_tf/main.c18
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c99
-rw-r--r--drivers/net/wireless/mwl8k.c154
-rw-r--r--drivers/net/wireless/orinoco/cfg.c5
-rw-r--r--drivers/net/wireless/p54/eeprom.c76
-rw-r--r--drivers/net/wireless/p54/fwio.c53
-rw-r--r--drivers/net/wireless/p54/led.c8
-rw-r--r--drivers/net/wireless/p54/main.c17
-rw-r--r--drivers/net/wireless/p54/p54pci.c3
-rw-r--r--drivers/net/wireless/p54/txrx.c36
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c19
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_dev.c35
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_grf5101.c12
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_max2820.c19
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_rtl8225.c5
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_sa2400.c28
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c11
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_rtl8225.c8
-rw-r--r--drivers/net/wireless/rtl818x/rtl818x.h1
-rw-r--r--drivers/net/wireless/wl12xx/wl1251.h3
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_boot.c8
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_cmd.h12
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_main.c22
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_rx.c6
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_tx.c10
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_tx.h8
-rw-r--r--drivers/net/wireless/wl12xx/wl1271.h3
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_main.c32
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_rx.c7
-rw-r--r--fs/compat_ioctl.c9
-rw-r--r--include/net/bluetooth/bluetooth.h3
-rw-r--r--include/net/bluetooth/hci.h187
-rw-r--r--include/net/bluetooth/hci_core.h30
-rw-r--r--include/net/bluetooth/l2cap.h34
-rw-r--r--include/net/bluetooth/rfcomm.h14
-rw-r--r--include/net/cfg80211.h65
-rw-r--r--include/net/lib80211.h3
-rw-r--r--include/net/mac80211.h12
-rw-r--r--net/bluetooth/Kconfig13
-rw-r--r--net/bluetooth/hci_conn.c34
-rw-r--r--net/bluetooth/hci_core.c204
-rw-r--r--net/bluetooth/hci_event.c39
-rw-r--r--net/bluetooth/hci_sock.c90
-rw-r--r--net/bluetooth/hci_sysfs.c38
-rw-r--r--net/bluetooth/l2cap.c669
-rw-r--r--net/bluetooth/rfcomm/sock.c2
-rw-r--r--net/bluetooth/rfcomm/tty.c4
-rw-r--r--net/mac80211/cfg.c13
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/key.c13
-rw-r--r--net/mac80211/key.h3
-rw-r--r--net/mac80211/main.c3
-rw-r--r--net/mac80211/mlme.c32
-rw-r--r--net/mac80211/rc80211_minstrel.c1
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c4
-rw-r--r--net/mac80211/scan.c8
-rw-r--r--net/mac80211/sta_info.c2
-rw-r--r--net/mac80211/tx.c19
-rw-r--r--net/mac80211/util.c8
-rw-r--r--net/mac80211/work.c43
-rw-r--r--net/wireless/core.c49
-rw-r--r--net/wireless/ibss.c4
-rw-r--r--net/wireless/lib80211_crypt_ccmp.c1
-rw-r--r--net/wireless/lib80211_crypt_tkip.c1
-rw-r--r--net/wireless/lib80211_crypt_wep.c1
-rw-r--r--net/wireless/nl80211.c2
-rw-r--r--net/wireless/reg.c8
145 files changed, 3858 insertions, 2826 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 1e4eb63e2fa4..b04b97fe3217 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3671,7 +3671,7 @@ F: include/linux/mv643xx.h
MARVELL MWL8K WIRELESS DRIVER
M: Lennert Buytenhek <buytenh@wantstofly.org>
L: linux-wireless@vger.kernel.org
-S: Maintained
+S: Odd Fixes
F: drivers/net/wireless/mwl8k.c
MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
@@ -4522,7 +4522,7 @@ PRISM54 WIRELESS DRIVER
M: "Luis R. Rodriguez" <mcgrof@gmail.com>
L: linux-wireless@vger.kernel.org
W: http://prism54.org
-S: Maintained
+S: Obsolete
F: drivers/net/wireless/prism54/
PROMISE DC4030 CACHING DISK CONTROLLER DRIVER
@@ -4712,9 +4712,8 @@ S: Maintained
F: drivers/rapidio/
RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
-M: Corey Thomas <coreythomas@charter.net>
L: linux-wireless@vger.kernel.org
-S: Maintained
+S: Orphan
F: drivers/net/wireless/ray*
RCUTORTURE MODULE
@@ -6037,10 +6036,9 @@ F: Documentation/video4linux/zc0301.txt
F: drivers/media/video/zc0301/
USB ZD1201 DRIVER
-M: Jeroen Vreeken <pe1rxq@amsat.org>
-L: linux-usb@vger.kernel.org
+L: linux-wireless@vger.kernel.org
W: http://linux-lc100020.sourceforge.net
-S: Maintained
+S: Orphan
F: drivers/net/wireless/zd1201.*
USB ZR364XX DRIVER
@@ -6226,14 +6224,6 @@ F: Documentation/watchdog/
F: drivers/watchdog/
F: include/linux/watchdog.h
-WAVELAN NETWORK DRIVER & WIRELESS EXTENSIONS
-M: Jean Tourrilhes <jt@hpl.hp.com>
-L: linux-wireless@vger.kernel.org
-W: http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
-S: Maintained
-F: Documentation/networking/wavelan.txt
-F: drivers/staging/wavelan/
-
WD7000 SCSI DRIVER
M: Miroslav Zagorac <zaga@fly.cc.fer.hr>
L: linux-scsi@vger.kernel.org
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 058fbccf2f52..02deef424926 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -58,6 +58,18 @@ config BT_HCIUART_BCSP
Say Y here to compile support for HCI BCSP protocol.
+config BT_HCIUART_ATH3K
+ bool "Atheros AR300x serial support"
+ depends on BT_HCIUART
+ help
+ HCIATH3K (HCI Atheros AR300x) is a serial protocol for
+ communication between host and Atheros AR300x Bluetooth devices.
+ This protocol enables AR300x chips to be enabled with
+ power management support.
+ Enable this if you have Atheros AR300x serial Bluetooth device.
+
+ Say Y here to compile support for HCI UART ATH3K protocol.
+
config BT_HCIUART_LL
bool "HCILL protocol support"
depends on BT_HCIUART
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 7e5aed598121..71bdf13287c4 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -26,4 +26,5 @@ hci_uart-y := hci_ldisc.o
hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o
hci_uart-$(CONFIG_BT_HCIUART_BCSP) += hci_bcsp.o
hci_uart-$(CONFIG_BT_HCIUART_LL) += hci_ll.o
+hci_uart-$(CONFIG_BT_HCIUART_ATH3K) += hci_ath.o
hci_uart-objs := $(hci_uart-y)
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c
index b0c84c19f442..8b1b643a519b 100644
--- a/drivers/bluetooth/bcm203x.c
+++ b/drivers/bluetooth/bcm203x.c
@@ -224,7 +224,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
- data->fw_data = kmalloc(firmware->size, GFP_KERNEL);
+ data->fw_data = kmemdup(firmware->data, firmware->size, GFP_KERNEL);
if (!data->fw_data) {
BT_ERR("Can't allocate memory for firmware image");
release_firmware(firmware);
@@ -234,7 +234,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
return -ENOMEM;
}
- memcpy(data->fw_data, firmware->data, firmware->size);
data->fw_size = firmware->size;
data->fw_sent = 0;
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index d945cd12433a..751b338d904a 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -62,7 +62,7 @@ struct hci_vendor_hdr {
__u8 type;
__le16 snum;
__le16 dlen;
-} __attribute__ ((packed));
+} __packed;
static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)
{
diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c
index b50b41d97a7f..54739b08c308 100644
--- a/drivers/bluetooth/btmrvl_debugfs.c
+++ b/drivers/bluetooth/btmrvl_debugfs.c
@@ -216,7 +216,7 @@ static const struct file_operations btmrvl_gpiogap_fops = {
static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
- struct btmrvl_private *priv = (struct btmrvl_private *) file->private_data;
+ struct btmrvl_private *priv = file->private_data;
char buf[16];
long result, ret;
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index bed0ba630235..90bda50dc446 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -76,6 +76,7 @@ struct btmrvl_private {
int (*hw_host_to_card) (struct btmrvl_private *priv,
u8 *payload, u16 nb);
int (*hw_wakeup_firmware) (struct btmrvl_private *priv);
+ int (*hw_process_int_status) (struct btmrvl_private *priv);
spinlock_t driver_lock; /* spinlock used by driver */
#ifdef CONFIG_DEBUG_FS
void *debugfs_data;
@@ -118,13 +119,13 @@ struct btmrvl_cmd {
__le16 ocf_ogf;
u8 length;
u8 data[4];
-} __attribute__ ((packed));
+} __packed;
struct btmrvl_event {
u8 ec; /* event counter */
u8 length;
u8 data[4];
-} __attribute__ ((packed));
+} __packed;
/* Prototype of global function */
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index ee37ef0caee2..0d32ec82e9bf 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -502,14 +502,17 @@ static int btmrvl_service_main_thread(void *data)
spin_lock_irqsave(&priv->driver_lock, flags);
if (adapter->int_count) {
adapter->int_count = 0;
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ priv->hw_process_int_status(priv);
} else if (adapter->ps_state == PS_SLEEP &&
!skb_queue_empty(&adapter->tx_queue)) {
spin_unlock_irqrestore(&priv->driver_lock, flags);
adapter->wakeup_tries++;
priv->hw_wakeup_firmware(priv);
continue;
+ } else {
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
}
- spin_unlock_irqrestore(&priv->driver_lock, flags);
if (adapter->ps_state == PS_SLEEP)
continue;
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index df0773ebd9e4..dcc2a6ec23f0 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -47,6 +47,7 @@
* module_exit function is called.
*/
static u8 user_rmmod;
+static u8 sdio_ireg;
static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
.helper = "sd8688_helper.bin",
@@ -83,10 +84,10 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
*dat = 0;
fws0 = sdio_readb(card->func, CARD_FW_STATUS0_REG, &ret);
+ if (ret)
+ return -EIO;
- if (!ret)
- fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
-
+ fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
if (ret)
return -EIO;
@@ -216,7 +217,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
tmphlprbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
- tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL);
+ tmphlprbuf = kzalloc(tmphlprbufsz, GFP_KERNEL);
if (!tmphlprbuf) {
BT_ERR("Unable to allocate buffer for helper."
" Terminating download");
@@ -224,8 +225,6 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
goto done;
}
- memset(tmphlprbuf, 0, tmphlprbufsz);
-
helperbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, BTSDIO_DMA_ALIGN);
/* Perform helper data transfer */
@@ -318,7 +317,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
BT_DBG("Downloading FW image (%d bytes)", firmwarelen);
tmpfwbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
- tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL);
+ tmpfwbuf = kzalloc(tmpfwbufsz, GFP_KERNEL);
if (!tmpfwbuf) {
BT_ERR("Unable to allocate buffer for firmware."
" Terminating download");
@@ -326,8 +325,6 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
goto done;
}
- memset(tmpfwbuf, 0, tmpfwbufsz);
-
/* Ensure aligned firmware buffer */
fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, BTSDIO_DMA_ALIGN);
@@ -555,78 +552,79 @@ exit:
return ret;
}
-static int btmrvl_sdio_get_int_status(struct btmrvl_private *priv, u8 * ireg)
+static int btmrvl_sdio_process_int_status(struct btmrvl_private *priv)
{
- int ret;
- u8 sdio_ireg = 0;
+ ulong flags;
+ u8 ireg;
struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
- *ireg = 0;
-
- sdio_ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
- if (ret) {
- BT_ERR("sdio_readb: read int status register failed");
- ret = -EIO;
- goto done;
- }
-
- if (sdio_ireg != 0) {
- /*
- * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
- * Clear the interrupt status register and re-enable the
- * interrupt.
- */
- BT_DBG("sdio_ireg = 0x%x", sdio_ireg);
-
- sdio_writeb(card->func, ~(sdio_ireg) & (DN_LD_HOST_INT_STATUS |
- UP_LD_HOST_INT_STATUS),
- HOST_INTSTATUS_REG, &ret);
- if (ret) {
- BT_ERR("sdio_writeb: clear int status register "
- "failed");
- ret = -EIO;
- goto done;
- }
- }
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ ireg = sdio_ireg;
+ sdio_ireg = 0;
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
- if (sdio_ireg & DN_LD_HOST_INT_STATUS) {
+ sdio_claim_host(card->func);
+ if (ireg & DN_LD_HOST_INT_STATUS) {
if (priv->btmrvl_dev.tx_dnld_rdy)
BT_DBG("tx_done already received: "
- " int_status=0x%x", sdio_ireg);
+ " int_status=0x%x", ireg);
else
priv->btmrvl_dev.tx_dnld_rdy = true;
}
- if (sdio_ireg & UP_LD_HOST_INT_STATUS)
+ if (ireg & UP_LD_HOST_INT_STATUS)
btmrvl_sdio_card_to_host(priv);
- *ireg = sdio_ireg;
-
- ret = 0;
+ sdio_release_host(card->func);
-done:
- return ret;
+ return 0;
}
static void btmrvl_sdio_interrupt(struct sdio_func *func)
{
struct btmrvl_private *priv;
- struct hci_dev *hcidev;
struct btmrvl_sdio_card *card;
+ ulong flags;
u8 ireg = 0;
+ int ret;
card = sdio_get_drvdata(func);
- if (card && card->priv) {
- priv = card->priv;
- hcidev = priv->btmrvl_dev.hcidev;
+ if (!card || !card->priv) {
+ BT_ERR("sbi_interrupt(%p) card or priv is "
+ "NULL, card=%p\n", func, card);
+ return;
+ }
- if (btmrvl_sdio_get_int_status(priv, &ireg))
- BT_ERR("reading HOST_INT_STATUS_REG failed");
- else
- BT_DBG("HOST_INT_STATUS_REG %#x", ireg);
+ priv = card->priv;
+
+ ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
+ if (ret) {
+ BT_ERR("sdio_readb: read int status register failed");
+ return;
+ }
+
+ if (ireg != 0) {
+ /*
+ * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
+ * Clear the interrupt status register and re-enable the
+ * interrupt.
+ */
+ BT_DBG("ireg = 0x%x", ireg);
- btmrvl_interrupt(priv);
+ sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
+ UP_LD_HOST_INT_STATUS),
+ HOST_INTSTATUS_REG, &ret);
+ if (ret) {
+ BT_ERR("sdio_writeb: clear int status register failed");
+ return;
+ }
}
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ sdio_ireg |= ireg;
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+ btmrvl_interrupt(priv);
}
static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
@@ -930,6 +928,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
/* Initialize the interface specific function pointers */
priv->hw_host_to_card = btmrvl_sdio_host_to_card;
priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
+ priv->hw_process_int_status = btmrvl_sdio_process_int_status;
if (btmrvl_register_hdev(priv)) {
BT_ERR("Register hdev failed!");
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 5d9cc53bd643..d22ce3cc611e 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -59,6 +59,9 @@ static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
+ /* Apple iMac11,1 */
+ { USB_DEVICE(0x05ac, 0x8215) },
+
/* AVM BlueFRITZ! USB v2.0 */
{ USB_DEVICE(0x057c, 0x3800) },
@@ -146,6 +149,7 @@ static struct usb_device_id blacklist_table[] = {
#define BTUSB_BULK_RUNNING 1
#define BTUSB_ISOC_RUNNING 2
#define BTUSB_SUSPENDING 3
+#define BTUSB_DID_ISO_RESUME 4
struct btusb_data {
struct hci_dev *hdev;
@@ -179,7 +183,6 @@ struct btusb_data {
unsigned int sco_num;
int isoc_altsetting;
int suspend_count;
- int did_iso_resume:1;
};
static int inc_tx(struct btusb_data *data)
@@ -807,7 +810,7 @@ static void btusb_work(struct work_struct *work)
int err;
if (hdev->conn_hash.sco_num > 0) {
- if (!data->did_iso_resume) {
+ if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) {
err = usb_autopm_get_interface(data->isoc);
if (err < 0) {
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
@@ -815,7 +818,7 @@ static void btusb_work(struct work_struct *work)
return;
}
- data->did_iso_resume = 1;
+ set_bit(BTUSB_DID_ISO_RESUME, &data->flags);
}
if (data->isoc_altsetting != 2) {
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
@@ -836,10 +839,8 @@ static void btusb_work(struct work_struct *work)
usb_kill_anchored_urbs(&data->isoc_anchor);
__set_isoc_interface(hdev, 0);
- if (data->did_iso_resume) {
- data->did_iso_resume = 0;
+ if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags))
usb_autopm_put_interface(data->isoc);
- }
}
}
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index ef044d55cb25..cbe9e44a42e9 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -104,7 +104,7 @@ typedef struct {
u8 type;
u8 zero;
u16 len;
-} __attribute__ ((packed)) nsh_t; /* Nokia Specific Header */
+} __packed nsh_t; /* Nokia Specific Header */
#define NSHL 4 /* Nokia Specific Header Length */
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
new file mode 100644
index 000000000000..6a160c17ea94
--- /dev/null
+++ b/drivers/bluetooth/hci_ath.c
@@ -0,0 +1,235 @@
+/*
+ * Atheros Communication Bluetooth HCIATH3K UART protocol
+ *
+ * HCIATH3K (HCI Atheros AR300x Protocol) is a Atheros Communication's
+ * power management protocol extension to H4 to support AR300x Bluetooth Chip.
+ *
+ * Copyright (c) 2009-2010 Atheros Communications Inc.
+ *
+ * Acknowledgements:
+ * This file is based on hci_h4.c, which was written
+ * by Maxim Krasnyansky and Marcel Holtmann.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/errno.h>
+#include <linux/ioctl.h>
+#include <linux/skbuff.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#include "hci_uart.h"
+
+struct ath_struct {
+ struct hci_uart *hu;
+ unsigned int cur_sleep;
+
+ struct sk_buff_head txq;
+ struct work_struct ctxtsw;
+};
+
+static int ath_wakeup_ar3k(struct tty_struct *tty)
+{
+ struct termios settings;
+ int status = tty->driver->ops->tiocmget(tty, NULL);
+
+ if (status & TIOCM_CTS)
+ return status;
+
+ /* Disable Automatic RTSCTS */
+ n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings);
+ settings.c_cflag &= ~CRTSCTS;
+ n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings);
+
+ /* Clear RTS first */
+ status = tty->driver->ops->tiocmget(tty, NULL);
+ tty->driver->ops->tiocmset(tty, NULL, 0x00, TIOCM_RTS);
+ mdelay(20);
+
+ /* Set RTS, wake up board */
+ status = tty->driver->ops->tiocmget(tty, NULL);
+ tty->driver->ops->tiocmset(tty, NULL, TIOCM_RTS, 0x00);
+ mdelay(20);
+
+ status = tty->driver->ops->tiocmget(tty, NULL);
+
+ n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings);
+ settings.c_cflag |= CRTSCTS;
+ n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings);
+
+ return status;
+}
+
+static void ath_hci_uart_work(struct work_struct *work)
+{
+ int status;
+ struct ath_struct *ath;
+ struct hci_uart *hu;
+ struct tty_struct *tty;
+
+ ath = container_of(work, struct ath_struct, ctxtsw);
+
+ hu = ath->hu;
+ tty = hu->tty;
+
+ /* verify and wake up controller */
+ if (ath->cur_sleep) {
+ status = ath_wakeup_ar3k(tty);
+ if (!(status & TIOCM_CTS))
+ return;
+ }
+
+ /* Ready to send Data */
+ clear_bit(HCI_UART_SENDING, &hu->tx_state);
+ hci_uart_tx_wakeup(hu);
+}
+
+/* Initialize protocol */
+static int ath_open(struct hci_uart *hu)
+{
+ struct ath_struct *ath;
+
+ BT_DBG("hu %p", hu);
+
+ ath = kzalloc(sizeof(*ath), GFP_ATOMIC);
+ if (!ath)
+ return -ENOMEM;
+
+ skb_queue_head_init(&ath->txq);
+
+ hu->priv = ath;
+ ath->hu = hu;
+
+ INIT_WORK(&ath->ctxtsw, ath_hci_uart_work);
+
+ return 0;
+}
+
+/* Flush protocol data */
+static int ath_flush(struct hci_uart *hu)
+{
+ struct ath_struct *ath = hu->priv;
+
+ BT_DBG("hu %p", hu);
+
+ skb_queue_purge(&ath->txq);
+
+ return 0;
+}
+
+/* Close protocol */
+static int ath_close(struct hci_uart *hu)
+{
+ struct ath_struct *ath = hu->priv;
+
+ BT_DBG("hu %p", hu);
+
+ skb_queue_purge(&ath->txq);
+
+ cancel_work_sync(&ath->ctxtsw);
+
+ hu->priv = NULL;
+ kfree(ath);
+
+ return 0;
+}
+
+#define HCI_OP_ATH_SLEEP 0xFC04
+
+/* Enqueue frame for transmittion */
+static int ath_enqueue(struct hci_uart *hu, struct sk_buff *skb)
+{
+ struct ath_struct *ath = hu->priv;
+
+ if (bt_cb(skb)->pkt_type == HCI_SCODATA_PKT) {
+ kfree_skb(skb);
+ return 0;
+ }
+
+ /*
+ * Update power management enable flag with parameters of
+ * HCI sleep enable vendor specific HCI command.
+ */
+ if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
+ struct hci_command_hdr *hdr = (void *)skb->data;
+
+ if (__le16_to_cpu(hdr->opcode) == HCI_OP_ATH_SLEEP)
+ ath->cur_sleep = skb->data[HCI_COMMAND_HDR_SIZE];
+ }
+
+ BT_DBG("hu %p skb %p", hu, skb);
+
+ /* Prepend skb with frame type */
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+
+ skb_queue_tail(&ath->txq, skb);
+ set_bit(HCI_UART_SENDING, &hu->tx_state);
+
+ schedule_work(&ath->ctxtsw);
+
+ return 0;
+}
+
+static struct sk_buff *ath_dequeue(struct hci_uart *hu)
+{
+ struct ath_struct *ath = hu->priv;
+
+ return skb_dequeue(&ath->txq);
+}
+
+/* Recv data */
+static int ath_recv(struct hci_uart *hu, void *data, int count)
+{
+ if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
+ BT_ERR("Frame Reassembly Failed");
+
+ return count;
+}
+
+static struct hci_uart_proto athp = {
+ .id = HCI_UART_ATH3K,
+ .open = ath_open,
+ .close = ath_close,
+ .recv = ath_recv,
+ .enqueue = ath_enqueue,
+ .dequeue = ath_dequeue,
+ .flush = ath_flush,
+};
+
+int __init ath_init(void)
+{
+ int err = hci_uart_register_proto(&athp);
+
+ if (!err)
+ BT_INFO("HCIATH3K protocol initialized");
+ else
+ BT_ERR("HCIATH3K protocol registration failed");
+
+ return err;
+}
+
+int __exit ath_deinit(void)
+{
+ return hci_uart_unregister_proto(&athp);
+}
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 42d69d4de05c..9c5b2dc38e29 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -739,7 +739,7 @@ static struct hci_uart_proto bcsp = {
.flush = bcsp_flush
};
-int bcsp_init(void)
+int __init bcsp_init(void)
{
int err = hci_uart_register_proto(&bcsp);
@@ -751,7 +751,7 @@ int bcsp_init(void)
return err;
}
-int bcsp_deinit(void)
+int __exit bcsp_deinit(void)
{
return hci_uart_unregister_proto(&bcsp);
}
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index 3f038f5308a4..7b8ad93e2c36 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -151,107 +151,8 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
/* Recv data */
static int h4_recv(struct hci_uart *hu, void *data, int count)
{
- struct h4_struct *h4 = hu->priv;
- register char *ptr;
- struct hci_event_hdr *eh;
- struct hci_acl_hdr *ah;
- struct hci_sco_hdr *sh;
- register int len, type, dlen;
-
- BT_DBG("hu %p count %d rx_state %ld rx_count %ld",
- hu, count, h4->rx_state, h4->rx_count);
-
- ptr = data;
- while (count) {
- if (h4->rx_count) {
- len = min_t(unsigned int, h4->rx_count, count);
- memcpy(skb_put(h4->rx_skb, len), ptr, len);
- h4->rx_count -= len; count -= len; ptr += len;
-
- if (h4->rx_count)
- continue;
-
- switch (h4->rx_state) {
- case H4_W4_DATA:
- BT_DBG("Complete data");
-
- hci_recv_frame(h4->rx_skb);
-
- h4->rx_state = H4_W4_PACKET_TYPE;
- h4->rx_skb = NULL;
- continue;
-
- case H4_W4_EVENT_HDR:
- eh = hci_event_hdr(h4->rx_skb);
-
- BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);
-
- h4_check_data_len(h4, eh->plen);
- continue;
-
- case H4_W4_ACL_HDR:
- ah = hci_acl_hdr(h4->rx_skb);
- dlen = __le16_to_cpu(ah->dlen);
-
- BT_DBG("ACL header: dlen %d", dlen);
-
- h4_check_data_len(h4, dlen);
- continue;
-
- case H4_W4_SCO_HDR:
- sh = hci_sco_hdr(h4->rx_skb);
-
- BT_DBG("SCO header: dlen %d", sh->dlen);
-
- h4_check_data_len(h4, sh->dlen);
- continue;
- }
- }
-
- /* H4_W4_PACKET_TYPE */
- switch (*ptr) {
- case HCI_EVENT_PKT:
- BT_DBG("Event packet");
- h4->rx_state = H4_W4_EVENT_HDR;
- h4->rx_count = HCI_EVENT_HDR_SIZE;
- type = HCI_EVENT_PKT;
- break;
-
- case HCI_ACLDATA_PKT:
- BT_DBG("ACL packet");
- h4->rx_state = H4_W4_ACL_HDR;
- h4->rx_count = HCI_ACL_HDR_SIZE;
- type = HCI_ACLDATA_PKT;
- break;
-
- case HCI_SCODATA_PKT:
- BT_DBG("SCO packet");
- h4->rx_state = H4_W4_SCO_HDR;
- h4->rx_count = HCI_SCO_HDR_SIZE;
- type = HCI_SCODATA_PKT;
- break;
-
- default:
- BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
- hu->hdev->stat.err_rx++;
- ptr++; count--;
- continue;
- };
-
- ptr++; count--;
-
- /* Allocate packet */
- h4->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
- if (!h4->rx_skb) {
- BT_ERR("Can't allocate mem for new packet");
- h4->rx_state = H4_W4_PACKET_TYPE;
- h4->rx_count = 0;
- return -ENOMEM;
- }
-
- h4->rx_skb->dev = (void *) hu->hdev;
- bt_cb(h4->rx_skb)->pkt_type = type;
- }
+ if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
+ BT_ERR("Frame Reassembly Failed");
return count;
}
@@ -272,7 +173,7 @@ static struct hci_uart_proto h4p = {
.flush = h4_flush,
};
-int h4_init(void)
+int __init h4_init(void)
{
int err = hci_uart_register_proto(&h4p);
@@ -284,7 +185,7 @@ int h4_init(void)
return err;
}
-int h4_deinit(void)
+int __exit h4_deinit(void)
{
return hci_uart_unregister_proto(&h4p);
}
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 76a1abb8f214..998833d93c13 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -210,7 +210,6 @@ static int hci_uart_close(struct hci_dev *hdev)
static int hci_uart_send_frame(struct sk_buff *skb)
{
struct hci_dev* hdev = (struct hci_dev *) skb->dev;
- struct tty_struct *tty;
struct hci_uart *hu;
if (!hdev) {
@@ -222,7 +221,6 @@ static int hci_uart_send_frame(struct sk_buff *skb)
return -EBUSY;
hu = (struct hci_uart *) hdev->driver_data;
- tty = hu->tty;
BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
@@ -397,6 +395,9 @@ static int hci_uart_register_dev(struct hci_uart *hu)
if (!reset)
set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
+ if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
+ set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
hci_free_dev(hdev);
@@ -477,6 +478,15 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
return hu->hdev->id;
return -EUNATCH;
+ case HCIUARTSETFLAGS:
+ if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
+ return -EBUSY;
+ hu->hdev_flags = arg;
+ break;
+
+ case HCIUARTGETFLAGS:
+ return hu->hdev_flags;
+
default:
err = n_tty_ioctl_helper(tty, file, cmd, arg);
break;
@@ -542,6 +552,9 @@ static int __init hci_uart_init(void)
#ifdef CONFIG_BT_HCIUART_LL
ll_init();
#endif
+#ifdef CONFIG_BT_HCIUART_ATH3K
+ ath_init();
+#endif
return 0;
}
@@ -559,6 +572,9 @@ static void __exit hci_uart_exit(void)
#ifdef CONFIG_BT_HCIUART_LL
ll_deinit();
#endif
+#ifdef CONFIG_BT_HCIUART_ATH3K
+ ath_deinit();
+#endif
/* Release tty registration of line discipline */
if ((err = tty_unregister_ldisc(N_HCI)))
diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c
index fb8445c7365e..38595e782d02 100644
--- a/drivers/bluetooth/hci_ll.c
+++ b/drivers/bluetooth/hci_ll.c
@@ -74,7 +74,7 @@ enum hcill_states_e {
struct hcill_cmd {
u8 cmd;
-} __attribute__((packed));
+} __packed;
struct ll_struct {
unsigned long rx_state;
@@ -517,7 +517,7 @@ static struct hci_uart_proto llp = {
.flush = ll_flush,
};
-int ll_init(void)
+int __init ll_init(void)
{
int err = hci_uart_register_proto(&llp);
@@ -529,7 +529,7 @@ int ll_init(void)
return err;
}
-int ll_deinit(void)
+int __exit ll_deinit(void)
{
return hci_uart_unregister_proto(&llp);
}
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index 50113db06b9f..99fb35239d1f 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -31,15 +31,20 @@
#define HCIUARTSETPROTO _IOW('U', 200, int)
#define HCIUARTGETPROTO _IOR('U', 201, int)
#define HCIUARTGETDEVICE _IOR('U', 202, int)
+#define HCIUARTSETFLAGS _IOW('U', 203, int)
+#define HCIUARTGETFLAGS _IOR('U', 204, int)
/* UART protocols */
-#define HCI_UART_MAX_PROTO 5
+#define HCI_UART_MAX_PROTO 6
#define HCI_UART_H4 0
#define HCI_UART_BCSP 1
#define HCI_UART_3WIRE 2
#define HCI_UART_H4DS 3
#define HCI_UART_LL 4
+#define HCI_UART_ATH3K 5
+
+#define HCI_UART_RAW_DEVICE 0
struct hci_uart;
@@ -57,6 +62,7 @@ struct hci_uart {
struct tty_struct *tty;
struct hci_dev *hdev;
unsigned long flags;
+ unsigned long hdev_flags;
struct hci_uart_proto *proto;
void *priv;
@@ -66,7 +72,7 @@ struct hci_uart {
spinlock_t rx_lock;
};
-/* HCI_UART flag bits */
+/* HCI_UART proto flag bits */
#define HCI_UART_PROTO_SET 0
/* TX states */
@@ -91,3 +97,8 @@ int bcsp_deinit(void);
int ll_init(void);
int ll_deinit(void);
#endif
+
+#ifdef CONFIG_BT_HCIUART_ATH3K
+int ath_init(void);
+int ath_deinit(void);
+#endif
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index bde2fa8bb639..a105087af963 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -373,8 +373,8 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev)
pktlen = status & RDES0_STATUS_FL;
if (pktlen > RX_PKT_SIZE) {
if (net_ratelimit())
- printk(KERN_DEBUG "%s: frame too long (%d)\n",
- wiphy_name(dev->wiphy), pktlen);
+ wiphy_debug(dev->wiphy, "frame too long (%d)\n",
+ pktlen);
pktlen = RX_PKT_SIZE;
}
@@ -454,10 +454,10 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev)
static irqreturn_t adm8211_interrupt(int irq, void *dev_id)
{
-#define ADM8211_INT(x) \
-do { \
- if (unlikely(stsr & ADM8211_STSR_ ## x)) \
- printk(KERN_DEBUG "%s: " #x "\n", wiphy_name(dev->wiphy)); \
+#define ADM8211_INT(x) \
+do { \
+ if (unlikely(stsr & ADM8211_STSR_ ## x)) \
+ wiphy_debug(dev->wiphy, "%s\n", #x); \
} while (0)
struct ieee80211_hw *dev = dev_id;
@@ -570,9 +570,9 @@ static int adm8211_write_bbp(struct ieee80211_hw *dev, u8 addr, u8 data)
}
if (timeout == 0) {
- printk(KERN_DEBUG "%s: adm8211_write_bbp(%d,%d) failed"
- " prewrite (reg=0x%08x)\n",
- wiphy_name(dev->wiphy), addr, data, reg);
+ wiphy_debug(dev->wiphy,
+ "adm8211_write_bbp(%d,%d) failed prewrite (reg=0x%08x)\n",
+ addr, data, reg);
return -ETIMEDOUT;
}
@@ -605,9 +605,9 @@ static int adm8211_write_bbp(struct ieee80211_hw *dev, u8 addr, u8 data)
if (timeout == 0) {
ADM8211_CSR_WRITE(BBPCTL, ADM8211_CSR_READ(BBPCTL) &
~ADM8211_BBPCTL_WR);
- printk(KERN_DEBUG "%s: adm8211_write_bbp(%d,%d) failed"
- " postwrite (reg=0x%08x)\n",
- wiphy_name(dev->wiphy), addr, data, reg);
+ wiphy_debug(dev->wiphy,
+ "adm8211_write_bbp(%d,%d) failed postwrite (reg=0x%08x)\n",
+ addr, data, reg);
return -ETIMEDOUT;
}
@@ -675,8 +675,8 @@ static int adm8211_rf_set_channel(struct ieee80211_hw *dev, unsigned int chan)
break;
default:
- printk(KERN_DEBUG "%s: unsupported transceiver type %d\n",
- wiphy_name(dev->wiphy), priv->transceiver_type);
+ wiphy_debug(dev->wiphy, "unsupported transceiver type %d\n",
+ priv->transceiver_type);
break;
}
@@ -732,8 +732,8 @@ static int adm8211_rf_set_channel(struct ieee80211_hw *dev, unsigned int chan)
/* Nothing to do for ADMtek BBP */
} else if (priv->bbp_type != ADM8211_TYPE_ADMTEK)
- printk(KERN_DEBUG "%s: unsupported BBP type %d\n",
- wiphy_name(dev->wiphy), priv->bbp_type);
+ wiphy_debug(dev->wiphy, "unsupported bbp type %d\n",
+ priv->bbp_type);
ADM8211_RESTORE();
@@ -1027,13 +1027,12 @@ static int adm8211_hw_init_bbp(struct ieee80211_hw *dev)
break;
default:
- printk(KERN_DEBUG "%s: unsupported transceiver %d\n",
- wiphy_name(dev->wiphy), priv->transceiver_type);
+ wiphy_debug(dev->wiphy, "unsupported transceiver %d\n",
+ priv->transceiver_type);
break;
}
} else
- printk(KERN_DEBUG "%s: unsupported BBP %d\n",
- wiphy_name(dev->wiphy), priv->bbp_type);
+ wiphy_debug(dev->wiphy, "unsupported bbp %d\n", priv->bbp_type);
ADM8211_CSR_WRITE(SYNRF, 0);
@@ -1509,15 +1508,13 @@ static int adm8211_start(struct ieee80211_hw *dev)
/* Power up MAC and RF chips */
retval = adm8211_hw_reset(dev);
if (retval) {
- printk(KERN_ERR "%s: hardware reset failed\n",
- wiphy_name(dev->wiphy));
+ wiphy_err(dev->wiphy, "hardware reset failed\n");
goto fail;
}
retval = adm8211_init_rings(dev);
if (retval) {
- printk(KERN_ERR "%s: failed to initialize rings\n",
- wiphy_name(dev->wiphy));
+ wiphy_err(dev->wiphy, "failed to initialize rings\n");
goto fail;
}
@@ -1528,8 +1525,7 @@ static int adm8211_start(struct ieee80211_hw *dev)
retval = request_irq(priv->pdev->irq, adm8211_interrupt,
IRQF_SHARED, "adm8211", dev);
if (retval) {
- printk(KERN_ERR "%s: failed to register IRQ handler\n",
- wiphy_name(dev->wiphy));
+ wiphy_err(dev->wiphy, "failed to register irq handler\n");
goto fail;
}
@@ -1906,9 +1902,8 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
goto err_free_eeprom;
}
- printk(KERN_INFO "%s: hwaddr %pM, Rev 0x%02x\n",
- wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
- pdev->revision);
+ wiphy_info(dev->wiphy, "hwaddr %pm, rev 0x%02x\n",
+ dev->wiphy->perm_addr, pdev->revision);
return 0;
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index cd8caeab86ea..d5140a87f073 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -89,22 +89,19 @@
#define DBG_DEFAULTS 0
/* Use our own dbg macro */
-#define at76_dbg(bits, format, arg...) \
- do { \
- if (at76_debug & (bits)) \
- printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , \
- ## arg); \
- } while (0)
-
-#define at76_dbg_dump(bits, buf, len, format, arg...) \
- do { \
- if (at76_debug & (bits)) { \
- printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , \
- ## arg); \
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, \
- buf, len); \
- } \
- } while (0)
+#define at76_dbg(bits, format, arg...) \
+do { \
+ if (at76_debug & (bits)) \
+ printk(KERN_DEBUG DRIVER_NAME ": " format "\n", ##arg); \
+} while (0)
+
+#define at76_dbg_dump(bits, buf, len, format, arg...) \
+do { \
+ if (at76_debug & (bits)) { \
+ printk(KERN_DEBUG DRIVER_NAME ": " format "\n", ##arg); \
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); \
+ } \
+} while (0)
static uint at76_debug = DBG_DEFAULTS;
@@ -658,8 +655,8 @@ static int at76_get_hw_config(struct at76_priv *priv)
exit:
kfree(hwcfg);
if (ret < 0)
- printk(KERN_ERR "%s: cannot get HW Config (error %d)\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy, "cannot get hw config (error %d)\n",
+ ret);
return ret;
}
@@ -794,8 +791,9 @@ static int at76_wait_completion(struct at76_priv *priv, int cmd)
do {
status = at76_get_cmd_status(priv->udev, cmd);
if (status < 0) {
- printk(KERN_ERR "%s: at76_get_cmd_status failed: %d\n",
- wiphy_name(priv->hw->wiphy), status);
+ wiphy_err(priv->hw->wiphy,
+ "at76_get_cmd_status failed: %d\n",
+ status);
break;
}
@@ -810,9 +808,8 @@ static int at76_wait_completion(struct at76_priv *priv, int cmd)
schedule_timeout_interruptible(HZ / 10); /* 100 ms */
if (time_after(jiffies, timeout)) {
- printk(KERN_ERR
- "%s: completion timeout for command %d\n",
- wiphy_name(priv->hw->wiphy), cmd);
+ wiphy_err(priv->hw->wiphy,
+ "completion timeout for command %d\n", cmd);
status = -ETIMEDOUT;
break;
}
@@ -833,9 +830,9 @@ static int at76_set_mib(struct at76_priv *priv, struct set_mib_buffer *buf)
ret = at76_wait_completion(priv, CMD_SET_MIB);
if (ret != CMD_STATUS_COMPLETE) {
- printk(KERN_INFO
- "%s: set_mib: at76_wait_completion failed "
- "with %d\n", wiphy_name(priv->hw->wiphy), ret);
+ wiphy_info(priv->hw->wiphy,
+ "set_mib: at76_wait_completion failed with %d\n",
+ ret);
ret = -EIO;
}
@@ -855,8 +852,8 @@ static int at76_set_radio(struct at76_priv *priv, int enable)
ret = at76_set_card_command(priv->udev, cmd, NULL, 0);
if (ret < 0)
- printk(KERN_ERR "%s: at76_set_card_command(%d) failed: %d\n",
- wiphy_name(priv->hw->wiphy), cmd, ret);
+ wiphy_err(priv->hw->wiphy,
+ "at76_set_card_command(%d) failed: %d\n", cmd, ret);
else
ret = 1;
@@ -876,8 +873,8 @@ static int at76_set_pm_mode(struct at76_priv *priv)
ret = at76_set_mib(priv, &priv->mib_buf);
if (ret < 0)
- printk(KERN_ERR "%s: set_mib (pm_mode) failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy, "set_mib (pm_mode) failed: %d\n",
+ ret);
return ret;
}
@@ -893,8 +890,8 @@ static int at76_set_preamble(struct at76_priv *priv, u8 type)
ret = at76_set_mib(priv, &priv->mib_buf);
if (ret < 0)
- printk(KERN_ERR "%s: set_mib (preamble) failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy, "set_mib (preamble) failed: %d\n",
+ ret);
return ret;
}
@@ -910,8 +907,8 @@ static int at76_set_frag(struct at76_priv *priv, u16 size)
ret = at76_set_mib(priv, &priv->mib_buf);
if (ret < 0)
- printk(KERN_ERR "%s: set_mib (frag threshold) failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy,
+ "set_mib (frag threshold) failed: %d\n", ret);
return ret;
}
@@ -927,8 +924,7 @@ static int at76_set_rts(struct at76_priv *priv, u16 size)
ret = at76_set_mib(priv, &priv->mib_buf);
if (ret < 0)
- printk(KERN_ERR "%s: set_mib (rts) failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy, "set_mib (rts) failed: %d\n", ret);
return ret;
}
@@ -944,8 +940,8 @@ static int at76_set_autorate_fallback(struct at76_priv *priv, int onoff)
ret = at76_set_mib(priv, &priv->mib_buf);
if (ret < 0)
- printk(KERN_ERR "%s: set_mib (autorate fallback) failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy,
+ "set_mib (autorate fallback) failed: %d\n", ret);
return ret;
}
@@ -963,8 +959,8 @@ static void at76_dump_mib_mac_addr(struct at76_priv *priv)
ret = at76_get_mib(priv->udev, MIB_MAC_ADDR, m,
sizeof(struct mib_mac_addr));
if (ret < 0) {
- printk(KERN_ERR "%s: at76_get_mib (MAC_ADDR) failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy,
+ "at76_get_mib (mac_addr) failed: %d\n", ret);
goto exit;
}
@@ -992,8 +988,8 @@ static void at76_dump_mib_mac_wep(struct at76_priv *priv)
ret = at76_get_mib(priv->udev, MIB_MAC_WEP, m,
sizeof(struct mib_mac_wep));
if (ret < 0) {
- printk(KERN_ERR "%s: at76_get_mib (MAC_WEP) failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy,
+ "at76_get_mib (mac_wep) failed: %d\n", ret);
goto exit;
}
@@ -1029,8 +1025,8 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
ret = at76_get_mib(priv->udev, MIB_MAC_MGMT, m,
sizeof(struct mib_mac_mgmt));
if (ret < 0) {
- printk(KERN_ERR "%s: at76_get_mib (MAC_MGMT) failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy,
+ "at76_get_mib (mac_mgmt) failed: %d\n", ret);
goto exit;
}
@@ -1065,8 +1061,8 @@ static void at76_dump_mib_mac(struct at76_priv *priv)
ret = at76_get_mib(priv->udev, MIB_MAC, m, sizeof(struct mib_mac));
if (ret < 0) {
- printk(KERN_ERR "%s: at76_get_mib (MAC) failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy,
+ "at76_get_mib (mac) failed: %d\n", ret);
goto exit;
}
@@ -1102,8 +1098,8 @@ static void at76_dump_mib_phy(struct at76_priv *priv)
ret = at76_get_mib(priv->udev, MIB_PHY, m, sizeof(struct mib_phy));
if (ret < 0) {
- printk(KERN_ERR "%s: at76_get_mib (PHY) failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy,
+ "at76_get_mib (phy) failed: %d\n", ret);
goto exit;
}
@@ -1135,8 +1131,8 @@ static void at76_dump_mib_local(struct at76_priv *priv)
ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local));
if (ret < 0) {
- printk(KERN_ERR "%s: at76_get_mib (LOCAL) failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy,
+ "at76_get_mib (local) failed: %d\n", ret);
goto exit;
}
@@ -1161,8 +1157,8 @@ static void at76_dump_mib_mdomain(struct at76_priv *priv)
ret = at76_get_mib(priv->udev, MIB_MDOMAIN, m,
sizeof(struct mib_mdomain));
if (ret < 0) {
- printk(KERN_ERR "%s: at76_get_mib (MDOMAIN) failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy,
+ "at76_get_mib (mdomain) failed: %d\n", ret);
goto exit;
}
@@ -1233,16 +1229,16 @@ static int at76_submit_rx_urb(struct at76_priv *priv)
struct sk_buff *skb = priv->rx_skb;
if (!priv->rx_urb) {
- printk(KERN_ERR "%s: %s: priv->rx_urb is NULL\n",
- wiphy_name(priv->hw->wiphy), __func__);
+ wiphy_err(priv->hw->wiphy, "%s: priv->rx_urb is null\n",
+ __func__);
return -EFAULT;
}
if (!skb) {
skb = dev_alloc_skb(sizeof(struct at76_rx_buffer));
if (!skb) {
- printk(KERN_ERR "%s: cannot allocate rx skbuff\n",
- wiphy_name(priv->hw->wiphy));
+ wiphy_err(priv->hw->wiphy,
+ "cannot allocate rx skbuff\n");
ret = -ENOMEM;
goto exit;
}
@@ -1261,15 +1257,14 @@ static int at76_submit_rx_urb(struct at76_priv *priv)
at76_dbg(DBG_DEVSTART,
"usb_submit_urb returned -ENODEV");
else
- printk(KERN_ERR "%s: rx, usb_submit_urb failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy,
+ "rx, usb_submit_urb failed: %d\n", ret);
}
exit:
if (ret < 0 && ret != -ENODEV)
- printk(KERN_ERR "%s: cannot submit rx urb - please unload the "
- "driver and/or power cycle the device\n",
- wiphy_name(priv->hw->wiphy));
+ wiphy_err(priv->hw->wiphy,
+ "cannot submit rx urb - please unload the driver and/or power cycle the device\n");
return ret;
}
@@ -1438,8 +1433,8 @@ static int at76_startup_device(struct at76_priv *priv)
ret = at76_set_card_command(priv->udev, CMD_STARTUP, &priv->card_config,
sizeof(struct at76_card_config));
if (ret < 0) {
- printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy, "at76_set_card_command failed: %d\n",
+ ret);
return ret;
}
@@ -1504,8 +1499,8 @@ static void at76_work_set_promisc(struct work_struct *work)
ret = at76_set_mib(priv, &priv->mib_buf);
if (ret < 0)
- printk(KERN_ERR "%s: set_mib (promiscuous_mode) failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy,
+ "set_mib (promiscuous_mode) failed: %d\n", ret);
mutex_unlock(&priv->mtx);
}
@@ -1668,16 +1663,16 @@ static int at76_join(struct at76_priv *priv)
sizeof(struct at76_req_join));
if (ret < 0) {
- printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy, "at76_set_card_command failed: %d\n",
+ ret);
return 0;
}
ret = at76_wait_completion(priv, CMD_JOIN);
at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret);
if (ret != CMD_STATUS_COMPLETE) {
- printk(KERN_ERR "%s: at76_wait_completion failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy, "at76_wait_completion failed: %d\n",
+ ret);
return 0;
}
@@ -1745,8 +1740,8 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
at76_dbg(DBG_MAC80211, "%s()", __func__);
if (priv->tx_urb->status == -EINPROGRESS) {
- printk(KERN_ERR "%s: %s called while tx urb is pending\n",
- wiphy_name(priv->hw->wiphy), __func__);
+ wiphy_err(priv->hw->wiphy,
+ "%s called while tx urb is pending\n", __func__);
return NETDEV_TX_BUSY;
}
@@ -1794,13 +1789,12 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
submit_len, at76_mac80211_tx_callback, priv);
ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC);
if (ret) {
- printk(KERN_ERR "%s: error in tx submit urb: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy, "error in tx submit urb: %d\n", ret);
if (ret == -EINVAL)
- printk(KERN_ERR
- "%s: -EINVAL: tx urb %p hcpriv %p complete %p\n",
- wiphy_name(priv->hw->wiphy), priv->tx_urb,
- priv->tx_urb->hcpriv, priv->tx_urb->complete);
+ wiphy_err(priv->hw->wiphy,
+ "-einval: tx urb %p hcpriv %p complete %p\n",
+ priv->tx_urb,
+ priv->tx_urb->hcpriv, priv->tx_urb->complete);
}
return 0;
@@ -1817,8 +1811,8 @@ static int at76_mac80211_start(struct ieee80211_hw *hw)
ret = at76_submit_rx_urb(priv);
if (ret < 0) {
- printk(KERN_ERR "%s: open: submit_rx_urb failed: %d\n",
- wiphy_name(priv->hw->wiphy), ret);
+ wiphy_err(priv->hw->wiphy, "open: submit_rx_urb failed: %d\n",
+ ret);
goto error;
}
@@ -2316,14 +2310,12 @@ static int at76_init_new_device(struct at76_priv *priv,
priv->mac80211_registered = 1;
- printk(KERN_INFO "%s: USB %s, MAC %pM, firmware %d.%d.%d-%d\n",
- wiphy_name(priv->hw->wiphy),
- dev_name(&interface->dev), priv->mac_addr,
- priv->fw_version.major, priv->fw_version.minor,
- priv->fw_version.patch, priv->fw_version.build);
- printk(KERN_INFO "%s: regulatory domain 0x%02x: %s\n",
- wiphy_name(priv->hw->wiphy),
- priv->regulatory_domain, priv->domain->name);
+ wiphy_info(priv->hw->wiphy, "usb %s, mac %pm, firmware %d.%d.%d-%d\n",
+ dev_name(&interface->dev), priv->mac_addr,
+ priv->fw_version.major, priv->fw_version.minor,
+ priv->fw_version.patch, priv->fw_version.build);
+ wiphy_info(priv->hw->wiphy, "regulatory domain 0x%02x: %s\n",
+ priv->regulatory_domain, priv->domain->name);
exit:
return ret;
@@ -2485,7 +2477,7 @@ static void at76_disconnect(struct usb_interface *interface)
if (!priv)
return;
- printk(KERN_INFO "%s: disconnecting\n", wiphy_name(priv->hw->wiphy));
+ wiphy_info(priv->hw->wiphy, "disconnecting\n");
at76_delete_device(priv);
dev_printk(KERN_INFO, &interface->dev, "disconnected\n");
}
diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c
index cf6f5c4174a6..4604de09a8b2 100644
--- a/drivers/net/wireless/ath/ar9170/cmd.c
+++ b/drivers/net/wireless/ath/ar9170/cmd.c
@@ -48,8 +48,7 @@ int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len)
err = ar->exec_cmd(ar, AR9170_CMD_WMEM, len, (u8 *) data, 0, NULL);
if (err)
- printk(KERN_DEBUG "%s: writing memory failed\n",
- wiphy_name(ar->hw->wiphy));
+ wiphy_debug(ar->hw->wiphy, "writing memory failed\n");
return err;
}
@@ -67,8 +66,8 @@ int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)
err = ar->exec_cmd(ar, AR9170_CMD_WREG, sizeof(buf),
(u8 *) buf, 0, NULL);
if (err)
- printk(KERN_DEBUG "%s: writing reg %#x (val %#x) failed\n",
- wiphy_name(ar->hw->wiphy), reg, val);
+ wiphy_debug(ar->hw->wiphy, "writing reg %#x (val %#x) failed\n",
+ reg, val);
return err;
}
diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c
index 86c4e79f6bc8..832d90087f8a 100644
--- a/drivers/net/wireless/ath/ar9170/led.c
+++ b/drivers/net/wireless/ath/ar9170/led.c
@@ -133,8 +133,8 @@ static int ar9170_register_led(struct ar9170 *ar, int i, char *name,
err = led_classdev_register(wiphy_dev(ar->hw->wiphy),
&ar->leds[i].l);
if (err)
- printk(KERN_ERR "%s: failed to register %s LED (%d).\n",
- wiphy_name(ar->hw->wiphy), ar->leds[i].name, err);
+ wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n",
+ ar->leds[i].name, err);
else
ar->leds[i].registered = true;
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index 2abc87578994..c67b05f3bcbd 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -198,12 +198,13 @@ static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb)
struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
struct ieee80211_hdr *hdr = (void *) txc->frame_data;
- printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] s:%d "
- "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n",
- wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb),
- ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr),
- le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control),
- jiffies_to_msecs(arinfo->timeout - jiffies));
+ wiphy_debug(ar->hw->wiphy,
+ "=> FRAME [skb:%p, q:%d, DA:[%pM] s:%d "
+ "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n",
+ skb, skb_get_queue_mapping(skb),
+ ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr),
+ le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control),
+ jiffies_to_msecs(arinfo->timeout - jiffies));
}
static void __ar9170_dump_txqueue(struct ar9170 *ar,
@@ -213,8 +214,8 @@ static void __ar9170_dump_txqueue(struct ar9170 *ar,
int i = 0;
printk(KERN_DEBUG "---[ cut here ]---\n");
- printk(KERN_DEBUG "%s: %d entries in queue.\n",
- wiphy_name(ar->hw->wiphy), skb_queue_len(queue));
+ wiphy_debug(ar->hw->wiphy, "%d entries in queue.\n",
+ skb_queue_len(queue));
skb_queue_walk(queue, skb) {
printk(KERN_DEBUG "index:%d =>\n", i++);
@@ -244,15 +245,14 @@ static void __ar9170_dump_txstats(struct ar9170 *ar)
{
int i;
- printk(KERN_DEBUG "%s: QoS queue stats\n",
- wiphy_name(ar->hw->wiphy));
+ wiphy_debug(ar->hw->wiphy, "qos queue stats\n");
for (i = 0; i < __AR9170_NUM_TXQ; i++)
- printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d "
- " stopped:%d\n", wiphy_name(ar->hw->wiphy), i,
- ar->tx_stats[i].limit, ar->tx_stats[i].len,
- skb_queue_len(&ar->tx_status[i]),
- ieee80211_queue_stopped(ar->hw, i));
+ wiphy_debug(ar->hw->wiphy,
+ "queue:%d limit:%d len:%d waitack:%d stopped:%d\n",
+ i, ar->tx_stats[i].limit, ar->tx_stats[i].len,
+ skb_queue_len(&ar->tx_status[i]),
+ ieee80211_queue_stopped(ar->hw, i));
}
#endif /* AR9170_QUEUE_STOP_DEBUG */
@@ -274,9 +274,9 @@ static void ar9170_recycle_expired(struct ar9170 *ar,
if (time_is_before_jiffies(arinfo->timeout)) {
#ifdef AR9170_QUEUE_DEBUG
- printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => "
- "recycle\n", wiphy_name(ar->hw->wiphy),
- jiffies, arinfo->timeout);
+ wiphy_debug(ar->hw->wiphy,
+ "[%ld > %ld] frame expired => recycle\n",
+ jiffies, arinfo->timeout);
ar9170_print_txheader(ar, skb);
#endif /* AR9170_QUEUE_DEBUG */
__skb_unlink(skb, queue);
@@ -317,8 +317,8 @@ static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
break;
default:
- printk(KERN_ERR "%s: invalid tx_status response (%x).\n",
- wiphy_name(ar->hw->wiphy), tx_status);
+ wiphy_err(ar->hw->wiphy,
+ "invalid tx_status response (%x)\n", tx_status);
break;
}
@@ -339,8 +339,7 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb)
if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) {
#ifdef AR9170_QUEUE_STOP_DEBUG
- printk(KERN_DEBUG "%s: wake queue %d\n",
- wiphy_name(ar->hw->wiphy), queue);
+ wiphy_debug(ar->hw->wiphy, "wake queue %d\n", queue);
__ar9170_dump_txstats(ar);
#endif /* AR9170_QUEUE_STOP_DEBUG */
ieee80211_wake_queue(ar->hw, queue);
@@ -387,9 +386,9 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar,
if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) {
#ifdef AR9170_QUEUE_DEBUG
- printk(KERN_DEBUG "%s: skip frame => DA %pM != %pM\n",
- wiphy_name(ar->hw->wiphy), mac,
- ieee80211_get_DA(hdr));
+ wiphy_debug(ar->hw->wiphy,
+ "skip frame => da %pm != %pm\n",
+ mac, ieee80211_get_DA(hdr));
ar9170_print_txheader(ar, skb);
#endif /* AR9170_QUEUE_DEBUG */
continue;
@@ -400,8 +399,8 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar,
if ((rate != AR9170_TX_INVALID_RATE) && (r != rate)) {
#ifdef AR9170_QUEUE_DEBUG
- printk(KERN_DEBUG "%s: skip frame => rate %d != %d\n",
- wiphy_name(ar->hw->wiphy), rate, r);
+ wiphy_debug(ar->hw->wiphy,
+ "skip frame => rate %d != %d\n", rate, r);
ar9170_print_txheader(ar, skb);
#endif /* AR9170_QUEUE_DEBUG */
continue;
@@ -413,9 +412,9 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar,
}
#ifdef AR9170_QUEUE_DEBUG
- printk(KERN_ERR "%s: ESS:[%pM] does not have any "
- "outstanding frames in queue.\n",
- wiphy_name(ar->hw->wiphy), mac);
+ wiphy_err(ar->hw->wiphy,
+ "ESS:[%pM] does not have any outstanding frames in queue.\n",
+ mac);
__ar9170_dump_txqueue(ar, queue);
#endif /* AR9170_QUEUE_DEBUG */
spin_unlock_irqrestore(&queue->lock, flags);
@@ -444,8 +443,8 @@ static void ar9170_tx_janitor(struct work_struct *work)
for (i = 0; i < __AR9170_NUM_TXQ; i++) {
#ifdef AR9170_QUEUE_DEBUG
- printk(KERN_DEBUG "%s: garbage collector scans queue:%d\n",
- wiphy_name(ar->hw->wiphy), i);
+ wiphy_debug(ar->hw->wiphy, "garbage collector scans queue:%d\n",
+ i);
ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
ar9170_dump_txqueue(ar, &ar->tx_status[i]);
#endif /* AR9170_QUEUE_DEBUG */
@@ -495,8 +494,9 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
u32 q = (phy & AR9170_TX_PHY_QOS_MASK) >>
AR9170_TX_PHY_QOS_SHIFT;
#ifdef AR9170_QUEUE_DEBUG
- printk(KERN_DEBUG "%s: recv tx_status for %pM, p:%08x, q:%d\n",
- wiphy_name(ar->hw->wiphy), cmd->tx_status.dst, phy, q);
+ wiphy_debug(ar->hw->wiphy,
+ "recv tx_status for %pm, p:%08x, q:%d\n",
+ cmd->tx_status.dst, phy, q);
#endif /* AR9170_QUEUE_DEBUG */
skb = ar9170_get_queued_skb(ar, cmd->tx_status.dst,
@@ -582,7 +582,7 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
break;
default:
- printk(KERN_INFO "received unhandled event %x\n", cmd->type);
+ pr_info("received unhandled event %x\n", cmd->type);
print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len);
break;
}
@@ -675,9 +675,9 @@ static int ar9170_rx_mac_status(struct ar9170 *ar,
/* TODO: update netdevice's RX dropped/errors statistics */
if (ar9170_nag_limiter(ar))
- printk(KERN_DEBUG "%s: received frame with "
- "suspicious error code (%#x).\n",
- wiphy_name(ar->hw->wiphy), error);
+ wiphy_debug(ar->hw->wiphy,
+ "received frame with suspicious error code (%#x).\n",
+ error);
return -EINVAL;
}
@@ -704,9 +704,9 @@ static int ar9170_rx_mac_status(struct ar9170 *ar,
break;
default:
if (ar9170_nag_limiter(ar))
- printk(KERN_ERR "%s: invalid plcp cck rate "
- "(%x).\n", wiphy_name(ar->hw->wiphy),
- head->plcp[0]);
+ wiphy_err(ar->hw->wiphy,
+ "invalid plcp cck rate (%x).\n",
+ head->plcp[0]);
return -EINVAL;
}
break;
@@ -740,9 +740,9 @@ static int ar9170_rx_mac_status(struct ar9170 *ar,
break;
default:
if (ar9170_nag_limiter(ar))
- printk(KERN_ERR "%s: invalid plcp ofdm rate "
- "(%x).\n", wiphy_name(ar->hw->wiphy),
- head->plcp[0]);
+ wiphy_err(ar->hw->wiphy,
+ "invalid plcp ofdm rate (%x).\n",
+ head->plcp[0]);
return -EINVAL;
}
if (status->band == IEEE80211_BAND_2GHZ)
@@ -761,8 +761,7 @@ static int ar9170_rx_mac_status(struct ar9170 *ar,
default:
if (ar9170_nag_limiter(ar))
- printk(KERN_ERR "%s: invalid modulation\n",
- wiphy_name(ar->hw->wiphy));
+ wiphy_err(ar->hw->wiphy, "invalid modulation\n");
return -EINVAL;
}
@@ -863,8 +862,8 @@ static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
ar->rx_mpdu.has_plcp = true;
} else {
if (ar9170_nag_limiter(ar))
- printk(KERN_ERR "%s: plcp info is clipped.\n",
- wiphy_name(ar->hw->wiphy));
+ wiphy_err(ar->hw->wiphy,
+ "plcp info is clipped.\n");
return ;
}
break;
@@ -877,8 +876,8 @@ static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
phy = (void *)(buf + mpdu_len);
} else {
if (ar9170_nag_limiter(ar))
- printk(KERN_ERR "%s: frame tail is clipped.\n",
- wiphy_name(ar->hw->wiphy));
+ wiphy_err(ar->hw->wiphy,
+ "frame tail is clipped.\n");
return ;
}
@@ -888,9 +887,8 @@ static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
if (!ar9170_nag_limiter(ar))
return ;
- printk(KERN_ERR "%s: rx stream did not start "
- "with a first_mpdu frame tag.\n",
- wiphy_name(ar->hw->wiphy));
+ wiphy_err(ar->hw->wiphy,
+ "rx stream did not start with a first_mpdu frame tag.\n");
return ;
}
@@ -954,8 +952,8 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb)
if (!ar->rx_failover_missing) {
/* this is no "short read". */
if (ar9170_nag_limiter(ar)) {
- printk(KERN_ERR "%s: missing tag!\n",
- wiphy_name(ar->hw->wiphy));
+ wiphy_err(ar->hw->wiphy,
+ "missing tag!\n");
goto err_telluser;
} else
goto err_silent;
@@ -963,9 +961,8 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb)
if (ar->rx_failover_missing > tlen) {
if (ar9170_nag_limiter(ar)) {
- printk(KERN_ERR "%s: possible multi "
- "stream corruption!\n",
- wiphy_name(ar->hw->wiphy));
+ wiphy_err(ar->hw->wiphy,
+ "possible multi stream corruption!\n");
goto err_telluser;
} else
goto err_silent;
@@ -997,9 +994,8 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb)
if (ar->rx_failover_missing) {
/* TODO: handle double stream corruption. */
if (ar9170_nag_limiter(ar)) {
- printk(KERN_ERR "%s: double rx stream "
- "corruption!\n",
- wiphy_name(ar->hw->wiphy));
+ wiphy_err(ar->hw->wiphy,
+ "double rx stream corruption!\n");
goto err_telluser;
} else
goto err_silent;
@@ -1042,9 +1038,9 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb)
if (tlen) {
if (net_ratelimit())
- printk(KERN_ERR "%s: %d bytes of unprocessed "
- "data left in rx stream!\n",
- wiphy_name(ar->hw->wiphy), tlen);
+ wiphy_err(ar->hw->wiphy,
+ "%d bytes of unprocessed data left in rx stream!\n",
+ tlen);
goto err_telluser;
}
@@ -1052,10 +1048,9 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb)
return ;
err_telluser:
- printk(KERN_ERR "%s: damaged RX stream data [want:%d, "
- "data:%d, rx:%d, pending:%d ]\n",
- wiphy_name(ar->hw->wiphy), clen, wlen, tlen,
- ar->rx_failover_missing);
+ wiphy_err(ar->hw->wiphy,
+ "damaged RX stream data [want:%d, data:%d, rx:%d, pending:%d ]\n",
+ clen, wlen, tlen, ar->rx_failover_missing);
if (ar->rx_failover_missing)
print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET,
@@ -1065,9 +1060,8 @@ err_telluser:
print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET,
skb->data, skb->len);
- printk(KERN_ERR "%s: please check your hardware and cables, if "
- "you see this message frequently.\n",
- wiphy_name(ar->hw->wiphy));
+ wiphy_err(ar->hw->wiphy,
+ "If you see this message frequently, please check your hardware and cables.\n");
err_silent:
if (ar->rx_failover_missing) {
@@ -1384,10 +1378,10 @@ static void ar9170_tx(struct ar9170 *ar)
if (remaining_space < frames) {
#ifdef AR9170_QUEUE_DEBUG
- printk(KERN_DEBUG "%s: tx quota reached queue:%d, "
- "remaining slots:%d, needed:%d\n",
- wiphy_name(ar->hw->wiphy), i, remaining_space,
- frames);
+ wiphy_debug(ar->hw->wiphy,
+ "tx quota reached queue:%d, "
+ "remaining slots:%d, needed:%d\n",
+ i, remaining_space, frames);
#endif /* AR9170_QUEUE_DEBUG */
frames = remaining_space;
}
@@ -1396,18 +1390,14 @@ static void ar9170_tx(struct ar9170 *ar)
ar->tx_stats[i].count += frames;
if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) {
#ifdef AR9170_QUEUE_DEBUG
- printk(KERN_DEBUG "%s: queue %d full\n",
- wiphy_name(ar->hw->wiphy), i);
-
- printk(KERN_DEBUG "%s: stuck frames: ===>\n",
- wiphy_name(ar->hw->wiphy));
+ wiphy_debug(ar->hw->wiphy, "queue %d full\n", i);
+ wiphy_debug(ar->hw->wiphy, "stuck frames: ===>\n");
ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
ar9170_dump_txqueue(ar, &ar->tx_status[i]);
#endif /* AR9170_QUEUE_DEBUG */
#ifdef AR9170_QUEUE_STOP_DEBUG
- printk(KERN_DEBUG "%s: stop queue %d\n",
- wiphy_name(ar->hw->wiphy), i);
+ wiphy_debug(ar->hw->wiphy, "stop queue %d\n", i);
__ar9170_dump_txstats(ar);
#endif /* AR9170_QUEUE_STOP_DEBUG */
ieee80211_stop_queue(ar->hw, i);
@@ -1435,8 +1425,7 @@ static void ar9170_tx(struct ar9170 *ar)
msecs_to_jiffies(AR9170_TX_TIMEOUT);
#ifdef AR9170_QUEUE_DEBUG
- printk(KERN_DEBUG "%s: send frame q:%d =>\n",
- wiphy_name(ar->hw->wiphy), i);
+ wiphy_debug(ar->hw->wiphy, "send frame q:%d =>\n", i);
ar9170_print_txheader(ar, skb);
#endif /* AR9170_QUEUE_DEBUG */
@@ -1453,26 +1442,25 @@ static void ar9170_tx(struct ar9170 *ar)
}
#ifdef AR9170_QUEUE_DEBUG
- printk(KERN_DEBUG "%s: ar9170_tx report for queue %d\n",
- wiphy_name(ar->hw->wiphy), i);
+ wiphy_debug(ar->hw->wiphy,
+ "ar9170_tx report for queue %d\n", i);
- printk(KERN_DEBUG "%s: unprocessed pending frames left:\n",
- wiphy_name(ar->hw->wiphy));
+ wiphy_debug(ar->hw->wiphy,
+ "unprocessed pending frames left:\n");
ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
#endif /* AR9170_QUEUE_DEBUG */
if (unlikely(frames_failed)) {
#ifdef AR9170_QUEUE_DEBUG
- printk(KERN_DEBUG "%s: frames failed %d =>\n",
- wiphy_name(ar->hw->wiphy), frames_failed);
+ wiphy_debug(ar->hw->wiphy,
+ "frames failed %d =>\n", frames_failed);
#endif /* AR9170_QUEUE_DEBUG */
spin_lock_irqsave(&ar->tx_stats_lock, flags);
ar->tx_stats[i].len -= frames_failed;
ar->tx_stats[i].count -= frames_failed;
#ifdef AR9170_QUEUE_STOP_DEBUG
- printk(KERN_DEBUG "%s: wake queue %d\n",
- wiphy_name(ar->hw->wiphy), i);
+ wiphy_debug(ar->hw->wiphy, "wake queue %d\n", i);
__ar9170_dump_txstats(ar);
#endif /* AR9170_QUEUE_STOP_DEBUG */
ieee80211_wake_queue(ar->hw, i);
@@ -1917,6 +1905,24 @@ static int ar9170_get_stats(struct ieee80211_hw *hw,
return 0;
}
+static int ar9170_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey)
+{
+ struct ar9170 *ar = hw->priv;
+ struct ieee80211_conf *conf = &hw->conf;
+
+ if (idx != 0)
+ return -ENOENT;
+
+ /* TODO: update noise value, e.g. call ar9170_set_channel */
+
+ survey->channel = conf->channel;
+ survey->filled = SURVEY_INFO_NOISE_DBM;
+ survey->noise = ar->noise[0];
+
+ return 0;
+}
+
static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *param)
{
@@ -1969,6 +1975,7 @@ static const struct ieee80211_ops ar9170_ops = {
.get_tsf = ar9170_op_get_tsf,
.set_key = ar9170_set_key,
.get_stats = ar9170_get_stats,
+ .get_survey = ar9170_get_survey,
.ampdu_action = ar9170_ampdu_action,
};
diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c
index 45a415ea809a..0dbfcf79ac96 100644
--- a/drivers/net/wireless/ath/ar9170/phy.c
+++ b/drivers/net/wireless/ath/ar9170/phy.c
@@ -670,8 +670,7 @@ static int ar9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz)
ar9170_regwrite_finish();
err = ar9170_regwrite_result();
if (err)
- printk(KERN_ERR "%s: rf init failed\n",
- wiphy_name(ar->hw->wiphy));
+ wiphy_err(ar->hw->wiphy, "rf init failed\n");
return err;
}
@@ -1702,9 +1701,8 @@ int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
0x200 | ar->phy_heavy_clip);
if (err) {
if (ar9170_nag_limiter(ar))
- printk(KERN_ERR "%s: failed to set "
- "heavy clip\n",
- wiphy_name(ar->hw->wiphy));
+ wiphy_err(ar->hw->wiphy,
+ "failed to set heavy clip\n");
}
}
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index ebb9c237a0d5..4cccc29964f6 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -239,6 +239,9 @@ static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
"TSF\t\t0x%016llx\tTU: %08x\n",
(unsigned long long)tsf, TSF_TO_TU(tsf));
+ if (len > sizeof(buf))
+ len = sizeof(buf);
+
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -334,6 +337,9 @@ static ssize_t read_file_debug(struct file *file, char __user *user_buf,
sc->debug.level == dbg_info[i].level ? '+' : ' ',
dbg_info[i].level, dbg_info[i].desc);
+ if (len > sizeof(buf))
+ len = sizeof(buf);
+
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -433,6 +439,9 @@ static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
len += snprintf(buf+len, sizeof(buf)-len,
"AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v);
+ if (len > sizeof(buf))
+ len = sizeof(buf);
+
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -542,6 +551,9 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n",
st->tx_all_count);
+ if (len > sizeof(buf))
+ len = sizeof(buf);
+
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -681,6 +693,9 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf,
ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2)));
+ if (len > sizeof(buf))
+ len = sizeof(buf);
+
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -766,6 +781,9 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf,
len += snprintf(buf+len, sizeof(buf)-len, " len: %d\n", n);
}
+ if (len > sizeof(buf))
+ len = sizeof(buf);
+
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 85fdd26039c8..1a984b02e9e5 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -131,11 +131,8 @@ static int ath_ahb_probe(struct platform_device *pdev)
ah = sc->sc_ah;
ath9k_hw_name(ah, hw_name, sizeof(hw_name));
- printk(KERN_INFO
- "%s: %s mem=0x%lx, irq=%d\n",
- wiphy_name(hw->wiphy),
- hw_name,
- (unsigned long)mem, irq);
+ wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
+ hw_name, (unsigned long)mem, irq);
return 0;
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 4a910b78de52..3d2c8679bc85 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -1506,6 +1506,9 @@ static void ar5008_hw_do_getnf(struct ath_hw *ah,
nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR);
nfarray[2] = sign_extend(nf, 9);
+ if (!IS_CHAN_HT40(ah->curchan))
+ return;
+
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
nfarray[3] = sign_extend(nf, 9);
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
index 4922b8d4a938..adbf031fbc5a 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
@@ -477,7 +477,8 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah,
nfarray[0] = sign_extend(nf, 9);
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR);
- nfarray[3] = sign_extend(nf, 9);
+ if (IS_CHAN_HT40(ah->curchan))
+ nfarray[3] = sign_extend(nf, 9);
if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
return;
@@ -486,7 +487,8 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah,
nfarray[1] = sign_extend(nf, 9);
nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR);
- nfarray[4] = sign_extend(nf, 9);
+ if (IS_CHAN_HT40(ah->curchan))
+ nfarray[4] = sign_extend(nf, 9);
}
static void ar9002_hw_set_nf_limits(struct ath_hw *ah)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 7c93338540ae..a753a431bb13 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -1029,6 +1029,9 @@ static void ar9003_hw_do_getnf(struct ath_hw *ah,
nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR);
nfarray[2] = sign_extend(nf, 9);
+ if (!IS_CHAN_HT40(ah->curchan))
+ return;
+
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
nfarray[3] = sign_extend(nf, 9);
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 6e486a508edb..998ae2c49ed2 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -687,7 +687,7 @@ bool ath9k_all_wiphys_idle(struct ath_softc *sc);
void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle);
void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue);
-void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue);
+bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue);
void ath_start_rfkill_poll(struct ath_softc *sc);
extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 7f4c55f90e74..139289e4e933 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -172,26 +172,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
struct ath9k_nfcal_hist *h;
unsigned i, j;
int32_t val;
- u8 chainmask;
+ u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
struct ath_common *common = ath9k_hw_common(ah);
- if (AR_SREV_9300_20_OR_LATER(ah))
- chainmask = 0x3F;
- else if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
- chainmask = 0x9;
- else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) {
- if ((ah->rxchainmask & 0x2) || (ah->rxchainmask & 0x4))
- chainmask = 0x1B;
- else
- chainmask = 0x09;
- } else {
- if (ah->rxchainmask & 0x4)
- chainmask = 0x3F;
- else if (ah->rxchainmask & 0x2)
- chainmask = 0x1B;
- else
- chainmask = 0x09;
- }
h = ah->nfCalHist;
for (i = 0; i < NUM_NF_READINGS; i++) {
@@ -278,7 +261,7 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
ath_print(common, ATH_DBG_CALIBRATE,
"NF calibrated [%s] [chain %d] is %d\n",
- (i > 3 ? "ext" : "ctl"), i % 3, nf[i]);
+ (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
if (nf[i] > limit->max) {
ath_print(common, ATH_DBG_CALIBRATE,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 32438771ca2b..cf9bcc67ade2 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -524,6 +524,9 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
len += snprintf(buf + len, sizeof(buf) - len,
"%19s : %10u\n", "TX Rate", priv->debug.txrate);
+ if (len > sizeof(buf))
+ len = sizeof(buf);
+
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -569,6 +572,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
"%20s : %10u\n", "VO queued",
priv->debug.tx_stats.queue_stats[WME_AC_VO]);
+ if (len > sizeof(buf))
+ len = sizeof(buf);
+
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -595,6 +601,9 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
"%20s : %10u\n", "SKBs Dropped",
priv->debug.rx_stats.skb_dropped);
+ if (len > sizeof(buf))
+ len = sizeof(buf);
+
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 2f83f975b891..8d291ccf5c88 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -532,7 +532,8 @@ static int __ath9k_hw_init(struct ath_hw *ah)
if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
- (AR_SREV_9280(ah) && !ah->is_pciexpress)) {
+ ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) &&
+ !ah->is_pciexpress)) {
ah->config.serialize_regmode =
SER_REG_MODE_ON;
} else {
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 6cf0410ae0ba..0429dda0961f 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1994,11 +1994,12 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
mutex_lock(&sc->mutex);
if (ath9k_wiphy_scanning(sc)) {
- printk(KERN_DEBUG "ath9k: Two wiphys trying to scan at the "
- "same time\n");
/*
- * Do not allow the concurrent scanning state for now. This
- * could be improved with scanning control moved into ath9k.
+ * There is a race here in mac80211 but fixing it requires
+ * we revisit how we handle the scan complete callback.
+ * After mac80211 fixes we will not have configured hardware
+ * to the home channel nor would we have configured the RX
+ * filter yet.
*/
mutex_unlock(&sc->mutex);
return;
@@ -2014,6 +2015,10 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
mutex_unlock(&sc->mutex);
}
+/*
+ * XXX: this requires a revisit after the driver
+ * scan_complete gets moved to another place/removed in mac80211.
+ */
static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
{
struct ath_wiphy *aphy = hw->priv;
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 257b10ba6f57..b5b651413e77 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -209,11 +209,8 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
- printk(KERN_INFO
- "%s: %s mem=0x%lx, irq=%d\n",
- wiphy_name(hw->wiphy),
- hw_name,
- (unsigned long)mem, pdev->irq);
+ wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
+ hw_name, (unsigned long)mem, pdev->irq);
return 0;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 600ee0ba2880..e49be733d546 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -20,95 +20,145 @@
#include "ath9k.h"
static const struct ath_rate_table ar5416_11na_ratetable = {
- 43,
+ 68,
8, /* MCS start */
{
- { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
- 5400, 0, 12, 0, 0, 0, 0, 0 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
- 7800, 1, 18, 0, 1, 1, 1, 1 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
- 10000, 2, 24, 2, 2, 2, 2, 2 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
- 13900, 3, 36, 2, 3, 3, 3, 3 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
- 17300, 4, 48, 4, 4, 4, 4, 4 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
- 23000, 5, 72, 4, 5, 5, 5, 5 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
- 27400, 6, 96, 4, 6, 6, 6, 6 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
- 29300, 7, 108, 4, 7, 7, 7, 7 },
- { VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
- 6400, 0, 0, 0, 8, 25, 8, 25 },
- { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
- 12700, 1, 1, 2, 9, 26, 9, 26 },
- { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
- 18800, 2, 2, 2, 10, 27, 10, 27 },
- { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
- 25000, 3, 3, 4, 11, 28, 11, 28 },
- { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
- 36700, 4, 4, 4, 12, 29, 12, 29 },
- { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
- 48100, 5, 5, 4, 13, 30, 13, 30 },
- { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
- 53500, 6, 6, 4, 14, 31, 14, 31 },
- { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
- 59000, 7, 7, 4, 15, 32, 15, 33 },
- { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
- 12700, 8, 8, 3, 16, 34, 16, 34 },
- { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
- 24800, 9, 9, 2, 17, 35, 17, 35 },
- { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
- 36600, 10, 10, 2, 18, 36, 18, 36 },
- { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
- 48100, 11, 11, 4, 19, 37, 19, 37 },
- { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
- 69500, 12, 12, 4, 20, 38, 20, 38 },
- { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
- 89500, 13, 13, 4, 21, 39, 21, 39 },
- { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
- 98900, 14, 14, 4, 22, 40, 22, 40 },
- { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
- 108300, 15, 15, 4, 23, 41, 24, 42 },
- { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS_HGI, 144400, /* 144.4 Mb */
- 12000, 15, 15, 4, 23, 41, 24, 42 },
- { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
- 13200, 0, 0, 0, 8, 25, 25, 25 },
- { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
- 25900, 1, 1, 2, 9, 26, 26, 26 },
- { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
- 38600, 2, 2, 2, 10, 27, 27, 27 },
- { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
- 49800, 3, 3, 4, 11, 28, 28, 28 },
- { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
- 72200, 4, 4, 4, 12, 29, 29, 29 },
- { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
- 92900, 5, 5, 4, 13, 30, 30, 30 },
- { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
- 102700, 6, 6, 4, 14, 31, 31, 31 },
- { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
- 112000, 7, 7, 4, 15, 32, 33, 33 },
- { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
- 122000, 7, 7, 4, 15, 32, 33, 33 },
- { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
- 25800, 8, 8, 0, 16, 34, 34, 34 },
- { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
- 49800, 9, 9, 2, 17, 35, 35, 35 },
- { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
- 71900, 10, 10, 2, 18, 36, 36, 36 },
- { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
- 92500, 11, 11, 4, 19, 37, 37, 37 },
- { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
- 130300, 12, 12, 4, 20, 38, 38, 38 },
- { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
- 162800, 13, 13, 4, 21, 39, 39, 39 },
- { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
- 178200, 14, 14, 4, 22, 40, 40, 40 },
- { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
- 192100, 15, 15, 4, 23, 41, 42, 42 },
- { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
- 207000, 15, 15, 4, 23, 41, 42, 42 },
+ [0] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000,
+ 5400, 0, 12, 0, 0, 0, 0 }, /* 6 Mb */
+ [1] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000,
+ 7800, 1, 18, 0, 1, 1, 1 }, /* 9 Mb */
+ [2] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000,
+ 10000, 2, 24, 2, 2, 2, 2 }, /* 12 Mb */
+ [3] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000,
+ 13900, 3, 36, 2, 3, 3, 3 }, /* 18 Mb */
+ [4] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000,
+ 17300, 4, 48, 4, 4, 4, 4 }, /* 24 Mb */
+ [5] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000,
+ 23000, 5, 72, 4, 5, 5, 5 }, /* 36 Mb */
+ [6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000,
+ 27400, 6, 96, 4, 6, 6, 6 }, /* 48 Mb */
+ [7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000,
+ 29300, 7, 108, 4, 7, 7, 7 }, /* 54 Mb */
+ [8] = { RC_HT_SDT_2040, WLAN_RC_PHY_HT_20_SS, 6500,
+ 6400, 0, 0, 0, 38, 8, 38 }, /* 6.5 Mb */
+ [9] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000,
+ 12700, 1, 1, 2, 39, 9, 39 }, /* 13 Mb */
+ [10] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500,
+ 18800, 2, 2, 2, 40, 10, 40 }, /* 19.5 Mb */
+ [11] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000,
+ 25000, 3, 3, 4, 41, 11, 41 }, /* 26 Mb */
+ [12] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000,
+ 36700, 4, 4, 4, 42, 12, 42 }, /* 39 Mb */
+ [13] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000,
+ 48100, 5, 5, 4, 43, 13, 43 }, /* 52 Mb */
+ [14] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500,
+ 53500, 6, 6, 4, 44, 14, 44 }, /* 58.5 Mb */
+ [15] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000,
+ 59000, 7, 7, 4, 45, 16, 46 }, /* 65 Mb */
+ [16] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200,
+ 65400, 7, 7, 4, 45, 16, 46 }, /* 75 Mb */
+ [17] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000,
+ 12700, 8, 8, 0, 47, 17, 47 }, /* 13 Mb */
+ [18] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000,
+ 24800, 9, 9, 2, 48, 18, 48 }, /* 26 Mb */
+ [19] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000,
+ 36600, 10, 10, 2, 49, 19, 49 }, /* 39 Mb */
+ [20] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000,
+ 48100, 11, 11, 4, 50, 20, 50 }, /* 52 Mb */
+ [21] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000,
+ 69500, 12, 12, 4, 51, 21, 51 }, /* 78 Mb */
+ [22] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000,
+ 89500, 13, 13, 4, 52, 22, 52 }, /* 104 Mb */
+ [23] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000,
+ 98900, 14, 14, 4, 53, 23, 53 }, /* 117 Mb */
+ [24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000,
+ 108300, 15, 15, 4, 54, 25, 55 }, /* 130 Mb */
+ [25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400,
+ 120000, 15, 15, 4, 54, 25, 55 }, /* 144.4 Mb */
+ [26] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500,
+ 17400, 16, 16, 0, 56, 26, 56 }, /* 19.5 Mb */
+ [27] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000,
+ 35100, 17, 17, 2, 57, 27, 57 }, /* 39 Mb */
+ [28] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500,
+ 52600, 18, 18, 2, 58, 28, 58 }, /* 58.5 Mb */
+ [29] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000,
+ 70400, 19, 19, 4, 59, 29, 59 }, /* 78 Mb */
+ [30] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000,
+ 104900, 20, 20, 4, 60, 31, 61 }, /* 117 Mb */
+ [31] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000,
+ 115800, 20, 20, 4, 60, 31, 61 }, /* 130 Mb*/
+ [32] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000,
+ 137200, 21, 21, 4, 62, 33, 63 }, /* 156 Mb */
+ [33] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300,
+ 151100, 21, 21, 4, 62, 33, 63 }, /* 173.3 Mb */
+ [34] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500,
+ 152800, 22, 22, 4, 64, 35, 65 }, /* 175.5 Mb */
+ [35] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000,
+ 168400, 22, 22, 4, 64, 35, 65 }, /* 195 Mb*/
+ [36] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000,
+ 168400, 23, 23, 4, 66, 37, 67 }, /* 195 Mb */
+ [37] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700,
+ 185000, 23, 23, 4, 66, 37, 67 }, /* 216.7 Mb */
+ [38] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500,
+ 13200, 0, 0, 0, 38, 38, 38 }, /* 13.5 Mb*/
+ [39] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500,
+ 25900, 1, 1, 2, 39, 39, 39 }, /* 27.0 Mb*/
+ [40] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500,
+ 38600, 2, 2, 2, 40, 40, 40 }, /* 40.5 Mb*/
+ [41] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000,
+ 49800, 3, 3, 4, 41, 41, 41 }, /* 54 Mb */
+ [42] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500,
+ 72200, 4, 4, 4, 42, 42, 42 }, /* 81 Mb */
+ [43] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 108000,
+ 92900, 5, 5, 4, 43, 43, 43 }, /* 108 Mb */
+ [44] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500,
+ 102700, 6, 6, 4, 44, 44, 44 }, /* 121.5 Mb*/
+ [45] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000,
+ 112000, 7, 7, 4, 45, 46, 46 }, /* 135 Mb */
+ [46] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000,
+ 122000, 7, 7, 4, 45, 46, 46 }, /* 150 Mb */
+ [47] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000,
+ 25800, 8, 8, 0, 47, 47, 47 }, /* 27 Mb */
+ [48] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000,
+ 49800, 9, 9, 2, 48, 48, 48 }, /* 54 Mb */
+ [49] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000,
+ 71900, 10, 10, 2, 49, 49, 49 }, /* 81 Mb */
+ [50] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000,
+ 92500, 11, 11, 4, 50, 50, 50 }, /* 108 Mb */
+ [51] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000,
+ 130300, 12, 12, 4, 51, 51, 51 }, /* 162 Mb */
+ [52] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000,
+ 162800, 13, 13, 4, 52, 52, 52 }, /* 216 Mb */
+ [53] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000,
+ 178200, 14, 14, 4, 53, 53, 53 }, /* 243 Mb */
+ [54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000,
+ 192100, 15, 15, 4, 54, 55, 55 }, /* 270 Mb */
+ [55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000,
+ 207000, 15, 15, 4, 54, 55, 55 }, /* 300 Mb */
+ [56] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500,
+ 36100, 16, 16, 0, 56, 56, 56 }, /* 40.5 Mb */
+ [57] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000,
+ 72900, 17, 17, 2, 57, 57, 57 }, /* 81 Mb */
+ [58] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500,
+ 108300, 18, 18, 2, 58, 58, 58 }, /* 121.5 Mb */
+ [59] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000,
+ 142000, 19, 19, 4, 59, 59, 59 }, /* 162 Mb */
+ [60] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000,
+ 205100, 20, 20, 4, 60, 61, 61 }, /* 243 Mb */
+ [61] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000,
+ 224700, 20, 20, 4, 60, 61, 61 }, /* 270 Mb */
+ [62] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000,
+ 263100, 21, 21, 4, 62, 63, 63 }, /* 324 Mb */
+ [63] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000,
+ 288000, 21, 21, 4, 62, 63, 63 }, /* 360 Mb */
+ [64] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500,
+ 290700, 22, 22, 4, 64, 65, 65 }, /* 364.5 Mb */
+ [65] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000,
+ 317200, 22, 22, 4, 64, 65, 65 }, /* 405 Mb */
+ [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000,
+ 317200, 23, 23, 4, 66, 67, 67 }, /* 405 Mb */
+ [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000,
+ 346400, 23, 23, 4, 66, 67, 67 }, /* 450 Mb */
},
50, /* probe interval */
WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
@@ -118,103 +168,153 @@ static const struct ath_rate_table ar5416_11na_ratetable = {
* for HT are the 64K max aggregate limit */
static const struct ath_rate_table ar5416_11ng_ratetable = {
- 47,
+ 72,
12, /* MCS start */
{
- { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
- 900, 0, 2, 0, 0, 0, 0, 0 },
- { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
- 1900, 1, 4, 1, 1, 1, 1, 1 },
- { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
- 4900, 2, 11, 2, 2, 2, 2, 2 },
- { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
- 8100, 3, 22, 3, 3, 3, 3, 3 },
- { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
- 5400, 4, 12, 4, 4, 4, 4, 4 },
- { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
- 7800, 5, 18, 4, 5, 5, 5, 5 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
- 10100, 6, 24, 6, 6, 6, 6, 6 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
- 14100, 7, 36, 6, 7, 7, 7, 7 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
- 17700, 8, 48, 8, 8, 8, 8, 8 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
- 23700, 9, 72, 8, 9, 9, 9, 9 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
- 27400, 10, 96, 8, 10, 10, 10, 10 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
- 30900, 11, 108, 8, 11, 11, 11, 11 },
- { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
- 6400, 0, 0, 4, 12, 29, 12, 29 },
- { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
- 12700, 1, 1, 6, 13, 30, 13, 30 },
- { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
- 18800, 2, 2, 6, 14, 31, 14, 31 },
- { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
- 25000, 3, 3, 8, 15, 32, 15, 32 },
- { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
- 36700, 4, 4, 8, 16, 33, 16, 33 },
- { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
- 48100, 5, 5, 8, 17, 34, 17, 34 },
- { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
- 53500, 6, 6, 8, 18, 35, 18, 35 },
- { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
- 59000, 7, 7, 8, 19, 36, 19, 37 },
- { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
- 12700, 8, 8, 4, 20, 38, 20, 38 },
- { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
- 24800, 9, 9, 6, 21, 39, 21, 39 },
- { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
- 36600, 10, 10, 6, 22, 40, 22, 40 },
- { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
- 48100, 11, 11, 8, 23, 41, 23, 41 },
- { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
- 69500, 12, 12, 8, 24, 42, 24, 42 },
- { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
- 89500, 13, 13, 8, 25, 43, 25, 43 },
- { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
- 98900, 14, 14, 8, 26, 44, 26, 44 },
- { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
- 108300, 15, 15, 8, 27, 45, 28, 46 },
- { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS_HGI, 144400, /* 130 Mb */
- 120000, 15, 15, 8, 27, 45, 28, 46 },
- { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
- 13200, 0, 0, 8, 12, 29, 29, 29 },
- { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
- 25900, 1, 1, 8, 13, 30, 30, 30 },
- { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
- 38600, 2, 2, 8, 14, 31, 31, 31 },
- { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
- 49800, 3, 3, 8, 15, 32, 32, 32 },
- { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
- 72200, 4, 4, 8, 16, 33, 33, 33 },
- { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
- 92900, 5, 5, 8, 17, 34, 34, 34 },
- { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
- 102700, 6, 6, 8, 18, 35, 35, 35 },
- { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
- 112000, 7, 7, 8, 19, 36, 37, 37 },
- { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
- 122000, 7, 7, 8, 19, 36, 37, 37 },
- { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
- 25800, 8, 8, 8, 20, 38, 38, 38 },
- { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
- 49800, 9, 9, 8, 21, 39, 39, 39 },
- { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
- 71900, 10, 10, 8, 22, 40, 40, 40 },
- { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
- 92500, 11, 11, 8, 23, 41, 41, 41 },
- { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
- 130300, 12, 12, 8, 24, 42, 42, 42 },
- { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
- 162800, 13, 13, 8, 25, 43, 43, 43 },
- { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
- 178200, 14, 14, 8, 26, 44, 44, 44 },
- { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
- 192100, 15, 15, 8, 27, 45, 46, 46 },
- { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
- 207000, 15, 15, 8, 27, 45, 46, 46 },
+ [0] = { RC_ALL, WLAN_RC_PHY_CCK, 1000,
+ 900, 0, 2, 0, 0, 0, 0 }, /* 1 Mb */
+ [1] = { RC_ALL, WLAN_RC_PHY_CCK, 2000,
+ 1900, 1, 4, 1, 1, 1, 1 }, /* 2 Mb */
+ [2] = { RC_ALL, WLAN_RC_PHY_CCK, 5500,
+ 4900, 2, 11, 2, 2, 2, 2 }, /* 5.5 Mb */
+ [3] = { RC_ALL, WLAN_RC_PHY_CCK, 11000,
+ 8100, 3, 22, 3, 3, 3, 3 }, /* 11 Mb */
+ [4] = { RC_INVALID, WLAN_RC_PHY_OFDM, 6000,
+ 5400, 4, 12, 4, 4, 4, 4 }, /* 6 Mb */
+ [5] = { RC_INVALID, WLAN_RC_PHY_OFDM, 9000,
+ 7800, 5, 18, 4, 5, 5, 5 }, /* 9 Mb */
+ [6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000,
+ 10100, 6, 24, 6, 6, 6, 6 }, /* 12 Mb */
+ [7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000,
+ 14100, 7, 36, 6, 7, 7, 7 }, /* 18 Mb */
+ [8] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000,
+ 17700, 8, 48, 8, 8, 8, 8 }, /* 24 Mb */
+ [9] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000,
+ 23700, 9, 72, 8, 9, 9, 9 }, /* 36 Mb */
+ [10] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000,
+ 27400, 10, 96, 8, 10, 10, 10 }, /* 48 Mb */
+ [11] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000,
+ 30900, 11, 108, 8, 11, 11, 11 }, /* 54 Mb */
+ [12] = { RC_INVALID, WLAN_RC_PHY_HT_20_SS, 6500,
+ 6400, 0, 0, 4, 42, 12, 42 }, /* 6.5 Mb */
+ [13] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000,
+ 12700, 1, 1, 6, 43, 13, 43 }, /* 13 Mb */
+ [14] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500,
+ 18800, 2, 2, 6, 44, 14, 44 }, /* 19.5 Mb*/
+ [15] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000,
+ 25000, 3, 3, 8, 45, 15, 45 }, /* 26 Mb */
+ [16] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000,
+ 36700, 4, 4, 8, 46, 16, 46 }, /* 39 Mb */
+ [17] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000,
+ 48100, 5, 5, 8, 47, 17, 47 }, /* 52 Mb */
+ [18] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500,
+ 53500, 6, 6, 8, 48, 18, 48 }, /* 58.5 Mb */
+ [19] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000,
+ 59000, 7, 7, 8, 49, 20, 50 }, /* 65 Mb */
+ [20] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200,
+ 65400, 7, 7, 8, 49, 20, 50 }, /* 65 Mb*/
+ [21] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000,
+ 12700, 8, 8, 4, 51, 21, 51 }, /* 13 Mb */
+ [22] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000,
+ 24800, 9, 9, 6, 52, 22, 52 }, /* 26 Mb */
+ [23] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000,
+ 36600, 10, 10, 6, 53, 23, 53 }, /* 39 Mb */
+ [24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000,
+ 48100, 11, 11, 8, 54, 24, 54 }, /* 52 Mb */
+ [25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000,
+ 69500, 12, 12, 8, 55, 25, 55 }, /* 78 Mb */
+ [26] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000,
+ 89500, 13, 13, 8, 56, 26, 56 }, /* 104 Mb */
+ [27] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000,
+ 98900, 14, 14, 8, 57, 27, 57 }, /* 117 Mb */
+ [28] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000,
+ 108300, 15, 15, 8, 58, 29, 59 }, /* 130 Mb */
+ [29] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400,
+ 120000, 15, 15, 8, 58, 29, 59 }, /* 144.4 Mb */
+ [30] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500,
+ 17400, 16, 16, 4, 60, 30, 60 }, /* 19.5 Mb */
+ [31] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000,
+ 35100, 17, 17, 6, 61, 31, 61 }, /* 39 Mb */
+ [32] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500,
+ 52600, 18, 18, 6, 62, 32, 62 }, /* 58.5 Mb */
+ [33] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000,
+ 70400, 19, 19, 8, 63, 33, 63 }, /* 78 Mb */
+ [34] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000,
+ 104900, 20, 20, 8, 64, 35, 65 }, /* 117 Mb */
+ [35] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000,
+ 115800, 20, 20, 8, 64, 35, 65 }, /* 130 Mb */
+ [36] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000,
+ 137200, 21, 21, 8, 66, 37, 67 }, /* 156 Mb */
+ [37] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300,
+ 151100, 21, 21, 8, 66, 37, 67 }, /* 173.3 Mb */
+ [38] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500,
+ 152800, 22, 22, 8, 68, 39, 69 }, /* 175.5 Mb */
+ [39] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000,
+ 168400, 22, 22, 8, 68, 39, 69 }, /* 195 Mb */
+ [40] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000,
+ 168400, 23, 23, 8, 70, 41, 71 }, /* 195 Mb */
+ [41] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700,
+ 185000, 23, 23, 8, 70, 41, 71 }, /* 216.7 Mb */
+ [42] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500,
+ 13200, 0, 0, 8, 42, 42, 42 }, /* 13.5 Mb */
+ [43] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500,
+ 25900, 1, 1, 8, 43, 43, 43 }, /* 27.0 Mb */
+ [44] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500,
+ 38600, 2, 2, 8, 44, 44, 44 }, /* 40.5 Mb */
+ [45] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000,
+ 49800, 3, 3, 8, 45, 45, 45 }, /* 54 Mb */
+ [46] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500,
+ 72200, 4, 4, 8, 46, 46, 46 }, /* 81 Mb */
+ [47] = { RC_HT_S_40 , WLAN_RC_PHY_HT_40_SS, 108000,
+ 92900, 5, 5, 8, 47, 47, 47 }, /* 108 Mb */
+ [48] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500,
+ 102700, 6, 6, 8, 48, 48, 48 }, /* 121.5 Mb */
+ [49] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000,
+ 112000, 7, 7, 8, 49, 50, 50 }, /* 135 Mb */
+ [50] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000,
+ 122000, 7, 7, 8, 49, 50, 50 }, /* 150 Mb */
+ [51] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000,
+ 25800, 8, 8, 8, 51, 51, 51 }, /* 27 Mb */
+ [52] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000,
+ 49800, 9, 9, 8, 52, 52, 52 }, /* 54 Mb */
+ [53] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000,
+ 71900, 10, 10, 8, 53, 53, 53 }, /* 81 Mb */
+ [54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000,
+ 92500, 11, 11, 8, 54, 54, 54 }, /* 108 Mb */
+ [55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000,
+ 130300, 12, 12, 8, 55, 55, 55 }, /* 162 Mb */
+ [56] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000,
+ 162800, 13, 13, 8, 56, 56, 56 }, /* 216 Mb */
+ [57] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000,
+ 178200, 14, 14, 8, 57, 57, 57 }, /* 243 Mb */
+ [58] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000,
+ 192100, 15, 15, 8, 58, 59, 59 }, /* 270 Mb */
+ [59] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000,
+ 207000, 15, 15, 8, 58, 59, 59 }, /* 300 Mb */
+ [60] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500,
+ 36100, 16, 16, 8, 60, 60, 60 }, /* 40.5 Mb */
+ [61] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000,
+ 72900, 17, 17, 8, 61, 61, 61 }, /* 81 Mb */
+ [62] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500,
+ 108300, 18, 18, 8, 62, 62, 62 }, /* 121.5 Mb */
+ [63] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000,
+ 142000, 19, 19, 8, 63, 63, 63 }, /* 162 Mb */
+ [64] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000,
+ 205100, 20, 20, 8, 64, 65, 65 }, /* 243 Mb */
+ [65] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000,
+ 224700, 20, 20, 8, 64, 65, 65 }, /* 170 Mb */
+ [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000,
+ 263100, 21, 21, 8, 66, 67, 67 }, /* 324 Mb */
+ [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000,
+ 288000, 21, 21, 8, 66, 67, 67 }, /* 360 Mb */
+ [68] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500,
+ 290700, 22, 22, 8, 68, 69, 69 }, /* 364.5 Mb */
+ [69] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000,
+ 317200, 22, 22, 8, 68, 69, 69 }, /* 405 Mb */
+ [70] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000,
+ 317200, 23, 23, 8, 70, 71, 71 }, /* 405 Mb */
+ [71] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000,
+ 346400, 23, 23, 8, 70, 71, 71 }, /* 450 Mb */
},
50, /* probe interval */
WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
@@ -224,22 +324,22 @@ static const struct ath_rate_table ar5416_11a_ratetable = {
8,
0,
{
- { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
- 5400, 0, 12, 0, 0, 0 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
- 7800, 1, 18, 0, 1, 0 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
- 10000, 2, 24, 2, 2, 0 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
- 13900, 3, 36, 2, 3, 0 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
- 17300, 4, 48, 4, 4, 0 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
- 23000, 5, 72, 4, 5, 0 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
- 27400, 6, 96, 4, 6, 0 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
- 29300, 7, 108, 4, 7, 0 },
+ { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
+ 5400, 0, 12, 0},
+ { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
+ 7800, 1, 18, 0},
+ { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
+ 10000, 2, 24, 2},
+ { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
+ 13900, 3, 36, 2},
+ { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
+ 17300, 4, 48, 4},
+ { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
+ 23000, 5, 72, 4},
+ { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
+ 27400, 6, 96, 4},
+ { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
+ 29300, 7, 108, 4},
},
50, /* probe interval */
0, /* Phy rates allowed initially */
@@ -249,30 +349,30 @@ static const struct ath_rate_table ar5416_11g_ratetable = {
12,
0,
{
- { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
- 900, 0, 2, 0, 0, 0 },
- { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
- 1900, 1, 4, 1, 1, 0 },
- { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
- 4900, 2, 11, 2, 2, 0 },
- { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
- 8100, 3, 22, 3, 3, 0 },
- { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
- 5400, 4, 12, 4, 4, 0 },
- { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
- 7800, 5, 18, 4, 5, 0 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
- 10000, 6, 24, 6, 6, 0 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
- 13900, 7, 36, 6, 7, 0 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
- 17300, 8, 48, 8, 8, 0 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
- 23000, 9, 72, 8, 9, 0 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
- 27400, 10, 96, 8, 10, 0 },
- { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
- 29300, 11, 108, 8, 11, 0 },
+ { RC_L_SDT, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
+ 900, 0, 2, 0},
+ { RC_L_SDT, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
+ 1900, 1, 4, 1},
+ { RC_L_SDT, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
+ 4900, 2, 11, 2},
+ { RC_L_SDT, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
+ 8100, 3, 22, 3},
+ { RC_INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
+ 5400, 4, 12, 4},
+ { RC_INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
+ 7800, 5, 18, 4},
+ { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
+ 10000, 6, 24, 6},
+ { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
+ 13900, 7, 36, 6},
+ { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
+ 17300, 8, 48, 8},
+ { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
+ 23000, 9, 72, 8},
+ { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
+ 27400, 10, 96, 8},
+ { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
+ 29300, 11, 108, 8},
},
50, /* probe interval */
0, /* Phy rates allowed initially */
@@ -342,7 +442,7 @@ static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv,
u8 index, int valid_tx_rate)
{
BUG_ON(index > ath_rc_priv->rate_table_size);
- ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0;
+ ath_rc_priv->valid_rate_index[index] = !!valid_tx_rate;
}
static inline
@@ -374,6 +474,8 @@ static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
return 0;
if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
return 0;
+ if (WLAN_RC_PHY_TS(phy) && !(capflag & WLAN_RC_TS_FLAG))
+ return 0;
if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG))
return 0;
if (!ignore_cw && WLAN_RC_PHY_HT(phy))
@@ -404,13 +506,9 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv,
u32 capflag)
{
u8 i, hi = 0;
- u32 valid;
for (i = 0; i < rate_table->rate_cnt; i++) {
- valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
- rate_table->info[i].valid_single_stream :
- rate_table->info[i].valid);
- if (valid == 1) {
+ if (rate_table->info[i].rate_flags & RC_LEGACY) {
u32 phy = rate_table->info[i].phy;
u8 valid_rate_count = 0;
@@ -422,7 +520,7 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv,
ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i;
ath_rc_priv->valid_phy_ratecnt[phy] += 1;
ath_rc_set_valid_txmask(ath_rc_priv, i, 1);
- hi = A_MAX(hi, i);
+ hi = i;
}
}
@@ -440,9 +538,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
for (i = 0; i < rateset->rs_nrates; i++) {
for (j = 0; j < rate_table->rate_cnt; j++) {
u32 phy = rate_table->info[j].phy;
- u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
- rate_table->info[j].valid_single_stream :
- rate_table->info[j].valid);
+ u16 rate_flags = rate_table->info[i].rate_flags;
u8 rate = rateset->rs_rates[i];
u8 dot11rate = rate_table->info[j].dot11rate;
@@ -451,8 +547,9 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
* (VALID/VALID_20/VALID_40) flags */
if ((rate == dot11rate) &&
- ((valid & WLAN_RC_CAP_MODE(capflag)) ==
- WLAN_RC_CAP_MODE(capflag)) &&
+ (rate_flags & WLAN_RC_CAP_MODE(capflag)) ==
+ WLAN_RC_CAP_MODE(capflag) &&
+ (rate_flags & WLAN_RC_CAP_STREAM(capflag)) &&
!WLAN_RC_PHY_HT(phy)) {
u8 valid_rate_count = 0;
@@ -486,14 +583,13 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
for (i = 0; i < rateset->rs_nrates; i++) {
for (j = 0; j < rate_table->rate_cnt; j++) {
u32 phy = rate_table->info[j].phy;
- u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
- rate_table->info[j].valid_single_stream :
- rate_table->info[j].valid);
+ u16 rate_flags = rate_table->info[j].rate_flags;
u8 rate = rateset->rs_rates[i];
u8 dot11rate = rate_table->info[j].dot11rate;
if ((rate != dot11rate) || !WLAN_RC_PHY_HT(phy) ||
- !WLAN_RC_PHY_HT_VALID(valid, capflag))
+ !(rate_flags & WLAN_RC_CAP_STREAM(capflag)) ||
+ !WLAN_RC_PHY_HT_VALID(rate_flags, capflag))
continue;
if (!ath_rc_valid_phyrate(phy, capflag, 0))
@@ -589,12 +685,15 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
if (rate > (ath_rc_priv->rate_table_size - 1))
rate = ath_rc_priv->rate_table_size - 1;
- if (rate_table->info[rate].valid &&
- (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))
+ if (RC_TS_ONLY(rate_table->info[rate].rate_flags) &&
+ (ath_rc_priv->ht_cap & WLAN_RC_TS_FLAG))
+ return rate;
+
+ if (RC_DS_OR_LATER(rate_table->info[rate].rate_flags) &&
+ (ath_rc_priv->ht_cap & (WLAN_RC_DS_FLAG | WLAN_RC_TS_FLAG)))
return rate;
- if (rate_table->info[rate].valid_single_stream &&
- !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))
+ if (RC_SS_OR_LEGACY(rate_table->info[rate].rate_flags))
return rate;
/* This should not happen */
@@ -1007,12 +1106,19 @@ static void ath_rc_update_ht(struct ath_softc *sc,
static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
struct ieee80211_tx_rate *rate)
{
- int rix;
+ int rix = 0, i = 0;
+ int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 };
if (!(rate->flags & IEEE80211_TX_RC_MCS))
return rate->idx;
- rix = rate->idx + rate_table->mcs_start;
+ while (rate->idx > mcs_rix_off[i] &&
+ i < sizeof(mcs_rix_off)/sizeof(int)) {
+ rix++; i++;
+ }
+
+ rix += rate->idx + rate_table->mcs_start;
+
if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
(rate->flags & IEEE80211_TX_RC_SHORT_GI))
rix = rate_table->info[rix].ht_index;
@@ -1020,8 +1126,6 @@ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
rix = rate_table->info[rix].sgi_index;
else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
rix = rate_table->info[rix].cw40index;
- else
- rix = rate_table->info[rix].base_index;
return rix;
}
@@ -1203,13 +1307,14 @@ static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta,
if (sta->ht_cap.ht_supported) {
caps = WLAN_RC_HT_FLAG;
- if (sta->ht_cap.mcs.rx_mask[1])
+ if (sta->ht_cap.mcs.rx_mask[1] && sta->ht_cap.mcs.rx_mask[2])
+ caps |= WLAN_RC_TS_FLAG | WLAN_RC_DS_FLAG;
+ else if (sta->ht_cap.mcs.rx_mask[1])
caps |= WLAN_RC_DS_FLAG;
if (is_cw40)
caps |= WLAN_RC_40_FLAG;
if (is_sgi)
caps |= WLAN_RC_SGI_FLAG;
-
}
return caps;
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
index 3d8d40cdc99e..dc1082654501 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -24,32 +24,63 @@
struct ath_softc;
#define ATH_RATE_MAX 30
-#define RATE_TABLE_SIZE 64
+#define RATE_TABLE_SIZE 72
#define MAX_TX_RATE_PHY 48
-/* VALID_ALL - valid for 20/40/Legacy,
- * VALID - Legacy only,
- * VALID_20 - HT 20 only,
- * VALID_40 - HT 40 only */
-#define INVALID 0x0
-#define VALID 0x1
-#define VALID_20 0x2
-#define VALID_40 0x4
-#define VALID_2040 (VALID_20|VALID_40)
-#define VALID_ALL (VALID_2040|VALID)
+#define RC_INVALID 0x0000
+#define RC_LEGACY 0x0001
+#define RC_SS 0x0002
+#define RC_DS 0x0004
+#define RC_TS 0x0008
+#define RC_HT_20 0x0010
+#define RC_HT_40 0x0020
+
+#define RC_STREAM_MASK 0xe
+#define RC_DS_OR_LATER(f) ((((f) & RC_STREAM_MASK) == RC_DS) || \
+ (((f) & RC_STREAM_MASK) == (RC_DS | RC_TS)))
+#define RC_TS_ONLY(f) (((f) & RC_STREAM_MASK) == RC_TS)
+#define RC_SS_OR_LEGACY(f) ((f) & (RC_SS | RC_LEGACY))
+
+#define RC_HT_2040 (RC_HT_20 | RC_HT_40)
+#define RC_ALL_STREAM (RC_SS | RC_DS | RC_TS)
+#define RC_L_SD (RC_LEGACY | RC_SS | RC_DS)
+#define RC_L_SDT (RC_LEGACY | RC_SS | RC_DS | RC_TS)
+#define RC_HT_S_20 (RC_HT_20 | RC_SS)
+#define RC_HT_D_20 (RC_HT_20 | RC_DS)
+#define RC_HT_T_20 (RC_HT_20 | RC_TS)
+#define RC_HT_S_40 (RC_HT_40 | RC_SS)
+#define RC_HT_D_40 (RC_HT_40 | RC_DS)
+#define RC_HT_T_40 (RC_HT_40 | RC_TS)
+
+#define RC_HT_SD_20 (RC_HT_20 | RC_SS | RC_DS)
+#define RC_HT_DT_20 (RC_HT_20 | RC_DS | RC_TS)
+#define RC_HT_SD_40 (RC_HT_40 | RC_SS | RC_DS)
+#define RC_HT_DT_40 (RC_HT_40 | RC_DS | RC_TS)
+
+#define RC_HT_SD_2040 (RC_HT_2040 | RC_SS | RC_DS)
+#define RC_HT_SDT_2040 (RC_HT_2040 | RC_SS | RC_DS | RC_TS)
+
+#define RC_HT_SDT_20 (RC_HT_20 | RC_SS | RC_DS | RC_TS)
+#define RC_HT_SDT_40 (RC_HT_40 | RC_SS | RC_DS | RC_TS)
+
+#define RC_ALL (RC_LEGACY | RC_HT_2040 | RC_ALL_STREAM)
enum {
WLAN_RC_PHY_OFDM,
WLAN_RC_PHY_CCK,
WLAN_RC_PHY_HT_20_SS,
WLAN_RC_PHY_HT_20_DS,
+ WLAN_RC_PHY_HT_20_TS,
WLAN_RC_PHY_HT_40_SS,
WLAN_RC_PHY_HT_40_DS,
+ WLAN_RC_PHY_HT_40_TS,
WLAN_RC_PHY_HT_20_SS_HGI,
WLAN_RC_PHY_HT_20_DS_HGI,
+ WLAN_RC_PHY_HT_20_TS_HGI,
WLAN_RC_PHY_HT_40_SS_HGI,
WLAN_RC_PHY_HT_40_DS_HGI,
+ WLAN_RC_PHY_HT_40_TS_HGI,
WLAN_RC_PHY_MAX
};
@@ -57,36 +88,50 @@ enum {
|| (_phy == WLAN_RC_PHY_HT_40_DS) \
|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+#define WLAN_RC_PHY_TS(_phy) ((_phy == WLAN_RC_PHY_HT_20_TS) \
+ || (_phy == WLAN_RC_PHY_HT_40_TS) \
+ || (_phy == WLAN_RC_PHY_HT_20_TS_HGI) \
+ || (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
#define WLAN_RC_PHY_20(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS) \
|| (_phy == WLAN_RC_PHY_HT_20_DS) \
+ || (_phy == WLAN_RC_PHY_HT_20_TS) \
|| (_phy == WLAN_RC_PHY_HT_20_SS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_20_DS_HGI))
+ || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
+ || (_phy == WLAN_RC_PHY_HT_20_TS_HGI))
#define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \
|| (_phy == WLAN_RC_PHY_HT_40_DS) \
+ || (_phy == WLAN_RC_PHY_HT_40_TS) \
|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+ || (_phy == WLAN_RC_PHY_HT_40_DS_HGI) \
+ || (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
#define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \
+ || (_phy == WLAN_RC_PHY_HT_20_TS_HGI) \
|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \
- || (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+ || (_phy == WLAN_RC_PHY_HT_40_DS_HGI) \
+ || (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
#define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS)
#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \
- (capflag & WLAN_RC_40_FLAG) ? VALID_40 : VALID_20 : VALID))
+ ((capflag & WLAN_RC_40_FLAG) ? RC_HT_40 : RC_HT_20) : RC_LEGACY))
+
+#define WLAN_RC_CAP_STREAM(capflag) (((capflag & WLAN_RC_TS_FLAG) ? \
+ (RC_TS) : ((capflag & WLAN_RC_DS_FLAG) ? RC_DS : RC_SS)))
/* Return TRUE if flag supports HT20 && client supports HT20 or
* return TRUE if flag supports HT40 && client supports HT40.
* This is used becos some rates overlap between HT20/HT40.
*/
#define WLAN_RC_PHY_HT_VALID(flag, capflag) \
- (((flag & VALID_20) && !(capflag & WLAN_RC_40_FLAG)) || \
- ((flag & VALID_40) && (capflag & WLAN_RC_40_FLAG)))
+ (((flag & RC_HT_20) && !(capflag & WLAN_RC_40_FLAG)) || \
+ ((flag & RC_HT_40) && (capflag & WLAN_RC_40_FLAG)))
#define WLAN_RC_DS_FLAG (0x01)
-#define WLAN_RC_40_FLAG (0x02)
-#define WLAN_RC_SGI_FLAG (0x04)
-#define WLAN_RC_HT_FLAG (0x08)
+#define WLAN_RC_TS_FLAG (0x02)
+#define WLAN_RC_40_FLAG (0x04)
+#define WLAN_RC_SGI_FLAG (0x08)
+#define WLAN_RC_HT_FLAG (0x10)
/**
* struct ath_rate_table - Rate Control table
@@ -110,15 +155,13 @@ struct ath_rate_table {
int rate_cnt;
int mcs_start;
struct {
- u8 valid;
- u8 valid_single_stream;
+ u16 rate_flags;
u8 phy;
u32 ratekbps;
u32 user_ratekbps;
u8 ratecode;
u8 dot11rate;
u8 ctrl_rate;
- u8 base_index;
u8 cw40index;
u8 sgi_index;
u8 ht_index;
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
index 89423ca23d2c..fd20241f57d8 100644
--- a/drivers/net/wireless/ath/ath9k/virtual.c
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
@@ -695,16 +695,18 @@ void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle)
idle ? "idle" : "not-idle");
}
/* Only bother starting a queue on an active virtual wiphy */
-void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue)
+bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue)
{
struct ieee80211_hw *hw = sc->pri_wiphy->hw;
unsigned int i;
+ bool txq_started = false;
spin_lock_bh(&sc->wiphy_lock);
/* Start the primary wiphy */
if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) {
ieee80211_wake_queue(hw, skb_queue);
+ txq_started = true;
goto unlock;
}
@@ -718,11 +720,13 @@ void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue)
hw = aphy->hw;
ieee80211_wake_queue(hw, skb_queue);
+ txq_started = true;
break;
}
unlock:
spin_unlock_bh(&sc->wiphy_lock);
+ return txq_started;
}
/* Go ahead and propagate information to all virtual wiphys, it won't hurt */
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 0644f1e91887..501b72821b4d 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -518,6 +518,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
bf = bf_next;
}
+ /* prepend un-acked frames to the beginning of the pending frame queue */
+ if (!list_empty(&bf_pending)) {
+ spin_lock_bh(&txq->axq_lock);
+ list_splice(&bf_pending, &tid->buf_q);
+ ath_tx_queue_tid(txq, tid);
+ spin_unlock_bh(&txq->axq_lock);
+ }
+
if (tid->state & AGGR_CLEANUP) {
if (tid->baw_head == tid->baw_tail) {
tid->state &= ~AGGR_ADDBA_COMPLETE;
@@ -530,14 +538,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
return;
}
- /* prepend un-acked frames to the beginning of the pending frame queue */
- if (!list_empty(&bf_pending)) {
- spin_lock_bh(&txq->axq_lock);
- list_splice(&bf_pending, &tid->buf_q);
- ath_tx_queue_tid(txq, tid);
- spin_unlock_bh(&txq->axq_lock);
- }
-
rcu_read_unlock();
if (needreset)
@@ -2077,8 +2077,8 @@ static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
spin_lock_bh(&txq->axq_lock);
if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) {
- ath_mac80211_start_queue(sc, qnum);
- txq->stopped = 0;
+ if (ath_mac80211_start_queue(sc, qnum))
+ txq->stopped = 0;
}
spin_unlock_bh(&txq->axq_lock);
}
diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h
index 4736861bc4f8..70f5586d96bd 100644
--- a/drivers/net/wireless/ipw2x00/libipw.h
+++ b/drivers/net/wireless/ipw2x00/libipw.h
@@ -828,7 +828,6 @@ struct libipw_device {
int host_strip_iv_icv;
int host_open_frag;
- int host_build_iv;
int ieee802_1x; /* is IEEE 802.1X used */
/* WPA data */
diff --git a/drivers/net/wireless/ipw2x00/libipw_tx.c b/drivers/net/wireless/ipw2x00/libipw_tx.c
index da8beac7fcf3..01c88a71abe1 100644
--- a/drivers/net/wireless/ipw2x00/libipw_tx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_tx.c
@@ -260,7 +260,7 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev)
int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
rts_required;
unsigned long flags;
- int encrypt, host_encrypt, host_encrypt_msdu, host_build_iv;
+ int encrypt, host_encrypt, host_encrypt_msdu;
__be16 ether_type;
int bytes, fc, hdr_len;
struct sk_buff *skb_frag;
@@ -301,7 +301,6 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev)
host_encrypt = ieee->host_encrypt && encrypt && crypt;
host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt;
- host_build_iv = ieee->host_build_iv && encrypt && crypt;
if (!encrypt && ieee->ieee802_1x &&
ieee->drop_unencrypted && ether_type != htons(ETH_P_PAE)) {
@@ -313,7 +312,7 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev)
skb_copy_from_linear_data(skb, dest, ETH_ALEN);
skb_copy_from_linear_data_offset(skb, ETH_ALEN, src, ETH_ALEN);
- if (host_encrypt || host_build_iv)
+ if (host_encrypt)
fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
IEEE80211_FCTL_PROTECTED;
else
@@ -467,7 +466,7 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev)
for (; i < nr_frags; i++) {
skb_frag = txb->fragments[i];
- if (host_encrypt || host_build_iv)
+ if (host_encrypt)
skb_reserve(skb_frag,
crypt->ops->extra_mpdu_prefix_len);
@@ -502,15 +501,6 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev)
* to insert the IV between the header and the payload */
if (host_encrypt)
libipw_encrypt_fragment(ieee, skb_frag, hdr_len);
- else if (host_build_iv) {
- atomic_inc(&crypt->refcnt);
- if (crypt->ops->build_iv)
- crypt->ops->build_iv(skb_frag, hdr_len,
- ieee->sec.keys[ieee->sec.active_key],
- ieee->sec.key_sizes[ieee->sec.active_key],
- crypt->priv);
- atomic_dec(&crypt->refcnt);
- }
if (ieee->config &
(CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c
index 8a4bae44b109..d7bd6cf00a81 100644
--- a/drivers/net/wireless/ipw2x00/libipw_wx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_wx.c
@@ -320,7 +320,7 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
};
int i, key, key_provided, len;
struct lib80211_crypt_data **crypt;
- int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
+ int host_crypto = ieee->host_encrypt || ieee->host_decrypt;
DECLARE_SSID_BUF(ssid);
LIBIPW_DEBUG_WX("SET_ENCODE\n");
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index c281d07ec5e5..8848333bc3a9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -222,6 +222,7 @@ static struct iwl_lib_ops iwl1000_lib = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
+ .bt_stats_read = iwl_ucode_bt_stats_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 3a0d0adab1ae..d6531ad3906a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -1605,8 +1605,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
if (!test_bit(STATUS_TEMPERATURE, &priv->status))
vt = sign_extend(R4, 23);
else
- vt = sign_extend(le32_to_cpu(
- priv->_agn.statistics.general.temperature), 23);
+ vt = sign_extend(le32_to_cpu(priv->_agn.statistics.
+ general.common.temperature), 23);
IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
@@ -2285,6 +2285,7 @@ static struct iwl_lib_ops iwl4965_lib = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
+ .bt_stats_read = iwl_ucode_bt_stats_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 7d89d99ce19c..8093ce2804fb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -265,7 +265,7 @@ static void iwl5150_temperature(struct iwl_priv *priv)
u32 vt = 0;
s32 offset = iwl_temp_calib_to_offset(priv);
- vt = le32_to_cpu(priv->_agn.statistics.general.temperature);
+ vt = le32_to_cpu(priv->_agn.statistics.general.common.temperature);
vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
/* now vt hold the temperature in Kelvin */
priv->temperature = KELVIN_TO_CELSIUS(vt);
@@ -398,6 +398,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
+ .bt_stats_read = iwl_ucode_bt_stats_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 095521952bbe..58270529a0e4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -323,6 +323,7 @@ static struct iwl_lib_ops iwl6000_lib = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
+ .bt_stats_read = iwl_ucode_bt_stats_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
@@ -500,6 +501,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = {
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
+ .bt_statistics = true,
};
struct iwl_cfg iwl6000g2b_2abg_cfg = {
@@ -535,6 +537,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = {
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
+ .bt_statistics = true,
};
struct iwl_cfg iwl6000g2b_2bgn_cfg = {
@@ -572,6 +575,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = {
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
+ .bt_statistics = true,
};
struct iwl_cfg iwl6000g2b_2bg_cfg = {
@@ -607,6 +611,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = {
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
+ .bt_statistics = true,
};
struct iwl_cfg iwl6000g2b_bgn_cfg = {
@@ -644,6 +649,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = {
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
+ .bt_statistics = true,
};
struct iwl_cfg iwl6000g2b_bg_cfg = {
@@ -679,6 +685,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = {
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
.need_dc_calib = true,
+ .bt_statistics = true,
};
/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index 90033e8752bb..c4c5691032a6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -605,8 +605,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);
}
-void iwl_sensitivity_calibration(struct iwl_priv *priv,
- struct iwl_notif_statistics *resp)
+void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp)
{
u32 rx_enable_time;
u32 fa_cck;
@@ -616,8 +615,8 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv,
u32 norm_fa_ofdm;
u32 norm_fa_cck;
struct iwl_sensitivity_data *data = NULL;
- struct statistics_rx_non_phy *rx_info = &(resp->rx.general);
- struct statistics_rx *statistics = &(resp->rx);
+ struct statistics_rx_non_phy *rx_info;
+ struct statistics_rx_phy *ofdm, *cck;
unsigned long flags;
struct statistics_general_data statis;
@@ -632,6 +631,16 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv,
}
spin_lock_irqsave(&priv->lock, flags);
+ if (priv->cfg->bt_statistics) {
+ rx_info = &(((struct iwl_bt_notif_statistics *)resp)->
+ rx.general.common);
+ ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm);
+ cck = &(((struct iwl_bt_notif_statistics *)resp)->rx.cck);
+ } else {
+ rx_info = &(((struct iwl_notif_statistics *)resp)->rx.general);
+ ofdm = &(((struct iwl_notif_statistics *)resp)->rx.ofdm);
+ cck = &(((struct iwl_notif_statistics *)resp)->rx.cck);
+ }
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
spin_unlock_irqrestore(&priv->lock, flags);
@@ -640,23 +649,23 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv,
/* Extract Statistics: */
rx_enable_time = le32_to_cpu(rx_info->channel_load);
- fa_cck = le32_to_cpu(statistics->cck.false_alarm_cnt);
- fa_ofdm = le32_to_cpu(statistics->ofdm.false_alarm_cnt);
- bad_plcp_cck = le32_to_cpu(statistics->cck.plcp_err);
- bad_plcp_ofdm = le32_to_cpu(statistics->ofdm.plcp_err);
+ fa_cck = le32_to_cpu(cck->false_alarm_cnt);
+ fa_ofdm = le32_to_cpu(ofdm->false_alarm_cnt);
+ bad_plcp_cck = le32_to_cpu(cck->plcp_err);
+ bad_plcp_ofdm = le32_to_cpu(ofdm->plcp_err);
statis.beacon_silence_rssi_a =
- le32_to_cpu(statistics->general.beacon_silence_rssi_a);
+ le32_to_cpu(rx_info->beacon_silence_rssi_a);
statis.beacon_silence_rssi_b =
- le32_to_cpu(statistics->general.beacon_silence_rssi_b);
+ le32_to_cpu(rx_info->beacon_silence_rssi_b);
statis.beacon_silence_rssi_c =
- le32_to_cpu(statistics->general.beacon_silence_rssi_c);
+ le32_to_cpu(rx_info->beacon_silence_rssi_c);
statis.beacon_energy_a =
- le32_to_cpu(statistics->general.beacon_energy_a);
+ le32_to_cpu(rx_info->beacon_energy_a);
statis.beacon_energy_b =
- le32_to_cpu(statistics->general.beacon_energy_b);
+ le32_to_cpu(rx_info->beacon_energy_b);
statis.beacon_energy_c =
- le32_to_cpu(statistics->general.beacon_energy_c);
+ le32_to_cpu(rx_info->beacon_energy_c);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -728,8 +737,7 @@ static inline u8 find_first_chain(u8 mask)
* 1) Which antennas are connected.
* 2) Differential rx gain settings to balance the 3 receivers.
*/
-void iwl_chain_noise_calibration(struct iwl_priv *priv,
- struct iwl_notif_statistics *stat_resp)
+void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
{
struct iwl_chain_noise_data *data = NULL;
@@ -753,7 +761,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
u32 active_chains = 0;
u8 num_tx_chains;
unsigned long flags;
- struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general);
+ struct statistics_rx_non_phy *rx_info;
u8 first_chain;
if (priv->disable_chain_noise_cal)
@@ -772,6 +780,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
}
spin_lock_irqsave(&priv->lock, flags);
+ if (priv->cfg->bt_statistics) {
+ rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)->
+ rx.general.common);
+ } else {
+ rx_info = &(((struct iwl_notif_statistics *)stat_resp)->
+ rx.general);
+ }
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
spin_unlock_irqrestore(&priv->lock, flags);
@@ -780,8 +795,19 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
rxon_band24 = !!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK);
rxon_chnum = le16_to_cpu(priv->staging_rxon.channel);
- stat_band24 = !!(stat_resp->flag & STATISTICS_REPLY_FLG_BAND_24G_MSK);
- stat_chnum = le32_to_cpu(stat_resp->flag) >> 16;
+ if (priv->cfg->bt_statistics) {
+ stat_band24 = !!(((struct iwl_bt_notif_statistics *)
+ stat_resp)->flag &
+ STATISTICS_REPLY_FLG_BAND_24G_MSK);
+ stat_chnum = le32_to_cpu(((struct iwl_bt_notif_statistics *)
+ stat_resp)->flag) >> 16;
+ } else {
+ stat_band24 = !!(((struct iwl_notif_statistics *)
+ stat_resp)->flag &
+ STATISTICS_REPLY_FLG_BAND_24G_MSK);
+ stat_chnum = le32_to_cpu(((struct iwl_notif_statistics *)
+ stat_resp)->flag) >> 16;
+ }
/* Make sure we accumulate data for just the associated channel
* (even if scanning). */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
index 5e5c5122fb15..f052c6d09b37 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
@@ -31,21 +31,24 @@
static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
{
int p = 0;
+ u32 flag;
- p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
- le32_to_cpu(priv->_agn.statistics.flag));
- if (le32_to_cpu(priv->_agn.statistics.flag) &
- UCODE_STATISTICS_CLEAR_MSK)
+ if (priv->cfg->bt_statistics)
+ flag = le32_to_cpu(priv->_agn.statistics_bt.flag);
+ else
+ flag = le32_to_cpu(priv->_agn.statistics.flag);
+
+ p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);
+ if (flag & UCODE_STATISTICS_CLEAR_MSK)
p += scnprintf(buf + p, bufsz - p,
- "\tStatistics have been cleared\n");
+ "\tStatistics have been cleared\n");
p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
- (le32_to_cpu(priv->_agn.statistics.flag) &
- UCODE_STATISTICS_FREQUENCY_MSK)
- ? "2.4 GHz" : "5.2 GHz");
+ (flag & UCODE_STATISTICS_FREQUENCY_MSK)
+ ? "2.4 GHz" : "5.2 GHz");
p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
- (le32_to_cpu(priv->_agn.statistics.flag) &
- UCODE_STATISTICS_NARROW_BAND_MSK)
- ? "enabled" : "disabled");
+ (flag & UCODE_STATISTICS_NARROW_BAND_MSK)
+ ? "enabled" : "disabled");
+
return p;
}
@@ -79,22 +82,43 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
- ofdm = &priv->_agn.statistics.rx.ofdm;
- cck = &priv->_agn.statistics.rx.cck;
- general = &priv->_agn.statistics.rx.general;
- ht = &priv->_agn.statistics.rx.ofdm_ht;
- accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm;
- accum_cck = &priv->_agn.accum_statistics.rx.cck;
- accum_general = &priv->_agn.accum_statistics.rx.general;
- accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht;
- delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm;
- delta_cck = &priv->_agn.delta_statistics.rx.cck;
- delta_general = &priv->_agn.delta_statistics.rx.general;
- delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht;
- max_ofdm = &priv->_agn.max_delta.rx.ofdm;
- max_cck = &priv->_agn.max_delta.rx.cck;
- max_general = &priv->_agn.max_delta.rx.general;
- max_ht = &priv->_agn.max_delta.rx.ofdm_ht;
+ if (priv->cfg->bt_statistics) {
+ ofdm = &priv->_agn.statistics_bt.rx.ofdm;
+ cck = &priv->_agn.statistics_bt.rx.cck;
+ general = &priv->_agn.statistics_bt.rx.general.common;
+ ht = &priv->_agn.statistics_bt.rx.ofdm_ht;
+ accum_ofdm = &priv->_agn.accum_statistics_bt.rx.ofdm;
+ accum_cck = &priv->_agn.accum_statistics_bt.rx.cck;
+ accum_general =
+ &priv->_agn.accum_statistics_bt.rx.general.common;
+ accum_ht = &priv->_agn.accum_statistics_bt.rx.ofdm_ht;
+ delta_ofdm = &priv->_agn.delta_statistics_bt.rx.ofdm;
+ delta_cck = &priv->_agn.delta_statistics_bt.rx.cck;
+ delta_general =
+ &priv->_agn.delta_statistics_bt.rx.general.common;
+ delta_ht = &priv->_agn.delta_statistics_bt.rx.ofdm_ht;
+ max_ofdm = &priv->_agn.max_delta_bt.rx.ofdm;
+ max_cck = &priv->_agn.max_delta_bt.rx.cck;
+ max_general = &priv->_agn.max_delta_bt.rx.general.common;
+ max_ht = &priv->_agn.max_delta_bt.rx.ofdm_ht;
+ } else {
+ ofdm = &priv->_agn.statistics.rx.ofdm;
+ cck = &priv->_agn.statistics.rx.cck;
+ general = &priv->_agn.statistics.rx.general;
+ ht = &priv->_agn.statistics.rx.ofdm_ht;
+ accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm;
+ accum_cck = &priv->_agn.accum_statistics.rx.cck;
+ accum_general = &priv->_agn.accum_statistics.rx.general;
+ accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht;
+ delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm;
+ delta_cck = &priv->_agn.delta_statistics.rx.cck;
+ delta_general = &priv->_agn.delta_statistics.rx.general;
+ delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht;
+ max_ofdm = &priv->_agn.max_delta.rx.ofdm;
+ max_cck = &priv->_agn.max_delta.rx.cck;
+ max_general = &priv->_agn.max_delta.rx.general;
+ max_ht = &priv->_agn.max_delta.rx.ofdm_ht;
+ }
pos += iwl_statistics_flag(priv, buf, bufsz);
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
@@ -560,10 +584,18 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file,
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
- tx = &priv->_agn.statistics.tx;
- accum_tx = &priv->_agn.accum_statistics.tx;
- delta_tx = &priv->_agn.delta_statistics.tx;
- max_tx = &priv->_agn.max_delta.tx;
+ if (priv->cfg->bt_statistics) {
+ tx = &priv->_agn.statistics_bt.tx;
+ accum_tx = &priv->_agn.accum_statistics_bt.tx;
+ delta_tx = &priv->_agn.delta_statistics_bt.tx;
+ max_tx = &priv->_agn.max_delta_bt.tx;
+ } else {
+ tx = &priv->_agn.statistics.tx;
+ accum_tx = &priv->_agn.accum_statistics.tx;
+ delta_tx = &priv->_agn.delta_statistics.tx;
+ max_tx = &priv->_agn.max_delta.tx;
+ }
+
pos += iwl_statistics_flag(priv, buf, bufsz);
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
"acumulative delta max\n",
@@ -759,8 +791,8 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
char *buf;
int bufsz = sizeof(struct statistics_general) * 10 + 300;
ssize_t ret;
- struct statistics_general *general, *accum_general;
- struct statistics_general *delta_general, *max_general;
+ struct statistics_general_common *general, *accum_general;
+ struct statistics_general_common *delta_general, *max_general;
struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
struct statistics_div *div, *accum_div, *delta_div, *max_div;
@@ -777,18 +809,34 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
- general = &priv->_agn.statistics.general;
- dbg = &priv->_agn.statistics.general.dbg;
- div = &priv->_agn.statistics.general.div;
- accum_general = &priv->_agn.accum_statistics.general;
- delta_general = &priv->_agn.delta_statistics.general;
- max_general = &priv->_agn.max_delta.general;
- accum_dbg = &priv->_agn.accum_statistics.general.dbg;
- delta_dbg = &priv->_agn.delta_statistics.general.dbg;
- max_dbg = &priv->_agn.max_delta.general.dbg;
- accum_div = &priv->_agn.accum_statistics.general.div;
- delta_div = &priv->_agn.delta_statistics.general.div;
- max_div = &priv->_agn.max_delta.general.div;
+ if (priv->cfg->bt_statistics) {
+ general = &priv->_agn.statistics_bt.general.common;
+ dbg = &priv->_agn.statistics_bt.general.common.dbg;
+ div = &priv->_agn.statistics_bt.general.common.div;
+ accum_general = &priv->_agn.accum_statistics_bt.general.common;
+ accum_dbg = &priv->_agn.accum_statistics_bt.general.common.dbg;
+ accum_div = &priv->_agn.accum_statistics_bt.general.common.div;
+ delta_general = &priv->_agn.delta_statistics_bt.general.common;
+ max_general = &priv->_agn.max_delta_bt.general.common;
+ delta_dbg = &priv->_agn.delta_statistics_bt.general.common.dbg;
+ max_dbg = &priv->_agn.max_delta_bt.general.common.dbg;
+ delta_div = &priv->_agn.delta_statistics_bt.general.common.div;
+ max_div = &priv->_agn.max_delta_bt.general.common.div;
+ } else {
+ general = &priv->_agn.statistics.general.common;
+ dbg = &priv->_agn.statistics.general.common.dbg;
+ div = &priv->_agn.statistics.general.common.div;
+ accum_general = &priv->_agn.accum_statistics.general.common;
+ accum_dbg = &priv->_agn.accum_statistics.general.common.dbg;
+ accum_div = &priv->_agn.accum_statistics.general.common.div;
+ delta_general = &priv->_agn.delta_statistics.general.common;
+ max_general = &priv->_agn.max_delta.general.common;
+ delta_dbg = &priv->_agn.delta_statistics.general.common.dbg;
+ max_dbg = &priv->_agn.max_delta.general.common.dbg;
+ delta_div = &priv->_agn.delta_statistics.general.common.div;
+ max_div = &priv->_agn.max_delta.general.common.div;
+ }
+
pos += iwl_statistics_flag(priv, buf, bufsz);
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
"acumulative delta max\n",
@@ -876,3 +924,90 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
kfree(buf);
return ret;
}
+
+ssize_t iwl_ucode_bt_stats_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int pos = 0;
+ char *buf;
+ int bufsz = (sizeof(struct statistics_bt_activity) * 24) + 200;
+ ssize_t ret;
+ struct statistics_bt_activity *bt, *accum_bt;
+
+ if (!iwl_is_alive(priv))
+ return -EAGAIN;
+
+ /* make request to uCode to retrieve statistics information */
+ mutex_lock(&priv->mutex);
+ ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
+ mutex_unlock(&priv->mutex);
+
+ if (ret) {
+ IWL_ERR(priv,
+ "Error sending statistics request: %zd\n", ret);
+ return -EAGAIN;
+ }
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf) {
+ IWL_ERR(priv, "Can not allocate Buffer\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * the statistic information display here is based on
+ * the last statistics notification from uCode
+ * might not reflect the current uCode activity
+ */
+ bt = &priv->_agn.statistics_bt.general.activity;
+ accum_bt = &priv->_agn.accum_statistics_bt.general.activity;
+
+ pos += iwl_statistics_flag(priv, buf, bufsz);
+ pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\t\t\tcurrent\t\t\taccumulative\n");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "hi_priority_tx_req_cnt:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(bt->hi_priority_tx_req_cnt),
+ accum_bt->hi_priority_tx_req_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "hi_priority_tx_denied_cnt:\t%u\t\t\t%u\n",
+ le32_to_cpu(bt->hi_priority_tx_denied_cnt),
+ accum_bt->hi_priority_tx_denied_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "lo_priority_tx_req_cnt:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(bt->lo_priority_tx_req_cnt),
+ accum_bt->lo_priority_tx_req_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n",
+ le32_to_cpu(bt->lo_priority_tx_denied_cnt),
+ accum_bt->lo_priority_tx_denied_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "hi_priority_rx_req_cnt:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(bt->hi_priority_rx_req_cnt),
+ accum_bt->hi_priority_rx_req_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "hi_priority_rx_denied_cnt:\t%u\t\t\t%u\n",
+ le32_to_cpu(bt->hi_priority_rx_denied_cnt),
+ accum_bt->hi_priority_rx_denied_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "lo_priority_rx_req_cnt:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(bt->lo_priority_rx_req_cnt),
+ accum_bt->lo_priority_rx_req_cnt);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n",
+ le32_to_cpu(bt->lo_priority_rx_denied_cnt),
+ accum_bt->lo_priority_rx_denied_cnt);
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "(rx)num_bt_kills:\t\t%u\t\t\t%u\n",
+ le32_to_cpu(priv->_agn.statistics_bt.rx.
+ general.num_bt_kills),
+ priv->_agn.accum_statistics_bt.rx.
+ general.num_bt_kills);
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h
index 59b1f25f0d85..bbdce5913ac7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h
@@ -37,6 +37,8 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
+ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos);
#else
static ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -53,4 +55,9 @@ static ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user
{
return 0;
}
+static ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return 0;
+}
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
index f06d1feedf81..a7216dda9786 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
@@ -164,7 +164,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,
memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD;
+ cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_gain_cmd;
cmd.hdr.first_group = 0;
cmd.hdr.groups_num = 1;
cmd.hdr.data_valid = 1;
@@ -197,7 +197,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
data->beacon_count = 0;
memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD;
+ cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_reset_cmd;
cmd.hdr.first_group = 0;
cmd.hdr.groups_num = 1;
cmd.hdr.data_valid = 1;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 74623e0d535f..a1b6d202d57c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -364,7 +364,7 @@ void iwlagn_temperature(struct iwl_priv *priv)
{
/* store temperature from statistics (in Celsius) */
priv->temperature =
- le32_to_cpu(priv->_agn.statistics.general.temperature);
+ le32_to_cpu(priv->_agn.statistics.general.common.temperature);
iwl_tt_handler(priv);
}
@@ -1234,7 +1234,10 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
spin_lock_irqsave(&priv->lock, flags);
- interval = vif ? vif->bss_conf.beacon_int : 0;
+ if (priv->is_internal_short_scan)
+ interval = 0;
+ else
+ interval = vif->bss_conf.beacon_int;
spin_unlock_irqrestore(&priv->lock, flags);
scan->suspend_time = 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index d54edc326f81..9490eced1198 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -67,17 +67,22 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
* exactly when to expect beacons, therefore only when we're associated. */
static void iwl_rx_calc_noise(struct iwl_priv *priv)
{
- struct statistics_rx_non_phy *rx_info
- = &(priv->_agn.statistics.rx.general);
+ struct statistics_rx_non_phy *rx_info;
int num_active_rx = 0;
int total_silence = 0;
- int bcn_silence_a =
+ int bcn_silence_a, bcn_silence_b, bcn_silence_c;
+ int last_rx_noise;
+
+ if (priv->cfg->bt_statistics)
+ rx_info = &(priv->_agn.statistics_bt.rx.general.common);
+ else
+ rx_info = &(priv->_agn.statistics.rx.general);
+ bcn_silence_a =
le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
- int bcn_silence_b =
+ bcn_silence_b =
le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
- int bcn_silence_c =
+ bcn_silence_c =
le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
- int last_rx_noise;
if (bcn_silence_a) {
total_silence += bcn_silence_a;
@@ -112,17 +117,35 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv)
static void iwl_accumulative_statistics(struct iwl_priv *priv,
__le32 *stats)
{
- int i;
+ int i, size;
__le32 *prev_stats;
u32 *accum_stats;
u32 *delta, *max_delta;
+ struct statistics_general_common *general, *accum_general;
+ struct statistics_tx *tx, *accum_tx;
- prev_stats = (__le32 *)&priv->_agn.statistics;
- accum_stats = (u32 *)&priv->_agn.accum_statistics;
- delta = (u32 *)&priv->_agn.delta_statistics;
- max_delta = (u32 *)&priv->_agn.max_delta;
-
- for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics);
+ if (priv->cfg->bt_statistics) {
+ prev_stats = (__le32 *)&priv->_agn.statistics_bt;
+ accum_stats = (u32 *)&priv->_agn.accum_statistics_bt;
+ size = sizeof(struct iwl_bt_notif_statistics);
+ general = &priv->_agn.statistics_bt.general.common;
+ accum_general = &priv->_agn.accum_statistics_bt.general.common;
+ tx = &priv->_agn.statistics_bt.tx;
+ accum_tx = &priv->_agn.accum_statistics_bt.tx;
+ delta = (u32 *)&priv->_agn.delta_statistics_bt;
+ max_delta = (u32 *)&priv->_agn.max_delta_bt;
+ } else {
+ prev_stats = (__le32 *)&priv->_agn.statistics;
+ accum_stats = (u32 *)&priv->_agn.accum_statistics;
+ size = sizeof(struct iwl_notif_statistics);
+ general = &priv->_agn.statistics.general.common;
+ accum_general = &priv->_agn.accum_statistics.general.common;
+ tx = &priv->_agn.statistics.tx;
+ accum_tx = &priv->_agn.accum_statistics.tx;
+ delta = (u32 *)&priv->_agn.delta_statistics;
+ max_delta = (u32 *)&priv->_agn.max_delta;
+ }
+ for (i = sizeof(__le32); i < size;
i += sizeof(__le32), stats++, prev_stats++, delta++,
max_delta++, accum_stats++) {
if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
@@ -135,18 +158,12 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,
}
/* reset accumulative statistics for "no-counter" type statistics */
- priv->_agn.accum_statistics.general.temperature =
- priv->_agn.statistics.general.temperature;
- priv->_agn.accum_statistics.general.temperature_m =
- priv->_agn.statistics.general.temperature_m;
- priv->_agn.accum_statistics.general.ttl_timestamp =
- priv->_agn.statistics.general.ttl_timestamp;
- priv->_agn.accum_statistics.tx.tx_power.ant_a =
- priv->_agn.statistics.tx.tx_power.ant_a;
- priv->_agn.accum_statistics.tx.tx_power.ant_b =
- priv->_agn.statistics.tx.tx_power.ant_b;
- priv->_agn.accum_statistics.tx.tx_power.ant_c =
- priv->_agn.statistics.tx.tx_power.ant_c;
+ accum_general->temperature = general->temperature;
+ accum_general->temperature_m = general->temperature_m;
+ accum_general->ttl_timestamp = general->ttl_timestamp;
+ accum_tx->tx_power.ant_a = tx->tx_power.ant_a;
+ accum_tx->tx_power.ant_b = tx->tx_power.ant_b;
+ accum_tx->tx_power.ant_c = tx->tx_power.ant_c;
}
#endif
@@ -185,11 +202,30 @@ bool iwl_good_plcp_health(struct iwl_priv *priv,
* by zero.
*/
if (plcp_msec) {
- combined_plcp_delta =
- (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) -
- le32_to_cpu(priv->_agn.statistics.rx.ofdm.plcp_err)) +
- (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) -
- le32_to_cpu(priv->_agn.statistics.rx.ofdm_ht.plcp_err));
+ struct statistics_rx_phy *ofdm;
+ struct statistics_rx_ht_phy *ofdm_ht;
+
+ if (priv->cfg->bt_statistics) {
+ ofdm = &pkt->u.stats_bt.rx.ofdm;
+ ofdm_ht = &pkt->u.stats_bt.rx.ofdm_ht;
+ combined_plcp_delta =
+ (le32_to_cpu(ofdm->plcp_err) -
+ le32_to_cpu(priv->_agn.statistics_bt.
+ rx.ofdm.plcp_err)) +
+ (le32_to_cpu(ofdm_ht->plcp_err) -
+ le32_to_cpu(priv->_agn.statistics_bt.
+ rx.ofdm_ht.plcp_err));
+ } else {
+ ofdm = &pkt->u.stats.rx.ofdm;
+ ofdm_ht = &pkt->u.stats.rx.ofdm_ht;
+ combined_plcp_delta =
+ (le32_to_cpu(ofdm->plcp_err) -
+ le32_to_cpu(priv->_agn.statistics.
+ rx.ofdm.plcp_err)) +
+ (le32_to_cpu(ofdm_ht->plcp_err) -
+ le32_to_cpu(priv->_agn.statistics.
+ rx.ofdm_ht.plcp_err));
+ }
if ((combined_plcp_delta > 0) &&
((combined_plcp_delta * 100) / plcp_msec) >
@@ -206,15 +242,14 @@ bool iwl_good_plcp_health(struct iwl_priv *priv,
* plcp_msec
*/
IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
- "%u, %u, %u, %u, %d, %u mSecs\n",
- priv->cfg->plcp_delta_threshold,
- le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
- le32_to_cpu(
- priv->_agn.statistics.rx.ofdm.plcp_err),
- le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err),
- le32_to_cpu(
- priv->_agn.statistics.rx.ofdm_ht.plcp_err),
- combined_plcp_delta, plcp_msec);
+ "%u, %u, %u, %u, %d, %u mSecs\n",
+ priv->cfg->plcp_delta_threshold,
+ le32_to_cpu(ofdm->plcp_err),
+ le32_to_cpu(ofdm->plcp_err),
+ le32_to_cpu(ofdm_ht->plcp_err),
+ le32_to_cpu(ofdm_ht->plcp_err),
+ combined_plcp_delta, plcp_msec);
+
rc = false;
}
}
@@ -227,24 +262,50 @@ void iwl_rx_statistics(struct iwl_priv *priv,
int change;
struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ if (priv->cfg->bt_statistics) {
+ IWL_DEBUG_RX(priv,
+ "Statistics notification received (%d vs %d).\n",
+ (int)sizeof(struct iwl_bt_notif_statistics),
+ le32_to_cpu(pkt->len_n_flags) &
+ FH_RSCSR_FRAME_SIZE_MSK);
- IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
- (int)sizeof(priv->_agn.statistics),
- le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
+ change = ((priv->_agn.statistics_bt.general.common.temperature !=
+ pkt->u.stats_bt.general.common.temperature) ||
+ ((priv->_agn.statistics_bt.flag &
+ STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
+ (pkt->u.stats_bt.flag &
+ STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt);
+#endif
- change = ((priv->_agn.statistics.general.temperature !=
- pkt->u.stats.general.temperature) ||
- ((priv->_agn.statistics.flag &
- STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
- (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
+ } else {
+ IWL_DEBUG_RX(priv,
+ "Statistics notification received (%d vs %d).\n",
+ (int)sizeof(struct iwl_notif_statistics),
+ le32_to_cpu(pkt->len_n_flags) &
+ FH_RSCSR_FRAME_SIZE_MSK);
+ change = ((priv->_agn.statistics.general.common.temperature !=
+ pkt->u.stats.general.common.temperature) ||
+ ((priv->_agn.statistics.flag &
+ STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
+ (pkt->u.stats.flag &
+ STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
#ifdef CONFIG_IWLWIFI_DEBUGFS
- iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
+ iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
#endif
+
+ }
+
iwl_recover_from_statistics(priv, pkt);
- memcpy(&priv->_agn.statistics, &pkt->u.stats,
- sizeof(priv->_agn.statistics));
+ if (priv->cfg->bt_statistics)
+ memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt,
+ sizeof(priv->_agn.statistics_bt));
+ else
+ memcpy(&priv->_agn.statistics, &pkt->u.stats,
+ sizeof(priv->_agn.statistics));
set_bit(STATUS_STATISTICS, &priv->status);
@@ -277,6 +338,12 @@ void iwl_reply_statistics(struct iwl_priv *priv,
sizeof(struct iwl_notif_statistics));
memset(&priv->_agn.max_delta, 0,
sizeof(struct iwl_notif_statistics));
+ memset(&priv->_agn.accum_statistics_bt, 0,
+ sizeof(struct iwl_bt_notif_statistics));
+ memset(&priv->_agn.delta_statistics_bt, 0,
+ sizeof(struct iwl_bt_notif_statistics));
+ memset(&priv->_agn.max_delta_bt, 0,
+ sizeof(struct iwl_bt_notif_statistics));
#endif
IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 7391c63fb024..35337b1e7cac 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -27,6 +27,8 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -292,9 +294,7 @@ static u32 iwl_fill_beacon_frame(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,
int left)
{
- if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
- ((priv->iw_mode != NL80211_IFTYPE_ADHOC) &&
- (priv->iw_mode != NL80211_IFTYPE_AP)))
+ if (!priv->ibss_beacon)
return 0;
if (priv->ibss_beacon->len > left)
@@ -1692,6 +1692,7 @@ static void iwl_nic_start(struct iwl_priv *priv)
struct iwlagn_ucode_capabilities {
u32 max_probe_length;
+ u32 standard_phy_calibration_size;
};
static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
@@ -1827,7 +1828,6 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
u32 tlv_len;
enum iwl_ucode_tlv_type tlv_type;
const u8 *tlv_data;
- int ret = 0;
if (len < sizeof(*ucode)) {
IWL_ERR(priv, "uCode has invalid length: %zd\n", len);
@@ -1863,9 +1863,8 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
len -= sizeof(*ucode);
- while (len >= sizeof(*tlv) && !ret) {
+ while (len >= sizeof(*tlv)) {
u16 tlv_alt;
- u32 fixed_tlv_size = 4;
len -= sizeof(*tlv);
tlv = (void *)data;
@@ -1913,59 +1912,57 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
pieces->boot_size = tlv_len;
break;
case IWL_UCODE_TLV_PROBE_MAX_LEN:
- if (tlv_len != fixed_tlv_size)
- ret = -EINVAL;
- else
- capa->max_probe_length =
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ capa->max_probe_length =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
- if (tlv_len != fixed_tlv_size)
- ret = -EINVAL;
- else
- pieces->init_evtlog_ptr =
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ pieces->init_evtlog_ptr =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_INIT_EVTLOG_SIZE:
- if (tlv_len != fixed_tlv_size)
- ret = -EINVAL;
- else
- pieces->init_evtlog_size =
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ pieces->init_evtlog_size =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_INIT_ERRLOG_PTR:
- if (tlv_len != fixed_tlv_size)
- ret = -EINVAL;
- else
- pieces->init_errlog_ptr =
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ pieces->init_errlog_ptr =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_RUNT_EVTLOG_PTR:
- if (tlv_len != fixed_tlv_size)
- ret = -EINVAL;
- else
- pieces->inst_evtlog_ptr =
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ pieces->inst_evtlog_ptr =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE:
- if (tlv_len != fixed_tlv_size)
- ret = -EINVAL;
- else
- pieces->inst_evtlog_size =
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ pieces->inst_evtlog_size =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_RUNT_ERRLOG_PTR:
- if (tlv_len != fixed_tlv_size)
- ret = -EINVAL;
- else
- pieces->inst_errlog_ptr =
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ pieces->inst_errlog_ptr =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_ENHANCE_SENS_TBL:
if (tlv_len)
- ret = -EINVAL;
- else
- priv->enhance_sensitivity_table = true;
+ goto invalid_tlv_len;
+ priv->enhance_sensitivity_table = true;
+ break;
+ case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE:
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ capa->standard_phy_calibration_size =
+ le32_to_cpup((__le32 *)tlv_data);
break;
default:
IWL_WARN(priv, "unknown TLV: %d\n", tlv_type);
@@ -1976,14 +1973,16 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
if (len) {
IWL_ERR(priv, "invalid TLV after parsing: %zd\n", len);
iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)data, len);
- ret = -EINVAL;
- } else if (ret) {
- IWL_ERR(priv, "TLV %d has invalid size: %u\n",
- tlv_type, tlv_len);
- iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)tlv_data, tlv_len);
+ return -EINVAL;
}
- return ret;
+ return 0;
+
+ invalid_tlv_len:
+ IWL_ERR(priv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len);
+ iwl_print_hex_dump(priv, IWL_DL_FW, tlv_data, tlv_len);
+
+ return -EINVAL;
}
/**
@@ -2005,6 +2004,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
u32 build;
struct iwlagn_ucode_capabilities ucode_capa = {
.max_probe_length = 200,
+ .standard_phy_calibration_size =
+ IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE,
};
memset(&pieces, 0, sizeof(pieces));
@@ -2226,6 +2227,20 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
pieces.boot_size);
memcpy(priv->ucode_boot.v_addr, pieces.boot, pieces.boot_size);
+ /*
+ * figure out the offset of chain noise reset and gain commands
+ * base on the size of standard phy calibration commands table size
+ */
+ if (ucode_capa.standard_phy_calibration_size >
+ IWL_MAX_PHY_CALIBRATE_TBL_SIZE)
+ ucode_capa.standard_phy_calibration_size =
+ IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE;
+
+ priv->_agn.phy_calib_chain_noise_reset_cmd =
+ ucode_capa.standard_phy_calibration_size;
+ priv->_agn.phy_calib_chain_noise_gain_cmd =
+ ucode_capa.standard_phy_calibration_size + 1;
+
/**************************************************
* This is still part of probe() in a sense...
*
@@ -3008,9 +3023,17 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
}
if (priv->start_calib) {
- iwl_chain_noise_calibration(priv, &priv->_agn.statistics);
-
- iwl_sensitivity_calibration(priv, &priv->_agn.statistics);
+ if (priv->cfg->bt_statistics) {
+ iwl_chain_noise_calibration(priv,
+ (void *)&priv->_agn.statistics_bt);
+ iwl_sensitivity_calibration(priv,
+ (void *)&priv->_agn.statistics_bt);
+ } else {
+ iwl_chain_noise_calibration(priv,
+ (void *)&priv->_agn.statistics);
+ iwl_sensitivity_calibration(priv,
+ (void *)&priv->_agn.statistics);
+ }
}
mutex_unlock(&priv->mutex);
@@ -3909,8 +3932,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct ieee80211_hw *hw;
struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
unsigned long flags;
- u16 pci_cmd;
- u8 perm_addr[ETH_ALEN];
+ u16 pci_cmd, num_mac;
/************************
* 1. Allocating HW data
@@ -4028,9 +4050,17 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_free_eeprom;
/* extract MAC Address */
- iwl_eeprom_get_mac(priv, perm_addr);
- IWL_DEBUG_INFO(priv, "MAC address: %pM\n", perm_addr);
- SET_IEEE80211_PERM_ADDR(priv->hw, perm_addr);
+ iwl_eeprom_get_mac(priv, priv->addresses[0].addr);
+ IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr);
+ priv->hw->wiphy->addresses = priv->addresses;
+ priv->hw->wiphy->n_addresses = 1;
+ num_mac = iwl_eeprom_query16(priv, EEPROM_NUM_MAC_ADDRESS);
+ if (num_mac > 1) {
+ memcpy(priv->addresses[1].addr, priv->addresses[0].addr,
+ ETH_ALEN);
+ priv->addresses[1].addr[5]++;
+ priv->hw->wiphy->n_addresses++;
+ }
/************************
* 5. Setup HW constants
@@ -4389,19 +4419,18 @@ static int __init iwl_init(void)
{
int ret;
- printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
- printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
+ pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
+ pr_info(DRV_COPYRIGHT "\n");
ret = iwlagn_rate_control_register();
if (ret) {
- printk(KERN_ERR DRV_NAME
- "Unable to register rate control algorithm: %d\n", ret);
+ pr_err("Unable to register rate control algorithm: %d\n", ret);
return ret;
}
ret = pci_register_driver(&iwl_driver);
if (ret) {
- printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n");
+ pr_err("Unable to initialize PCI module\n");
goto error_register;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h
index 2b7b1df83ba0..ba9523fbb300 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.h
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.h
@@ -66,10 +66,8 @@
#include "iwl-core.h"
#include "iwl-commands.h"
-void iwl_chain_noise_calibration(struct iwl_priv *priv,
- struct iwl_notif_statistics *stat_resp);
-void iwl_sensitivity_calibration(struct iwl_priv *priv,
- struct iwl_notif_statistics *resp);
+void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp);
+void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp);
void iwl_init_sensitivity(struct iwl_priv *priv);
void iwl_reset_run_time_calib(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index bd1ec933cd98..60725a5c1b69 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -964,8 +964,8 @@ struct iwl_qosparam_cmd {
#define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/
#define IWL_INVALID_STATION 255
-#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2);
-#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8);
+#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2)
+#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8)
#define STA_FLG_RTS_MIMO_PROT_MSK cpu_to_le32(1 << 17)
#define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18)
#define STA_FLG_MAX_AGG_SIZE_POS (19)
@@ -3127,6 +3127,13 @@ struct statistics_rx_non_phy {
__le32 beacon_energy_c;
} __packed;
+struct statistics_rx_non_phy_bt {
+ struct statistics_rx_non_phy common;
+ /* additional stats for bt */
+ __le32 num_bt_kills;
+ __le32 reserved[2];
+} __packed;
+
struct statistics_rx {
struct statistics_rx_phy ofdm;
struct statistics_rx_phy cck;
@@ -3134,6 +3141,13 @@ struct statistics_rx {
struct statistics_rx_ht_phy ofdm_ht;
} __packed;
+struct statistics_rx_bt {
+ struct statistics_rx_phy ofdm;
+ struct statistics_rx_phy cck;
+ struct statistics_rx_non_phy_bt general;
+ struct statistics_rx_ht_phy ofdm_ht;
+} __packed;
+
/**
* struct statistics_tx_power - current tx power
*
@@ -3196,7 +3210,7 @@ struct statistics_div {
__le32 reserved2;
} __packed;
-struct statistics_general {
+struct statistics_general_common {
__le32 temperature; /* radio temperature */
__le32 temperature_m; /* for 5000 and up, this is radio voltage */
struct statistics_dbg dbg;
@@ -3212,6 +3226,30 @@ struct statistics_general {
* in order to get out of bad PHY status
*/
__le32 num_of_sos_states;
+} __packed;
+
+struct statistics_bt_activity {
+ /* Tx statistics */
+ __le32 hi_priority_tx_req_cnt;
+ __le32 hi_priority_tx_denied_cnt;
+ __le32 lo_priority_tx_req_cnt;
+ __le32 lo_priority_tx_denied_cnt;
+ /* Rx statistics */
+ __le32 hi_priority_rx_req_cnt;
+ __le32 hi_priority_rx_denied_cnt;
+ __le32 lo_priority_rx_req_cnt;
+ __le32 lo_priority_rx_denied_cnt;
+} __packed;
+
+struct statistics_general {
+ struct statistics_general_common common;
+ __le32 reserved2;
+ __le32 reserved3;
+} __packed;
+
+struct statistics_general_bt {
+ struct statistics_general_common common;
+ struct statistics_bt_activity activity;
__le32 reserved2;
__le32 reserved3;
} __packed;
@@ -3273,6 +3311,12 @@ struct iwl_notif_statistics {
struct statistics_general general;
} __packed;
+struct iwl_bt_notif_statistics {
+ __le32 flag;
+ struct statistics_rx_bt rx;
+ struct statistics_tx tx;
+ struct statistics_general_bt general;
+} __packed;
/*
* MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command)
@@ -3616,10 +3660,10 @@ enum {
IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16,
IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
- IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD = 18,
- IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD = 19,
+ IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE = 18,
};
+#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE (253)
#define IWL_CALIB_INIT_CFG_ALL cpu_to_le32(0xffffffff)
@@ -3944,6 +3988,7 @@ struct iwl_rx_packet {
struct iwl_sleep_notification sleep_notif;
struct iwl_spectrum_resp spectrum;
struct iwl_notif_statistics stats;
+ struct iwl_bt_notif_statistics stats_bt;
struct iwl_compressed_ba_resp compressed_ba;
struct iwl_missed_beacon_notif missed_beacon;
struct iwl_coex_medium_notification coex_medium_notif;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 676d49df77ed..8024d44ce4bb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -170,7 +170,7 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
struct ieee80211_hw *hw =
ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops);
if (hw == NULL) {
- printk(KERN_ERR "%s: Can not allocate network device\n",
+ pr_err("%s: Can not allocate network device\n",
cfg->name);
goto out;
}
@@ -1748,6 +1748,37 @@ static inline void iwl_set_no_assoc(struct iwl_priv *priv)
iwlcore_commit_rxon(priv);
}
+static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+ struct iwl_priv *priv = hw->priv;
+ unsigned long flags;
+ __le64 timestamp;
+
+ IWL_DEBUG_MAC80211(priv, "enter\n");
+
+ if (!iwl_is_ready_rf(priv)) {
+ IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
+ return -EIO;
+ }
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (priv->ibss_beacon)
+ dev_kfree_skb(priv->ibss_beacon);
+
+ priv->ibss_beacon = skb;
+
+ timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
+ priv->timestamp = le64_to_cpu(timestamp);
+
+ IWL_DEBUG_MAC80211(priv, "leave\n");
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ priv->cfg->ops->lib->post_associate(priv, priv->vif);
+
+ return 0;
+}
+
void iwl_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
@@ -1914,38 +1945,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(iwl_bss_info_changed);
-int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
- struct iwl_priv *priv = hw->priv;
- unsigned long flags;
- __le64 timestamp;
-
- IWL_DEBUG_MAC80211(priv, "enter\n");
-
- if (!iwl_is_ready_rf(priv)) {
- IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
- return -EIO;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
-
- if (priv->ibss_beacon)
- dev_kfree_skb(priv->ibss_beacon);
-
- priv->ibss_beacon = skb;
-
- timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
- priv->timestamp = le64_to_cpu(timestamp);
-
- IWL_DEBUG_MAC80211(priv, "leave\n");
- spin_unlock_irqrestore(&priv->lock, flags);
-
- priv->cfg->ops->lib->post_associate(priv, priv->vif);
-
- return 0;
-}
-EXPORT_SYMBOL(iwl_mac_beacon_update);
-
static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
iwl_connection_init_rx_config(priv, vif);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index fcbba3d604de..e9d23f2f869d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -125,6 +125,8 @@ struct iwl_debugfs_ops {
size_t count, loff_t *ppos);
ssize_t (*general_stats_read)(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
+ ssize_t (*bt_stats_read)(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos);
};
struct iwl_temp_ops {
@@ -335,6 +337,7 @@ struct iwl_cfg {
u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
const bool need_dc_calib;
+ const bool bt_statistics;
};
/***************************
@@ -377,7 +380,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u32 changes);
-int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
int iwl_commit_rxon(struct iwl_priv *priv);
int iwl_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 7b25d1468358..e96a1bb12783 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -1519,6 +1519,16 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
return count;
}
+static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+
+ return priv->cfg->ops->lib->debugfs_ops.bt_stats_read(file,
+ user_buf, count, ppos);
+}
+
DEBUGFS_READ_FILE_OPS(rx_statistics);
DEBUGFS_READ_FILE_OPS(tx_statistics);
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
@@ -1541,6 +1551,7 @@ DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
DEBUGFS_READ_FILE_OPS(rxon_flags);
DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
DEBUGFS_WRITE_FILE_OPS(txfifo_flush);
+DEBUGFS_READ_FILE_OPS(ucode_bt_stats);
/*
* Create the debugfs files and directories
@@ -1608,6 +1619,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
if (priv->cfg->ucode_tracing)
DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
+ if (priv->cfg->bt_statistics)
+ DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
if (priv->cfg->sensitivity_calib_by_driver)
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index c4dba62b74af..f35bcad56e36 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -571,6 +571,7 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12,
IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13,
IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14,
+ IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15,
};
struct iwl_ucode_tlv {
@@ -1153,6 +1154,9 @@ struct iwl_priv {
u32 hw_wa_rev;
u8 rev_id;
+ /* EEPROM MAC addresses */
+ struct mac_address addresses[2];
+
/* uCode images, save to reload in case of failure */
int fw_index; /* firmware we're trying to load */
u32 ucode_ver; /* version of ucode, copy of
@@ -1321,11 +1325,23 @@ struct iwl_priv {
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
+ /*
+ * chain noise reset and gain commands are the
+ * two extra calibration commands follows the standard
+ * phy calibration commands
+ */
+ u8 phy_calib_chain_noise_reset_cmd;
+ u8 phy_calib_chain_noise_gain_cmd;
+
struct iwl_notif_statistics statistics;
+ struct iwl_bt_notif_statistics statistics_bt;
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct iwl_notif_statistics accum_statistics;
struct iwl_notif_statistics delta_statistics;
struct iwl_notif_statistics max_delta;
+ struct iwl_bt_notif_statistics accum_statistics_bt;
+ struct iwl_bt_notif_statistics delta_statistics_bt;
+ struct iwl_bt_notif_statistics max_delta_bt;
#endif
} _agn;
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 3452dfa7b571..a4772aff51fe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -402,6 +402,7 @@ struct iwl_eeprom_calib_info {
#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */
#define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */
#define EEPROM_3945_M_VERSION (2*0x4A) /* 1 bytes */
+#define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */
/* The following masks are to be applied on EEPROM_RADIO_CONFIG */
#define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 2a7c399fee1e..b0c6b0473901 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -429,11 +429,10 @@ void iwl_bg_scan_check(struct work_struct *data)
return;
mutex_lock(&priv->mutex);
- if (test_bit(STATUS_SCANNING, &priv->status) ||
- test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan completion watchdog resetting "
- "adapter (%dms)\n",
- jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
+ if (test_bit(STATUS_SCANNING, &priv->status) &&
+ !test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+ IWL_DEBUG_SCAN(priv, "Scan completion watchdog (%dms)\n",
+ jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
iwl_send_scan_abort(priv);
@@ -498,12 +497,11 @@ void iwl_bg_abort_scan(struct work_struct *work)
!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
return;
- mutex_lock(&priv->mutex);
-
- cancel_delayed_work_sync(&priv->scan_check);
- set_bit(STATUS_SCAN_ABORTING, &priv->status);
- iwl_send_scan_abort(priv);
+ cancel_delayed_work(&priv->scan_check);
+ mutex_lock(&priv->mutex);
+ if (test_bit(STATUS_SCAN_ABORTING, &priv->status))
+ iwl_send_scan_abort(priv);
mutex_unlock(&priv->mutex);
}
EXPORT_SYMBOL(iwl_bg_abort_scan);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 8eb347106902..d24eb47d3705 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -27,6 +27,8 @@
*
*****************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -311,9 +313,7 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
int left)
{
- if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
- ((priv->iw_mode != NL80211_IFTYPE_ADHOC) &&
- (priv->iw_mode != NL80211_IFTYPE_AP)))
+ if (!iwl_is_associated(priv) || !priv->ibss_beacon)
return 0;
if (priv->ibss_beacon->len > left)
@@ -2883,7 +2883,10 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
spin_lock_irqsave(&priv->lock, flags);
- interval = vif ? vif->bss_conf.beacon_int : 0;
+ if (priv->is_internal_short_scan)
+ interval = 0;
+ else
+ interval = vif->bss_conf.beacon_int;
spin_unlock_irqrestore(&priv->lock, flags);
scan->suspend_time = 0;
@@ -3932,7 +3935,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
* space for this driver's private structure */
hw = iwl_alloc_all(cfg, &iwl3945_hw_ops);
if (hw == NULL) {
- printk(KERN_ERR DRV_NAME "Can not allocate network device\n");
+ pr_err("Can not allocate network device\n");
err = -ENOMEM;
goto out;
}
@@ -4224,19 +4227,18 @@ static int __init iwl3945_init(void)
{
int ret;
- printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
- printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
+ pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
+ pr_info(DRV_COPYRIGHT "\n");
ret = iwl3945_rate_control_register();
if (ret) {
- printk(KERN_ERR DRV_NAME
- "Unable to register rate control algorithm: %d\n", ret);
+ pr_err("Unable to register rate control algorithm: %d\n", ret);
return ret;
}
ret = pci_register_driver(&iwl3945_driver);
if (ret) {
- printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n");
+ pr_err("Unable to initialize PCI module\n");
goto error_register;
}
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 7e0741608856..25f902760980 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -7,7 +7,6 @@
*/
#include <linux/slab.h>
-#include <linux/if_arp.h>
#include <linux/ieee80211.h>
#include <net/cfg80211.h>
#include <asm/unaligned.h>
@@ -1383,93 +1382,10 @@ static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev,
}
-
-/***************************************************************************
- * Monitor mode
- */
-
-/* like "struct cmd_ds_802_11_monitor_mode", but with cmd_header. Once we
- * get rid of WEXT, this should go into host.h */
-struct cmd_monitor_mode {
- struct cmd_header hdr;
-
- __le16 action;
- __le16 mode;
-} __packed;
-
-static int lbs_enable_monitor_mode(struct lbs_private *priv, int mode)
-{
- struct cmd_monitor_mode cmd;
- int ret;
-
- lbs_deb_enter(LBS_DEB_CFG80211);
-
- /*
- * cmd 98 00
- * size 0c 00
- * sequence xx xx
- * result 00 00
- * action 01 00 ACT_SET
- * enable 01 00
- */
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_SET);
- cmd.mode = cpu_to_le16(mode);
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_MONITOR_MODE, &cmd);
-
- if (ret == 0)
- priv->dev->type = ARPHRD_IEEE80211_RADIOTAP;
- else
- priv->dev->type = ARPHRD_ETHER;
-
- lbs_deb_leave(LBS_DEB_CFG80211);
- return ret;
-}
-
-
-
-
-
-
/***************************************************************************
* Get station
*/
-/*
- * Returns the signal or 0 in case of an error.
- */
-
-/* like "struct cmd_ds_802_11_rssi", but with cmd_header. Once we get rid
- * of WEXT, this should go into host.h */
-struct cmd_rssi {
- struct cmd_header hdr;
-
- __le16 n_or_snr;
- __le16 nf;
- __le16 avg_snr;
- __le16 avg_nf;
-} __packed;
-
-static int lbs_get_signal(struct lbs_private *priv, s8 *signal, s8 *noise)
-{
- struct cmd_rssi cmd;
- int ret;
-
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.n_or_snr = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
- ret = lbs_cmd_with_response(priv, CMD_802_11_RSSI, &cmd);
-
- if (ret == 0) {
- *signal = CAL_RSSI(le16_to_cpu(cmd.n_or_snr),
- le16_to_cpu(cmd.nf));
- *noise = CAL_NF(le16_to_cpu(cmd.nf));
- }
- return ret;
-}
-
-
static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,
u8 *mac, struct station_info *sinfo)
{
@@ -1490,7 +1406,7 @@ static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,
sinfo->rx_packets = priv->dev->stats.rx_packets;
/* Get current RSSI */
- ret = lbs_get_signal(priv, &signal, &noise);
+ ret = lbs_get_rssi(priv, &signal, &noise);
if (ret == 0) {
sinfo->signal = signal;
sinfo->filled |= STATION_INFO_SIGNAL;
@@ -1530,7 +1446,7 @@ static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev,
survey->channel = ieee80211_get_channel(wiphy,
ieee80211_channel_to_frequency(priv->channel));
- ret = lbs_get_signal(priv, &signal, &noise);
+ ret = lbs_get_rssi(priv, &signal, &noise);
if (ret == 0) {
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = noise;
@@ -1558,17 +1474,17 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev,
switch (type) {
case NL80211_IFTYPE_MONITOR:
- ret = lbs_enable_monitor_mode(priv, 1);
+ ret = lbs_set_monitor_mode(priv, 1);
break;
case NL80211_IFTYPE_STATION:
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
- ret = lbs_enable_monitor_mode(priv, 0);
+ ret = lbs_set_monitor_mode(priv, 0);
if (!ret)
ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1);
break;
case NL80211_IFTYPE_ADHOC:
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
- ret = lbs_enable_monitor_mode(priv, 0);
+ ret = lbs_set_monitor_mode(priv, 0);
if (!ret)
ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2);
break;
@@ -2063,113 +1979,20 @@ int lbs_cfg_register(struct lbs_private *priv)
return ret;
}
-/**
- * @brief This function sets DOMAIN INFO to FW
- * @param priv pointer to struct lbs_private
- * @return 0; -1
-*/
-static int lbs_11d_set_domain_info(struct lbs_private *priv)
-{
- int ret;
-
- ret = lbs_prepare_and_send_command(priv, CMD_802_11D_DOMAIN_INFO,
- CMD_ACT_SET,
- CMD_OPTION_WAITFORRSP, 0, NULL);
- if (ret)
- lbs_deb_11d("fail to dnld domain info\n");
-
- return ret;
-}
-
-static void lbs_send_domain_info_cmd_fw(struct wiphy *wiphy,
- struct regulatory_request *request)
-{
- u8 no_of_triplet = 0;
- u8 no_of_parsed_chan = 0;
- u8 first_channel = 0, next_chan = 0, max_pwr = 0;
- u8 i, flag = 0;
- enum ieee80211_band band;
- struct ieee80211_supported_band *sband;
- struct ieee80211_channel *ch;
- struct lbs_private *priv = wiphy_priv(wiphy);
- struct lbs_802_11d_domain_reg *domain_info = &priv->domain_reg;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CFG80211);
-
- /* Set country code */
- domain_info->country_code[0] = request->alpha2[0];
- domain_info->country_code[1] = request->alpha2[1];
- domain_info->country_code[2] = ' ';
-
- for (band = 0; band < IEEE80211_NUM_BANDS ; band++) {
-
- if (!wiphy->bands[band])
- continue;
-
- sband = wiphy->bands[band];
-
- for (i = 0; i < sband->n_channels ; i++) {
- ch = &sband->channels[i];
- if (ch->flags & IEEE80211_CHAN_DISABLED)
- continue;
-
- if (!flag) {
- flag = 1;
- next_chan = first_channel = (u32) ch->hw_value;
- max_pwr = ch->max_power;
- no_of_parsed_chan = 1;
- continue;
- }
-
- if (ch->hw_value == next_chan + 1 &&
- ch->max_power == max_pwr) {
- next_chan++;
- no_of_parsed_chan++;
- } else {
- domain_info->triplet[no_of_triplet]
- .chans.first_channel = first_channel;
- domain_info->triplet[no_of_triplet]
- .chans.num_channels = no_of_parsed_chan;
- domain_info->triplet[no_of_triplet]
- .chans.max_power = max_pwr;
- no_of_triplet++;
- flag = 0;
- }
- }
- if (flag) {
- domain_info->triplet[no_of_triplet]
- .chans.first_channel = first_channel;
- domain_info->triplet[no_of_triplet]
- .chans.num_channels = no_of_parsed_chan;
- domain_info->triplet[no_of_triplet]
- .chans.max_power = max_pwr;
- no_of_triplet++;
- }
- }
-
- domain_info->no_triplet = no_of_triplet;
-
- /* Set domain info */
- ret = lbs_11d_set_domain_info(priv);
- if (ret)
- lbs_pr_err("11D: error setting domain info in FW\n");
-
- lbs_deb_leave(LBS_DEB_CFG80211);
-}
-
int lbs_reg_notifier(struct wiphy *wiphy,
struct regulatory_request *request)
{
+ struct lbs_private *priv = wiphy_priv(wiphy);
+ int ret;
+
lbs_deb_enter_args(LBS_DEB_CFG80211, "cfg80211 regulatory domain "
"callback for domain %c%c\n", request->alpha2[0],
request->alpha2[1]);
- lbs_send_domain_info_cmd_fw(wiphy, request);
+ ret = lbs_set_11d_domain_info(priv, request, wiphy->bands);
lbs_deb_leave(LBS_DEB_CFG80211);
-
- return 0;
+ return ret;
}
void lbs_scan_deinit(struct lbs_private *priv)
diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h
index 756fb98f9f05..4f46bb744bee 100644
--- a/drivers/net/wireless/libertas/cfg.h
+++ b/drivers/net/wireless/libertas/cfg.h
@@ -13,12 +13,6 @@ void lbs_cfg_free(struct lbs_private *priv);
int lbs_reg_notifier(struct wiphy *wiphy,
struct regulatory_request *request);
-/* All of those are TODOs: */
-#define lbs_cmd_802_11_rssi(priv, cmdptr) (0)
-#define lbs_ret_802_11_rssi(priv, resp) (0)
-#define lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action) (0)
-#define lbs_ret_802_11_bcn_ctrl(priv, resp) (0)
-
void lbs_send_disconnect_notification(struct lbs_private *priv);
void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 749fbde4fd54..70745928f3f8 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -6,13 +6,14 @@
#include <linux/kfifo.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/if_arp.h>
#include "decl.h"
#include "cfg.h"
#include "cmd.h"
-
-static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
+#define CAL_NF(nf) ((s32)(-(s32)(nf)))
+#define CAL_RSSI(snr, nf) ((s32)((s32)(snr) + CAL_NF(nf)))
/**
* @brief Simple callback that copies response back into command
@@ -74,30 +75,6 @@ static u8 is_command_allowed_in_ps(u16 cmd)
}
/**
- * @brief This function checks if the command is allowed.
- *
- * @param priv A pointer to lbs_private structure
- * @return allowed or not allowed.
- */
-
-static int lbs_is_cmd_allowed(struct lbs_private *priv)
-{
- int ret = 1;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- if (!priv->is_auto_deep_sleep_enabled) {
- if (priv->is_deep_sleep) {
- lbs_deb_cmd("command not allowed in deep sleep\n");
- ret = 0;
- }
- }
-
- lbs_deb_leave(LBS_DEB_CMD);
- return ret;
-}
-
-/**
* @brief Updates the hardware details like MAC address and regulatory region
*
* @param priv A pointer to struct lbs_private structure
@@ -227,42 +204,49 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
}
EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);
-static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd,
- u16 cmd_action)
+/**
+ * @brief Sets the Power Save mode
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param cmd_action The Power Save operation (PS_MODE_ACTION_ENTER_PS or
+ * PS_MODE_ACTION_EXIT_PS)
+ * @param block Whether to block on a response or not
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block)
{
- struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
+ struct cmd_ds_802_11_ps_mode cmd;
+ int ret = 0;
lbs_deb_enter(LBS_DEB_CMD);
- cmd->command = cpu_to_le16(CMD_802_11_PS_MODE);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
- sizeof(struct cmd_header));
- psm->action = cpu_to_le16(cmd_action);
- psm->multipledtim = 0;
- switch (cmd_action) {
- case CMD_SUBCMD_ENTER_PS:
- lbs_deb_cmd("PS command:" "SubCode- Enter PS\n");
-
- psm->locallisteninterval = 0;
- psm->nullpktinterval = 0;
- psm->multipledtim =
- cpu_to_le16(MRVDRV_DEFAULT_MULTIPLE_DTIM);
- break;
-
- case CMD_SUBCMD_EXIT_PS:
- lbs_deb_cmd("PS command:" "SubCode- Exit PS\n");
- break;
-
- case CMD_SUBCMD_SLEEP_CONFIRMED:
- lbs_deb_cmd("PS command: SubCode- sleep confirm\n");
- break;
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(cmd_action);
- default:
- break;
+ if (cmd_action == PS_MODE_ACTION_ENTER_PS) {
+ lbs_deb_cmd("PS_MODE: action ENTER_PS\n");
+ cmd.multipledtim = cpu_to_le16(1); /* Default DTIM multiple */
+ } else if (cmd_action == PS_MODE_ACTION_EXIT_PS) {
+ lbs_deb_cmd("PS_MODE: action EXIT_PS\n");
+ } else {
+ /* We don't handle CONFIRM_SLEEP here because it needs to
+ * be fastpathed to the firmware.
+ */
+ lbs_deb_cmd("PS_MODE: unknown action 0x%X\n", cmd_action);
+ ret = -EOPNOTSUPP;
+ goto out;
}
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
+ if (block)
+ ret = lbs_cmd_with_response(priv, CMD_802_11_PS_MODE, &cmd);
+ else
+ lbs_cmd_async(priv, CMD_802_11_PS_MODE, &cmd.hdr, sizeof (cmd));
+
+out:
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
}
int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
@@ -576,23 +560,35 @@ int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)
return ret;
}
-static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
+/**
+ * @brief Enable or disable monitor mode (only implemented on OLPC usb8388 FW)
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param enable 1 to enable monitor mode, 0 to disable
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_set_monitor_mode(struct lbs_private *priv, int enable)
{
- struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor;
+ struct cmd_ds_802_11_monitor_mode cmd;
+ int ret;
- cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) +
- sizeof(struct cmd_header));
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_SET);
+ if (enable)
+ cmd.mode = cpu_to_le16(0x1);
+
+ lbs_deb_cmd("SET_MONITOR_MODE: %d\n", enable);
- monitor->action = cpu_to_le16(cmd_action);
- if (cmd_action == CMD_ACT_SET) {
- monitor->mode =
- cpu_to_le16((u16) (*(u32 *) pdata_buf));
+ ret = lbs_cmd_with_response(priv, CMD_802_11_MONITOR_MODE, &cmd);
+ if (ret == 0) {
+ priv->dev->type = enable ? ARPHRD_IEEE80211_RADIOTAP :
+ ARPHRD_ETHER;
}
- return 0;
+ lbs_deb_leave(LBS_DEB_CMD);
+ return ret;
}
/**
@@ -677,78 +673,242 @@ out:
return ret;
}
-static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
- u8 cmd_action, void *pdata_buf)
+/**
+ * @brief Get current RSSI and noise floor
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param rssi On successful return, signal level in mBm
+ *
+ * @return The channel on success, error on failure
+ */
+int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf)
{
- struct lbs_offset_value *offval;
+ struct cmd_ds_802_11_rssi cmd;
+ int ret = 0;
lbs_deb_enter(LBS_DEB_CMD);
- offval = (struct lbs_offset_value *)pdata_buf;
+ BUG_ON(rssi == NULL);
+ BUG_ON(nf == NULL);
- switch (le16_to_cpu(cmdptr->command)) {
- case CMD_MAC_REG_ACCESS:
- {
- struct cmd_ds_mac_reg_access *macreg;
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ /* Average SNR over last 8 beacons */
+ cmd.n_or_snr = cpu_to_le16(8);
- cmdptr->size =
- cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access)
- + sizeof(struct cmd_header));
- macreg =
- (struct cmd_ds_mac_reg_access *)&cmdptr->params.
- macreg;
+ ret = lbs_cmd_with_response(priv, CMD_802_11_RSSI, &cmd);
+ if (ret == 0) {
+ *nf = CAL_NF(le16_to_cpu(cmd.nf));
+ *rssi = CAL_RSSI(le16_to_cpu(cmd.n_or_snr), le16_to_cpu(cmd.nf));
+ }
- macreg->action = cpu_to_le16(cmd_action);
- macreg->offset = cpu_to_le16((u16) offval->offset);
- macreg->value = cpu_to_le32(offval->value);
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
+}
- break;
- }
+/**
+ * @brief Send regulatory and 802.11d domain information to the firmware
+ *
+ * @param priv pointer to struct lbs_private
+ * @param request cfg80211 regulatory request structure
+ * @param bands the device's supported bands and channels
+ *
+ * @return 0 on success, error code on failure
+*/
+int lbs_set_11d_domain_info(struct lbs_private *priv,
+ struct regulatory_request *request,
+ struct ieee80211_supported_band **bands)
+{
+ struct cmd_ds_802_11d_domain_info cmd;
+ struct mrvl_ie_domain_param_set *domain = &cmd.domain;
+ struct ieee80211_country_ie_triplet *t;
+ enum ieee80211_band band;
+ struct ieee80211_channel *ch;
+ u8 num_triplet = 0;
+ u8 num_parsed_chan = 0;
+ u8 first_channel = 0, next_chan = 0, max_pwr = 0;
+ u8 i, flag = 0;
+ size_t triplet_size;
+ int ret;
- case CMD_BBP_REG_ACCESS:
- {
- struct cmd_ds_bbp_reg_access *bbpreg;
+ lbs_deb_enter(LBS_DEB_11D);
- cmdptr->size =
- cpu_to_le16(sizeof
- (struct cmd_ds_bbp_reg_access)
- + sizeof(struct cmd_header));
- bbpreg =
- (struct cmd_ds_bbp_reg_access *)&cmdptr->params.
- bbpreg;
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_SET);
- bbpreg->action = cpu_to_le16(cmd_action);
- bbpreg->offset = cpu_to_le16((u16) offval->offset);
- bbpreg->value = (u8) offval->value;
+ lbs_deb_11d("Setting country code '%c%c'\n",
+ request->alpha2[0], request->alpha2[1]);
- break;
+ domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
+
+ /* Set country code */
+ domain->country_code[0] = request->alpha2[0];
+ domain->country_code[1] = request->alpha2[1];
+ domain->country_code[2] = ' ';
+
+ /* Now set up the channel triplets; firmware is somewhat picky here
+ * and doesn't validate channel numbers and spans; hence it would
+ * interpret a triplet of (36, 4, 20) as channels 36, 37, 38, 39. Since
+ * the last 3 aren't valid channels, the driver is responsible for
+ * splitting that up into 4 triplet pairs of (36, 1, 20) + (40, 1, 20)
+ * etc.
+ */
+ for (band = 0;
+ (band < IEEE80211_NUM_BANDS) && (num_triplet < MAX_11D_TRIPLETS);
+ band++) {
+
+ if (!bands[band])
+ continue;
+
+ for (i = 0;
+ (i < bands[band]->n_channels) && (num_triplet < MAX_11D_TRIPLETS);
+ i++) {
+ ch = &bands[band]->channels[i];
+ if (ch->flags & IEEE80211_CHAN_DISABLED)
+ continue;
+
+ if (!flag) {
+ flag = 1;
+ next_chan = first_channel = (u32) ch->hw_value;
+ max_pwr = ch->max_power;
+ num_parsed_chan = 1;
+ continue;
+ }
+
+ if ((ch->hw_value == next_chan + 1) &&
+ (ch->max_power == max_pwr)) {
+ /* Consolidate adjacent channels */
+ next_chan++;
+ num_parsed_chan++;
+ } else {
+ /* Add this triplet */
+ lbs_deb_11d("11D triplet (%d, %d, %d)\n",
+ first_channel, num_parsed_chan,
+ max_pwr);
+ t = &domain->triplet[num_triplet];
+ t->chans.first_channel = first_channel;
+ t->chans.num_channels = num_parsed_chan;
+ t->chans.max_power = max_pwr;
+ num_triplet++;
+ flag = 0;
+ }
}
- case CMD_RF_REG_ACCESS:
- {
- struct cmd_ds_rf_reg_access *rfreg;
+ if (flag) {
+ /* Add last triplet */
+ lbs_deb_11d("11D triplet (%d, %d, %d)\n", first_channel,
+ num_parsed_chan, max_pwr);
+ t = &domain->triplet[num_triplet];
+ t->chans.first_channel = first_channel;
+ t->chans.num_channels = num_parsed_chan;
+ t->chans.max_power = max_pwr;
+ num_triplet++;
+ }
+ }
- cmdptr->size =
- cpu_to_le16(sizeof
- (struct cmd_ds_rf_reg_access) +
- sizeof(struct cmd_header));
- rfreg =
- (struct cmd_ds_rf_reg_access *)&cmdptr->params.
- rfreg;
+ lbs_deb_11d("# triplets %d\n", num_triplet);
- rfreg->action = cpu_to_le16(cmd_action);
- rfreg->offset = cpu_to_le16((u16) offval->offset);
- rfreg->value = (u8) offval->value;
+ /* Set command header sizes */
+ triplet_size = num_triplet * sizeof(struct ieee80211_country_ie_triplet);
+ domain->header.len = cpu_to_le16(sizeof(domain->country_code) +
+ triplet_size);
- break;
- }
+ lbs_deb_hex(LBS_DEB_11D, "802.11D domain param set",
+ (u8 *) &cmd.domain.country_code,
+ le16_to_cpu(domain->header.len));
- default:
- break;
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd.hdr) +
+ sizeof(cmd.action) +
+ sizeof(cmd.domain.header) +
+ sizeof(cmd.domain.country_code) +
+ triplet_size);
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11D_DOMAIN_INFO, &cmd);
+
+ lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
+ return ret;
+}
+
+/**
+ * @brief Read a MAC, Baseband, or RF register
+ *
+ * @param priv pointer to struct lbs_private
+ * @param cmd register command, one of CMD_MAC_REG_ACCESS,
+ * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS
+ * @param offset byte offset of the register to get
+ * @param value on success, the value of the register at 'offset'
+ *
+ * @return 0 on success, error code on failure
+*/
+int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
+{
+ struct cmd_ds_reg_access cmd;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+ BUG_ON(value == NULL);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_GET);
+
+ if (reg != CMD_MAC_REG_ACCESS &&
+ reg != CMD_BBP_REG_ACCESS &&
+ reg != CMD_RF_REG_ACCESS) {
+ ret = -EINVAL;
+ goto out;
}
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
+ ret = lbs_cmd_with_response(priv, reg, &cmd);
+ if (ret) {
+ if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
+ *value = cmd.value.bbp_rf;
+ else if (reg == CMD_MAC_REG_ACCESS)
+ *value = le32_to_cpu(cmd.value.mac);
+ }
+
+out:
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
+}
+
+/**
+ * @brief Write a MAC, Baseband, or RF register
+ *
+ * @param priv pointer to struct lbs_private
+ * @param cmd register command, one of CMD_MAC_REG_ACCESS,
+ * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS
+ * @param offset byte offset of the register to set
+ * @param value the value to write to the register at 'offset'
+ *
+ * @return 0 on success, error code on failure
+*/
+int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)
+{
+ struct cmd_ds_reg_access cmd;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_SET);
+
+ if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
+ cmd.value.bbp_rf = (u8) (value & 0xFF);
+ else if (reg == CMD_MAC_REG_ACCESS)
+ cmd.value.mac = cpu_to_le32(value);
+ else {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = lbs_cmd_with_response(priv, reg, &cmd);
+
+out:
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
}
static void lbs_queue_cmd(struct lbs_private *priv,
@@ -771,16 +931,15 @@ static void lbs_queue_cmd(struct lbs_private *priv,
/* Exit_PS command needs to be queued in the header always. */
if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) {
- struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf[1];
+ struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf;
- if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
+ if (psm->action == cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
if (priv->psstate != PS_STATE_FULL_POWER)
addtail = 0;
}
}
- if (le16_to_cpu(cmdnode->cmdbuf->command) ==
- CMD_802_11_WAKEUP_CONFIRM)
+ if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_WAKEUP_CONFIRM)
addtail = 0;
spin_lock_irqsave(&priv->driver_lock, flags);
@@ -815,7 +974,6 @@ static void lbs_submit_command(struct lbs_private *priv,
spin_lock_irqsave(&priv->driver_lock, flags);
priv->cur_cmd = cmdnode;
- priv->cur_cmd_retcode = 0;
spin_unlock_irqrestore(&priv->driver_lock, flags);
cmdsize = le16_to_cpu(cmd->size);
@@ -888,9 +1046,6 @@ static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
int result)
{
- if (cmd == priv->cur_cmd)
- priv->cur_cmd_retcode = result;
-
cmd->result = result;
cmd->cmdwaitqwoken = 1;
wake_up_interruptible(&cmd->cmdwait_q);
@@ -958,240 +1113,6 @@ void lbs_set_mac_control(struct lbs_private *priv)
}
/**
- * @brief This function implements command CMD_802_11D_DOMAIN_INFO
- * @param priv pointer to struct lbs_private
- * @param cmd pointer to cmd buffer
- * @param cmdno cmd ID
- * @param cmdOption cmd action
- * @return 0
-*/
-int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- u16 cmdoption)
-{
- struct cmd_ds_802_11d_domain_info *pdomaininfo =
- &cmd->params.domaininfo;
- struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain;
- u8 nr_triplet = priv->domain_reg.no_triplet;
-
- lbs_deb_enter(LBS_DEB_11D);
-
- lbs_deb_11d("nr_triplet=%x\n", nr_triplet);
-
- pdomaininfo->action = cpu_to_le16(cmdoption);
- if (cmdoption == CMD_ACT_GET) {
- cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
- sizeof(struct cmd_header));
- lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd,
- le16_to_cpu(cmd->size));
- goto done;
- }
-
- domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
- memcpy(domain->countrycode, priv->domain_reg.country_code,
- sizeof(domain->countrycode));
-
- domain->header.len = cpu_to_le16(nr_triplet
- * sizeof(struct ieee80211_country_ie_triplet)
- + sizeof(domain->countrycode));
-
- if (nr_triplet) {
- memcpy(domain->triplet, priv->domain_reg.triplet,
- nr_triplet *
- sizeof(struct ieee80211_country_ie_triplet));
-
- cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
- le16_to_cpu(domain->header.len) +
- sizeof(struct mrvl_ie_header) +
- sizeof(struct cmd_header));
- } else {
- cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
- sizeof(struct cmd_header));
- }
-
- lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd,
- le16_to_cpu(cmd->size));
-
-done:
- lbs_deb_enter(LBS_DEB_11D);
- return 0;
-}
-
-/**
- * @brief This function prepare the command before send to firmware.
- *
- * @param priv A pointer to struct lbs_private structure
- * @param cmd_no command number
- * @param cmd_action command action: GET or SET
- * @param wait_option wait option: wait response or not
- * @param cmd_oid cmd oid: treated as sub command
- * @param pdata_buf A pointer to informaion buffer
- * @return 0 or -1
- */
-int lbs_prepare_and_send_command(struct lbs_private *priv,
- u16 cmd_no,
- u16 cmd_action,
- u16 wait_option, u32 cmd_oid, void *pdata_buf)
-{
- int ret = 0;
- struct cmd_ctrl_node *cmdnode;
- struct cmd_ds_command *cmdptr;
- unsigned long flags;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- if (!priv) {
- lbs_deb_host("PREP_CMD: priv is NULL\n");
- ret = -1;
- goto done;
- }
-
- if (priv->surpriseremoved) {
- lbs_deb_host("PREP_CMD: card removed\n");
- ret = -1;
- goto done;
- }
-
- if (!lbs_is_cmd_allowed(priv)) {
- ret = -EBUSY;
- goto done;
- }
-
- cmdnode = lbs_get_cmd_ctrl_node(priv);
-
- if (cmdnode == NULL) {
- lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
-
- /* Wake up main thread to execute next command */
- wake_up_interruptible(&priv->waitq);
- ret = -1;
- goto done;
- }
-
- cmdnode->callback = NULL;
- cmdnode->callback_arg = (unsigned long)pdata_buf;
-
- cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf;
-
- lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no);
-
- /* Set sequence number, command and INT option */
- priv->seqnum++;
- cmdptr->seqnum = cpu_to_le16(priv->seqnum);
-
- cmdptr->command = cpu_to_le16(cmd_no);
- cmdptr->result = 0;
-
- switch (cmd_no) {
- case CMD_802_11_PS_MODE:
- ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action);
- break;
-
- case CMD_MAC_REG_ACCESS:
- case CMD_BBP_REG_ACCESS:
- case CMD_RF_REG_ACCESS:
- ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf);
- break;
-
- case CMD_802_11_MONITOR_MODE:
- ret = lbs_cmd_802_11_monitor_mode(cmdptr,
- cmd_action, pdata_buf);
- break;
-
- case CMD_802_11_RSSI:
- ret = lbs_cmd_802_11_rssi(priv, cmdptr);
- break;
-
- case CMD_802_11_SET_AFC:
- case CMD_802_11_GET_AFC:
-
- cmdptr->command = cpu_to_le16(cmd_no);
- cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
- sizeof(struct cmd_header));
-
- memmove(&cmdptr->params.afc,
- pdata_buf, sizeof(struct cmd_ds_802_11_afc));
-
- ret = 0;
- goto done;
-
- case CMD_802_11D_DOMAIN_INFO:
- cmdptr->command = cpu_to_le16(cmd_no);
- ret = lbs_cmd_802_11d_domain_info(priv, cmdptr, cmd_action);
- break;
-
- case CMD_802_11_TPC_CFG:
- cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
- cmdptr->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) +
- sizeof(struct cmd_header));
-
- memmove(&cmdptr->params.tpccfg,
- pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg));
-
- ret = 0;
- break;
-
-#ifdef CONFIG_LIBERTAS_MESH
-
- case CMD_BT_ACCESS:
- ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf);
- break;
-
- case CMD_FWT_ACCESS:
- ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
- break;
-
-#endif
-
- case CMD_802_11_BEACON_CTRL:
- ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
- break;
- case CMD_802_11_DEEP_SLEEP:
- cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP);
- cmdptr->size = cpu_to_le16(sizeof(struct cmd_header));
- break;
- default:
- lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
- ret = -1;
- break;
- }
-
- /* return error, since the command preparation failed */
- if (ret != 0) {
- lbs_deb_host("PREP_CMD: command preparation failed\n");
- lbs_cleanup_and_insert_cmd(priv, cmdnode);
- ret = -1;
- goto done;
- }
-
- cmdnode->cmdwaitqwoken = 0;
-
- lbs_queue_cmd(priv, cmdnode);
- wake_up_interruptible(&priv->waitq);
-
- if (wait_option & CMD_OPTION_WAITFORRSP) {
- lbs_deb_host("PREP_CMD: wait for response\n");
- might_sleep();
- wait_event_interruptible(cmdnode->cmdwait_q,
- cmdnode->cmdwaitqwoken);
- }
-
- spin_lock_irqsave(&priv->driver_lock, flags);
- if (priv->cur_cmd_retcode) {
- lbs_deb_host("PREP_CMD: command failed with return code %d\n",
- priv->cur_cmd_retcode);
- priv->cur_cmd_retcode = 0;
- ret = -1;
- }
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-done:
- lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
- return ret;
-}
-
-/**
* @brief This function allocates the command buffer and link
* it to command free queue.
*
@@ -1284,7 +1205,7 @@ done:
* @param priv A pointer to struct lbs_private structure
* @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
*/
-static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv)
+static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)
{
struct cmd_ctrl_node *tempnode;
unsigned long flags;
@@ -1367,10 +1288,10 @@ int lbs_execute_next_command(struct lbs_private *priv)
/*
* 1. Non-PS command:
* Queue it. set needtowakeup to TRUE if current state
- * is SLEEP, otherwise call lbs_ps_wakeup to send Exit_PS.
- * 2. PS command but not Exit_PS:
+ * is SLEEP, otherwise call send EXIT_PS.
+ * 2. PS command but not EXIT_PS:
* Ignore it.
- * 3. PS command Exit_PS:
+ * 3. PS command EXIT_PS:
* Set needtowakeup to TRUE if current state is SLEEP,
* otherwise send this command down to firmware
* immediately.
@@ -1384,8 +1305,11 @@ int lbs_execute_next_command(struct lbs_private *priv)
/* w/ new scheme, it will not reach here.
since it is blocked in main_thread. */
priv->needtowakeup = 1;
- } else
- lbs_ps_wakeup(priv, 0);
+ } else {
+ lbs_set_ps_mode(priv,
+ PS_MODE_ACTION_EXIT_PS,
+ false);
+ }
ret = 0;
goto done;
@@ -1400,7 +1324,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
"EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
psm->action);
if (psm->action !=
- cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
+ cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
lbs_deb_host(
"EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
list_del(&cmdnode->list);
@@ -1460,13 +1384,16 @@ int lbs_execute_next_command(struct lbs_private *priv)
lbs_deb_host(
"EXEC_NEXT_CMD: WPA enabled and GTK_SET"
" go back to PS_SLEEP");
- lbs_ps_sleep(priv, 0);
+ lbs_set_ps_mode(priv,
+ PS_MODE_ACTION_ENTER_PS,
+ false);
}
} else {
lbs_deb_host(
"EXEC_NEXT_CMD: cmdpendingq empty, "
"go back to PS_SLEEP");
- lbs_ps_sleep(priv, 0);
+ lbs_set_ps_mode(priv, PS_MODE_ACTION_ENTER_PS,
+ false);
}
}
#endif
@@ -1514,43 +1441,6 @@ out:
lbs_deb_leave(LBS_DEB_HOST);
}
-void lbs_ps_sleep(struct lbs_private *priv, int wait_option)
-{
- lbs_deb_enter(LBS_DEB_HOST);
-
- /*
- * PS is currently supported only in Infrastructure mode
- * Remove this check if it is to be supported in IBSS mode also
- */
-
- lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
- CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL);
-
- lbs_deb_leave(LBS_DEB_HOST);
-}
-
-/**
- * @brief This function sends Exit_PS command to firmware.
- *
- * @param priv A pointer to struct lbs_private structure
- * @param wait_option wait response or not
- * @return n/a
- */
-void lbs_ps_wakeup(struct lbs_private *priv, int wait_option)
-{
- __le32 Localpsmode;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
-
- lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
- CMD_SUBCMD_EXIT_PS,
- wait_option, 0, &Localpsmode);
-
- lbs_deb_leave(LBS_DEB_HOST);
-}
-
/**
* @brief This function checks condition and prepares to
* send sleep confirm command to firmware if ok.
@@ -1675,12 +1565,18 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
goto done;
}
- if (!lbs_is_cmd_allowed(priv)) {
- cmdnode = ERR_PTR(-EBUSY);
- goto done;
+ /* No commands are allowed in Deep Sleep until we toggle the GPIO
+ * to wake up the card and it has signaled that it's ready.
+ */
+ if (!priv->is_auto_deep_sleep_enabled) {
+ if (priv->is_deep_sleep) {
+ lbs_deb_cmd("command not allowed in deep sleep\n");
+ cmdnode = ERR_PTR(-EBUSY);
+ goto done;
+ }
}
- cmdnode = lbs_get_cmd_ctrl_node(priv);
+ cmdnode = lbs_get_free_cmd_node(priv);
if (cmdnode == NULL) {
lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
index 386e565d99ad..7109d6b717ea 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -3,6 +3,8 @@
#ifndef _LBS_CMD_H_
#define _LBS_CMD_H_
+#include <net/cfg80211.h>
+
#include "host.h"
#include "dev.h"
@@ -37,11 +39,6 @@ struct cmd_ctrl_node {
#define lbs_cmd_with_response(priv, cmdnr, cmd) \
lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd))
-int lbs_prepare_and_send_command(struct lbs_private *priv,
- u16 cmd_no,
- u16 cmd_action,
- u16 wait_option, u32 cmd_oid, void *pdata_buf);
-
void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
struct cmd_header *in_cmd, int in_cmd_size);
@@ -92,10 +89,6 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
struct sleep_params *sp);
-void lbs_ps_sleep(struct lbs_private *priv, int wait_option);
-
-void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);
-
void lbs_ps_confirm_sleep(struct lbs_private *priv);
int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
@@ -129,4 +122,18 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep);
int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep);
+int lbs_set_monitor_mode(struct lbs_private *priv, int enable);
+
+int lbs_get_rssi(struct lbs_private *priv, s8 *snr, s8 *nf);
+
+int lbs_set_11d_domain_info(struct lbs_private *priv,
+ struct regulatory_request *request,
+ struct ieee80211_supported_band **bands);
+
+int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value);
+
+int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value);
+
+int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block);
+
#endif /* _LBS_CMD_H */
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index a0d9482ef5e2..5e95da9dcc2e 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -49,171 +49,11 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
if (priv->psstate != PS_STATE_FULL_POWER) {
/* make firmware to exit PS mode */
lbs_deb_cmd("disconnected, so exit PS mode\n");
- lbs_ps_wakeup(priv, 0);
+ lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false);
}
lbs_deb_leave(LBS_DEB_ASSOC);
}
-static int lbs_ret_reg_access(struct lbs_private *priv,
- u16 type, struct cmd_ds_command *resp)
-{
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- switch (type) {
- case CMD_RET(CMD_MAC_REG_ACCESS):
- {
- struct cmd_ds_mac_reg_access *reg = &resp->params.macreg;
-
- priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
- priv->offsetvalue.value = le32_to_cpu(reg->value);
- break;
- }
-
- case CMD_RET(CMD_BBP_REG_ACCESS):
- {
- struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg;
-
- priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
- priv->offsetvalue.value = reg->value;
- break;
- }
-
- case CMD_RET(CMD_RF_REG_ACCESS):
- {
- struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg;
-
- priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
- priv->offsetvalue.value = reg->value;
- break;
- }
-
- default:
- ret = -1;
- }
-
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-/**
- * @brief This function parses countryinfo from AP and download country info to FW
- * @param priv pointer to struct lbs_private
- * @param resp pointer to command response buffer
- * @return 0; -1
- */
-static int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11d_domain_info *domaininfo =
- &resp->params.domaininforesp;
- struct mrvl_ie_domain_param_set *domain = &domaininfo->domain;
- u16 action = le16_to_cpu(domaininfo->action);
- s16 ret = 0;
- u8 nr_triplet = 0;
-
- lbs_deb_enter(LBS_DEB_11D);
-
- lbs_deb_hex(LBS_DEB_11D, "domain info resp", (u8 *) resp,
- (int)le16_to_cpu(resp->size));
-
- nr_triplet = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) /
- sizeof(struct ieee80211_country_ie_triplet);
-
- lbs_deb_11d("domain info resp: nr_triplet %d\n", nr_triplet);
-
- if (nr_triplet > MRVDRV_MAX_TRIPLET_802_11D) {
- lbs_deb_11d("invalid number of triplets returned!!\n");
- return -1;
- }
-
- switch (action) {
- case CMD_ACT_SET: /*Proc set action */
- break;
-
- case CMD_ACT_GET:
- break;
- default:
- lbs_deb_11d("invalid action:%d\n", domaininfo->action);
- ret = -1;
- break;
- }
-
- lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
- return ret;
-}
-
-static inline int handle_cmd_response(struct lbs_private *priv,
- struct cmd_header *cmd_response)
-{
- struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response;
- int ret = 0;
- unsigned long flags;
- uint16_t respcmd = le16_to_cpu(resp->command);
-
- lbs_deb_enter(LBS_DEB_HOST);
-
- switch (respcmd) {
- case CMD_RET(CMD_MAC_REG_ACCESS):
- case CMD_RET(CMD_BBP_REG_ACCESS):
- case CMD_RET(CMD_RF_REG_ACCESS):
- ret = lbs_ret_reg_access(priv, respcmd, resp);
- break;
-
- case CMD_RET(CMD_802_11_SET_AFC):
- case CMD_RET(CMD_802_11_GET_AFC):
- spin_lock_irqsave(&priv->driver_lock, flags);
- memmove((void *)priv->cur_cmd->callback_arg, &resp->params.afc,
- sizeof(struct cmd_ds_802_11_afc));
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- break;
-
- case CMD_RET(CMD_802_11_BEACON_STOP):
- break;
-
- case CMD_RET(CMD_802_11_RSSI):
- ret = lbs_ret_802_11_rssi(priv, resp);
- break;
-
- case CMD_RET(CMD_802_11D_DOMAIN_INFO):
- ret = lbs_ret_802_11d_domain_info(resp);
- break;
-
- case CMD_RET(CMD_802_11_TPC_CFG):
- spin_lock_irqsave(&priv->driver_lock, flags);
- memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg,
- sizeof(struct cmd_ds_802_11_tpc_cfg));
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- break;
-
- case CMD_RET(CMD_BT_ACCESS):
- spin_lock_irqsave(&priv->driver_lock, flags);
- if (priv->cur_cmd->callback_arg)
- memcpy((void *)priv->cur_cmd->callback_arg,
- &resp->params.bt.addr1, 2 * ETH_ALEN);
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- break;
- case CMD_RET(CMD_FWT_ACCESS):
- spin_lock_irqsave(&priv->driver_lock, flags);
- if (priv->cur_cmd->callback_arg)
- memcpy((void *)priv->cur_cmd->callback_arg, &resp->params.fwt,
- sizeof(resp->params.fwt));
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- break;
- case CMD_RET(CMD_802_11_BEACON_CTRL):
- ret = lbs_ret_802_11_bcn_ctrl(priv, resp);
- break;
-
- default:
- lbs_pr_err("CMD_RESP: unknown cmd response 0x%04x\n",
- le16_to_cpu(resp->command));
- break;
- }
- lbs_deb_leave(LBS_DEB_HOST);
- return ret;
-}
-
int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
{
uint16_t respcmd, curcmd;
@@ -272,9 +112,6 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
del_timer(&priv->command_timer);
priv->cmd_timed_out = 0;
- /* Store the response code to cur_cmd_retcode. */
- priv->cur_cmd_retcode = result;
-
if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1];
u16 action = le16_to_cpu(psmode->action);
@@ -292,9 +129,9 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
* lbs_execute_next_command().
*/
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR &&
- action == CMD_SUBCMD_ENTER_PS)
+ action == PS_MODE_ACTION_ENTER_PS)
priv->psmode = LBS802_11POWERMODECAM;
- } else if (action == CMD_SUBCMD_ENTER_PS) {
+ } else if (action == PS_MODE_ACTION_ENTER_PS) {
priv->needtowakeup = 0;
priv->psstate = PS_STATE_AWAKE;
@@ -309,11 +146,12 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
spin_unlock_irqrestore(&priv->driver_lock, flags);
mutex_unlock(&priv->lock);
- lbs_ps_wakeup(priv, 0);
+ lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS,
+ false);
mutex_lock(&priv->lock);
spin_lock_irqsave(&priv->driver_lock, flags);
}
- } else if (action == CMD_SUBCMD_EXIT_PS) {
+ } else if (action == PS_MODE_ACTION_EXIT_PS) {
priv->needtowakeup = 0;
priv->psstate = PS_STATE_FULL_POWER;
lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
@@ -354,8 +192,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
if (priv->cur_cmd && priv->cur_cmd->callback) {
ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
resp);
- } else
- ret = handle_cmd_response(priv, resp);
+ }
spin_lock_irqsave(&priv->driver_lock, flags);
@@ -452,7 +289,7 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
* in lbs_ps_wakeup()
*/
lbs_deb_cmd("waking up ...\n");
- lbs_ps_wakeup(priv, 0);
+ lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false);
}
break;
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 3db621b18a2f..651a79c8de8a 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -446,30 +446,24 @@ static ssize_t lbs_bcnmiss_write(struct file *file, const char __user *userbuf,
}
-
static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
- struct lbs_offset_value offval;
ssize_t pos = 0;
int ret;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
+ u32 val = 0;
+
if (!buf)
return -ENOMEM;
- offval.offset = priv->mac_offset;
- offval.value = 0;
-
- ret = lbs_prepare_and_send_command(priv,
- CMD_MAC_REG_ACCESS, 0,
- CMD_OPTION_WAITFORRSP, 0, &offval);
+ ret = lbs_get_reg(priv, CMD_MAC_REG_ACCESS, priv->mac_offset, &val);
mdelay(10);
if (!ret) {
- pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
- priv->mac_offset, priv->offsetvalue.value);
-
+ pos = snprintf(buf, len, "MAC[0x%x] = 0x%08x\n",
+ priv->mac_offset, val);
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
}
free_page(addr);
@@ -507,7 +501,6 @@ static ssize_t lbs_wrmac_write(struct file *file,
struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
u32 offset, value;
- struct lbs_offset_value offval;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
if (!buf)
@@ -524,11 +517,7 @@ static ssize_t lbs_wrmac_write(struct file *file,
goto out_unlock;
}
- offval.offset = offset;
- offval.value = value;
- res = lbs_prepare_and_send_command(priv,
- CMD_MAC_REG_ACCESS, 1,
- CMD_OPTION_WAITFORRSP, 0, &offval);
+ res = lbs_set_reg(priv, CMD_MAC_REG_ACCESS, offset, value);
mdelay(10);
if (!res)
@@ -542,25 +531,20 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
- struct lbs_offset_value offval;
ssize_t pos = 0;
int ret;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
+ u32 val;
+
if (!buf)
return -ENOMEM;
- offval.offset = priv->bbp_offset;
- offval.value = 0;
-
- ret = lbs_prepare_and_send_command(priv,
- CMD_BBP_REG_ACCESS, 0,
- CMD_OPTION_WAITFORRSP, 0, &offval);
+ ret = lbs_get_reg(priv, CMD_BBP_REG_ACCESS, priv->bbp_offset, &val);
mdelay(10);
if (!ret) {
- pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
- priv->bbp_offset, priv->offsetvalue.value);
-
+ pos = snprintf(buf, len, "BBP[0x%x] = 0x%08x\n",
+ priv->bbp_offset, val);
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
}
free_page(addr);
@@ -599,7 +583,6 @@ static ssize_t lbs_wrbbp_write(struct file *file,
struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
u32 offset, value;
- struct lbs_offset_value offval;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
if (!buf)
@@ -616,11 +599,7 @@ static ssize_t lbs_wrbbp_write(struct file *file,
goto out_unlock;
}
- offval.offset = offset;
- offval.value = value;
- res = lbs_prepare_and_send_command(priv,
- CMD_BBP_REG_ACCESS, 1,
- CMD_OPTION_WAITFORRSP, 0, &offval);
+ res = lbs_set_reg(priv, CMD_BBP_REG_ACCESS, offset, value);
mdelay(10);
if (!res)
@@ -634,25 +613,20 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
- struct lbs_offset_value offval;
ssize_t pos = 0;
int ret;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
+ u32 val;
+
if (!buf)
return -ENOMEM;
- offval.offset = priv->rf_offset;
- offval.value = 0;
-
- ret = lbs_prepare_and_send_command(priv,
- CMD_RF_REG_ACCESS, 0,
- CMD_OPTION_WAITFORRSP, 0, &offval);
+ ret = lbs_get_reg(priv, CMD_RF_REG_ACCESS, priv->rf_offset, &val);
mdelay(10);
if (!ret) {
- pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
- priv->rf_offset, priv->offsetvalue.value);
-
+ pos = snprintf(buf, len, "RF[0x%x] = 0x%08x\n",
+ priv->rf_offset, val);
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
}
free_page(addr);
@@ -691,7 +665,6 @@ static ssize_t lbs_wrrf_write(struct file *file,
struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
u32 offset, value;
- struct lbs_offset_value offval;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
if (!buf)
@@ -708,11 +681,7 @@ static ssize_t lbs_wrrf_write(struct file *file,
goto out_unlock;
}
- offval.offset = offset;
- offval.value = value;
- res = lbs_prepare_and_send_command(priv,
- CMD_RF_REG_ACCESS, 1,
- CMD_OPTION_WAITFORRSP, 0, &offval);
+ res = lbs_set_reg(priv, CMD_RF_REG_ACCESS, offset, value);
mdelay(10);
if (!res)
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index ba5438a7ba17..1d141fefd767 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -53,9 +53,4 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
u32 lbs_fw_index_to_data_rate(u8 index);
u8 lbs_data_rate_to_fw_index(u32 rate);
-int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
- struct cmd_ds_command *cmd, u16 cmdoption);
-
-int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp);
-
#endif
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index ea3f10ef4e00..d00c728cec47 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -172,11 +172,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
#define MRVDRV_MAX_BSS_DESCRIPTS 16
#define MRVDRV_MAX_REGION_CODE 6
-#define MRVDRV_IGNORE_MULTIPLE_DTIM 0xfffe
-#define MRVDRV_MIN_MULTIPLE_DTIM 1
-#define MRVDRV_MAX_MULTIPLE_DTIM 5
-#define MRVDRV_DEFAULT_MULTIPLE_DTIM 1
-
#define MRVDRV_DEFAULT_LISTEN_INTERVAL 10
#define MRVDRV_CHANNELS_PER_SCAN 4
@@ -301,19 +296,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
#define BAND_G (0x02)
#define ALL_802_11_BANDS (BAND_B | BAND_G)
-/** MACRO DEFINITIONS */
-#define CAL_NF(NF) ((s32)(-(s32)(NF)))
-#define CAL_RSSI(SNR, NF) ((s32)((s32)(SNR) + CAL_NF(NF)))
-#define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI)))
-
-#define DEFAULT_BCN_AVG_FACTOR 8
-#define DEFAULT_DATA_AVG_FACTOR 8
-#define AVG_SCALE 100
-#define CAL_AVG_SNR_NF(AVG, SNRNF, N) \
- (((AVG) == 0) ? ((u16)(SNRNF) * AVG_SCALE) : \
- ((((int)(AVG) * (N -1)) + ((u16)(SNRNF) * \
- AVG_SCALE)) / N))
-
#define MAX_RATES 14
#define MAX_LEDS 8
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 4536d9c0ad87..3c7e255e18c7 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -60,14 +60,10 @@ struct lbs_private {
struct dentry *regs_dir;
struct dentry *debugfs_regs_files[6];
- /** 11D and domain regulatory data */
- struct lbs_802_11d_domain_reg domain_reg;
-
/* Hardware debugging */
u32 mac_offset;
u32 bbp_offset;
u32 rf_offset;
- struct lbs_offset_value offsetvalue;
/* Power management */
u16 psmode;
@@ -115,12 +111,10 @@ struct lbs_private {
struct cmd_ctrl_node *cur_cmd;
struct list_head cmdfreeq; /* free command buffers */
struct list_head cmdpendingq; /* pending command buffers */
- wait_queue_head_t cmd_pending;
struct timer_list command_timer;
int cmd_timed_out;
/* Command responses sent from the hardware to the driver */
- int cur_cmd_retcode;
u8 resp_idx;
u8 resp_buf[2][LBS_UPLD_SIZE];
u32 resp_len[2];
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index 43d020cd7403..5eac1351a021 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -94,11 +94,9 @@
#define CMD_802_11_BEACON_CTRL 0x00b0
/* For the IEEE Power Save */
-#define CMD_SUBCMD_ENTER_PS 0x0030
-#define CMD_SUBCMD_EXIT_PS 0x0031
-#define CMD_SUBCMD_SLEEP_CONFIRMED 0x0034
-#define CMD_SUBCMD_FULL_POWERDOWN 0x0035
-#define CMD_SUBCMD_FULL_POWERUP 0x0036
+#define PS_MODE_ACTION_ENTER_PS 0x0030
+#define PS_MODE_ACTION_EXIT_PS 0x0031
+#define PS_MODE_ACTION_SLEEP_CONFIRMED 0x0034
#define CMD_ENABLE_RSN 0x0001
#define CMD_DISABLE_RSN 0x0000
@@ -163,11 +161,6 @@
#define CMD_ACT_SET_TX_FIX_RATE 0x0001
#define CMD_ACT_GET_TX_RATE 0x0002
-/* Define action or option for CMD_802_11_PS_MODE */
-#define CMD_TYPE_CAM 0x0000
-#define CMD_TYPE_MAX_PSP 0x0001
-#define CMD_TYPE_FAST_PSP 0x0002
-
/* Options for CMD_802_11_FW_WAKE_METHOD */
#define CMD_WAKE_METHOD_UNCHANGED 0x0000
#define CMD_WAKE_METHOD_COMMAND_INT 0x0001
@@ -389,30 +382,22 @@ struct lbs_offset_value {
u32 value;
} __packed;
-#define MRVDRV_MAX_TRIPLET_802_11D 83
-
-#define COUNTRY_CODE_LEN 3
+#define MAX_11D_TRIPLETS 83
struct mrvl_ie_domain_param_set {
struct mrvl_ie_header header;
- u8 countrycode[COUNTRY_CODE_LEN];
- struct ieee80211_country_ie_triplet triplet[1];
+ u8 country_code[3];
+ struct ieee80211_country_ie_triplet triplet[MAX_11D_TRIPLETS];
} __packed;
struct cmd_ds_802_11d_domain_info {
+ struct cmd_header hdr;
+
__le16 action;
struct mrvl_ie_domain_param_set domain;
} __packed;
-struct lbs_802_11d_domain_reg {
- /** Country code*/
- u8 country_code[COUNTRY_CODE_LEN];
- /** No. of triplet*/
- u8 no_triplet;
- struct ieee80211_country_ie_triplet triplet[MRVDRV_MAX_TRIPLET_802_11D];
-} __packed;
-
/*
* Define data structure for CMD_GET_HW_SPEC
* This structure defines the response for the GET_HW_SPEC command
@@ -575,24 +560,15 @@ struct cmd_ds_802_11_snmp_mib {
u8 value[128];
} __packed;
-struct cmd_ds_mac_reg_access {
- __le16 action;
- __le16 offset;
- __le32 value;
-} __packed;
-
-struct cmd_ds_bbp_reg_access {
- __le16 action;
- __le16 offset;
- u8 value;
- u8 reserved[3];
-} __packed;
+struct cmd_ds_reg_access {
+ struct cmd_header hdr;
-struct cmd_ds_rf_reg_access {
__le16 action;
__le16 offset;
- u8 value;
- u8 reserved[3];
+ union {
+ u8 bbp_rf; /* for BBP and RF registers */
+ __le32 mac; /* for MAC registers */
+ } value;
} __packed;
struct cmd_ds_802_11_radio_control {
@@ -603,6 +579,8 @@ struct cmd_ds_802_11_radio_control {
} __packed;
struct cmd_ds_802_11_beacon_control {
+ struct cmd_header hdr;
+
__le16 action;
__le16 beacon_enable;
__le16 beacon_period;
@@ -644,19 +622,19 @@ struct cmd_ds_802_11_rf_channel {
} __packed;
struct cmd_ds_802_11_rssi {
- /* weighting factor */
- __le16 N;
+ struct cmd_header hdr;
- __le16 reserved_0;
- __le16 reserved_1;
- __le16 reserved_2;
-} __packed;
+ /* request: number of beacons (N) to average the SNR and NF over
+ * response: SNR of most recent beacon
+ */
+ __le16 n_or_snr;
-struct cmd_ds_802_11_rssi_rsp {
- __le16 SNR;
- __le16 noisefloor;
- __le16 avgSNR;
- __le16 avgnoisefloor;
+ /* The following fields are only set in the response.
+ * In the request these are reserved and should be set to 0.
+ */
+ __le16 nf; /* most recent beacon noise floor */
+ __le16 avg_snr; /* average SNR weighted by N from request */
+ __le16 avg_nf; /* average noise floor weighted by N from request */
} __packed;
struct cmd_ds_802_11_mac_address {
@@ -675,7 +653,10 @@ struct cmd_ds_802_11_rf_tx_power {
s8 minlevel;
} __packed;
+/* MONITOR_MODE only exists in OLPC v5 firmware */
struct cmd_ds_802_11_monitor_mode {
+ struct cmd_header hdr;
+
__le16 action;
__le16 mode;
} __packed;
@@ -695,11 +676,35 @@ struct cmd_ds_802_11_fw_wake_method {
} __packed;
struct cmd_ds_802_11_ps_mode {
+ struct cmd_header hdr;
+
__le16 action;
+
+ /* Interval for keepalive in PS mode:
+ * 0x0000 = don't change
+ * 0x001E = firmware default
+ * 0xFFFF = disable
+ */
__le16 nullpktinterval;
+
+ /* Number of DTIM intervals to wake up for:
+ * 0 = don't change
+ * 1 = firmware default
+ * 5 = max
+ */
__le16 multipledtim;
+
__le16 reserved;
__le16 locallisteninterval;
+
+ /* AdHoc awake period (FW v9+ only):
+ * 0 = don't change
+ * 1 = always awake (IEEE standard behavior)
+ * 2 - 31 = sleep for (n - 1) periods and awake for 1 period
+ * 32 - 254 = invalid
+ * 255 = sleep at each ATIM
+ */
+ __le16 adhoc_awake_period;
} __packed;
struct cmd_confirm_sleep {
@@ -882,12 +887,17 @@ struct cmd_ds_802_11_pa_cfg {
struct cmd_ds_802_11_led_ctrl {
+ struct cmd_header hdr;
+
__le16 action;
__le16 numled;
u8 data[256];
} __packed;
+/* Automatic Frequency Control */
struct cmd_ds_802_11_afc {
+ struct cmd_header hdr;
+
__le16 afc_auto;
union {
struct {
@@ -910,6 +920,8 @@ struct cmd_ds_get_tsf {
} __packed;
struct cmd_ds_bt_access {
+ struct cmd_header hdr;
+
__le16 action;
__le32 id;
u8 addr1[ETH_ALEN];
@@ -917,6 +929,8 @@ struct cmd_ds_bt_access {
} __packed;
struct cmd_ds_fwt_access {
+ struct cmd_header hdr;
+
__le16 action;
__le32 id;
u8 valid;
@@ -955,34 +969,4 @@ struct cmd_ds_mesh_access {
/* Number of stats counters returned by the firmware */
#define MESH_STATS_NUM 8
-
-struct cmd_ds_command {
- /* command header */
- __le16 command;
- __le16 size;
- __le16 seqnum;
- __le16 result;
-
- /* command Body */
- union {
- struct cmd_ds_802_11_ps_mode psmode;
- struct cmd_ds_802_11_monitor_mode monitor;
- struct cmd_ds_802_11_rssi rssi;
- struct cmd_ds_802_11_rssi_rsp rssirsp;
- struct cmd_ds_mac_reg_access macreg;
- struct cmd_ds_bbp_reg_access bbpreg;
- struct cmd_ds_rf_reg_access rfreg;
-
- struct cmd_ds_802_11d_domain_info domaininfo;
- struct cmd_ds_802_11d_domain_info domaininforesp;
-
- struct cmd_ds_802_11_tpc_cfg tpccfg;
- struct cmd_ds_802_11_afc afc;
- struct cmd_ds_802_11_led_ctrl ledgpio;
-
- struct cmd_ds_bt_access bt;
- struct cmd_ds_fwt_access fwt;
- struct cmd_ds_802_11_beacon_control bcn_ctrl;
- } params;
-} __packed;
#endif
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 3678e532874f..07ece9d26c63 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -433,7 +433,7 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
static int if_usb_reset_device(struct if_usb_card *cardp)
{
- struct cmd_ds_command *cmd = cardp->ep_out_buf + 4;
+ struct cmd_header *cmd = cardp->ep_out_buf + 4;
int ret;
lbs_deb_enter(LBS_DEB_USB);
@@ -441,7 +441,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
cmd->command = cpu_to_le16(CMD_802_11_RESET);
- cmd->size = cpu_to_le16(sizeof(struct cmd_header));
+ cmd->size = cpu_to_le16(sizeof(cmd));
cmd->result = cpu_to_le16(0);
cmd->seqnum = cpu_to_le16(0x5a5a);
usb_tx_block(cardp, cardp->ep_out_buf, 4 + sizeof(struct cmd_header));
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 2a0b590a93f1..258967144b96 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -157,12 +157,7 @@ static void lbs_tx_timeout(struct net_device *dev)
to kick it somehow? */
lbs_host_to_card_done(priv);
- /* More often than not, this actually happens because the
- firmware has crapped itself -- rather than just a very
- busy medium. So send a harmless command, and if/when
- _that_ times out, we'll kick it in the head. */
- lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
- 0, 0, NULL);
+ /* FIXME: reset the card */
lbs_deb_leave(LBS_DEB_TX);
}
@@ -507,12 +502,6 @@ static int lbs_thread(void *data)
if (!priv->dnld_sent && !priv->cur_cmd)
lbs_execute_next_command(priv);
- /* Wake-up command waiters which can't sleep in
- * lbs_prepare_and_send_command
- */
- if (!list_empty(&priv->cmdpendingq))
- wake_up_all(&priv->cmd_pending);
-
spin_lock_irq(&priv->driver_lock);
if (!priv->dnld_sent && priv->tx_pending_len > 0) {
int ret = priv->hw_host_to_card(priv, MVMS_DAT,
@@ -538,7 +527,6 @@ static int lbs_thread(void *data)
del_timer(&priv->command_timer);
del_timer(&priv->auto_deepsleep_timer);
- wake_up_all(&priv->cmd_pending);
lbs_deb_leave(LBS_DEB_THREAD);
return 0;
@@ -663,7 +651,6 @@ out:
static void auto_deepsleep_timer_fn(unsigned long data)
{
struct lbs_private *priv = (struct lbs_private *)data;
- int ret;
lbs_deb_enter(LBS_DEB_CMD);
@@ -671,14 +658,15 @@ static void auto_deepsleep_timer_fn(unsigned long data)
priv->is_activity_detected = 0;
} else {
if (priv->is_auto_deep_sleep_enabled &&
- (!priv->wakeup_dev_required) &&
- (priv->connect_status != LBS_CONNECTED)) {
+ (!priv->wakeup_dev_required) &&
+ (priv->connect_status != LBS_CONNECTED)) {
+ struct cmd_header cmd;
+
lbs_deb_main("Entering auto deep sleep mode...\n");
- ret = lbs_prepare_and_send_command(priv,
- CMD_802_11_DEEP_SLEEP, 0,
- 0, 0, NULL);
- if (ret)
- lbs_pr_err("Enter Deep Sleep command failed\n");
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.size = cpu_to_le16(sizeof(cmd));
+ lbs_cmd_async(priv, CMD_802_11_DEEP_SLEEP, &cmd,
+ sizeof(cmd));
}
}
mod_timer(&priv->auto_deepsleep_timer , jiffies +
@@ -746,7 +734,6 @@ static int lbs_init_adapter(struct lbs_private *priv)
INIT_LIST_HEAD(&priv->cmdpendingq);
spin_lock_init(&priv->driver_lock);
- init_waitqueue_head(&priv->cmd_pending);
/* Allocate the command buffers */
if (lbs_allocate_cmd_buffer(priv)) {
@@ -902,7 +889,7 @@ void lbs_remove_card(struct lbs_private *priv)
if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
priv->psmode = LBS802_11POWERMODECAM;
- lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
+ lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, true);
}
if (priv->is_deep_sleep) {
@@ -1065,7 +1052,7 @@ static int __init lbs_init_module(void)
memset(&confirm_sleep, 0, sizeof(confirm_sleep));
confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE);
confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep));
- confirm_sleep.action = cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);
+ confirm_sleep.action = cpu_to_le16(PS_MODE_ACTION_SLEEP_CONFIRMED);
lbs_debugfs_init();
lbs_deb_leave(LBS_DEB_MAIN);
return 0;
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index bc5bc1384c35..194762ab0142 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -455,65 +455,189 @@ void lbs_mesh_set_txpd(struct lbs_private *priv,
* Mesh command handling
*/
-int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
+/**
+ * @brief Add or delete Mesh Blinding Table entries
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param add TRUE to add the entry, FALSE to delete it
+ * @param addr1 Destination address to blind or unblind
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1)
{
- struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
- lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
+ struct cmd_ds_bt_access cmd;
+ int ret = 0;
- cmd->command = cpu_to_le16(CMD_BT_ACCESS);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) +
- sizeof(struct cmd_header));
- cmd->result = 0;
- bt_access->action = cpu_to_le16(cmd_action);
+ lbs_deb_enter(LBS_DEB_CMD);
- switch (cmd_action) {
- case CMD_ACT_BT_ACCESS_ADD:
- memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
+ BUG_ON(addr1 == NULL);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ memcpy(cmd.addr1, addr1, ETH_ALEN);
+ if (add) {
+ cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_ADD);
lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr",
- bt_access->addr1, 6);
- break;
- case CMD_ACT_BT_ACCESS_DEL:
- memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN);
+ addr1, ETH_ALEN);
+ } else {
+ cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_DEL);
lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr",
- bt_access->addr1, 6);
- break;
- case CMD_ACT_BT_ACCESS_LIST:
- bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
- break;
- case CMD_ACT_BT_ACCESS_RESET:
- break;
- case CMD_ACT_BT_ACCESS_SET_INVERT:
- bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
- break;
- case CMD_ACT_BT_ACCESS_GET_INVERT:
- break;
- default:
- break;
+ addr1, ETH_ALEN);
}
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
+
+ ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
+
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
}
-int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
+/**
+ * @brief Reset/clear the mesh blinding table
+ *
+ * @param priv A pointer to struct lbs_private structure
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_mesh_bt_reset(struct lbs_private *priv)
{
- struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
- lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
+ struct cmd_ds_bt_access cmd;
+ int ret = 0;
- cmd->command = cpu_to_le16(CMD_FWT_ACCESS);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) +
- sizeof(struct cmd_header));
- cmd->result = 0;
+ lbs_deb_enter(LBS_DEB_CMD);
- if (pdata_buf)
- memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
- else
- memset(fwt_access, 0, sizeof(*fwt_access));
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_RESET);
- fwt_access->action = cpu_to_le16(cmd_action);
+ ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
- lbs_deb_leave(LBS_DEB_CMD);
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
+}
+
+/**
+ * @brief Gets the inverted status of the mesh blinding table
+ *
+ * Normally the firmware "blinds" or ignores traffic from mesh nodes in the
+ * table, but an inverted table allows *only* traffic from nodes listed in
+ * the table.
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param invert On success, TRUE if the blinding table is inverted,
+ * FALSE if it is not inverted
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted)
+{
+ struct cmd_ds_bt_access cmd;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+ BUG_ON(inverted == NULL);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_GET_INVERT);
+
+ ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
+ if (ret == 0)
+ *inverted = !!cmd.id;
+
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
+}
+
+/**
+ * @brief Sets the inverted status of the mesh blinding table
+ *
+ * Normally the firmware "blinds" or ignores traffic from mesh nodes in the
+ * table, but an inverted table allows *only* traffic from nodes listed in
+ * the table.
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param invert TRUE to invert the blinding table (only traffic from
+ * listed nodes allowed), FALSE to return it
+ * to normal state (listed nodes ignored)
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted)
+{
+ struct cmd_ds_bt_access cmd;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
+ cmd.id = !!inverted;
+
+ ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
+
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
+}
+
+/**
+ * @brief List an entry in the mesh blinding table
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param id The ID of the entry to list
+ * @param addr1 MAC address associated with the table entry
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1)
+{
+ struct cmd_ds_bt_access cmd;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+ BUG_ON(addr1 == NULL);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
+ cmd.id = cpu_to_le32(id);
+
+ ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
+ if (ret == 0)
+ memcpy(addr1, cmd.addr1, sizeof(cmd.addr1));
+
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
+}
+
+/**
+ * @brief Access the mesh forwarding table
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param cmd_action The forwarding table action to perform
+ * @param cmd The pre-filled FWT_ACCESS command
+ *
+ * @return 0 on success and 'cmd' will be filled with the
+ * firmware's response
+ */
+int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action,
+ struct cmd_ds_fwt_access *cmd)
+{
+ int ret;
+
+ lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
+
+ cmd->hdr.command = cpu_to_le16(CMD_FWT_ACCESS);
+ cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access));
+ cmd->hdr.result = 0;
+ cmd->action = cpu_to_le16(cmd_action);
+
+ ret = lbs_cmd_with_response(priv, CMD_FWT_ACCESS, cmd);
+
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return 0;
}
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h
index 84ea2481ff20..afb2e8dead3f 100644
--- a/drivers/net/wireless/libertas/mesh.h
+++ b/drivers/net/wireless/libertas/mesh.h
@@ -8,6 +8,7 @@
#include <net/iw_handler.h>
#include <net/lib80211.h>
+#include "host.h"
#ifdef CONFIG_LIBERTAS_MESH
@@ -51,10 +52,15 @@ struct cmd_ds_command;
struct cmd_ds_mesh_access;
struct cmd_ds_mesh_config;
-int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf);
-int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf);
+int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1);
+int lbs_mesh_bt_reset(struct lbs_private *priv);
+int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted);
+int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted);
+int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1);
+
+int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action,
+ struct cmd_ds_fwt_access *cmd);
+
int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
struct cmd_ds_mesh_access *cmd);
int lbs_mesh_config_send(struct lbs_private *priv,
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index 411a3bbf035e..8000ca6165d0 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -180,7 +180,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
{
struct tx_radiotap_hdr *radiotap_hdr;
- if (!priv->wdev->iftype == NL80211_IFTYPE_MONITOR ||
+ if (priv->wdev->iftype != NL80211_IFTYPE_MONITOR ||
priv->currenttxskb == NULL)
return;
diff --git a/drivers/net/wireless/libertas_tf/libertas_tf.h b/drivers/net/wireless/libertas_tf/libertas_tf.h
index 737eac92ef72..ad77b92d0b41 100644
--- a/drivers/net/wireless/libertas_tf/libertas_tf.h
+++ b/drivers/net/wireless/libertas_tf/libertas_tf.h
@@ -253,6 +253,9 @@ struct lbtf_private {
u8 fw_ready;
u8 surpriseremoved;
struct sk_buff_head bc_ps_buf;
+
+ /* Most recently reported noise in dBm */
+ s8 noise;
};
/* 802.11-related definitions */
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index 817fffc0de4b..9278b3c8ee30 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -525,6 +525,22 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
lbtf_deb_leave(LBTF_DEB_MACOPS);
}
+static int lbtf_op_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey)
+{
+ struct lbtf_private *priv = hw->priv;
+ struct ieee80211_conf *conf = &hw->conf;
+
+ if (idx != 0)
+ return -ENOENT;
+
+ survey->channel = conf->channel;
+ survey->filled = SURVEY_INFO_NOISE_DBM;
+ survey->noise = priv->noise;
+
+ return 0;
+}
+
static const struct ieee80211_ops lbtf_ops = {
.tx = lbtf_op_tx,
.start = lbtf_op_start,
@@ -535,6 +551,7 @@ static const struct ieee80211_ops lbtf_ops = {
.prepare_multicast = lbtf_op_prepare_multicast,
.configure_filter = lbtf_op_configure_filter,
.bss_info_changed = lbtf_op_bss_info_changed,
+ .get_survey = lbtf_op_get_survey,
};
int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
@@ -555,6 +572,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
stats.freq = priv->cur_freq;
stats.band = IEEE80211_BAND_2GHZ;
stats.signal = prxpd->snr;
+ priv->noise = prxpd->nf;
/* Marvell rate index has a hole at value 4 */
if (prxpd->rx_rate > 4)
--prxpd->rx_rate;
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index e7f299dc9ef5..01ad7f77383a 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -486,8 +486,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
struct ieee80211_rx_status rx_status;
if (data->idle) {
- printk(KERN_DEBUG "%s: Trying to TX when idle - reject\n",
- wiphy_name(hw->wiphy));
+ wiphy_debug(hw->wiphy, "trying to tx when idle - reject\n");
return false;
}
@@ -576,7 +575,7 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
static int mac80211_hwsim_start(struct ieee80211_hw *hw)
{
struct mac80211_hwsim_data *data = hw->priv;
- printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__);
+ wiphy_debug(hw->wiphy, "%s\n", __func__);
data->started = 1;
return 0;
}
@@ -587,16 +586,15 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
struct mac80211_hwsim_data *data = hw->priv;
data->started = 0;
del_timer(&data->beacon_timer);
- printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__);
+ wiphy_debug(hw->wiphy, "%s\n", __func__);
}
static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n",
- wiphy_name(hw->wiphy), __func__, vif->type,
- vif->addr);
+ wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n",
+ __func__, vif->type, vif->addr);
hwsim_set_magic(vif);
return 0;
}
@@ -605,9 +603,8 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
static void mac80211_hwsim_remove_interface(
struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
- printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n",
- wiphy_name(hw->wiphy), __func__, vif->type,
- vif->addr);
+ wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n",
+ __func__, vif->type, vif->addr);
hwsim_check_magic(vif);
hwsim_clear_magic(vif);
}
@@ -670,13 +667,14 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
[IEEE80211_SMPS_DYNAMIC] = "dynamic",
};
- printk(KERN_DEBUG "%s:%s (freq=%d/%s idle=%d ps=%d smps=%s)\n",
- wiphy_name(hw->wiphy), __func__,
- conf->channel->center_freq,
- hwsim_chantypes[conf->channel_type],
- !!(conf->flags & IEEE80211_CONF_IDLE),
- !!(conf->flags & IEEE80211_CONF_PS),
- smps_modes[conf->smps_mode]);
+ wiphy_debug(hw->wiphy,
+ "%s (freq=%d/%s idle=%d ps=%d smps=%s)\n",
+ __func__,
+ conf->channel->center_freq,
+ hwsim_chantypes[conf->channel_type],
+ !!(conf->flags & IEEE80211_CONF_IDLE),
+ !!(conf->flags & IEEE80211_CONF_PS),
+ smps_modes[conf->smps_mode]);
data->idle = !!(conf->flags & IEEE80211_CONF_IDLE);
@@ -696,7 +694,7 @@ static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw,
{
struct mac80211_hwsim_data *data = hw->priv;
- printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__);
+ wiphy_debug(hw->wiphy, "%s\n", __func__);
data->rx_filter = 0;
if (*total_flags & FIF_PROMISC_IN_BSS)
@@ -717,26 +715,23 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
hwsim_check_magic(vif);
- printk(KERN_DEBUG "%s:%s(changed=0x%x)\n",
- wiphy_name(hw->wiphy), __func__, changed);
+ wiphy_debug(hw->wiphy, "%s(changed=0x%x)\n", __func__, changed);
if (changed & BSS_CHANGED_BSSID) {
- printk(KERN_DEBUG "%s:%s: BSSID changed: %pM\n",
- wiphy_name(hw->wiphy), __func__,
- info->bssid);
+ wiphy_debug(hw->wiphy, "%s: BSSID changed: %pM\n",
+ __func__, info->bssid);
memcpy(vp->bssid, info->bssid, ETH_ALEN);
}
if (changed & BSS_CHANGED_ASSOC) {
- printk(KERN_DEBUG " %s: ASSOC: assoc=%d aid=%d\n",
- wiphy_name(hw->wiphy), info->assoc, info->aid);
+ wiphy_debug(hw->wiphy, " ASSOC: assoc=%d aid=%d\n",
+ info->assoc, info->aid);
vp->assoc = info->assoc;
vp->aid = info->aid;
}
if (changed & BSS_CHANGED_BEACON_INT) {
- printk(KERN_DEBUG " %s: BCNINT: %d\n",
- wiphy_name(hw->wiphy), info->beacon_int);
+ wiphy_debug(hw->wiphy, " BCNINT: %d\n", info->beacon_int);
data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000;
if (WARN_ON(!data->beacon_int))
data->beacon_int = 1;
@@ -746,31 +741,28 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_ERP_CTS_PROT) {
- printk(KERN_DEBUG " %s: ERP_CTS_PROT: %d\n",
- wiphy_name(hw->wiphy), info->use_cts_prot);
+ wiphy_debug(hw->wiphy, " ERP_CTS_PROT: %d\n",
+ info->use_cts_prot);
}
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- printk(KERN_DEBUG " %s: ERP_PREAMBLE: %d\n",
- wiphy_name(hw->wiphy), info->use_short_preamble);
+ wiphy_debug(hw->wiphy, " ERP_PREAMBLE: %d\n",
+ info->use_short_preamble);
}
if (changed & BSS_CHANGED_ERP_SLOT) {
- printk(KERN_DEBUG " %s: ERP_SLOT: %d\n",
- wiphy_name(hw->wiphy), info->use_short_slot);
+ wiphy_debug(hw->wiphy, " ERP_SLOT: %d\n", info->use_short_slot);
}
if (changed & BSS_CHANGED_HT) {
- printk(KERN_DEBUG " %s: HT: op_mode=0x%x, chantype=%s\n",
- wiphy_name(hw->wiphy),
- info->ht_operation_mode,
- hwsim_chantypes[info->channel_type]);
+ wiphy_debug(hw->wiphy, " HT: op_mode=0x%x, chantype=%s\n",
+ info->ht_operation_mode,
+ hwsim_chantypes[info->channel_type]);
}
if (changed & BSS_CHANGED_BASIC_RATES) {
- printk(KERN_DEBUG " %s: BASIC_RATES: 0x%llx\n",
- wiphy_name(hw->wiphy),
- (unsigned long long) info->basic_rates);
+ wiphy_debug(hw->wiphy, " BASIC_RATES: 0x%llx\n",
+ (unsigned long long) info->basic_rates);
}
}
@@ -824,10 +816,11 @@ static int mac80211_hwsim_conf_tx(
struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
- printk(KERN_DEBUG "%s:%s (queue=%d txop=%d cw_min=%d cw_max=%d "
- "aifs=%d)\n",
- wiphy_name(hw->wiphy), __func__, queue,
- params->txop, params->cw_min, params->cw_max, params->aifs);
+ wiphy_debug(hw->wiphy,
+ "%s (queue=%d txop=%d cw_min=%d cw_max=%d aifs=%d)\n",
+ __func__, queue,
+ params->txop, params->cw_min,
+ params->cw_max, params->aifs);
return 0;
}
@@ -837,8 +830,7 @@ static int mac80211_hwsim_get_survey(
{
struct ieee80211_conf *conf = &hw->conf;
- printk(KERN_DEBUG "%s:%s (idx=%d)\n",
- wiphy_name(hw->wiphy), __func__, idx);
+ wiphy_debug(hw->wiphy, "%s (idx=%d)\n", __func__, idx);
if (idx != 0)
return -ENOENT;
@@ -1108,8 +1100,9 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
if (!vp->assoc)
return;
- printk(KERN_DEBUG "%s:%s: send PS-Poll to %pM for aid %d\n",
- wiphy_name(data->hw->wiphy), __func__, vp->bssid, vp->aid);
+ wiphy_debug(data->hw->wiphy,
+ "%s: send PS-Poll to %pM for aid %d\n",
+ __func__, vp->bssid, vp->aid);
skb = dev_alloc_skb(sizeof(*pspoll));
if (!skb)
@@ -1137,8 +1130,9 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
if (!vp->assoc)
return;
- printk(KERN_DEBUG "%s:%s: send data::nullfunc to %pM ps=%d\n",
- wiphy_name(data->hw->wiphy), __func__, vp->bssid, ps);
+ wiphy_debug(data->hw->wiphy,
+ "%s: send data::nullfunc to %pM ps=%d\n",
+ __func__, vp->bssid, ps);
skb = dev_alloc_skb(sizeof(*hdr));
if (!skb)
@@ -1473,9 +1467,8 @@ static int __init init_mac80211_hwsim(void)
break;
}
- printk(KERN_DEBUG "%s: hwaddr %pM registered\n",
- wiphy_name(hw->wiphy),
- hw->wiphy->perm_addr);
+ wiphy_debug(hw->wiphy, "hwaddr %pm registered\n",
+ hw->wiphy->perm_addr);
data->debugfs = debugfs_create_dir("hwsim",
hw->wiphy->debugfsdir);
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 0e34260b22b1..d761ed2d8af4 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -86,7 +86,7 @@ struct rxd_ops {
void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr);
void (*rxd_refill)(void *rxd, dma_addr_t addr, int len);
int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status,
- __le16 *qos);
+ __le16 *qos, s8 *noise);
};
struct mwl8k_device_info {
@@ -207,6 +207,9 @@ struct mwl8k_priv {
/* Tasklet to perform RX. */
struct tasklet_struct poll_rx_task;
+
+ /* Most recently reported noise in dBm */
+ s8 noise;
};
/* Per interface specific private data */
@@ -741,7 +744,7 @@ static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len)
static int
mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
- __le16 *qos)
+ __le16 *qos, s8 *noise)
{
struct mwl8k_rxd_8366_ap *rxd = _rxd;
@@ -752,6 +755,7 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
memset(status, 0, sizeof(*status));
status->signal = -rxd->rssi;
+ *noise = -rxd->noise_floor;
if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) {
status->flag |= RX_FLAG_HT;
@@ -839,7 +843,7 @@ static void mwl8k_rxd_sta_refill(void *_rxd, dma_addr_t addr, int len)
static int
mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
- __le16 *qos)
+ __le16 *qos, s8 *noise)
{
struct mwl8k_rxd_sta *rxd = _rxd;
u16 rate_info;
@@ -853,6 +857,7 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
memset(status, 0, sizeof(*status));
status->signal = -rxd->rssi;
+ *noise = -rxd->noise_level;
status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info);
status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info);
@@ -905,16 +910,14 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma);
if (rxq->rxd == NULL) {
- printk(KERN_ERR "%s: failed to alloc RX descriptors\n",
- wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy, "failed to alloc rx descriptors\n");
return -ENOMEM;
}
memset(rxq->rxd, 0, size);
rxq->buf = kmalloc(MWL8K_RX_DESCS * sizeof(*rxq->buf), GFP_KERNEL);
if (rxq->buf == NULL) {
- printk(KERN_ERR "%s: failed to alloc RX skbuff list\n",
- wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy, "failed to alloc rx skbuff list\n");
pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma);
return -ENOMEM;
}
@@ -1055,7 +1058,8 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size);
- pkt_len = priv->rxd_ops->rxd_process(rxd, &status, &qos);
+ pkt_len = priv->rxd_ops->rxd_process(rxd, &status, &qos,
+ &priv->noise);
if (pkt_len < 0)
break;
@@ -1141,16 +1145,14 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
txq->txd = pci_alloc_consistent(priv->pdev, size, &txq->txd_dma);
if (txq->txd == NULL) {
- printk(KERN_ERR "%s: failed to alloc TX descriptors\n",
- wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy, "failed to alloc tx descriptors\n");
return -ENOMEM;
}
memset(txq->txd, 0, size);
txq->skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->skb), GFP_KERNEL);
if (txq->skb == NULL) {
- printk(KERN_ERR "%s: failed to alloc TX skbuff list\n",
- wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy, "failed to alloc tx skbuff list\n");
pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma);
return -ENOMEM;
}
@@ -1206,11 +1208,12 @@ static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw)
unused++;
}
- printk(KERN_ERR "%s: txq[%d] len=%d head=%d tail=%d "
- "fw_owned=%d drv_owned=%d unused=%d\n",
- wiphy_name(hw->wiphy), i,
- txq->len, txq->head, txq->tail,
- fw_owned, drv_owned, unused);
+ wiphy_err(hw->wiphy,
+ "txq[%d] len=%d head=%d tail=%d "
+ "fw_owned=%d drv_owned=%d unused=%d\n",
+ i,
+ txq->len, txq->head, txq->tail,
+ fw_owned, drv_owned, unused);
}
}
@@ -1254,25 +1257,23 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
if (timeout) {
WARN_ON(priv->pending_tx_pkts);
if (retry) {
- printk(KERN_NOTICE "%s: tx rings drained\n",
- wiphy_name(hw->wiphy));
+ wiphy_notice(hw->wiphy, "tx rings drained\n");
}
break;
}
if (priv->pending_tx_pkts < oldcount) {
- printk(KERN_NOTICE "%s: waiting for tx rings "
- "to drain (%d -> %d pkts)\n",
- wiphy_name(hw->wiphy), oldcount,
- priv->pending_tx_pkts);
+ wiphy_notice(hw->wiphy,
+ "waiting for tx rings to drain (%d -> %d pkts)\n",
+ oldcount, priv->pending_tx_pkts);
retry = 1;
continue;
}
priv->tx_wait = NULL;
- printk(KERN_ERR "%s: tx rings stuck for %d ms\n",
- wiphy_name(hw->wiphy), MWL8K_TX_WAIT_TIMEOUT_MS);
+ wiphy_err(hw->wiphy, "tx rings stuck for %d ms\n",
+ MWL8K_TX_WAIT_TIMEOUT_MS);
mwl8k_dump_tx_rings(hw);
rc = -ETIMEDOUT;
@@ -1423,8 +1424,8 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
skb->len, PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(priv->pdev, dma)) {
- printk(KERN_DEBUG "%s: failed to dma map skb, "
- "dropping TX frame.\n", wiphy_name(hw->wiphy));
+ wiphy_debug(hw->wiphy,
+ "failed to dma map skb, dropping TX frame.\n");
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
@@ -1572,10 +1573,9 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
PCI_DMA_BIDIRECTIONAL);
if (!timeout) {
- printk(KERN_ERR "%s: Command %s timeout after %u ms\n",
- wiphy_name(hw->wiphy),
- mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
- MWL8K_CMD_TIMEOUT_MS);
+ wiphy_err(hw->wiphy, "command %s timeout after %u ms\n",
+ mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
+ MWL8K_CMD_TIMEOUT_MS);
rc = -ETIMEDOUT;
} else {
int ms;
@@ -1584,15 +1584,14 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
rc = cmd->result ? -EINVAL : 0;
if (rc)
- printk(KERN_ERR "%s: Command %s error 0x%x\n",
- wiphy_name(hw->wiphy),
- mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
- le16_to_cpu(cmd->result));
+ wiphy_err(hw->wiphy, "command %s error 0x%x\n",
+ mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
+ le16_to_cpu(cmd->result));
else if (ms > 2000)
- printk(KERN_NOTICE "%s: Command %s took %d ms\n",
- wiphy_name(hw->wiphy),
- mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
- ms);
+ wiphy_notice(hw->wiphy, "command %s took %d ms\n",
+ mwl8k_cmd_name(cmd->code,
+ buf, sizeof(buf)),
+ ms);
}
return rc;
@@ -3192,8 +3191,8 @@ static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
int rc;
if (!priv->radio_on) {
- printk(KERN_DEBUG "%s: dropped TX frame since radio "
- "disabled\n", wiphy_name(hw->wiphy));
+ wiphy_debug(hw->wiphy,
+ "dropped TX frame since radio disabled\n");
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
@@ -3211,8 +3210,7 @@ static int mwl8k_start(struct ieee80211_hw *hw)
rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
IRQF_SHARED, MWL8K_NAME, hw);
if (rc) {
- printk(KERN_ERR "%s: failed to register IRQ handler\n",
- wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy, "failed to register irq handler\n");
return -EIO;
}
@@ -3299,9 +3297,8 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
* mode. (Sniffer mode is only used on STA firmware.)
*/
if (priv->sniffer_enabled) {
- printk(KERN_INFO "%s: unable to create STA "
- "interface due to sniffer mode being enabled\n",
- wiphy_name(hw->wiphy));
+ wiphy_info(hw->wiphy,
+ "unable to create STA interface because sniffer mode is enabled\n");
return -EINVAL;
}
@@ -3583,9 +3580,8 @@ mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw,
*/
if (!list_empty(&priv->vif_list)) {
if (net_ratelimit())
- printk(KERN_INFO "%s: not enabling sniffer "
- "mode because STA interface is active\n",
- wiphy_name(hw->wiphy));
+ wiphy_info(hw->wiphy,
+ "not enabling sniffer mode because STA interface is active\n");
return 0;
}
@@ -3765,6 +3761,22 @@ static int mwl8k_get_stats(struct ieee80211_hw *hw,
return mwl8k_cmd_get_stat(hw, stats);
}
+static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey)
+{
+ struct mwl8k_priv *priv = hw->priv;
+ struct ieee80211_conf *conf = &hw->conf;
+
+ if (idx != 0)
+ return -ENOENT;
+
+ survey->channel = conf->channel;
+ survey->filled = SURVEY_INFO_NOISE_DBM;
+ survey->noise = priv->noise;
+
+ return 0;
+}
+
static int
mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action,
@@ -3796,6 +3808,7 @@ static const struct ieee80211_ops mwl8k_ops = {
.sta_remove = mwl8k_sta_remove,
.conf_tx = mwl8k_conf_tx,
.get_stats = mwl8k_get_stats,
+ .get_survey = mwl8k_get_survey,
.ampdu_action = mwl8k_ampdu_action,
};
@@ -3913,8 +3926,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
priv->sram = pci_iomap(pdev, 0, 0x10000);
if (priv->sram == NULL) {
- printk(KERN_ERR "%s: Cannot map device SRAM\n",
- wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy, "cannot map device sram\n");
goto err_iounmap;
}
@@ -3926,8 +3938,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
if (priv->regs == NULL) {
priv->regs = pci_iomap(pdev, 2, 0x10000);
if (priv->regs == NULL) {
- printk(KERN_ERR "%s: Cannot map device registers\n",
- wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy, "cannot map device registers\n");
goto err_iounmap;
}
}
@@ -3939,16 +3950,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
/* Ask userland hotplug daemon for the device firmware */
rc = mwl8k_request_firmware(priv);
if (rc) {
- printk(KERN_ERR "%s: Firmware files not found\n",
- wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy, "firmware files not found\n");
goto err_stop_firmware;
}
/* Load firmware into hardware */
rc = mwl8k_load_firmware(hw);
if (rc) {
- printk(KERN_ERR "%s: Cannot start firmware\n",
- wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy, "cannot start firmware\n");
goto err_stop_firmware;
}
@@ -3959,9 +3968,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
if (priv->ap_fw) {
priv->rxd_ops = priv->device_info->ap_rxd_ops;
if (priv->rxd_ops == NULL) {
- printk(KERN_ERR "%s: Driver does not have AP "
- "firmware image support for this hardware\n",
- wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy,
+ "Driver does not have AP firmware image support for this hardware\n");
goto err_stop_firmware;
}
} else {
@@ -4039,8 +4047,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
IRQF_SHARED, MWL8K_NAME, hw);
if (rc) {
- printk(KERN_ERR "%s: failed to register IRQ handler\n",
- wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy, "failed to register irq handler\n");
goto err_free_queues;
}
@@ -4060,8 +4067,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
rc = mwl8k_cmd_get_hw_spec_sta(hw);
}
if (rc) {
- printk(KERN_ERR "%s: Cannot initialise firmware\n",
- wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy, "cannot initialise firmware\n");
goto err_free_irq;
}
@@ -4075,15 +4081,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
/* Turn radio off */
rc = mwl8k_cmd_radio_disable(hw);
if (rc) {
- printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy, "cannot disable\n");
goto err_free_irq;
}
/* Clear MAC address */
rc = mwl8k_cmd_set_mac_addr(hw, NULL, "\x00\x00\x00\x00\x00\x00");
if (rc) {
- printk(KERN_ERR "%s: Cannot clear MAC address\n",
- wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy, "cannot clear mac address\n");
goto err_free_irq;
}
@@ -4093,17 +4098,16 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
rc = ieee80211_register_hw(hw);
if (rc) {
- printk(KERN_ERR "%s: Cannot register device\n",
- wiphy_name(hw->wiphy));
+ wiphy_err(hw->wiphy, "cannot register device\n");
goto err_free_queues;
}
- printk(KERN_INFO "%s: %s v%d, %pM, %s firmware %u.%u.%u.%u\n",
- wiphy_name(hw->wiphy), priv->device_info->part_name,
- priv->hw_rev, hw->wiphy->perm_addr,
- priv->ap_fw ? "AP" : "STA",
- (priv->fw_rev >> 24) & 0xff, (priv->fw_rev >> 16) & 0xff,
- (priv->fw_rev >> 8) & 0xff, priv->fw_rev & 0xff);
+ wiphy_info(hw->wiphy, "%s v%d, %pm, %s firmware %u.%u.%u.%u\n",
+ priv->device_info->part_name,
+ priv->hw_rev, hw->wiphy->perm_addr,
+ priv->ap_fw ? "AP" : "STA",
+ (priv->fw_rev >> 24) & 0xff, (priv->fw_rev >> 16) & 0xff,
+ (priv->fw_rev >> 8) & 0xff, priv->fw_rev & 0xff);
return 0;
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index 8c4169c227ae..09fae2f0ea08 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -117,9 +117,8 @@ static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev,
case NL80211_IFTYPE_MONITOR:
if (priv->broken_monitor && !force_monitor) {
- printk(KERN_WARNING "%s: Monitor mode support is "
- "buggy in this firmware, not enabling\n",
- wiphy_name(wiphy));
+ wiphy_warn(wiphy,
+ "Monitor mode support is buggy in this firmware, not enabling\n");
err = -EINVAL;
}
break;
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c
index e51650ed49f2..d687cb7f2a59 100644
--- a/drivers/net/wireless/p54/eeprom.c
+++ b/drivers/net/wireless/p54/eeprom.c
@@ -149,16 +149,15 @@ static int p54_generate_band(struct ieee80211_hw *dev,
continue;
if (list->channels[i].data != CHAN_HAS_ALL) {
- printk(KERN_ERR "%s:%s%s%s is/are missing for "
- "channel:%d [%d MHz].\n",
- wiphy_name(dev->wiphy),
- (list->channels[i].data & CHAN_HAS_CAL ? "" :
- " [iqauto calibration data]"),
- (list->channels[i].data & CHAN_HAS_LIMIT ? "" :
- " [output power limits]"),
- (list->channels[i].data & CHAN_HAS_CURVE ? "" :
- " [curve data]"),
- list->channels[i].index, list->channels[i].freq);
+ wiphy_err(dev->wiphy,
+ "%s%s%s is/are missing for channel:%d [%d MHz].\n",
+ (list->channels[i].data & CHAN_HAS_CAL ? "" :
+ " [iqauto calibration data]"),
+ (list->channels[i].data & CHAN_HAS_LIMIT ? "" :
+ " [output power limits]"),
+ (list->channels[i].data & CHAN_HAS_CURVE ? "" :
+ " [curve data]"),
+ list->channels[i].index, list->channels[i].freq);
continue;
}
@@ -168,9 +167,8 @@ static int p54_generate_band(struct ieee80211_hw *dev,
}
if (j == 0) {
- printk(KERN_ERR "%s: Disabling totally damaged %s band.\n",
- wiphy_name(dev->wiphy), (band == IEEE80211_BAND_2GHZ) ?
- "2 GHz" : "5 GHz");
+ wiphy_err(dev->wiphy, "disabling totally damaged %d GHz band\n",
+ (band == IEEE80211_BAND_2GHZ) ? 2 : 5);
ret = -ENODATA;
goto err_out;
@@ -244,9 +242,9 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
if ((priv->iq_autocal_len != priv->curve_data->entries) ||
(priv->iq_autocal_len != priv->output_limit->entries))
- printk(KERN_ERR "%s: Unsupported or damaged EEPROM detected. "
- "You may not be able to use all channels.\n",
- wiphy_name(dev->wiphy));
+ wiphy_err(dev->wiphy,
+ "Unsupported or damaged EEPROM detected. "
+ "You may not be able to use all channels.\n");
max_channel_num = max_t(unsigned int, priv->output_limit->entries,
priv->iq_autocal_len);
@@ -419,15 +417,14 @@ static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len,
int i;
if (len != (entry_size * num_entries)) {
- printk(KERN_ERR "%s: unknown rssi calibration data packing "
- " type:(%x) len:%d.\n",
- wiphy_name(dev->wiphy), type, len);
+ wiphy_err(dev->wiphy,
+ "unknown rssi calibration data packing type:(%x) len:%d.\n",
+ type, len);
print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE,
data, len);
- printk(KERN_ERR "%s: please report this issue.\n",
- wiphy_name(dev->wiphy));
+ wiphy_err(dev->wiphy, "please report this issue.\n");
return;
}
@@ -445,15 +442,14 @@ static void p54_parse_default_country(struct ieee80211_hw *dev,
struct pda_country *country;
if (len != sizeof(*country)) {
- printk(KERN_ERR "%s: found possible invalid default country "
- "eeprom entry. (entry size: %d)\n",
- wiphy_name(dev->wiphy), len);
+ wiphy_err(dev->wiphy,
+ "found possible invalid default country eeprom entry. (entry size: %d)\n",
+ len);
print_hex_dump_bytes("country:", DUMP_PREFIX_NONE,
data, len);
- printk(KERN_ERR "%s: please report this issue.\n",
- wiphy_name(dev->wiphy));
+ wiphy_err(dev->wiphy, "please report this issue.\n");
return;
}
@@ -478,8 +474,8 @@ static int p54_convert_output_limits(struct ieee80211_hw *dev,
return -EINVAL;
if (data[0] != 0) {
- printk(KERN_ERR "%s: unknown output power db revision:%x\n",
- wiphy_name(dev->wiphy), data[0]);
+ wiphy_err(dev->wiphy, "unknown output power db revision:%x\n",
+ data[0]);
return -EINVAL;
}
@@ -587,10 +583,9 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
err = p54_convert_rev1(dev, curve_data);
break;
default:
- printk(KERN_ERR "%s: unknown curve data "
- "revision %d\n",
- wiphy_name(dev->wiphy),
- curve_data->cal_method_rev);
+ wiphy_err(dev->wiphy,
+ "unknown curve data revision %d\n",
+ curve_data->cal_method_rev);
err = -ENODEV;
break;
}
@@ -672,8 +667,8 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
if (!synth || !priv->iq_autocal || !priv->output_limit ||
!priv->curve_data) {
- printk(KERN_ERR "%s: not all required entries found in eeprom!\n",
- wiphy_name(dev->wiphy));
+ wiphy_err(dev->wiphy,
+ "not all required entries found in eeprom!\n");
err = -EINVAL;
goto err;
}
@@ -699,15 +694,15 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
u8 perm_addr[ETH_ALEN];
- printk(KERN_WARNING "%s: Invalid hwaddr! Using randomly generated MAC addr\n",
- wiphy_name(dev->wiphy));
+ wiphy_warn(dev->wiphy,
+ "invalid hwaddr! using randomly generated mac addr\n");
random_ether_addr(perm_addr);
SET_IEEE80211_PERM_ADDR(dev, perm_addr);
}
- printk(KERN_INFO "%s: hwaddr %pM, MAC:isl38%02x RF:%s\n",
- wiphy_name(dev->wiphy), dev->wiphy->perm_addr, priv->version,
- p54_rf_chips[priv->rxhw]);
+ wiphy_info(dev->wiphy, "hwaddr %pm, mac:isl38%02x rf:%s\n",
+ dev->wiphy->perm_addr, priv->version,
+ p54_rf_chips[priv->rxhw]);
return 0;
@@ -719,8 +714,7 @@ err:
priv->output_limit = NULL;
priv->curve_data = NULL;
- printk(KERN_ERR "%s: eeprom parse failed!\n",
- wiphy_name(dev->wiphy));
+ wiphy_err(dev->wiphy, "eeprom parse failed!\n");
return err;
}
EXPORT_SYMBOL_GPL(p54_parse_eeprom);
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
index c43a5d461ab2..47006bca4852 100644
--- a/drivers/net/wireless/p54/fwio.c
+++ b/drivers/net/wireless/p54/fwio.c
@@ -62,16 +62,15 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
case FW_LM20:
case FW_LM87: {
char *iftype = (char *)bootrec->data;
- printk(KERN_INFO "%s: p54 detected a LM%c%c "
- "firmware\n",
- wiphy_name(priv->hw->wiphy),
- iftype[2], iftype[3]);
+ wiphy_info(priv->hw->wiphy,
+ "p54 detected a LM%c%c firmware\n",
+ iftype[2], iftype[3]);
break;
}
case FW_FMAC:
default:
- printk(KERN_ERR "%s: unsupported firmware\n",
- wiphy_name(priv->hw->wiphy));
+ wiphy_err(priv->hw->wiphy,
+ "unsupported firmware\n");
return -ENODEV;
}
break;
@@ -125,15 +124,15 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
}
if (fw_version)
- printk(KERN_INFO "%s: FW rev %s - Softmac protocol %x.%x\n",
- wiphy_name(priv->hw->wiphy), fw_version,
- priv->fw_var >> 8, priv->fw_var & 0xff);
+ wiphy_info(priv->hw->wiphy,
+ "fw rev %s - softmac protocol %x.%x\n",
+ fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
if (priv->fw_var < 0x500)
- printk(KERN_INFO "%s: you are using an obsolete firmware. "
- "visit http://wireless.kernel.org/en/users/Drivers/p54 "
- "and grab one for \"kernel >= 2.6.28\"!\n",
- wiphy_name(priv->hw->wiphy));
+ wiphy_info(priv->hw->wiphy,
+ "you are using an obsolete firmware. "
+ "visit http://wireless.kernel.org/en/users/Drivers/p54 "
+ "and grab one for \"kernel >= 2.6.28\"!\n");
if (priv->fw_var >= 0x300) {
/* Firmware supports QoS, use it! */
@@ -152,13 +151,14 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
priv->hw->queues = P54_QUEUE_AC_NUM;
}
- printk(KERN_INFO "%s: cryptographic accelerator "
- "WEP:%s, TKIP:%s, CCMP:%s\n", wiphy_name(priv->hw->wiphy),
- (priv->privacy_caps & BR_DESC_PRIV_CAP_WEP) ? "YES" :
- "no", (priv->privacy_caps & (BR_DESC_PRIV_CAP_TKIP |
- BR_DESC_PRIV_CAP_MICHAEL)) ? "YES" : "no",
- (priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP) ?
- "YES" : "no");
+ wiphy_info(priv->hw->wiphy,
+ "cryptographic accelerator WEP:%s, TKIP:%s, CCMP:%s\n",
+ (priv->privacy_caps & BR_DESC_PRIV_CAP_WEP) ? "YES" : "no",
+ (priv->privacy_caps &
+ (BR_DESC_PRIV_CAP_TKIP | BR_DESC_PRIV_CAP_MICHAEL))
+ ? "YES" : "no",
+ (priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)
+ ? "YES" : "no");
if (priv->rx_keycache_size) {
/*
@@ -247,8 +247,7 @@ int p54_download_eeprom(struct p54_common *priv, void *buf,
if (!wait_for_completion_interruptible_timeout(
&priv->eeprom_comp, HZ)) {
- printk(KERN_ERR "%s: device does not respond!\n",
- wiphy_name(priv->hw->wiphy));
+ wiphy_err(priv->hw->wiphy, "device does not respond!\n");
ret = -EBUSY;
}
priv->eeprom = NULL;
@@ -523,9 +522,9 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
return 0;
err:
- printk(KERN_ERR "%s: frequency change to channel %d failed.\n",
- wiphy_name(priv->hw->wiphy), ieee80211_frequency_to_channel(
- priv->hw->conf.channel->center_freq));
+ wiphy_err(priv->hw->wiphy, "frequency change to channel %d failed.\n",
+ ieee80211_frequency_to_channel(
+ priv->hw->conf.channel->center_freq));
dev_kfree_skb_any(skb);
return -EINVAL;
@@ -676,8 +675,8 @@ int p54_upload_key(struct p54_common *priv, u8 algo, int slot, u8 idx, u8 len,
break;
default:
- printk(KERN_ERR "%s: invalid cryptographic algorithm: %d\n",
- wiphy_name(priv->hw->wiphy), algo);
+ wiphy_err(priv->hw->wiphy,
+ "invalid cryptographic algorithm: %d\n", algo);
dev_kfree_skb(skb);
return -EINVAL;
}
diff --git a/drivers/net/wireless/p54/led.c b/drivers/net/wireless/p54/led.c
index 9575ac033630..ea91f5cce6b3 100644
--- a/drivers/net/wireless/p54/led.c
+++ b/drivers/net/wireless/p54/led.c
@@ -57,8 +57,8 @@ static void p54_update_leds(struct work_struct *work)
err = p54_set_leds(priv);
if (err && net_ratelimit())
- printk(KERN_ERR "%s: failed to update LEDs (%d).\n",
- wiphy_name(priv->hw->wiphy), err);
+ wiphy_err(priv->hw->wiphy,
+ "failed to update leds (%d).\n", err);
if (rerun)
ieee80211_queue_delayed_work(priv->hw, &priv->led_work,
@@ -102,8 +102,8 @@ static int p54_register_led(struct p54_common *priv,
err = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_dev);
if (err)
- printk(KERN_ERR "%s: Failed to register %s LED.\n",
- wiphy_name(priv->hw->wiphy), name);
+ wiphy_err(priv->hw->wiphy,
+ "failed to register %s led.\n", name);
else
led->registered = 1;
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index c072f41747ca..47db439b63bf 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -507,6 +507,22 @@ out_unlock:
return ret;
}
+static int p54_get_survey(struct ieee80211_hw *dev, int idx,
+ struct survey_info *survey)
+{
+ struct p54_common *priv = dev->priv;
+ struct ieee80211_conf *conf = &dev->conf;
+
+ if (idx != 0)
+ return -ENOENT;
+
+ survey->channel = conf->channel;
+ survey->filled = SURVEY_INFO_NOISE_DBM;
+ survey->noise = clamp_t(s8, priv->noise, -128, 127);
+
+ return 0;
+}
+
static const struct ieee80211_ops p54_ops = {
.tx = p54_tx_80211,
.start = p54_start,
@@ -523,6 +539,7 @@ static const struct ieee80211_ops p54_ops = {
.configure_filter = p54_configure_filter,
.conf_tx = p54_conf_tx,
.get_stats = p54_get_stats,
+ .get_survey = p54_get_survey,
};
struct ieee80211_hw *p54_init_common(size_t priv_data_len)
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index a5ea89cde8c4..822f8dc26e9c 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -466,8 +466,7 @@ static int p54p_open(struct ieee80211_hw *dev)
P54P_READ(dev_int);
if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
- printk(KERN_ERR "%s: Cannot boot firmware!\n",
- wiphy_name(dev->wiphy));
+ wiphy_err(dev->wiphy, "cannot boot firmware!\n");
p54p_stop(dev);
return -ETIMEDOUT;
}
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index 4e6891099d43..427b46f558ed 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -38,8 +38,8 @@ static void p54_dump_tx_queue(struct p54_common *priv)
u32 largest_hole = 0, free;
spin_lock_irqsave(&priv->tx_queue.lock, flags);
- printk(KERN_DEBUG "%s: / --- tx queue dump (%d entries) ---\n",
- wiphy_name(priv->hw->wiphy), skb_queue_len(&priv->tx_queue));
+ wiphy_debug(priv->hw->wiphy, "/ --- tx queue dump (%d entries) ---\n",
+ skb_queue_len(&priv->tx_queue));
prev_addr = priv->rx_start;
skb_queue_walk(&priv->tx_queue, skb) {
@@ -48,21 +48,23 @@ static void p54_dump_tx_queue(struct p54_common *priv)
hdr = (void *) skb->data;
free = range->start_addr - prev_addr;
- printk(KERN_DEBUG "%s: | [%02d] => [skb:%p skb_len:0x%04x "
- "hdr:{flags:%02x len:%04x req_id:%04x type:%02x} "
- "mem:{start:%04x end:%04x, free:%d}]\n",
- wiphy_name(priv->hw->wiphy), i++, skb, skb->len,
- le16_to_cpu(hdr->flags), le16_to_cpu(hdr->len),
- le32_to_cpu(hdr->req_id), le16_to_cpu(hdr->type),
- range->start_addr, range->end_addr, free);
+ wiphy_debug(priv->hw->wiphy,
+ "| [%02d] => [skb:%p skb_len:0x%04x "
+ "hdr:{flags:%02x len:%04x req_id:%04x type:%02x} "
+ "mem:{start:%04x end:%04x, free:%d}]\n",
+ i++, skb, skb->len,
+ le16_to_cpu(hdr->flags), le16_to_cpu(hdr->len),
+ le32_to_cpu(hdr->req_id), le16_to_cpu(hdr->type),
+ range->start_addr, range->end_addr, free);
prev_addr = range->end_addr;
largest_hole = max(largest_hole, free);
}
free = priv->rx_end - prev_addr;
largest_hole = max(largest_hole, free);
- printk(KERN_DEBUG "%s: \\ --- [free: %d], largest free block: %d ---\n",
- wiphy_name(priv->hw->wiphy), free, largest_hole);
+ wiphy_debug(priv->hw->wiphy,
+ "\\ --- [free: %d], largest free block: %d ---\n",
+ free, largest_hole);
spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
}
#endif /* P54_MM_DEBUG */
@@ -538,8 +540,7 @@ static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb)
case P54_TRAP_BEACON_TX:
break;
case P54_TRAP_RADAR:
- printk(KERN_INFO "%s: radar (freq:%d MHz)\n",
- wiphy_name(priv->hw->wiphy), freq);
+ wiphy_info(priv->hw->wiphy, "radar (freq:%d mhz)\n", freq);
break;
case P54_TRAP_NO_BEACON:
if (priv->vif)
@@ -558,8 +559,8 @@ static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb)
wiphy_rfkill_set_hw_state(priv->hw->wiphy, false);
break;
default:
- printk(KERN_INFO "%s: received event:%x freq:%d\n",
- wiphy_name(priv->hw->wiphy), event, freq);
+ wiphy_info(priv->hw->wiphy, "received event:%x freq:%d\n",
+ event, freq);
break;
}
}
@@ -584,8 +585,9 @@ static int p54_rx_control(struct p54_common *priv, struct sk_buff *skb)
p54_rx_eeprom_readback(priv, skb);
break;
default:
- printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n",
- wiphy_name(priv->hw->wiphy), le16_to_cpu(hdr->type));
+ wiphy_debug(priv->hw->wiphy,
+ "not handling 0x%02x type control frame\n",
+ le16_to_cpu(hdr->type));
break;
}
return 0;
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 242d59558b79..cdaf93f48263 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -351,6 +351,14 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
if (crypto->cmd == SET_KEY) {
/*
+ * Disallow to set WEP key other than with index 0,
+ * it is known that not work at least on some hardware.
+ * SW crypto will be used in that case.
+ */
+ if (key->alg == ALG_WEP && key->keyidx != 0)
+ return -EOPNOTSUPP;
+
+ /*
* Pairwise key will always be entry 0, but this
* could collide with a shared key on the same
* position...
@@ -376,7 +384,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
if (key->hw_key_idx > 0 && crypto->cipher != curr_cipher)
return -EOPNOTSUPP;
- rt2500usb_register_multiwrite(rt2x00dev, reg,
+ rt2500usb_register_multiwrite(rt2x00dev, KEY_ENTRY(key->hw_key_idx),
crypto->key, sizeof(crypto->key));
/*
@@ -817,6 +825,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2500usb_register_write(rt2x00dev, MAC_CSR8, reg);
rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00_set_field16(&reg, TXRX_CSR0_ALGORITHM, CIPHER_NONE);
rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, 0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 4d8d2320c9fd..235e037e6509 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -273,17 +273,24 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
mutex_init(&intf->beacon_skb_mutex);
intf->beacon = entry;
- if (vif->type == NL80211_IFTYPE_AP)
- memcpy(&intf->bssid, vif->addr, ETH_ALEN);
- memcpy(&intf->mac, vif->addr, ETH_ALEN);
-
/*
* The MAC adddress must be configured after the device
* has been initialized. Otherwise the device can reset
* the MAC registers.
+ * The BSSID address must only be configured in AP mode,
+ * however we should not send an empty BSSID address for
+ * STA interfaces at this time, since this can cause
+ * invalid behavior in the device.
*/
- rt2x00lib_config_intf(rt2x00dev, intf, vif->type,
- intf->mac, intf->bssid);
+ memcpy(&intf->mac, vif->addr, ETH_ALEN);
+ if (vif->type == NL80211_IFTYPE_AP) {
+ memcpy(&intf->bssid, vif->addr, ETH_ALEN);
+ rt2x00lib_config_intf(rt2x00dev, intf, vif->type,
+ intf->mac, intf->bssid);
+ } else {
+ rt2x00lib_config_intf(rt2x00dev, intf, vif->type,
+ intf->mac, NULL);
+ }
/*
* Some filters depend on the current working mode. We can force
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c
index 31808f96a3d6..1d8178563d76 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -103,7 +103,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
{
struct rtl8180_priv *priv = dev->priv;
unsigned int count = 32;
- u8 signal;
+ u8 signal, agc, sq;
while (count--) {
struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx];
@@ -132,12 +132,16 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
rx_status.antenna = (flags2 >> 15) & 1;
rx_status.rate_idx = (flags >> 20) & 0xF;
- /* TODO: improve signal/rssi reporting for !rtl8185 */
- signal = (flags2 >> 17) & 0x7F;
- if (rx_status.rate_idx > 3)
- signal = 90 - clamp_t(u8, signal, 25, 90);
- else
- signal = 95 - clamp_t(u8, signal, 30, 95);
+ agc = (flags2 >> 17) & 0x7F;
+ if (priv->r8185) {
+ if (rx_status.rate_idx > 3)
+ signal = 90 - clamp_t(u8, agc, 25, 90);
+ else
+ signal = 95 - clamp_t(u8, agc, 30, 95);
+ } else {
+ sq = flags2 & 0xff;
+ signal = priv->rf->calc_rssi(agc, sq);
+ }
rx_status.signal = signal;
rx_status.freq = dev->conf.channel->center_freq;
rx_status.band = dev->conf.channel->band;
@@ -357,7 +361,7 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev)
/* check success of reset */
if (rtl818x_ioread8(priv, &priv->map->CMD) & RTL818X_CMD_RESET) {
- printk(KERN_ERR "%s: reset timeout!\n", wiphy_name(dev->wiphy));
+ wiphy_err(dev->wiphy, "reset timeout!\n");
return -ETIMEDOUT;
}
@@ -441,8 +445,7 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev)
&priv->rx_ring_dma);
if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) {
- printk(KERN_ERR "%s: Cannot allocate RX ring\n",
- wiphy_name(dev->wiphy));
+ wiphy_err(dev->wiphy, "cannot allocate rx ring\n");
return -ENOMEM;
}
@@ -499,8 +502,8 @@ static int rtl8180_init_tx_ring(struct ieee80211_hw *dev,
ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma);
if (!ring || (unsigned long)ring & 0xFF) {
- printk(KERN_ERR "%s: Cannot allocate TX ring (prio = %d)\n",
- wiphy_name(dev->wiphy), prio);
+ wiphy_err(dev->wiphy, "cannot allocate tx ring (prio = %d)\n",
+ prio);
return -ENOMEM;
}
@@ -565,8 +568,7 @@ static int rtl8180_start(struct ieee80211_hw *dev)
ret = request_irq(priv->pdev->irq, rtl8180_interrupt,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret) {
- printk(KERN_ERR "%s: failed to register IRQ handler\n",
- wiphy_name(dev->wiphy));
+ wiphy_err(dev->wiphy, "failed to register irq handler\n");
goto err_free_rings;
}
@@ -1103,9 +1105,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
goto err_iounmap;
}
- printk(KERN_INFO "%s: hwaddr %pM, %s + %s\n",
- wiphy_name(dev->wiphy), mac_addr,
- chip_name, priv->rf->name);
+ wiphy_info(dev->wiphy, "hwaddr %pm, %s + %s\n",
+ mac_addr, chip_name, priv->rf->name);
return 0;
diff --git a/drivers/net/wireless/rtl818x/rtl8180_grf5101.c b/drivers/net/wireless/rtl818x/rtl8180_grf5101.c
index 947ee55f18b2..5cab9dfa8c07 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_grf5101.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_grf5101.c
@@ -69,6 +69,15 @@ static void grf5101_write_phy_antenna(struct ieee80211_hw *dev, short chan)
rtl8180_write_phy(dev, 0x10, ant);
}
+static u8 grf5101_rf_calc_rssi(u8 agc, u8 sq)
+{
+ if (agc > 60)
+ return 65;
+
+ /* TODO(?): just return agc (or agc + 5) to avoid mult / div */
+ return 65 * agc / 60;
+}
+
static void grf5101_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
@@ -176,5 +185,6 @@ const struct rtl818x_rf_ops grf5101_rf_ops = {
.name = "GCT",
.init = grf5101_rf_init,
.stop = grf5101_rf_stop,
- .set_chan = grf5101_rf_set_channel
+ .set_chan = grf5101_rf_set_channel,
+ .calc_rssi = grf5101_rf_calc_rssi,
};
diff --git a/drivers/net/wireless/rtl818x/rtl8180_max2820.c b/drivers/net/wireless/rtl818x/rtl8180_max2820.c
index 6c825fd7f3b6..16c4655181c0 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_max2820.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_max2820.c
@@ -74,6 +74,22 @@ static void max2820_write_phy_antenna(struct ieee80211_hw *dev, short chan)
rtl8180_write_phy(dev, 0x10, ant);
}
+static u8 max2820_rf_calc_rssi(u8 agc, u8 sq)
+{
+ bool odd;
+
+ odd = !!(agc & 1);
+
+ agc >>= 1;
+ if (odd)
+ agc += 76;
+ else
+ agc += 66;
+
+ /* TODO: change addends above to avoid mult / div below */
+ return 65 * agc / 100;
+}
+
static void max2820_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
@@ -148,5 +164,6 @@ const struct rtl818x_rf_ops max2820_rf_ops = {
.name = "Maxim",
.init = max2820_rf_init,
.stop = max2820_rf_stop,
- .set_chan = max2820_rf_set_channel
+ .set_chan = max2820_rf_set_channel,
+ .calc_rssi = max2820_rf_calc_rssi,
};
diff --git a/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c
index 4d2be0d9672b..69e4d4745dae 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c
@@ -50,7 +50,10 @@ static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
udelay(10);
for (i = 15; i >= 0; i--) {
- u16 reg = reg80 | !!(bangdata & (1 << i));
+ u16 reg = reg80;
+
+ if (bangdata & (1 << i))
+ reg |= 1;
if (i & 1)
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
diff --git a/drivers/net/wireless/rtl818x/rtl8180_sa2400.c b/drivers/net/wireless/rtl818x/rtl8180_sa2400.c
index cea4e0ccb92d..d064fcc5ec08 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_sa2400.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_sa2400.c
@@ -76,6 +76,31 @@ static void sa2400_write_phy_antenna(struct ieee80211_hw *dev, short chan)
}
+static u8 sa2400_rf_rssi_map[] = {
+ 0x64, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e,
+ 0x5d, 0x5c, 0x5b, 0x5a, 0x57, 0x54, 0x52, 0x50,
+ 0x4e, 0x4c, 0x4a, 0x48, 0x46, 0x44, 0x41, 0x3f,
+ 0x3c, 0x3a, 0x37, 0x36, 0x36, 0x1c, 0x1c, 0x1b,
+ 0x1b, 0x1a, 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17,
+ 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13,
+ 0x13, 0x12, 0x12, 0x11, 0x11, 0x10, 0x10, 0x0f,
+ 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b,
+ 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07,
+ 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x02,
+};
+
+static u8 sa2400_rf_calc_rssi(u8 agc, u8 sq)
+{
+ if (sq == 0x80)
+ return 1;
+
+ if (sq > 78)
+ return 32;
+
+ /* TODO: recalc sa2400_rf_rssi_map to avoid mult / div */
+ return 65 * sa2400_rf_rssi_map[sq] / 100;
+}
+
static void sa2400_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
@@ -198,5 +223,6 @@ const struct rtl818x_rf_ops sa2400_rf_ops = {
.name = "Philips",
.init = sa2400_rf_init,
.stop = sa2400_rf_stop,
- .set_chan = sa2400_rf_set_channel
+ .set_chan = sa2400_rf_set_channel,
+ .calc_rssi = sa2400_rf_calc_rssi,
};
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 891b8490e349..5738a55c1b06 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -573,7 +573,7 @@ static int rtl8187_cmd_reset(struct ieee80211_hw *dev)
} while (--i);
if (!i) {
- printk(KERN_ERR "%s: Reset timeout!\n", wiphy_name(dev->wiphy));
+ wiphy_err(dev->wiphy, "reset timeout!\n");
return -ETIMEDOUT;
}
@@ -589,8 +589,7 @@ static int rtl8187_cmd_reset(struct ieee80211_hw *dev)
} while (--i);
if (!i) {
- printk(KERN_ERR "%s: eeprom reset timeout!\n",
- wiphy_name(dev->wiphy));
+ wiphy_err(dev->wiphy, "eeprom reset timeout!\n");
return -ETIMEDOUT;
}
@@ -1527,9 +1526,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
mutex_init(&priv->conf_mutex);
skb_queue_head_init(&priv->b_tx_status.queue);
- printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s, rfkill mask %d\n",
- wiphy_name(dev->wiphy), mac_addr,
- chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask);
+ wiphy_info(dev->wiphy, "hwaddr %pm, %s v%d + %s, rfkill mask %d\n",
+ mac_addr, chip_name, priv->asic_rev, priv->rf->name,
+ priv->rfkill_mask);
#ifdef CONFIG_RTL8187_LEDS
eeprom_93cx6_read(&eeprom, 0x3F, &reg);
diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
index a09819386a1e..fd96f9112322 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
@@ -366,8 +366,8 @@ static void rtl8225_rf_init(struct ieee80211_hw *dev)
rtl8225_write(dev, 0x02, 0x044d);
msleep(100);
if (!(rtl8225_read(dev, 6) & (1 << 7)))
- printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
- wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+ wiphy_warn(dev->wiphy, "rf calibration failed! %x\n",
+ rtl8225_read(dev, 6));
}
rtl8225_write(dev, 0x0, 0x127);
@@ -735,8 +735,8 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
rtl8225_write(dev, 0x02, 0x044D);
msleep(100);
if (!(rtl8225_read(dev, 6) & (1 << 7)))
- printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
- wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+ wiphy_warn(dev->wiphy, "rf calibration failed! %x\n",
+ rtl8225_read(dev, 6));
}
msleep(200);
diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h
index 978519d1ff4c..1615f63b02f6 100644
--- a/drivers/net/wireless/rtl818x/rtl818x.h
+++ b/drivers/net/wireless/rtl818x/rtl818x.h
@@ -193,6 +193,7 @@ struct rtl818x_rf_ops {
void (*stop)(struct ieee80211_hw *);
void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *);
void (*conf_erp)(struct ieee80211_hw *, struct ieee80211_bss_conf *);
+ u8 (*calc_rssi)(u8 agc, u8 sq);
};
/**
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h
index 4f5f02a26e62..6b942a28e6a5 100644
--- a/drivers/net/wireless/wl12xx/wl1251.h
+++ b/drivers/net/wireless/wl12xx/wl1251.h
@@ -381,6 +381,9 @@ struct wl1251 {
u32 chip_id;
char fw_ver[21];
+
+ /* Most recently reported noise in dBm */
+ s8 noise;
};
int wl1251_plt_start(struct wl1251 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c
index 2545123931e8..65e0416be5b6 100644
--- a/drivers/net/wireless/wl12xx/wl1251_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1251_boot.c
@@ -225,7 +225,7 @@ static void wl1251_boot_set_ecpu_ctrl(struct wl1251 *wl, u32 flag)
int wl1251_boot_run_firmware(struct wl1251 *wl)
{
int loop, ret;
- u32 chip_id, interrupt;
+ u32 chip_id, acx_intr;
wl1251_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
@@ -242,15 +242,15 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
loop = 0;
while (loop++ < INIT_LOOP) {
udelay(INIT_LOOP_DELAY);
- interrupt = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+ acx_intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
- if (interrupt == 0xffffffff) {
+ if (acx_intr == 0xffffffff) {
wl1251_error("error reading hardware complete "
"init indication");
return -EIO;
}
/* check that ACX_INTR_INIT_COMPLETE is enabled */
- else if (interrupt & WL1251_ACX_INTR_INIT_COMPLETE) {
+ else if (acx_intr & WL1251_ACX_INTR_INIT_COMPLETE) {
wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
WL1251_ACX_INTR_INIT_COMPLETE);
break;
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h
index 7e70dd5a21b8..a9e4991369be 100644
--- a/drivers/net/wireless/wl12xx/wl1251_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h
@@ -175,8 +175,8 @@ struct cmd_read_write_memory {
#define WL1251_SCAN_NUM_PROBES 3
struct wl1251_scan_parameters {
- u32 rx_config_options;
- u32 rx_filter_options;
+ __le32 rx_config_options;
+ __le32 rx_filter_options;
/*
* Scan options:
@@ -186,7 +186,7 @@ struct wl1251_scan_parameters {
* bit 2: voice mode, 0 for normal scan.
* bit 3: scan priority, 1 for high priority.
*/
- u16 scan_options;
+ __le16 scan_options;
/* Number of channels to scan */
u8 num_channels;
@@ -195,7 +195,7 @@ struct wl1251_scan_parameters {
u8 num_probe_requests;
/* Rate and modulation for probe requests */
- u16 tx_rate;
+ __le16 tx_rate;
u8 tid_trigger;
u8 ssid_len;
@@ -204,8 +204,8 @@ struct wl1251_scan_parameters {
} __packed;
struct wl1251_scan_ch_parameters {
- u32 min_duration; /* in TU */
- u32 max_duration; /* in TU */
+ __le32 min_duration; /* in TU */
+ __le32 max_duration; /* in TU */
u32 bssid_lsb;
u16 bssid_msb;
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index 38f72f417183..861a5f33761e 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -411,6 +411,7 @@ static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
static int wl1251_op_start(struct ieee80211_hw *hw)
{
struct wl1251 *wl = hw->priv;
+ struct wiphy *wiphy = hw->wiphy;
int ret = 0;
wl1251_debug(DEBUG_MAC80211, "mac80211 start");
@@ -444,6 +445,10 @@ static int wl1251_op_start(struct ieee80211_hw *hw)
wl1251_info("firmware booted (%s)", wl->fw_ver);
+ /* update hw/fw version info in wiphy struct */
+ wiphy->hw_version = wl->chip_id;
+ strncpy(wiphy->fw_version, wl->fw_ver, sizeof(wiphy->fw_version));
+
out:
if (ret < 0)
wl1251_power_off(wl);
@@ -1172,6 +1177,22 @@ out:
return ret;
}
+static int wl1251_op_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey)
+{
+ struct wl1251 *wl = hw->priv;
+ struct ieee80211_conf *conf = &hw->conf;
+
+ if (idx != 0)
+ return -ENOENT;
+
+ survey->channel = conf->channel;
+ survey->filled = SURVEY_INFO_NOISE_DBM;
+ survey->noise = wl->noise;
+
+ return 0;
+}
+
/* can't be const, mac80211 writes to this */
static struct ieee80211_supported_band wl1251_band_2ghz = {
.channels = wl1251_channels,
@@ -1193,6 +1214,7 @@ static const struct ieee80211_ops wl1251_ops = {
.bss_info_changed = wl1251_op_bss_info_changed,
.set_rts_threshold = wl1251_op_set_rts_threshold,
.conf_tx = wl1251_op_conf_tx,
+ .get_survey = wl1251_op_get_survey,
};
static int wl1251_read_eeprom_byte(struct wl1251 *wl, off_t offset, u8 *data)
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c
index 851515836a7f..1b6294b3b996 100644
--- a/drivers/net/wireless/wl12xx/wl1251_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_rx.c
@@ -74,6 +74,12 @@ static void wl1251_rx_status(struct wl1251 *wl,
status->signal = desc->rssi;
+ /*
+ * FIXME: guessing that snr needs to be divided by two, otherwise
+ * the values don't make any sense
+ */
+ wl->noise = desc->rssi - desc->snr / 2;
+
status->freq = ieee80211_channel_to_frequency(desc->channel);
status->flag |= RX_FLAG_TSFT;
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c
index c8223185efd2..a38ec199187a 100644
--- a/drivers/net/wireless/wl12xx/wl1251_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_tx.c
@@ -117,7 +117,7 @@ static void wl1251_tx_frag_block_num(struct tx_double_buffer_desc *tx_hdr)
frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
tx_hdr->frag_threshold = cpu_to_le16(frag_threshold);
- payload_len = tx_hdr->length + MAX_MSDU_SECURITY_LENGTH;
+ payload_len = le16_to_cpu(tx_hdr->length) + MAX_MSDU_SECURITY_LENGTH;
if (payload_len > frag_threshold) {
mem_blocks_per_frag =
@@ -191,11 +191,13 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb,
if (control->control.hw_key &&
control->control.hw_key->alg == ALG_TKIP) {
int hdrlen;
- u16 fc;
+ __le16 fc;
+ u16 length;
u8 *pos;
- fc = *(u16 *)(skb->data + sizeof(*tx_hdr));
- tx_hdr->length += WL1251_TKIP_IV_SPACE;
+ fc = *(__le16 *)(skb->data + sizeof(*tx_hdr));
+ length = le16_to_cpu(tx_hdr->length) + WL1251_TKIP_IV_SPACE;
+ tx_hdr->length = cpu_to_le16(length);
hdrlen = ieee80211_hdrlen(fc);
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl12xx/wl1251_tx.h
index 65c4be8c2e80..f40eeb37f5aa 100644
--- a/drivers/net/wireless/wl12xx/wl1251_tx.h
+++ b/drivers/net/wireless/wl12xx/wl1251_tx.h
@@ -114,7 +114,7 @@ struct tx_control {
struct tx_double_buffer_desc {
/* Length of payload, including headers. */
- u16 length;
+ __le16 length;
/*
* A bit mask that specifies the initial rate to be used
@@ -133,10 +133,10 @@ struct tx_double_buffer_desc {
* 0x0800 - 48Mbits
* 0x1000 - 54Mbits
*/
- u16 rate;
+ __le16 rate;
/* Time in us that a packet can spend in the target */
- u32 expiry_time;
+ __le32 expiry_time;
/* index of the TX queue used for this packet */
u8 xmit_queue;
@@ -150,7 +150,7 @@ struct tx_double_buffer_desc {
* The FW should cut the packet into fragments
* of this size.
*/
- u16 frag_threshold;
+ __le16 frag_threshold;
/* Numbers of HW queue blocks to be allocated */
u8 num_mem_blocks;
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 53d47d7a2a1d..dd3cee6ea5bb 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -475,6 +475,9 @@ struct wl1271 {
bool sg_enabled;
struct list_head list;
+
+ /* Most recently reported noise in dBm */
+ s8 noise;
};
int wl1271_plt_start(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index d30de58cef90..9d68f0012f05 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -576,7 +576,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
goto out;
}
- wl->nvs = kzalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
+ wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL);
if (!wl->nvs) {
wl1271_error("could not allocate memory for the nvs file");
@@ -584,8 +584,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
goto out;
}
- memcpy(wl->nvs, fw->data, fw->size);
-
out:
release_firmware(fw);
@@ -841,6 +839,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct wl1271 *wl = hw->priv;
+ struct wiphy *wiphy = hw->wiphy;
int retries = WL1271_BOOT_RETRIES;
int ret = 0;
@@ -894,6 +893,12 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
wl->state = WL1271_STATE_ON;
wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
+
+ /* update hw/fw version info in wiphy struct */
+ wiphy->hw_version = wl->chip.id;
+ strncpy(wiphy->fw_version, wl->chip.fw_ver,
+ sizeof(wiphy->fw_version));
+
goto out;
irq_disable:
@@ -1929,6 +1934,22 @@ out:
return mactime;
}
+static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey)
+{
+ struct wl1271 *wl = hw->priv;
+ struct ieee80211_conf *conf = &hw->conf;
+
+ if (idx != 0)
+ return -ENOENT;
+
+ survey->channel = conf->channel;
+ survey->filled = SURVEY_INFO_NOISE_DBM;
+ survey->noise = wl->noise;
+
+ return 0;
+}
+
/* can't be const, mac80211 writes to this */
static struct ieee80211_rate wl1271_rates[] = {
{ .bitrate = 10,
@@ -2158,6 +2179,7 @@ static const struct ieee80211_ops wl1271_ops = {
.set_rts_threshold = wl1271_op_set_rts_threshold,
.conf_tx = wl1271_op_conf_tx,
.get_tsf = wl1271_op_get_tsf,
+ .get_survey = wl1271_op_get_survey,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
};
@@ -2350,15 +2372,13 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
goto err_hw_alloc;
}
- plat_dev = kmalloc(sizeof(wl1271_device), GFP_KERNEL);
+ plat_dev = kmemdup(&wl1271_device, sizeof(wl1271_device), GFP_KERNEL);
if (!plat_dev) {
wl1271_error("could not allocate platform_device");
ret = -ENOMEM;
goto err_plat_alloc;
}
- memcpy(plat_dev, &wl1271_device, sizeof(wl1271_device));
-
wl = hw->priv;
memset(wl, 0, sizeof(*wl));
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index e98f22b3c3ba..019aa79cd9df 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -55,6 +55,13 @@ static void wl1271_rx_status(struct wl1271 *wl,
status->signal = desc->rssi;
+ /*
+ * FIXME: In wl1251, the SNR should be divided by two. In wl1271 we
+ * need to divide by two for now, but TI has been discussing about
+ * changing it. This needs to be rechecked.
+ */
+ wl->noise = desc->rssi - (desc->snr >> 1);
+
status->freq = ieee80211_channel_to_frequency(desc->channel);
if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) {
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 641640dc7ae5..8ea5e3374507 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -601,8 +601,11 @@ static int ioc_settimeout(unsigned int fd, unsigned int cmd,
}
/* Bluetooth ioctls */
-#define HCIUARTSETPROTO _IOW('U', 200, int)
-#define HCIUARTGETPROTO _IOR('U', 201, int)
+#define HCIUARTSETPROTO _IOW('U', 200, int)
+#define HCIUARTGETPROTO _IOR('U', 201, int)
+#define HCIUARTGETDEVICE _IOR('U', 202, int)
+#define HCIUARTSETFLAGS _IOW('U', 203, int)
+#define HCIUARTGETFLAGS _IOR('U', 204, int)
#define BNEPCONNADD _IOW('B', 200, int)
#define BNEPCONNDEL _IOW('B', 201, int)
@@ -1328,6 +1331,8 @@ COMPATIBLE_IOCTL(HCISETLINKPOL)
COMPATIBLE_IOCTL(HCISETLINKMODE)
COMPATIBLE_IOCTL(HCISETACLMTU)
COMPATIBLE_IOCTL(HCISETSCOMTU)
+COMPATIBLE_IOCTL(HCIBLOCKADDR)
+COMPATIBLE_IOCTL(HCIUNBLOCKADDR)
COMPATIBLE_IOCTL(HCIINQUIRY)
COMPATIBLE_IOCTL(HCIUARTSETPROTO)
COMPATIBLE_IOCTL(HCIUARTGETPROTO)
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index ff77e8f882f1..27a902d9b3a9 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -84,7 +84,7 @@ enum {
/* BD Address */
typedef struct {
__u8 b[6];
-} __attribute__((packed)) bdaddr_t;
+} __packed bdaddr_t;
#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}})
#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
@@ -138,6 +138,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
struct bt_skb_cb {
__u8 pkt_type;
__u8 incoming;
+ __u16 expect;
__u8 tx_seq;
__u8 retries;
__u8 sar;
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index fc0c502d9fd1..bcbdd6d4e6dd 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -100,6 +100,9 @@ enum {
#define HCISETACLMTU _IOW('H', 227, int)
#define HCISETSCOMTU _IOW('H', 228, int)
+#define HCIBLOCKADDR _IOW('H', 230, int)
+#define HCIUNBLOCKADDR _IOW('H', 231, int)
+
#define HCIINQUIRY _IOR('H', 240, int)
/* HCI timeouts */
@@ -227,7 +230,7 @@ struct hci_cp_inquiry {
__u8 lap[3];
__u8 length;
__u8 num_rsp;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_INQUIRY_CANCEL 0x0402
@@ -241,81 +244,81 @@ struct hci_cp_create_conn {
__u8 pscan_mode;
__le16 clock_offset;
__u8 role_switch;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_DISCONNECT 0x0406
struct hci_cp_disconnect {
__le16 handle;
__u8 reason;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_ADD_SCO 0x0407
struct hci_cp_add_sco {
__le16 handle;
__le16 pkt_type;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_CREATE_CONN_CANCEL 0x0408
struct hci_cp_create_conn_cancel {
bdaddr_t bdaddr;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_ACCEPT_CONN_REQ 0x0409
struct hci_cp_accept_conn_req {
bdaddr_t bdaddr;
__u8 role;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_REJECT_CONN_REQ 0x040a
struct hci_cp_reject_conn_req {
bdaddr_t bdaddr;
__u8 reason;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_LINK_KEY_REPLY 0x040b
struct hci_cp_link_key_reply {
bdaddr_t bdaddr;
__u8 link_key[16];
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_LINK_KEY_NEG_REPLY 0x040c
struct hci_cp_link_key_neg_reply {
bdaddr_t bdaddr;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_PIN_CODE_REPLY 0x040d
struct hci_cp_pin_code_reply {
bdaddr_t bdaddr;
__u8 pin_len;
__u8 pin_code[16];
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_PIN_CODE_NEG_REPLY 0x040e
struct hci_cp_pin_code_neg_reply {
bdaddr_t bdaddr;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_CHANGE_CONN_PTYPE 0x040f
struct hci_cp_change_conn_ptype {
__le16 handle;
__le16 pkt_type;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_AUTH_REQUESTED 0x0411
struct hci_cp_auth_requested {
__le16 handle;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_SET_CONN_ENCRYPT 0x0413
struct hci_cp_set_conn_encrypt {
__le16 handle;
__u8 encrypt;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_CHANGE_CONN_LINK_KEY 0x0415
struct hci_cp_change_conn_link_key {
__le16 handle;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_REMOTE_NAME_REQ 0x0419
struct hci_cp_remote_name_req {
@@ -323,28 +326,28 @@ struct hci_cp_remote_name_req {
__u8 pscan_rep_mode;
__u8 pscan_mode;
__le16 clock_offset;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_REMOTE_NAME_REQ_CANCEL 0x041a
struct hci_cp_remote_name_req_cancel {
bdaddr_t bdaddr;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_READ_REMOTE_FEATURES 0x041b
struct hci_cp_read_remote_features {
__le16 handle;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_READ_REMOTE_EXT_FEATURES 0x041c
struct hci_cp_read_remote_ext_features {
__le16 handle;
__u8 page;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_READ_REMOTE_VERSION 0x041d
struct hci_cp_read_remote_version {
__le16 handle;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_SETUP_SYNC_CONN 0x0428
struct hci_cp_setup_sync_conn {
@@ -355,7 +358,7 @@ struct hci_cp_setup_sync_conn {
__le16 voice_setting;
__u8 retrans_effort;
__le16 pkt_type;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_ACCEPT_SYNC_CONN_REQ 0x0429
struct hci_cp_accept_sync_conn_req {
@@ -366,13 +369,13 @@ struct hci_cp_accept_sync_conn_req {
__le16 content_format;
__u8 retrans_effort;
__le16 pkt_type;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_REJECT_SYNC_CONN_REQ 0x042a
struct hci_cp_reject_sync_conn_req {
bdaddr_t bdaddr;
__u8 reason;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_SNIFF_MODE 0x0803
struct hci_cp_sniff_mode {
@@ -381,59 +384,59 @@ struct hci_cp_sniff_mode {
__le16 min_interval;
__le16 attempt;
__le16 timeout;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_EXIT_SNIFF_MODE 0x0804
struct hci_cp_exit_sniff_mode {
__le16 handle;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_ROLE_DISCOVERY 0x0809
struct hci_cp_role_discovery {
__le16 handle;
-} __attribute__ ((packed));
+} __packed;
struct hci_rp_role_discovery {
__u8 status;
__le16 handle;
__u8 role;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_SWITCH_ROLE 0x080b
struct hci_cp_switch_role {
bdaddr_t bdaddr;
__u8 role;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_READ_LINK_POLICY 0x080c
struct hci_cp_read_link_policy {
__le16 handle;
-} __attribute__ ((packed));
+} __packed;
struct hci_rp_read_link_policy {
__u8 status;
__le16 handle;
__le16 policy;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_WRITE_LINK_POLICY 0x080d
struct hci_cp_write_link_policy {
__le16 handle;
__le16 policy;
-} __attribute__ ((packed));
+} __packed;
struct hci_rp_write_link_policy {
__u8 status;
__le16 handle;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_READ_DEF_LINK_POLICY 0x080e
struct hci_rp_read_def_link_policy {
__u8 status;
__le16 policy;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_WRITE_DEF_LINK_POLICY 0x080f
struct hci_cp_write_def_link_policy {
__le16 policy;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_SNIFF_SUBRATE 0x0811
struct hci_cp_sniff_subrate {
@@ -441,12 +444,12 @@ struct hci_cp_sniff_subrate {
__le16 max_latency;
__le16 min_remote_timeout;
__le16 min_local_timeout;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_SET_EVENT_MASK 0x0c01
struct hci_cp_set_event_mask {
__u8 mask[8];
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_RESET 0x0c03
@@ -455,7 +458,7 @@ struct hci_cp_set_event_flt {
__u8 flt_type;
__u8 cond_type;
__u8 condition[0];
-} __attribute__ ((packed));
+} __packed;
/* Filter types */
#define HCI_FLT_CLEAR_ALL 0x00
@@ -474,13 +477,13 @@ struct hci_cp_set_event_flt {
#define HCI_OP_WRITE_LOCAL_NAME 0x0c13
struct hci_cp_write_local_name {
__u8 name[248];
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_READ_LOCAL_NAME 0x0c14
struct hci_rp_read_local_name {
__u8 status;
__u8 name[248];
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_WRITE_CA_TIMEOUT 0x0c16
@@ -508,23 +511,23 @@ struct hci_rp_read_local_name {
struct hci_rp_read_class_of_dev {
__u8 status;
__u8 dev_class[3];
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_WRITE_CLASS_OF_DEV 0x0c24
struct hci_cp_write_class_of_dev {
__u8 dev_class[3];
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_READ_VOICE_SETTING 0x0c25
struct hci_rp_read_voice_setting {
__u8 status;
__le16 voice_setting;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_WRITE_VOICE_SETTING 0x0c26
struct hci_cp_write_voice_setting {
__le16 voice_setting;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_HOST_BUFFER_SIZE 0x0c33
struct hci_cp_host_buffer_size {
@@ -532,18 +535,18 @@ struct hci_cp_host_buffer_size {
__u8 sco_mtu;
__le16 acl_max_pkt;
__le16 sco_max_pkt;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_READ_SSP_MODE 0x0c55
struct hci_rp_read_ssp_mode {
__u8 status;
__u8 mode;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_WRITE_SSP_MODE 0x0c56
struct hci_cp_write_ssp_mode {
__u8 mode;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_READ_LOCAL_VERSION 0x1001
struct hci_rp_read_local_version {
@@ -553,19 +556,19 @@ struct hci_rp_read_local_version {
__u8 lmp_ver;
__le16 manufacturer;
__le16 lmp_subver;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_READ_LOCAL_COMMANDS 0x1002
struct hci_rp_read_local_commands {
__u8 status;
__u8 commands[64];
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_READ_LOCAL_FEATURES 0x1003
struct hci_rp_read_local_features {
__u8 status;
__u8 features[8];
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_READ_LOCAL_EXT_FEATURES 0x1004
struct hci_rp_read_local_ext_features {
@@ -573,7 +576,7 @@ struct hci_rp_read_local_ext_features {
__u8 page;
__u8 max_page;
__u8 features[8];
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_READ_BUFFER_SIZE 0x1005
struct hci_rp_read_buffer_size {
@@ -582,13 +585,13 @@ struct hci_rp_read_buffer_size {
__u8 sco_mtu;
__le16 acl_max_pkt;
__le16 sco_max_pkt;
-} __attribute__ ((packed));
+} __packed;
#define HCI_OP_READ_BD_ADDR 0x1009
struct hci_rp_read_bd_addr {
__u8 status;
bdaddr_t bdaddr;
-} __attribute__ ((packed));
+} __packed;
/* ---- HCI Events ---- */
#define HCI_EV_INQUIRY_COMPLETE 0x01
@@ -601,7 +604,7 @@ struct inquiry_info {
__u8 pscan_mode;
__u8 dev_class[3];
__le16 clock_offset;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_CONN_COMPLETE 0x03
struct hci_ev_conn_complete {
@@ -610,54 +613,54 @@ struct hci_ev_conn_complete {
bdaddr_t bdaddr;
__u8 link_type;
__u8 encr_mode;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_CONN_REQUEST 0x04
struct hci_ev_conn_request {
bdaddr_t bdaddr;
__u8 dev_class[3];
__u8 link_type;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_DISCONN_COMPLETE 0x05
struct hci_ev_disconn_complete {
__u8 status;
__le16 handle;
__u8 reason;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_AUTH_COMPLETE 0x06
struct hci_ev_auth_complete {
__u8 status;
__le16 handle;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_REMOTE_NAME 0x07
struct hci_ev_remote_name {
__u8 status;
bdaddr_t bdaddr;
__u8 name[248];
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_ENCRYPT_CHANGE 0x08
struct hci_ev_encrypt_change {
__u8 status;
__le16 handle;
__u8 encrypt;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_CHANGE_LINK_KEY_COMPLETE 0x09
struct hci_ev_change_link_key_complete {
__u8 status;
__le16 handle;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_REMOTE_FEATURES 0x0b
struct hci_ev_remote_features {
__u8 status;
__le16 handle;
__u8 features[8];
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_REMOTE_VERSION 0x0c
struct hci_ev_remote_version {
@@ -666,7 +669,7 @@ struct hci_ev_remote_version {
__u8 lmp_ver;
__le16 manufacturer;
__le16 lmp_subver;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_QOS_SETUP_COMPLETE 0x0d
struct hci_qos {
@@ -675,38 +678,38 @@ struct hci_qos {
__u32 peak_bandwidth;
__u32 latency;
__u32 delay_variation;
-} __attribute__ ((packed));
+} __packed;
struct hci_ev_qos_setup_complete {
__u8 status;
__le16 handle;
struct hci_qos qos;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_CMD_COMPLETE 0x0e
struct hci_ev_cmd_complete {
__u8 ncmd;
__le16 opcode;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_CMD_STATUS 0x0f
struct hci_ev_cmd_status {
__u8 status;
__u8 ncmd;
__le16 opcode;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_ROLE_CHANGE 0x12
struct hci_ev_role_change {
__u8 status;
bdaddr_t bdaddr;
__u8 role;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_NUM_COMP_PKTS 0x13
struct hci_ev_num_comp_pkts {
__u8 num_hndl;
/* variable length part */
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_MODE_CHANGE 0x14
struct hci_ev_mode_change {
@@ -714,44 +717,44 @@ struct hci_ev_mode_change {
__le16 handle;
__u8 mode;
__le16 interval;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_PIN_CODE_REQ 0x16
struct hci_ev_pin_code_req {
bdaddr_t bdaddr;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_LINK_KEY_REQ 0x17
struct hci_ev_link_key_req {
bdaddr_t bdaddr;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_LINK_KEY_NOTIFY 0x18
struct hci_ev_link_key_notify {
bdaddr_t bdaddr;
__u8 link_key[16];
__u8 key_type;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_CLOCK_OFFSET 0x1c
struct hci_ev_clock_offset {
__u8 status;
__le16 handle;
__le16 clock_offset;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_PKT_TYPE_CHANGE 0x1d
struct hci_ev_pkt_type_change {
__u8 status;
__le16 handle;
__le16 pkt_type;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_PSCAN_REP_MODE 0x20
struct hci_ev_pscan_rep_mode {
bdaddr_t bdaddr;
__u8 pscan_rep_mode;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22
struct inquiry_info_with_rssi {
@@ -761,7 +764,7 @@ struct inquiry_info_with_rssi {
__u8 dev_class[3];
__le16 clock_offset;
__s8 rssi;
-} __attribute__ ((packed));
+} __packed;
struct inquiry_info_with_rssi_and_pscan_mode {
bdaddr_t bdaddr;
__u8 pscan_rep_mode;
@@ -770,7 +773,7 @@ struct inquiry_info_with_rssi_and_pscan_mode {
__u8 dev_class[3];
__le16 clock_offset;
__s8 rssi;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_REMOTE_EXT_FEATURES 0x23
struct hci_ev_remote_ext_features {
@@ -779,7 +782,7 @@ struct hci_ev_remote_ext_features {
__u8 page;
__u8 max_page;
__u8 features[8];
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_SYNC_CONN_COMPLETE 0x2c
struct hci_ev_sync_conn_complete {
@@ -792,7 +795,7 @@ struct hci_ev_sync_conn_complete {
__le16 rx_pkt_len;
__le16 tx_pkt_len;
__u8 air_mode;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_SYNC_CONN_CHANGED 0x2d
struct hci_ev_sync_conn_changed {
@@ -802,7 +805,7 @@ struct hci_ev_sync_conn_changed {
__u8 retrans_window;
__le16 rx_pkt_len;
__le16 tx_pkt_len;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_SNIFF_SUBRATE 0x2e
struct hci_ev_sniff_subrate {
@@ -812,7 +815,7 @@ struct hci_ev_sniff_subrate {
__le16 max_rx_latency;
__le16 max_remote_timeout;
__le16 max_local_timeout;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2f
struct extended_inquiry_info {
@@ -823,37 +826,37 @@ struct extended_inquiry_info {
__le16 clock_offset;
__s8 rssi;
__u8 data[240];
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_IO_CAPA_REQUEST 0x31
struct hci_ev_io_capa_request {
bdaddr_t bdaddr;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36
struct hci_ev_simple_pair_complete {
__u8 status;
bdaddr_t bdaddr;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_REMOTE_HOST_FEATURES 0x3d
struct hci_ev_remote_host_features {
bdaddr_t bdaddr;
__u8 features[8];
-} __attribute__ ((packed));
+} __packed;
/* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xfd
struct hci_ev_stack_internal {
__u16 type;
__u8 data[0];
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_SI_DEVICE 0x01
struct hci_ev_si_device {
__u16 event;
__u16 dev_id;
-} __attribute__ ((packed));
+} __packed;
#define HCI_EV_SI_SECURITY 0x02
struct hci_ev_si_security {
@@ -861,7 +864,7 @@ struct hci_ev_si_security {
__u16 proto;
__u16 subproto;
__u8 incoming;
-} __attribute__ ((packed));
+} __packed;
/* ---- HCI Packet structures ---- */
#define HCI_COMMAND_HDR_SIZE 3
@@ -872,22 +875,22 @@ struct hci_ev_si_security {
struct hci_command_hdr {
__le16 opcode; /* OCF & OGF */
__u8 plen;
-} __attribute__ ((packed));
+} __packed;
struct hci_event_hdr {
__u8 evt;
__u8 plen;
-} __attribute__ ((packed));
+} __packed;
struct hci_acl_hdr {
__le16 handle; /* Handle & Flags(PB, BC) */
__le16 dlen;
-} __attribute__ ((packed));
+} __packed;
struct hci_sco_hdr {
__le16 handle;
__u8 dlen;
-} __attribute__ ((packed));
+} __packed;
#ifdef __KERNEL__
#include <linux/skbuff.h>
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index e42f6ed5421c..8b28962e737e 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1,6 +1,6 @@
-/*
+/*
BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
+ Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@@ -12,13 +12,13 @@
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
- CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
- COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
@@ -62,6 +62,11 @@ struct hci_conn_hash {
unsigned int sco_num;
};
+struct bdaddr_list {
+ struct list_head list;
+ bdaddr_t bdaddr;
+};
+#define NUM_REASSEMBLY 4
struct hci_dev {
struct list_head list;
spinlock_t lock;
@@ -118,7 +123,7 @@ struct hci_dev {
struct sk_buff_head cmd_q;
struct sk_buff *sent_cmd;
- struct sk_buff *reassembly[3];
+ struct sk_buff *reassembly[NUM_REASSEMBLY];
struct mutex req_lock;
wait_queue_head_t req_wait_q;
@@ -127,6 +132,7 @@ struct hci_dev {
struct inquiry_cache inq_cache;
struct hci_conn_hash conn_hash;
+ struct bdaddr_list blacklist;
struct hci_dev_stats stat;
@@ -250,6 +256,7 @@ enum {
HCI_CONN_ENCRYPT_PEND,
HCI_CONN_RSWITCH_PEND,
HCI_CONN_MODE_CHANGE_PEND,
+ HCI_CONN_SCO_SETUP_PEND,
};
static inline void hci_conn_hash_init(struct hci_dev *hdev)
@@ -330,6 +337,7 @@ void hci_acl_connect(struct hci_conn *conn);
void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
void hci_add_sco(struct hci_conn *conn, __u16 handle);
void hci_setup_sync(struct hci_conn *conn, __u16 handle);
+void hci_sco_setup(struct hci_conn *conn, __u8 status);
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
int hci_conn_del(struct hci_conn *conn);
@@ -380,7 +388,7 @@ static inline void __hci_dev_put(struct hci_dev *d)
}
static inline void hci_dev_put(struct hci_dev *d)
-{
+{
__hci_dev_put(d);
module_put(d->owner);
}
@@ -424,10 +432,14 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg);
int hci_get_auth_info(struct hci_dev *hdev, void __user *arg);
int hci_inquiry(void __user *arg);
+struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_blacklist_clear(struct hci_dev *hdev);
+
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
int hci_recv_frame(struct sk_buff *skb);
int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count);
+int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count);
int hci_register_sysfs(struct hci_dev *hdev);
void hci_unregister_sysfs(struct hci_dev *hdev);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 7c695bfd853c..636724b203ee 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -1,6 +1,8 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
+ Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
+ Copyright (C) 2010 Google Inc.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@@ -129,31 +131,31 @@ struct l2cap_conninfo {
struct l2cap_hdr {
__le16 len;
__le16 cid;
-} __attribute__ ((packed));
+} __packed;
#define L2CAP_HDR_SIZE 4
struct l2cap_cmd_hdr {
__u8 code;
__u8 ident;
__le16 len;
-} __attribute__ ((packed));
+} __packed;
#define L2CAP_CMD_HDR_SIZE 4
struct l2cap_cmd_rej {
__le16 reason;
-} __attribute__ ((packed));
+} __packed;
struct l2cap_conn_req {
__le16 psm;
__le16 scid;
-} __attribute__ ((packed));
+} __packed;
struct l2cap_conn_rsp {
__le16 dcid;
__le16 scid;
__le16 result;
__le16 status;
-} __attribute__ ((packed));
+} __packed;
/* channel indentifier */
#define L2CAP_CID_SIGNALING 0x0001
@@ -177,14 +179,14 @@ struct l2cap_conf_req {
__le16 dcid;
__le16 flags;
__u8 data[0];
-} __attribute__ ((packed));
+} __packed;
struct l2cap_conf_rsp {
__le16 scid;
__le16 flags;
__le16 result;
__u8 data[0];
-} __attribute__ ((packed));
+} __packed;
#define L2CAP_CONF_SUCCESS 0x0000
#define L2CAP_CONF_UNACCEPT 0x0001
@@ -195,7 +197,7 @@ struct l2cap_conf_opt {
__u8 type;
__u8 len;
__u8 val[0];
-} __attribute__ ((packed));
+} __packed;
#define L2CAP_CONF_OPT_SIZE 2
#define L2CAP_CONF_HINT 0x80
@@ -216,7 +218,7 @@ struct l2cap_conf_rfc {
__le16 retrans_timeout;
__le16 monitor_timeout;
__le16 max_pdu_size;
-} __attribute__ ((packed));
+} __packed;
#define L2CAP_MODE_BASIC 0x00
#define L2CAP_MODE_RETRANS 0x01
@@ -227,22 +229,22 @@ struct l2cap_conf_rfc {
struct l2cap_disconn_req {
__le16 dcid;
__le16 scid;
-} __attribute__ ((packed));
+} __packed;
struct l2cap_disconn_rsp {
__le16 dcid;
__le16 scid;
-} __attribute__ ((packed));
+} __packed;
struct l2cap_info_req {
__le16 type;
-} __attribute__ ((packed));
+} __packed;
struct l2cap_info_rsp {
__le16 type;
__le16 result;
__u8 data[0];
-} __attribute__ ((packed));
+} __packed;
/* info type */
#define L2CAP_IT_CL_MTU 0x0001
@@ -287,6 +289,11 @@ struct l2cap_conn {
struct l2cap_chan_list chan_list;
};
+struct sock_del_list {
+ struct sock *sk;
+ struct list_head list;
+};
+
#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
#define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04
#define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08
@@ -353,7 +360,6 @@ struct l2cap_pinfo {
__le16 sport;
- spinlock_t send_lock;
struct timer_list retrans_timer;
struct timer_list monitor_timer;
struct timer_list ack_timer;
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 921d7b3c7f8d..a140847d622c 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -106,19 +106,19 @@ struct rfcomm_hdr {
u8 addr;
u8 ctrl;
u8 len; // Actual size can be 2 bytes
-} __attribute__ ((packed));
+} __packed;
struct rfcomm_cmd {
u8 addr;
u8 ctrl;
u8 len;
u8 fcs;
-} __attribute__ ((packed));
+} __packed;
struct rfcomm_mcc {
u8 type;
u8 len;
-} __attribute__ ((packed));
+} __packed;
struct rfcomm_pn {
u8 dlci;
@@ -128,7 +128,7 @@ struct rfcomm_pn {
__le16 mtu;
u8 max_retrans;
u8 credits;
-} __attribute__ ((packed));
+} __packed;
struct rfcomm_rpn {
u8 dlci;
@@ -138,17 +138,17 @@ struct rfcomm_rpn {
u8 xon_char;
u8 xoff_char;
__le16 param_mask;
-} __attribute__ ((packed));
+} __packed;
struct rfcomm_rls {
u8 dlci;
u8 status;
-} __attribute__ ((packed));
+} __packed;
struct rfcomm_msc {
u8 dlci;
u8 v24_sig;
-} __attribute__ ((packed));
+} __packed;
/* ---- Core structures, flags etc ---- */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4d1f19d70798..2fd06c60ffbb 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1416,7 +1416,7 @@ static inline struct device *wiphy_dev(struct wiphy *wiphy)
*
* @wiphy: The wiphy whose name to return
*/
-static inline const char *wiphy_name(struct wiphy *wiphy)
+static inline const char *wiphy_name(const struct wiphy *wiphy)
{
return dev_name(&wiphy->dev);
}
@@ -2420,4 +2420,67 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
enum nl80211_cqm_rssi_threshold_event rssi_event,
gfp_t gfp);
+#ifdef __KERNEL__
+
+/* Logging, debugging and troubleshooting/diagnostic helpers. */
+
+/* wiphy_printk helpers, similar to dev_printk */
+
+#define wiphy_printk(level, wiphy, format, args...) \
+ printk(level "%s: " format, wiphy_name(wiphy), ##args)
+#define wiphy_emerg(wiphy, format, args...) \
+ wiphy_printk(KERN_EMERG, wiphy, format, ##args)
+#define wiphy_alert(wiphy, format, args...) \
+ wiphy_printk(KERN_ALERT, wiphy, format, ##args)
+#define wiphy_crit(wiphy, format, args...) \
+ wiphy_printk(KERN_CRIT, wiphy, format, ##args)
+#define wiphy_err(wiphy, format, args...) \
+ wiphy_printk(KERN_ERR, wiphy, format, ##args)
+#define wiphy_warn(wiphy, format, args...) \
+ wiphy_printk(KERN_WARNING, wiphy, format, ##args)
+#define wiphy_notice(wiphy, format, args...) \
+ wiphy_printk(KERN_NOTICE, wiphy, format, ##args)
+#define wiphy_info(wiphy, format, args...) \
+ wiphy_printk(KERN_INFO, wiphy, format, ##args)
+
+int wiphy_debug(const struct wiphy *wiphy, const char *format, ...)
+ __attribute__ ((format (printf, 2, 3)));
+
+#if defined(DEBUG)
+#define wiphy_dbg(wiphy, format, args...) \
+ wiphy_printk(KERN_DEBUG, wiphy, format, ##args)
+#elif defined(CONFIG_DYNAMIC_DEBUG)
+#define wiphy_dbg(wiphy, format, args...) \
+ dynamic_pr_debug("%s: " format, wiphy_name(wiphy), ##args)
+#else
+#define wiphy_dbg(wiphy, format, args...) \
+({ \
+ if (0) \
+ wiphy_printk(KERN_DEBUG, wiphy, format, ##args); \
+ 0; \
+})
+#endif
+
+#if defined(VERBOSE_DEBUG)
+#define wiphy_vdbg wiphy_dbg
+#else
+
+#define wiphy_vdbg(wiphy, format, args...) \
+({ \
+ if (0) \
+ wiphy_printk(KERN_DEBUG, wiphy, format, ##args); \
+ 0; \
+})
+#endif
+
+/*
+ * wiphy_WARN() acts like wiphy_printk(), but with the key difference
+ * of using a WARN/WARN_ON to get the message out, including the
+ * file/line information and a backtrace.
+ */
+#define wiphy_WARN(wiphy, format, args...) \
+ WARN(1, "wiphy: %s\n" format, wiphy_name(wiphy), ##args);
+
+#endif
+
#endif /* __NET_CFG80211_H */
diff --git a/include/net/lib80211.h b/include/net/lib80211.h
index fb4e2784857d..848cce1bb7a5 100644
--- a/include/net/lib80211.h
+++ b/include/net/lib80211.h
@@ -54,9 +54,6 @@ struct lib80211_crypto_ops {
/* deinitialize crypto context and free allocated private data */
void (*deinit) (void *priv);
- int (*build_iv) (struct sk_buff * skb, int hdr_len,
- u8 *key, int keylen, void *priv);
-
/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
* value from decrypt_mpdu is passed as the keyidx value for
* decrypt_msdu. skb must have enough head and tail room for the
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 837353bfcb20..b0787a1dea90 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -194,7 +194,9 @@ enum ieee80211_bss_change {
* if the hardware cannot handle this it must set the
* IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag
* @dtim_period: num of beacons before the next DTIM, for beaconing,
- * not valid in station mode (cf. hw conf ps_dtim_period)
+ * valid in station mode only while @assoc is true and if also
+ * requested by %IEEE80211_HW_NEED_DTIM_PERIOD (cf. also hw conf
+ * @ps_dtim_period)
* @timestamp: beacon timestamp
* @beacon_int: beacon interval
* @assoc_capability: capabilities taken from assoc resp
@@ -625,11 +627,14 @@ struct ieee80211_rx_status {
* may turn the device off as much as possible. Typically, this flag will
* be set when an interface is set UP but not associated or scanning, but
* it can also be unset in that case when monitor interfaces are active.
+ * @IEEE80211_CONF_OFFCHANNEL: The device is currently not on its main
+ * operating channel.
*/
enum ieee80211_conf_flags {
IEEE80211_CONF_MONITOR = (1<<0),
IEEE80211_CONF_PS = (1<<1),
IEEE80211_CONF_IDLE = (1<<2),
+ IEEE80211_CONF_OFFCHANNEL = (1<<3),
};
@@ -1024,6 +1029,9 @@ enum ieee80211_tkip_key_type {
* connection quality related parameters, such as the RSSI level and
* provide notifications if configured trigger levels are reached.
*
+ * @IEEE80211_HW_NEED_DTIM_PERIOD:
+ * This device needs to know the DTIM period for the BSS before
+ * associating.
*/
enum ieee80211_hw_flags {
IEEE80211_HW_HAS_RATE_CONTROL = 1<<0,
@@ -1033,7 +1041,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4,
IEEE80211_HW_SIGNAL_UNSPEC = 1<<5,
IEEE80211_HW_SIGNAL_DBM = 1<<6,
- /* use this hole */
+ IEEE80211_HW_NEED_DTIM_PERIOD = 1<<7,
IEEE80211_HW_SPECTRUM_MGMT = 1<<8,
IEEE80211_HW_AMPDU_AGGREGATION = 1<<9,
IEEE80211_HW_SUPPORTS_PS = 1<<10,
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index ee3b3049d385..ed371684c133 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -43,19 +43,6 @@ config BT_L2CAP
Say Y here to compile L2CAP support into the kernel or say M to
compile it as module (l2cap).
-config BT_L2CAP_EXT_FEATURES
- bool "L2CAP Extended Features support (EXPERIMENTAL)"
- depends on BT_L2CAP && EXPERIMENTAL
- help
- This option enables the L2CAP Extended Features support. These
- new features include the Enhanced Retransmission and Streaming
- Modes, the Frame Check Sequence (FCS), and Segmentation and
- Reassembly (SAR) for L2CAP packets. They are a required for the
- new Alternate MAC/PHY and the Bluetooth Medical Profile.
-
- You should say N unless you know what you are doing. Note that
- this is in an experimental state yet.
-
config BT_SCO
tristate "SCO links support"
depends on BT
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 800b6b9fbbae..0b1e460fe440 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -1,6 +1,6 @@
/*
BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
+ Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@@ -155,6 +155,27 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
}
+/* Device _must_ be locked */
+void hci_sco_setup(struct hci_conn *conn, __u8 status)
+{
+ struct hci_conn *sco = conn->link;
+
+ BT_DBG("%p", conn);
+
+ if (!sco)
+ return;
+
+ if (!status) {
+ if (lmp_esco_capable(conn->hdev))
+ hci_setup_sync(sco, conn->handle);
+ else
+ hci_add_sco(sco, conn->handle);
+ } else {
+ hci_proto_connect_cfm(sco, status);
+ hci_conn_del(sco);
+ }
+}
+
static void hci_conn_timeout(unsigned long arg)
{
struct hci_conn *conn = (void *) arg;
@@ -385,10 +406,13 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
acl->power_save = 1;
hci_conn_enter_active_mode(acl);
- if (lmp_esco_capable(hdev))
- hci_setup_sync(sco, acl->handle);
- else
- hci_add_sco(sco, acl->handle);
+ if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
+ /* defer SCO setup until mode change completed */
+ set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->pend);
+ return sco;
+ }
+
+ hci_sco_setup(acl, 0x00);
}
return sco;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 2f768de87011..8303f1c9ef54 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -562,6 +562,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
hci_dev_lock_bh(hdev);
inquiry_cache_flush(hdev);
hci_conn_hash_flush(hdev);
+ hci_blacklist_clear(hdev);
hci_dev_unlock_bh(hdev);
hci_notify(hdev, HCI_DEV_DOWN);
@@ -913,7 +914,7 @@ int hci_register_dev(struct hci_dev *hdev)
skb_queue_head_init(&hdev->cmd_q);
skb_queue_head_init(&hdev->raw_q);
- for (i = 0; i < 3; i++)
+ for (i = 0; i < NUM_REASSEMBLY; i++)
hdev->reassembly[i] = NULL;
init_waitqueue_head(&hdev->req_wait_q);
@@ -923,6 +924,8 @@ int hci_register_dev(struct hci_dev *hdev)
hci_conn_hash_init(hdev);
+ INIT_LIST_HEAD(&hdev->blacklist.list);
+
memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
atomic_set(&hdev->promisc, 0);
@@ -970,7 +973,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
hci_dev_do_close(hdev);
- for (i = 0; i < 3; i++)
+ for (i = 0; i < NUM_REASSEMBLY; i++)
kfree_skb(hdev->reassembly[i]);
hci_notify(hdev, HCI_DEV_UNREG);
@@ -1030,89 +1033,170 @@ int hci_recv_frame(struct sk_buff *skb)
}
EXPORT_SYMBOL(hci_recv_frame);
-/* Receive packet type fragment */
-#define __reassembly(hdev, type) ((hdev)->reassembly[(type) - 2])
-
-int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
+static int hci_reassembly(struct hci_dev *hdev, int type, void *data,
+ int count, __u8 index, gfp_t gfp_mask)
{
- if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT)
+ int len = 0;
+ int hlen = 0;
+ int remain = count;
+ struct sk_buff *skb;
+ struct bt_skb_cb *scb;
+
+ if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) ||
+ index >= NUM_REASSEMBLY)
return -EILSEQ;
+ skb = hdev->reassembly[index];
+
+ if (!skb) {
+ switch (type) {
+ case HCI_ACLDATA_PKT:
+ len = HCI_MAX_FRAME_SIZE;
+ hlen = HCI_ACL_HDR_SIZE;
+ break;
+ case HCI_EVENT_PKT:
+ len = HCI_MAX_EVENT_SIZE;
+ hlen = HCI_EVENT_HDR_SIZE;
+ break;
+ case HCI_SCODATA_PKT:
+ len = HCI_MAX_SCO_SIZE;
+ hlen = HCI_SCO_HDR_SIZE;
+ break;
+ }
+
+ skb = bt_skb_alloc(len, gfp_mask);
+ if (!skb)
+ return -ENOMEM;
+
+ scb = (void *) skb->cb;
+ scb->expect = hlen;
+ scb->pkt_type = type;
+
+ skb->dev = (void *) hdev;
+ hdev->reassembly[index] = skb;
+ }
+
while (count) {
- struct sk_buff *skb = __reassembly(hdev, type);
- struct { int expect; } *scb;
- int len = 0;
+ scb = (void *) skb->cb;
+ len = min(scb->expect, (__u16)count);
- if (!skb) {
- /* Start of the frame */
+ memcpy(skb_put(skb, len), data, len);
- switch (type) {
- case HCI_EVENT_PKT:
- if (count >= HCI_EVENT_HDR_SIZE) {
- struct hci_event_hdr *h = data;
- len = HCI_EVENT_HDR_SIZE + h->plen;
- } else
- return -EILSEQ;
- break;
+ count -= len;
+ data += len;
+ scb->expect -= len;
+ remain = count;
- case HCI_ACLDATA_PKT:
- if (count >= HCI_ACL_HDR_SIZE) {
- struct hci_acl_hdr *h = data;
- len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen);
- } else
- return -EILSEQ;
- break;
+ switch (type) {
+ case HCI_EVENT_PKT:
+ if (skb->len == HCI_EVENT_HDR_SIZE) {
+ struct hci_event_hdr *h = hci_event_hdr(skb);
+ scb->expect = h->plen;
+
+ if (skb_tailroom(skb) < scb->expect) {
+ kfree_skb(skb);
+ hdev->reassembly[index] = NULL;
+ return -ENOMEM;
+ }
+ }
+ break;
- case HCI_SCODATA_PKT:
- if (count >= HCI_SCO_HDR_SIZE) {
- struct hci_sco_hdr *h = data;
- len = HCI_SCO_HDR_SIZE + h->dlen;
- } else
- return -EILSEQ;
- break;
+ case HCI_ACLDATA_PKT:
+ if (skb->len == HCI_ACL_HDR_SIZE) {
+ struct hci_acl_hdr *h = hci_acl_hdr(skb);
+ scb->expect = __le16_to_cpu(h->dlen);
+
+ if (skb_tailroom(skb) < scb->expect) {
+ kfree_skb(skb);
+ hdev->reassembly[index] = NULL;
+ return -ENOMEM;
+ }
}
+ break;
- skb = bt_skb_alloc(len, GFP_ATOMIC);
- if (!skb) {
- BT_ERR("%s no memory for packet", hdev->name);
- return -ENOMEM;
+ case HCI_SCODATA_PKT:
+ if (skb->len == HCI_SCO_HDR_SIZE) {
+ struct hci_sco_hdr *h = hci_sco_hdr(skb);
+ scb->expect = h->dlen;
+
+ if (skb_tailroom(skb) < scb->expect) {
+ kfree_skb(skb);
+ hdev->reassembly[index] = NULL;
+ return -ENOMEM;
+ }
}
+ break;
+ }
+
+ if (scb->expect == 0) {
+ /* Complete frame */
- skb->dev = (void *) hdev;
bt_cb(skb)->pkt_type = type;
+ hci_recv_frame(skb);
- __reassembly(hdev, type) = skb;
+ hdev->reassembly[index] = NULL;
+ return remain;
+ }
+ }
- scb = (void *) skb->cb;
- scb->expect = len;
- } else {
- /* Continuation */
+ return remain;
+}
- scb = (void *) skb->cb;
- len = scb->expect;
- }
+int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
+{
+ int rem = 0;
- len = min(len, count);
+ if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT)
+ return -EILSEQ;
- memcpy(skb_put(skb, len), data, len);
+ while (count) {
+ rem = hci_reassembly(hdev, type, data, count,
+ type - 1, GFP_ATOMIC);
+ if (rem < 0)
+ return rem;
- scb->expect -= len;
+ data += (count - rem);
+ count = rem;
+ };
- if (scb->expect == 0) {
- /* Complete frame */
+ return rem;
+}
+EXPORT_SYMBOL(hci_recv_fragment);
- __reassembly(hdev, type) = NULL;
+#define STREAM_REASSEMBLY 0
- bt_cb(skb)->pkt_type = type;
- hci_recv_frame(skb);
- }
+int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count)
+{
+ int type;
+ int rem = 0;
- count -= len; data += len;
- }
+ while (count) {
+ struct sk_buff *skb = hdev->reassembly[STREAM_REASSEMBLY];
- return 0;
+ if (!skb) {
+ struct { char type; } *pkt;
+
+ /* Start of the frame */
+ pkt = data;
+ type = pkt->type;
+
+ data++;
+ count--;
+ } else
+ type = bt_cb(skb)->pkt_type;
+
+ rem = hci_reassembly(hdev, type, data,
+ count, STREAM_REASSEMBLY, GFP_ATOMIC);
+ if (rem < 0)
+ return rem;
+
+ data += (count - rem);
+ count = rem;
+ };
+
+ return rem;
}
-EXPORT_SYMBOL(hci_recv_fragment);
+EXPORT_SYMBOL(hci_recv_stream_fragment);
/* ---- Interface to upper protocols ---- */
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 786b5de0bac4..bfef5bae0b3a 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1,6 +1,6 @@
/*
BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
+ Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@@ -584,7 +584,7 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
conn->out = 1;
conn->link_mode |= HCI_LM_MASTER;
} else
- BT_ERR("No memmory for new connection");
+ BT_ERR("No memory for new connection");
}
}
@@ -785,9 +785,13 @@ static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
- if (conn)
+ if (conn) {
clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
+ if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
+ hci_sco_setup(conn, status);
+ }
+
hci_dev_unlock(hdev);
}
@@ -808,9 +812,13 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
- if (conn)
+ if (conn) {
clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
+ if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
+ hci_sco_setup(conn, status);
+ }
+
hci_dev_unlock(hdev);
}
@@ -915,20 +923,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
} else
conn->state = BT_CLOSED;
- if (conn->type == ACL_LINK) {
- struct hci_conn *sco = conn->link;
- if (sco) {
- if (!ev->status) {
- if (lmp_esco_capable(hdev))
- hci_setup_sync(sco, conn->handle);
- else
- hci_add_sco(sco, conn->handle);
- } else {
- hci_proto_connect_cfm(sco, ev->status);
- hci_conn_del(sco);
- }
- }
- }
+ if (conn->type == ACL_LINK)
+ hci_sco_setup(conn, ev->status);
if (ev->status) {
hci_proto_connect_cfm(conn, ev->status);
@@ -952,7 +948,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
- if (mask & HCI_LM_ACCEPT) {
+ if ((mask & HCI_LM_ACCEPT) && !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
/* Connection accepted */
struct inquiry_entry *ie;
struct hci_conn *conn;
@@ -965,7 +961,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
if (!conn) {
if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) {
- BT_ERR("No memmory for new connection");
+ BT_ERR("No memory for new connection");
hci_dev_unlock(hdev);
return;
}
@@ -1481,6 +1477,9 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb
else
conn->power_save = 0;
}
+
+ if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
+ hci_sco_setup(conn, ev->status);
}
hci_dev_unlock(hdev);
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 38f08f6b86f6..4f170a595934 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -165,6 +165,86 @@ static int hci_sock_release(struct socket *sock)
return 0;
}
+struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+ struct list_head *p;
+ struct bdaddr_list *blacklist = &hdev->blacklist;
+
+ list_for_each(p, &blacklist->list) {
+ struct bdaddr_list *b;
+
+ b = list_entry(p, struct bdaddr_list, list);
+
+ if (bacmp(bdaddr, &b->bdaddr) == 0)
+ return b;
+ }
+
+ return NULL;
+}
+
+static int hci_blacklist_add(struct hci_dev *hdev, void __user *arg)
+{
+ bdaddr_t bdaddr;
+ struct bdaddr_list *entry;
+
+ if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
+ return -EFAULT;
+
+ if (bacmp(&bdaddr, BDADDR_ANY) == 0)
+ return -EBADF;
+
+ if (hci_blacklist_lookup(hdev, &bdaddr))
+ return -EEXIST;
+
+ entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+
+ bacpy(&entry->bdaddr, &bdaddr);
+
+ list_add(&entry->list, &hdev->blacklist.list);
+
+ return 0;
+}
+
+int hci_blacklist_clear(struct hci_dev *hdev)
+{
+ struct list_head *p, *n;
+ struct bdaddr_list *blacklist = &hdev->blacklist;
+
+ list_for_each_safe(p, n, &blacklist->list) {
+ struct bdaddr_list *b;
+
+ b = list_entry(p, struct bdaddr_list, list);
+
+ list_del(p);
+ kfree(b);
+ }
+
+ return 0;
+}
+
+static int hci_blacklist_del(struct hci_dev *hdev, void __user *arg)
+{
+ bdaddr_t bdaddr;
+ struct bdaddr_list *entry;
+
+ if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
+ return -EFAULT;
+
+ if (bacmp(&bdaddr, BDADDR_ANY) == 0)
+ return hci_blacklist_clear(hdev);
+
+ entry = hci_blacklist_lookup(hdev, &bdaddr);
+ if (!entry)
+ return -ENOENT;
+
+ list_del(&entry->list);
+ kfree(entry);
+
+ return 0;
+}
+
/* Ioctls that require bound socket */
static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
{
@@ -194,6 +274,16 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
case HCIGETAUTHINFO:
return hci_get_auth_info(hdev, (void __user *) arg);
+ case HCIBLOCKADDR:
+ if (!capable(CAP_NET_ADMIN))
+ return -EACCES;
+ return hci_blacklist_add(hdev, (void __user *) arg);
+
+ case HCIUNBLOCKADDR:
+ if (!capable(CAP_NET_ADMIN))
+ return -EACCES;
+ return hci_blacklist_del(hdev, (void __user *) arg);
+
default:
if (hdev->ioctl)
return hdev->ioctl(hdev, cmd, arg);
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 463ffa4fe042..ce44c47eeac1 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -436,6 +436,41 @@ static const struct file_operations inquiry_cache_fops = {
.release = single_release,
};
+static int blacklist_show(struct seq_file *f, void *p)
+{
+ struct hci_dev *hdev = f->private;
+ struct bdaddr_list *blacklist = &hdev->blacklist;
+ struct list_head *l;
+
+ hci_dev_lock_bh(hdev);
+
+ list_for_each(l, &blacklist->list) {
+ struct bdaddr_list *b;
+ bdaddr_t bdaddr;
+
+ b = list_entry(l, struct bdaddr_list, list);
+
+ baswap(&bdaddr, &b->bdaddr);
+
+ seq_printf(f, "%s\n", batostr(&bdaddr));
+ }
+
+ hci_dev_unlock_bh(hdev);
+
+ return 0;
+}
+
+static int blacklist_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, blacklist_show, inode->i_private);
+}
+
+static const struct file_operations blacklist_fops = {
+ .open = blacklist_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
int hci_register_sysfs(struct hci_dev *hdev)
{
struct device *dev = &hdev->dev;
@@ -465,6 +500,9 @@ int hci_register_sysfs(struct hci_dev *hdev)
debugfs_create_file("inquiry_cache", 0444, hdev->debugfs,
hdev, &inquiry_cache_fops);
+ debugfs_create_file("blacklist", 0444, hdev->debugfs,
+ hdev, &blacklist_fops);
+
return 0;
}
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index cf3c4073a8a6..9ba1e8eee37c 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1,6 +1,8 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
+ Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
+ Copyright (C) 2010 Google Inc.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@@ -53,15 +55,9 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
-#define VERSION "2.14"
+#define VERSION "2.15"
-#ifdef CONFIG_BT_L2CAP_EXT_FEATURES
-static int enable_ertm = 1;
-#else
-static int enable_ertm = 0;
-#endif
-static int max_transmit = L2CAP_DEFAULT_MAX_TX;
-static int tx_window = L2CAP_DEFAULT_TX_WINDOW;
+static int disable_ertm = 0;
static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
static u8 l2cap_fixed_chan[8] = { 0x02, };
@@ -80,9 +76,12 @@ static void __l2cap_sock_close(struct sock *sk, int reason);
static void l2cap_sock_close(struct sock *sk);
static void l2cap_sock_kill(struct sock *sk);
+static int l2cap_build_conf_req(struct sock *sk, void *data);
static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
u8 code, u8 ident, u16 dlen, void *data);
+static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
+
/* ---- L2CAP timers ---- */
static void l2cap_sock_timeout(unsigned long arg)
{
@@ -278,6 +277,24 @@ static void l2cap_chan_del(struct sock *sk, int err)
parent->sk_data_ready(parent, 0);
} else
sk->sk_state_change(sk);
+
+ skb_queue_purge(TX_QUEUE(sk));
+
+ if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
+ struct srej_list *l, *tmp;
+
+ del_timer(&l2cap_pi(sk)->retrans_timer);
+ del_timer(&l2cap_pi(sk)->monitor_timer);
+ del_timer(&l2cap_pi(sk)->ack_timer);
+
+ skb_queue_purge(SREJ_QUEUE(sk));
+ skb_queue_purge(BUSY_QUEUE(sk));
+
+ list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
+ list_del(&l->list);
+ kfree(l);
+ }
+ }
}
/* Service level security */
@@ -351,8 +368,12 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
struct sk_buff *skb;
struct l2cap_hdr *lh;
struct l2cap_conn *conn = pi->conn;
+ struct sock *sk = (struct sock *)pi;
int count, hlen = L2CAP_HDR_SIZE + 2;
+ if (sk->sk_state != BT_CONNECTED)
+ return;
+
if (pi->fcs == L2CAP_FCS_CRC16)
hlen += 2;
@@ -440,24 +461,57 @@ static void l2cap_do_start(struct sock *sk)
}
}
-static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk)
+static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
+{
+ u32 local_feat_mask = l2cap_feat_mask;
+ if (!disable_ertm)
+ local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
+
+ switch (mode) {
+ case L2CAP_MODE_ERTM:
+ return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
+ case L2CAP_MODE_STREAMING:
+ return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
+ default:
+ return 0x00;
+ }
+}
+
+static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
{
struct l2cap_disconn_req req;
+ if (!conn)
+ return;
+
+ skb_queue_purge(TX_QUEUE(sk));
+
+ if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
+ del_timer(&l2cap_pi(sk)->retrans_timer);
+ del_timer(&l2cap_pi(sk)->monitor_timer);
+ del_timer(&l2cap_pi(sk)->ack_timer);
+ }
+
req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
l2cap_send_cmd(conn, l2cap_get_ident(conn),
L2CAP_DISCONN_REQ, sizeof(req), &req);
+
+ sk->sk_state = BT_DISCONN;
+ sk->sk_err = err;
}
/* ---- L2CAP connections ---- */
static void l2cap_conn_start(struct l2cap_conn *conn)
{
struct l2cap_chan_list *l = &conn->chan_list;
+ struct sock_del_list del, *tmp1, *tmp2;
struct sock *sk;
BT_DBG("conn %p", conn);
+ INIT_LIST_HEAD(&del.list);
+
read_lock(&l->lock);
for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
@@ -470,20 +524,38 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
}
if (sk->sk_state == BT_CONNECT) {
- if (l2cap_check_security(sk) &&
- __l2cap_no_conn_pending(sk)) {
- struct l2cap_conn_req req;
- req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
- req.psm = l2cap_pi(sk)->psm;
+ struct l2cap_conn_req req;
- l2cap_pi(sk)->ident = l2cap_get_ident(conn);
- l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
+ if (!l2cap_check_security(sk) ||
+ !__l2cap_no_conn_pending(sk)) {
+ bh_unlock_sock(sk);
+ continue;
+ }
- l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
- L2CAP_CONN_REQ, sizeof(req), &req);
+ if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
+ conn->feat_mask)
+ && l2cap_pi(sk)->conf_state &
+ L2CAP_CONF_STATE2_DEVICE) {
+ tmp1 = kzalloc(sizeof(struct sock_del_list),
+ GFP_ATOMIC);
+ tmp1->sk = sk;
+ list_add_tail(&tmp1->list, &del.list);
+ bh_unlock_sock(sk);
+ continue;
}
+
+ req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
+ req.psm = l2cap_pi(sk)->psm;
+
+ l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+ l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
+
+ l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
+ L2CAP_CONN_REQ, sizeof(req), &req);
+
} else if (sk->sk_state == BT_CONNECT2) {
struct l2cap_conn_rsp rsp;
+ char buf[128];
rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
@@ -506,12 +578,31 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+
+ if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
+ rsp.result != L2CAP_CR_SUCCESS) {
+ bh_unlock_sock(sk);
+ continue;
+ }
+
+ l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+ l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
+ l2cap_build_conf_req(sk, buf), buf);
+ l2cap_pi(sk)->num_conf_req++;
}
bh_unlock_sock(sk);
}
read_unlock(&l->lock);
+
+ list_for_each_entry_safe(tmp1, tmp2, &del.list, list) {
+ bh_lock_sock(tmp1->sk);
+ __l2cap_sock_close(tmp1->sk, ECONNRESET);
+ bh_unlock_sock(tmp1->sk);
+ list_del(&tmp1->list);
+ kfree(tmp1);
+ }
}
static void l2cap_conn_ready(struct l2cap_conn *conn)
@@ -740,9 +831,8 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
sk->sk_type == SOCK_STREAM) {
struct l2cap_conn *conn = l2cap_pi(sk)->conn;
- sk->sk_state = BT_DISCONN;
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
- l2cap_send_disconn_req(conn, sk);
+ l2cap_send_disconn_req(conn, sk, reason);
} else
l2cap_chan_del(sk, reason);
break;
@@ -802,6 +892,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
pi->imtu = l2cap_pi(parent)->imtu;
pi->omtu = l2cap_pi(parent)->omtu;
+ pi->conf_state = l2cap_pi(parent)->conf_state;
pi->mode = l2cap_pi(parent)->mode;
pi->fcs = l2cap_pi(parent)->fcs;
pi->max_tx = l2cap_pi(parent)->max_tx;
@@ -812,13 +903,15 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
} else {
pi->imtu = L2CAP_DEFAULT_MTU;
pi->omtu = 0;
- if (enable_ertm && sk->sk_type == SOCK_STREAM)
+ if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
pi->mode = L2CAP_MODE_ERTM;
- else
+ pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
+ } else {
pi->mode = L2CAP_MODE_BASIC;
- pi->max_tx = max_transmit;
+ }
+ pi->max_tx = L2CAP_DEFAULT_MAX_TX;
pi->fcs = L2CAP_FCS_CRC16;
- pi->tx_win = tx_window;
+ pi->tx_win = L2CAP_DEFAULT_TX_WINDOW;
pi->sec_level = BT_SECURITY_LOW;
pi->role_switch = 0;
pi->force_reliable = 0;
@@ -1067,7 +1160,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
break;
case L2CAP_MODE_ERTM:
case L2CAP_MODE_STREAMING:
- if (enable_ertm)
+ if (!disable_ertm)
break;
/* fall through */
default:
@@ -1084,6 +1177,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
case BT_CONNECTED:
/* Already connected */
+ err = -EISCONN;
goto done;
case BT_OPEN:
@@ -1132,7 +1226,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
break;
case L2CAP_MODE_ERTM:
case L2CAP_MODE_STREAMING:
- if (enable_ertm)
+ if (!disable_ertm)
break;
/* fall through */
default:
@@ -1285,9 +1379,11 @@ static void l2cap_monitor_timeout(unsigned long arg)
{
struct sock *sk = (void *) arg;
+ BT_DBG("sk %p", sk);
+
bh_lock_sock(sk);
if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
- l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk);
+ l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
bh_unlock_sock(sk);
return;
}
@@ -1303,6 +1399,8 @@ static void l2cap_retrans_timeout(unsigned long arg)
{
struct sock *sk = (void *) arg;
+ BT_DBG("sk %p", sk);
+
bh_lock_sock(sk);
l2cap_pi(sk)->retry_count = 1;
__mod_monitor_timer();
@@ -1341,7 +1439,7 @@ static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
hci_send_acl(pi->conn->hcon, skb, 0);
}
-static int l2cap_streaming_send(struct sock *sk)
+static void l2cap_streaming_send(struct sock *sk)
{
struct sk_buff *skb, *tx_skb;
struct l2cap_pinfo *pi = l2cap_pi(sk);
@@ -1371,7 +1469,6 @@ static int l2cap_streaming_send(struct sock *sk)
skb = skb_dequeue(TX_QUEUE(sk));
kfree_skb(skb);
}
- return 0;
}
static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
@@ -1395,15 +1492,22 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
if (pi->remote_max_tx &&
bt_cb(skb)->retries == pi->remote_max_tx) {
- l2cap_send_disconn_req(pi->conn, sk);
+ l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
return;
}
tx_skb = skb_clone(skb, GFP_ATOMIC);
bt_cb(skb)->retries++;
control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+
+ if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
+ control |= L2CAP_CTRL_FINAL;
+ pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
+ }
+
control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
| (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
+
put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
if (pi->fcs == L2CAP_FCS_CRC16) {
@@ -1421,15 +1525,14 @@ static int l2cap_ertm_send(struct sock *sk)
u16 control, fcs;
int nsent = 0;
- if (pi->conn_state & L2CAP_CONN_WAIT_F)
- return 0;
+ if (sk->sk_state != BT_CONNECTED)
+ return -ENOTCONN;
- while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) &&
- !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) {
+ while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
if (pi->remote_max_tx &&
bt_cb(skb)->retries == pi->remote_max_tx) {
- l2cap_send_disconn_req(pi->conn, sk);
+ l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
break;
}
@@ -1438,6 +1541,8 @@ static int l2cap_ertm_send(struct sock *sk)
bt_cb(skb)->retries++;
control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+ control &= L2CAP_CTRL_SAR;
+
if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
control |= L2CAP_CTRL_FINAL;
pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
@@ -1478,16 +1583,11 @@ static int l2cap_retransmit_frames(struct sock *sk)
struct l2cap_pinfo *pi = l2cap_pi(sk);
int ret;
- spin_lock_bh(&pi->send_lock);
-
if (!skb_queue_empty(TX_QUEUE(sk)))
sk->sk_send_head = TX_QUEUE(sk)->next;
pi->next_tx_seq = pi->expected_ack_seq;
ret = l2cap_ertm_send(sk);
-
- spin_unlock_bh(&pi->send_lock);
-
return ret;
}
@@ -1495,7 +1595,6 @@ static void l2cap_send_ack(struct l2cap_pinfo *pi)
{
struct sock *sk = (struct sock *)pi;
u16 control = 0;
- int nframes;
control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
@@ -1506,11 +1605,7 @@ static void l2cap_send_ack(struct l2cap_pinfo *pi)
return;
}
- spin_lock_bh(&pi->send_lock);
- nframes = l2cap_ertm_send(sk);
- spin_unlock_bh(&pi->send_lock);
-
- if (nframes > 0)
+ if (l2cap_ertm_send(sk) > 0)
return;
control |= L2CAP_SUPER_RCV_READY;
@@ -1705,10 +1800,8 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz
size += buflen;
}
skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
- spin_lock_bh(&pi->send_lock);
if (sk->sk_send_head == NULL)
sk->sk_send_head = sar_queue.next;
- spin_unlock_bh(&pi->send_lock);
return size;
}
@@ -1753,7 +1846,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
case L2CAP_MODE_BASIC:
/* Check outgoing MTU */
if (len > pi->omtu) {
- err = -EINVAL;
+ err = -EMSGSIZE;
goto done;
}
@@ -1780,14 +1873,9 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
}
__skb_queue_tail(TX_QUEUE(sk), skb);
- if (pi->mode == L2CAP_MODE_ERTM)
- spin_lock_bh(&pi->send_lock);
-
if (sk->sk_send_head == NULL)
sk->sk_send_head = skb;
- if (pi->mode == L2CAP_MODE_ERTM)
- spin_unlock_bh(&pi->send_lock);
} else {
/* Segment SDU into multiples PDUs */
err = l2cap_sar_segment_sdu(sk, msg, len);
@@ -1796,11 +1884,14 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
}
if (pi->mode == L2CAP_MODE_STREAMING) {
- err = l2cap_streaming_send(sk);
+ l2cap_streaming_send(sk);
} else {
- spin_lock_bh(&pi->send_lock);
+ if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY &&
+ pi->conn_state && L2CAP_CONN_WAIT_F) {
+ err = len;
+ break;
+ }
err = l2cap_ertm_send(sk);
- spin_unlock_bh(&pi->send_lock);
}
if (err >= 0)
@@ -1809,7 +1900,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
default:
BT_DBG("bad state %1.1x", pi->mode);
- err = -EINVAL;
+ err = -EBADFD;
}
done:
@@ -1825,6 +1916,8 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
struct l2cap_conn_rsp rsp;
+ struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+ u8 buf[128];
sk->sk_state = BT_CONFIG;
@@ -1835,6 +1928,16 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+ if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) {
+ release_sock(sk);
+ return 0;
+ }
+
+ l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+ l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
+ l2cap_build_conf_req(sk, buf), buf);
+ l2cap_pi(sk)->num_conf_req++;
+
release_sock(sk);
return 0;
}
@@ -1871,13 +1974,19 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
break;
}
+ if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
+ err = -EINVAL;
+ break;
+ }
+
l2cap_pi(sk)->mode = opts.mode;
switch (l2cap_pi(sk)->mode) {
case L2CAP_MODE_BASIC:
+ l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
break;
case L2CAP_MODE_ERTM:
case L2CAP_MODE_STREAMING:
- if (enable_ertm)
+ if (!disable_ertm)
break;
/* fall through */
default:
@@ -2145,6 +2254,10 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
err = bt_sock_wait_state(sk, BT_CLOSED,
sk->sk_lingertime);
}
+
+ if (!err && sk->sk_err)
+ err = -sk->sk_err;
+
release_sock(sk);
return err;
}
@@ -2365,25 +2478,10 @@ static inline void l2cap_ertm_init(struct sock *sk)
__skb_queue_head_init(SREJ_QUEUE(sk));
__skb_queue_head_init(BUSY_QUEUE(sk));
- spin_lock_init(&l2cap_pi(sk)->send_lock);
INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
-}
-static int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
-{
- u32 local_feat_mask = l2cap_feat_mask;
- if (enable_ertm)
- local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
-
- switch (mode) {
- case L2CAP_MODE_ERTM:
- return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
- case L2CAP_MODE_STREAMING:
- return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
- default:
- return 0x00;
- }
+ sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
}
static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
@@ -2414,10 +2512,10 @@ static int l2cap_build_conf_req(struct sock *sk, void *data)
switch (pi->mode) {
case L2CAP_MODE_STREAMING:
case L2CAP_MODE_ERTM:
- pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
- if (!l2cap_mode_supported(pi->mode, pi->conn->feat_mask))
- l2cap_send_disconn_req(pi->conn, sk);
- break;
+ if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
+ break;
+
+ /* fall through */
default:
pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
break;
@@ -2428,6 +2526,14 @@ done:
case L2CAP_MODE_BASIC:
if (pi->imtu != L2CAP_DEFAULT_MTU)
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
+
+ rfc.mode = L2CAP_MODE_BASIC;
+ rfc.txwin_size = 0;
+ rfc.max_transmit = 0;
+ rfc.retrans_timeout = 0;
+ rfc.monitor_timeout = 0;
+ rfc.max_pdu_size = 0;
+
break;
case L2CAP_MODE_ERTM:
@@ -2440,9 +2546,6 @@ done:
if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
-
if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
break;
@@ -2463,9 +2566,6 @@ done:
if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
-
if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
break;
@@ -2477,6 +2577,9 @@ done:
break;
}
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
+ (unsigned long) &rfc);
+
/* FIXME: Need actual value of the flush timeout */
//if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
// l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
@@ -2541,18 +2644,21 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
}
}
- if (pi->num_conf_rsp || pi->num_conf_req)
+ if (pi->num_conf_rsp || pi->num_conf_req > 1)
goto done;
switch (pi->mode) {
case L2CAP_MODE_STREAMING:
case L2CAP_MODE_ERTM:
- pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
- if (!l2cap_mode_supported(pi->mode, pi->conn->feat_mask))
+ if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
+ pi->mode = l2cap_select_mode(rfc.mode,
+ pi->conn->feat_mask);
+ break;
+ }
+
+ if (pi->mode != rfc.mode)
return -ECONNREFUSED;
- break;
- default:
- pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
+
break;
}
@@ -2675,7 +2781,6 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
rfc.mode != pi->mode)
return -ECONNREFUSED;
- pi->mode = rfc.mode;
pi->fcs = 0;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
@@ -2684,6 +2789,11 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
}
}
+ if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
+ return -ECONNREFUSED;
+
+ pi->mode = rfc.mode;
+
if (*result == L2CAP_CONF_SUCCESS) {
switch (rfc.mode) {
case L2CAP_MODE_ERTM:
@@ -2778,7 +2888,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
struct l2cap_chan_list *list = &conn->chan_list;
struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
struct l2cap_conn_rsp rsp;
- struct sock *sk, *parent;
+ struct sock *parent, *uninitialized_var(sk);
int result, status = L2CAP_CS_NO_INFO;
u16 dcid = 0, scid = __le16_to_cpu(req->scid);
@@ -2887,6 +2997,15 @@ sendresp:
L2CAP_INFO_REQ, sizeof(info), &info);
}
+ if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
+ result == L2CAP_CR_SUCCESS) {
+ u8 buf[128];
+ l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+ l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
+ l2cap_build_conf_req(sk, buf), buf);
+ l2cap_pi(sk)->num_conf_req++;
+ }
+
return 0;
}
@@ -2907,11 +3026,11 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
if (scid) {
sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
if (!sk)
- return 0;
+ return -EFAULT;
} else {
sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
if (!sk)
- return 0;
+ return -EFAULT;
}
switch (result) {
@@ -2919,9 +3038,13 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
sk->sk_state = BT_CONFIG;
l2cap_pi(sk)->ident = 0;
l2cap_pi(sk)->dcid = dcid;
- l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
+ if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
+ break;
+
+ l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
l2cap_build_conf_req(sk, req), req);
l2cap_pi(sk)->num_conf_req++;
@@ -2957,8 +3080,14 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if (!sk)
return -ENOENT;
- if (sk->sk_state == BT_DISCONN)
+ if (sk->sk_state != BT_CONFIG) {
+ struct l2cap_cmd_rej rej;
+
+ rej.reason = cpu_to_le16(0x0002);
+ l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
+ sizeof(rej), &rej);
goto unlock;
+ }
/* Reject if config buffer is too small. */
len = cmd_len - sizeof(*req);
@@ -2984,7 +3113,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
/* Complete config. */
len = l2cap_parse_conf_req(sk, rsp);
if (len < 0) {
- l2cap_send_disconn_req(conn, sk);
+ l2cap_send_disconn_req(conn, sk, ECONNRESET);
goto unlock;
}
@@ -3054,7 +3183,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
char req[64];
if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
- l2cap_send_disconn_req(conn, sk);
+ l2cap_send_disconn_req(conn, sk, ECONNRESET);
goto done;
}
@@ -3063,7 +3192,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
len = l2cap_parse_conf_rsp(sk, rsp->data,
len, req, &result);
if (len < 0) {
- l2cap_send_disconn_req(conn, sk);
+ l2cap_send_disconn_req(conn, sk, ECONNRESET);
goto done;
}
@@ -3076,10 +3205,9 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
}
default:
- sk->sk_state = BT_DISCONN;
sk->sk_err = ECONNRESET;
l2cap_sock_set_timer(sk, HZ * 5);
- l2cap_send_disconn_req(conn, sk);
+ l2cap_send_disconn_req(conn, sk, ECONNRESET);
goto done;
}
@@ -3130,16 +3258,6 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
sk->sk_shutdown = SHUTDOWN_MASK;
- skb_queue_purge(TX_QUEUE(sk));
-
- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
- skb_queue_purge(SREJ_QUEUE(sk));
- skb_queue_purge(BUSY_QUEUE(sk));
- del_timer(&l2cap_pi(sk)->retrans_timer);
- del_timer(&l2cap_pi(sk)->monitor_timer);
- del_timer(&l2cap_pi(sk)->ack_timer);
- }
-
l2cap_chan_del(sk, ECONNRESET);
bh_unlock_sock(sk);
@@ -3162,16 +3280,6 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
if (!sk)
return 0;
- skb_queue_purge(TX_QUEUE(sk));
-
- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
- skb_queue_purge(SREJ_QUEUE(sk));
- skb_queue_purge(BUSY_QUEUE(sk));
- del_timer(&l2cap_pi(sk)->retrans_timer);
- del_timer(&l2cap_pi(sk)->monitor_timer);
- del_timer(&l2cap_pi(sk)->ack_timer);
- }
-
l2cap_chan_del(sk, 0);
bh_unlock_sock(sk);
@@ -3194,7 +3302,7 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm
struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
- if (enable_ertm)
+ if (!disable_ertm)
feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
| L2CAP_FEAT_FCS;
put_unaligned_le32(feat_mask, rsp->data);
@@ -3359,7 +3467,7 @@ static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
if (our_fcs != rcv_fcs)
- return -EINVAL;
+ return -EBADMSG;
}
return 0;
}
@@ -3370,25 +3478,19 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
u16 control = 0;
pi->frames_sent = 0;
- pi->conn_state |= L2CAP_CONN_SEND_FBIT;
control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
- control |= L2CAP_SUPER_RCV_NOT_READY | L2CAP_CTRL_FINAL;
+ control |= L2CAP_SUPER_RCV_NOT_READY;
l2cap_send_sframe(pi, control);
pi->conn_state |= L2CAP_CONN_RNR_SENT;
- pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
}
- if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0)
- __mod_retrans_timer();
-
- pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+ if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
+ l2cap_retransmit_frames(sk);
- spin_lock_bh(&pi->send_lock);
l2cap_ertm_send(sk);
- spin_unlock_bh(&pi->send_lock);
if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
pi->frames_sent == 0) {
@@ -3400,6 +3502,8 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
{
struct sk_buff *next_skb;
+ struct l2cap_pinfo *pi = l2cap_pi(sk);
+ int tx_seq_offset, next_tx_seq_offset;
bt_cb(skb)->tx_seq = tx_seq;
bt_cb(skb)->sar = sar;
@@ -3410,11 +3514,20 @@ static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_s
return 0;
}
+ tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
+ if (tx_seq_offset < 0)
+ tx_seq_offset += 64;
+
do {
if (bt_cb(next_skb)->tx_seq == tx_seq)
return -EINVAL;
- if (bt_cb(next_skb)->tx_seq > tx_seq) {
+ next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
+ pi->buffer_seq) % 64;
+ if (next_tx_seq_offset < 0)
+ next_tx_seq_offset += 64;
+
+ if (next_tx_seq_offset > tx_seq_offset) {
__skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
return 0;
}
@@ -3532,11 +3645,51 @@ drop:
pi->sdu = NULL;
disconnect:
- l2cap_send_disconn_req(pi->conn, sk);
+ l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
kfree_skb(skb);
return 0;
}
+static int l2cap_try_push_rx_skb(struct sock *sk)
+{
+ struct l2cap_pinfo *pi = l2cap_pi(sk);
+ struct sk_buff *skb;
+ u16 control;
+ int err;
+
+ while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
+ control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
+ err = l2cap_ertm_reassembly_sdu(sk, skb, control);
+ if (err < 0) {
+ skb_queue_head(BUSY_QUEUE(sk), skb);
+ return -EBUSY;
+ }
+
+ pi->buffer_seq = (pi->buffer_seq + 1) % 64;
+ }
+
+ if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
+ goto done;
+
+ control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+ control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
+ l2cap_send_sframe(pi, control);
+ l2cap_pi(sk)->retry_count = 1;
+
+ del_timer(&pi->retrans_timer);
+ __mod_monitor_timer();
+
+ l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
+
+done:
+ pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
+ pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
+
+ BT_DBG("sk %p, Exit local busy", sk);
+
+ return 0;
+}
+
static void l2cap_busy_work(struct work_struct *work)
{
DECLARE_WAITQUEUE(wait, current);
@@ -3545,7 +3698,6 @@ static void l2cap_busy_work(struct work_struct *work)
struct sock *sk = (struct sock *)pi;
int n_tries = 0, timeo = HZ/5, err;
struct sk_buff *skb;
- u16 control;
lock_sock(sk);
@@ -3555,8 +3707,8 @@ static void l2cap_busy_work(struct work_struct *work)
if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
err = -EBUSY;
- l2cap_send_disconn_req(pi->conn, sk);
- goto done;
+ l2cap_send_disconn_req(pi->conn, sk, EBUSY);
+ break;
}
if (!timeo)
@@ -3564,7 +3716,7 @@ static void l2cap_busy_work(struct work_struct *work)
if (signal_pending(current)) {
err = sock_intr_errno(timeo);
- goto done;
+ break;
}
release_sock(sk);
@@ -3573,40 +3725,12 @@ static void l2cap_busy_work(struct work_struct *work)
err = sock_error(sk);
if (err)
- goto done;
-
- while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
- control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
- err = l2cap_ertm_reassembly_sdu(sk, skb, control);
- if (err < 0) {
- skb_queue_head(BUSY_QUEUE(sk), skb);
- break;
- }
-
- pi->buffer_seq = (pi->buffer_seq + 1) % 64;
- }
+ break;
- if (!skb)
+ if (l2cap_try_push_rx_skb(sk) == 0)
break;
}
- if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
- goto done;
-
- control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
- control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
- l2cap_send_sframe(pi, control);
- l2cap_pi(sk)->retry_count = 1;
-
- del_timer(&pi->retrans_timer);
- __mod_monitor_timer();
-
- l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
-
-done:
- pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
- pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
-
set_current_state(TASK_RUNNING);
remove_wait_queue(sk_sleep(sk), &wait);
@@ -3621,7 +3745,9 @@ static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
__skb_queue_tail(BUSY_QUEUE(sk), skb);
- return -EBUSY;
+ return l2cap_try_push_rx_skb(sk);
+
+
}
err = l2cap_ertm_reassembly_sdu(sk, skb, control);
@@ -3631,6 +3757,8 @@ static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
}
/* Busy Condition */
+ BT_DBG("sk %p, Enter local busy", sk);
+
pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
__skb_queue_tail(BUSY_QUEUE(sk), skb);
@@ -3641,6 +3769,8 @@ static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
pi->conn_state |= L2CAP_CONN_RNR_SENT;
+ del_timer(&pi->ack_timer);
+
queue_work(_busy_wq, &pi->busy_work);
return err;
@@ -3754,7 +3884,7 @@ static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
l2cap_ertm_reassembly_sdu(sk, skb, control);
l2cap_pi(sk)->buffer_seq_srej =
(l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
- tx_seq++;
+ tx_seq = (tx_seq + 1) % 64;
}
}
@@ -3790,10 +3920,11 @@ static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
l2cap_send_sframe(pi, control);
new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
- new->tx_seq = pi->expected_tx_seq++;
+ new->tx_seq = pi->expected_tx_seq;
+ pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
list_add_tail(&new->list, SREJ_LIST(sk));
}
- pi->expected_tx_seq++;
+ pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
}
static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
@@ -3802,11 +3933,12 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
u8 tx_seq = __get_txseq(rx_control);
u8 req_seq = __get_reqseq(rx_control);
u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
- u8 tx_seq_offset, expected_tx_seq_offset;
+ int tx_seq_offset, expected_tx_seq_offset;
int num_to_ack = (pi->tx_win/6) + 1;
int err = 0;
- BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
+ BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
+ rx_control);
if (L2CAP_CTRL_FINAL & rx_control &&
l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
@@ -3828,7 +3960,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
/* invalid tx_seq */
if (tx_seq_offset >= pi->tx_win) {
- l2cap_send_disconn_req(pi->conn, sk);
+ l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
goto drop;
}
@@ -3851,6 +3983,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
pi->buffer_seq = pi->buffer_seq_srej;
pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
l2cap_send_ack(pi);
+ BT_DBG("sk %p, Exit SREJ_SENT", sk);
}
} else {
struct srej_list *l;
@@ -3879,6 +4012,8 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
pi->conn_state |= L2CAP_CONN_SREJ_SENT;
+ BT_DBG("sk %p, Enter SREJ", sk);
+
INIT_LIST_HEAD(SREJ_LIST(sk));
pi->buffer_seq_srej = pi->buffer_seq;
@@ -3889,6 +4024,8 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
pi->conn_state |= L2CAP_CONN_SEND_PBIT;
l2cap_send_srejframe(sk, tx_seq);
+
+ del_timer(&pi->ack_timer);
}
return 0;
@@ -3902,6 +4039,10 @@ expected:
return 0;
}
+ err = l2cap_push_rx_skb(sk, skb, rx_control);
+ if (err < 0)
+ return 0;
+
if (rx_control & L2CAP_CTRL_FINAL) {
if (pi->conn_state & L2CAP_CONN_REJ_ACT)
pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
@@ -3909,10 +4050,6 @@ expected:
l2cap_retransmit_frames(sk);
}
- err = l2cap_push_rx_skb(sk, skb, rx_control);
- if (err < 0)
- return 0;
-
__mod_ack_timer();
pi->num_acked = (pi->num_acked + 1) % num_to_ack;
@@ -3930,10 +4067,14 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
+ BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
+ rx_control);
+
pi->expected_ack_seq = __get_reqseq(rx_control);
l2cap_drop_acked_frames(sk);
if (rx_control & L2CAP_CTRL_POLL) {
+ pi->conn_state |= L2CAP_CONN_SEND_FBIT;
if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
(pi->unacked_frames > 0))
@@ -3962,9 +4103,7 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
l2cap_send_ack(pi);
} else {
- spin_lock_bh(&pi->send_lock);
l2cap_ertm_send(sk);
- spin_unlock_bh(&pi->send_lock);
}
}
}
@@ -3974,6 +4113,8 @@ static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
struct l2cap_pinfo *pi = l2cap_pi(sk);
u8 tx_seq = __get_reqseq(rx_control);
+ BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
+
pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
pi->expected_ack_seq = tx_seq;
@@ -3996,16 +4137,18 @@ static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
struct l2cap_pinfo *pi = l2cap_pi(sk);
u8 tx_seq = __get_reqseq(rx_control);
+ BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
+
pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
if (rx_control & L2CAP_CTRL_POLL) {
pi->expected_ack_seq = tx_seq;
l2cap_drop_acked_frames(sk);
+
+ pi->conn_state |= L2CAP_CONN_SEND_FBIT;
l2cap_retransmit_one_frame(sk, tx_seq);
- spin_lock_bh(&pi->send_lock);
l2cap_ertm_send(sk);
- spin_unlock_bh(&pi->send_lock);
if (pi->conn_state & L2CAP_CONN_WAIT_F) {
pi->srej_save_reqseq = tx_seq;
@@ -4031,10 +4174,15 @@ static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
struct l2cap_pinfo *pi = l2cap_pi(sk);
u8 tx_seq = __get_reqseq(rx_control);
+ BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
+
pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
pi->expected_ack_seq = tx_seq;
l2cap_drop_acked_frames(sk);
+ if (rx_control & L2CAP_CTRL_POLL)
+ pi->conn_state |= L2CAP_CONN_SEND_FBIT;
+
if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
del_timer(&pi->retrans_timer);
if (rx_control & L2CAP_CTRL_POLL)
@@ -4082,12 +4230,83 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
return 0;
}
+static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
+{
+ struct l2cap_pinfo *pi = l2cap_pi(sk);
+ u16 control;
+ u8 req_seq;
+ int len, next_tx_seq_offset, req_seq_offset;
+
+ control = get_unaligned_le16(skb->data);
+ skb_pull(skb, 2);
+ len = skb->len;
+
+ /*
+ * We can just drop the corrupted I-frame here.
+ * Receiver will miss it and start proper recovery
+ * procedures and ask retransmission.
+ */
+ if (l2cap_check_fcs(pi, skb))
+ goto drop;
+
+ if (__is_sar_start(control) && __is_iframe(control))
+ len -= 2;
+
+ if (pi->fcs == L2CAP_FCS_CRC16)
+ len -= 2;
+
+ if (len > pi->mps) {
+ l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+ goto drop;
+ }
+
+ req_seq = __get_reqseq(control);
+ req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
+ if (req_seq_offset < 0)
+ req_seq_offset += 64;
+
+ next_tx_seq_offset =
+ (pi->next_tx_seq - pi->expected_ack_seq) % 64;
+ if (next_tx_seq_offset < 0)
+ next_tx_seq_offset += 64;
+
+ /* check for invalid req-seq */
+ if (req_seq_offset > next_tx_seq_offset) {
+ l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+ goto drop;
+ }
+
+ if (__is_iframe(control)) {
+ if (len < 0) {
+ l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+ goto drop;
+ }
+
+ l2cap_data_channel_iframe(sk, control, skb);
+ } else {
+ if (len != 0) {
+ BT_ERR("%d", len);
+ l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+ goto drop;
+ }
+
+ l2cap_data_channel_sframe(sk, control, skb);
+ }
+
+ return 0;
+
+drop:
+ kfree_skb(skb);
+ return 0;
+}
+
static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
{
struct sock *sk;
struct l2cap_pinfo *pi;
- u16 control, len;
- u8 tx_seq, req_seq, next_tx_seq_offset, req_seq_offset;
+ u16 control;
+ u8 tx_seq;
+ int len;
sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
if (!sk) {
@@ -4117,59 +4336,11 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
break;
case L2CAP_MODE_ERTM:
- control = get_unaligned_le16(skb->data);
- skb_pull(skb, 2);
- len = skb->len;
-
- if (__is_sar_start(control))
- len -= 2;
-
- if (pi->fcs == L2CAP_FCS_CRC16)
- len -= 2;
-
- /*
- * We can just drop the corrupted I-frame here.
- * Receiver will miss it and start proper recovery
- * procedures and ask retransmission.
- */
- if (len > pi->mps) {
- l2cap_send_disconn_req(pi->conn, sk);
- goto drop;
- }
-
- if (l2cap_check_fcs(pi, skb))
- goto drop;
-
- req_seq = __get_reqseq(control);
- req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
- if (req_seq_offset < 0)
- req_seq_offset += 64;
-
- next_tx_seq_offset =
- (pi->next_tx_seq - pi->expected_ack_seq) % 64;
- if (next_tx_seq_offset < 0)
- next_tx_seq_offset += 64;
-
- /* check for invalid req-seq */
- if (req_seq_offset > next_tx_seq_offset) {
- l2cap_send_disconn_req(pi->conn, sk);
- goto drop;
- }
-
- if (__is_iframe(control)) {
- if (len < 4) {
- l2cap_send_disconn_req(pi->conn, sk);
- goto drop;
- }
-
- l2cap_data_channel_iframe(sk, control, skb);
+ if (!sock_owned_by_user(sk)) {
+ l2cap_ertm_data_rcv(sk, skb);
} else {
- if (len != 0) {
- l2cap_send_disconn_req(pi->conn, sk);
+ if (sk_add_backlog(sk, skb))
goto drop;
- }
-
- l2cap_data_channel_sframe(sk, control, skb);
}
goto done;
@@ -4179,16 +4350,16 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
skb_pull(skb, 2);
len = skb->len;
+ if (l2cap_check_fcs(pi, skb))
+ goto drop;
+
if (__is_sar_start(control))
len -= 2;
if (pi->fcs == L2CAP_FCS_CRC16)
len -= 2;
- if (len > pi->mps || len < 4 || __is_sframe(control))
- goto drop;
-
- if (l2cap_check_fcs(pi, skb))
+ if (len > pi->mps || len < 0 || __is_sframe(control))
goto drop;
tx_seq = __get_txseq(control);
@@ -4288,7 +4459,7 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
struct hlist_node *node;
if (type != ACL_LINK)
- return 0;
+ return -EINVAL;
BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
@@ -4321,7 +4492,7 @@ static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
if (hcon->type != ACL_LINK)
- return 0;
+ return -EINVAL;
if (!status) {
conn = l2cap_conn_add(hcon, status);
@@ -4350,7 +4521,7 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
BT_DBG("hcon %p reason %d", hcon, reason);
if (hcon->type != ACL_LINK)
- return 0;
+ return -EINVAL;
l2cap_conn_del(hcon, bt_err(reason));
@@ -4679,14 +4850,8 @@ EXPORT_SYMBOL(l2cap_load);
module_init(l2cap_init);
module_exit(l2cap_exit);
-module_param(enable_ertm, bool, 0644);
-MODULE_PARM_DESC(enable_ertm, "Enable enhanced retransmission mode");
-
-module_param(max_transmit, uint, 0644);
-MODULE_PARM_DESC(max_transmit, "Max transmit value (default = 3)");
-
-module_param(tx_window, uint, 0644);
-MODULE_PARM_DESC(tx_window, "Transmission window size value (default = 63)");
+module_param(disable_ertm, bool, 0644);
+MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 43fbf6b4b4bf..44a623275951 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -1152,7 +1152,7 @@ error:
return err;
}
-void rfcomm_cleanup_sockets(void)
+void __exit rfcomm_cleanup_sockets(void)
{
debugfs_remove(rfcomm_sock_debugfs);
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 309b6c261b25..026205c18b78 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -1153,7 +1153,7 @@ static const struct tty_operations rfcomm_ops = {
.tiocmset = rfcomm_tty_tiocmset,
};
-int rfcomm_init_ttys(void)
+int __init rfcomm_init_ttys(void)
{
rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS);
if (!rfcomm_tty_driver)
@@ -1183,7 +1183,7 @@ int rfcomm_init_ttys(void)
return 0;
}
-void rfcomm_cleanup_ttys(void)
+void __exit rfcomm_cleanup_ttys(void)
{
tty_unregister_driver(rfcomm_tty_driver);
put_tty_driver(rfcomm_tty_driver);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index db4d9340c846..29ac8e1a509e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -158,7 +158,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
if (mac_addr) {
sta = sta_info_get_bss(sdata, mac_addr);
if (!sta) {
- ieee80211_key_free(key);
+ ieee80211_key_free(sdata->local, key);
err = -ENOENT;
goto out_unlock;
}
@@ -192,7 +192,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
goto out_unlock;
if (sta->key) {
- ieee80211_key_free(sta->key);
+ ieee80211_key_free(sdata->local, sta->key);
WARN_ON(sta->key);
ret = 0;
}
@@ -205,7 +205,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
goto out_unlock;
}
- ieee80211_key_free(sdata->keys[key_idx]);
+ ieee80211_key_free(sdata->local, sdata->keys[key_idx]);
WARN_ON(sdata->keys[key_idx]);
ret = 0;
@@ -324,15 +324,10 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
struct net_device *dev,
u8 key_idx)
{
- struct ieee80211_sub_if_data *sdata;
-
- rcu_read_lock();
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
ieee80211_set_default_mgmt_key(sdata, key_idx);
- rcu_read_unlock();
-
return 0;
}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ef470064b154..65e0ed6c2975 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -238,6 +238,7 @@ enum ieee80211_work_type {
IEEE80211_WORK_ABORT,
IEEE80211_WORK_DIRECT_PROBE,
IEEE80211_WORK_AUTH,
+ IEEE80211_WORK_ASSOC_BEACON_WAIT,
IEEE80211_WORK_ASSOC,
IEEE80211_WORK_REMAIN_ON_CHANNEL,
};
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 50d1cff23d8e..1b9d87ed143a 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -323,13 +323,15 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
if (!key)
return;
- ieee80211_key_disable_hw_accel(key);
+ if (key->local)
+ ieee80211_key_disable_hw_accel(key);
if (key->conf.alg == ALG_CCMP)
ieee80211_aes_key_free(key->u.ccmp.tfm);
if (key->conf.alg == ALG_AES_CMAC)
ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
- ieee80211_debugfs_key_remove(key);
+ if (key->local)
+ ieee80211_debugfs_key_remove(key);
kfree(key);
}
@@ -410,15 +412,12 @@ static void __ieee80211_key_free(struct ieee80211_key *key)
__ieee80211_key_destroy(key);
}
-void ieee80211_key_free(struct ieee80211_key *key)
+void ieee80211_key_free(struct ieee80211_local *local,
+ struct ieee80211_key *key)
{
- struct ieee80211_local *local;
-
if (!key)
return;
- local = key->sdata->local;
-
mutex_lock(&local->key_mtx);
__ieee80211_key_free(key);
mutex_unlock(&local->key_mtx);
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index a3849fa3fce8..b665bbb7a471 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -135,7 +135,8 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
void ieee80211_key_link(struct ieee80211_key *key,
struct ieee80211_sub_if_data *sdata,
struct sta_info *sta);
-void ieee80211_key_free(struct ieee80211_key *key);
+void ieee80211_key_free(struct ieee80211_local *local,
+ struct ieee80211_key *key);
void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
int idx);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 0e95c750ded9..7cc4f913a431 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -107,12 +107,15 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
if (scan_chan) {
chan = scan_chan;
channel_type = NL80211_CHAN_NO_HT;
+ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
} else if (local->tmp_channel) {
chan = scan_chan = local->tmp_channel;
channel_type = local->tmp_channel_type;
+ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
} else {
chan = local->oper_channel;
channel_type = local->_oper_channel_type;
+ local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
}
if (chan != local->hw.conf.channel ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index cf8d72196c65..b6c163ac22da 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -870,6 +870,11 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
ieee80211_led_assoc(local, 1);
+ if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD)
+ bss_conf->dtim_period = bss->dtim_period;
+ else
+ bss_conf->dtim_period = 0;
+
bss_conf->assoc = 1;
/*
* For now just always ask the driver to update the basic rateset
@@ -1751,7 +1756,8 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
if (wk->sdata != sdata)
continue;
- if (wk->type != IEEE80211_WORK_ASSOC)
+ if (wk->type != IEEE80211_WORK_ASSOC &&
+ wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
continue;
if (memcmp(mgmt->bssid, wk->filter_ta, ETH_ALEN))
@@ -2086,6 +2092,8 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
struct sk_buff *skb)
{
struct ieee80211_mgmt *mgmt;
+ struct ieee80211_rx_status *rx_status;
+ struct ieee802_11_elems elems;
u16 status;
if (!skb) {
@@ -2093,6 +2101,19 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
return WORK_DONE_DESTROY;
}
+ if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) {
+ mutex_lock(&wk->sdata->u.mgd.mtx);
+ rx_status = (void *) skb->cb;
+ ieee802_11_parse_elems(skb->data + 24 + 12, skb->len - 24 - 12, &elems);
+ ieee80211_rx_bss_info(wk->sdata, (void *)skb->data, skb->len, rx_status,
+ &elems, true);
+ mutex_unlock(&wk->sdata->u.mgd.mtx);
+
+ wk->type = IEEE80211_WORK_ASSOC;
+ /* not really done yet */
+ return WORK_DONE_REQUEUE;
+ }
+
mgmt = (void *)skb->data;
status = le16_to_cpu(mgmt->u.assoc_resp.status_code);
@@ -2206,10 +2227,14 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
if (req->prev_bssid)
memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN);
- wk->type = IEEE80211_WORK_ASSOC;
wk->chan = req->bss->channel;
wk->sdata = sdata;
wk->done = ieee80211_assoc_done;
+ if (!bss->dtim_period &&
+ sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD)
+ wk->type = IEEE80211_WORK_ASSOC_BEACON_WAIT;
+ else
+ wk->type = IEEE80211_WORK_ASSOC;
if (req->use_mfp) {
ifmgd->mfp = IEEE80211_MFP_REQUIRED;
@@ -2257,7 +2282,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
if (wk->type != IEEE80211_WORK_DIRECT_PROBE &&
wk->type != IEEE80211_WORK_AUTH &&
- wk->type != IEEE80211_WORK_ASSOC)
+ wk->type != IEEE80211_WORK_ASSOC &&
+ wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
continue;
if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN))
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index f65ce6dcc8e2..778c604d7939 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -67,7 +67,6 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix)
for (i = rix; i >= 0; i--)
if (mi->r[i].rix == rix)
break;
- WARN_ON(i < 0);
return i;
}
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index b5ace243546c..c5b465904e3b 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -636,7 +636,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
int i;
/* fall back to the old minstrel for legacy stations */
- if (sta && !sta->ht_cap.ht_supported) {
+ if (!sta->ht_cap.ht_supported) {
msp->is_ht = false;
memset(&msp->legacy, 0, sizeof(msp->legacy));
msp->legacy.r = msp->ratelist;
@@ -748,7 +748,7 @@ minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
return msp;
error1:
- kfree(msp->sample_table);
+ kfree(msp->ratelist);
error:
kfree(msp);
return NULL;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 439c98d93a79..41f20fb7e670 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -114,6 +114,10 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
bss->dtim_period = tim_ie->dtim_period;
}
+ /* If the beacon had no TIM IE, or it was invalid, use 1 */
+ if (beacon && !bss->dtim_period)
+ bss->dtim_period = 1;
+
/* replace old supported rates if we get new values */
srlen = 0;
if (elems->supp_rates) {
@@ -286,8 +290,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
local->scanning = 0;
local->scan_channel = NULL;
- drv_sw_scan_complete(local);
-
/* we only have to protect scan_req and hw/sw scan */
mutex_unlock(&local->scan_mtx);
@@ -297,6 +299,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
ieee80211_configure_filter(local);
+ drv_sw_scan_complete(local);
+
ieee80211_offchannel_return(local, true);
done:
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 67656cbf2b15..6d86f0c1ad04 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -647,7 +647,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
return ret;
if (sta->key) {
- ieee80211_key_free(sta->key);
+ ieee80211_key_free(local, sta->key);
WARN_ON(sta->key);
}
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 698d4718b1a4..c54db966926b 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -576,17 +576,6 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
}
static ieee80211_tx_result debug_noinline
-ieee80211_tx_h_sta(struct ieee80211_tx_data *tx)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
-
- if (tx->sta && tx->sta->uploaded)
- info->control.sta = &tx->sta->sta;
-
- return TX_CONTINUE;
-}
-
-static ieee80211_tx_result debug_noinline
ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
@@ -1307,6 +1296,11 @@ static int __ieee80211_tx(struct ieee80211_local *local,
break;
}
+ if (sta && sta->uploaded)
+ info->control.sta = &sta->sta;
+ else
+ info->control.sta = NULL;
+
ret = drv_tx(local, skb);
if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) {
dev_kfree_skb(skb);
@@ -1346,7 +1340,6 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
CALL_TXH(ieee80211_tx_h_check_assoc);
CALL_TXH(ieee80211_tx_h_ps_buf);
CALL_TXH(ieee80211_tx_h_select_key);
- CALL_TXH(ieee80211_tx_h_sta);
if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
CALL_TXH(ieee80211_tx_h_rate_ctrl);
@@ -1942,11 +1935,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
h_pos += encaps_len;
}
+#ifdef CONFIG_MAC80211_MESH
if (meshhdrlen > 0) {
memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen);
nh_pos += meshhdrlen;
h_pos += meshhdrlen;
}
+#endif
if (ieee80211_is_data_qos(fc)) {
__le16 *qos_control;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 794792177376..748387d45bc0 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -803,8 +803,12 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
/* after reinitialize QoS TX queues setting to default,
* disable QoS at all */
- sdata->vif.bss_conf.qos = sdata->vif.type != NL80211_IFTYPE_STATION;
- ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
+
+ if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
+ sdata->vif.bss_conf.qos =
+ sdata->vif.type != NL80211_IFTYPE_STATION;
+ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
+ }
}
void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index c22a71c5cb45..81d4ad64184a 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -560,6 +560,22 @@ ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk)
return WORK_ACT_TIMEOUT;
}
+static enum work_action __must_check
+ieee80211_assoc_beacon_wait(struct ieee80211_work *wk)
+{
+ if (wk->started)
+ return WORK_ACT_TIMEOUT;
+
+ /*
+ * Wait up to one beacon interval ...
+ * should this be more if we miss one?
+ */
+ printk(KERN_DEBUG "%s: waiting for beacon from %pM\n",
+ wk->sdata->name, wk->filter_ta);
+ wk->timeout = TU_TO_EXP_TIME(wk->assoc.bss->beacon_interval);
+ return WORK_ACT_NONE;
+}
+
static void ieee80211_auth_challenge(struct ieee80211_work *wk,
struct ieee80211_mgmt *mgmt,
size_t len)
@@ -709,6 +725,25 @@ ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk,
return WORK_ACT_DONE;
}
+static enum work_action __must_check
+ieee80211_rx_mgmt_beacon(struct ieee80211_work *wk,
+ struct ieee80211_mgmt *mgmt, size_t len)
+{
+ struct ieee80211_sub_if_data *sdata = wk->sdata;
+ struct ieee80211_local *local = sdata->local;
+
+ ASSERT_WORK_MTX(local);
+
+ if (wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
+ return WORK_ACT_MISMATCH;
+
+ if (len < 24 + 12)
+ return WORK_ACT_NONE;
+
+ printk(KERN_DEBUG "%s: beacon received\n", sdata->name);
+ return WORK_ACT_DONE;
+}
+
static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
struct sk_buff *skb)
{
@@ -731,6 +766,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
case IEEE80211_WORK_DIRECT_PROBE:
case IEEE80211_WORK_AUTH:
case IEEE80211_WORK_ASSOC:
+ case IEEE80211_WORK_ASSOC_BEACON_WAIT:
bssid = wk->filter_ta;
break;
default:
@@ -745,6 +781,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
continue;
switch (fc & IEEE80211_FCTL_STYPE) {
+ case IEEE80211_STYPE_BEACON:
+ rma = ieee80211_rx_mgmt_beacon(wk, mgmt, skb->len);
+ break;
case IEEE80211_STYPE_PROBE_RESP:
rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len,
rx_status);
@@ -916,6 +955,9 @@ static void ieee80211_work_work(struct work_struct *work)
case IEEE80211_WORK_REMAIN_ON_CHANNEL:
rma = ieee80211_remain_on_channel_timeout(wk);
break;
+ case IEEE80211_WORK_ASSOC_BEACON_WAIT:
+ rma = ieee80211_assoc_beacon_wait(wk);
+ break;
}
wk->started = started;
@@ -1065,6 +1107,7 @@ ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
case IEEE80211_STYPE_PROBE_RESP:
case IEEE80211_STYPE_ASSOC_RESP:
case IEEE80211_STYPE_REASSOC_RESP:
+ case IEEE80211_STYPE_BEACON:
skb_queue_tail(&local->work_skb_queue, skb);
ieee80211_queue_work(&local->hw, &local->work_work);
return RX_QUEUED;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index f65c6494ede9..541e2fff5e9c 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -907,3 +907,52 @@ static void __exit cfg80211_exit(void)
destroy_workqueue(cfg80211_wq);
}
module_exit(cfg80211_exit);
+
+static int ___wiphy_printk(const char *level, const struct wiphy *wiphy,
+ struct va_format *vaf)
+{
+ if (!wiphy)
+ return printk("%s(NULL wiphy *): %pV", level, vaf);
+
+ return printk("%s%s: %pV", level, wiphy_name(wiphy), vaf);
+}
+
+int __wiphy_printk(const char *level, const struct wiphy *wiphy,
+ const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+ int r;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ r = ___wiphy_printk(level, wiphy, &vaf);
+ va_end(args);
+
+ return r;
+}
+EXPORT_SYMBOL(__wiphy_printk);
+
+#define define_wiphy_printk_level(func, kern_level) \
+int func(const struct wiphy *wiphy, const char *fmt, ...) \
+{ \
+ struct va_format vaf; \
+ va_list args; \
+ int r; \
+ \
+ va_start(args, fmt); \
+ \
+ vaf.fmt = fmt; \
+ vaf.va = &args; \
+ \
+ r = ___wiphy_printk(kern_level, wiphy, &vaf); \
+ va_end(args); \
+ \
+ return r; \
+} \
+EXPORT_SYMBOL(func);
+
+define_wiphy_printk_level(wiphy_debug, KERN_DEBUG);
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index adcabba02e20..27a8ce9343c3 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -247,8 +247,10 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
if (!netif_running(wdev->netdev))
return 0;
- if (wdev->wext.keys)
+ if (wdev->wext.keys) {
wdev->wext.keys->def = wdev->wext.default_key;
+ wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
+ }
wdev->wext.ibss.privacy = wdev->wext.default_key != -1;
diff --git a/net/wireless/lib80211_crypt_ccmp.c b/net/wireless/lib80211_crypt_ccmp.c
index b7fa31d5fd13..dacb3b4b1bdb 100644
--- a/net/wireless/lib80211_crypt_ccmp.c
+++ b/net/wireless/lib80211_crypt_ccmp.c
@@ -467,7 +467,6 @@ static struct lib80211_crypto_ops lib80211_crypt_ccmp = {
.name = "CCMP",
.init = lib80211_ccmp_init,
.deinit = lib80211_ccmp_deinit,
- .build_iv = lib80211_ccmp_hdr,
.encrypt_mpdu = lib80211_ccmp_encrypt,
.decrypt_mpdu = lib80211_ccmp_decrypt,
.encrypt_msdu = NULL,
diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c
index a7f995613f1f..0fe40510e2cb 100644
--- a/net/wireless/lib80211_crypt_tkip.c
+++ b/net/wireless/lib80211_crypt_tkip.c
@@ -757,7 +757,6 @@ static struct lib80211_crypto_ops lib80211_crypt_tkip = {
.name = "TKIP",
.init = lib80211_tkip_init,
.deinit = lib80211_tkip_deinit,
- .build_iv = lib80211_tkip_hdr,
.encrypt_mpdu = lib80211_tkip_encrypt,
.decrypt_mpdu = lib80211_tkip_decrypt,
.encrypt_msdu = lib80211_michael_mic_add,
diff --git a/net/wireless/lib80211_crypt_wep.c b/net/wireless/lib80211_crypt_wep.c
index 6d41e05ca33b..e2e88878ba35 100644
--- a/net/wireless/lib80211_crypt_wep.c
+++ b/net/wireless/lib80211_crypt_wep.c
@@ -269,7 +269,6 @@ static struct lib80211_crypto_ops lib80211_crypt_wep = {
.name = "WEP",
.init = lib80211_wep_init,
.deinit = lib80211_wep_deinit,
- .build_iv = lib80211_wep_build_iv,
.encrypt_mpdu = lib80211_wep_encrypt,
.decrypt_mpdu = lib80211_wep_decrypt,
.encrypt_msdu = NULL,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index fbfac588297c..37902a54e9c1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2769,6 +2769,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
nla_put_failure:
genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
err = -EMSGSIZE;
out:
/* Cleanup */
@@ -2960,6 +2961,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
nla_put_failure:
genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
err = -EMSGSIZE;
out:
mutex_unlock(&cfg80211_mutex);
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 48baf28cc4b6..f180db0de66c 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1306,6 +1306,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
{
int r = 0;
struct wiphy *wiphy = NULL;
+ enum nl80211_reg_initiator initiator = reg_request->initiator;
BUG_ON(!reg_request->alpha2);
@@ -1325,7 +1326,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
/* This is required so that the orig_* parameters are saved */
if (r == -EALREADY && wiphy &&
wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
- wiphy_update_regulatory(wiphy, reg_request->initiator);
+ wiphy_update_regulatory(wiphy, initiator);
out:
mutex_unlock(&reg_mutex);
mutex_unlock(&cfg80211_mutex);
@@ -1492,7 +1493,6 @@ void regulatory_hint_11d(struct wiphy *wiphy,
u8 *country_ie,
u8 country_ie_len)
{
- struct ieee80211_regdomain *rd = NULL;
char alpha2[2];
enum environment_cap env = ENVIRON_ANY;
struct regulatory_request *request;
@@ -1529,7 +1529,7 @@ void regulatory_hint_11d(struct wiphy *wiphy,
request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
if (!request)
- goto free_rd_out;
+ goto out;
request->wiphy_idx = get_wiphy_idx(wiphy);
request->alpha2[0] = alpha2[0];
@@ -1543,8 +1543,6 @@ void regulatory_hint_11d(struct wiphy *wiphy,
return;
-free_rd_out:
- kfree(rd);
out:
mutex_unlock(&reg_mutex);
}