Merge remote-tracking branch 'wireless-next/master' into ath-next
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
¶ms->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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)/../
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+26
@@ -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__ */
|
||||
@@ -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),
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)/../
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
******************************************************/
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user