Merge remote-tracking branch 'wireless-next/master' into ath-next

This commit is contained in:
Kalle Valo
2014-05-14 16:20:08 +03:00
190 changed files with 4403 additions and 2794 deletions
+1
View File
@@ -100,6 +100,7 @@
!Finclude/net/cfg80211.h wdev_priv
!Finclude/net/cfg80211.h ieee80211_iface_limit
!Finclude/net/cfg80211.h ieee80211_iface_combination
!Finclude/net/cfg80211.h cfg80211_check_combinations
</chapter>
<chapter>
<title>Actions and configuration</title>
-1
View File
@@ -7277,7 +7277,6 @@ F: drivers/video/aty/aty128fb.c
RALINK RT2X00 WIRELESS LAN DRIVER
P: rt2x00 project
M: Ivo van Doorn <IvDoorn@gmail.com>
M: Gertjan van Wingerde <gwingerde@gmail.com>
M: Helmut Schaa <helmut.schaa@googlemail.com>
L: linux-wireless@vger.kernel.org
L: users@rt2x00.serialmonkey.com (moderated for non-subscribers)
+1 -3
View File
@@ -23,9 +23,7 @@
#include "board.h"
static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = {
.name = "wifi_rfkill",
.reset_gpio = 25, /* PD1 */
.shutdown_gpio = 85, /* PK5 */
.name = "wifi_rfkill",
.type = RFKILL_TYPE_WLAN,
};
+2
View File
@@ -82,6 +82,7 @@ static const struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x04CA, 0x3004) },
{ USB_DEVICE(0x04CA, 0x3005) },
{ USB_DEVICE(0x04CA, 0x3006) },
{ USB_DEVICE(0x04CA, 0x3007) },
{ USB_DEVICE(0x04CA, 0x3008) },
{ USB_DEVICE(0x04CA, 0x300b) },
{ USB_DEVICE(0x0930, 0x0219) },
@@ -131,6 +132,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+3 -1
View File
@@ -59,6 +59,8 @@ struct btmrvl_device {
};
struct btmrvl_adapter {
void *hw_regs_buf;
u8 *hw_regs;
u32 int_count;
struct sk_buff_head tx_queue;
u8 psmode;
@@ -140,7 +142,7 @@ void btmrvl_interrupt(struct btmrvl_private *priv);
bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb);
int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb);
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd);
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd);
int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv);
int btmrvl_enable_ps(struct btmrvl_private *priv);
int btmrvl_prepare_command(struct btmrvl_private *priv);
+18 -1
View File
@@ -24,6 +24,7 @@
#include <net/bluetooth/hci_core.h>
#include "btmrvl_drv.h"
#include "btmrvl_sdio.h"
#define VERSION "1.0"
@@ -201,7 +202,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode,
return 0;
}
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd)
{
int ret;
@@ -337,10 +338,25 @@ static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
static void btmrvl_init_adapter(struct btmrvl_private *priv)
{
int buf_size;
skb_queue_head_init(&priv->adapter->tx_queue);
priv->adapter->ps_state = PS_AWAKE;
buf_size = ALIGN_SZ(SDIO_BLOCK_SIZE, BTSDIO_DMA_ALIGN);
priv->adapter->hw_regs_buf = kzalloc(buf_size, GFP_KERNEL);
if (!priv->adapter->hw_regs_buf) {
priv->adapter->hw_regs = NULL;
BT_ERR("Unable to allocate buffer for hw_regs.");
} else {
priv->adapter->hw_regs =
(u8 *)ALIGN_ADDR(priv->adapter->hw_regs_buf,
BTSDIO_DMA_ALIGN);
BT_DBG("hw_regs_buf=%p hw_regs=%p",
priv->adapter->hw_regs_buf, priv->adapter->hw_regs);
}
init_waitqueue_head(&priv->adapter->cmd_wait_q);
}
@@ -348,6 +364,7 @@ static void btmrvl_free_adapter(struct btmrvl_private *priv)
{
skb_queue_purge(&priv->adapter->tx_queue);
kfree(priv->adapter->hw_regs_buf);
kfree(priv->adapter);
priv->adapter = NULL;
+82 -21
View File
@@ -64,6 +64,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {
.io_port_0 = 0x00,
.io_port_1 = 0x01,
.io_port_2 = 0x02,
.int_read_to_clear = false,
};
static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
.cfg = 0x00,
@@ -80,6 +81,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
.io_port_0 = 0x78,
.io_port_1 = 0x79,
.io_port_2 = 0x7a,
.int_read_to_clear = false,
};
static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = {
@@ -97,6 +99,9 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = {
.io_port_0 = 0xd8,
.io_port_1 = 0xd9,
.io_port_2 = 0xda,
.int_read_to_clear = true,
.host_int_rsr = 0x01,
.card_misc_cfg = 0xcc,
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
@@ -667,6 +672,53 @@ static int btmrvl_sdio_process_int_status(struct btmrvl_private *priv)
return 0;
}
static int btmrvl_sdio_read_to_clear(struct btmrvl_sdio_card *card, u8 *ireg)
{
struct btmrvl_adapter *adapter = card->priv->adapter;
int ret;
ret = sdio_readsb(card->func, adapter->hw_regs, 0, SDIO_BLOCK_SIZE);
if (ret) {
BT_ERR("sdio_readsb: read int hw_regs failed: %d", ret);
return ret;
}
*ireg = adapter->hw_regs[card->reg->host_intstatus];
BT_DBG("hw_regs[%#x]=%#x", card->reg->host_intstatus, *ireg);
return 0;
}
static int btmrvl_sdio_write_to_clear(struct btmrvl_sdio_card *card, u8 *ireg)
{
int ret;
*ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret);
if (ret) {
BT_ERR("sdio_readb: read int status failed: %d", ret);
return ret;
}
if (*ireg) {
/*
* DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
* Clear the interrupt status register and re-enable the
* interrupt.
*/
BT_DBG("int_status = 0x%x", *ireg);
sdio_writeb(card->func, ~(*ireg) & (DN_LD_HOST_INT_STATUS |
UP_LD_HOST_INT_STATUS),
card->reg->host_intstatus, &ret);
if (ret) {
BT_ERR("sdio_writeb: clear int status failed: %d", ret);
return ret;
}
}
return 0;
}
static void btmrvl_sdio_interrupt(struct sdio_func *func)
{
struct btmrvl_private *priv;
@@ -684,28 +736,13 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
priv = card->priv;
ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret);
if (ret) {
BT_ERR("sdio_readb: read int status register failed");
if (card->reg->int_read_to_clear)
ret = btmrvl_sdio_read_to_clear(card, &ireg);
else
ret = btmrvl_sdio_write_to_clear(card, &ireg);
if (ret)
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);
sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
UP_LD_HOST_INT_STATUS),
card->reg->host_intstatus, &ret);
if (ret) {
BT_ERR("sdio_writeb: clear int status register failed");
return;
}
}
spin_lock_irqsave(&priv->driver_lock, flags);
sdio_ireg |= ireg;
@@ -777,6 +814,30 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
BT_DBG("SDIO FUNC%d IO port: 0x%x", func->num, card->ioport);
if (card->reg->int_read_to_clear) {
reg = sdio_readb(func, card->reg->host_int_rsr, &ret);
if (ret < 0) {
ret = -EIO;
goto release_irq;
}
sdio_writeb(func, reg | 0x3f, card->reg->host_int_rsr, &ret);
if (ret < 0) {
ret = -EIO;
goto release_irq;
}
reg = sdio_readb(func, card->reg->card_misc_cfg, &ret);
if (ret < 0) {
ret = -EIO;
goto release_irq;
}
sdio_writeb(func, reg | 0x10, card->reg->card_misc_cfg, &ret);
if (ret < 0) {
ret = -EIO;
goto release_irq;
}
}
sdio_set_drvdata(func, card);
sdio_release_host(func);
+3
View File
@@ -78,6 +78,9 @@ struct btmrvl_sdio_card_reg {
u8 io_port_0;
u8 io_port_1;
u8 io_port_2;
bool int_read_to_clear;
u8 host_int_rsr;
u8 card_misc_cfg;
};
struct btmrvl_sdio_card {
+2 -3
View File
@@ -152,6 +152,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
@@ -1485,10 +1486,8 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info & BTUSB_BCM92035)
hdev->setup = btusb_setup_bcm92035;
if (id->driver_info & BTUSB_INTEL) {
usb_enable_autosuspend(data->udev);
if (id->driver_info & BTUSB_INTEL)
hdev->setup = btusb_setup_intel;
}
/* Interface numbers are hardcoded in the specification */
data->isoc = usb_ifnum_to_if(data->udev, 1);
-7
View File
@@ -55,13 +55,6 @@ struct h4_struct {
struct sk_buff_head txq;
};
/* H4 receiver States */
#define H4_W4_PACKET_TYPE 0
#define H4_W4_EVENT_HDR 1
#define H4_W4_ACL_HDR 2
#define H4_W4_SCO_HDR 3
#define H4_W4_DATA 4
/* Initialize protocol */
static int h4_open(struct hci_uart *hu)
{
+2 -1
View File
@@ -1090,7 +1090,8 @@ static int ar5523_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
return ret;
}
static void ar5523_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
static void ar5523_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
struct ar5523 *ar = hw->priv;
+2 -1
View File
@@ -3651,7 +3651,8 @@ static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
return ret;
}
static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
struct ath10k *ar = hw->priv;
bool skip;
+2 -2
View File
@@ -3709,8 +3709,8 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CHIRP),
AR5K_TPC);
} else {
ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX |
AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
ath5k_hw_reg_write(ah, AR5K_TUNE_MAX_TXPOWER,
AR5K_PHY_TXPOWER_RATE_MAX);
}
return 0;
+2 -1
View File
@@ -53,7 +53,8 @@ obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o
obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o
ath9k_common-y:= common.o \
common-init.o \
common-beacon.o
common-beacon.o \
common-debug.o
ath9k_htc-y += htc_hst.o \
hif_usb.o \
-4
View File
@@ -86,7 +86,6 @@ static int ath_ahb_probe(struct platform_device *pdev)
int irq;
int ret = 0;
struct ath_hw *ah;
struct ath_common *common;
char hw_name[64];
if (!dev_get_platdata(&pdev->dev)) {
@@ -146,9 +145,6 @@ static int ath_ahb_probe(struct platform_device *pdev)
wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
hw_name, (unsigned long)mem, irq);
common = ath9k_hw_common(sc->sc_ah);
/* Will be cleared in ath9k_start() */
set_bit(ATH_OP_INVALID, &common->op_flags);
return 0;
err_irq:
+6
View File
@@ -155,6 +155,9 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel,
ATH9K_ANI_RSSI_THR_LOW,
ATH9K_ANI_RSSI_THR_HIGH);
if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_OFDM_DEF_LEVEL)
immunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
if (!scan)
aniState->ofdmNoiseImmunityLevel = immunityLevel;
@@ -235,6 +238,9 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel,
BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW,
ATH9K_ANI_RSSI_THR_HIGH);
if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_CCK_DEF_LEVEL)
immunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
if (ah->opmode == NL80211_IFTYPE_STATION &&
BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW &&
immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
@@ -410,7 +410,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
{0x00009e30, 0x06336f77},
{0x00009e34, 0x6af6532f},
{0x00009e38, 0x0cc80c00},
{0x00009e40, 0x0d261820},
{0x00009e40, 0x0d261800},
{0x00009e4c, 0x00001004},
{0x00009e50, 0x00ff03f1},
{0x00009e54, 0x00000000},
@@ -592,7 +592,7 @@ static const u32 ar9331_1p1_baseband_core[][2] = {
{0x00009e30, 0x06336f77},
{0x00009e34, 0x6af6532f},
{0x00009e38, 0x0cc80c00},
{0x00009e40, 0x0d261820},
{0x00009e40, 0x0d261800},
{0x00009e4c, 0x00001004},
{0x00009e50, 0x00ff03f1},
{0x00009fc0, 0x803e4788},
@@ -231,7 +231,7 @@ static const u32 ar9331_1p2_baseband_core[][2] = {
{0x00009e30, 0x06336f77},
{0x00009e34, 0x6af6532f},
{0x00009e38, 0x0cc80c00},
{0x00009e40, 0x0d261820},
{0x00009e40, 0x0d261800},
{0x00009e4c, 0x00001004},
{0x00009e50, 0x00ff03f1},
{0x00009fc0, 0x803e4788},
@@ -318,7 +318,7 @@ static const u32 ar9340_1p0_baseband_core[][2] = {
{0x00009e30, 0x06336f77},
{0x00009e34, 0x6af6532f},
{0x00009e38, 0x0cc80c00},
{0x00009e40, 0x0d261820},
{0x00009e40, 0x0d261800},
{0x00009e4c, 0x00001004},
{0x00009e50, 0x00ff03f1},
{0x00009e54, 0x00000000},
@@ -348,9 +348,9 @@ static const u32 ar9340_1p0_baseband_core[][2] = {
{0x0000a370, 0x00000000},
{0x0000a390, 0x00000001},
{0x0000a394, 0x00000444},
{0x0000a398, 0x00000000},
{0x0000a39c, 0x210d0401},
{0x0000a3a0, 0xab9a7144},
{0x0000a398, 0x001f0e0f},
{0x0000a39c, 0x0075393f},
{0x0000a3a0, 0xb79f6427},
{0x0000a3a4, 0x00000000},
{0x0000a3a8, 0xaaaaaaaa},
{0x0000a3ac, 0x3c466478},
@@ -257,9 +257,9 @@ static const u32 qca953x_1p0_baseband_core[][2] = {
{0x0000a370, 0x00000000},
{0x0000a390, 0x00000001},
{0x0000a394, 0x00000444},
{0x0000a398, 0x1f020503},
{0x0000a39c, 0x29180c03},
{0x0000a3a0, 0x9a8b6844},
{0x0000a398, 0x001f0e0f},
{0x0000a39c, 0x0075393f},
{0x0000a3a0, 0xb79f6427},
{0x0000a3a4, 0x000000ff},
{0x0000a3a8, 0x6a6a6a6a},
{0x0000a3ac, 0x6a6a6a6a},
@@ -90,7 +90,7 @@ static const u32 ar9580_1p0_baseband_core[][2] = {
{0x00009e30, 0x06336f77},
{0x00009e34, 0x6af6532f},
{0x00009e38, 0x0cc80c00},
{0x00009e40, 0x0d261820},
{0x00009e40, 0x0d261800},
{0x00009e4c, 0x00001004},
{0x00009e50, 0x00ff03f1},
{0x00009e54, 0x00000000},
+1 -2
View File
@@ -23,8 +23,8 @@
#include <linux/leds.h>
#include <linux/completion.h>
#include "debug.h"
#include "common.h"
#include "debug.h"
#include "mci.h"
#include "dfs.h"
#include "spectral.h"
@@ -254,7 +254,6 @@ struct ath_atx_tid {
s8 bar_index;
bool sched;
bool paused;
bool active;
};
+3 -2
View File
@@ -537,8 +537,6 @@ static void ath9k_cache_beacon_config(struct ath_softc *sc,
cur_conf->dtim_period = bss_conf->dtim_period;
cur_conf->dtim_count = 1;
cur_conf->ibss_creator = bss_conf->ibss_creator;
cur_conf->bmiss_timeout =
ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
/*
* It looks like mac80211 may end up using beacon interval of zero in
@@ -549,6 +547,9 @@ static void ath9k_cache_beacon_config(struct ath_softc *sc,
if (cur_conf->beacon_interval == 0)
cur_conf->beacon_interval = 100;
cur_conf->bmiss_timeout =
ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
/*
* We don't parse dtim period from mac80211 during the driver
* initialization as it breaks association with hidden-ssid
@@ -0,0 +1,253 @@
/*
* Copyright (c) 2008-2011 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, 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.
*/
#include "common.h"
static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_hw *ah = file->private_data;
u32 len = 0, size = 6000;
char *buf;
size_t retval;
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
len = ah->eep_ops->dump_eeprom(ah, false, buf, len, size);
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
}
static const struct file_operations fops_modal_eeprom = {
.read = read_file_modal_eeprom,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
void ath9k_cmn_debug_modal_eeprom(struct dentry *debugfs_phy,
struct ath_hw *ah)
{
debugfs_create_file("modal_eeprom", S_IRUSR, debugfs_phy, ah,
&fops_modal_eeprom);
}
EXPORT_SYMBOL(ath9k_cmn_debug_modal_eeprom);
static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_hw *ah = file->private_data;
u32 len = 0, size = 1500;
ssize_t retval = 0;
char *buf;
buf = kzalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
len = ah->eep_ops->dump_eeprom(ah, true, buf, len, size);
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
}
static const struct file_operations fops_base_eeprom = {
.read = read_file_base_eeprom,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy,
struct ath_hw *ah)
{
debugfs_create_file("base_eeprom", S_IRUSR, debugfs_phy, ah,
&fops_base_eeprom);
}
EXPORT_SYMBOL(ath9k_cmn_debug_base_eeprom);
void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats,
struct ath_rx_status *rs)
{
#define RX_PHY_ERR_INC(c) rxstats->phy_err_stats[c]++
#define RX_CMN_STAT_INC(c) (rxstats->c++)
RX_CMN_STAT_INC(rx_pkts_all);
rxstats->rx_bytes_all += rs->rs_datalen;
if (rs->rs_status & ATH9K_RXERR_CRC)
RX_CMN_STAT_INC(crc_err);
if (rs->rs_status & ATH9K_RXERR_DECRYPT)
RX_CMN_STAT_INC(decrypt_crc_err);
if (rs->rs_status & ATH9K_RXERR_MIC)
RX_CMN_STAT_INC(mic_err);
if (rs->rs_status & ATH9K_RX_DELIM_CRC_PRE)
RX_CMN_STAT_INC(pre_delim_crc_err);
if (rs->rs_status & ATH9K_RX_DELIM_CRC_POST)
RX_CMN_STAT_INC(post_delim_crc_err);
if (rs->rs_status & ATH9K_RX_DECRYPT_BUSY)
RX_CMN_STAT_INC(decrypt_busy_err);
if (rs->rs_status & ATH9K_RXERR_PHY) {
RX_CMN_STAT_INC(phy_err);
if (rs->rs_phyerr < ATH9K_PHYERR_MAX)
RX_PHY_ERR_INC(rs->rs_phyerr);
}
#undef RX_CMN_STAT_INC
#undef RX_PHY_ERR_INC
}
EXPORT_SYMBOL(ath9k_cmn_debug_stat_rx);
static ssize_t read_file_recv(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
#define RXS_ERR(s, e) \
do { \
len += scnprintf(buf + len, size - len, \
"%18s : %10u\n", s, \
rxstats->e); \
} while (0)
struct ath_rx_stats *rxstats = file->private_data;
char *buf;
unsigned int len = 0, size = 1600;
ssize_t retval = 0;
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
RXS_ERR("PKTS-ALL", rx_pkts_all);
RXS_ERR("BYTES-ALL", rx_bytes_all);
RXS_ERR("BEACONS", rx_beacons);
RXS_ERR("FRAGS", rx_frags);
RXS_ERR("SPECTRAL", rx_spectral);
RXS_ERR("CRC ERR", crc_err);
RXS_ERR("DECRYPT CRC ERR", decrypt_crc_err);
RXS_ERR("PHY ERR", phy_err);
RXS_ERR("MIC ERR", mic_err);
RXS_ERR("PRE-DELIM CRC ERR", pre_delim_crc_err);
RXS_ERR("POST-DELIM CRC ERR", post_delim_crc_err);
RXS_ERR("DECRYPT BUSY ERR", decrypt_busy_err);
RXS_ERR("LENGTH-ERR", rx_len_err);
RXS_ERR("OOM-ERR", rx_oom_err);
RXS_ERR("RATE-ERR", rx_rate_err);
RXS_ERR("TOO-MANY-FRAGS", rx_too_many_frags_err);
if (len > size)
len = size;
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
#undef RXS_ERR
}
static const struct file_operations fops_recv = {
.read = read_file_recv,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
void ath9k_cmn_debug_recv(struct dentry *debugfs_phy,
struct ath_rx_stats *rxstats)
{
debugfs_create_file("recv", S_IRUSR, debugfs_phy, rxstats,
&fops_recv);
}
EXPORT_SYMBOL(ath9k_cmn_debug_recv);
static ssize_t read_file_phy_err(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
#define PHY_ERR(s, p) \
len += scnprintf(buf + len, size - len, "%22s : %10u\n", s, \
rxstats->phy_err_stats[p]);
struct ath_rx_stats *rxstats = file->private_data;
char *buf;
unsigned int len = 0, size = 1600;
ssize_t retval = 0;
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN);
PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING);
PHY_ERR("PARITY ERR", ATH9K_PHYERR_PARITY);
PHY_ERR("RATE ERR", ATH9K_PHYERR_RATE);
PHY_ERR("LENGTH ERR", ATH9K_PHYERR_LENGTH);
PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR);
PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE);
PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR);
PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING);
PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
PHY_ERR("OFDM-LENGTH ERR", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL);
PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP);
PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE);
PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART);
PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT);
PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING);
PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC);
PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE);
PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART);
PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP);
PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR);
PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL);
if (len > size)
len = size;
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
#undef PHY_ERR
}
static const struct file_operations fops_phy_err = {
.read = read_file_phy_err,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
void ath9k_cmn_debug_phy_err(struct dentry *debugfs_phy,
struct ath_rx_stats *rxstats)
{
debugfs_create_file("phy_err", S_IRUSR, debugfs_phy, rxstats,
&fops_phy_err);
}
EXPORT_SYMBOL(ath9k_cmn_debug_phy_err);
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2008-2011 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, 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.
*/
/**
* struct ath_rx_stats - RX Statistics
* @rx_pkts_all: No. of total frames received, including ones that
may have had errors.
* @rx_bytes_all: No. of total bytes received, including ones that
may have had errors.
* @crc_err: No. of frames with incorrect CRC value
* @decrypt_crc_err: No. of frames whose CRC check failed after
decryption process completed
* @phy_err: No. of frames whose reception failed because the PHY
encountered an error
* @mic_err: No. of frames with incorrect TKIP MIC verification failure
* @pre_delim_crc_err: Pre-Frame delimiter CRC error detections
* @post_delim_crc_err: Post-Frame delimiter CRC error detections
* @decrypt_busy_err: Decryption interruptions counter
* @phy_err_stats: Individual PHY error statistics
* @rx_len_err: No. of frames discarded due to bad length.
* @rx_oom_err: No. of frames dropped due to OOM issues.
* @rx_rate_err: No. of frames dropped due to rate errors.
* @rx_too_many_frags_err: Frames dropped due to too-many-frags received.
* @rx_beacons: No. of beacons received.
* @rx_frags: No. of rx-fragements received.
* @rx_spectral: No of spectral packets received.
*/
struct ath_rx_stats {
u32 rx_pkts_all;
u32 rx_bytes_all;
u32 crc_err;
u32 decrypt_crc_err;
u32 phy_err;
u32 mic_err;
u32 pre_delim_crc_err;
u32 post_delim_crc_err;
u32 decrypt_busy_err;
u32 phy_err_stats[ATH9K_PHYERR_MAX];
u32 rx_len_err;
u32 rx_oom_err;
u32 rx_rate_err;
u32 rx_too_many_frags_err;
u32 rx_beacons;
u32 rx_frags;
u32 rx_spectral;
};
void ath9k_cmn_debug_modal_eeprom(struct dentry *debugfs_phy,
struct ath_hw *ah);
void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy,
struct ath_hw *ah);
void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats,
struct ath_rx_status *rs);
void ath9k_cmn_debug_recv(struct dentry *debugfs_phy,
struct ath_rx_stats *rxstats);
void ath9k_cmn_debug_phy_err(struct dentry *debugfs_phy,
struct ath_rx_stats *rxstats);
+1
View File
@@ -23,6 +23,7 @@
#include "common-init.h"
#include "common-beacon.h"
#include "common-debug.h"
/* Common header for Atheros 802.11n base driver cores */
+9 -205
View File
@@ -948,151 +948,11 @@ static const struct file_operations fops_reset = {
.llseek = default_llseek,
};
static ssize_t read_file_recv(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
#define RXS_ERR(s, e) \
do { \
len += scnprintf(buf + len, size - len, \
"%18s : %10u\n", s, \
sc->debug.stats.rxstats.e);\
} while (0)
struct ath_softc *sc = file->private_data;
char *buf;
unsigned int len = 0, size = 1600;
ssize_t retval = 0;
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
RXS_ERR("PKTS-ALL", rx_pkts_all);
RXS_ERR("BYTES-ALL", rx_bytes_all);
RXS_ERR("BEACONS", rx_beacons);
RXS_ERR("FRAGS", rx_frags);
RXS_ERR("SPECTRAL", rx_spectral);
RXS_ERR("CRC ERR", crc_err);
RXS_ERR("DECRYPT CRC ERR", decrypt_crc_err);
RXS_ERR("PHY ERR", phy_err);
RXS_ERR("MIC ERR", mic_err);
RXS_ERR("PRE-DELIM CRC ERR", pre_delim_crc_err);
RXS_ERR("POST-DELIM CRC ERR", post_delim_crc_err);
RXS_ERR("DECRYPT BUSY ERR", decrypt_busy_err);
RXS_ERR("LENGTH-ERR", rx_len_err);
RXS_ERR("OOM-ERR", rx_oom_err);
RXS_ERR("RATE-ERR", rx_rate_err);
RXS_ERR("TOO-MANY-FRAGS", rx_too_many_frags_err);
if (len > size)
len = size;
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
#undef RXS_ERR
}
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
{
#define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++
RX_STAT_INC(rx_pkts_all);
sc->debug.stats.rxstats.rx_bytes_all += rs->rs_datalen;
if (rs->rs_status & ATH9K_RXERR_CRC)
RX_STAT_INC(crc_err);
if (rs->rs_status & ATH9K_RXERR_DECRYPT)
RX_STAT_INC(decrypt_crc_err);
if (rs->rs_status & ATH9K_RXERR_MIC)
RX_STAT_INC(mic_err);
if (rs->rs_status & ATH9K_RX_DELIM_CRC_PRE)
RX_STAT_INC(pre_delim_crc_err);
if (rs->rs_status & ATH9K_RX_DELIM_CRC_POST)
RX_STAT_INC(post_delim_crc_err);
if (rs->rs_status & ATH9K_RX_DECRYPT_BUSY)
RX_STAT_INC(decrypt_busy_err);
if (rs->rs_status & ATH9K_RXERR_PHY) {
RX_STAT_INC(phy_err);
if (rs->rs_phyerr < ATH9K_PHYERR_MAX)
RX_PHY_ERR_INC(rs->rs_phyerr);
}
#undef RX_PHY_ERR_INC
ath9k_cmn_debug_stat_rx(&sc->debug.stats.rxstats, rs);
}
static const struct file_operations fops_recv = {
.read = read_file_recv,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t read_file_phy_err(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
#define PHY_ERR(s, p) \
len += scnprintf(buf + len, size - len, "%22s : %10u\n", s, \
sc->debug.stats.rxstats.phy_err_stats[p]);
struct ath_softc *sc = file->private_data;
char *buf;
unsigned int len = 0, size = 1600;
ssize_t retval = 0;
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN);
PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING);
PHY_ERR("PARITY ERR", ATH9K_PHYERR_PARITY);
PHY_ERR("RATE ERR", ATH9K_PHYERR_RATE);
PHY_ERR("LENGTH ERR", ATH9K_PHYERR_LENGTH);
PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR);
PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE);
PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR);
PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING);
PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
PHY_ERR("OFDM-LENGTH ERR", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL);
PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP);
PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE);
PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART);
PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT);
PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING);
PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC);
PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE);
PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART);
PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP);
PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR);
PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL);
if (len > size)
len = size;
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
#undef PHY_ERR
}
static const struct file_operations fops_phy_err = {
.read = read_file_phy_err,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -1268,62 +1128,6 @@ static const struct file_operations fops_dump_nfcal = {
.llseek = default_llseek,
};
static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
struct ath_hw *ah = sc->sc_ah;
u32 len = 0, size = 1500;
ssize_t retval = 0;
char *buf;
buf = kzalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
len = ah->eep_ops->dump_eeprom(ah, true, buf, len, size);
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
}
static const struct file_operations fops_base_eeprom = {
.read = read_file_base_eeprom,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
struct ath_hw *ah = sc->sc_ah;
u32 len = 0, size = 6000;
char *buf;
size_t retval;
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
len = ah->eep_ops->dump_eeprom(ah, false, buf, len, size);
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
}
static const struct file_operations fops_modal_eeprom = {
.read = read_file_modal_eeprom,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
static ssize_t read_file_btcoex(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -1524,10 +1328,10 @@ int ath9k_init_debug(struct ath_hw *ah)
&fops_misc);
debugfs_create_file("reset", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_reset);
debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_recv);
debugfs_create_file("phy_err", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_phy_err);
ath9k_cmn_debug_recv(sc->debug.debugfs_phy, &sc->debug.stats.rxstats);
ath9k_cmn_debug_phy_err(sc->debug.debugfs_phy, &sc->debug.stats.rxstats);
debugfs_create_u8("rx_chainmask", S_IRUSR, sc->debug.debugfs_phy,
&ah->rxchainmask);
debugfs_create_u8("tx_chainmask", S_IRUSR, sc->debug.debugfs_phy,
@@ -1547,10 +1351,10 @@ int ath9k_init_debug(struct ath_hw *ah)
&fops_regdump);
debugfs_create_file("dump_nfcal", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_dump_nfcal);
debugfs_create_file("base_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_base_eeprom);
debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_modal_eeprom);
ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah);
ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah);
debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
-44
View File
@@ -221,50 +221,6 @@ struct ath_rx_rate_stats {
} cck_stats[4];
};
/**
* struct ath_rx_stats - RX Statistics
* @rx_pkts_all: No. of total frames received, including ones that
may have had errors.
* @rx_bytes_all: No. of total bytes received, including ones that
may have had errors.
* @crc_err: No. of frames with incorrect CRC value
* @decrypt_crc_err: No. of frames whose CRC check failed after
decryption process completed
* @phy_err: No. of frames whose reception failed because the PHY
encountered an error
* @mic_err: No. of frames with incorrect TKIP MIC verification failure
* @pre_delim_crc_err: Pre-Frame delimiter CRC error detections
* @post_delim_crc_err: Post-Frame delimiter CRC error detections
* @decrypt_busy_err: Decryption interruptions counter
* @phy_err_stats: Individual PHY error statistics
* @rx_len_err: No. of frames discarded due to bad length.
* @rx_oom_err: No. of frames dropped due to OOM issues.
* @rx_rate_err: No. of frames dropped due to rate errors.
* @rx_too_many_frags_err: Frames dropped due to too-many-frags received.
* @rx_beacons: No. of beacons received.
* @rx_frags: No. of rx-fragements received.
* @rx_spectral: No of spectral packets received.
*/
struct ath_rx_stats {
u32 rx_pkts_all;
u32 rx_bytes_all;
u32 crc_err;
u32 decrypt_crc_err;
u32 phy_err;
u32 mic_err;
u32 pre_delim_crc_err;
u32 post_delim_crc_err;
u32 decrypt_busy_err;
u32 phy_err_stats[ATH9K_PHYERR_MAX];
u32 rx_len_err;
u32 rx_oom_err;
u32 rx_rate_err;
u32 rx_too_many_frags_err;
u32 rx_beacons;
u32 rx_frags;
u32 rx_spectral;
};
#define ANT_MAIN 0
#define ANT_ALT 1
+2 -3
View File
@@ -72,7 +72,7 @@ static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf,
ath_txq_lock(sc, txq);
if (tid->active) {
len += scnprintf(buf + len, size - len,
"%3d%11d%10d%10d%10d%10d%9d%6d%8d\n",
"%3d%11d%10d%10d%10d%10d%9d%6d\n",
tid->tidno,
tid->seq_start,
tid->seq_next,
@@ -80,8 +80,7 @@ static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf,
tid->baw_head,
tid->baw_tail,
tid->bar_index,
tid->sched,
tid->paused);
tid->sched);
}
ath_txq_unlock(sc, txq);
}
+3 -3
View File
@@ -178,12 +178,12 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
pe.ts = mactime;
if (ath9k_postprocess_radar_event(sc, &ard, &pe)) {
struct dfs_pattern_detector *pd = sc->dfs_detector;
static u64 last_ts;
ath_dbg(common, DFS,
"ath9k_dfs_process_phyerr: channel=%d, ts=%llu, "
"width=%d, rssi=%d, delta_ts=%llu\n",
pe.freq, pe.ts, pe.width, pe.rssi, pe.ts-last_ts);
last_ts = pe.ts;
pe.freq, pe.ts, pe.width, pe.rssi,
pe.ts - sc->debug.stats.dfs_stats.last_ts);
sc->debug.stats.dfs_stats.last_ts = pe.ts;
DFS_STAT_INC(sc, pulses_processed);
if (pd != NULL && pd->add_pulse(pd, &pe)) {
DFS_STAT_INC(sc, radar_detected);
@@ -51,6 +51,7 @@ struct ath_dfs_stats {
/* pattern detection stats */
u32 pulses_processed;
u32 radar_detected;
u64 last_ts;
};
#if defined(CONFIG_ATH9K_DFS_DEBUGFS)
+5 -12
View File
@@ -325,14 +325,14 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
#define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++)
#define TX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c += a)
#define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++)
#define RX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c += a)
#define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c++)
#define RX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c += a)
#define CAB_STAT_INC priv->debug.tx_stats.cab_queued++
#define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
struct ath_htc_rx_status *rxs);
struct ath_rx_status *rs);
struct ath_tx_stats {
u32 buf_queued;
@@ -345,25 +345,18 @@ struct ath_tx_stats {
u32 queue_stats[IEEE80211_NUM_ACS];
};
struct ath_rx_stats {
struct ath_skbrx_stats {
u32 skb_allocated;
u32 skb_completed;
u32 skb_completed_bytes;
u32 skb_dropped;
u32 err_crc;
u32 err_decrypt_crc;
u32 err_mic;
u32 err_pre_delim;
u32 err_post_delim;
u32 err_decrypt_busy;
u32 err_phy;
u32 err_phy_stats[ATH9K_PHYERR_MAX];
};
struct ath9k_debug {
struct dentry *debugfs_phy;
struct ath_tx_stats tx_stats;
struct ath_rx_stats rx_stats;
struct ath_skbrx_stats skbrx_stats;
};
void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
+33 -522
View File
@@ -243,39 +243,14 @@ static const struct file_operations fops_xmit = {
};
void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
struct ath_htc_rx_status *rxs)
struct ath_rx_status *rs)
{
#define RX_PHY_ERR_INC(c) priv->debug.rx_stats.err_phy_stats[c]++
if (rxs->rs_status & ATH9K_RXERR_CRC)
priv->debug.rx_stats.err_crc++;
if (rxs->rs_status & ATH9K_RXERR_DECRYPT)
priv->debug.rx_stats.err_decrypt_crc++;
if (rxs->rs_status & ATH9K_RXERR_MIC)
priv->debug.rx_stats.err_mic++;
if (rxs->rs_status & ATH9K_RX_DELIM_CRC_PRE)
priv->debug.rx_stats.err_pre_delim++;
if (rxs->rs_status & ATH9K_RX_DELIM_CRC_POST)
priv->debug.rx_stats.err_post_delim++;
if (rxs->rs_status & ATH9K_RX_DECRYPT_BUSY)
priv->debug.rx_stats.err_decrypt_busy++;
if (rxs->rs_status & ATH9K_RXERR_PHY) {
priv->debug.rx_stats.err_phy++;
if (rxs->rs_phyerr < ATH9K_PHYERR_MAX)
RX_PHY_ERR_INC(rxs->rs_phyerr);
}
#undef RX_PHY_ERR_INC
ath9k_cmn_debug_stat_rx(&priv->debug.rx_stats, rs);
}
static ssize_t read_file_recv(struct file *file, char __user *user_buf,
static ssize_t read_file_skb_rx(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
#define PHY_ERR(s, p) \
len += scnprintf(buf + len, size - len, "%20s : %10u\n", s, \
priv->debug.rx_stats.err_phy_stats[p]);
struct ath9k_htc_priv *priv = file->private_data;
char *buf;
unsigned int len = 0, size = 1500;
@@ -287,63 +262,13 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
len += scnprintf(buf + len, size - len,
"%20s : %10u\n", "SKBs allocated",
priv->debug.rx_stats.skb_allocated);
priv->debug.skbrx_stats.skb_allocated);
len += scnprintf(buf + len, size - len,
"%20s : %10u\n", "SKBs completed",
priv->debug.rx_stats.skb_completed);
priv->debug.skbrx_stats.skb_completed);
len += scnprintf(buf + len, size - len,
"%20s : %10u\n", "SKBs Dropped",
priv->debug.rx_stats.skb_dropped);
len += scnprintf(buf + len, size - len,
"%20s : %10u\n", "CRC ERR",
priv->debug.rx_stats.err_crc);
len += scnprintf(buf + len, size - len,
"%20s : %10u\n", "DECRYPT CRC ERR",
priv->debug.rx_stats.err_decrypt_crc);
len += scnprintf(buf + len, size - len,
"%20s : %10u\n", "MIC ERR",
priv->debug.rx_stats.err_mic);
len += scnprintf(buf + len, size - len,
"%20s : %10u\n", "PRE-DELIM CRC ERR",
priv->debug.rx_stats.err_pre_delim);
len += scnprintf(buf + len, size - len,
"%20s : %10u\n", "POST-DELIM CRC ERR",
priv->debug.rx_stats.err_post_delim);
len += scnprintf(buf + len, size - len,
"%20s : %10u\n", "DECRYPT BUSY ERR",
priv->debug.rx_stats.err_decrypt_busy);
len += scnprintf(buf + len, size - len,
"%20s : %10u\n", "TOTAL PHY ERR",
priv->debug.rx_stats.err_phy);
PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN);
PHY_ERR("TIMING", ATH9K_PHYERR_TIMING);
PHY_ERR("PARITY", ATH9K_PHYERR_PARITY);
PHY_ERR("RATE", ATH9K_PHYERR_RATE);
PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH);
PHY_ERR("RADAR", ATH9K_PHYERR_RADAR);
PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE);
PHY_ERR("TOR", ATH9K_PHYERR_TOR);
PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING);
PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL);
PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP);
PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE);
PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART);
PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT);
PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING);
PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC);
PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE);
PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART);
PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP);
PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR);
PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL);
priv->debug.skbrx_stats.skb_dropped);
if (len > size)
len = size;
@@ -352,12 +277,10 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
kfree(buf);
return retval;
#undef PHY_ERR
}
static const struct file_operations fops_recv = {
.read = read_file_recv,
static const struct file_operations fops_skb_rx = {
.read = read_file_skb_rx,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
@@ -486,423 +409,6 @@ static const struct file_operations fops_debug = {
.llseek = default_llseek,
};
static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath9k_htc_priv *priv = file->private_data;
struct ath_common *common = ath9k_hw_common(priv->ah);
struct base_eep_header *pBase = NULL;
unsigned int len = 0, size = 1500;
ssize_t retval = 0;
char *buf;
pBase = ath9k_htc_get_eeprom_base(priv);
if (pBase == NULL) {
ath_err(common, "Unknown EEPROM type\n");
return 0;
}
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
len += scnprintf(buf + len, size - len,
"%20s : %10d\n", "Major Version",
pBase->version >> 12);
len += scnprintf(buf + len, size - len,
"%20s : %10d\n", "Minor Version",
pBase->version & 0xFFF);
len += scnprintf(buf + len, size - len,
"%20s : %10d\n", "Checksum",
pBase->checksum);
len += scnprintf(buf + len, size - len,
"%20s : %10d\n", "Length",
pBase->length);
len += scnprintf(buf + len, size - len,
"%20s : %10d\n", "RegDomain1",
pBase->regDmn[0]);
len += scnprintf(buf + len, size - len,
"%20s : %10d\n", "RegDomain2",
pBase->regDmn[1]);
len += scnprintf(buf + len, size - len,
"%20s : %10d\n",
"TX Mask", pBase->txMask);
len += scnprintf(buf + len, size - len,
"%20s : %10d\n",
"RX Mask", pBase->rxMask);
len += scnprintf(buf + len, size - len,
"%20s : %10d\n",
"Allow 5GHz",
!!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
len += scnprintf(buf + len, size - len,
"%20s : %10d\n",
"Allow 2GHz",
!!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
len += scnprintf(buf + len, size - len,
"%20s : %10d\n",
"Disable 2GHz HT20",
!!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT20));
len += scnprintf(buf + len, size - len,
"%20s : %10d\n",
"Disable 2GHz HT40",
!!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT40));
len += scnprintf(buf + len, size - len,
"%20s : %10d\n",
"Disable 5Ghz HT20",
!!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT20));
len += scnprintf(buf + len, size - len,
"%20s : %10d\n",
"Disable 5Ghz HT40",
!!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT40));
len += scnprintf(buf + len, size - len,
"%20s : %10d\n",
"Big Endian",
!!(pBase->eepMisc & 0x01));
len += scnprintf(buf + len, size - len,
"%20s : %10d\n",
"Cal Bin Major Ver",
(pBase->binBuildNumber >> 24) & 0xFF);
len += scnprintf(buf + len, size - len,
"%20s : %10d\n",
"Cal Bin Minor Ver",
(pBase->binBuildNumber >> 16) & 0xFF);
len += scnprintf(buf + len, size - len,
"%20s : %10d\n",
"Cal Bin Build",
(pBase->binBuildNumber >> 8) & 0xFF);
/*
* UB91 specific data.
*/
if (AR_SREV_9271(priv->ah)) {
struct base_eep_header_4k *pBase4k =
&priv->ah->eeprom.map4k.baseEepHeader;
len += scnprintf(buf + len, size - len,
"%20s : %10d\n",
"TX Gain type",
pBase4k->txGainType);
}
/*
* UB95 specific data.
*/
if (priv->ah->hw_version.usbdev == AR9287_USB) {
struct base_eep_ar9287_header *pBase9287 =
&priv->ah->eeprom.map9287.baseEepHeader;
len += scnprintf(buf + len, size - len,
"%20s : %10ddB\n",
"Power Table Offset",
pBase9287->pwrTableOffset);
len += scnprintf(buf + len, size - len,
"%20s : %10d\n",
"OpenLoop Power Ctrl",
pBase9287->openLoopPwrCntl);
}
len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
pBase->macAddr);
if (len > size)
len = size;
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
}
static const struct file_operations fops_base_eeprom = {
.read = read_file_base_eeprom,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t read_4k_modal_eeprom(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
#define PR_EEP(_s, _val) \
do { \
len += scnprintf(buf + len, size - len, "%20s : %10d\n",\
_s, (_val)); \
} while (0)
struct ath9k_htc_priv *priv = file->private_data;
struct modal_eep_4k_header *pModal = &priv->ah->eeprom.map4k.modalHeader;
unsigned int len = 0, size = 2048;
ssize_t retval = 0;
char *buf;
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]);
PR_EEP("Ant. Common Control", pModal->antCtrlCommon);
PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]);
PR_EEP("Switch Settle", pModal->switchSettling);
PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]);
PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]);
PR_EEP("ADC Desired size", pModal->adcDesiredSize);
PR_EEP("PGA Desired size", pModal->pgaDesiredSize);
PR_EEP("Chain0 xlna Gain", pModal->xlnaGainCh[0]);
PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff);
PR_EEP("txEndToRxOn", pModal->txEndToRxOn);
PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn);
PR_EEP("CCA Threshold)", pModal->thresh62);
PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]);
PR_EEP("xpdGain", pModal->xpdGain);
PR_EEP("External PD", pModal->xpd);
PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]);
PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]);
PR_EEP("pdGainOverlap", pModal->pdGainOverlap);
PR_EEP("O/D Bias Version", pModal->version);
PR_EEP("CCK OutputBias", pModal->ob_0);
PR_EEP("BPSK OutputBias", pModal->ob_1);
PR_EEP("QPSK OutputBias", pModal->ob_2);
PR_EEP("16QAM OutputBias", pModal->ob_3);
PR_EEP("64QAM OutputBias", pModal->ob_4);
PR_EEP("CCK Driver1_Bias", pModal->db1_0);
PR_EEP("BPSK Driver1_Bias", pModal->db1_1);
PR_EEP("QPSK Driver1_Bias", pModal->db1_2);
PR_EEP("16QAM Driver1_Bias", pModal->db1_3);
PR_EEP("64QAM Driver1_Bias", pModal->db1_4);
PR_EEP("CCK Driver2_Bias", pModal->db2_0);
PR_EEP("BPSK Driver2_Bias", pModal->db2_1);
PR_EEP("QPSK Driver2_Bias", pModal->db2_2);
PR_EEP("16QAM Driver2_Bias", pModal->db2_3);
PR_EEP("64QAM Driver2_Bias", pModal->db2_4);
PR_EEP("xPA Bias Level", pModal->xpaBiasLvl);
PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart);
PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn);
PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc);
PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]);
PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]);
PR_EEP("HT40 Switch Settle", pModal->swSettleHt40);
PR_EEP("Chain0 xatten2Db", pModal->xatten2Db[0]);
PR_EEP("Chain0 xatten2Margin", pModal->xatten2Margin[0]);
PR_EEP("Ant. Diversity ctl1", pModal->antdiv_ctl1);
PR_EEP("Ant. Diversity ctl2", pModal->antdiv_ctl2);
PR_EEP("TX Diversity", pModal->tx_diversity);
if (len > size)
len = size;
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
#undef PR_EEP
}
static ssize_t read_def_modal_eeprom(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
#define PR_EEP(_s, _val) \
do { \
if (pBase->opCapFlags & AR5416_OPFLAGS_11G) { \
pModal = &priv->ah->eeprom.def.modalHeader[1]; \
len += scnprintf(buf + len, size - len, "%20s : %8d%7s", \
_s, (_val), "|"); \
} \
if (pBase->opCapFlags & AR5416_OPFLAGS_11A) { \
pModal = &priv->ah->eeprom.def.modalHeader[0]; \
len += scnprintf(buf + len, size - len, "%9d\n",\
(_val)); \
} \
} while (0)
struct ath9k_htc_priv *priv = file->private_data;
struct base_eep_header *pBase = &priv->ah->eeprom.def.baseEepHeader;
struct modal_eep_header *pModal = NULL;
unsigned int len = 0, size = 3500;
ssize_t retval = 0;
char *buf;
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
len += scnprintf(buf + len, size - len,
"%31s %15s\n", "2G", "5G");
len += scnprintf(buf + len, size - len,
"%32s %16s\n", "====", "====\n");
PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]);
PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]);
PR_EEP("Chain2 Ant. Control", pModal->antCtrlChain[2]);
PR_EEP("Ant. Common Control", pModal->antCtrlCommon);
PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]);
PR_EEP("Chain1 Ant. Gain", pModal->antennaGainCh[1]);
PR_EEP("Chain2 Ant. Gain", pModal->antennaGainCh[2]);
PR_EEP("Switch Settle", pModal->switchSettling);
PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]);
PR_EEP("Chain1 TxRxAtten", pModal->txRxAttenCh[1]);
PR_EEP("Chain2 TxRxAtten", pModal->txRxAttenCh[2]);
PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]);
PR_EEP("Chain1 RxTxMargin", pModal->rxTxMarginCh[1]);
PR_EEP("Chain2 RxTxMargin", pModal->rxTxMarginCh[2]);
PR_EEP("ADC Desired size", pModal->adcDesiredSize);
PR_EEP("PGA Desired size", pModal->pgaDesiredSize);
PR_EEP("Chain0 xlna Gain", pModal->xlnaGainCh[0]);
PR_EEP("Chain1 xlna Gain", pModal->xlnaGainCh[1]);
PR_EEP("Chain2 xlna Gain", pModal->xlnaGainCh[2]);
PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff);
PR_EEP("txEndToRxOn", pModal->txEndToRxOn);
PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn);
PR_EEP("CCA Threshold)", pModal->thresh62);
PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]);
PR_EEP("Chain1 NF Threshold", pModal->noiseFloorThreshCh[1]);
PR_EEP("Chain2 NF Threshold", pModal->noiseFloorThreshCh[2]);
PR_EEP("xpdGain", pModal->xpdGain);
PR_EEP("External PD", pModal->xpd);
PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]);
PR_EEP("Chain1 I Coefficient", pModal->iqCalICh[1]);
PR_EEP("Chain2 I Coefficient", pModal->iqCalICh[2]);
PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]);
PR_EEP("Chain1 Q Coefficient", pModal->iqCalQCh[1]);
PR_EEP("Chain2 Q Coefficient", pModal->iqCalQCh[2]);
PR_EEP("pdGainOverlap", pModal->pdGainOverlap);
PR_EEP("Chain0 OutputBias", pModal->ob);
PR_EEP("Chain0 DriverBias", pModal->db);
PR_EEP("xPA Bias Level", pModal->xpaBiasLvl);
PR_EEP("2chain pwr decrease", pModal->pwrDecreaseFor2Chain);
PR_EEP("3chain pwr decrease", pModal->pwrDecreaseFor3Chain);
PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart);
PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn);
PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc);
PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]);
PR_EEP("Chain1 bswAtten", pModal->bswAtten[1]);
PR_EEP("Chain2 bswAtten", pModal->bswAtten[2]);
PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]);
PR_EEP("Chain1 bswMargin", pModal->bswMargin[1]);
PR_EEP("Chain2 bswMargin", pModal->bswMargin[2]);
PR_EEP("HT40 Switch Settle", pModal->swSettleHt40);
PR_EEP("Chain0 xatten2Db", pModal->xatten2Db[0]);
PR_EEP("Chain1 xatten2Db", pModal->xatten2Db[1]);
PR_EEP("Chain2 xatten2Db", pModal->xatten2Db[2]);
PR_EEP("Chain0 xatten2Margin", pModal->xatten2Margin[0]);
PR_EEP("Chain1 xatten2Margin", pModal->xatten2Margin[1]);
PR_EEP("Chain2 xatten2Margin", pModal->xatten2Margin[2]);
PR_EEP("Chain1 OutputBias", pModal->ob_ch1);
PR_EEP("Chain1 DriverBias", pModal->db_ch1);
PR_EEP("LNA Control", pModal->lna_ctl);
PR_EEP("XPA Bias Freq0", pModal->xpaBiasLvlFreq[0]);
PR_EEP("XPA Bias Freq1", pModal->xpaBiasLvlFreq[1]);
PR_EEP("XPA Bias Freq2", pModal->xpaBiasLvlFreq[2]);
if (len > size)
len = size;
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
#undef PR_EEP
}
static ssize_t read_9287_modal_eeprom(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
#define PR_EEP(_s, _val) \
do { \
len += scnprintf(buf + len, size - len, "%20s : %10d\n",\
_s, (_val)); \
} while (0)
struct ath9k_htc_priv *priv = file->private_data;
struct modal_eep_ar9287_header *pModal = &priv->ah->eeprom.map9287.modalHeader;
unsigned int len = 0, size = 3000;
ssize_t retval = 0;
char *buf;
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]);
PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]);
PR_EEP("Ant. Common Control", pModal->antCtrlCommon);
PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]);
PR_EEP("Chain1 Ant. Gain", pModal->antennaGainCh[1]);
PR_EEP("Switch Settle", pModal->switchSettling);
PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]);
PR_EEP("Chain1 TxRxAtten", pModal->txRxAttenCh[1]);
PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]);
PR_EEP("Chain1 RxTxMargin", pModal->rxTxMarginCh[1]);
PR_EEP("ADC Desired size", pModal->adcDesiredSize);
PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff);
PR_EEP("txEndToRxOn", pModal->txEndToRxOn);
PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn);
PR_EEP("CCA Threshold)", pModal->thresh62);
PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]);
PR_EEP("Chain1 NF Threshold", pModal->noiseFloorThreshCh[1]);
PR_EEP("xpdGain", pModal->xpdGain);
PR_EEP("External PD", pModal->xpd);
PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]);
PR_EEP("Chain1 I Coefficient", pModal->iqCalICh[1]);
PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]);
PR_EEP("Chain1 Q Coefficient", pModal->iqCalQCh[1]);
PR_EEP("pdGainOverlap", pModal->pdGainOverlap);
PR_EEP("xPA Bias Level", pModal->xpaBiasLvl);
PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart);
PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn);
PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc);
PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]);
PR_EEP("Chain1 bswAtten", pModal->bswAtten[1]);
PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]);
PR_EEP("Chain1 bswMargin", pModal->bswMargin[1]);
PR_EEP("HT40 Switch Settle", pModal->swSettleHt40);
PR_EEP("AR92x7 Version", pModal->version);
PR_EEP("DriverBias1", pModal->db1);
PR_EEP("DriverBias2", pModal->db1);
PR_EEP("CCK OutputBias", pModal->ob_cck);
PR_EEP("PSK OutputBias", pModal->ob_psk);
PR_EEP("QAM OutputBias", pModal->ob_qam);
PR_EEP("PAL_OFF OutputBias", pModal->ob_pal_off);
if (len > size)
len = size;
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
#undef PR_EEP
}
static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath9k_htc_priv *priv = file->private_data;
if (AR_SREV_9271(priv->ah))
return read_4k_modal_eeprom(file, user_buf, count, ppos);
else if (priv->ah->hw_version.usbdev == AR9280_USB)
return read_def_modal_eeprom(file, user_buf, count, ppos);
else if (priv->ah->hw_version.usbdev == AR9287_USB)
return read_9287_modal_eeprom(file, user_buf, count, ppos);
return 0;
}
static const struct file_operations fops_modal_eeprom = {
.read = read_file_modal_eeprom,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
/* Ethtool support for get-stats */
#define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO"
static const char ath9k_htc_gstrings_stats[][ETH_GSTRING_LEN] = {
@@ -947,6 +453,8 @@ int ath9k_htc_get_et_sset_count(struct ieee80211_hw *hw,
#define STXBASE priv->debug.tx_stats
#define SRXBASE priv->debug.rx_stats
#define SKBTXBASE priv->debug.tx_stats
#define SKBRXBASE priv->debug.skbrx_stats
#define ASTXQ(a) \
data[i++] = STXBASE.a[IEEE80211_AC_BE]; \
data[i++] = STXBASE.a[IEEE80211_AC_BK]; \
@@ -960,24 +468,24 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw,
struct ath9k_htc_priv *priv = hw->priv;
int i = 0;
data[i++] = STXBASE.skb_success;
data[i++] = STXBASE.skb_success_bytes;
data[i++] = SRXBASE.skb_completed;
data[i++] = SRXBASE.skb_completed_bytes;
data[i++] = SKBTXBASE.skb_success;
data[i++] = SKBTXBASE.skb_success_bytes;
data[i++] = SKBRXBASE.skb_completed;
data[i++] = SKBRXBASE.skb_completed_bytes;
ASTXQ(queue_stats);
data[i++] = SRXBASE.err_crc;
data[i++] = SRXBASE.err_decrypt_crc;
data[i++] = SRXBASE.err_phy;
data[i++] = SRXBASE.err_mic;
data[i++] = SRXBASE.err_pre_delim;
data[i++] = SRXBASE.err_post_delim;
data[i++] = SRXBASE.err_decrypt_busy;
data[i++] = SRXBASE.crc_err;
data[i++] = SRXBASE.decrypt_crc_err;
data[i++] = SRXBASE.phy_err;
data[i++] = SRXBASE.mic_err;
data[i++] = SRXBASE.pre_delim_crc_err;
data[i++] = SRXBASE.post_delim_crc_err;
data[i++] = SRXBASE.decrypt_busy_err;
data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_RADAR];
data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_OFDM_TIMING];
data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_CCK_TIMING];
data[i++] = SRXBASE.phy_err_stats[ATH9K_PHYERR_RADAR];
data[i++] = SRXBASE.phy_err_stats[ATH9K_PHYERR_OFDM_TIMING];
data[i++] = SRXBASE.phy_err_stats[ATH9K_PHYERR_CCK_TIMING];
WARN_ON(i != ATH9K_HTC_SSTATS_LEN);
}
@@ -1001,18 +509,21 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
priv, &fops_tgt_rx_stats);
debugfs_create_file("xmit", S_IRUSR, priv->debug.debugfs_phy,
priv, &fops_xmit);
debugfs_create_file("recv", S_IRUSR, priv->debug.debugfs_phy,
priv, &fops_recv);
debugfs_create_file("skb_rx", S_IRUSR, priv->debug.debugfs_phy,
priv, &fops_skb_rx);
ath9k_cmn_debug_recv(priv->debug.debugfs_phy, &priv->debug.rx_stats);
ath9k_cmn_debug_phy_err(priv->debug.debugfs_phy, &priv->debug.rx_stats);
debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy,
priv, &fops_slot);
debugfs_create_file("queue", S_IRUSR, priv->debug.debugfs_phy,
priv, &fops_queue);
debugfs_create_file("debug", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy,
priv, &fops_debug);
debugfs_create_file("base_eeprom", S_IRUSR, priv->debug.debugfs_phy,
priv, &fops_base_eeprom);
debugfs_create_file("modal_eeprom", S_IRUSR, priv->debug.debugfs_phy,
priv, &fops_modal_eeprom);
ath9k_cmn_debug_base_eeprom(priv->debug.debugfs_phy, priv->ah);
ath9k_cmn_debug_modal_eeprom(priv->debug.debugfs_phy, priv->ah);
return 0;
}
@@ -996,8 +996,6 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
goto rx_next;
}
ath9k_htc_err_stat_rx(priv, rxstatus);
/* Get the RX status information */
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
@@ -1005,6 +1003,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
/* Copy everything from ath_htc_rx_status (HTC_RX_FRAME_HEADER).
* After this, we can drop this part of skb. */
rx_status_htc_to_ath(&rx_stats, rxstatus);
ath9k_htc_err_stat_rx(priv, &rx_stats);
rx_status->mactime = be64_to_cpu(rxstatus->rs_tstamp);
skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
+2 -1
View File
@@ -26,7 +26,6 @@
#include "ar9003_mac.h"
#include "ar9003_mci.h"
#include "ar9003_phy.h"
#include "debug.h"
#include "ath9k.h"
static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
@@ -246,6 +245,8 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
return;
case AR9300_DEVID_AR953X:
ah->hw_version.macVersion = AR_SREV_VERSION_9531;
if (ah->get_mac_revision)
ah->hw_version.macRev = ah->get_mac_revision();
return;
}
+6 -2
View File
@@ -508,7 +508,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
sc->tx99_power = MAX_RATE_POWER + 1;
init_waitqueue_head(&sc->tx_wait);
if (!pdata) {
if (!pdata || pdata->use_eeprom) {
ah->ah_flags |= AH_USE_EEPROM;
sc->sc_ah->led_pin = -1;
} else {
@@ -714,7 +714,8 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt)
hw->flags |= IEEE80211_HW_MFP_CAPABLE;
hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
hw->wiphy->features |= (NL80211_FEATURE_ACTIVE_MONITOR |
NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE);
if (!config_enabled(CONFIG_ATH9K_TX99)) {
hw->wiphy->interface_modes =
@@ -786,6 +787,9 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
common = ath9k_hw_common(ah);
ath9k_set_hw_capab(sc, hw);
/* Will be cleared in ath9k_start() */
set_bit(ATH_OP_INVALID, &common->op_flags);
/* Initialize regulatory */
error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
ath9k_reg_notifier);
+2 -1
View File
@@ -1989,7 +1989,8 @@ static bool ath9k_has_tx_pending(struct ath_softc *sc)
return !!npend;
}
static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
+1 -6
View File
@@ -686,7 +686,7 @@ static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
struct ath_softc *sc = (struct ath_softc *) common->priv;
struct ath9k_platform_data *pdata = sc->dev->platform_data;
if (pdata) {
if (pdata && !pdata->use_eeprom) {
if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
ath_err(common,
"%s: eeprom read failed, offset %08x is out of range\n",
@@ -784,7 +784,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct ath_softc *sc;
struct ieee80211_hw *hw;
struct ath_common *common;
u8 csz;
u32 val;
int ret = 0;
@@ -877,10 +876,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
hw_name, (unsigned long)sc->mem, pdev->irq);
/* Will be cleared in ath9k_start() */
common = ath9k_hw_common(sc->sc_ah);
set_bit(ATH_OP_INVALID, &common->op_flags);
return 0;
err_init:
+8 -5
View File
@@ -538,8 +538,8 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
sc->ps_flags &= ~PS_BEACON_SYNC;
ath_dbg(common, PS,
"Reconfigure beacon timers based on synchronized timestamp\n");
ath9k_set_beacon(sc);
if (!(WARN_ON_ONCE(sc->cur_beacon_conf.beacon_interval == 0)))
ath9k_set_beacon(sc);
if (sc->p2p_ps_vif)
ath9k_update_p2p_ps(sc, sc->p2p_ps_vif->vif);
}
@@ -978,6 +978,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
u64 tsf = 0;
unsigned long flags;
dma_addr_t new_buf_addr;
unsigned int budget = 512;
if (edma)
dma_type = DMA_BIDIRECTIONAL;
@@ -1116,15 +1117,17 @@ requeue_drop_frag:
}
requeue:
list_add_tail(&bf->list, &sc->rx.rxbuf);
if (flush)
continue;
if (edma) {
ath_rx_edma_buf_link(sc, qtype);
} else {
ath_rx_buf_relink(sc, bf);
ath9k_hw_rxena(ah);
if (!flush)
ath9k_hw_rxena(ah);
}
if (!budget--)
break;
} while (1);
if (!(ah->imask & ATH9K_INT_RXEOL)) {
+1 -13
View File
@@ -107,9 +107,6 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
{
struct ath_atx_ac *ac = tid->ac;
if (tid->paused)
return;
if (tid->sched)
return;
@@ -1407,7 +1404,6 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
ath_tx_tid_change_state(sc, txtid);
txtid->active = true;
txtid->paused = true;
*ssn = txtid->seq_start = txtid->seq_next;
txtid->bar_index = -1;
@@ -1427,7 +1423,6 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
ath_txq_lock(sc, txq);
txtid->active = false;
txtid->paused = false;
ath_tx_flush_tid(sc, txtid);
ath_tx_tid_change_state(sc, txtid);
ath_txq_unlock_complete(sc, txq);
@@ -1487,7 +1482,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
ath_txq_lock(sc, txq);
ac->clear_ps_filter = true;
if (!tid->paused && ath_tid_has_buffered(tid)) {
if (ath_tid_has_buffered(tid)) {
ath_tx_queue_tid(txq, tid);
ath_txq_schedule(sc, txq);
}
@@ -1510,7 +1505,6 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta,
ath_txq_lock(sc, txq);
tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
tid->paused = false;
if (ath_tid_has_buffered(tid)) {
ath_tx_queue_tid(txq, tid);
@@ -1544,8 +1538,6 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
continue;
tid = ATH_AN_2_TID(an, i);
if (tid->paused)
continue;
ath_txq_lock(sc, tid->ac->txq);
while (nframes > 0) {
@@ -1844,9 +1836,6 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
list_del(&tid->list);
tid->sched = false;
if (tid->paused)
continue;
if (ath_tx_sched_aggr(sc, txq, tid, &stop))
sent = true;
@@ -2698,7 +2687,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
tid->baw_size = WME_MAX_BA;
tid->baw_head = tid->baw_tail = 0;
tid->sched = false;
tid->paused = false;
tid->active = false;
__skb_queue_head_init(&tid->buf_q);
__skb_queue_head_init(&tid->retry_q);
+3 -1
View File
@@ -1707,7 +1707,9 @@ found:
return 0;
}
static void carl9170_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
static void carl9170_op_flush(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u32 queues, bool drop)
{
struct ar9170 *ar = hw->priv;
unsigned int vid;
+29 -9
View File
@@ -1,7 +1,8 @@
config B43
tristate "Broadcom 43xx wireless support (mac80211 stack)"
depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
select SSB
depends on (BCMA_POSSIBLE || SSB_POSSIBLE) && MAC80211 && HAS_DMA
select BCMA if B43_BCMA
select SSB if B43_SSB
select FW_LOADER
---help---
b43 is a driver for the Broadcom 43xx series wireless devices.
@@ -27,14 +28,33 @@ config B43
If unsure, say M.
config B43_BCMA
bool "Support for BCMA bus"
depends on B43 && (BCMA = y || BCMA = B43)
default y
bool
config B43_SSB
bool
depends on B43 && (SSB = y || SSB = B43)
default y
choice
prompt "Supported bus types"
depends on B43
default B43_BCMA_AND_SSB
config B43_BUSES_BCMA_AND_SSB
bool "BCMA and SSB"
depends on BCMA_POSSIBLE && SSB_POSSIBLE
select B43_BCMA
select B43_SSB
config B43_BUSES_BCMA
bool "BCMA only"
depends on BCMA_POSSIBLE
select B43_BCMA
config B43_BUSES_SSB
bool "SSB only"
depends on SSB_POSSIBLE
select B43_SSB
endchoice
# Auto-select SSB PCI-HOST support, if possible
config B43_PCI_AUTOSELECT
@@ -98,7 +118,7 @@ config B43_BCMA_PIO
config B43_PIO
bool
depends on B43
depends on B43 && B43_SSB
select SSB_BLOCKIO
default y
@@ -116,7 +136,7 @@ config B43_PHY_N
config B43_PHY_LP
bool "Support for low-power (LP-PHY) devices"
depends on B43
depends on B43 && B43_SSB
default y
---help---
Support for the LP-PHY.
+10
View File
@@ -5,7 +5,9 @@ enum b43_bus_type {
#ifdef CONFIG_B43_BCMA
B43_BUS_BCMA,
#endif
#ifdef CONFIG_B43_SSB
B43_BUS_SSB,
#endif
};
struct b43_bus_dev {
@@ -52,13 +54,21 @@ struct b43_bus_dev {
static inline bool b43_bus_host_is_pcmcia(struct b43_bus_dev *dev)
{
#ifdef CONFIG_B43_SSB
return (dev->bus_type == B43_BUS_SSB &&
dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA);
#else
return false;
#endif
}
static inline bool b43_bus_host_is_sdio(struct b43_bus_dev *dev)
{
#ifdef CONFIG_B43_SSB
return (dev->bus_type == B43_BUS_SSB &&
dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
#else
return false;
#endif
}
struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core);
+24 -3
View File
@@ -1195,14 +1195,20 @@ static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode)
B43_BCMA_CLKCTLST_PHY_PLL_REQ;
u32 status = B43_BCMA_CLKCTLST_80211_PLL_ST |
B43_BCMA_CLKCTLST_PHY_PLL_ST;
u32 flags;
flags = B43_BCMA_IOCTL_PHY_CLKEN;
if (gmode)
flags |= B43_BCMA_IOCTL_GMODE;
b43_device_enable(dev, flags);
b43_device_enable(dev, B43_BCMA_IOCTL_PHY_CLKEN);
bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST);
b43_bcma_phy_reset(dev);
bcma_core_pll_ctl(dev->dev->bdev, req, status, true);
}
#endif
#ifdef CONFIG_B43_SSB
static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{
struct ssb_device *sdev = dev->dev->sdev;
@@ -1230,6 +1236,7 @@ static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode)
ssb_read32(sdev, SSB_TMSLOW); /* flush */
msleep(1);
}
#endif
void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{
@@ -2730,6 +2737,8 @@ out:
/* Initialize the GPIOs
* http://bcm-specs.sipsolutions.net/GPIO
*/
#ifdef CONFIG_B43_SSB
static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev)
{
struct ssb_bus *bus = dev->dev->sdev->bus;
@@ -2740,10 +2749,13 @@ static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev)
return bus->chipco.dev;
#endif
}
#endif
static int b43_gpio_init(struct b43_wldev *dev)
{
#ifdef CONFIG_B43_SSB
struct ssb_device *gpiodev;
#endif
u32 mask, set;
b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
@@ -2802,7 +2814,9 @@ static int b43_gpio_init(struct b43_wldev *dev)
/* Turn off all GPIO stuff. Call this on module unload, for example. */
static void b43_gpio_cleanup(struct b43_wldev *dev)
{
#ifdef CONFIG_B43_SSB
struct ssb_device *gpiodev;
#endif
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
@@ -3687,7 +3701,9 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw,
static void b43_put_phy_into_reset(struct b43_wldev *dev)
{
#ifdef CONFIG_B43_SSB
u32 tmp;
#endif
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
@@ -4577,8 +4593,12 @@ static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
struct ssb_bus *bus;
u32 tmp;
#ifdef CONFIG_B43_SSB
if (dev->dev->bus_type != B43_BUS_SSB)
return;
#else
return;
#endif
bus = dev->dev->sdev->bus;
@@ -4733,7 +4753,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
}
if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
#ifdef CONFIG_SSB_DRIVER_PCICORE
#if defined(CONFIG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE)
if (dev->dev->bus_type == B43_BUS_SSB &&
dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
@@ -5173,7 +5193,6 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
}
dev->phy.gmode = have_2ghz_phy;
dev->phy.radio_on = true;
b43_wireless_core_reset(dev, dev->phy.gmode);
err = b43_phy_versioning(dev);
@@ -5306,6 +5325,7 @@ static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl)
(pdev->subsystem_vendor == PCI_VENDOR_ID_##_subvendor) && \
(pdev->subsystem_device == _subdevice) )
#ifdef CONFIG_B43_SSB
static void b43_sprom_fixup(struct ssb_bus *bus)
{
struct pci_dev *pdev;
@@ -5337,6 +5357,7 @@ static void b43_wireless_exit(struct b43_bus_dev *dev, struct b43_wl *wl)
ssb_set_devtypedata(dev->sdev, NULL);
ieee80211_free_hw(hw);
}
#endif
static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
{
+3 -3
View File
@@ -96,7 +96,7 @@ int b43_phy_init(struct b43_wldev *dev)
phy->channel = ops->get_default_chan(dev);
ops->software_rfkill(dev, false);
b43_software_rfkill(dev, false);
err = ops->init(dev);
if (err) {
b43err(dev->wl, "PHY init failed\n");
@@ -116,7 +116,7 @@ err_phy_exit:
if (ops->exit)
ops->exit(dev);
err_block_rf:
ops->software_rfkill(dev, true);
b43_software_rfkill(dev, true);
return err;
}
@@ -125,7 +125,7 @@ void b43_phy_exit(struct b43_wldev *dev)
{
const struct b43_phy_operations *ops = dev->phy.ops;
ops->software_rfkill(dev, true);
b43_software_rfkill(dev, true);
if (ops->exit)
ops->exit(dev);
}
+27 -5
View File
@@ -807,9 +807,16 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
u16 bias, cbias;
u16 pag_boost, padg_boost, pgag_boost, mixg_boost;
u16 paa_boost, pada_boost, pgaa_boost, mixa_boost;
bool is_pkg_fab_smic;
B43_WARN_ON(dev->phy.rev < 3);
is_pkg_fab_smic =
((dev->dev->chip_id == BCMA_CHIP_ID_BCM43224 ||
dev->dev->chip_id == BCMA_CHIP_ID_BCM43225 ||
dev->dev->chip_id == BCMA_CHIP_ID_BCM43421) &&
dev->dev->chip_pkg == BCMA_PKG_ID_BCM43224_FAB_SMIC);
b43_chantab_radio_2056_upload(dev, e);
b2056_upload_syn_pll_cp2(dev, band == IEEE80211_BAND_5GHZ);
@@ -817,7 +824,8 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
if (dev->dev->chip_id == 0x4716) {
if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 ||
dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) {
b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x14);
b43_radio_write(dev, B2056_SYN_PLL_CP2, 0);
} else {
@@ -825,6 +833,13 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x14);
}
}
if (sprom->boardflags2_hi & B43_BFH2_GPLL_WAR2 &&
b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1f);
b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1f);
b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0b);
b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x20);
}
if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
@@ -840,7 +855,8 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
b43_radio_write(dev,
offset | B2056_TX_PADG_IDAC, 0xcc);
if (dev->dev->chip_id == 0x4716) {
if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 ||
dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) {
bias = 0x40;
cbias = 0x45;
pag_boost = 0x5;
@@ -849,6 +865,10 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
} else {
bias = 0x25;
cbias = 0x20;
if (is_pkg_fab_smic) {
bias = 0x2a;
cbias = 0x38;
}
pag_boost = 0x4;
pgag_boost = 0x03;
mixg_boost = 0x65;
@@ -917,6 +937,8 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
mixa_boost = 0xF;
}
cbias = is_pkg_fab_smic ? 0x35 : 0x30;
for (i = 0; i < 2; i++) {
offset = i ? B2056_TX1 : B2056_TX0;
@@ -935,11 +957,11 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
b43_radio_write(dev,
offset | B2056_TX_PADA_CASCBIAS, 0x03);
b43_radio_write(dev,
offset | B2056_TX_INTPAA_IAUX_STAT, 0x50);
offset | B2056_TX_INTPAA_IAUX_STAT, 0x30);
b43_radio_write(dev,
offset | B2056_TX_INTPAA_IMAIN_STAT, 0x50);
offset | B2056_TX_INTPAA_IMAIN_STAT, 0x30);
b43_radio_write(dev,
offset | B2056_TX_INTPAA_CASCBIAS, 0x30);
offset | B2056_TX_INTPAA_CASCBIAS, cbias);
}
}
@@ -303,10 +303,10 @@ static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core,
ci = core->chip;
/* if core is already in reset, just return */
/* if core is already in reset, skip reset */
regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL);
if ((regdata & BCMA_RESET_CTL_RESET) != 0)
return;
goto in_reset_configure;
/* configure reset */
ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
@@ -322,6 +322,7 @@ static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core,
SPINWAIT(ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) !=
BCMA_RESET_CTL_RESET, 300);
in_reset_configure:
/* in-reset configure */
ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
@@ -186,7 +186,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
void brcmf_txflowblock_if(struct brcmf_if *ifp,
enum brcmf_netif_stop_reason reason, bool state);
u32 brcmf_get_chip_info(struct brcmf_if *ifp);
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
bool success);
/* Sets dongle media info (drv_version, mac address). */
@@ -99,6 +99,7 @@ struct brcmf_bus {
unsigned long tx_realloc;
u32 chip;
u32 chiprev;
bool always_use_fws_queue;
struct brcmf_bus_ops *ops;
};
@@ -32,6 +32,9 @@
#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
#define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00"
/* boost value for RSSI_DELTA in preferred join selection */
#define BRCMF_JOIN_PREF_RSSI_BOOST 8
bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
struct sk_buff *pkt, int prec)
@@ -246,6 +249,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
{
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
u8 buf[BRCMF_DCMD_SMLEN];
struct brcmf_join_pref_params join_pref_params[2];
char *ptr;
s32 err;
@@ -298,6 +302,20 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
goto done;
}
/* Setup join_pref to select target by RSSI(with boost on 5GHz) */
join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
join_pref_params[0].len = 2;
join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST;
join_pref_params[0].band = WLC_BAND_5G;
join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI;
join_pref_params[1].len = 2;
join_pref_params[1].rssi_gain = 0;
join_pref_params[1].band = 0;
err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
sizeof(join_pref_params));
if (err)
brcmf_err("Set join_pref error (%d)\n", err);
/* Setup event_msgs, enable E_IF */
err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
BRCMF_EVENTING_MASK_LEN);
@@ -190,7 +190,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
int ret;
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_pub *drvr = ifp->drvr;
struct ethhdr *eh;
struct ethhdr *eh = (struct ethhdr *)(skb->data);
brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx);
@@ -236,6 +236,9 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
goto done;
}
if (eh->h_proto == htons(ETH_P_PAE))
atomic_inc(&ifp->pend_8021x_cnt);
ret = brcmf_fws_process_skb(ifp, skb);
done:
@@ -538,31 +541,26 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb)
brcmf_netif_rx(ifp, skb);
}
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
bool success)
{
struct brcmf_if *ifp;
struct ethhdr *eh;
u8 ifidx;
u16 type;
int res;
res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp);
ifp = drvr->iflist[ifidx];
if (!ifp)
goto done;
if (res == 0) {
eh = (struct ethhdr *)(txp->data);
type = ntohs(eh->h_proto);
eh = (struct ethhdr *)(txp->data);
type = ntohs(eh->h_proto);
if (type == ETH_P_PAE) {
atomic_dec(&ifp->pend_8021x_cnt);
if (waitqueue_active(&ifp->pend_8021x_wait))
wake_up(&ifp->pend_8021x_wait);
}
if (type == ETH_P_PAE) {
atomic_dec(&ifp->pend_8021x_cnt);
if (waitqueue_active(&ifp->pend_8021x_wait))
wake_up(&ifp->pend_8021x_wait);
}
if (!success)
ifp->stats.tx_errors++;
done:
@@ -573,13 +571,17 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;
u8 ifidx;
/* await txstatus signal for firmware if active */
if (brcmf_fws_fc_active(drvr->fws)) {
if (!success)
brcmf_fws_bustxfail(drvr->fws, txp);
} else {
brcmf_txfinalize(drvr, txp, success);
if (brcmf_proto_hdrpull(drvr, false, &ifidx, txp))
brcmu_pkt_buf_free_skb(txp);
else
brcmf_txfinalize(drvr, txp, ifidx, success);
}
}
@@ -53,6 +53,14 @@
#define BRCMF_OBSS_COEX_OFF 0
#define BRCMF_OBSS_COEX_ON 1
/* join preference types for join_pref iovar */
enum brcmf_join_pref_types {
BRCMF_JOIN_PREF_RSSI = 1,
BRCMF_JOIN_PREF_WPA,
BRCMF_JOIN_PREF_BAND,
BRCMF_JOIN_PREF_RSSI_DELTA,
};
enum brcmf_fil_p2p_if_types {
BRCMF_FIL_P2P_IF_CLIENT,
BRCMF_FIL_P2P_IF_GO,
@@ -282,6 +290,22 @@ struct brcmf_assoc_params_le {
__le16 chanspec_list[1];
};
/**
* struct join_pref params - parameters for preferred join selection.
*
* @type: preference type (see enum brcmf_join_pref_types).
* @len: length of bytes following (currently always 2).
* @rssi_gain: signal gain for selection (only when @type is RSSI_DELTA).
* @band: band to which selection preference applies.
* This is used if @type is BAND or RSSI_DELTA.
*/
struct brcmf_join_pref_params {
u8 type;
u8 len;
u8 rssi_gain;
u8 band;
};
/* used for join with or without a specific bssid and channel list */
struct brcmf_join_params {
struct brcmf_ssid_le ssid_le;
@@ -476,6 +476,7 @@ struct brcmf_fws_info {
bool bus_flow_blocked;
bool creditmap_received;
u8 mode;
bool avoid_queueing;
};
/*
@@ -1369,13 +1370,12 @@ done:
}
static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
struct sk_buff *skb, u32 genbit,
u16 seq)
struct sk_buff *skb, u8 ifidx,
u32 genbit, u16 seq)
{
struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
u32 hslot;
int ret;
u8 ifidx;
hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
@@ -1389,29 +1389,21 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
entry->generation = genbit;
ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
if (ret == 0) {
brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit);
brcmf_skbcb(skb)->htod_seq = seq;
if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) {
brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1);
brcmf_skb_htod_seq_set_field(skb, FROMFW, 0);
} else {
brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0);
}
ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo,
skb);
brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit);
brcmf_skbcb(skb)->htod_seq = seq;
if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) {
brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1);
brcmf_skb_htod_seq_set_field(skb, FROMFW, 0);
} else {
brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0);
}
ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, skb);
if (ret != 0) {
/* suppress q is full or hdrpull failed, drop this packet */
brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
true);
/* suppress q is full drop this packet */
brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, true);
} else {
/*
* Mark suppressed to avoid a double free during
* wlfc cleanup
*/
/* Mark suppressed to avoid a double free during wlfc cleanup */
brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot);
}
@@ -1428,6 +1420,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
struct sk_buff *skb;
struct brcmf_skbuff_cb *skcb;
struct brcmf_fws_mac_descriptor *entry = NULL;
u8 ifidx;
brcmf_dbg(DATA, "flags %d\n", flags);
@@ -1476,12 +1469,15 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
}
brcmf_fws_macdesc_return_req_credit(skb);
if (brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb)) {
brcmu_pkt_buf_free_skb(skb);
return -EINVAL;
}
if (!remove_from_hanger)
ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit,
seq);
ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifidx,
genbit, seq);
if (remove_from_hanger || ret)
brcmf_txfinalize(fws->drvr, skb, true);
brcmf_txfinalize(fws->drvr, skb, ifidx, true);
return 0;
}
@@ -1868,7 +1864,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
struct ethhdr *eh = (struct ethhdr *)(skb->data);
int fifo = BRCMF_FWS_FIFO_BCMC;
bool multicast = is_multicast_ether_addr(eh->h_dest);
bool pae = eh->h_proto == htons(ETH_P_PAE);
int rc = 0;
brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto));
/* determine the priority */
@@ -1876,8 +1872,13 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
skb->priority = cfg80211_classify8021d(skb, NULL);
drvr->tx_multicast += !!multicast;
if (pae)
atomic_inc(&ifp->pend_8021x_cnt);
if (fws->avoid_queueing) {
rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb);
if (rc < 0)
brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
return rc;
}
/* set control buffer information */
skcb->if_flags = 0;
@@ -1899,15 +1900,12 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
brcmf_fws_schedule_deq(fws);
} else {
brcmf_err("drop skb: no hanger slot\n");
if (pae) {
atomic_dec(&ifp->pend_8021x_cnt);
if (waitqueue_active(&ifp->pend_8021x_wait))
wake_up(&ifp->pend_8021x_wait);
}
brcmu_pkt_buf_free_skb(skb);
brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
rc = -ENOMEM;
}
brcmf_fws_unlock(fws);
return 0;
return rc;
}
void brcmf_fws_reset_interface(struct brcmf_if *ifp)
@@ -1982,7 +1980,8 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
ret = brcmf_proto_txdata(drvr, ifidx, 0, skb);
brcmf_fws_lock(fws);
if (ret < 0)
brcmf_txfinalize(drvr, skb, false);
brcmf_txfinalize(drvr, skb, ifidx,
false);
if (fws->bus_flow_blocked)
break;
}
@@ -2039,6 +2038,13 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
fws->drvr = drvr;
fws->fcmode = fcmode;
if ((drvr->bus_if->always_use_fws_queue == false) &&
(fcmode == BRCMF_FWS_FCMODE_NONE)) {
fws->avoid_queueing = true;
brcmf_dbg(INFO, "FWS queueing will be avoided\n");
return 0;
}
fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq");
if (fws->fws_wq == NULL) {
brcmf_err("workqueue creation failed\n");
+176 -44
View File
@@ -18,72 +18,205 @@
#include <linux/slab.h>
#include <linux/firmware.h>
#include "dhd_dbg.h"
#include "nvram.h"
/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a file
enum nvram_parser_state {
IDLE,
KEY,
VALUE,
COMMENT,
END
};
/**
* struct nvram_parser - internal info for parser.
*
* @state: current parser state.
* @fwnv: input buffer being parsed.
* @nvram: output buffer with parse result.
* @nvram_len: lenght of parse result.
* @line: current line.
* @column: current column in line.
* @pos: byte offset in input buffer.
* @entry: start position of key,value entry.
*/
struct nvram_parser {
enum nvram_parser_state state;
const struct firmware *fwnv;
u8 *nvram;
u32 nvram_len;
u32 line;
u32 column;
u32 pos;
u32 entry;
};
static bool is_nvram_char(char c)
{
/* comment marker excluded */
if (c == '#')
return false;
/* key and value may have any other readable character */
return (c > 0x20 && c < 0x7f);
}
static bool is_whitespace(char c)
{
return (c == ' ' || c == '\r' || c == '\n' || c == '\t');
}
static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp)
{
char c;
c = nvp->fwnv->data[nvp->pos];
if (c == '\n')
return COMMENT;
if (is_whitespace(c))
goto proceed;
if (c == '#')
return COMMENT;
if (is_nvram_char(c)) {
nvp->entry = nvp->pos;
return KEY;
}
brcmf_dbg(INFO, "warning: ln=%d:col=%d: ignoring invalid character\n",
nvp->line, nvp->column);
proceed:
nvp->column++;
nvp->pos++;
return IDLE;
}
static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
{
enum nvram_parser_state st = nvp->state;
char c;
c = nvp->fwnv->data[nvp->pos];
if (c == '=') {
st = VALUE;
} else if (!is_nvram_char(c)) {
brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
nvp->line, nvp->column);
return COMMENT;
}
nvp->column++;
nvp->pos++;
return st;
}
static enum nvram_parser_state
brcmf_nvram_handle_value(struct nvram_parser *nvp)
{
char c;
char *skv;
char *ekv;
u32 cplen;
c = nvp->fwnv->data[nvp->pos];
if (!is_nvram_char(c)) {
/* key,value pair complete */
ekv = (u8 *)&nvp->fwnv->data[nvp->pos];
skv = (u8 *)&nvp->fwnv->data[nvp->entry];
cplen = ekv - skv;
/* copy to output buffer */
memcpy(&nvp->nvram[nvp->nvram_len], skv, cplen);
nvp->nvram_len += cplen;
nvp->nvram[nvp->nvram_len] = '\0';
nvp->nvram_len++;
return IDLE;
}
nvp->pos++;
nvp->column++;
return VALUE;
}
static enum nvram_parser_state
brcmf_nvram_handle_comment(struct nvram_parser *nvp)
{
char *eol, *sol;
sol = (char *)&nvp->fwnv->data[nvp->pos];
eol = strchr(sol, '\n');
if (eol == NULL)
return END;
/* eat all moving to next line */
nvp->line++;
nvp->column = 1;
nvp->pos += (eol - sol) + 1;
return IDLE;
}
static enum nvram_parser_state brcmf_nvram_handle_end(struct nvram_parser *nvp)
{
/* final state */
return END;
}
static enum nvram_parser_state
(*nv_parser_states[])(struct nvram_parser *nvp) = {
brcmf_nvram_handle_idle,
brcmf_nvram_handle_key,
brcmf_nvram_handle_value,
brcmf_nvram_handle_comment,
brcmf_nvram_handle_end
};
static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
const struct firmware *nv)
{
memset(nvp, 0, sizeof(*nvp));
nvp->fwnv = nv;
/* Alloc for extra 0 byte + roundup by 4 + length field */
nvp->nvram = kzalloc(nv->size + 1 + 3 + sizeof(u32), GFP_KERNEL);
if (!nvp->nvram)
return -ENOMEM;
nvp->line = 1;
nvp->column = 1;
return 0;
}
/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
* and ending in a NUL. Removes carriage returns, empty lines, comment lines,
* and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
* End of buffer is completed with token identifying length of buffer.
*/
void *brcmf_nvram_strip(const struct firmware *nv, u32 *new_length)
{
u8 *nvram;
u32 i;
u32 len;
u32 column;
u8 val;
bool comment;
struct nvram_parser nvp;
u32 pad;
u32 token;
__le32 token_le;
/* Alloc for extra 0 byte + roundup by 4 + length field */
nvram = kmalloc(nv->size + 1 + 3 + sizeof(token_le), GFP_KERNEL);
if (!nvram)
if (brcmf_init_nvram_parser(&nvp, nv) < 0)
return NULL;
len = 0;
column = 0;
comment = false;
for (i = 0; i < nv->size; i++) {
val = nv->data[i];
if (val == 0)
while (nvp.pos < nv->size) {
nvp.state = nv_parser_states[nvp.state](&nvp);
if (nvp.state == END)
break;
if (val == '\r')
continue;
if (comment && (val != '\n'))
continue;
comment = false;
if (val == '#') {
comment = true;
continue;
}
if (val == '\n') {
if (column == 0)
continue;
nvram[len] = 0;
len++;
column = 0;
continue;
}
nvram[len] = val;
len++;
column++;
}
column = len;
*new_length = roundup(len + 1, 4);
while (column != *new_length) {
nvram[column] = 0;
column++;
pad = nvp.nvram_len;
*new_length = roundup(nvp.nvram_len + 1, 4);
while (pad != *new_length) {
nvp.nvram[pad] = 0;
pad++;
}
token = *new_length / 4;
token = (~token << 16) | (token & 0x0000FFFF);
token_le = cpu_to_le32(token);
memcpy(&nvram[*new_length], &token_le, sizeof(token_le));
memcpy(&nvp.nvram[*new_length], &token_le, sizeof(token_le));
*new_length += sizeof(token_le);
return nvram;
return nvp.nvram;
}
void brcmf_nvram_free(void *nvram)
@@ -91,4 +224,3 @@ void brcmf_nvram_free(void *nvram)
kfree(nvram);
}
@@ -1254,6 +1254,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
bus->chip = bus_pub->devid;
bus->chiprev = bus_pub->chiprev;
bus->proto_type = BRCMF_PROTO_BCDC;
bus->always_use_fws_queue = true;
/* Attach to the common driver interface */
ret = brcmf_attach(dev);
@@ -221,9 +221,9 @@ static const struct ieee80211_regdomain brcmf_regdom = {
*/
REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
/* IEEE 802.11a, channel 36..64 */
REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
REG_RULE(5150-10, 5350+10, 80, 6, 20, 0),
/* IEEE 802.11a, channel 100..165 */
REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
REG_RULE(5470-10, 5850+10, 80, 6, 20, 0), }
};
static const u32 __wl_cipher_suites[] = {
@@ -341,6 +341,60 @@ static u8 brcmf_mw_to_qdbm(u16 mw)
return qdbm;
}
u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
struct cfg80211_chan_def *ch)
{
struct brcmu_chan ch_inf;
s32 primary_offset;
brcmf_dbg(TRACE, "chandef: control %d center %d width %d\n",
ch->chan->center_freq, ch->center_freq1, ch->width);
ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq1);
primary_offset = ch->center_freq1 - ch->chan->center_freq;
switch (ch->width) {
case NL80211_CHAN_WIDTH_20:
ch_inf.bw = BRCMU_CHAN_BW_20;
WARN_ON(primary_offset != 0);
break;
case NL80211_CHAN_WIDTH_40:
ch_inf.bw = BRCMU_CHAN_BW_40;
if (primary_offset < 0)
ch_inf.sb = BRCMU_CHAN_SB_U;
else
ch_inf.sb = BRCMU_CHAN_SB_L;
break;
case NL80211_CHAN_WIDTH_80:
ch_inf.bw = BRCMU_CHAN_BW_80;
if (primary_offset < 0) {
if (primary_offset < -CH_10MHZ_APART)
ch_inf.sb = BRCMU_CHAN_SB_UU;
else
ch_inf.sb = BRCMU_CHAN_SB_UL;
} else {
if (primary_offset > CH_10MHZ_APART)
ch_inf.sb = BRCMU_CHAN_SB_LL;
else
ch_inf.sb = BRCMU_CHAN_SB_LU;
}
break;
default:
WARN_ON_ONCE(1);
}
switch (ch->chan->band) {
case IEEE80211_BAND_2GHZ:
ch_inf.band = BRCMU_CHAN_BAND_2G;
break;
case IEEE80211_BAND_5GHZ:
ch_inf.band = BRCMU_CHAN_BAND_5G;
break;
default:
WARN_ON_ONCE(1);
}
d11inf->encchspec(&ch_inf);
return ch_inf.chspec;
}
u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
struct ieee80211_channel *ch)
{
@@ -1236,8 +1290,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
params->chandef.chan->center_freq);
if (params->channel_fixed) {
/* adding chanspec */
chanspec = channel_to_chanspec(&cfg->d11inf,
params->chandef.chan);
chanspec = chandef_to_chanspec(&cfg->d11inf,
&params->chandef);
join_params.params_le.chanspec_list[0] =
cpu_to_le16(chanspec);
join_params.params_le.chanspec_num = cpu_to_le32(1);
@@ -3733,23 +3787,6 @@ brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif,
return err;
}
static s32
brcmf_cfg80211_set_channel(struct brcmf_cfg80211_info *cfg,
struct brcmf_if *ifp,
struct ieee80211_channel *channel)
{
u16 chanspec;
s32 err;
brcmf_dbg(TRACE, "band=%d, center_freq=%d\n", channel->band,
channel->center_freq);
chanspec = channel_to_chanspec(&cfg->d11inf, channel);
err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
return err;
}
static s32
brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_ap_settings *settings)
@@ -3765,11 +3802,12 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_join_params join_params;
enum nl80211_iftype dev_role;
struct brcmf_fil_bss_enable_le bss_enable;
u16 chanspec;
brcmf_dbg(TRACE, "channel_type=%d, beacon_interval=%d, dtim_period=%d,\n",
cfg80211_get_chandef_type(&settings->chandef),
settings->beacon_interval,
settings->dtim_period);
brcmf_dbg(TRACE, "ctrlchn=%d, center=%d, bw=%d, beacon_interval=%d, dtim_period=%d,\n",
settings->chandef.chan->hw_value,
settings->chandef.center_freq1, settings->chandef.width,
settings->beacon_interval, settings->dtim_period);
brcmf_dbg(TRACE, "ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n",
settings->ssid, settings->ssid_len, settings->auth_type,
settings->inactivity_timeout);
@@ -3826,9 +3864,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
err = brcmf_cfg80211_set_channel(cfg, ifp, settings->chandef.chan);
chanspec = chandef_to_chanspec(&cfg->d11inf, &settings->chandef);
err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
if (err < 0) {
brcmf_err("Set Channel failed, %d\n", err);
brcmf_err("Set Channel failed: chspec=%d, %d\n", chanspec, err);
goto exit;
}
@@ -4364,6 +4403,8 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
WIPHY_FLAG_OFFCHAN_TX |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
WIPHY_FLAG_SUPPORTS_TDLS;
if (!brcmf_roamoff)
wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
wiphy->mgmt_stypes = brcmf_txrx_stypes;
wiphy->max_remain_on_channel_duration = 5000;
brcmf_wiphy_pno_params(wiphy);
@@ -4685,7 +4726,6 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct ieee80211_channel *chan;
s32 err = 0;
u16 reason;
if (brcmf_is_apmode(ifp->vif)) {
err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
@@ -4706,16 +4746,6 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
brcmf_dbg(CONN, "Linkdown\n");
if (!brcmf_is_ibssmode(ifp->vif)) {
brcmf_bss_connect_done(cfg, ndev, e, false);
if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED,
&ifp->vif->sme_state)) {
reason = 0;
if (((e->event_code == BRCMF_E_DEAUTH_IND) ||
(e->event_code == BRCMF_E_DISASSOC_IND)) &&
(e->reason != WLAN_REASON_UNSPECIFIED))
reason = e->reason;
cfg80211_disconnected(ndev, reason, NULL, 0,
GFP_KERNEL);
}
}
brcmf_link_down(ifp->vif);
brcmf_init_prof(ndev_to_prof(ndev));
@@ -4948,7 +4978,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_if *ifp)
if (!err) {
/* only set 2G bandwidth using bw_cap command */
band_bwcap.band = cpu_to_le32(WLC_BAND_2G);
band_bwcap.bw_cap = cpu_to_le32(WLC_BW_40MHZ_BIT);
band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ);
err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap,
sizeof(band_bwcap));
} else {
@@ -5215,6 +5245,9 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
if (!(bw_cap[band] & WLC_BW_40MHZ_BIT) &&
ch.bw == BRCMU_CHAN_BW_40)
continue;
if (!(bw_cap[band] & WLC_BW_80MHZ_BIT) &&
ch.bw == BRCMU_CHAN_BW_80)
continue;
update = false;
for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
if (band_chan_arr[j].hw_value == ch.chnum) {
@@ -5231,10 +5264,13 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
ieee80211_channel_to_frequency(ch.chnum, band);
band_chan_arr[index].hw_value = ch.chnum;
if (ch.bw == BRCMU_CHAN_BW_40) {
/* assuming the order is HT20, HT40 Upper,
* HT40 lower from chanspecs
*/
/* assuming the chanspecs order is HT20,
* HT40 upper, HT40 lower, and VHT80.
*/
if (ch.bw == BRCMU_CHAN_BW_80) {
band_chan_arr[index].flags &=
~IEEE80211_CHAN_NO_80MHZ;
} else if (ch.bw == BRCMU_CHAN_BW_40) {
ht40_flag = band_chan_arr[index].flags &
IEEE80211_CHAN_NO_HT40;
if (ch.sb == BRCMU_CHAN_SB_U) {
@@ -5255,8 +5291,13 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
IEEE80211_CHAN_NO_HT40MINUS;
}
} else {
/* disable other bandwidths for now as mentioned
* order assure they are enabled for subsequent
* chanspecs.
*/
band_chan_arr[index].flags =
IEEE80211_CHAN_NO_HT40;
IEEE80211_CHAN_NO_HT40 |
IEEE80211_CHAN_NO_80MHZ;
ch.bw = BRCMU_CHAN_BW_20;
cfg->d11inf.encchspec(&ch);
channel = ch.chspec;
@@ -5323,13 +5364,63 @@ static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[])
}
}
static void brcmf_update_ht_cap(struct ieee80211_supported_band *band,
u32 bw_cap[2], u32 nchain)
{
band->ht_cap.ht_supported = true;
if (bw_cap[band->band] & WLC_BW_40MHZ_BIT) {
band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
}
band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
memset(band->ht_cap.mcs.rx_mask, 0xff, nchain);
band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
}
static __le16 brcmf_get_mcs_map(u32 nchain, enum ieee80211_vht_mcs_support supp)
{
u16 mcs_map;
int i;
for (i = 0, mcs_map = 0xFFFF; i < nchain; i++)
mcs_map = (mcs_map << 2) | supp;
return cpu_to_le16(mcs_map);
}
static void brcmf_update_vht_cap(struct ieee80211_supported_band *band,
u32 bw_cap[2], u32 nchain)
{
__le16 mcs_map;
/* not allowed in 2.4G band */
if (band->band == IEEE80211_BAND_2GHZ)
return;
band->vht_cap.vht_supported = true;
/* 80MHz is mandatory */
band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
if (bw_cap[band->band] & WLC_BW_160MHZ_BIT) {
band->vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
}
/* all support 256-QAM */
mcs_map = brcmf_get_mcs_map(nchain, IEEE80211_VHT_MCS_SUPPORT_0_9);
band->vht_cap.vht_mcs.rx_mcs_map = mcs_map;
band->vht_cap.vht_mcs.tx_mcs_map = mcs_map;
}
static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
{
struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
struct wiphy *wiphy;
s32 phy_list;
u32 band_list[3];
u32 nmode;
u32 nmode = 0;
u32 vhtmode = 0;
u32 bw_cap[2] = { 0, 0 };
u32 rxchain;
u32 nchain;
@@ -5360,14 +5451,16 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n",
band_list[0], band_list[1], band_list[2]);
(void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode);
err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
if (err) {
brcmf_err("nmode error (%d)\n", err);
} else {
brcmf_get_bwcap(ifp, bw_cap);
}
brcmf_dbg(INFO, "nmode=%d, bw_cap=(%d, %d)\n", nmode,
bw_cap[IEEE80211_BAND_2GHZ], bw_cap[IEEE80211_BAND_5GHZ]);
brcmf_dbg(INFO, "nmode=%d, vhtmode=%d, bw_cap=(%d, %d)\n",
nmode, vhtmode, bw_cap[IEEE80211_BAND_2GHZ],
bw_cap[IEEE80211_BAND_5GHZ]);
err = brcmf_fil_iovar_int_get(ifp, "rxchain", &rxchain);
if (err) {
@@ -5398,17 +5491,10 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
else
continue;
if (bw_cap[band->band] & WLC_BW_40MHZ_BIT) {
band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
}
band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
band->ht_cap.ht_supported = true;
band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
memset(band->ht_cap.mcs.rx_mask, 0xff, nchain);
band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
if (nmode)
brcmf_update_ht_cap(band, bw_cap, nchain);
if (vhtmode)
brcmf_update_vht_cap(band, bw_cap, nchain);
bands[band->band] = band;
}
@@ -897,7 +897,8 @@ static bool brcms_tx_flush_completed(struct brcms_info *wl)
return result;
}
static void brcms_ops_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
static void brcms_ops_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
struct brcms_info *wl = hw->priv;
int ret;
+82 -23
View File
@@ -21,43 +21,81 @@
#include <brcmu_wifi.h>
#include <brcmu_d11.h>
static u16 d11n_sb(enum brcmu_chan_sb sb)
{
switch (sb) {
case BRCMU_CHAN_SB_NONE:
return BRCMU_CHSPEC_D11N_SB_N;
case BRCMU_CHAN_SB_L:
return BRCMU_CHSPEC_D11N_SB_L;
case BRCMU_CHAN_SB_U:
return BRCMU_CHSPEC_D11N_SB_U;
default:
WARN_ON(1);
}
return 0;
}
static u16 d11n_bw(enum brcmu_chan_bw bw)
{
switch (bw) {
case BRCMU_CHAN_BW_20:
return BRCMU_CHSPEC_D11N_BW_20;
case BRCMU_CHAN_BW_40:
return BRCMU_CHSPEC_D11N_BW_40;
default:
WARN_ON(1);
}
return 0;
}
static void brcmu_d11n_encchspec(struct brcmu_chan *ch)
{
ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK;
if (ch->bw == BRCMU_CHAN_BW_20)
ch->sb = BRCMU_CHAN_SB_NONE;
switch (ch->bw) {
case BRCMU_CHAN_BW_20:
ch->chspec |= BRCMU_CHSPEC_D11N_BW_20 | BRCMU_CHSPEC_D11N_SB_N;
break;
case BRCMU_CHAN_BW_40:
default:
WARN_ON_ONCE(1);
break;
}
brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_CH_MASK,
BRCMU_CHSPEC_CH_SHIFT, ch->chnum);
brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11N_SB_MASK,
0, d11n_sb(ch->sb));
brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11N_BW_MASK,
0, d11n_bw(ch->bw));
ch->chspec &= ~BRCMU_CHSPEC_D11N_BND_MASK;
if (ch->chnum <= CH_MAX_2G_CHANNEL)
ch->chspec |= BRCMU_CHSPEC_D11N_BND_2G;
else
ch->chspec |= BRCMU_CHSPEC_D11N_BND_5G;
}
static u16 d11ac_bw(enum brcmu_chan_bw bw)
{
switch (bw) {
case BRCMU_CHAN_BW_20:
return BRCMU_CHSPEC_D11AC_BW_20;
case BRCMU_CHAN_BW_40:
return BRCMU_CHSPEC_D11AC_BW_40;
case BRCMU_CHAN_BW_80:
return BRCMU_CHSPEC_D11AC_BW_80;
default:
WARN_ON(1);
}
return 0;
}
static void brcmu_d11ac_encchspec(struct brcmu_chan *ch)
{
ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK;
if (ch->bw == BRCMU_CHAN_BW_20 || ch->sb == BRCMU_CHAN_SB_NONE)
ch->sb = BRCMU_CHAN_SB_L;
switch (ch->bw) {
case BRCMU_CHAN_BW_20:
ch->chspec |= BRCMU_CHSPEC_D11AC_BW_20;
break;
case BRCMU_CHAN_BW_40:
case BRCMU_CHAN_BW_80:
case BRCMU_CHAN_BW_80P80:
case BRCMU_CHAN_BW_160:
default:
WARN_ON_ONCE(1);
break;
}
brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_CH_MASK,
BRCMU_CHSPEC_CH_SHIFT, ch->chnum);
brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
BRCMU_CHSPEC_D11AC_SB_SHIFT, ch->sb);
brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11AC_BW_MASK,
0, d11ac_bw(ch->bw));
ch->chspec &= ~BRCMU_CHSPEC_D11AC_BND_MASK;
if (ch->chnum <= CH_MAX_2G_CHANNEL)
ch->chspec |= BRCMU_CHSPEC_D11AC_BND_2G;
else
@@ -73,6 +111,7 @@ static void brcmu_d11n_decchspec(struct brcmu_chan *ch)
switch (ch->chspec & BRCMU_CHSPEC_D11N_BW_MASK) {
case BRCMU_CHSPEC_D11N_BW_20:
ch->bw = BRCMU_CHAN_BW_20;
ch->sb = BRCMU_CHAN_SB_NONE;
break;
case BRCMU_CHSPEC_D11N_BW_40:
ch->bw = BRCMU_CHAN_BW_40;
@@ -112,6 +151,7 @@ static void brcmu_d11ac_decchspec(struct brcmu_chan *ch)
switch (ch->chspec & BRCMU_CHSPEC_D11AC_BW_MASK) {
case BRCMU_CHSPEC_D11AC_BW_20:
ch->bw = BRCMU_CHAN_BW_20;
ch->sb = BRCMU_CHAN_SB_NONE;
break;
case BRCMU_CHSPEC_D11AC_BW_40:
ch->bw = BRCMU_CHAN_BW_40;
@@ -128,6 +168,25 @@ static void brcmu_d11ac_decchspec(struct brcmu_chan *ch)
break;
case BRCMU_CHSPEC_D11AC_BW_80:
ch->bw = BRCMU_CHAN_BW_80;
ch->sb = brcmu_maskget16(ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
BRCMU_CHSPEC_D11AC_SB_SHIFT);
switch (ch->sb) {
case BRCMU_CHAN_SB_LL:
ch->chnum -= CH_30MHZ_APART;
break;
case BRCMU_CHAN_SB_LU:
ch->chnum -= CH_10MHZ_APART;
break;
case BRCMU_CHAN_SB_UL:
ch->chnum += CH_10MHZ_APART;
break;
case BRCMU_CHAN_SB_UU:
ch->chnum += CH_30MHZ_APART;
break;
default:
WARN_ON_ONCE(1);
break;
}
break;
case BRCMU_CHSPEC_D11AC_BW_8080:
case BRCMU_CHSPEC_D11AC_BW_160:
@@ -108,13 +108,7 @@ enum brcmu_chan_bw {
};
enum brcmu_chan_sb {
BRCMU_CHAN_SB_NONE = 0,
BRCMU_CHAN_SB_L,
BRCMU_CHAN_SB_U,
BRCMU_CHAN_SB_LL,
BRCMU_CHAN_SB_LU,
BRCMU_CHAN_SB_UL,
BRCMU_CHAN_SB_UU,
BRCMU_CHAN_SB_NONE = -1,
BRCMU_CHAN_SB_LLL,
BRCMU_CHAN_SB_LLU,
BRCMU_CHAN_SB_LUL,
@@ -123,6 +117,12 @@ enum brcmu_chan_sb {
BRCMU_CHAN_SB_ULU,
BRCMU_CHAN_SB_UUL,
BRCMU_CHAN_SB_UUU,
BRCMU_CHAN_SB_L = BRCMU_CHAN_SB_LLL,
BRCMU_CHAN_SB_U = BRCMU_CHAN_SB_LLU,
BRCMU_CHAN_SB_LL = BRCMU_CHAN_SB_LLL,
BRCMU_CHAN_SB_LU = BRCMU_CHAN_SB_LLU,
BRCMU_CHAN_SB_UL = BRCMU_CHAN_SB_LUL,
BRCMU_CHAN_SB_UU = BRCMU_CHAN_SB_LUU,
};
struct brcmu_chan {
@@ -29,6 +29,7 @@
#define CH_UPPER_SB 0x01
#define CH_LOWER_SB 0x02
#define CH_EWA_VALID 0x04
#define CH_30MHZ_APART 6
#define CH_20MHZ_APART 4
#define CH_10MHZ_APART 2
#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */
+2 -1
View File
@@ -936,7 +936,8 @@ static int __cw1200_flush(struct cw1200_common *priv, bool drop)
return ret;
}
void cw1200_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
void cw1200_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
struct cw1200_common *priv = hw->priv;
+2 -1
View File
@@ -40,7 +40,8 @@ int cw1200_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
int cw1200_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
void cw1200_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
void cw1200_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop);
u64 cw1200_prepare_multicast(struct ieee80211_hw *hw,
struct netdev_hw_addr_list *mc_list);
+1 -1
View File
@@ -573,7 +573,7 @@ il3945_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
rx_status.flag |= RX_FLAG_SHORTPRE;
if ((unlikely(rx_stats->phy_count > 20))) {
D_DROP("dsp size out of range [0,20]: %d/n",
D_DROP("dsp size out of range [0,20]: %d\n",
rx_stats->phy_count);
return;
}
+1 -1
View File
@@ -670,7 +670,7 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
}
if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
D_DROP("dsp size out of range [0,20]: %d/n",
D_DROP("dsp size out of range [0,20]: %d\n",
phy_res->cfg_phy_cnt);
return;
}
+2 -1
View File
@@ -4755,7 +4755,8 @@ out:
}
EXPORT_SYMBOL(il_mac_change_interface);
void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
void il_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
struct il_priv *il = hw->priv;
unsigned long timeout = jiffies + msecs_to_jiffies(500);
+2 -1
View File
@@ -1723,7 +1723,8 @@ void il_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum nl80211_iftype newtype, bool newp2p);
void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
void il_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop);
int il_alloc_txq_mem(struct il_priv *il);
void il_free_txq_mem(struct il_priv *il);
+8 -4
View File
@@ -2,10 +2,6 @@ config IWLWIFI
tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "
depends on PCI && MAC80211 && HAS_IOMEM
select FW_LOADER
select NEW_LEDS
select LEDS_CLASS
select LEDS_TRIGGERS
select MAC80211_LEDS
---help---
Select to build the driver supporting the:
@@ -43,6 +39,14 @@ config IWLWIFI
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwlwifi.
config IWLWIFI_LEDS
bool
depends on IWLWIFI
depends on LEDS_CLASS
select LEDS_TRIGGERS
select MAC80211_LEDS
default y
config IWLDVM
tristate "Intel Wireless WiFi DVM Firmware support"
depends on IWLWIFI
+2 -1
View File
@@ -4,9 +4,10 @@ iwldvm-objs += main.o rs.o mac80211.o ucode.o tx.o
iwldvm-objs += lib.o calib.o tt.o sta.o rx.o
iwldvm-objs += power.o
iwldvm-objs += scan.o led.o
iwldvm-objs += scan.o
iwldvm-objs += rxon.o devices.o
iwldvm-$(CONFIG_IWLWIFI_LEDS) += led.o
iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
+2
View File
@@ -888,9 +888,11 @@ struct iwl_priv {
struct iwl_event_log event_log;
#ifdef CONFIG_IWLWIFI_LEDS
struct led_classdev led;
unsigned long blink_on, blink_off;
bool led_registered;
#endif
/* WoWLAN GTK rekey data */
u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN];
+12
View File
@@ -36,8 +36,20 @@ struct iwl_priv;
#define IWL_LED_ACTIVITY (0<<1)
#define IWL_LED_LINK (1<<1)
#ifdef CONFIG_IWLWIFI_LEDS
void iwlagn_led_enable(struct iwl_priv *priv);
void iwl_leds_init(struct iwl_priv *priv);
void iwl_leds_exit(struct iwl_priv *priv);
#else
static inline void iwlagn_led_enable(struct iwl_priv *priv)
{
}
static inline void iwl_leds_init(struct iwl_priv *priv)
{
}
static inline void iwl_leds_exit(struct iwl_priv *priv)
{
}
#endif
#endif /* __iwl_leds_h__ */
+2 -1
View File
@@ -1091,7 +1091,8 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
}
static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
static void iwlagn_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
+1 -1
View File
@@ -98,7 +98,7 @@
#define NVM_HW_SECTION_NUM_FAMILY_7000 0
static const struct iwl_base_params iwl7000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_7000,
.num_of_queues = IWLAGN_NUM_QUEUES,
.pll_cfg_val = 0,
.shadow_ram_support = true,
+1 -1
View File
@@ -85,7 +85,7 @@
#define NVM_HW_SECTION_NUM_FAMILY_8000 10
static const struct iwl_base_params iwl8000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000,
.num_of_queues = IWLAGN_NUM_QUEUES,
.pll_cfg_val = 0,
.shadow_ram_support = true,
+1 -3
View File
@@ -102,9 +102,7 @@
/* EEPROM */
#define IWLAGN_EEPROM_IMG_SIZE 2048
/* OTP */
/* lower blocks contain EEPROM image and calibration data */
#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */
/* high blocks contain PAPD data */
#define OTP_HIGH_IMAGE_SIZE_6x00 (6 * 512 * sizeof(u16)) /* 6 KB */
#define OTP_HIGH_IMAGE_SIZE_1000 (0x200 * sizeof(u16)) /* 1024 bytes */
@@ -193,6 +193,11 @@ struct iwl_ht_params {
#define EEPROM_6000_REG_BAND_24_HT40_CHANNELS 0x80
#define EEPROM_REGULATORY_BAND_NO_HT40 0
/* lower blocks contain EEPROM image and calibration data */
#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */
#define OTP_LOW_IMAGE_SIZE_FAMILY_7000 (4 * 512 * sizeof(u16)) /* 4 KB */
#define OTP_LOW_IMAGE_SIZE_FAMILY_8000 (32 * 512 * sizeof(u16)) /* 32 KB */
struct iwl_eeprom_params {
const u8 regulatory_bands[7];
bool enhanced_txpower;
@@ -269,6 +274,7 @@ struct iwl_cfg {
u8 nvm_hw_section_num;
bool lp_xtal_workaround;
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
bool no_power_up_nic_in_init;
};
/*
@@ -72,11 +72,14 @@
* @IWL_FW_ERROR_DUMP_SRAM:
* @IWL_FW_ERROR_DUMP_REG:
* @IWL_FW_ERROR_DUMP_RXF:
* @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as
* &struct iwl_fw_error_dump_txcmd packets
*/
enum iwl_fw_error_dump_type {
IWL_FW_ERROR_DUMP_SRAM = 0,
IWL_FW_ERROR_DUMP_REG = 1,
IWL_FW_ERROR_DUMP_RXF = 2,
IWL_FW_ERROR_DUMP_TXCMD = 3,
IWL_FW_ERROR_DUMP_MAX,
};
@@ -105,4 +108,27 @@ struct iwl_fw_error_dump_file {
u8 data[0];
} __packed;
/**
* struct iwl_fw_error_dump_txcmd - TX command data
* @cmdlen: original length of command
* @caplen: captured length of command (may be less)
* @data: captured command data, @caplen bytes
*/
struct iwl_fw_error_dump_txcmd {
__le32 cmdlen;
__le32 caplen;
u8 data[];
} __packed;
/**
* iwl_mvm_fw_error_next_data - advance fw error dump data pointer
* @data: previous data block
* Returns: next data block
*/
static inline struct iwl_fw_error_dump_data *
iwl_mvm_fw_error_next_data(struct iwl_fw_error_dump_data *data)
{
return (void *)(data->data + le32_to_cpu(data->len));
}
#endif /* __fw_error_dump_h__ */
+2
View File
@@ -116,9 +116,11 @@ enum iwl_ucode_tlv_flag {
/**
* enum iwl_ucode_tlv_api - ucode api
* @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field.
* @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA.
*/
enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID = BIT(0),
IWL_UCODE_TLV_API_CSA_FLOW = BIT(4),
};
/**
+38 -8
View File
@@ -62,6 +62,7 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/export.h>
#include <linux/etherdevice.h>
#include "iwl-drv.h"
#include "iwl-modparams.h"
#include "iwl-nvm-parse.h"
@@ -450,13 +451,7 @@ static void iwl_set_hw_address(const struct iwl_cfg *cfg,
struct iwl_nvm_data *data,
const __le16 *nvm_sec)
{
u8 hw_addr[ETH_ALEN];
if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
memcpy(hw_addr, nvm_sec + HW_ADDR, ETH_ALEN);
else
memcpy(hw_addr, nvm_sec + MAC_ADDRESS_OVERRIDE_FAMILY_8000,
ETH_ALEN);
const u8 *hw_addr = (const u8 *)(nvm_sec + HW_ADDR);
/* The byte order is little endian 16 bit, meaning 214365 */
data->hw_addr[0] = hw_addr[1];
@@ -467,6 +462,41 @@ static void iwl_set_hw_address(const struct iwl_cfg *cfg,
data->hw_addr[5] = hw_addr[4];
}
static void iwl_set_hw_address_family_8000(const struct iwl_cfg *cfg,
struct iwl_nvm_data *data,
const __le16 *mac_override,
const __le16 *nvm_hw)
{
const u8 *hw_addr;
if (mac_override) {
hw_addr = (const u8 *)(mac_override +
MAC_ADDRESS_OVERRIDE_FAMILY_8000);
/* The byte order is little endian 16 bit, meaning 214365 */
data->hw_addr[0] = hw_addr[1];
data->hw_addr[1] = hw_addr[0];
data->hw_addr[2] = hw_addr[3];
data->hw_addr[3] = hw_addr[2];
data->hw_addr[4] = hw_addr[5];
data->hw_addr[5] = hw_addr[4];
if (is_valid_ether_addr(hw_addr))
return;
}
/* take the MAC address from the OTP */
hw_addr = (const u8 *)(nvm_hw + HW_ADDR0_FAMILY_8000);
data->hw_addr[0] = hw_addr[3];
data->hw_addr[1] = hw_addr[2];
data->hw_addr[2] = hw_addr[1];
data->hw_addr[3] = hw_addr[0];
hw_addr = (const u8 *)(nvm_hw + HW_ADDR1_FAMILY_8000);
data->hw_addr[4] = hw_addr[1];
data->hw_addr[5] = hw_addr[0];
}
struct iwl_nvm_data *
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
const __le16 *nvm_hw, const __le16 *nvm_sw,
@@ -526,7 +556,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
rx_chains);
} else {
/* MAC address in family 8000 */
iwl_set_hw_address(cfg, data, mac_override);
iwl_set_hw_address_family_8000(cfg, data, mac_override, nvm_hw);
iwl_init_sbands(dev, cfg, data, regulatory,
sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains,
+19
View File
@@ -463,6 +463,11 @@ struct iwl_trans;
* @unref: release a reference previously taken with @ref. Note that
* initially the reference count is 1, making an initial @unref
* necessary to allow low power states.
* @dump_data: fill a data dump with debug data, maybe containing last
* TX'ed commands and similar. When called with a NULL buffer and
* zero buffer length, provide only the (estimated) required buffer
* length. Return the used buffer length.
* Note that the transport must fill in the proper file headers.
*/
struct iwl_trans_ops {
@@ -511,6 +516,10 @@ struct iwl_trans_ops {
u32 value);
void (*ref)(struct iwl_trans *trans);
void (*unref)(struct iwl_trans *trans);
#ifdef CONFIG_IWLWIFI_DEBUGFS
u32 (*dump_data)(struct iwl_trans *trans, void *buf, u32 buflen);
#endif
};
/**
@@ -664,6 +673,16 @@ static inline void iwl_trans_unref(struct iwl_trans *trans)
trans->ops->unref(trans);
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
static inline u32 iwl_trans_dump_data(struct iwl_trans *trans,
void *buf, u32 buflen)
{
if (!trans->ops->dump_data)
return 0;
return trans->ops->dump_data(trans, buf, buflen);
}
#endif
static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
{
+2 -1
View File
@@ -3,8 +3,9 @@ iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o
iwlmvm-y += scan.o time-event.o rs.o
iwlmvm-y += power.o coex.o
iwlmvm-y += led.o tt.o offloading.o
iwlmvm-y += tt.o offloading.o
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o
iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
+3 -3
View File
@@ -611,14 +611,14 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO);
if (IWL_MVM_BT_COEX_CORUNNING) {
bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_CORUN_LUT_20 |
BT_VALID_CORUN_LUT_40);
bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_CORUN_LUT_20 |
BT_VALID_CORUN_LUT_40);
bt_cmd->flags |= cpu_to_le32(BT_COEX_CORUNNING);
}
if (IWL_MVM_BT_COEX_MPLUT) {
bt_cmd->flags |= cpu_to_le32(BT_COEX_MPLUT);
bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
}
if (mvm->cfg->bt_shared_single_ant)
+1 -1
View File
@@ -67,7 +67,7 @@
#include "iwl-io.h"
#include "iwl-prph.h"
#include "debugfs.h"
#include "fw-error-dump.h"
#include "iwl-fw-error-dump.h"
static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
@@ -187,9 +187,9 @@ enum iwl_scan_type {
* this number of packets were received (typically 1)
* @passive2active: is auto switching from passive to active during scan allowed
* @rxchain_sel_flags: RXON_RX_CHAIN_*
* @max_out_time: in usecs, max out of serving channel time
* @max_out_time: in TUs, max out of serving channel time
* @suspend_time: how long to pause scan when returning to service channel:
* bits 0-19: beacon interal in usecs (suspend before executing)
* bits 0-19: beacon interal in TUs (suspend before executing)
* bits 20-23: reserved
* bits 24-31: number of beacons (suspend between channels)
* @rxon_flags: RXON_FLG_*
@@ -387,8 +387,8 @@ enum scan_framework_client {
* @quiet_plcp_th: quiet channel num of packets threshold
* @good_CRC_th: passive to active promotion threshold
* @rx_chain: RXON rx chain.
* @max_out_time: max uSec to be out of assoceated channel
* @suspend_time: pause scan this long when returning to service channel
* @max_out_time: max TUs to be out of assoceated channel
* @suspend_time: pause scan this TUs when returning to service channel
* @flags: RXON flags
* @filter_flags: RXONfilter
* @tx_cmd: tx command for active scan; for 2GHz and for 5GHz.
+1 -1
View File
@@ -295,7 +295,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
/* Read the NVM only at driver load time, no need to do this twice */
if (read_nvm) {
/* Read nvm */
ret = iwl_nvm_init(mvm);
ret = iwl_nvm_init(mvm, true);
if (ret) {
IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
goto error;
@@ -1237,11 +1237,23 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
u32 rate __maybe_unused =
le32_to_cpu(beacon->beacon_notify_hdr.initial_rate);
lockdep_assert_held(&mvm->mutex);
IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n",
status & TX_STATUS_MSK,
beacon->beacon_notify_hdr.failure_frame,
le64_to_cpu(beacon->tsf),
rate);
if (unlikely(mvm->csa_vif && mvm->csa_vif->csa_active)) {
if (!ieee80211_csa_is_complete(mvm->csa_vif)) {
iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm->csa_vif);
} else {
ieee80211_csa_finish(mvm->csa_vif);
mvm->csa_vif = NULL;
}
}
return 0;
}
+94 -6
View File
@@ -320,6 +320,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD)
hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_CSA_FLOW)
hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
hw->wiphy->iface_combinations = iwl_mvm_iface_combinations;
hw->wiphy->n_iface_combinations =
ARRAY_SIZE(iwl_mvm_iface_combinations);
@@ -539,13 +542,22 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
return -EACCES;
/* return from D0i3 before starting a new Tx aggregation */
if (action == IEEE80211_AMPDU_TX_START) {
switch (action) {
case IEEE80211_AMPDU_TX_START:
case IEEE80211_AMPDU_TX_STOP_CONT:
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
case IEEE80211_AMPDU_TX_OPERATIONAL:
iwl_mvm_ref(mvm, IWL_MVM_REF_TX_AGG);
tx_agg_ref = true;
/*
* wait synchronously until D0i3 exit to get the correct
* sequence number for the tid
* for tx start, wait synchronously until D0i3 exit to
* get the correct sequence number for the tid.
* additionally, some other ampdu actions use direct
* target access, which is not handled automatically
* by the trans layer (unlike commands), so wait for
* d0i3 exit in these cases as well.
*/
if (!wait_event_timeout(mvm->d0i3_exit_waitq,
!test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status), HZ)) {
@@ -553,6 +565,9 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
iwl_mvm_unref(mvm, IWL_MVM_REF_TX_AGG);
return -EIO;
}
break;
default:
break;
}
mutex_lock(&mvm->mutex);
@@ -1005,7 +1020,7 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac,
memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN);
len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4);
ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_SYNC, len, cmd);
ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_ASYNC, len, cmd);
if (ret)
IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret);
}
@@ -1021,7 +1036,7 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm)
if (WARN_ON_ONCE(!mvm->mcast_filter_cmd))
return;
ieee80211_iterate_active_interfaces(
ieee80211_iterate_active_interfaces_atomic(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_mc_iface_iterator, &iter_data);
}
@@ -1814,6 +1829,11 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);
if (!iwl_mvm_is_idle(mvm)) {
ret = -EBUSY;
goto out;
}
switch (mvm->scan_status) {
case IWL_MVM_SCAN_OS:
IWL_DEBUG_SCAN(mvm, "Stopping previous scan for sched_scan\n");
@@ -2186,6 +2206,11 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
switch (vif->type) {
case NL80211_IFTYPE_AP:
/* Unless it's a CSA flow we have nothing to do here */
if (vif->csa_active) {
mvmvif->ap_ibss_active = true;
break;
}
case NL80211_IFTYPE_ADHOC:
/*
* The AP binding flow is handled as part of the start_ap flow
@@ -2222,6 +2247,12 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
goto out_remove_binding;
}
/* Handle binding during CSA */
if (vif->type == NL80211_IFTYPE_AP) {
iwl_mvm_update_quotas(mvm, vif);
iwl_mvm_mac_ctxt_changed(mvm, vif);
}
goto out_unlock;
out_remove_binding:
@@ -2246,13 +2277,20 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data);
switch (vif->type) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_ADHOC:
goto out_unlock;
case NL80211_IFTYPE_MONITOR:
mvmvif->monitor_active = false;
iwl_mvm_update_quotas(mvm, NULL);
break;
case NL80211_IFTYPE_AP:
/* This part is triggered only during CSA */
if (!vif->csa_active || !mvmvif->ap_ibss_active)
goto out_unlock;
mvmvif->ap_ibss_active = false;
iwl_mvm_update_quotas(mvm, NULL);
/*TODO: bt_coex notification here? */
default:
break;
}
@@ -2348,6 +2386,53 @@ static int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw,
}
#endif
static void iwl_mvm_channel_switch_beacon(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_chan_def *chandef)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
mutex_lock(&mvm->mutex);
if (WARN(mvm->csa_vif && mvm->csa_vif->csa_active,
"Another CSA is already in progress"))
goto out_unlock;
IWL_DEBUG_MAC80211(mvm, "CSA started to freq %d\n",
chandef->center_freq1);
mvm->csa_vif = vif;
out_unlock:
mutex_unlock(&mvm->mutex);
}
static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u32 queues, bool drop)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif;
struct iwl_mvm_sta *mvmsta;
if (!vif || vif->type != NL80211_IFTYPE_STATION)
return;
mutex_lock(&mvm->mutex);
mvmvif = iwl_mvm_vif_from_mac80211(vif);
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id);
if (WARN_ON_ONCE(!mvmsta))
goto done;
if (drop) {
if (iwl_mvm_flush_tx_path(mvm, mvmsta->tfd_queue_msk, true))
IWL_ERR(mvm, "flush request fail\n");
} else {
iwl_trans_wait_tx_queue_empty(mvm->trans,
mvmsta->tfd_queue_msk);
}
done:
mutex_unlock(&mvm->mutex);
}
const struct ieee80211_ops iwl_mvm_hw_ops = {
.tx = iwl_mvm_mac_tx,
.ampdu_action = iwl_mvm_mac_ampdu_action,
@@ -2371,6 +2456,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.sta_rc_update = iwl_mvm_sta_rc_update,
.conf_tx = iwl_mvm_mac_conf_tx,
.mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
.flush = iwl_mvm_mac_flush,
.sched_scan_start = iwl_mvm_mac_sched_scan_start,
.sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
.set_key = iwl_mvm_mac_set_key,
@@ -2390,6 +2476,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.set_tim = iwl_mvm_set_tim,
.channel_switch_beacon = iwl_mvm_channel_switch_beacon,
CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
#ifdef CONFIG_PM_SLEEP
+18 -1
View File
@@ -589,7 +589,9 @@ struct iwl_mvm {
u32 *fw_error_rxf;
u32 fw_error_rxf_len;
#ifdef CONFIG_IWLWIFI_LEDS
struct led_classdev led;
#endif
struct ieee80211_vif *p2p_device_vif;
@@ -642,6 +644,8 @@ struct iwl_mvm {
/* Indicate if device power save is allowed */
bool ps_disabled;
struct ieee80211_vif *csa_vif;
};
/* Extract MVM priv from op_mode and _hw */
@@ -757,7 +761,7 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
struct iwl_device_cmd *cmd);
/* NVM */
int iwl_nvm_init(struct iwl_mvm *mvm);
int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic);
int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm);
int iwl_mvm_up(struct iwl_mvm *mvm);
@@ -896,8 +900,18 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
#ifdef CONFIG_IWLWIFI_LEDS
int iwl_mvm_leds_init(struct iwl_mvm *mvm);
void iwl_mvm_leds_exit(struct iwl_mvm *mvm);
#else
static inline int iwl_mvm_leds_init(struct iwl_mvm *mvm)
{
return 0;
}
static inline void iwl_mvm_leds_exit(struct iwl_mvm *mvm)
{
}
#endif
/* D3 (WoWLAN, NetDetect) */
int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
@@ -1015,6 +1029,9 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif)
return mvmvif->low_latency;
}
/* Assoc status */
bool iwl_mvm_is_idle(struct iwl_mvm *mvm);
/* Thermal management and CT-kill */
void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff);
void iwl_mvm_tt_handler(struct iwl_mvm *mvm);
+20 -10
View File
@@ -238,13 +238,20 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
return NULL;
}
} else {
/* SW and REGULATORY sections are mandatory */
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
!mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data ||
!mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) {
IWL_ERR(mvm,
"Can't parse empty family 8000 NVM sections\n");
return NULL;
}
/* MAC_OVERRIDE or at least HW section must exist */
if (!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data &&
!mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data) {
IWL_ERR(mvm,
"Can't parse mac_address, empty sections\n");
return NULL;
}
}
if (WARN_ON(!mvm->cfg))
@@ -427,7 +434,7 @@ int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm)
return ret;
}
int iwl_nvm_init(struct iwl_mvm *mvm)
int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
{
int ret, i, section;
u8 *nvm_buffer, *temp;
@@ -437,13 +444,8 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
return -EINVAL;
/* load external NVM if configured */
if (iwlwifi_mod_params.nvm_file) {
/* move to External NVM flow */
ret = iwl_mvm_read_external_nvm(mvm);
if (ret)
return ret;
} else {
/* load NVM values from nic */
if (read_nvm_from_nic) {
/* list of NVM sections we are allowed/need to read */
if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
nvm_to_read[0] = mvm->cfg->nvm_hw_section_num;
@@ -463,7 +465,6 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
/* Read From FW NVM */
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");
/* TODO: find correct NVM max size for a section */
nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
GFP_KERNEL);
if (!nvm_buffer)
@@ -511,6 +512,15 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
return ret;
}
/* load external NVM if configured */
if (iwlwifi_mod_params.nvm_file) {
/* move to External NVM flow */
ret = iwl_mvm_read_external_nvm(mvm);
if (ret)
return ret;
}
/* parse the relevant nvm sections */
mvm->nvm_data = iwl_parse_nvm_sections(mvm);
if (!mvm->nvm_data)
return -ENODATA;
+28 -8
View File
@@ -79,8 +79,8 @@
#include "iwl-prph.h"
#include "rs.h"
#include "fw-api-scan.h"
#include "fw-error-dump.h"
#include "time-event.h"
#include "iwl-fw-error-dump.h"
/*
* module name, copyright, version, etc.
@@ -220,7 +220,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, false),
RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true),
RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false),
RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, true),
RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, true),
RX_HANDLER(ANTENNA_COUPLING_NOTIFICATION,
iwl_mvm_rx_ant_coupling_notif, true),
@@ -467,12 +467,18 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
min_backoff = calc_min_backoff(trans, cfg);
iwl_mvm_tt_initialize(mvm, min_backoff);
if (WARN(cfg->no_power_up_nic_in_init && !iwlwifi_mod_params.nvm_file,
"not allowing power-up and not having nvm_file\n"))
goto out_free;
/*
* If the NVM exists in an external file,
* there is no need to unnecessarily power up the NIC at driver load
* Even if nvm exists in the nvm_file driver should read agin the nvm
* from the nic because there might be entries that exist in the OTP
* and not in the file.
* for nics with no_power_up_nic_in_init: rely completley on nvm_file
*/
if (iwlwifi_mod_params.nvm_file) {
err = iwl_nvm_init(mvm);
if (cfg->no_power_up_nic_in_init && iwlwifi_mod_params.nvm_file) {
err = iwl_nvm_init(mvm, false);
if (err)
goto out_free;
} else {
@@ -519,7 +525,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
out_free:
iwl_phy_db_free(mvm->phy_db);
kfree(mvm->scan_cmd);
if (!iwlwifi_mod_params.nvm_file)
if (!cfg->no_power_up_nic_in_init || !iwlwifi_mod_params.nvm_file)
iwl_trans_op_mode_leave(trans);
ieee80211_free_hw(mvm->hw);
return NULL;
@@ -816,6 +822,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
struct iwl_fw_error_dump_file *dump_file;
struct iwl_fw_error_dump_data *dump_data;
u32 file_len;
u32 trans_len;
lockdep_assert_held(&mvm->mutex);
@@ -827,6 +834,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
sizeof(*dump_file) +
sizeof(*dump_data) * 2;
trans_len = iwl_trans_dump_data(mvm->trans, NULL, 0);
if (trans_len)
file_len += trans_len;
dump_file = vmalloc(file_len);
if (!dump_file)
return;
@@ -840,7 +851,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
dump_data->len = cpu_to_le32(mvm->fw_error_rxf_len);
memcpy(dump_data->data, mvm->fw_error_rxf, mvm->fw_error_rxf_len);
dump_data = (void *)((u8 *)dump_data->data + mvm->fw_error_rxf_len);
dump_data = iwl_mvm_fw_error_next_data(dump_data);
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM);
dump_data->len = cpu_to_le32(mvm->fw_error_sram_len);
@@ -858,6 +869,15 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
kfree(mvm->fw_error_sram);
mvm->fw_error_sram = NULL;
mvm->fw_error_sram_len = 0;
if (trans_len) {
void *buf = iwl_mvm_fw_error_next_data(dump_data);
u32 real_trans_len = iwl_trans_dump_data(mvm->trans, buf,
trans_len);
dump_data = (void *)((u8 *)buf + real_trans_len);
dump_file->file_len =
cpu_to_le32(file_len - trans_len + real_trans_len);
}
}
#endif
+3 -6
View File
@@ -202,18 +202,15 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
struct cfg80211_chan_def *chandef,
u8 chains_static, u8 chains_dynamic)
{
int ret;
WARN_ON(!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
ctxt->ref);
lockdep_assert_held(&mvm->mutex);
ctxt->channel = chandef->chan;
ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
chains_static, chains_dynamic,
FW_CTXT_ACTION_ADD, 0);
return ret;
return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
chains_static, chains_dynamic,
FW_CTXT_ACTION_ADD, 0);
}
/*
+62 -119
View File
@@ -211,7 +211,7 @@ static const struct rs_tx_column rs_tx_columns[] = {
.next_columns = {
RS_COLUMN_LEGACY_ANT_B,
RS_COLUMN_SISO_ANT_A,
RS_COLUMN_SISO_ANT_B,
RS_COLUMN_MIMO2,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
@@ -223,8 +223,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
.ant = ANT_B,
.next_columns = {
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_SISO_ANT_A,
RS_COLUMN_SISO_ANT_B,
RS_COLUMN_MIMO2,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
@@ -238,10 +238,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_B,
RS_COLUMN_MIMO2,
RS_COLUMN_SISO_ANT_A_SGI,
RS_COLUMN_SISO_ANT_B_SGI,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
},
.checks = {
rs_siso_allow,
@@ -254,10 +254,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_A,
RS_COLUMN_MIMO2,
RS_COLUMN_SISO_ANT_B_SGI,
RS_COLUMN_SISO_ANT_A_SGI,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
},
.checks = {
rs_siso_allow,
@@ -271,10 +271,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_B_SGI,
RS_COLUMN_MIMO2_SGI,
RS_COLUMN_SISO_ANT_A,
RS_COLUMN_SISO_ANT_B,
RS_COLUMN_MIMO2,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
},
.checks = {
rs_siso_allow,
@@ -289,10 +289,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_A_SGI,
RS_COLUMN_MIMO2_SGI,
RS_COLUMN_SISO_ANT_B,
RS_COLUMN_SISO_ANT_A,
RS_COLUMN_MIMO2,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
},
.checks = {
rs_siso_allow,
@@ -304,12 +304,12 @@ static const struct rs_tx_column rs_tx_columns[] = {
.ant = ANT_AB,
.next_columns = {
RS_COLUMN_SISO_ANT_A,
RS_COLUMN_SISO_ANT_B,
RS_COLUMN_SISO_ANT_A_SGI,
RS_COLUMN_SISO_ANT_B_SGI,
RS_COLUMN_MIMO2_SGI,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
},
.checks = {
rs_mimo_allow,
@@ -321,12 +321,12 @@ static const struct rs_tx_column rs_tx_columns[] = {
.sgi = true,
.next_columns = {
RS_COLUMN_SISO_ANT_A_SGI,
RS_COLUMN_SISO_ANT_B_SGI,
RS_COLUMN_SISO_ANT_A,
RS_COLUMN_SISO_ANT_B,
RS_COLUMN_MIMO2,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
},
.checks = {
rs_mimo_allow,
@@ -1031,7 +1031,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
return;
}
#ifdef CPTCFG_MAC80211_DEBUGFS
#ifdef CONFIG_MAC80211_DEBUGFS
/* Disable last tx check if we are debugging with fixed rate */
if (lq_sta->dbg_fixed_rate) {
IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n");
@@ -1335,105 +1335,50 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw);
}
/*
* Find starting rate for new "search" high-throughput mode of modulation.
* Goal is to find lowest expected rate (under perfect conditions) that is
* above the current measured throughput of "active" mode, to give new mode
* a fair chance to prove itself without too many challenges.
*
* This gets called when transitioning to more aggressive modulation
* (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive
* (i.e. MIMO to SISO). When moving to MIMO, bit rate will typically need
* to decrease to match "active" throughput. When moving from MIMO to SISO,
* bit rate will typically need to increase, but not if performance was bad.
*/
static s32 rs_get_best_rate(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl, /* "search" */
u16 rate_mask, s8 index)
unsigned long rate_mask, s8 index)
{
/* "active" values */
struct iwl_scale_tbl_info *active_tbl =
&(lq_sta->lq_info[lq_sta->active_tbl]);
s32 active_sr = active_tbl->win[index].success_ratio;
s32 active_tpt = active_tbl->expected_tpt[index];
/* expected "search" throughput */
s32 success_ratio = active_tbl->win[index].success_ratio;
u16 expected_current_tpt = active_tbl->expected_tpt[index];
const u16 *tpt_tbl = tbl->expected_tpt;
s32 new_rate, high, low, start_hi;
u16 high_low;
s8 rate = index;
u32 target_tpt;
int rate_idx;
new_rate = high = low = start_hi = IWL_RATE_INVALID;
while (1) {
high_low = rs_get_adjacent_rate(mvm, rate, rate_mask,
tbl->rate.type);
low = high_low & 0xff;
high = (high_low >> 8) & 0xff;
/*
* Lower the "search" bit rate, to give new "search" mode
* approximately the same throughput as "active" if:
*
* 1) "Active" mode has been working modestly well (but not
* great), and expected "search" throughput (under perfect
* conditions) at candidate rate is above the actual
* measured "active" throughput (but less than expected
* "active" throughput under perfect conditions).
* OR
* 2) "Active" mode has been working perfectly or very well
* and expected "search" throughput (under perfect
* conditions) at candidate rate is above expected
* "active" throughput (under perfect conditions).
*/
if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) &&
((active_sr > RS_SR_FORCE_DECREASE) &&
(active_sr <= IWL_RATE_HIGH_TH) &&
(tpt_tbl[rate] <= active_tpt))) ||
((active_sr >= IWL_RATE_SCALE_SWITCH) &&
(tpt_tbl[rate] > active_tpt))) {
/* (2nd or later pass)
* If we've already tried to raise the rate, and are
* now trying to lower it, use the higher rate. */
if (start_hi != IWL_RATE_INVALID) {
new_rate = start_hi;
break;
}
new_rate = rate;
/* Loop again with lower rate */
if (low != IWL_RATE_INVALID)
rate = low;
/* Lower rate not available, use the original */
else
break;
/* Else try to raise the "search" rate to match "active" */
} else {
/* (2nd or later pass)
* If we've already tried to lower the rate, and are
* now trying to raise it, use the lower rate. */
if (new_rate != IWL_RATE_INVALID)
break;
/* Loop again with higher rate */
else if (high != IWL_RATE_INVALID) {
start_hi = high;
rate = high;
/* Higher rate not available, use the original */
} else {
new_rate = rate;
break;
}
}
if (success_ratio > RS_SR_NO_DECREASE) {
target_tpt = 100 * expected_current_tpt;
IWL_DEBUG_RATE(mvm,
"SR %d high. Find rate exceeding EXPECTED_CURRENT %d\n",
success_ratio, target_tpt);
} else {
target_tpt = lq_sta->last_tpt;
IWL_DEBUG_RATE(mvm,
"SR %d not thag good. Find rate exceeding ACTUAL_TPT %d\n",
success_ratio, target_tpt);
}
return new_rate;
rate_idx = find_first_bit(&rate_mask, BITS_PER_LONG);
while (rate_idx != IWL_RATE_INVALID) {
if (target_tpt < (100 * tpt_tbl[rate_idx]))
break;
high_low = rs_get_adjacent_rate(mvm, rate_idx, rate_mask,
tbl->rate.type);
rate_idx = (high_low >> 8) & 0xff;
}
IWL_DEBUG_RATE(mvm, "Best rate found %d target_tp %d expected_new %d\n",
rate_idx, target_tpt,
rate_idx != IWL_RATE_INVALID ?
100 * tpt_tbl[rate_idx] : IWL_INVALID_VALUE);
return rate_idx;
}
static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta)
@@ -1608,7 +1553,7 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
tpt = lq_sta->last_tpt / 100;
expected_tpt_tbl = rs_get_expected_tpt_table(lq_sta, next_col,
tbl->rate.bw);
rs_bw_from_sta_bw(sta));
if (WARN_ON_ONCE(!expected_tpt_tbl))
continue;
@@ -1649,7 +1594,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column];
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u16 rate_mask = 0;
unsigned long rate_mask = 0;
u32 rate_idx = 0;
memcpy(search_tbl, tbl, sz);
@@ -1691,7 +1636,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
!(BIT(rate_idx) & rate_mask)) {
IWL_DEBUG_RATE(mvm,
"can not switch with index %d"
" rate mask %x\n",
" rate mask %lx\n",
rate_idx, rate_mask);
goto err;
@@ -1805,16 +1750,21 @@ static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index,
*stronger = TPC_INVALID;
}
static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct rs_rate *rate,
enum ieee80211_band band)
static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct rs_rate *rate, enum ieee80211_band band)
{
int index = rate->index;
bool cam = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM);
bool sta_ps_disabled = (vif->type == NL80211_IFTYPE_STATION &&
!vif->bss_conf.ps);
IWL_DEBUG_RATE(mvm, "cam: %d sta_ps_disabled %d\n",
cam, sta_ps_disabled);
/*
* allow tpc only if power management is enabled, or bt coex
* activity grade allows it and we are on 2.4Ghz.
*/
if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM &&
if ((cam || sta_ps_disabled) &&
!iwl_mvm_bt_coex_is_tpc_allowed(mvm, band))
return false;
@@ -1931,7 +1881,7 @@ static bool rs_tpc_perform(struct iwl_mvm *mvm,
band = chanctx_conf->def.chan->band;
rcu_read_unlock();
if (!rs_tpc_allowed(mvm, rate, band)) {
if (!rs_tpc_allowed(mvm, vif, rate, band)) {
IWL_DEBUG_RATE(mvm,
"tpc is not allowed. remove txp restrictions");
lq_sta->lq.reduced_tpc = TPC_NO_REDUCTION;
@@ -2235,7 +2185,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
break;
case RS_ACTION_STAY:
/* No change */
update_lq = rs_tpc_perform(mvm, sta, lq_sta, tbl);
if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN)
update_lq = rs_tpc_perform(mvm, sta, lq_sta, tbl);
break;
default:
break;
@@ -2489,10 +2440,6 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta,
if (i == IWL_RATE_9M_INDEX)
continue;
/* Disable MCS9 as a workaround */
if (i == IWL_RATE_MCS_9_INDEX)
continue;
/* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */
if (i == IWL_RATE_MCS_9_INDEX &&
sta->bandwidth == IEEE80211_STA_RX_BW_20)
@@ -2511,10 +2458,6 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta,
if (i == IWL_RATE_9M_INDEX)
continue;
/* Disable MCS9 as a workaround */
if (i == IWL_RATE_MCS_9_INDEX)
continue;
/* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */
if (i == IWL_RATE_MCS_9_INDEX &&
sta->bandwidth == IEEE80211_STA_RX_BW_20)
+13 -42
View File
@@ -277,51 +277,22 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_scan_condition_iterator,
&global_bound);
/*
* Under low latency traffic passive scan is fragmented meaning
* that dwell on a particular channel will be fragmented. Each fragment
* dwell time is 20ms and fragments period is 105ms. Skipping to next
* channel will be delayed by the same period - 105ms. So suspend_time
* parameter describing both fragments and channels skipping periods is
* set to 105ms. This value is chosen so that overall passive scan
* duration will not be too long. Max_out_time in this case is set to
* 70ms, so for active scanning operating channel will be left for 70ms
* while for passive still for 20ms (fragment dwell).
*/
if (global_bound) {
if (!iwl_mvm_low_latency(mvm)) {
params->suspend_time = ieee80211_tu_to_usec(100);
params->max_out_time = ieee80211_tu_to_usec(600);
} else {
params->suspend_time = ieee80211_tu_to_usec(105);
/* P2P doesn't support fragmented passive scan, so
* configure max_out_time to be at least longest dwell
* time for passive scan.
*/
if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p) {
params->max_out_time = ieee80211_tu_to_usec(70);
params->passive_fragmented = true;
} else {
u32 passive_dwell;
/*
* Use band G so that passive channel dwell time
* will be assigned with maximum value.
*/
band = IEEE80211_BAND_2GHZ;
passive_dwell = iwl_mvm_get_passive_dwell(band);
params->max_out_time =
ieee80211_tu_to_usec(passive_dwell);
}
}
if (!global_bound)
goto not_bound;
params->suspend_time = 100;
params->max_out_time = 600;
if (iwl_mvm_low_latency(mvm)) {
params->suspend_time = 250;
params->max_out_time = 250;
}
not_bound:
for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) {
if (params->passive_fragmented)
params->dwell[band].passive = 20;
else
params->dwell[band].passive =
iwl_mvm_get_passive_dwell(band);
params->dwell[band].passive = iwl_mvm_get_passive_dwell(band);
params->dwell[band].active = iwl_mvm_get_active_dwell(band,
n_ssids);
}
@@ -770,7 +741,7 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels;
int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels;
int head = 0;
int tail = band_2ghz + band_5ghz;
int tail = band_2ghz + band_5ghz - 1;
u32 ssid_bitmap;
int cmd_len;
int ret;
+21
View File
@@ -519,6 +519,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
iwl_mvm_dump_umac_error_log(mvm);
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm)
{
const struct fw_img *img;
@@ -581,6 +582,7 @@ void iwl_mvm_fw_error_rxf_dump(struct iwl_mvm *mvm)
}
iwl_trans_release_nic_access(mvm->trans, &flags);
}
#endif
/**
* iwl_mvm_send_lq_cmd() - Send link quality command
@@ -688,3 +690,22 @@ bool iwl_mvm_low_latency(struct iwl_mvm *mvm)
return result;
}
static void iwl_mvm_idle_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
{
bool *idle = _data;
if (!vif->bss_conf.idle)
*idle = false;
}
bool iwl_mvm_is_idle(struct iwl_mvm *mvm)
{
bool idle = true;
ieee80211_iterate_active_interfaces_atomic(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_idle_iter, &idle);
return idle;
}
+14 -10
View File
@@ -117,21 +117,19 @@ struct iwl_dma_ptr {
/**
* iwl_queue_inc_wrap - increment queue index, wrap back to beginning
* @index -- current index
* @n_bd -- total number of entries in queue (must be power of 2)
*/
static inline int iwl_queue_inc_wrap(int index, int n_bd)
static inline int iwl_queue_inc_wrap(int index)
{
return ++index & (n_bd - 1);
return ++index & (TFD_QUEUE_SIZE_MAX - 1);
}
/**
* iwl_queue_dec_wrap - decrement queue index, wrap back to end
* @index -- current index
* @n_bd -- total number of entries in queue (must be power of 2)
*/
static inline int iwl_queue_dec_wrap(int index, int n_bd)
static inline int iwl_queue_dec_wrap(int index)
{
return --index & (n_bd - 1);
return --index & (TFD_QUEUE_SIZE_MAX - 1);
}
struct iwl_cmd_meta {
@@ -145,13 +143,13 @@ struct iwl_cmd_meta {
*
* Contains common data for Rx and Tx queues.
*
* Note the difference between n_bd and n_window: the hardware
* always assumes 256 descriptors, so n_bd is always 256 (unless
* Note the difference between TFD_QUEUE_SIZE_MAX and n_window: the hardware
* always assumes 256 descriptors, so TFD_QUEUE_SIZE_MAX is always 256 (unless
* there might be HW changes in the future). For the normal TX
* queues, n_window, which is the size of the software queue data
* is also 256; however, for the command queue, n_window is only
* 32 since we don't need so many commands pending. Since the HW
* still uses 256 BDs for DMA though, n_bd stays 256. As a result,
* still uses 256 BDs for DMA though, TFD_QUEUE_SIZE_MAX stays 256. As a result,
* the software buffers (in the variables @meta, @txb in struct
* iwl_txq) only have 32 entries, while the HW buffers (@tfds in
* the same struct) have 256.
@@ -162,7 +160,6 @@ struct iwl_cmd_meta {
* data is a window overlayed over the HW queue.
*/
struct iwl_queue {
int n_bd; /* number of BDs in this queue */
int write_ptr; /* 1-st empty entry (index) host_w*/
int read_ptr; /* last used entry (index) host_r*/
/* use for monitoring and recovering the stuck queue */
@@ -373,6 +370,13 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
struct sk_buff_head *skbs);
void iwl_trans_pcie_tx_reset(struct iwl_trans *trans);
static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
{
struct iwl_tfd_tb *tb = &tfd->tbs[idx];
return le16_to_cpu(tb->hi_n_len) >> 4;
}
/*****************************************************
* Error handling
******************************************************/
+1 -1
View File
@@ -850,7 +850,7 @@ static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans)
trans_pcie->ict_index, read);
trans_pcie->ict_tbl[trans_pcie->ict_index] = 0;
trans_pcie->ict_index =
iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
((trans_pcie->ict_index + 1) & (ICT_COUNT - 1));
read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index,
+68 -6
View File
@@ -73,6 +73,7 @@
#include "iwl-csr.h"
#include "iwl-prph.h"
#include "iwl-agn-hw.h"
#include "iwl-fw-error-dump.h"
#include "internal.h"
static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg)
@@ -1337,8 +1338,8 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm)
IWL_ERR(trans,
"Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n",
cnt, active ? "" : "in", fifo, tbl_dw,
iwl_read_prph(trans,
SCD_QUEUE_RDPTR(cnt)) & (txq->q.n_bd - 1),
iwl_read_prph(trans, SCD_QUEUE_RDPTR(cnt)) &
(TFD_QUEUE_SIZE_MAX - 1),
iwl_read_prph(trans, SCD_QUEUE_WRPTR(cnt)));
}
@@ -1669,6 +1670,61 @@ err:
IWL_ERR(trans, "failed to create the trans debugfs entry\n");
return -ENOMEM;
}
static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
{
u32 cmdlen = 0;
int i;
for (i = 0; i < IWL_NUM_OF_TBS; i++)
cmdlen += iwl_pcie_tfd_tb_get_len(tfd, i);
return cmdlen;
}
static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
void *buf, u32 buflen)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_fw_error_dump_data *data;
struct iwl_txq *cmdq = &trans_pcie->txq[trans_pcie->cmd_queue];
struct iwl_fw_error_dump_txcmd *txcmd;
u32 len;
int i, ptr;
if (!buf)
return sizeof(*data) +
cmdq->q.n_window * (sizeof(*txcmd) +
TFD_MAX_PAYLOAD_SIZE);
len = 0;
data = buf;
data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);
txcmd = (void *)data->data;
spin_lock_bh(&cmdq->lock);
ptr = cmdq->q.write_ptr;
for (i = 0; i < cmdq->q.n_window; i++) {
u8 idx = get_cmd_index(&cmdq->q, ptr);
u32 caplen, cmdlen;
cmdlen = iwl_trans_pcie_get_cmdlen(&cmdq->tfds[ptr]);
caplen = min_t(u32, TFD_MAX_PAYLOAD_SIZE, cmdlen);
if (cmdlen) {
len += sizeof(*txcmd) + caplen;
txcmd->cmdlen = cpu_to_le32(cmdlen);
txcmd->caplen = cpu_to_le32(caplen);
memcpy(txcmd->data, cmdq->entries[idx].cmd, caplen);
txcmd = (void *)((u8 *)txcmd->data + caplen);
}
ptr = iwl_queue_dec_wrap(ptr);
}
spin_unlock_bh(&cmdq->lock);
data->len = cpu_to_le32(len);
return sizeof(*data) + len;
}
#else
static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
struct dentry *dir)
@@ -1711,6 +1767,10 @@ static const struct iwl_trans_ops trans_ops_pcie = {
.grab_nic_access = iwl_trans_pcie_grab_nic_access,
.release_nic_access = iwl_trans_pcie_release_nic_access,
.set_bits_mask = iwl_trans_pcie_set_bits_mask,
#ifdef CONFIG_IWLWIFI_DEBUGFS
.dump_data = iwl_trans_pcie_dump_data,
#endif
};
struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
@@ -1788,6 +1848,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
* PCI Tx retries from interfering with C3 CPU state */
pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
trans->dev = &pdev->dev;
trans_pcie->pci_dev = pdev;
iwl_disable_interrupts(trans);
err = pci_enable_msi(pdev);
if (err) {
dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", err);
@@ -1799,8 +1863,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
}
}
trans->dev = &pdev->dev;
trans_pcie->pci_dev = pdev;
trans->hw_rev = iwl_read32(trans, CSR_HW_REV);
trans->hw_id = (pdev->device << 16) + pdev->subsystem_device;
snprintf(trans->hw_id_str, sizeof(trans->hw_id_str),
@@ -1826,8 +1888,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
goto out_pci_disable_msi;
}
trans_pcie->inta_mask = CSR_INI_SET_MASK;
if (iwl_pcie_alloc_ict(trans))
goto out_free_cmd_pool;
@@ -1839,6 +1899,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
goto out_free_ict;
}
trans_pcie->inta_mask = CSR_INI_SET_MASK;
return trans;
out_free_ict:
+65 -66
View File
@@ -70,20 +70,20 @@ static int iwl_queue_space(const struct iwl_queue *q)
/*
* To avoid ambiguity between empty and completely full queues, there
* should always be less than q->n_bd elements in the queue.
* If q->n_window is smaller than q->n_bd, there is no need to reserve
* any queue entries for this purpose.
* should always be less than TFD_QUEUE_SIZE_MAX elements in the queue.
* If q->n_window is smaller than TFD_QUEUE_SIZE_MAX, there is no need
* to reserve any queue entries for this purpose.
*/
if (q->n_window < q->n_bd)
if (q->n_window < TFD_QUEUE_SIZE_MAX)
max = q->n_window;
else
max = q->n_bd - 1;
max = TFD_QUEUE_SIZE_MAX - 1;
/*
* q->n_bd is a power of 2, so the following is equivalent to modulo by
* q->n_bd and is well defined for negative dividends.
* TFD_QUEUE_SIZE_MAX is a power of 2, so the following is equivalent to
* modulo by TFD_QUEUE_SIZE_MAX and is well defined.
*/
used = (q->write_ptr - q->read_ptr) & (q->n_bd - 1);
used = (q->write_ptr - q->read_ptr) & (TFD_QUEUE_SIZE_MAX - 1);
if (WARN_ON(used > max))
return 0;
@@ -94,17 +94,11 @@ static int iwl_queue_space(const struct iwl_queue *q)
/*
* iwl_queue_init - Initialize queue's high/low-water and read/write indexes
*/
static int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id)
static int iwl_queue_init(struct iwl_queue *q, int slots_num, u32 id)
{
q->n_bd = count;
q->n_window = slots_num;
q->id = id;
/* count must be power-of-two size, otherwise iwl_queue_inc_wrap
* and iwl_queue_dec_wrap are broken. */
if (WARN_ON(!is_power_of_2(count)))
return -EINVAL;
/* slots_num must be power-of-two size, otherwise
* get_cmd_index is broken. */
if (WARN_ON(!is_power_of_2(slots_num)))
@@ -197,13 +191,13 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
IWL_ERR(trans,
"Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n",
i, active ? "" : "in", fifo, tbl_dw,
iwl_read_prph(trans,
SCD_QUEUE_RDPTR(i)) & (txq->q.n_bd - 1),
iwl_read_prph(trans, SCD_QUEUE_RDPTR(i)) &
(TFD_QUEUE_SIZE_MAX - 1),
iwl_read_prph(trans, SCD_QUEUE_WRPTR(i)));
}
for (i = q->read_ptr; i != q->write_ptr;
i = iwl_queue_inc_wrap(i, q->n_bd))
i = iwl_queue_inc_wrap(i))
IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
le32_to_cpu(txq->scratchbufs[i].scratch));
@@ -359,13 +353,6 @@ static inline dma_addr_t iwl_pcie_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
return addr;
}
static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
{
struct iwl_tfd_tb *tb = &tfd->tbs[idx];
return le16_to_cpu(tb->hi_n_len) >> 4;
}
static inline void iwl_pcie_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
dma_addr_t addr, u16 len)
{
@@ -425,13 +412,17 @@ static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)
{
struct iwl_tfd *tfd_tmp = txq->tfds;
/* rd_ptr is bounded by n_bd and idx is bounded by n_window */
/* rd_ptr is bounded by TFD_QUEUE_SIZE_MAX and
* idx is bounded by n_window
*/
int rd_ptr = txq->q.read_ptr;
int idx = get_cmd_index(&txq->q, rd_ptr);
lockdep_assert_held(&txq->lock);
/* We have only q->n_window txq->entries, but we use q->n_bd tfds */
/* We have only q->n_window txq->entries, but we use
* TFD_QUEUE_SIZE_MAX tfds
*/
iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr]);
/* free SKB */
@@ -452,7 +443,7 @@ static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)
}
static int iwl_pcie_txq_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
dma_addr_t addr, u16 len, u8 reset)
dma_addr_t addr, u16 len, bool reset)
{
struct iwl_queue *q;
struct iwl_tfd *tfd, *tfd_tmp;
@@ -565,8 +556,7 @@ static int iwl_pcie_txq_init(struct iwl_trans *trans, struct iwl_txq *txq,
BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
/* Initialize queue's high/low-water marks, and head/tail indexes */
ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num,
txq_id);
ret = iwl_queue_init(&txq->q, slots_num, txq_id);
if (ret)
return ret;
@@ -591,15 +581,12 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
struct iwl_txq *txq = &trans_pcie->txq[txq_id];
struct iwl_queue *q = &txq->q;
if (!q->n_bd)
return;
spin_lock_bh(&txq->lock);
while (q->write_ptr != q->read_ptr) {
IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n",
txq_id, q->read_ptr);
iwl_pcie_txq_free_tfd(trans, txq);
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr);
}
txq->active = false;
spin_unlock_bh(&txq->lock);
@@ -636,10 +623,12 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
}
/* De-alloc circular buffer of TFDs */
if (txq->q.n_bd) {
dma_free_coherent(dev, sizeof(struct iwl_tfd) *
txq->q.n_bd, txq->tfds, txq->q.dma_addr);
if (txq->tfds) {
dma_free_coherent(dev,
sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX,
txq->tfds, txq->q.dma_addr);
txq->q.dma_addr = 0;
txq->tfds = NULL;
dma_free_coherent(dev,
sizeof(*txq->scratchbufs) * txq->q.n_window,
@@ -948,8 +937,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *txq = &trans_pcie->txq[txq_id];
/* n_bd is usually 256 => n_bd - 1 = 0xff */
int tfd_num = ssn & (txq->q.n_bd - 1);
int tfd_num = ssn & (TFD_QUEUE_SIZE_MAX - 1);
struct iwl_queue *q = &txq->q;
int last_to_free;
@@ -973,12 +961,12 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
/*Since we free until index _not_ inclusive, the one before index is
* the last we will free. This one must be used */
last_to_free = iwl_queue_dec_wrap(tfd_num, q->n_bd);
last_to_free = iwl_queue_dec_wrap(tfd_num);
if (!iwl_queue_used(q, last_to_free)) {
IWL_ERR(trans,
"%s: Read index for DMA queue txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n",
__func__, txq_id, last_to_free, q->n_bd,
__func__, txq_id, last_to_free, TFD_QUEUE_SIZE_MAX,
q->write_ptr, q->read_ptr);
goto out;
}
@@ -988,7 +976,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
for (;
q->read_ptr != tfd_num;
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr)) {
if (WARN_ON_ONCE(txq->entries[txq->q.read_ptr].skb == NULL))
continue;
@@ -1027,16 +1015,16 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
lockdep_assert_held(&txq->lock);
if ((idx >= q->n_bd) || (!iwl_queue_used(q, idx))) {
if ((idx >= TFD_QUEUE_SIZE_MAX) || (!iwl_queue_used(q, idx))) {
IWL_ERR(trans,
"%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n",
__func__, txq_id, idx, q->n_bd,
__func__, txq_id, idx, TFD_QUEUE_SIZE_MAX,
q->write_ptr, q->read_ptr);
return;
}
for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
for (idx = iwl_queue_inc_wrap(idx); q->read_ptr != idx;
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr)) {
if (nfreed++ > 0) {
IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
@@ -1327,27 +1315,38 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
cmd_pos = offsetof(struct iwl_device_cmd, payload);
copy_size = sizeof(out_cmd->hdr);
for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
int copy = 0;
int copy;
if (!cmd->len[i])
continue;
/* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */
/* copy everything if not nocopy/dup */
if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
IWL_HCMD_DFL_DUP))) {
copy = cmd->len[i];
memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);
cmd_pos += copy;
copy_size += copy;
continue;
}
/*
* Otherwise we need at least IWL_HCMD_SCRATCHBUF_SIZE copied
* in total (for the scratchbuf handling), but copy up to what
* we can fit into the payload for debug dump purposes.
*/
copy = min_t(int, TFD_MAX_PAYLOAD_SIZE - cmd_pos, cmd->len[i]);
memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);
cmd_pos += copy;
/* However, treat copy_size the proper way, we need it below */
if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) {
copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size;
if (copy > cmd->len[i])
copy = cmd->len[i];
}
/* copy everything if not nocopy/dup */
if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
IWL_HCMD_DFL_DUP)))
copy = cmd->len[i];
if (copy) {
memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);
cmd_pos += copy;
copy_size += copy;
}
}
@@ -1363,7 +1362,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size);
iwl_pcie_txq_build_tfd(trans, txq,
iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr),
scratch_size, 1);
scratch_size, true);
/* map first command fragment, if any remains */
if (copy_size > scratch_size) {
@@ -1379,7 +1378,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
}
iwl_pcie_txq_build_tfd(trans, txq, phys_addr,
copy_size - scratch_size, 0);
copy_size - scratch_size, false);
}
/* map the remaining (adjusted) nocopy/dup fragments */
@@ -1402,7 +1401,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
goto out;
}
iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0);
iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], false);
}
out_meta->flags = cmd->flags;
@@ -1445,7 +1444,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
}
/* Increment and update queue's write index */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr);
iwl_pcie_txq_inc_wr_ptr(trans, txq);
spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
@@ -1740,7 +1739,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr,
IWL_HCMD_SCRATCHBUF_SIZE);
iwl_pcie_txq_build_tfd(trans, txq, tb0_phys,
IWL_HCMD_SCRATCHBUF_SIZE, 1);
IWL_HCMD_SCRATCHBUF_SIZE, true);
/* there must be data left over for TB1 or this code must be changed */
BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_HCMD_SCRATCHBUF_SIZE);
@@ -1750,7 +1749,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
tb1_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(trans->dev, tb1_phys)))
goto out_err;
iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, 0);
iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, false);
/*
* Set up TFD's third entry to point directly to remainder
@@ -1766,7 +1765,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
&txq->tfds[q->write_ptr]);
goto out_err;
}
iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, 0);
iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, false);
}
/* Set up entry for this TFD in Tx byte-count array */
@@ -1788,7 +1787,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
/* Tell device the write index *just past* this latest filled TFD */
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr);
if (!wait_write_ptr)
iwl_pcie_txq_inc_wr_ptr(trans, txq);
+4 -1
View File
@@ -1676,7 +1676,9 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
return 0;
}
static void mac80211_hwsim_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
static void mac80211_hwsim_flush(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u32 queues, bool drop)
{
/* Not implemented, queues only on kernel side */
}
@@ -2056,6 +2058,7 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
WIPHY_FLAG_AP_UAPSD |
WIPHY_FLAG_HAS_CHANNEL_SWITCH;
hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
/* ask mac80211 to reserve space for magic */
hw->vif_data_size = sizeof(struct hwsim_vif_priv);
+42
View File
@@ -749,3 +749,45 @@ void mwifiex_set_ba_params(struct mwifiex_private *priv)
return;
}
u8 mwifiex_get_sec_chan_offset(int chan)
{
u8 sec_offset;
switch (chan) {
case 36:
case 44:
case 52:
case 60:
case 100:
case 108:
case 116:
case 124:
case 132:
case 140:
case 149:
case 157:
sec_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
break;
case 40:
case 48:
case 56:
case 64:
case 104:
case 112:
case 120:
case 128:
case 136:
case 144:
case 153:
case 161:
sec_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
break;
case 165:
default:
sec_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
break;
}
return sec_offset;
}

Some files were not shown because too many files have changed in this diff Show More