提交 37320537 编写于 作者: D David S. Miller

Merge tag 'wireless-drivers-next-for-davem-2017-10-18' of...

Merge tag 'wireless-drivers-next-for-davem-2017-10-18' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Valo says:

====================
wireless-drivers-next patches for 4.15

The first pull request for 4.15, unusually late this time but still
relatively small. Also includes merge from wireless-drivers to fix
conflicts in iwlwifi.

Major changes:

rsi

* add P2P mode support

* sdio suspend and resume support

iwlwifi

* A fix and an addition for PCI devices for the A000 family

* Dump PCI registers when an error occurs, to make it easier to debug

rtlwifi

* add support for 64 bit DMA, enabled with a module parameter

* add module parameter to enable ASPM
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
......@@ -10,14 +10,15 @@ menuconfig BCMA
Bus driver for Broadcom specific Advanced Microcontroller Bus
Architecture.
if BCMA
# Support for Block-I/O. SELECT this from the driver that needs it.
config BCMA_BLOCKIO
bool
depends on BCMA
config BCMA_HOST_PCI_POSSIBLE
bool
depends on BCMA && PCI = y
depends on PCI = y
default y
config BCMA_HOST_PCI
......@@ -28,7 +29,6 @@ config BCMA_HOST_PCI
config BCMA_HOST_SOC
bool "Support for BCMA in a SoC"
depends on BCMA
help
Host interface for a Broadcom AIX bus directly mapped into
the memory. This only works with the Broadcom SoCs from the
......@@ -38,7 +38,7 @@ config BCMA_HOST_SOC
config BCMA_DRIVER_PCI
bool "BCMA Broadcom PCI core driver"
depends on BCMA && PCI
depends on PCI
default y
help
BCMA bus may have many versions of PCIe core. This driver
......@@ -54,13 +54,13 @@ config BCMA_DRIVER_PCI
config BCMA_DRIVER_PCI_HOSTMODE
bool "Driver for PCI core working in hostmode"
depends on BCMA && MIPS && BCMA_DRIVER_PCI
depends on MIPS && BCMA_DRIVER_PCI
help
PCI core hostmode operation (external PCI bus).
config BCMA_DRIVER_MIPS
bool "BCMA Broadcom MIPS core driver"
depends on BCMA && MIPS
depends on MIPS
help
Driver for the Broadcom MIPS core attached to Broadcom specific
Advanced Microcontroller Bus.
......@@ -91,7 +91,6 @@ config BCMA_NFLASH
config BCMA_DRIVER_GMAC_CMN
bool "BCMA Broadcom GBIT MAC COMMON core driver"
depends on BCMA
help
Driver for the Broadcom GBIT MAC COMMON core attached to Broadcom
specific Advanced Microcontroller Bus.
......@@ -100,7 +99,7 @@ config BCMA_DRIVER_GMAC_CMN
config BCMA_DRIVER_GPIO
bool "BCMA GPIO driver"
depends on BCMA && GPIOLIB
depends on GPIOLIB
select GPIOLIB_IRQCHIP if BCMA_HOST_SOC
help
Driver to provide access to the GPIO pins of the bcma bus.
......@@ -109,8 +108,9 @@ config BCMA_DRIVER_GPIO
config BCMA_DEBUG
bool "BCMA debugging"
depends on BCMA
help
This turns on additional debugging messages.
If unsure, say N
endif # BCMA
......@@ -184,10 +184,11 @@ static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
{
int i;
static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
printk(KERN_DEBUG KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
bcma_debug(dev->bus, "core 0x%04x, irq :", dev->id.id);
for (i = 0; i <= 6; i++)
printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
printk("\n");
pr_cont(" %s%s", irq_name[i], i == irq ? "*" : " ");
pr_cont("\n");
}
static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
......
......@@ -2297,7 +2297,7 @@ static u8 b43_gphy_aci_detect(struct b43_wldev *dev, u8 channel)
static u8 b43_gphy_aci_scan(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
u8 ret[13];
u8 ret[13] = { 0 };
unsigned int channel = phy->channel;
unsigned int i, j, start, end;
......
......@@ -119,7 +119,7 @@ static void b43_radio_2059_rcal(struct b43_wldev *dev)
/* Calibrate the internal RC oscillator? */
static void b43_radio_2057_rccal(struct b43_wldev *dev)
{
const u16 radio_values[3][2] = {
static const u16 radio_values[3][2] = {
{ 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 },
};
int i;
......@@ -154,7 +154,7 @@ static void b43_radio_2059_init_pre(struct b43_wldev *dev)
static void b43_radio_2059_init(struct b43_wldev *dev)
{
const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3 };
static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3 };
int i;
/* Prepare (reset?) radio */
......@@ -263,7 +263,7 @@ static void b43_phy_ht_reset_cca(struct b43_wldev *dev)
static void b43_phy_ht_zero_extg(struct b43_wldev *dev)
{
u8 i, j;
u16 base[] = { 0x40, 0x60, 0x80 };
static const u16 base[] = { 0x40, 0x60, 0x80 };
for (i = 0; i < ARRAY_SIZE(base); i++) {
for (j = 0; j < 4; j++)
......
......@@ -280,7 +280,7 @@ u8 b43legacy_radio_aci_detect(struct b43legacy_wldev *dev, u8 channel)
u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev)
{
struct b43legacy_phy *phy = &dev->phy;
u8 ret[13];
u8 ret[13] = { 0 };
unsigned int channel = phy->channel;
unsigned int i;
unsigned int j;
......
......@@ -257,11 +257,6 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), event->data,
min_t(u32, emsg.datalen, 64),
"event payload, len=%d\n", emsg.datalen);
if (emsg.datalen > event->datalen) {
brcmf_err("event invalid length header=%d, msg=%d\n",
event->datalen, emsg.datalen);
goto event_free;
}
/* special handling of interface event */
if (event->code == BRCMF_E_IF) {
......@@ -429,7 +424,8 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
if (code != BRCMF_E_IF && !fweh->evt_handler[code])
return;
if (datalen > BRCMF_DCMD_MAXLEN)
if (datalen > BRCMF_DCMD_MAXLEN ||
datalen + sizeof(*event_packet) > packet_len)
return;
if (in_interrupt())
......
......@@ -1853,7 +1853,6 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
struct afx_hdl *afx_hdl = &p2p->afx_hdl;
struct brcmf_cfg80211_vif *vif = ifp->vif;
struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
u16 chanspec = be16_to_cpu(rxframe->chanspec);
struct brcmu_chan ch;
u8 *mgmt_frame;
u32 mgmt_frame_len;
......@@ -1906,7 +1905,7 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
cfg80211_rx_mgmt(&vif->wdev, freq, 0, mgmt_frame, mgmt_frame_len, 0);
brcmf_dbg(INFO, "mgmt_frame_len (%d) , e->datalen (%d), chanspec (%04x), freq (%d)\n",
mgmt_frame_len, e->datalen, chanspec, freq);
mgmt_frame_len, e->datalen, ch.chspec, freq);
return 0;
}
......
......@@ -4144,10 +4144,8 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
init_waitqueue_head(&bus->dcmd_resp_wait);
/* Set up the watchdog timer */
init_timer(&bus->timer);
bus->timer.data = (unsigned long)bus;
bus->timer.function = brcmf_sdio_watchdog;
setup_timer(&bus->timer, brcmf_sdio_watchdog,
(unsigned long)bus);
/* Initialize watchdog thread */
init_completion(&bus->watchdog_wait);
bus->watchdog_tsk = kthread_run(brcmf_sdio_watchdog_thread,
......
......@@ -1916,7 +1916,7 @@ void wlc_phy_txpower_update_shm(struct brcms_phy *pi)
pi->hwpwr_txcur);
for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) {
const u8 ucode_ofdm_rates[] = {
static const u8 ucode_ofdm_rates[] = {
0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
};
offset = wlapi_bmac_rate_shm_offset(
......
......@@ -14764,8 +14764,8 @@ static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi)
}
static void
wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys,
u8 len)
wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, const u8 *events,
const u8 *dlys, u8 len)
{
u32 t1_offset, t2_offset;
u8 ctr;
......@@ -15240,16 +15240,16 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi)
static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi)
{
u16 currband;
s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 };
s8 *lna1_gain_db = NULL;
s8 *lna1_gain_db_2 = NULL;
s8 *lna2_gain_db = NULL;
s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 };
s8 *tia_gain_db;
s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 };
s8 *tia_gainbits;
u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f };
u16 *rfseq_init_gain;
static const s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 };
const s8 *lna1_gain_db = NULL;
const s8 *lna1_gain_db_2 = NULL;
const s8 *lna2_gain_db = NULL;
static const s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 };
const s8 *tia_gain_db;
static const s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 };
const s8 *tia_gainbits;
static const u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f };
const u16 *rfseq_init_gain;
u16 init_gaincode;
u16 clip1hi_gaincode;
u16 clip1md_gaincode = 0;
......@@ -15310,10 +15310,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi)
if ((freq <= 5080) || (freq == 5825)) {
s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 };
s8 lna1A_gain_db_2_rev7[] = {
11, 17, 22, 25};
s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
static const s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 };
static const s8 lna1A_gain_db_2_rev7[] = { 11, 17, 22, 25};
static const s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
crsminu_th = 0x3e;
lna1_gain_db = lna1A_gain_db_rev7;
......@@ -15321,10 +15320,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi)
lna2_gain_db = lna2A_gain_db_rev7;
} else if ((freq >= 5500) && (freq <= 5700)) {
s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 };
s8 lna1A_gain_db_2_rev7[] = {
12, 18, 22, 26};
s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
static const s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 };
static const s8 lna1A_gain_db_2_rev7[] = { 12, 18, 22, 26};
static const s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
crsminu_th = 0x45;
clip1md_gaincode_B = 0x14;
......@@ -15335,10 +15333,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi)
lna2_gain_db = lna2A_gain_db_rev7;
} else {
s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 };
s8 lna1A_gain_db_2_rev7[] = {
12, 18, 22, 26};
s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
static const s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 };
static const s8 lna1A_gain_db_2_rev7[] = { 12, 18, 22, 26};
static const s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
crsminu_th = 0x41;
lna1_gain_db = lna1A_gain_db_rev7;
......@@ -15450,65 +15447,65 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi)
NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
NPHY_RFSEQ_CMD_SET_HPF_BW
};
u8 rfseq_updategainu_dlys[] = { 10, 30, 1 };
s8 lna1G_gain_db[] = { 7, 11, 16, 23 };
s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 };
s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 };
s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 };
s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 };
s8 lna1A_gain_db[] = { 7, 11, 17, 23 };
s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 };
s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 };
s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 };
s8 *lna1_gain_db = NULL;
s8 lna2G_gain_db[] = { -5, 6, 10, 14 };
s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 };
s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 };
s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 };
s8 lna2A_gain_db[] = { -6, 2, 6, 10 };
s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 };
s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 };
s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 };
s8 *lna2_gain_db = NULL;
s8 tiaG_gain_db[] = {
static const u8 rfseq_updategainu_dlys[] = { 10, 30, 1 };
static const s8 lna1G_gain_db[] = { 7, 11, 16, 23 };
static const s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 };
static const s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 };
static const s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 };
static const s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 };
static const s8 lna1A_gain_db[] = { 7, 11, 17, 23 };
static const s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 };
static const s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 };
static const s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 };
const s8 *lna1_gain_db = NULL;
static const s8 lna2G_gain_db[] = { -5, 6, 10, 14 };
static const s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 };
static const s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 };
static const s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 };
static const s8 lna2A_gain_db[] = { -6, 2, 6, 10 };
static const s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 };
static const s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 };
static const s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 };
const s8 *lna2_gain_db = NULL;
static const s8 tiaG_gain_db[] = {
0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
s8 tiaA_gain_db[] = {
static const s8 tiaA_gain_db[] = {
0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 };
s8 tiaA_gain_db_rev4[] = {
static const s8 tiaA_gain_db_rev4[] = {
0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
s8 tiaA_gain_db_rev5[] = {
static const s8 tiaA_gain_db_rev5[] = {
0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
s8 tiaA_gain_db_rev6[] = {
static const s8 tiaA_gain_db_rev6[] = {
0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
s8 *tia_gain_db;
s8 tiaG_gainbits[] = {
const s8 *tia_gain_db;
static const s8 tiaG_gainbits[] = {
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
s8 tiaA_gainbits[] = {
static const s8 tiaA_gainbits[] = {
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 };
s8 tiaA_gainbits_rev4[] = {
static const s8 tiaA_gainbits_rev4[] = {
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
s8 tiaA_gainbits_rev5[] = {
static const s8 tiaA_gainbits_rev5[] = {
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
s8 tiaA_gainbits_rev6[] = {
static const s8 tiaA_gainbits_rev6[] = {
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
s8 *tia_gainbits;
s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 };
s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 };
u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f };
u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f };
u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f };
u16 rfseqG_init_gain_rev5_elna[] = {
const s8 *tia_gainbits;
static const s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 };
static const s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 };
static const u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f };
static const u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f };
static const u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f };
static const u16 rfseqG_init_gain_rev5_elna[] = {
0x013f, 0x013f, 0x013f, 0x013f };
u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f };
u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f };
u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f };
u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f };
u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f };
u16 rfseqA_init_gain_rev4_elna[] = {
static const u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f };
static const u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f };
static const u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f };
static const u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f };
static const u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f };
static const u16 rfseqA_init_gain_rev4_elna[] = {
0x314f, 0x314f, 0x314f, 0x314f };
u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f };
u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f };
u16 *rfseq_init_gain;
static const u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f };
static const u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f };
const u16 *rfseq_init_gain;
u16 initG_gaincode = 0x627e;
u16 initG_gaincode_rev4 = 0x527e;
u16 initG_gaincode_rev5 = 0x427e;
......@@ -15538,10 +15535,10 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi)
u16 clip1mdA_gaincode_rev6 = 0x2084;
u16 clip1md_gaincode = 0;
u16 clip1loG_gaincode = 0x0074;
u16 clip1loG_gaincode_rev5[] = {
static const u16 clip1loG_gaincode_rev5[] = {
0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c
};
u16 clip1loG_gaincode_rev6[] = {
static const u16 clip1loG_gaincode_rev6[] = {
0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e
};
u16 clip1loG_gaincode_rev6_224B0 = 0x1074;
......@@ -16066,7 +16063,7 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi)
static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
{
u8 rfseq_rx2tx_events[] = {
static const u8 rfseq_rx2tx_events[] = {
NPHY_RFSEQ_CMD_NOP,
NPHY_RFSEQ_CMD_RXG_FBW,
NPHY_RFSEQ_CMD_TR_SWITCH,
......@@ -16076,7 +16073,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
NPHY_RFSEQ_CMD_EXT_PA
};
u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 };
u8 rfseq_tx2rx_events[] = {
static const u8 rfseq_tx2rx_events[] = {
NPHY_RFSEQ_CMD_NOP,
NPHY_RFSEQ_CMD_EXT_PA,
NPHY_RFSEQ_CMD_TX_GAIN,
......@@ -16085,8 +16082,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
NPHY_RFSEQ_CMD_RXG_FBW,
NPHY_RFSEQ_CMD_CLR_HIQ_DIS
};
u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 };
u8 rfseq_tx2rx_events_rev3[] = {
static const u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 };
static const u8 rfseq_tx2rx_events_rev3[] = {
NPHY_REV3_RFSEQ_CMD_EXT_PA,
NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
NPHY_REV3_RFSEQ_CMD_TX_GAIN,
......@@ -16096,7 +16093,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
NPHY_REV3_RFSEQ_CMD_END
};
u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 };
static const u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 };
u8 rfseq_rx2tx_events_rev3[] = {
NPHY_REV3_RFSEQ_CMD_NOP,
NPHY_REV3_RFSEQ_CMD_RXG_FBW,
......@@ -16110,7 +16107,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
};
u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
u8 rfseq_rx2tx_events_rev3_ipa[] = {
static const u8 rfseq_rx2tx_events_rev3_ipa[] = {
NPHY_REV3_RFSEQ_CMD_NOP,
NPHY_REV3_RFSEQ_CMD_RXG_FBW,
NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
......@@ -16121,15 +16118,15 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
NPHY_REV3_RFSEQ_CMD_END
};
u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f };
static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
static const u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f };
s16 alpha0, alpha1, alpha2;
s16 beta0, beta1, beta2;
u32 leg_data_weights, ht_data_weights, nss1_data_weights,
stbc_data_weights;
u8 chan_freq_range = 0;
u16 dac_control = 0x0002;
static const u16 dac_control = 0x0002;
u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 };
u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 };
u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 };
......@@ -16139,8 +16136,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 };
u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 };
u16 *aux_adc_gain;
u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 };
u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 };
static const u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 };
static const u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 };
s32 min_nvar_val = 0x18d;
s32 min_nvar_offset_6mbps = 20;
u8 pdetrange;
......@@ -16151,9 +16148,9 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77;
u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77;
u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77;
u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 };
u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
static const u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 };
static const u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
static const u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
u16 ipalvlshift_3p3_war_en = 0;
u16 rccal_bcap_val, rccal_scap_val;
u16 rccal_tx20_11b_bcap = 0;
......@@ -24291,13 +24288,13 @@ static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core)
u16 bbmult;
u16 tblentry;
struct nphy_txiqcal_ladder ladder_lo[] = {
static const struct nphy_txiqcal_ladder ladder_lo[] = {
{3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
{25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5},
{25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7}
};
struct nphy_txiqcal_ladder ladder_iq[] = {
static const struct nphy_txiqcal_ladder ladder_iq[] = {
{3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
{25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1},
{100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7}
......@@ -25773,67 +25770,67 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
u16 cal_gain[2];
struct nphy_iqcal_params cal_params[2];
u32 tbl_len;
void *tbl_ptr;
const void *tbl_ptr;
bool ladder_updated[2];
u8 mphase_cal_lastphase = 0;
int bcmerror = 0;
bool phyhang_avoid_state = false;
u16 tbl_tx_iqlo_cal_loft_ladder_20[] = {
static const u16 tbl_tx_iqlo_cal_loft_ladder_20[] = {
0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901,
0x1902,
0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607,
0x6407
};
u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = {
static const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = {
0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400,
0x3200,
0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406,
0x6407
};
u16 tbl_tx_iqlo_cal_loft_ladder_40[] = {
static const u16 tbl_tx_iqlo_cal_loft_ladder_40[] = {
0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201,
0x1202,
0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207,
0x4707
};
u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = {
static const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = {
0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900,
0x2300,
0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706,
0x4707
};
u16 tbl_tx_iqlo_cal_startcoefs[] = {
static const u16 tbl_tx_iqlo_cal_startcoefs[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000
};
u16 tbl_tx_iqlo_cal_cmds_fullcal[] = {
static const u16 tbl_tx_iqlo_cal_cmds_fullcal[] = {
0x8123, 0x8264, 0x8086, 0x8245, 0x8056,
0x9123, 0x9264, 0x9086, 0x9245, 0x9056
};
u16 tbl_tx_iqlo_cal_cmds_recal[] = {
static const u16 tbl_tx_iqlo_cal_cmds_recal[] = {
0x8101, 0x8253, 0x8053, 0x8234, 0x8034,
0x9101, 0x9253, 0x9053, 0x9234, 0x9034
};
u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = {
static const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000
};
u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
static const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234,
0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234
};
u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = {
static const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = {
0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223,
0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223
};
......
......@@ -1480,7 +1480,7 @@ il4965_get_ac_from_tid(u16 tid)
static inline int
il4965_get_fifo_from_tid(u16 tid)
{
const u8 ac_to_fifo[] = {
static const u8 ac_to_fifo[] = {
IL_TX_FIFO_VO,
IL_TX_FIFO_VI,
IL_TX_FIFO_BE,
......
......@@ -13,6 +13,7 @@ iwlwifi-objs += iwl-trans.o
iwlwifi-objs += fw/notif-wait.o
iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o fw/dbg.o
iwlwifi-$(CONFIG_IWLMVM) += fw/common_rx.o fw/nvm.o
iwlwifi-$(CONFIG_ACPI) += fw/acpi.o
iwlwifi-objs += $(iwlwifi-m)
......
......@@ -309,6 +309,7 @@ const struct iwl_cfg iwl3168_2ac_cfg = {
.nvm_calib_ver = IWL3168_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
.nvm_type = IWL_NVM_SDP,
};
const struct iwl_cfg iwl7265_2ac_cfg = {
......
......@@ -164,7 +164,7 @@ static const struct iwl_tt_params iwl8000_tt_params = {
.default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C, \
.thermal_params = &iwl8000_tt_params, \
.apmg_not_supported = true, \
.ext_nvm = true, \
.nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true
#define IWL_DEVICE_8000 \
......
......@@ -148,7 +148,7 @@ static const struct iwl_tt_params iwl9000_tt_params = {
.vht_mu_mimo_supported = true, \
.mac_addr_from_csr = true, \
.rf_id = true, \
.ext_nvm = true, \
.nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true
const struct iwl_cfg iwl9160_2ac_cfg = {
......
......@@ -133,78 +133,79 @@ static const struct iwl_ht_params iwl_a000_ht_params = {
.use_tfh = true, \
.rf_id = true, \
.gen2 = true, \
.ext_nvm = true, \
.dbgc_supported = true
.nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true, \
.tx_cmd_queue_size = 32
const struct iwl_cfg iwla000_2ac_cfg_hr = {
.name = "Intel(R) Dual Band Wireless AC a000",
.fw_name_pre = IWL_A000_HR_FW_PRE,
IWL_DEVICE_A000,
.ht_params = &iwl_a000_ht_params,
.nvm_ver = IWL_A000_NVM_VERSION,
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
.name = "Intel(R) Dual Band Wireless AC a000",
.fw_name_pre = IWL_A000_HR_FW_PRE,
IWL_DEVICE_A000,
.ht_params = &iwl_a000_ht_params,
.nvm_ver = IWL_A000_NVM_VERSION,
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
};
const struct iwl_cfg iwla000_2ac_cfg_hr_cdb = {
.name = "Intel(R) Dual Band Wireless AC a000",
.fw_name_pre = IWL_A000_HR_CDB_FW_PRE,
IWL_DEVICE_A000,
.ht_params = &iwl_a000_ht_params,
.nvm_ver = IWL_A000_NVM_VERSION,
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
.cdb = true,
.name = "Intel(R) Dual Band Wireless AC a000",
.fw_name_pre = IWL_A000_HR_CDB_FW_PRE,
IWL_DEVICE_A000,
.ht_params = &iwl_a000_ht_params,
.nvm_ver = IWL_A000_NVM_VERSION,
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
.cdb = true,
};
const struct iwl_cfg iwla000_2ac_cfg_jf = {
.name = "Intel(R) Dual Band Wireless AC a000",
.fw_name_pre = IWL_A000_JF_FW_PRE,
IWL_DEVICE_A000,
.ht_params = &iwl_a000_ht_params,
.nvm_ver = IWL_A000_NVM_VERSION,
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
.name = "Intel(R) Dual Band Wireless AC a000",
.fw_name_pre = IWL_A000_JF_FW_PRE,
IWL_DEVICE_A000,
.ht_params = &iwl_a000_ht_params,
.nvm_ver = IWL_A000_NVM_VERSION,
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
};
const struct iwl_cfg iwla000_2ax_cfg_hr = {
.name = "Intel(R) Dual Band Wireless AX a000",
.fw_name_pre = IWL_A000_HR_FW_PRE,
IWL_DEVICE_A000,
.ht_params = &iwl_a000_ht_params,
.nvm_ver = IWL_A000_NVM_VERSION,
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
.name = "Intel(R) Dual Band Wireless AX a000",
.fw_name_pre = IWL_A000_HR_FW_PRE,
IWL_DEVICE_A000,
.ht_params = &iwl_a000_ht_params,
.nvm_ver = IWL_A000_NVM_VERSION,
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
};
const struct iwl_cfg iwla000_2ax_cfg_qnj_hr_f0 = {
.name = "Intel(R) Dual Band Wireless AX a000",
.fw_name_pre = IWL_A000_HR_F0_FW_PRE,
IWL_DEVICE_A000,
.ht_params = &iwl_a000_ht_params,
.nvm_ver = IWL_A000_NVM_VERSION,
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
.name = "Intel(R) Dual Band Wireless AX a000",
.fw_name_pre = IWL_A000_HR_F0_FW_PRE,
IWL_DEVICE_A000,
.ht_params = &iwl_a000_ht_params,
.nvm_ver = IWL_A000_NVM_VERSION,
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
};
const struct iwl_cfg iwla000_2ax_cfg_qnj_jf_b0 = {
.name = "Intel(R) Dual Band Wireless AX a000",
.fw_name_pre = IWL_A000_JF_B0_FW_PRE,
IWL_DEVICE_A000,
.ht_params = &iwl_a000_ht_params,
.nvm_ver = IWL_A000_NVM_VERSION,
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
.name = "Intel(R) Dual Band Wireless AX a000",
.fw_name_pre = IWL_A000_JF_B0_FW_PRE,
IWL_DEVICE_A000,
.ht_params = &iwl_a000_ht_params,
.nvm_ver = IWL_A000_NVM_VERSION,
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
};
const struct iwl_cfg iwla000_2ax_cfg_qnj_hr_a0 = {
.name = "Intel(R) Dual Band Wireless AX a000",
.fw_name_pre = IWL_A000_HR_A0_FW_PRE,
IWL_DEVICE_A000,
.ht_params = &iwl_a000_ht_params,
.nvm_ver = IWL_A000_NVM_VERSION,
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
.name = "Intel(R) Dual Band Wireless AX a000",
.fw_name_pre = IWL_A000_HR_A0_FW_PRE,
IWL_DEVICE_A000,
.ht_params = &iwl_a000_ht_params,
.nvm_ver = IWL_A000_NVM_VERSION,
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
};
MODULE_FIRMWARE(IWL_A000_HR_MODULE_FIRMWARE(IWL_A000_UCODE_API_MAX));
......
/******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program;
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include "iwl-drv.h"
#include "iwl-debug.h"
#include "acpi.h"
void *iwl_acpi_get_object(struct device *dev, acpi_string method)
{
acpi_handle root_handle;
acpi_handle handle;
struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
root_handle = ACPI_HANDLE(dev);
if (!root_handle) {
IWL_DEBUG_DEV_RADIO(dev,
"Could not retrieve root port ACPI handle\n");
return ERR_PTR(-ENOENT);
}
/* Get the method's handle */
status = acpi_get_handle(root_handle, method, &handle);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_DEV_RADIO(dev, "%s method not found\n", method);
return ERR_PTR(-ENOENT);
}
/* Call the method with no arguments */
status = acpi_evaluate_object(handle, NULL, NULL, &buf);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_DEV_RADIO(dev, "%s invocation failed (0x%x)\n",
method, status);
return ERR_PTR(-ENOENT);
}
return buf.pointer;
}
IWL_EXPORT_SYMBOL(iwl_acpi_get_object);
union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
union acpi_object *data,
int data_size)
{
int i;
union acpi_object *wifi_pkg;
/*
* We need at least one entry in the wifi package that
* describes the domain, and one more entry, otherwise there's
* no point in reading it.
*/
if (WARN_ON_ONCE(data_size < 2))
return ERR_PTR(-EINVAL);
/*
* We need at least two packages, one for the revision and one
* for the data itself. Also check that the revision is valid
* (i.e. it is an integer set to 0).
*/
if (data->type != ACPI_TYPE_PACKAGE ||
data->package.count < 2 ||
data->package.elements[0].type != ACPI_TYPE_INTEGER ||
data->package.elements[0].integer.value != 0) {
IWL_DEBUG_DEV_RADIO(dev, "Unsupported packages structure\n");
return ERR_PTR(-EINVAL);
}
/* loop through all the packages to find the one for WiFi */
for (i = 1; i < data->package.count; i++) {
union acpi_object *domain;
wifi_pkg = &data->package.elements[i];
/* skip entries that are not a package with the right size */
if (wifi_pkg->type != ACPI_TYPE_PACKAGE ||
wifi_pkg->package.count != data_size)
continue;
domain = &wifi_pkg->package.elements[0];
if (domain->type == ACPI_TYPE_INTEGER &&
domain->integer.value == ACPI_WIFI_DOMAIN)
goto found;
}
return ERR_PTR(-ENOENT);
found:
return wifi_pkg;
}
IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg);
int iwl_acpi_get_mcc(struct device *dev, char *mcc)
{
union acpi_object *wifi_pkg, *data;
u32 mcc_val;
int ret;
data = iwl_acpi_get_object(dev, ACPI_WRDD_METHOD);
if (IS_ERR(data))
return PTR_ERR(data);
wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_WRDD_WIFI_DATA_SIZE);
if (IS_ERR(wifi_pkg)) {
ret = PTR_ERR(wifi_pkg);
goto out_free;
}
if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
ret = -EINVAL;
goto out_free;
}
mcc_val = wifi_pkg->package.elements[1].integer.value;
mcc[0] = (mcc_val >> 8) & 0xff;
mcc[1] = mcc_val & 0xff;
mcc[2] = '\0';
ret = 0;
out_free:
kfree(data);
return ret;
}
IWL_EXPORT_SYMBOL(iwl_acpi_get_mcc);
u64 iwl_acpi_get_pwr_limit(struct device *dev)
{
union acpi_object *data, *wifi_pkg;
u64 dflt_pwr_limit;
data = iwl_acpi_get_object(dev, ACPI_SPLC_METHOD);
if (IS_ERR(data)) {
dflt_pwr_limit = 0;
goto out;
}
wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data,
ACPI_SPLC_WIFI_DATA_SIZE);
if (IS_ERR(wifi_pkg) ||
wifi_pkg->package.elements[1].integer.value != ACPI_TYPE_INTEGER) {
dflt_pwr_limit = 0;
goto out_free;
}
dflt_pwr_limit = wifi_pkg->package.elements[1].integer.value;
out_free:
kfree(data);
out:
return dflt_pwr_limit;
}
IWL_EXPORT_SYMBOL(iwl_acpi_get_pwr_limit);
/******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program;
*
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#ifndef __iwl_fw_acpi__
#define __iwl_fw_acpi__
#include <linux/acpi.h>
#define ACPI_WRDS_METHOD "WRDS"
#define ACPI_EWRD_METHOD "EWRD"
#define ACPI_WGDS_METHOD "WGDS"
#define ACPI_WRDD_METHOD "WRDD"
#define ACPI_SPLC_METHOD "SPLC"
#define ACPI_WIFI_DOMAIN (0x07)
#define ACPI_SAR_TABLE_SIZE 10
#define ACPI_SAR_PROFILE_NUM 4
#define ACPI_GEO_TABLE_SIZE 6
#define ACPI_NUM_GEO_PROFILES 3
#define ACPI_GEO_PER_CHAIN_SIZE 3
#define ACPI_SAR_NUM_CHAIN_LIMITS 2
#define ACPI_SAR_NUM_SUB_BANDS 5
#define ACPI_WRDS_WIFI_DATA_SIZE (ACPI_SAR_TABLE_SIZE + 2)
#define ACPI_EWRD_WIFI_DATA_SIZE ((ACPI_SAR_PROFILE_NUM - 1) * \
ACPI_SAR_TABLE_SIZE + 3)
#define ACPI_WGDS_WIFI_DATA_SIZE 18
#define ACPI_WRDD_WIFI_DATA_SIZE 2
#define ACPI_SPLC_WIFI_DATA_SIZE 2
#define ACPI_WGDS_NUM_BANDS 2
#define ACPI_WGDS_TABLE_SIZE 3
#ifdef CONFIG_ACPI
void *iwl_acpi_get_object(struct device *dev, acpi_string method);
union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
union acpi_object *data,
int data_size);
/**
* iwl_acpi_get_mcc - read MCC from ACPI, if available
*
* @dev: the struct device
* @mcc: output buffer (3 bytes) that will get the MCC
*
* This function tries to read the current MCC from ACPI if available.
*/
int iwl_acpi_get_mcc(struct device *dev, char *mcc);
u64 iwl_acpi_get_pwr_limit(struct device *dev);
#else /* CONFIG_ACPI */
static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method)
{
return ERR_PTR(-ENOENT);
}
static inline union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
union acpi_object *data,
int data_size)
{
return ERR_PTR(-ENOENT);
}
static inline int iwl_acpi_get_mcc(struct device *dev, char *mcc)
{
return -ENOENT;
}
static inline u64 iwl_acpi_get_pwr_limit(struct device *dev)
{
return 0;
}
#endif /* CONFIG_ACPI */
#endif /* __iwl_fw_acpi__ */
......@@ -116,14 +116,14 @@ struct iwl_binding_cmd {
#define IWL_MVM_MAX_QUOTA 128
/**
* struct iwl_time_quota_data - configuration of time quota per binding
* struct iwl_time_quota_data_v1 - configuration of time quota per binding
* @id_and_color: ID and color of the relevant Binding,
* &enum iwl_ctxt_id_and_color
* @quota: absolute time quota in TU. The scheduler will try to divide the
* remainig quota (after Time Events) according to this quota.
* @max_duration: max uninterrupted context duration in TU
*/
struct iwl_time_quota_data {
struct iwl_time_quota_data_v1 {
__le32 id_and_color;
__le32 quota;
__le32 max_duration;
......@@ -137,8 +137,43 @@ struct iwl_time_quota_data {
* essentially zero.
* On CDB the fourth one is a regular binding.
*/
struct iwl_time_quota_cmd_v1 {
struct iwl_time_quota_data_v1 quotas[MAX_BINDINGS];
} __packed; /* TIME_QUOTA_ALLOCATION_CMD_API_S_VER_1 */
enum iwl_quota_low_latency {
IWL_QUOTA_LOW_LATENCY_NONE = 0,
IWL_QUOTA_LOW_LATENCY_TX = BIT(0),
IWL_QUOTA_LOW_LATENCY_RX = BIT(1),
IWL_QUOTA_LOW_LATENCY_TX_RX =
IWL_QUOTA_LOW_LATENCY_TX | IWL_QUOTA_LOW_LATENCY_RX,
};
/**
* struct iwl_time_quota_data - configuration of time quota per binding
* @id_and_color: ID and color of the relevant Binding.
* @quota: absolute time quota in TU. The scheduler will try to divide the
* remainig quota (after Time Events) according to this quota.
* @max_duration: max uninterrupted context duration in TU
* @low_latency: low latency status, &enum iwl_quota_low_latency
*/
struct iwl_time_quota_data {
__le32 id_and_color;
__le32 quota;
__le32 max_duration;
__le32 low_latency;
} __packed; /* TIME_QUOTA_DATA_API_S_VER_2 */
/**
* struct iwl_time_quota_cmd - configuration of time quota between bindings
* ( TIME_QUOTA_CMD = 0x2c )
* Note: on non-CDB the fourth one is the auxilary mac and is essentially zero.
* On CDB the fourth one is a regular binding.
*
* @quotas: allocations per binding
*/
struct iwl_time_quota_cmd {
struct iwl_time_quota_data quotas[MAX_BINDINGS];
} __packed; /* TIME_QUOTA_ALLOCATION_CMD_API_S_VER_1 */
} __packed; /* TIME_QUOTA_ALLOCATION_CMD_API_S_VER_2 */
#endif /* __iwl_fw_api_binding_h__ */
......@@ -504,6 +504,7 @@ enum iwl_legacy_cmds {
/**
* @MARKER_CMD: trace marker command, uses &struct iwl_mvm_marker
* with &struct iwl_mvm_marker_rsp
*/
MARKER_CMD = 0xcb,
......
......@@ -278,6 +278,15 @@ struct iwl_mvm_marker {
__le32 metadata[0];
} __packed; /* MARKER_API_S_VER_1 */
/**
* struct iwl_mvm_marker_rsp - Response to marker cmd
*
* @gp2: The gp2 clock value in the FW
*/
struct iwl_mvm_marker_rsp {
__le32 gp2;
} __packed;
/* Operation types for the debug mem access */
enum {
DEBUG_MEM_OP_READ = 0,
......
......@@ -67,79 +67,12 @@
* enum iwl_mac_conf_subcmd_ids - mac configuration command IDs
*/
enum iwl_mac_conf_subcmd_ids {
/**
* @LINK_QUALITY_MEASUREMENT_CMD: &struct iwl_link_qual_msrmnt_cmd
*/
LINK_QUALITY_MEASUREMENT_CMD = 0x1,
/**
* @LINK_QUALITY_MEASUREMENT_COMPLETE_NOTIF:
* &struct iwl_link_qual_msrmnt_notif
*/
LINK_QUALITY_MEASUREMENT_COMPLETE_NOTIF = 0xFE,
/**
* @CHANNEL_SWITCH_NOA_NOTIF: &struct iwl_channel_switch_noa_notif
*/
CHANNEL_SWITCH_NOA_NOTIF = 0xFF,
};
#define LQM_NUMBER_OF_STATIONS_IN_REPORT 16
enum iwl_lqm_cmd_operatrions {
LQM_CMD_OPERATION_START_MEASUREMENT = 0x01,
LQM_CMD_OPERATION_STOP_MEASUREMENT = 0x02,
};
enum iwl_lqm_status {
LQM_STATUS_SUCCESS = 0,
LQM_STATUS_TIMEOUT = 1,
LQM_STATUS_ABORT = 2,
};
/**
* struct iwl_link_qual_msrmnt_cmd - Link Quality Measurement command
* @cmd_operation: command operation to be performed (start or stop)
* as defined above.
* @mac_id: MAC ID the measurement applies to.
* @measurement_time: time of the total measurement to be performed, in uSec.
* @timeout: maximum time allowed until a response is sent, in uSec.
*/
struct iwl_link_qual_msrmnt_cmd {
__le32 cmd_operation;
__le32 mac_id;
__le32 measurement_time;
__le32 timeout;
} __packed /* LQM_CMD_API_S_VER_1 */;
/**
* struct iwl_link_qual_msrmnt_notif - Link Quality Measurement notification
*
* @frequent_stations_air_time: an array containing the total air time
* (in uSec) used by the most frequently transmitting stations.
* @number_of_stations: the number of uniqe stations included in the array
* (a number between 0 to 16)
* @total_air_time_other_stations: the total air time (uSec) used by all the
* stations which are not included in the above report.
* @time_in_measurement_window: the total time in uSec in which a measurement
* took place.
* @tx_frame_dropped: the number of TX frames dropped due to retry limit during
* measurement
* @mac_id: MAC ID the measurement applies to.
* @status: return status. may be one of the LQM_STATUS_* defined above.
* @reserved: reserved.
*/
struct iwl_link_qual_msrmnt_notif {
__le32 frequent_stations_air_time[LQM_NUMBER_OF_STATIONS_IN_REPORT];
__le32 number_of_stations;
__le32 total_air_time_other_stations;
__le32 time_in_measurement_window;
__le32 tx_frame_dropped;
__le32 mac_id;
__le32 status;
u8 reserved[12];
} __packed; /* LQM_MEASUREMENT_COMPLETE_NTF_API_S_VER1 */
/**
* struct iwl_channel_switch_noa_notif - Channel switch NOA notification
*
......
......@@ -108,6 +108,7 @@ enum iwl_nvm_access_target {
* @NVM_SECTION_TYPE_REGULATORY: regulatory section
* @NVM_SECTION_TYPE_CALIBRATION: calibration section
* @NVM_SECTION_TYPE_PRODUCTION: production section
* @NVM_SECTION_TYPE_REGULATORY_SDP: regulatory section used by 3168 series
* @NVM_SECTION_TYPE_MAC_OVERRIDE: MAC override section
* @NVM_SECTION_TYPE_PHY_SKU: PHY SKU section
* @NVM_MAX_NUM_SECTIONS: number of sections
......@@ -117,6 +118,7 @@ enum iwl_nvm_section_type {
NVM_SECTION_TYPE_REGULATORY = 3,
NVM_SECTION_TYPE_CALIBRATION = 4,
NVM_SECTION_TYPE_PRODUCTION = 5,
NVM_SECTION_TYPE_REGULATORY_SDP = 8,
NVM_SECTION_TYPE_MAC_OVERRIDE = 11,
NVM_SECTION_TYPE_PHY_SKU = 12,
NVM_MAX_NUM_SECTIONS = 13,
......
......@@ -357,8 +357,7 @@ struct iwl_dev_tx_power_cmd {
u8 reserved[3];
} __packed; /* TX_REDUCED_POWER_API_S_VER_4 */
#define IWL_NUM_GEO_PROFILES 3
#define IWL_GEO_PER_CHAIN_SIZE 3
#define IWL_NUM_GEO_PROFILES 3
/**
* enum iwl_geo_per_chain_offset_operation - type of operation
......
......@@ -68,9 +68,6 @@
* @STA_FLG_REDUCED_TX_PWR_DATA: reduced TX power (data frames)
* @STA_FLG_DISABLE_TX: set if TX should be disabled
* @STA_FLG_PS: set if STA is in Power Save
* @STA_FLG_INVALID: set if STA is invalid
* @STA_FLG_DLP_EN: Direct Link Protocol is enabled
* @STA_FLG_SET_ALL_KEYS: the current key applies to all key IDs
* @STA_FLG_DRAIN_FLOW: drain flow
* @STA_FLG_PAN: STA is for PAN interface
* @STA_FLG_CLASS_AUTH: station is authenticated
......@@ -100,7 +97,6 @@
* @STA_FLG_MIMO_EN_SISO: no support for MIMO
* @STA_FLG_MIMO_EN_MIMO2: 2 streams supported
* @STA_FLG_MIMO_EN_MIMO3: 3 streams supported
* @STA_FLG_MFP_EN: Management Frame Protection
* @STA_FLG_AGG_MPDU_DENS_MSK: A-MPDU density (mask)
* @STA_FLG_AGG_MPDU_DENS_SHIFT: A-MPDU density (bit shift)
* @STA_FLG_AGG_MPDU_DENS_2US: A-MPDU density (2 usec gap)
......
......@@ -93,6 +93,8 @@ static void iwl_read_radio_regs(struct iwl_fw_runtime *fwrt,
unsigned long flags;
int i;
IWL_DEBUG_INFO(fwrt, "WRT radio registers dump\n");
if (!iwl_trans_grab_nic_access(fwrt->trans, &flags))
return;
......@@ -233,6 +235,8 @@ static void iwl_fw_dump_fifos(struct iwl_fw_runtime *fwrt,
unsigned long flags;
int i, j;
IWL_DEBUG_INFO(fwrt, "WRT FIFO dump\n");
if (!iwl_trans_grab_nic_access(fwrt->trans, &flags))
return;
......@@ -476,6 +480,8 @@ static void iwl_dump_prph(struct iwl_trans *trans,
unsigned long flags;
u32 i;
IWL_DEBUG_INFO(trans, "WRT PRPH dump\n");
if (!iwl_trans_grab_nic_access(trans, &flags))
return;
......@@ -559,6 +565,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
bool monitor_dump_only = false;
int i;
IWL_DEBUG_INFO(fwrt, "WRT dump start\n");
/* there's no point in fw dump if the bus is dead */
if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) {
IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n");
......@@ -816,6 +824,9 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
dump_mem->type = fw_dbg_mem[i].data_type;
dump_mem->offset = cpu_to_le32(ofs);
IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n",
dump_mem->type);
switch (dump_mem->type & cpu_to_le32(FW_DBG_MEM_TYPE_MASK)) {
case cpu_to_le32(FW_DBG_MEM_TYPE_REGULAR):
iwl_trans_read_mem_bytes(fwrt->trans, ofs,
......@@ -841,6 +852,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
}
if (smem_len) {
IWL_DEBUG_INFO(fwrt, "WRT SMEM dump\n");
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
dump_data->len = cpu_to_le32(smem_len + sizeof(*dump_mem));
dump_mem = (void *)dump_data->data;
......@@ -853,6 +865,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
}
if (sram2_len) {
IWL_DEBUG_INFO(fwrt, "WRT SRAM dump\n");
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
dump_data->len = cpu_to_le32(sram2_len + sizeof(*dump_mem));
dump_mem = (void *)dump_data->data;
......@@ -868,6 +881,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
if (!fwrt->trans->cfg->gen2 &&
fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size &&
fwrt->fw_paging_db[0].fw_paging_block) {
IWL_DEBUG_INFO(fwrt, "WRT paging dump\n");
for (i = 1; i < fwrt->num_of_paging_blk + 1; i++) {
struct iwl_fw_error_dump_paging *paging;
struct page *pages =
......@@ -930,6 +944,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
iwl_fw_free_dump_desc(fwrt);
fwrt->dump.trig = NULL;
clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status);
IWL_DEBUG_INFO(fwrt, "WRT dump done\n");
}
IWL_EXPORT_SYMBOL(iwl_fw_error_dump);
......@@ -1086,7 +1101,7 @@ void iwl_fw_error_dump_wk(struct work_struct *work)
if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
/* stop recording */
iwl_set_bits_prph(fwrt->trans, MON_BUFF_SAMPLE_CTL, 0x100);
iwl_fw_dbg_stop_recording(fwrt);
iwl_fw_error_dump(fwrt);
......@@ -1104,10 +1119,7 @@ void iwl_fw_error_dump_wk(struct work_struct *work)
u32 in_sample = iwl_read_prph(fwrt->trans, DBGC_IN_SAMPLE);
u32 out_ctrl = iwl_read_prph(fwrt->trans, DBGC_OUT_CTRL);
/* stop recording */
iwl_write_prph(fwrt->trans, DBGC_IN_SAMPLE, 0);
udelay(100);
iwl_write_prph(fwrt->trans, DBGC_OUT_CTRL, 0);
iwl_fw_dbg_stop_recording(fwrt);
/* wait before we collect the data till the DBGC stop */
udelay(500);
......
......@@ -68,6 +68,8 @@
#include <linux/workqueue.h>
#include <net/cfg80211.h>
#include "runtime.h"
#include "iwl-prph.h"
#include "iwl-io.h"
#include "file.h"
#include "error-dump.h"
......@@ -194,8 +196,21 @@ _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt,
iwl_fw_dbg_get_trigger((fwrt)->fw,\
(trig)))
static inline void iwl_fw_dbg_stop_recording(struct iwl_fw_runtime *fwrt)
{
if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_set_bits_prph(fwrt->trans, MON_BUFF_SAMPLE_CTL, 0x100);
} else {
iwl_write_prph(fwrt->trans, DBGC_IN_SAMPLE, 0);
udelay(100);
iwl_write_prph(fwrt->trans, DBGC_OUT_CTRL, 0);
}
}
static inline void iwl_fw_dump_conf_clear(struct iwl_fw_runtime *fwrt)
{
iwl_fw_dbg_stop_recording(fwrt);
fwrt->dump.conf = FW_DBG_INVALID;
}
......
......@@ -248,6 +248,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
* @IWL_UCODE_TLV_API_NEW_RX_STATS: should new RX STATISTICS API be used
* @IWL_UCODE_TLV_API_ATS_COEX_EXTERNAL: the coex notification is enlared to
* include information about ACL time sharing.
* @IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY: Quota command includes a field
* indicating low latency direction.
*
* @NUM_IWL_UCODE_TLV_API: number of bits used
*/
......@@ -265,6 +267,7 @@ enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE = (__force iwl_ucode_tlv_api_t)34,
IWL_UCODE_TLV_API_NEW_RX_STATS = (__force iwl_ucode_tlv_api_t)35,
IWL_UCODE_TLV_API_COEX_ATS_EXTERNAL = (__force iwl_ucode_tlv_api_t)37,
IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY = (__force iwl_ucode_tlv_api_t)38,
NUM_IWL_UCODE_TLV_API
#ifdef __CHECKER__
......
......@@ -108,6 +108,18 @@ enum iwl_led_mode {
IWL_LED_DISABLE,
};
/**
* enum iwl_nvm_type - nvm formats
* @IWL_NVM: the regular format
* @IWL_NVM_EXT: extended NVM format
* @IWL_NVM_SDP: NVM format used by 3168 series
*/
enum iwl_nvm_type {
IWL_NVM,
IWL_NVM_EXT,
IWL_NVM_SDP,
};
/*
* This is the threshold value of plcp error rate per 100mSecs. It is
* used to set and check for the validity of plcp_delta.
......@@ -320,7 +332,9 @@ struct iwl_pwr_tx_backoff {
* @integrated: discrete or integrated
* @gen2: a000 and on transport operation
* @cdb: CDB support
* @ext_nvm: extended NVM format
* @nvm_type: see &enum iwl_nvm_type
* @tx_cmd_queue_size: size of the cmd queue. If zero, use the same value as
* the regular queues
*
* We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs
......@@ -342,6 +356,7 @@ struct iwl_cfg {
const struct iwl_tt_params *thermal_params;
enum iwl_device_family device_family;
enum iwl_led_mode led_mode;
enum iwl_nvm_type nvm_type;
u32 max_data_size;
u32 max_inst_size;
netdev_features_t features;
......@@ -369,8 +384,8 @@ struct iwl_cfg {
use_tfh:1,
gen2:1,
cdb:1,
ext_nvm:1,
dbgc_supported:1;
u16 tx_cmd_queue_size;
u8 valid_tx_ant;
u8 valid_rx_ant;
u8 non_shared_ant;
......
......@@ -216,6 +216,7 @@ do { \
#define IWL_DEBUG_TX_REPLY(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_REPLY, f, ## a)
#define IWL_DEBUG_TX_QUEUES(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_QUEUES, f, ## a)
#define IWL_DEBUG_RADIO(p, f, a...) IWL_DEBUG(p, IWL_DL_RADIO, f, ## a)
#define IWL_DEBUG_DEV_RADIO(p, f, a...) IWL_DEBUG_DEV(p, IWL_DL_RADIO, f, ## a)
#define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a)
#define IWL_DEBUG_11H(p, f, a...) IWL_DEBUG(p, IWL_DL_11H, f, ## a)
#define IWL_DEBUG_RPM(p, f, a...) IWL_DEBUG(p, IWL_DL_RPM, f, ## a)
......
......@@ -832,7 +832,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
capa->standard_phy_calibration_size =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_SEC_RT:
case IWL_UCODE_TLV_SEC_RT:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
tlv_len);
drv->fw.type = IWL_FW_MVM;
......@@ -864,7 +864,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
FW_PHY_CFG_RX_CHAIN) >>
FW_PHY_CFG_RX_CHAIN_POS;
break;
case IWL_UCODE_TLV_SECURE_SEC_RT:
case IWL_UCODE_TLV_SECURE_SEC_RT:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
tlv_len);
drv->fw.type = IWL_FW_MVM;
......@@ -1335,7 +1335,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
/* Runtime instructions and 2 copies of data:
* 1) unmodified from disk
* 2) backup cache for save/restore during power-downs */
* 2) backup cache for save/restore during power-downs
*/
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
if (iwl_alloc_ucode(drv, pieces, i))
goto out_free_fw;
......
......@@ -68,16 +68,17 @@
#include <linux/export.h>
#include <linux/etherdevice.h>
#include <linux/pci.h>
#include <linux/acpi.h>
#include "iwl-drv.h"
#include "iwl-modparams.h"
#include "iwl-nvm-parse.h"
#include "iwl-prph.h"
#include "iwl-io.h"
#include "iwl-csr.h"
#include "fw/acpi.h"
/* NVM offsets (in words) definitions */
enum wkp_nvm_offsets {
enum nvm_offsets {
/* NVM HW-Section offset (in words) definitions */
SUBSYSTEM_ID = 0x0A,
HW_ADDR = 0x15,
......@@ -92,7 +93,10 @@ enum wkp_nvm_offsets {
/* NVM calibration section offset (in words) definitions */
NVM_CALIB_SECTION = 0x2B8,
XTAL_CALIB = 0x316 - NVM_CALIB_SECTION
XTAL_CALIB = 0x316 - NVM_CALIB_SECTION,
/* NVM REGULATORY -Section offset (in words) definitions */
NVM_CHANNELS_SDP = 0,
};
enum ext_nvm_offsets {
......@@ -206,8 +210,36 @@ enum iwl_nvm_channel_flags {
NVM_CHANNEL_DC_HIGH = BIT(12),
};
static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
int chan, u16 flags)
{
#define CHECK_AND_PRINT_I(x) \
((ch_flags & NVM_CHANNEL_##x) ? # x " " : "")
((flags & NVM_CHANNEL_##x) ? " " #x : "")
if (!(flags & NVM_CHANNEL_VALID)) {
IWL_DEBUG_DEV(dev, level, "Ch. %d: 0x%x: No traffic\n",
chan, flags);
return;
}
/* Note: already can print up to 101 characters, 110 is the limit! */
IWL_DEBUG_DEV(dev, level,
"Ch. %d: 0x%x:%s%s%s%s%s%s%s%s%s%s%s%s\n",
chan, flags,
CHECK_AND_PRINT_I(VALID),
CHECK_AND_PRINT_I(IBSS),
CHECK_AND_PRINT_I(ACTIVE),
CHECK_AND_PRINT_I(RADAR),
CHECK_AND_PRINT_I(INDOOR_ONLY),
CHECK_AND_PRINT_I(GO_CONCURRENT),
CHECK_AND_PRINT_I(UNIFORM),
CHECK_AND_PRINT_I(20MHZ),
CHECK_AND_PRINT_I(40MHZ),
CHECK_AND_PRINT_I(80MHZ),
CHECK_AND_PRINT_I(160MHZ),
CHECK_AND_PRINT_I(DC_HIGH));
#undef CHECK_AND_PRINT_I
}
static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
u16 nvm_flags, const struct iwl_cfg *cfg)
......@@ -215,7 +247,7 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
u32 flags = IEEE80211_CHAN_NO_HT40;
u32 last_5ghz_ht = LAST_5GHZ_HT;
if (cfg->ext_nvm)
if (cfg->nvm_type == IWL_NVM_EXT)
last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
if (!is_5ghz && (nvm_flags & NVM_CHANNEL_40MHZ)) {
......@@ -268,7 +300,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, num_2ghz_channels;
const u8 *nvm_chan;
if (!cfg->ext_nvm) {
if (cfg->nvm_type != IWL_NVM_EXT) {
num_of_ch = IWL_NUM_CHANNELS;
nvm_chan = &iwl_nvm_channels[0];
num_2ghz_channels = NUM_2GHZ_CHANNELS;
......@@ -302,12 +334,8 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
* supported, hence we still want to add them to
* the list of supported channels to cfg80211.
*/
IWL_DEBUG_EEPROM(dev,
"Ch. %d Flags %x [%sGHz] - No traffic\n",
nvm_chan[ch_idx],
ch_flags,
(ch_idx >= num_2ghz_channels) ?
"5.2" : "2.4");
iwl_nvm_print_channel_flags(dev, IWL_DL_EEPROM,
nvm_chan[ch_idx], ch_flags);
continue;
}
......@@ -337,27 +365,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
else
channel->flags = 0;
IWL_DEBUG_EEPROM(dev,
"Ch. %d [%sGHz] flags 0x%x %s%s%s%s%s%s%s%s%s%s%s%s(%ddBm): Ad-Hoc %ssupported\n",
channel->hw_value,
is_5ghz ? "5.2" : "2.4",
ch_flags,
CHECK_AND_PRINT_I(VALID),
CHECK_AND_PRINT_I(IBSS),
CHECK_AND_PRINT_I(ACTIVE),
CHECK_AND_PRINT_I(RADAR),
CHECK_AND_PRINT_I(INDOOR_ONLY),
CHECK_AND_PRINT_I(GO_CONCURRENT),
CHECK_AND_PRINT_I(UNIFORM),
CHECK_AND_PRINT_I(20MHZ),
CHECK_AND_PRINT_I(40MHZ),
CHECK_AND_PRINT_I(80MHZ),
CHECK_AND_PRINT_I(160MHZ),
CHECK_AND_PRINT_I(DC_HIGH),
channel->max_power,
((ch_flags & NVM_CHANNEL_IBSS) &&
!(ch_flags & NVM_CHANNEL_RADAR))
? "" : "not ");
iwl_nvm_print_channel_flags(dev, IWL_DL_EEPROM,
channel->hw_value, ch_flags);
IWL_DEBUG_EEPROM(dev, "Ch. %d: %ddBm\n",
channel->hw_value, channel->max_power);
}
return n_channels;
......@@ -484,7 +495,7 @@ IWL_EXPORT_SYMBOL(iwl_init_sbands);
static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
const __le16 *phy_sku)
{
if (!cfg->ext_nvm)
if (cfg->nvm_type != IWL_NVM_EXT)
return le16_to_cpup(nvm_sw + SKU);
return le32_to_cpup((__le32 *)(phy_sku + SKU_FAMILY_8000));
......@@ -492,7 +503,7 @@ static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
{
if (!cfg->ext_nvm)
if (cfg->nvm_type != IWL_NVM_EXT)
return le16_to_cpup(nvm_sw + NVM_VERSION);
else
return le32_to_cpup((__le32 *)(nvm_sw +
......@@ -502,7 +513,7 @@ static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
const __le16 *phy_sku)
{
if (!cfg->ext_nvm)
if (cfg->nvm_type != IWL_NVM_EXT)
return le16_to_cpup(nvm_sw + RADIO_CFG);
return le32_to_cpup((__le32 *)(phy_sku + RADIO_CFG_FAMILY_EXT_NVM));
......@@ -513,7 +524,7 @@ static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
{
int n_hw_addr;
if (!cfg->ext_nvm)
if (cfg->nvm_type != IWL_NVM_EXT)
return le16_to_cpup(nvm_sw + N_HW_ADDRS);
n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw + N_HW_ADDRS_FAMILY_8000));
......@@ -525,7 +536,7 @@ static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
struct iwl_nvm_data *data,
u32 radio_cfg)
{
if (!cfg->ext_nvm) {
if (cfg->nvm_type != IWL_NVM_EXT) {
data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg);
data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg);
data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg);
......@@ -634,7 +645,7 @@ static int iwl_set_hw_address(struct iwl_trans *trans,
{
if (cfg->mac_addr_from_csr) {
iwl_set_hw_address_from_csr(trans, data);
} else if (!cfg->ext_nvm) {
} else if (cfg->nvm_type != IWL_NVM_EXT) {
const u8 *hw_addr = (const u8 *)(nvm_hw + HW_ADDR);
/* The byte order is little endian 16 bit, meaning 214365 */
......@@ -706,7 +717,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
u16 lar_config;
const __le16 *ch_section;
if (!cfg->ext_nvm)
if (cfg->nvm_type != IWL_NVM_EXT)
data = kzalloc(sizeof(*data) +
sizeof(struct ieee80211_channel) *
IWL_NUM_CHANNELS,
......@@ -740,7 +751,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw);
if (!cfg->ext_nvm) {
if (cfg->nvm_type != IWL_NVM_EXT) {
/* Checking for required sections */
if (!nvm_calib) {
IWL_ERR(trans,
......@@ -748,11 +759,15 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
kfree(data);
return NULL;
}
ch_section = cfg->nvm_type == IWL_NVM_SDP ?
&regulatory[NVM_CHANNELS_SDP] :
&nvm_sw[NVM_CHANNELS];
/* in family 8000 Xtal calibration values moved to OTP */
data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB);
data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1);
lar_enabled = true;
ch_section = &nvm_sw[NVM_CHANNELS];
} else {
u16 lar_offset = data->nvm_version < 0xE39 ?
NVM_LAR_OFFSET_OLD :
......@@ -786,7 +801,7 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan,
u32 flags = NL80211_RRF_NO_HT40;
u32 last_5ghz_ht = LAST_5GHZ_HT;
if (cfg->ext_nvm)
if (cfg->nvm_type == IWL_NVM_EXT)
last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
if (ch_idx < NUM_2GHZ_CHANNELS &&
......@@ -834,7 +849,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int ch_idx;
u16 ch_flags;
u32 reg_rule_flags, prev_reg_rule_flags = 0;
const u8 *nvm_chan = cfg->ext_nvm ?
const u8 *nvm_chan = cfg->nvm_type == IWL_NVM_EXT ?
iwl_ext_nvm_channels : iwl_nvm_channels;
struct ieee80211_regdomain *regd;
int size_of_regd;
......@@ -843,7 +858,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int center_freq, prev_center_freq = 0;
int valid_rules = 0;
bool new_rule;
int max_num_ch = cfg->ext_nvm ?
int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ?
IWL_NUM_CHANNELS_EXT : IWL_NUM_CHANNELS;
if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES))
......@@ -873,12 +888,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
new_rule = false;
if (!(ch_flags & NVM_CHANNEL_VALID)) {
IWL_DEBUG_DEV(dev, IWL_DL_LAR,
"Ch. %d Flags %x [%sGHz] - No traffic\n",
nvm_chan[ch_idx],
ch_flags,
(ch_idx >= NUM_2GHZ_CHANNELS) ?
"5.2" : "2.4");
iwl_nvm_print_channel_flags(dev, IWL_DL_LAR,
nvm_chan[ch_idx], ch_flags);
continue;
}
......@@ -914,31 +925,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
prev_center_freq = center_freq;
prev_reg_rule_flags = reg_rule_flags;
IWL_DEBUG_DEV(dev, IWL_DL_LAR,
"Ch. %d [%sGHz] %s%s%s%s%s%s%s%s%s%s%s%s(0x%02x)\n",
center_freq,
band == NL80211_BAND_5GHZ ? "5.2" : "2.4",
CHECK_AND_PRINT_I(VALID),
CHECK_AND_PRINT_I(IBSS),
CHECK_AND_PRINT_I(ACTIVE),
CHECK_AND_PRINT_I(RADAR),
CHECK_AND_PRINT_I(INDOOR_ONLY),
CHECK_AND_PRINT_I(GO_CONCURRENT),
CHECK_AND_PRINT_I(UNIFORM),
CHECK_AND_PRINT_I(20MHZ),
CHECK_AND_PRINT_I(40MHZ),
CHECK_AND_PRINT_I(80MHZ),
CHECK_AND_PRINT_I(160MHZ),
CHECK_AND_PRINT_I(DC_HIGH),
ch_flags);
IWL_DEBUG_DEV(dev, IWL_DL_LAR,
"Ch. %d [%sGHz] reg_flags 0x%x: %s\n",
center_freq,
band == NL80211_BAND_5GHZ ? "5.2" : "2.4",
reg_rule_flags,
((ch_flags & NVM_CHANNEL_ACTIVE) &&
!(ch_flags & NVM_CHANNEL_RADAR))
? "Ad-Hoc" : "");
iwl_nvm_print_channel_flags(dev, IWL_DL_LAR,
nvm_chan[ch_idx], ch_flags);
}
regd->n_reg_rules = valid_rules;
......@@ -950,91 +938,3 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
return regd;
}
IWL_EXPORT_SYMBOL(iwl_parse_nvm_mcc_info);
#ifdef CONFIG_ACPI
#define WRDD_METHOD "WRDD"
#define WRDD_WIFI (0x07)
#define WRDD_WIGIG (0x10)
static u32 iwl_wrdd_get_mcc(struct device *dev, union acpi_object *wrdd)
{
union acpi_object *mcc_pkg, *domain_type, *mcc_value;
u32 i;
if (wrdd->type != ACPI_TYPE_PACKAGE ||
wrdd->package.count < 2 ||
wrdd->package.elements[0].type != ACPI_TYPE_INTEGER ||
wrdd->package.elements[0].integer.value != 0) {
IWL_DEBUG_EEPROM(dev, "Unsupported wrdd structure\n");
return 0;
}
for (i = 1 ; i < wrdd->package.count ; ++i) {
mcc_pkg = &wrdd->package.elements[i];
if (mcc_pkg->type != ACPI_TYPE_PACKAGE ||
mcc_pkg->package.count < 2 ||
mcc_pkg->package.elements[0].type != ACPI_TYPE_INTEGER ||
mcc_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
mcc_pkg = NULL;
continue;
}
domain_type = &mcc_pkg->package.elements[0];
if (domain_type->integer.value == WRDD_WIFI)
break;
mcc_pkg = NULL;
}
if (mcc_pkg) {
mcc_value = &mcc_pkg->package.elements[1];
return mcc_value->integer.value;
}
return 0;
}
int iwl_get_bios_mcc(struct device *dev, char *mcc)
{
acpi_handle root_handle;
acpi_handle handle;
struct acpi_buffer wrdd = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
u32 mcc_val;
root_handle = ACPI_HANDLE(dev);
if (!root_handle) {
IWL_DEBUG_EEPROM(dev,
"Could not retrieve root port ACPI handle\n");
return -ENOENT;
}
/* Get the method's handle */
status = acpi_get_handle(root_handle, (acpi_string)WRDD_METHOD,
&handle);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_EEPROM(dev, "WRD method not found\n");
return -ENOENT;
}
/* Call WRDD with no arguments */
status = acpi_evaluate_object(handle, NULL, NULL, &wrdd);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_EEPROM(dev, "WRDC invocation failed (0x%x)\n",
status);
return -ENOENT;
}
mcc_val = iwl_wrdd_get_mcc(dev, wrdd.pointer);
kfree(wrdd.pointer);
if (!mcc_val)
return -ENOENT;
mcc[0] = (mcc_val >> 8) & 0xff;
mcc[1] = mcc_val & 0xff;
mcc[2] = '\0';
return 0;
}
IWL_EXPORT_SYMBOL(iwl_get_bios_mcc);
#endif
......@@ -109,21 +109,4 @@ struct ieee80211_regdomain *
iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, __le32 *channels, u16 fw_mcc);
#ifdef CONFIG_ACPI
/**
* iwl_get_bios_mcc - read MCC from BIOS, if available
*
* @dev: the struct device
* @mcc: output buffer (3 bytes) that will get the MCC
*
* This function tries to read the current MCC from ACPI if available.
*/
int iwl_get_bios_mcc(struct device *dev, char *mcc);
#else
static inline int iwl_get_bios_mcc(struct device *dev, char *mcc)
{
return -ENOENT;
}
#endif
#endif /* __iwl_nvm_parse_h__ */
......@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
......@@ -31,6 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -205,3 +207,17 @@ int iwl_cmd_groups_verify_sorted(const struct iwl_trans_config *trans)
return 0;
}
IWL_EXPORT_SYMBOL(iwl_cmd_groups_verify_sorted);
void iwl_trans_ref(struct iwl_trans *trans)
{
if (trans->ops->ref)
trans->ops->ref(trans);
}
IWL_EXPORT_SYMBOL(iwl_trans_ref);
void iwl_trans_unref(struct iwl_trans *trans)
{
if (trans->ops->unref)
trans->ops->unref(trans);
}
IWL_EXPORT_SYMBOL(iwl_trans_unref);
......@@ -749,8 +749,6 @@ struct iwl_trans {
struct lockdep_map sync_cmd_lockdep_map;
#endif
u64 dflt_pwr_limit;
const struct iwl_fw_dbg_dest_tlv *dbg_dest_tlv;
const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX];
struct iwl_fw_dbg_trigger_tlv * const *dbg_trigger_tlv;
......@@ -875,18 +873,6 @@ static inline int iwl_trans_d3_resume(struct iwl_trans *trans,
return trans->ops->d3_resume(trans, status, test, reset);
}
static inline void iwl_trans_ref(struct iwl_trans *trans)
{
if (trans->ops->ref)
trans->ops->ref(trans);
}
static inline void iwl_trans_unref(struct iwl_trans *trans)
{
if (trans->ops->unref)
trans->ops->unref(trans);
}
static inline int iwl_trans_suspend(struct iwl_trans *trans)
{
if (!trans->ops->suspend)
......@@ -1191,6 +1177,8 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
const struct iwl_cfg *cfg,
const struct iwl_trans_ops *ops);
void iwl_trans_free(struct iwl_trans *trans);
void iwl_trans_ref(struct iwl_trans *trans);
void iwl_trans_unref(struct iwl_trans *trans);
/*****************************************************
* driver (transport) register/unregister functions
......
......@@ -664,6 +664,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
int ret, i;
struct iwl_binding_cmd binding_cmd = {};
struct iwl_time_quota_cmd quota_cmd = {};
struct iwl_time_quota_data *quota;
u32 status;
int size;
......@@ -745,17 +746,20 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return ret;
/* and some quota */
quota_cmd.quotas[0].id_and_color =
quota = iwl_mvm_quota_cmd_get_quota(mvm, &quota_cmd, 0);
quota->id_and_color =
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->phy_ctxt->id,
mvmvif->phy_ctxt->color));
quota_cmd.quotas[0].quota = cpu_to_le32(IWL_MVM_MAX_QUOTA);
quota_cmd.quotas[0].max_duration = cpu_to_le32(IWL_MVM_MAX_QUOTA);
quota->quota = cpu_to_le32(IWL_MVM_MAX_QUOTA);
quota->max_duration = cpu_to_le32(IWL_MVM_MAX_QUOTA);
for (i = 1; i < MAX_BINDINGS; i++)
quota_cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID);
for (i = 1; i < MAX_BINDINGS; i++) {
quota = iwl_mvm_quota_cmd_get_quota(mvm, &quota_cmd, i);
quota->id_and_color = cpu_to_le32(FW_CTXT_INVALID);
}
ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0,
sizeof(quota_cmd), &quota_cmd);
iwl_mvm_quota_cmd_size(mvm), &quota_cmd);
if (ret)
IWL_ERR(mvm, "Failed to send quota: %d\n", ret);
......
......@@ -1455,80 +1455,6 @@ static const char * const chanwidths[] = {
[NL80211_CHAN_WIDTH_160] = "vht160",
};
static bool iwl_mvm_lqm_notif_wait(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt, void *data)
{
struct ieee80211_vif *vif = data;
struct iwl_mvm *mvm =
container_of(notif_wait, struct iwl_mvm, notif_wait);
struct iwl_link_qual_msrmnt_notif *report = (void *)pkt->data;
u32 num_of_stations = le32_to_cpu(report->number_of_stations);
int i;
IWL_INFO(mvm, "LQM report:\n");
IWL_INFO(mvm, "\tstatus: %d\n", report->status);
IWL_INFO(mvm, "\tmacID: %d\n", le32_to_cpu(report->mac_id));
IWL_INFO(mvm, "\ttx_frame_dropped: %d\n",
le32_to_cpu(report->tx_frame_dropped));
IWL_INFO(mvm, "\ttime_in_measurement_window: %d us\n",
le32_to_cpu(report->time_in_measurement_window));
IWL_INFO(mvm, "\ttotal_air_time_other_stations: %d\n",
le32_to_cpu(report->total_air_time_other_stations));
IWL_INFO(mvm, "\tchannel_freq: %d\n",
vif->bss_conf.chandef.center_freq1);
IWL_INFO(mvm, "\tchannel_width: %s\n",
chanwidths[vif->bss_conf.chandef.width]);
IWL_INFO(mvm, "\tnumber_of_stations: %d\n", num_of_stations);
for (i = 0; i < num_of_stations; i++)
IWL_INFO(mvm, "\t\tsta[%d]: %d\n", i,
report->frequent_stations_air_time[i]);
return true;
}
static ssize_t iwl_dbgfs_lqm_send_cmd_write(struct ieee80211_vif *vif,
char *buf, size_t count,
loff_t *ppos)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = mvmvif->mvm;
struct iwl_notification_wait wait_lqm_notif;
static u16 lqm_notif[] = {
WIDE_ID(MAC_CONF_GROUP,
LINK_QUALITY_MEASUREMENT_COMPLETE_NOTIF)
};
int err;
u32 duration;
u32 timeout;
if (sscanf(buf, "%d,%d", &duration, &timeout) != 2)
return -EINVAL;
iwl_init_notification_wait(&mvm->notif_wait, &wait_lqm_notif,
lqm_notif, ARRAY_SIZE(lqm_notif),
iwl_mvm_lqm_notif_wait, vif);
mutex_lock(&mvm->mutex);
err = iwl_mvm_send_lqm_cmd(vif, LQM_CMD_OPERATION_START_MEASUREMENT,
duration, timeout);
mutex_unlock(&mvm->mutex);
if (err) {
IWL_ERR(mvm, "Failed to send lqm cmdf(err=%d)\n", err);
iwl_remove_notification(&mvm->notif_wait, &wait_lqm_notif);
return err;
}
/* wait for 2 * timeout (safety guard) and convert to jiffies*/
timeout = msecs_to_jiffies((timeout * 2) / 1000);
err = iwl_wait_notification(&mvm->notif_wait, &wait_lqm_notif,
timeout);
if (err)
IWL_ERR(mvm, "Getting lqm notif timed out\n");
return count;
}
#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
_MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
......@@ -1553,7 +1479,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_abort, 32);
MVM_DEBUGFS_READ_FILE_OPS(tof_range_response);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_responder_params, 32);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32);
MVM_DEBUGFS_WRITE_FILE_OPS(lqm_send_cmd, 64);
MVM_DEBUGFS_READ_FILE_OPS(os_device_timediff);
......@@ -1594,7 +1519,6 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
S_IRUSR | S_IWUSR);
MVM_DEBUGFS_ADD_FILE_VIF(quota_min, mvmvif->dbgfs_dir,
S_IRUSR | S_IWUSR);
MVM_DEBUGFS_ADD_FILE_VIF(lqm_send_cmd, mvmvif->dbgfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE_VIF(os_device_timediff,
mvmvif->dbgfs_dir, S_IRUSR);
......
......@@ -660,6 +660,36 @@ iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf,
return ret ?: count;
}
static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
char *buff, *pos, *endpos;
static const size_t bufsz = 1024;
int ret;
buff = kmalloc(bufsz, GFP_KERNEL);
if (!buff)
return -ENOMEM;
pos = buff;
endpos = pos + bufsz;
pos += scnprintf(pos, endpos - pos, "FW prefix: %s\n",
mvm->trans->cfg->fw_name_pre);
pos += scnprintf(pos, endpos - pos, "FW: %s\n",
mvm->fwrt.fw->human_readable);
pos += scnprintf(pos, endpos - pos, "Device: %s\n",
mvm->fwrt.trans->cfg->name);
pos += scnprintf(pos, endpos - pos, "Bus: %s\n",
mvm->fwrt.dev->bus->name);
ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
kfree(buff);
return ret;
}
#define PRINT_STATS_LE32(_struct, _memb) \
pos += scnprintf(buf + pos, bufsz - pos, \
fmt_table, #_memb, \
......@@ -1662,6 +1692,7 @@ MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
MVM_DEBUGFS_READ_FILE_OPS(fw_ver);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
......@@ -1843,6 +1874,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
S_IRUSR | S_IWUSR);
MVM_DEBUGFS_ADD_FILE(fw_ver, mvm->debugfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
......
......@@ -66,7 +66,6 @@
*****************************************************************************/
#include <net/mac80211.h>
#include <linux/netdevice.h>
#include <linux/acpi.h>
#include "iwl-trans.h"
#include "iwl-op-mode.h"
......@@ -75,7 +74,7 @@
#include "iwl-csr.h" /* for iwl_mvm_rx_card_state_notif */
#include "iwl-io.h" /* for iwl_mvm_rx_card_state_notif */
#include "iwl-prph.h"
#include "iwl-eeprom-parse.h"
#include "fw/acpi.h"
#include "mvm.h"
#include "fw/dbg.h"
......@@ -579,17 +578,6 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
}
#ifdef CONFIG_ACPI
#define ACPI_WRDS_METHOD "WRDS"
#define ACPI_EWRD_METHOD "EWRD"
#define ACPI_WGDS_METHOD "WGDS"
#define ACPI_WIFI_DOMAIN (0x07)
#define ACPI_WRDS_WIFI_DATA_SIZE (IWL_MVM_SAR_TABLE_SIZE + 2)
#define ACPI_EWRD_WIFI_DATA_SIZE ((IWL_MVM_SAR_PROFILE_NUM - 1) * \
IWL_MVM_SAR_TABLE_SIZE + 3)
#define ACPI_WGDS_WIFI_DATA_SIZE 18
#define ACPI_WGDS_NUM_BANDS 2
#define ACPI_WGDS_TABLE_SIZE 3
static int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm,
union acpi_object *table,
struct iwl_mvm_sar_profile *profile,
......@@ -599,7 +587,7 @@ static int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm,
profile->enabled = enabled;
for (i = 0; i < IWL_MVM_SAR_TABLE_SIZE; i++) {
for (i = 0; i < ACPI_SAR_TABLE_SIZE; i++) {
if ((table[i].type != ACPI_TYPE_INTEGER) ||
(table[i].integer.value > U8_MAX))
return -EINVAL;
......@@ -610,88 +598,18 @@ static int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm,
return 0;
}
static union acpi_object *iwl_mvm_sar_find_wifi_pkg(struct iwl_mvm *mvm,
union acpi_object *data,
int data_size)
{
union acpi_object *wifi_pkg = NULL;
int i;
/*
* We need at least two packages, one for the revision and one
* for the data itself. Also check that the revision is valid
* (i.e. it is an integer set to 0).
*/
if (data->type != ACPI_TYPE_PACKAGE ||
data->package.count < 2 ||
data->package.elements[0].type != ACPI_TYPE_INTEGER ||
data->package.elements[0].integer.value != 0) {
IWL_DEBUG_RADIO(mvm, "Unsupported packages structure\n");
return ERR_PTR(-EINVAL);
}
/* loop through all the packages to find the one for WiFi */
for (i = 1; i < data->package.count; i++) {
union acpi_object *domain;
wifi_pkg = &data->package.elements[i];
/* Skip anything that is not a package with the right
* amount of elements (i.e. domain_type,
* enabled/disabled plus the actual data size.
*/
if (wifi_pkg->type != ACPI_TYPE_PACKAGE ||
wifi_pkg->package.count != data_size)
continue;
domain = &wifi_pkg->package.elements[0];
if (domain->type == ACPI_TYPE_INTEGER &&
domain->integer.value == ACPI_WIFI_DOMAIN)
break;
wifi_pkg = NULL;
}
if (!wifi_pkg)
return ERR_PTR(-ENOENT);
return wifi_pkg;
}
static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm)
{
union acpi_object *wifi_pkg, *table;
acpi_handle root_handle;
acpi_handle handle;
struct acpi_buffer wrds = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
union acpi_object *wifi_pkg, *table, *data;
bool enabled;
int ret;
root_handle = ACPI_HANDLE(mvm->dev);
if (!root_handle) {
IWL_DEBUG_RADIO(mvm,
"Could not retrieve root port ACPI handle\n");
return -ENOENT;
}
/* Get the method's handle */
status = acpi_get_handle(root_handle, (acpi_string)ACPI_WRDS_METHOD,
&handle);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_RADIO(mvm, "WRDS method not found\n");
return -ENOENT;
}
/* Call WRDS with no arguments */
status = acpi_evaluate_object(handle, NULL, NULL, &wrds);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_RADIO(mvm, "WRDS invocation failed (0x%x)\n", status);
return -ENOENT;
}
data = iwl_acpi_get_object(mvm->dev, ACPI_WRDS_METHOD);
if (IS_ERR(data))
return PTR_ERR(data);
wifi_pkg = iwl_mvm_sar_find_wifi_pkg(mvm, wrds.pointer,
ACPI_WRDS_WIFI_DATA_SIZE);
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
ACPI_WRDS_WIFI_DATA_SIZE);
if (IS_ERR(wifi_pkg)) {
ret = PTR_ERR(wifi_pkg);
goto out_free;
......@@ -712,46 +630,23 @@ static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm)
*/
ret = iwl_mvm_sar_set_profile(mvm, table, &mvm->sar_profiles[0],
enabled);
out_free:
kfree(wrds.pointer);
kfree(data);
return ret;
}
static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
{
union acpi_object *wifi_pkg;
acpi_handle root_handle;
acpi_handle handle;
struct acpi_buffer ewrd = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
union acpi_object *wifi_pkg, *data;
bool enabled;
int i, n_profiles, ret;
root_handle = ACPI_HANDLE(mvm->dev);
if (!root_handle) {
IWL_DEBUG_RADIO(mvm,
"Could not retrieve root port ACPI handle\n");
return -ENOENT;
}
/* Get the method's handle */
status = acpi_get_handle(root_handle, (acpi_string)ACPI_EWRD_METHOD,
&handle);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_RADIO(mvm, "EWRD method not found\n");
return -ENOENT;
}
data = iwl_acpi_get_object(mvm->dev, ACPI_EWRD_METHOD);
if (IS_ERR(data))
return PTR_ERR(data);
/* Call EWRD with no arguments */
status = acpi_evaluate_object(handle, NULL, NULL, &ewrd);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_RADIO(mvm, "EWRD invocation failed (0x%x)\n", status);
return -ENOENT;
}
wifi_pkg = iwl_mvm_sar_find_wifi_pkg(mvm, ewrd.pointer,
ACPI_EWRD_WIFI_DATA_SIZE);
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
ACPI_EWRD_WIFI_DATA_SIZE);
if (IS_ERR(wifi_pkg)) {
ret = PTR_ERR(wifi_pkg);
goto out_free;
......@@ -788,55 +683,33 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
break;
/* go to the next table */
pos += IWL_MVM_SAR_TABLE_SIZE;
pos += ACPI_SAR_TABLE_SIZE;
}
out_free:
kfree(ewrd.pointer);
kfree(data);
return ret;
}
static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
{
union acpi_object *wifi_pkg;
acpi_handle root_handle;
acpi_handle handle;
struct acpi_buffer wgds = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
union acpi_object *wifi_pkg, *data;
int i, j, ret;
int idx = 1;
root_handle = ACPI_HANDLE(mvm->dev);
if (!root_handle) {
IWL_DEBUG_RADIO(mvm,
"Could not retrieve root port ACPI handle\n");
return -ENOENT;
}
data = iwl_acpi_get_object(mvm->dev, ACPI_WGDS_METHOD);
if (IS_ERR(data))
return PTR_ERR(data);
/* Get the method's handle */
status = acpi_get_handle(root_handle, (acpi_string)ACPI_WGDS_METHOD,
&handle);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_RADIO(mvm, "WGDS method not found\n");
return -ENOENT;
}
/* Call WGDS with no arguments */
status = acpi_evaluate_object(handle, NULL, NULL, &wgds);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_RADIO(mvm, "WGDS invocation failed (0x%x)\n", status);
return -ENOENT;
}
wifi_pkg = iwl_mvm_sar_find_wifi_pkg(mvm, wgds.pointer,
ACPI_WGDS_WIFI_DATA_SIZE);
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
ACPI_WGDS_WIFI_DATA_SIZE);
if (IS_ERR(wifi_pkg)) {
ret = PTR_ERR(wifi_pkg);
goto out_free;
}
for (i = 0; i < IWL_NUM_GEO_PROFILES; i++) {
for (j = 0; j < IWL_MVM_GEO_TABLE_SIZE; j++) {
for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
for (j = 0; j < ACPI_GEO_TABLE_SIZE; j++) {
union acpi_object *entry;
entry = &wifi_pkg->package.elements[idx++];
......@@ -851,7 +724,7 @@ static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
}
ret = 0;
out_free:
kfree(wgds.pointer);
kfree(data);
return ret;
}
......@@ -861,25 +734,25 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
.v3.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),
};
int i, j, idx;
int profs[IWL_NUM_CHAIN_LIMITS] = { prof_a, prof_b };
int profs[ACPI_SAR_NUM_CHAIN_LIMITS] = { prof_a, prof_b };
int len = sizeof(cmd);
BUILD_BUG_ON(IWL_NUM_CHAIN_LIMITS < 2);
BUILD_BUG_ON(IWL_NUM_CHAIN_LIMITS * IWL_NUM_SUB_BANDS !=
IWL_MVM_SAR_TABLE_SIZE);
BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS < 2);
BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS * ACPI_SAR_NUM_SUB_BANDS !=
ACPI_SAR_TABLE_SIZE);
if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TX_POWER_ACK))
len = sizeof(cmd.v3);
for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
for (i = 0; i < ACPI_SAR_NUM_CHAIN_LIMITS; i++) {
struct iwl_mvm_sar_profile *prof;
/* don't allow SAR to be disabled (profile 0 means disable) */
if (profs[i] == 0)
return -EPERM;
/* we are off by one, so allow up to IWL_MVM_SAR_PROFILE_NUM */
if (profs[i] > IWL_MVM_SAR_PROFILE_NUM)
/* we are off by one, so allow up to ACPI_SAR_PROFILE_NUM */
if (profs[i] > ACPI_SAR_PROFILE_NUM)
return -EINVAL;
/* profiles go from 1 to 4, so decrement to access the array */
......@@ -894,8 +767,8 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
}
IWL_DEBUG_RADIO(mvm, " Chain[%d]:\n", i);
for (j = 0; j < IWL_NUM_SUB_BANDS; j++) {
idx = (i * IWL_NUM_SUB_BANDS) + j;
for (j = 0; j < ACPI_SAR_NUM_SUB_BANDS; j++) {
idx = (i * ACPI_SAR_NUM_SUB_BANDS) + j;
cmd.v3.per_chain_restriction[i][j] =
cpu_to_le16(prof->table[idx]);
IWL_DEBUG_RADIO(mvm, " Band[%d] = %d * .125dBm\n",
......@@ -931,7 +804,7 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
resp = (void *)cmd.resp_pkt->data;
ret = le32_to_cpu(resp->profile_idx);
if (WARN_ON(ret > IWL_NUM_GEO_PROFILES)) {
if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES)) {
ret = -EIO;
IWL_WARN(mvm, "Invalid geographic profile idx (%d)\n", ret);
}
......@@ -959,10 +832,12 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
IWL_DEBUG_RADIO(mvm, "Sending GEO_TX_POWER_LIMIT\n");
BUILD_BUG_ON(IWL_NUM_GEO_PROFILES * ACPI_WGDS_NUM_BANDS *
BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES * ACPI_WGDS_NUM_BANDS *
ACPI_WGDS_TABLE_SIZE != ACPI_WGDS_WIFI_DATA_SIZE);
for (i = 0; i < IWL_NUM_GEO_PROFILES; i++) {
BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES > IWL_NUM_GEO_PROFILES);
for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
struct iwl_per_chain_offset *chain =
(struct iwl_per_chain_offset *)&cmd.table[i];
......@@ -970,7 +845,7 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
u8 *value;
value = &mvm->geo_profiles[i].values[j *
IWL_GEO_PER_CHAIN_SIZE];
ACPI_GEO_PER_CHAIN_SIZE];
chain[j].max_tx_power = cpu_to_le16(value[0]);
chain[j].chain_a = value[1];
chain[j].chain_b = value[2];
......
......@@ -1077,6 +1077,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
mvm->vif_count = 0;
mvm->rx_ba_sessions = 0;
mvm->fwrt.dump.conf = FW_DBG_INVALID;
mvm->monitor_on = false;
/* keep statistics ticking */
iwl_mvm_accu_radio_stats(mvm);
......@@ -1437,6 +1438,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
mvm->p2p_device_vif = vif;
}
if (vif->type == NL80211_IFTYPE_MONITOR)
mvm->monitor_on = true;
iwl_mvm_vif_dbgfs_register(mvm, vif);
goto out_unlock;
......@@ -1526,6 +1530,9 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
iwl_mvm_power_update_mac(mvm);
iwl_mvm_mac_ctxt_remove(mvm, vif);
if (vif->type == NL80211_IFTYPE_MONITOR)
mvm->monitor_on = false;
out_release:
mutex_unlock(&mvm->mutex);
}
......@@ -1892,11 +1899,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc)
iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);
if (changes & BSS_CHANGED_ASSOC && !bss_conf->assoc &&
mvmvif->lqm_active)
iwl_mvm_send_lqm_cmd(vif, LQM_CMD_OPERATION_STOP_MEASUREMENT,
0, 0);
/*
* If we're not associated yet, take the (new) BSSID before associating
* so the firmware knows. If we're already associated, then use the old
......@@ -3425,10 +3427,24 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
return;
mutex_lock(&mvm->mutex);
/* we are only changing the min_width, may be a noop */
if (changed == IEEE80211_CHANCTX_CHANGE_MIN_WIDTH) {
if (phy_ctxt->width == ctx->min_def.width)
goto out_unlock;
/* we are just toggling between 20_NOHT and 20 */
if (phy_ctxt->width <= NL80211_CHAN_WIDTH_20 &&
ctx->min_def.width <= NL80211_CHAN_WIDTH_20)
goto out_unlock;
}
iwl_mvm_bt_coex_vif_change(mvm);
iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def,
ctx->rx_chains_static,
ctx->rx_chains_dynamic);
out_unlock:
mutex_unlock(&mvm->mutex);
}
......@@ -3893,11 +3909,6 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
break;
case NL80211_IFTYPE_STATION:
if (mvmvif->lqm_active)
iwl_mvm_send_lqm_cmd(vif,
LQM_CMD_OPERATION_STOP_MEASUREMENT,
0, 0);
/* Schedule the time event to a bit before beacon 1,
* to make sure we're in the new channel when the
* GO/AP arrives. In case count <= 1 immediately schedule the
......@@ -4252,31 +4263,6 @@ static void iwl_mvm_event_bar_rx_callback(struct iwl_mvm *mvm,
event->u.ba.ssn);
}
static void
iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
const struct ieee80211_event *event)
{
struct iwl_fw_dbg_trigger_tlv *trig;
struct iwl_fw_dbg_trigger_ba *ba_trig;
if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA))
return;
trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA);
ba_trig = (void *)trig->data;
if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
ieee80211_vif_to_wdev(vif), trig))
return;
if (!(le16_to_cpu(ba_trig->frame_timeout) & BIT(event->u.ba.tid)))
return;
iwl_fw_dbg_collect_trig(&mvm->fwrt, trig,
"Frame from %pM timed out, tid %d",
event->u.ba.sta->addr, event->u.ba.tid);
}
static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
const struct ieee80211_event *event)
......@@ -4291,7 +4277,8 @@ static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
iwl_mvm_event_bar_rx_callback(mvm, vif, event);
break;
case BA_FRAME_TIMEOUT:
iwl_mvm_event_frame_timeout_callback(mvm, vif, event);
iwl_mvm_event_frame_timeout_callback(mvm, vif, event->u.ba.sta,
event->u.ba.tid);
break;
default:
break;
......
......@@ -89,6 +89,7 @@
#include "tof.h"
#include "fw/runtime.h"
#include "fw/dbg.h"
#include "fw/acpi.h"
#define IWL_MVM_MAX_ADDRESSES 5
/* RSSI offset for WkP */
......@@ -147,6 +148,8 @@ struct iwl_mvm_phy_ctxt {
u16 color;
u32 ref;
enum nl80211_chan_width width;
/*
* TODO: This should probably be removed. Currently here only for rate
* scaling algorithm
......@@ -436,12 +439,6 @@ struct iwl_mvm_vif {
/* TCP Checksum Offload */
netdev_features_t features;
/*
* link quality measurement - used to check whether this interface
* is in the middle of a link quality measurement
*/
bool lqm_active;
};
static inline struct iwl_mvm_vif *
......@@ -592,6 +589,7 @@ enum iwl_mvm_tdls_cs_state {
* @queue: queue of this reorder buffer
* @last_amsdu: track last ASMDU SN for duplication detection
* @last_sub_index: track ASMDU sub frame index for duplication detection
* @tid: the tid
* @entries: list of skbs stored
* @reorder_time: time the packet was stored in the reorder buffer
* @reorder_timer: timer for frames are in the reorder buffer. For AMSDU
......@@ -609,6 +607,7 @@ struct iwl_mvm_reorder_buffer {
int queue;
u16 last_amsdu;
u8 last_sub_index;
u8 tid;
struct sk_buff_head entries[IEEE80211_MAX_AMPDU_BUF];
unsigned long reorder_time[IEEE80211_MAX_AMPDU_BUF];
struct timer_list reorder_timer;
......@@ -685,20 +684,14 @@ enum iwl_mvm_queue_status {
#define IWL_MVM_NUM_CIPHERS 10
#ifdef CONFIG_ACPI
#define IWL_MVM_SAR_TABLE_SIZE 10
#define IWL_MVM_SAR_PROFILE_NUM 4
#define IWL_MVM_GEO_TABLE_SIZE 6
struct iwl_mvm_sar_profile {
bool enabled;
u8 table[IWL_MVM_SAR_TABLE_SIZE];
u8 table[ACPI_SAR_TABLE_SIZE];
};
struct iwl_mvm_geo_profile {
u8 values[IWL_MVM_GEO_TABLE_SIZE];
u8 values[ACPI_GEO_TABLE_SIZE];
};
#endif
struct iwl_mvm {
/* for logger access */
......@@ -1015,9 +1008,12 @@ struct iwl_mvm {
bool drop_bcn_ap_mode;
struct delayed_work cs_tx_unblock_dwork;
/* does a monitor vif exist (only one can exist hence bool) */
bool monitor_on;
#ifdef CONFIG_ACPI
struct iwl_mvm_sar_profile sar_profiles[IWL_MVM_SAR_PROFILE_NUM];
struct iwl_mvm_geo_profile geo_profiles[IWL_NUM_GEO_PROFILES];
struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
struct iwl_mvm_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
#endif
};
......@@ -1159,7 +1155,7 @@ static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm)
* Enable LAR only if it is supported by the FW (TLV) &&
* enabled in the NVM
*/
if (mvm->cfg->ext_nvm)
if (mvm->cfg->nvm_type == IWL_NVM_EXT)
return nvm_lar && tlv_lar;
else
return tlv_lar;
......@@ -1248,6 +1244,12 @@ static inline bool iwl_mvm_has_new_ats_coex_api(struct iwl_mvm *mvm)
IWL_UCODE_TLV_API_COEX_ATS_EXTERNAL);
}
static inline bool iwl_mvm_has_quota_low_latency(struct iwl_mvm *mvm)
{
return fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY);
}
static inline struct agg_tx_status *
iwl_mvm_get_agg_status(struct iwl_mvm *mvm, void *tx_resp)
{
......@@ -1486,6 +1488,27 @@ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
/* Quota management */
static inline size_t iwl_mvm_quota_cmd_size(struct iwl_mvm *mvm)
{
return iwl_mvm_has_quota_low_latency(mvm) ?
sizeof(struct iwl_time_quota_cmd) :
sizeof(struct iwl_time_quota_cmd_v1);
}
static inline struct iwl_time_quota_data
*iwl_mvm_quota_cmd_get_quota(struct iwl_mvm *mvm,
struct iwl_time_quota_cmd *cmd,
int i)
{
struct iwl_time_quota_data_v1 *quotas;
if (iwl_mvm_has_quota_low_latency(mvm))
return &cmd->quotas[i];
quotas = (struct iwl_time_quota_data_v1 *)cmd->quotas;
return (struct iwl_time_quota_data *)&quotas[i];
}
int iwl_mvm_update_quotas(struct iwl_mvm *mvm, bool force_upload,
struct ieee80211_vif *disabled_vif);
......@@ -1818,12 +1841,10 @@ unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
bool tdls, bool cmd_q);
void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
const char *errmsg);
/* Link Quality Measurement */
int iwl_mvm_send_lqm_cmd(struct ieee80211_vif *vif,
enum iwl_lqm_cmd_operatrions operation,
u32 duration, u32 timeout);
bool iwl_mvm_lqm_active(struct iwl_mvm *mvm);
void iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
const struct ieee80211_sta *sta,
u16 tid);
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b);
int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm);
......
......@@ -73,6 +73,7 @@
#include "iwl-eeprom-read.h"
#include "iwl-nvm-parse.h"
#include "iwl-prph.h"
#include "fw/acpi.h"
/* Default NVM size to read */
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024)
......@@ -295,18 +296,24 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
const __be16 *hw;
const __le16 *sw, *calib, *regulatory, *mac_override, *phy_sku;
bool lar_enabled;
int regulatory_type;
/* Checking for required sections */
if (!mvm->trans->cfg->ext_nvm) {
if (mvm->trans->cfg->nvm_type != IWL_NVM_EXT) {
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n");
return NULL;
}
} else {
if (mvm->trans->cfg->nvm_type == IWL_NVM_SDP)
regulatory_type = NVM_SECTION_TYPE_REGULATORY_SDP;
else
regulatory_type = NVM_SECTION_TYPE_REGULATORY;
/* SW and REGULATORY sections are mandatory */
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
!mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) {
!mvm->nvm_sections[regulatory_type].data) {
IWL_ERR(mvm,
"Can't parse empty family 8000 OTP/NVM sections\n");
return NULL;
......@@ -330,11 +337,14 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
hw = (const __be16 *)sections[mvm->cfg->nvm_hw_section_num].data;
sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data;
calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data;
regulatory = (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data;
mac_override =
(const __le16 *)sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data;
phy_sku = (const __le16 *)sections[NVM_SECTION_TYPE_PHY_SKU].data;
regulatory = mvm->trans->cfg->nvm_type == IWL_NVM_SDP ?
(const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY_SDP].data :
(const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data;
lar_enabled = !iwlwifi_mod_params.lar_disable &&
fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
......@@ -394,7 +404,7 @@ int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n");
/* Maximal size depends on NVM version */
if (!mvm->trans->cfg->ext_nvm)
if (mvm->trans->cfg->nvm_type != IWL_NVM_EXT)
max_section_size = IWL_MAX_NVM_SECTION_SIZE;
else
max_section_size = IWL_MAX_EXT_NVM_SECTION_SIZE;
......@@ -465,7 +475,7 @@ int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
break;
}
if (!mvm->trans->cfg->ext_nvm) {
if (mvm->trans->cfg->nvm_type != IWL_NVM_EXT) {
section_size =
2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1));
section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2));
......@@ -740,7 +750,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
struct ieee80211_regdomain *regd;
char mcc[3];
if (mvm->cfg->ext_nvm) {
if (mvm->cfg->nvm_type == IWL_NVM_EXT) {
tlv_lar = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_LAR_SUPPORT);
nvm_lar = mvm->nvm_data->lar_enabled;
......@@ -775,7 +785,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
return -EIO;
if (iwl_mvm_is_wifi_mcc_supported(mvm) &&
!iwl_get_bios_mcc(mvm->dev, mcc)) {
!iwl_acpi_get_mcc(mvm->dev, mcc)) {
kfree(regd);
regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc,
MCC_SOURCE_BIOS, NULL);
......
......@@ -86,6 +86,7 @@
#include "time-event.h"
#include "fw-api.h"
#include "fw/api/scan.h"
#include "fw/acpi.h"
#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux"
MODULE_DESCRIPTION(DRV_DESCRIPTION);
......@@ -423,8 +424,6 @@ static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
* Access is done through binary search
*/
static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {
HCMD_NAME(LINK_QUALITY_MEASUREMENT_CMD),
HCMD_NAME(LINK_QUALITY_MEASUREMENT_COMPLETE_NOTIF),
HCMD_NAME(CHANNEL_SWITCH_NOA_NOTIF),
};
......@@ -490,18 +489,21 @@ static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
static void iwl_mvm_async_handlers_wk(struct work_struct *wk);
static void iwl_mvm_d0i3_exit_work(struct work_struct *wk);
static u32 calc_min_backoff(struct iwl_trans *trans, const struct iwl_cfg *cfg)
static u32 iwl_mvm_min_backoff(struct iwl_mvm *mvm)
{
const struct iwl_pwr_tx_backoff *pwr_tx_backoff = cfg->pwr_tx_backoffs;
const struct iwl_pwr_tx_backoff *backoff = mvm->cfg->pwr_tx_backoffs;
u64 dflt_pwr_limit;
if (!pwr_tx_backoff)
if (!backoff)
return 0;
while (pwr_tx_backoff->pwr) {
if (trans->dflt_pwr_limit >= pwr_tx_backoff->pwr)
return pwr_tx_backoff->backoff;
dflt_pwr_limit = iwl_acpi_get_pwr_limit(mvm->dev);
pwr_tx_backoff++;
while (backoff->pwr) {
if (dflt_pwr_limit >= backoff->pwr)
return backoff->backoff;
backoff++;
}
return 0;
......@@ -771,7 +773,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
goto out_free;
mvm->hw_registered = true;
min_backoff = calc_min_backoff(trans, cfg);
min_backoff = iwl_mvm_min_backoff(mvm);
iwl_mvm_thermal_initialize(mvm, min_backoff);
err = iwl_mvm_dbgfs_register(mvm, dbgfs_dir);
......
......@@ -272,6 +272,7 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
}
ctxt->channel = chandef->chan;
ctxt->width = chandef->width;
return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
chains_static, chains_dynamic,
action, 0);
......
......@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
......@@ -34,7 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -164,9 +164,12 @@ static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm,
beacon_int = mvm->noa_vif->bss_conf.beacon_int;
for (i = 0; i < MAX_BINDINGS; i++) {
u32 id_n_c = le32_to_cpu(cmd->quotas[i].id_and_color);
struct iwl_time_quota_data *data =
iwl_mvm_quota_cmd_get_quota(mvm, cmd,
i);
u32 id_n_c = le32_to_cpu(data->id_and_color);
u32 id = (id_n_c & FW_CTXT_ID_MSK) >> FW_CTXT_ID_POS;
u32 quota = le32_to_cpu(cmd->quotas[i].quota);
u32 quota = le32_to_cpu(data->quota);
if (id != phy_id)
continue;
......@@ -175,9 +178,9 @@ static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm,
quota /= beacon_int;
IWL_DEBUG_QUOTA(mvm, "quota: adjust for NoA from %d to %d\n",
le32_to_cpu(cmd->quotas[i].quota), quota);
le32_to_cpu(data->quota), quota);
cmd->quotas[i].quota = cpu_to_le32(quota);
data->quota = cpu_to_le32(quota);
}
#endif
}
......@@ -194,6 +197,7 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
.disabled_vif = disabled_vif,
};
struct iwl_time_quota_cmd *last = &mvm->last_quota_cmd;
struct iwl_time_quota_data *qdata, *last_data;
bool send = false;
lockdep_assert_held(&mvm->mutex);
......@@ -216,7 +220,8 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
*/
num_active_macs = 0;
for (i = 0; i < MAX_BINDINGS; i++) {
cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID);
qdata = iwl_mvm_quota_cmd_get_quota(mvm, &cmd, i);
qdata->id_and_color = cpu_to_le32(FW_CTXT_INVALID);
num_active_macs += data.n_interfaces[i];
}
......@@ -265,14 +270,16 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
if (data.colors[i] < 0)
continue;
cmd.quotas[idx].id_and_color =
qdata = iwl_mvm_quota_cmd_get_quota(mvm, &cmd, idx);
qdata->id_and_color =
cpu_to_le32(FW_CMD_ID_AND_COLOR(i, data.colors[i]));
if (data.n_interfaces[i] <= 0)
cmd.quotas[idx].quota = cpu_to_le32(0);
qdata->quota = cpu_to_le32(0);
#ifdef CONFIG_IWLWIFI_DEBUGFS
else if (data.dbgfs_min[i])
cmd.quotas[idx].quota =
qdata->quota =
cpu_to_le32(data.dbgfs_min[i] * QUOTA_100 / 100);
#endif
else if (data.n_low_latency_bindings == 1 && n_non_lowlat &&
......@@ -283,24 +290,25 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
* the minimal required quota for the low latency
* binding.
*/
cmd.quotas[idx].quota = cpu_to_le32(QUOTA_LOWLAT_MIN);
qdata->quota = cpu_to_le32(QUOTA_LOWLAT_MIN);
else
cmd.quotas[idx].quota =
qdata->quota =
cpu_to_le32(quota * data.n_interfaces[i]);
WARN_ONCE(le32_to_cpu(cmd.quotas[idx].quota) > QUOTA_100,
WARN_ONCE(le32_to_cpu(qdata->quota) > QUOTA_100,
"Binding=%d, quota=%u > max=%u\n",
idx, le32_to_cpu(cmd.quotas[idx].quota), QUOTA_100);
idx, le32_to_cpu(qdata->quota), QUOTA_100);
cmd.quotas[idx].max_duration = cpu_to_le32(0);
qdata->max_duration = cpu_to_le32(0);
idx++;
}
/* Give the remainder of the session to the first data binding */
for (i = 0; i < MAX_BINDINGS; i++) {
if (le32_to_cpu(cmd.quotas[i].quota) != 0) {
le32_add_cpu(&cmd.quotas[i].quota, quota_rem);
qdata = iwl_mvm_quota_cmd_get_quota(mvm, &cmd, i);
if (le32_to_cpu(qdata->quota) != 0) {
le32_add_cpu(&qdata->quota, quota_rem);
IWL_DEBUG_QUOTA(mvm,
"quota: giving remainder of %d to binding %d\n",
quota_rem, i);
......@@ -312,17 +320,19 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
/* check that we have non-zero quota for all valid bindings */
for (i = 0; i < MAX_BINDINGS; i++) {
if (cmd.quotas[i].id_and_color != last->quotas[i].id_and_color)
qdata = iwl_mvm_quota_cmd_get_quota(mvm, &cmd, i);
last_data = iwl_mvm_quota_cmd_get_quota(mvm, last, i);
if (qdata->id_and_color != last_data->id_and_color)
send = true;
if (cmd.quotas[i].max_duration != last->quotas[i].max_duration)
if (qdata->max_duration != last_data->max_duration)
send = true;
if (abs((int)le32_to_cpu(cmd.quotas[i].quota) -
(int)le32_to_cpu(last->quotas[i].quota))
if (abs((int)le32_to_cpu(qdata->quota) -
(int)le32_to_cpu(last_data->quota))
> IWL_MVM_QUOTA_THRESHOLD)
send = true;
if (cmd.quotas[i].id_and_color == cpu_to_le32(FW_CTXT_INVALID))
if (qdata->id_and_color == cpu_to_le32(FW_CTXT_INVALID))
continue;
WARN_ONCE(cmd.quotas[i].quota == 0,
WARN_ONCE(qdata->quota == 0,
"zero quota on binding %d\n", i);
}
......@@ -334,7 +344,8 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
return 0;
}
err = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0, sizeof(cmd), &cmd);
err = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0,
iwl_mvm_quota_cmd_size(mvm), &cmd);
if (err)
IWL_ERR(mvm, "Failed to send quota: %d\n", err);
......
......@@ -244,7 +244,9 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
return 0;
default:
IWL_ERR(mvm, "Unhandled alg: 0x%x\n", rx_pkt_status);
/* Expected in monitor (not having the keys) */
if (!mvm->monitor_on)
IWL_ERR(mvm, "Unhandled alg: 0x%x\n", rx_pkt_status);
}
return 0;
......@@ -661,11 +663,10 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
expected_size = sizeof(struct iwl_notif_statistics_cdb);
}
if (iwl_rx_packet_payload_len(pkt) != expected_size) {
IWL_ERR(mvm, "received invalid statistics size (%d)!\n",
iwl_rx_packet_payload_len(pkt));
if (WARN_ONCE(iwl_rx_packet_payload_len(pkt) != expected_size,
"received invalid statistics size (%d)!\n",
iwl_rx_packet_payload_len(pkt)))
return;
}
if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
struct iwl_notif_statistics_v11 *stats = (void *)&pkt->data;
......
......@@ -277,7 +277,9 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
stats->flag |= RX_FLAG_DECRYPTED;
return 0;
default:
IWL_ERR(mvm, "Unhandled alg: 0x%x\n", status);
/* Expected in monitor (not having the keys) */
if (!mvm->monitor_on)
IWL_ERR(mvm, "Unhandled alg: 0x%x\n", status);
}
return 0;
......@@ -492,13 +494,18 @@ void iwl_mvm_reorder_timer_expired(unsigned long data)
if (expired) {
struct ieee80211_sta *sta;
struct iwl_mvm_sta *mvmsta;
rcu_read_lock();
sta = rcu_dereference(buf->mvm->fw_id_to_mac_id[buf->sta_id]);
mvmsta = iwl_mvm_sta_from_mac80211(sta);
/* SN is set to the last expired frame + 1 */
IWL_DEBUG_HT(buf->mvm,
"Releasing expired frames for sta %u, sn %d\n",
buf->sta_id, sn);
iwl_mvm_event_frame_timeout_callback(buf->mvm, mvmsta->vif,
sta, buf->tid);
iwl_mvm_release_frames(buf->mvm, sta, NULL, buf, sn);
rcu_read_unlock();
} else {
......@@ -619,7 +626,8 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
return false;
/* no sta yet */
if (WARN_ON(IS_ERR_OR_NULL(sta)))
if (WARN_ONCE(IS_ERR_OR_NULL(sta),
"Got valid BAID without a valid station assigned\n"))
return false;
mvm_sta = iwl_mvm_sta_from_mac80211(sta);
......
......@@ -2158,6 +2158,7 @@ static void iwl_mvm_init_reorder_buffer(struct iwl_mvm *mvm,
reorder_buf->mvm = mvm;
reorder_buf->queue = i;
reorder_buf->sta_id = sta_id;
reorder_buf->tid = data->tid;
reorder_buf->valid = false;
for (j = 0; j < reorder_buf->buf_size; j++)
__skb_queue_head_init(&reorder_buf->entries[j]);
......
......@@ -631,7 +631,7 @@ static int iwl_mvm_tzone_get_temp(struct thermal_zone_device *device,
if (!iwl_mvm_firmware_running(mvm) ||
mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR) {
ret = -EIO;
ret = -ENODATA;
goto out;
}
......
......@@ -1368,6 +1368,31 @@ void iwl_mvm_inactivity_check(struct iwl_mvm *mvm)
rcu_read_unlock();
}
void iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
const struct ieee80211_sta *sta,
u16 tid)
{
struct iwl_fw_dbg_trigger_tlv *trig;
struct iwl_fw_dbg_trigger_ba *ba_trig;
if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA))
return;
trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA);
ba_trig = (void *)trig->data;
if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt,
ieee80211_vif_to_wdev(vif), trig))
return;
if (!(le16_to_cpu(ba_trig->frame_timeout) & BIT(tid)))
return;
iwl_fw_dbg_collect_trig(&mvm->fwrt, trig,
"Frame from %pM timed out, tid %d",
sta->addr, tid);
}
void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, u32 *gp2, u64 *boottime)
{
bool ps_disabled;
......@@ -1389,74 +1414,3 @@ void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, u32 *gp2, u64 *boottime)
iwl_mvm_power_update_device(mvm);
}
}
int iwl_mvm_send_lqm_cmd(struct ieee80211_vif *vif,
enum iwl_lqm_cmd_operatrions operation,
u32 duration, u32 timeout)
{
struct iwl_mvm_vif *mvm_vif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_link_qual_msrmnt_cmd cmd = {
.cmd_operation = cpu_to_le32(operation),
.mac_id = cpu_to_le32(mvm_vif->id),
.measurement_time = cpu_to_le32(duration),
.timeout = cpu_to_le32(timeout),
};
u32 cmdid =
iwl_cmd_id(LINK_QUALITY_MEASUREMENT_CMD, MAC_CONF_GROUP, 0);
int ret;
if (!fw_has_capa(&mvm_vif->mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_LQM_SUPPORT))
return -EOPNOTSUPP;
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
return -EINVAL;
switch (operation) {
case LQM_CMD_OPERATION_START_MEASUREMENT:
if (iwl_mvm_lqm_active(mvm_vif->mvm))
return -EBUSY;
if (!vif->bss_conf.assoc)
return -EINVAL;
mvm_vif->lqm_active = true;
break;
case LQM_CMD_OPERATION_STOP_MEASUREMENT:
if (!iwl_mvm_lqm_active(mvm_vif->mvm))
return -EINVAL;
break;
default:
return -EINVAL;
}
ret = iwl_mvm_send_cmd_pdu(mvm_vif->mvm, cmdid, 0, sizeof(cmd),
&cmd);
/* command failed - roll back lqm_active state */
if (ret) {
mvm_vif->lqm_active =
operation == LQM_CMD_OPERATION_STOP_MEASUREMENT;
}
return ret;
}
static void iwl_mvm_lqm_active_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvm_vif = iwl_mvm_vif_from_mac80211(vif);
bool *lqm_active = _data;
*lqm_active = *lqm_active || mvm_vif->lqm_active;
}
bool iwl_mvm_lqm_active(struct iwl_mvm *mvm)
{
bool ret = false;
lockdep_assert_held(&mvm->mutex);
ieee80211_iterate_active_interfaces_atomic(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_lqm_active_iterator, &ret);
return ret;
}
......@@ -244,7 +244,7 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
ctxt_info->hcmd_cfg.cmd_queue_addr =
cpu_to_le64(trans_pcie->txq[trans_pcie->cmd_queue]->dma_addr);
ctxt_info->hcmd_cfg.cmd_queue_size =
TFD_QUEUE_CB_SIZE(TFD_CMD_SLOTS);
TFD_QUEUE_CB_SIZE(trans_pcie->tx_cmd_queue_size);
/* allocate ucode sections in dram and set addresses */
ret = iwl_pcie_ctxt_info_init_fw_sec(trans, fw, ctxt_info);
......
......@@ -73,6 +73,8 @@
#include <linux/pci-aspm.h>
#include <linux/acpi.h>
#include "fw/acpi.h"
#include "iwl-trans.h"
#include "iwl-drv.h"
#include "internal.h"
......@@ -576,7 +578,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x2720, 0x0000, iwla000_2ax_cfg_hr)},
{IWL_PCI_DEVICE(0x34F0, 0x0070, iwla000_2ax_cfg_hr)},
{IWL_PCI_DEVICE(0x2720, 0x0078, iwla000_2ax_cfg_hr)},
{IWL_PCI_DEVICE(0x2720, 0x0070, iwla000_2ax_cfg_hr)},
{IWL_PCI_DEVICE(0x2720, 0x0070, iwla000_2ac_cfg_hr_cdb)},
{IWL_PCI_DEVICE(0x2720, 0x0030, iwla000_2ac_cfg_hr_cdb)},
{IWL_PCI_DEVICE(0x2720, 0x1080, iwla000_2ax_cfg_hr)},
#endif /* CONFIG_IWLMVM */
......@@ -584,99 +587,6 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
};
MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
#ifdef CONFIG_ACPI
#define ACPI_SPLC_METHOD "SPLC"
#define ACPI_SPLC_DOMAIN_WIFI (0x07)
static u64 splc_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splc)
{
union acpi_object *data_pkg, *dflt_pwr_limit;
int i;
/* We need at least two elements, one for the revision and one
* for the data itself. Also check that the revision is
* supported (currently only revision 0).
*/
if (splc->type != ACPI_TYPE_PACKAGE ||
splc->package.count < 2 ||
splc->package.elements[0].type != ACPI_TYPE_INTEGER ||
splc->package.elements[0].integer.value != 0) {
IWL_DEBUG_INFO(trans,
"Unsupported structure returned by the SPLC method. Ignoring.\n");
return 0;
}
/* loop through all the packages to find the one for WiFi */
for (i = 1; i < splc->package.count; i++) {
union acpi_object *domain;
data_pkg = &splc->package.elements[i];
/* Skip anything that is not a package with the right
* amount of elements (i.e. at least 2 integers).
*/
if (data_pkg->type != ACPI_TYPE_PACKAGE ||
data_pkg->package.count < 2 ||
data_pkg->package.elements[0].type != ACPI_TYPE_INTEGER ||
data_pkg->package.elements[1].type != ACPI_TYPE_INTEGER)
continue;
domain = &data_pkg->package.elements[0];
if (domain->integer.value == ACPI_SPLC_DOMAIN_WIFI)
break;
data_pkg = NULL;
}
if (!data_pkg) {
IWL_DEBUG_INFO(trans,
"No element for the WiFi domain returned by the SPLC method.\n");
return 0;
}
dflt_pwr_limit = &data_pkg->package.elements[1];
return dflt_pwr_limit->integer.value;
}
static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev)
{
acpi_handle pxsx_handle;
acpi_handle handle;
struct acpi_buffer splc = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
pxsx_handle = ACPI_HANDLE(&pdev->dev);
if (!pxsx_handle) {
IWL_DEBUG_INFO(trans,
"Could not retrieve root port ACPI handle\n");
return;
}
/* Get the method's handle */
status = acpi_get_handle(pxsx_handle, (acpi_string)ACPI_SPLC_METHOD,
&handle);
if (ACPI_FAILURE(status)) {
IWL_DEBUG_INFO(trans, "SPLC method not found\n");
return;
}
/* Call SPLC with no arguments */
status = acpi_evaluate_object(handle, NULL, NULL, &splc);
if (ACPI_FAILURE(status)) {
IWL_ERR(trans, "SPLC invocation failed (0x%x)\n", status);
return;
}
trans->dflt_pwr_limit = splc_get_pwr_limit(trans, splc.pointer);
IWL_DEBUG_INFO(trans, "Default power limit set to %lld\n",
trans->dflt_pwr_limit);
kfree(splc.pointer);
}
#else /* CONFIG_ACPI */
static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev) {}
#endif
/* PCI registers */
#define PCI_CFG_RETRY_TIMEOUT 0x041
......@@ -740,8 +650,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_free_trans;
}
set_dflt_pwr_limit(iwl_trans, pdev);
/* register transport layer debugfs here */
ret = iwl_trans_pcie_dbgfs_register(iwl_trans);
if (ret)
......
......@@ -383,6 +383,7 @@ struct iwl_self_init_dram {
* @hw_init_mask: initial unmasked hw causes
* @fh_mask: current unmasked fh causes
* @hw_mask: current unmasked hw causes
* @tx_cmd_queue_size: the size of the tx command queue
*/
struct iwl_trans_pcie {
struct iwl_rxq *rxq;
......@@ -442,6 +443,7 @@ struct iwl_trans_pcie {
bool bc_table_dword;
bool scd_set_active;
bool sw_csum_tx;
bool pcie_dbg_dumped_once;
u32 rx_page_order;
/*protect hw register */
......@@ -463,6 +465,7 @@ struct iwl_trans_pcie {
u32 fh_mask;
u32 hw_mask;
cpumask_t affinity_mask[IWL_MAX_RX_HW_QUEUES];
u16 tx_cmd_queue_size;
};
static inline struct iwl_trans_pcie *
......@@ -534,6 +537,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
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);
void iwl_pcie_set_tx_cmd_queue_size(struct iwl_trans *trans);
static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_trans *trans, void *_tfd,
u8 idx)
......
......@@ -88,6 +88,93 @@
#define IWL_FW_MEM_EXTENDED_START 0x40000
#define IWL_FW_MEM_EXTENDED_END 0x57FFF
static void iwl_trans_pcie_err_dump(struct iwl_trans *trans)
{
#define PCI_DUMP_SIZE 64
#define PREFIX_LEN 32
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct pci_dev *pdev = trans_pcie->pci_dev;
u32 i, pos, alloc_size, *ptr, *buf;
char *prefix;
if (trans_pcie->pcie_dbg_dumped_once)
return;
/* Should be a multiple of 4 */
BUILD_BUG_ON(PCI_DUMP_SIZE > 4096 || PCI_DUMP_SIZE & 0x3);
/* Alloc a max size buffer */
if (PCI_ERR_ROOT_ERR_SRC + 4 > PCI_DUMP_SIZE)
alloc_size = PCI_ERR_ROOT_ERR_SRC + 4 + PREFIX_LEN;
else
alloc_size = PCI_DUMP_SIZE + PREFIX_LEN;
buf = kmalloc(alloc_size, GFP_ATOMIC);
if (!buf)
return;
prefix = (char *)buf + alloc_size - PREFIX_LEN;
IWL_ERR(trans, "iwlwifi transaction failed, dumping registers\n");
/* Print wifi device registers */
sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
IWL_ERR(trans, "iwlwifi device config registers:\n");
for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++)
if (pci_read_config_dword(pdev, i, ptr))
goto err_read;
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
IWL_ERR(trans, "iwlwifi device memory mapped registers:\n");
for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++)
*ptr = iwl_read32(trans, i);
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
if (pos) {
IWL_ERR(trans, "iwlwifi device AER capability structure:\n");
for (i = 0, ptr = buf; i < PCI_ERR_ROOT_COMMAND; i += 4, ptr++)
if (pci_read_config_dword(pdev, pos + i, ptr))
goto err_read;
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET,
32, 4, buf, i, 0);
}
/* Print parent device registers next */
if (!pdev->bus->self)
goto out;
pdev = pdev->bus->self;
sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
IWL_ERR(trans, "iwlwifi parent port (%s) config registers:\n",
pci_name(pdev));
for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++)
if (pci_read_config_dword(pdev, i, ptr))
goto err_read;
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
/* Print root port AER registers */
pos = 0;
pdev = pcie_find_root_port(pdev);
if (pdev)
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
if (pos) {
IWL_ERR(trans, "iwlwifi root port (%s) AER cap structure:\n",
pci_name(pdev));
sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
for (i = 0, ptr = buf; i <= PCI_ERR_ROOT_ERR_SRC; i += 4, ptr++)
if (pci_read_config_dword(pdev, pos + i, ptr))
goto err_read;
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32,
4, buf, i, 0);
}
err_read:
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
IWL_ERR(trans, "Read failed at 0x%X\n", i);
out:
trans_pcie->pcie_dbg_dumped_once = 1;
kfree(buf);
}
static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
......@@ -649,6 +736,7 @@ static int iwl_pcie_load_firmware_chunk(struct iwl_trans *trans,
trans_pcie->ucode_write_complete, 5 * HZ);
if (!ret) {
IWL_ERR(trans, "Failed to load firmware chunk!\n");
iwl_trans_pcie_err_dump(trans);
return -ETIMEDOUT;
}
......@@ -1868,6 +1956,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans,
(CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
if (unlikely(ret < 0)) {
iwl_trans_pcie_err_dump(trans);
iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
WARN_ONCE(1,
"Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n",
......
......@@ -1160,6 +1160,8 @@ int iwl_pcie_gen2_tx_init(struct iwl_trans *trans)
struct iwl_txq *cmd_queue;
int txq_id = trans_pcie->cmd_queue, ret;
iwl_pcie_set_tx_cmd_queue_size(trans);
/* alloc and init the command queue */
if (!trans_pcie->txq[txq_id]) {
cmd_queue = kzalloc(sizeof(*cmd_queue), GFP_KERNEL);
......@@ -1168,7 +1170,8 @@ int iwl_pcie_gen2_tx_init(struct iwl_trans *trans)
return -ENOMEM;
}
trans_pcie->txq[txq_id] = cmd_queue;
ret = iwl_pcie_txq_alloc(trans, cmd_queue, TFD_CMD_SLOTS, true);
ret = iwl_pcie_txq_alloc(trans, cmd_queue,
trans_pcie->tx_cmd_queue_size, true);
if (ret) {
IWL_ERR(trans, "Tx %d queue init failed\n", txq_id);
goto error;
......@@ -1177,7 +1180,8 @@ int iwl_pcie_gen2_tx_init(struct iwl_trans *trans)
cmd_queue = trans_pcie->txq[txq_id];
}
ret = iwl_pcie_txq_init(trans, cmd_queue, TFD_CMD_SLOTS, true);
ret = iwl_pcie_txq_init(trans, cmd_queue,
trans_pcie->tx_cmd_queue_size, true);
if (ret) {
IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id);
goto error;
......
......@@ -951,7 +951,8 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
txq_id++) {
bool cmd_queue = (txq_id == trans_pcie->cmd_queue);
slots_num = cmd_queue ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
slots_num = cmd_queue ? trans_pcie->tx_cmd_queue_size :
TFD_TX_CMD_SLOTS;
trans_pcie->txq[txq_id] = &trans_pcie->txq_memory[txq_id];
ret = iwl_pcie_txq_alloc(trans, trans_pcie->txq[txq_id],
slots_num, cmd_queue);
......@@ -970,6 +971,21 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
return ret;
}
void iwl_pcie_set_tx_cmd_queue_size(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int queue_size = TFD_CMD_SLOTS;
if (trans->cfg->tx_cmd_queue_size)
queue_size = trans->cfg->tx_cmd_queue_size;
if (WARN_ON(!(is_power_of_2(queue_size) &&
TFD_QUEUE_CB_SIZE(queue_size) > 0)))
trans_pcie->tx_cmd_queue_size = TFD_CMD_SLOTS;
else
trans_pcie->tx_cmd_queue_size = queue_size;
}
int iwl_pcie_tx_init(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
......@@ -977,6 +993,8 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
int txq_id, slots_num;
bool alloc = false;
iwl_pcie_set_tx_cmd_queue_size(trans);
if (!trans_pcie->txq_memory) {
ret = iwl_pcie_tx_alloc(trans);
if (ret)
......@@ -1000,7 +1018,8 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
txq_id++) {
bool cmd_queue = (txq_id == trans_pcie->cmd_queue);
slots_num = cmd_queue ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
slots_num = cmd_queue ? trans_pcie->tx_cmd_queue_size :
TFD_TX_CMD_SLOTS;
ret = iwl_pcie_txq_init(trans, trans_pcie->txq[txq_id],
slots_num, cmd_queue);
if (ret) {
......
......@@ -852,12 +852,11 @@ void p54_unregister_common(struct ieee80211_hw *dev)
{
struct p54_common *priv = dev->priv;
#ifdef CONFIG_P54_LEDS
p54_unregister_leds(priv);
#endif /* CONFIG_P54_LEDS */
if (priv->registered) {
priv->registered = false;
#ifdef CONFIG_P54_LEDS
p54_unregister_leds(priv);
#endif /* CONFIG_P54_LEDS */
ieee80211_unregister_hw(dev);
}
......
......@@ -658,12 +658,6 @@ void mwifiex_11n_delba(struct mwifiex_private *priv, int tid)
unsigned long flags;
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
if (list_empty(&priv->rx_reorder_tbl_ptr)) {
dev_dbg(priv->adapter->dev,
"mwifiex_11n_delba: rx_reorder_tbl_ptr empty\n");
goto exit;
}
list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) {
if (rx_reor_tbl_ptr->tid == tid) {
dev_dbg(priv->adapter->dev,
......@@ -854,9 +848,6 @@ mwifiex_send_delba_txbastream_tbl(struct mwifiex_private *priv, u8 tid)
struct mwifiex_adapter *adapter = priv->adapter;
struct mwifiex_tx_ba_stream_tbl *tx_ba_stream_tbl_ptr;
if (list_empty(&priv->tx_ba_stream_tbl_ptr))
return;
list_for_each_entry(tx_ba_stream_tbl_ptr,
&priv->tx_ba_stream_tbl_ptr, list) {
if (tx_ba_stream_tbl_ptr->ba_status == BA_SETUP_COMPLETE) {
......
......@@ -835,12 +835,6 @@ void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags)
continue;
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags);
if (list_empty(&priv->rx_reorder_tbl_ptr)) {
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
lock_flags);
continue;
}
list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list)
tbl->flags = flags;
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags);
......
......@@ -142,7 +142,7 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
u8 key_index, bool pairwise, const u8 *mac_addr)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) {
......@@ -454,7 +454,7 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
struct mwifiex_wep_key *wep_key;
const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
......@@ -2503,6 +2503,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
struct ieee80211_channel *chan;
struct ieee_types_header *ie;
struct mwifiex_user_scan_cfg *user_scan_cfg;
u8 mac_addr[ETH_ALEN];
mwifiex_dbg(priv->adapter, CMD,
"info: received scan request on %s\n", dev->name);
......@@ -2529,15 +2530,10 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
priv->scan_request = request;
if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
ether_addr_copy(priv->random_mac, request->mac_addr);
for (i = 0; i < ETH_ALEN; i++) {
priv->random_mac[i] &= request->mac_addr_mask[i];
priv->random_mac[i] |= get_random_int() &
~(request->mac_addr_mask[i]);
}
ether_addr_copy(user_scan_cfg->random_mac, priv->random_mac);
} else {
eth_zero_addr(priv->random_mac);
get_random_mask_addr(mac_addr, request->mac_addr,
request->mac_addr_mask);
ether_addr_copy(request->mac_addr, mac_addr);
ether_addr_copy(user_scan_cfg->random_mac, mac_addr);
}
user_scan_cfg->num_ssids = request->n_ssids;
......@@ -2959,18 +2955,21 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
}
mwifiex_init_priv_params(priv, dev);
mwifiex_set_mac_address(priv, dev);
priv->netdev = dev;
ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
HostCmd_ACT_GEN_SET, 0, NULL, true);
if (ret)
goto err_set_bss_mode;
if (!adapter->mfg_mode) {
mwifiex_set_mac_address(priv, dev);
ret = mwifiex_sta_init_cmd(priv, false, false);
if (ret)
goto err_sta_init;
ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
HostCmd_ACT_GEN_SET, 0, NULL, true);
if (ret)
goto err_set_bss_mode;
ret = mwifiex_sta_init_cmd(priv, false, false);
if (ret)
goto err_sta_init;
}
mwifiex_setup_ht_caps(&wiphy->bands[NL80211_BAND_2GHZ]->ht_cap, priv);
if (adapter->is_hw_11ac_capable)
......@@ -3250,8 +3249,8 @@ static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv,
int i, filt_num = 0, ret = 0;
bool first_pat = true;
u8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1];
const u8 ipv4_mc_mac[] = {0x33, 0x33};
const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
static const u8 ipv4_mc_mac[] = {0x33, 0x33};
static const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
mef_entry->mode = MEF_MODE_HOST_SLEEP;
mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST;
......@@ -3544,9 +3543,9 @@ static int mwifiex_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
static int mwifiex_get_coalesce_pkt_type(u8 *byte_seq)
{
const u8 ipv4_mc_mac[] = {0x33, 0x33};
const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff};
static const u8 ipv4_mc_mac[] = {0x33, 0x33};
static const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
static const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff};
if ((byte_seq[0] & 0x01) &&
(byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 1))
......@@ -3795,9 +3794,8 @@ mwifiex_cfg80211_tdls_chan_switch(struct wiphy *wiphy, struct net_device *dev,
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
sta_ptr = mwifiex_get_sta_entry(priv, addr);
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
if (!sta_ptr) {
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
__func__, addr);
return -ENOENT;
......@@ -3805,15 +3803,18 @@ mwifiex_cfg80211_tdls_chan_switch(struct wiphy *wiphy, struct net_device *dev,
if (!(sta_ptr->tdls_cap.extcap.ext_capab[3] &
WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)) {
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
wiphy_err(wiphy, "%pM do not support tdls cs\n", addr);
return -ENOENT;
}
if (sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
sta_ptr->tdls_status == TDLS_IN_OFF_CHAN) {
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
wiphy_err(wiphy, "channel switch is running, abort request\n");
return -EALREADY;
}
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
chan = chandef->chan->hw_value;
second_chan_offset = mwifiex_get_sec_chan_offset(chan);
......@@ -3834,18 +3835,20 @@ mwifiex_cfg80211_tdls_cancel_chan_switch(struct wiphy *wiphy,
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
sta_ptr = mwifiex_get_sta_entry(priv, addr);
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
if (!sta_ptr) {
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
__func__, addr);
} else if (!(sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
sta_ptr->tdls_status == TDLS_IN_BASE_CHAN ||
sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)) {
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
wiphy_err(wiphy, "tdls chan switch not initialize by %pM\n",
addr);
} else
} else {
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
mwifiex_stop_tdls_cs(priv, addr);
}
}
static int
......@@ -4202,7 +4205,10 @@ int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter)
if (adapter->config_bands & BAND_A)
n_channels_a = mwifiex_band_5ghz.n_channels;
adapter->num_in_chan_stats = n_channels_bg + n_channels_a;
/* allocate twice the number total channels, since the driver issues an
* additional active scan request for hidden SSIDs on passive channels.
*/
adapter->num_in_chan_stats = 2 * (n_channels_bg + n_channels_a);
adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) *
adapter->num_in_chan_stats);
......@@ -4306,10 +4312,12 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
wiphy->features |= NL80211_FEATURE_HT_IBSS |
NL80211_FEATURE_INACTIVITY_TIMER |
NL80211_FEATURE_LOW_PRIORITY_SCAN |
NL80211_FEATURE_NEED_OBSS_SCAN |
NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR |
NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
NL80211_FEATURE_NEED_OBSS_SCAN;
if (ISSUPP_RANDOM_MAC(adapter->fw_cap_info))
wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR |
NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
......
......@@ -17,6 +17,7 @@
* this warranty disclaimer.
*/
#include <asm/unaligned.h>
#include "decl.h"
#include "ioctl.h"
#include "util.h"
......@@ -183,7 +184,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
uint16_t cmd_code;
uint16_t cmd_size;
unsigned long flags;
__le32 tmp;
if (!adapter || !cmd_node)
return -1;
......@@ -249,9 +249,9 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
mwifiex_dbg_dump(adapter, CMD_D, "cmd buffer:", host_cmd, cmd_size);
if (adapter->iface_type == MWIFIEX_USB) {
tmp = cpu_to_le32(MWIFIEX_USB_TYPE_CMD);
skb_push(cmd_node->cmd_skb, MWIFIEX_TYPE_LEN);
memcpy(cmd_node->cmd_skb->data, &tmp, MWIFIEX_TYPE_LEN);
put_unaligned_le32(MWIFIEX_USB_TYPE_CMD,
cmd_node->cmd_skb->data);
adapter->cmd_sent = true;
ret = adapter->if_ops.host_to_card(adapter,
MWIFIEX_USB_EP_CMD_EVENT,
......@@ -317,7 +317,6 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
(struct mwifiex_opt_sleep_confirm *)
adapter->sleep_cfm->data;
struct sk_buff *sleep_cfm_tmp;
__le32 tmp;
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
......@@ -342,8 +341,7 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
+ MWIFIEX_TYPE_LEN);
skb_put(sleep_cfm_tmp, sizeof(struct mwifiex_opt_sleep_confirm)
+ MWIFIEX_TYPE_LEN);
tmp = cpu_to_le32(MWIFIEX_USB_TYPE_CMD);
memcpy(sleep_cfm_tmp->data, &tmp, MWIFIEX_TYPE_LEN);
put_unaligned_le32(MWIFIEX_USB_TYPE_CMD, sleep_cfm_tmp->data);
memcpy(sleep_cfm_tmp->data + MWIFIEX_TYPE_LEN,
adapter->sleep_cfm->data,
sizeof(struct mwifiex_opt_sleep_confirm));
......
......@@ -238,6 +238,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define ISSUPP_DRCS_ENABLED(FwCapInfo) (FwCapInfo & BIT(15))
#define ISSUPP_SDIO_SPA_ENABLED(FwCapInfo) (FwCapInfo & BIT(16))
#define ISSUPP_ADHOC_ENABLED(FwCapInfo) (FwCapInfo & BIT(25))
#define ISSUPP_RANDOM_MAC(FwCapInfo) (FwCapInfo & BIT(27))
#define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \
(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \
......
......@@ -579,10 +579,6 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
{
spin_lock_irqsave(lock, flags);
if (list_empty(head)) {
spin_unlock_irqrestore(lock, flags);
continue;
}
list_for_each_entry_safe(bssprio_node, tmp_node, head,
list) {
if (bssprio_node->priv == priv) {
......
......@@ -680,7 +680,6 @@ struct mwifiex_private {
struct mwifiex_user_scan_chan hidden_chan[MWIFIEX_USER_SCAN_CHAN_MAX];
u8 assoc_resp_ht_param;
bool ht_param_present;
u8 random_mac[ETH_ALEN];
};
......
......@@ -1936,8 +1936,6 @@ mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
if (!user_scan_cfg)
return -ENOMEM;
memset(user_scan_cfg, 0, sizeof(*user_scan_cfg));
for (id = 0; id < MWIFIEX_USER_SCAN_CHAN_MAX; id++) {
if (!priv->hidden_chan[id].chan_number)
break;
......@@ -1948,7 +1946,8 @@ mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
adapter->active_scan_triggered = true;
if (priv->scan_request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
ether_addr_copy(user_scan_cfg->random_mac, priv->random_mac);
ether_addr_copy(user_scan_cfg->random_mac,
priv->scan_request->mac_addr);
user_scan_cfg->num_ssids = priv->scan_request->n_ssids;
user_scan_cfg->ssid_list = priv->scan_request->ssids;
......
......@@ -70,11 +70,7 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
break;
case HostCmd_CMD_802_11_SCAN:
case HostCmd_CMD_802_11_SCAN_EXT:
mwifiex_cancel_pending_scan_cmd(adapter);
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
adapter->scan_processing = false;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
mwifiex_cancel_scan(adapter);
break;
case HostCmd_CMD_MAC_CONTROL:
......
......@@ -359,13 +359,12 @@ static void mwifiex_process_uap_tx_pause(struct mwifiex_private *priv,
} else {
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
sta_ptr->tx_pause = tp->tx_pause;
mwifiex_update_ralist_tx_pause(priv, tp->peermac,
tp->tx_pause);
}
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
}
}
......@@ -396,14 +395,13 @@ static void mwifiex_process_sta_tx_pause(struct mwifiex_private *priv,
if (mwifiex_is_tdls_link_setup(status)) {
spin_lock_irqsave(&priv->sta_list_spinlock, flags);
sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
sta_ptr->tx_pause = tp->tx_pause;
mwifiex_update_ralist_tx_pause(priv,
tp->peermac,
tp->tx_pause);
}
spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
}
}
}
......
......@@ -1413,13 +1413,6 @@ void mwifiex_check_auto_tdls(unsigned long context)
priv->check_tdls_tx = false;
if (list_empty(&priv->auto_tdls_list)) {
mod_timer(&priv->auto_tdls_timer,
jiffies +
msecs_to_jiffies(MWIFIEX_TIMER_10S));
return;
}
spin_lock_irqsave(&priv->auto_tdls_lock, flags);
list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
if ((jiffies - tdls_peer->rssi_jiffies) >
......
......@@ -359,7 +359,8 @@ static enum mwifiex_wmm_ac_e
mwifiex_wmm_convert_tos_to_ac(struct mwifiex_adapter *adapter, u32 tos)
{
/* Map of TOS UP values to WMM AC */
const enum mwifiex_wmm_ac_e tos_to_ac[] = { WMM_AC_BE,
static const enum mwifiex_wmm_ac_e tos_to_ac[] = {
WMM_AC_BE,
WMM_AC_BK,
WMM_AC_BK,
WMM_AC_BE,
......
......@@ -133,6 +133,7 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
vif->netdev = NULL;
vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
eth_zero_addr(vif->mac_addr);
eth_zero_addr(vif->bssid);
return 0;
}
......@@ -201,6 +202,8 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy,
qtnf_cmd_send_del_intf(vif);
err_cmd:
vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
eth_zero_addr(vif->mac_addr);
eth_zero_addr(vif->bssid);
return ERR_PTR(-EFAULT);
}
......@@ -256,11 +259,6 @@ static int qtnf_change_beacon(struct wiphy *wiphy, struct net_device *dev,
{
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
if (!(vif->bss_status & QTNF_STATE_AP_START)) {
pr_err("VIF%u.%u: not started\n", vif->mac->macid, vif->vifid);
return -EFAULT;
}
return qtnf_mgmt_set_appie(vif, info);
}
......@@ -268,46 +266,15 @@ static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ap_settings *settings)
{
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
struct qtnf_wmac *mac = wiphy_priv(wiphy);
struct qtnf_bss_config *bss_cfg;
int ret;
if (!cfg80211_chandef_identical(&mac->chandef, &settings->chandef)) {
memcpy(&mac->chandef, &settings->chandef, sizeof(mac->chandef));
if (vif->vifid != 0)
pr_warn("%s: unexpected chan %u (%u MHz)\n", dev->name,
settings->chandef.chan->hw_value,
settings->chandef.chan->center_freq);
}
bss_cfg = &vif->bss_cfg;
memset(bss_cfg, 0, sizeof(*bss_cfg));
bss_cfg->bcn_period = settings->beacon_interval;
bss_cfg->dtim = settings->dtim_period;
bss_cfg->auth_type = settings->auth_type;
bss_cfg->privacy = settings->privacy;
bss_cfg->ssid_len = settings->ssid_len;
memcpy(&bss_cfg->ssid, settings->ssid, bss_cfg->ssid_len);
memcpy(&bss_cfg->crypto, &settings->crypto,
sizeof(struct cfg80211_crypto_settings));
ret = qtnf_cmd_send_config_ap(vif);
ret = qtnf_cmd_send_config_ap(vif, settings);
if (ret) {
pr_err("VIF%u.%u: failed to push config to FW\n",
vif->mac->macid, vif->vifid);
goto out;
}
if (!(vif->bss_status & QTNF_STATE_AP_CONFIG)) {
pr_err("VIF%u.%u: AP config failed in FW\n", vif->mac->macid,
vif->vifid);
ret = -EFAULT;
goto out;
}
ret = qtnf_mgmt_set_appie(vif, &settings->beacon);
if (ret) {
pr_err("VIF%u.%u: failed to add IEs to beacon\n",
......@@ -316,17 +283,9 @@ static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev,
}
ret = qtnf_cmd_send_start_ap(vif);
if (ret) {
if (ret)
pr_err("VIF%u.%u: failed to start AP\n", vif->mac->macid,
vif->vifid);
goto out;
}
if (!(vif->bss_status & QTNF_STATE_AP_START)) {
pr_err("VIF%u.%u: FW failed to start AP operation\n",
vif->mac->macid, vif->vifid);
ret = -EFAULT;
}
out:
return ret;
......@@ -343,8 +302,6 @@ static int qtnf_stop_ap(struct wiphy *wiphy, struct net_device *dev)
if (ret) {
pr_err("VIF%u.%u: failed to stop AP operation in FW\n",
vif->mac->macid, vif->vifid);
vif->bss_status &= ~QTNF_STATE_AP_START;
vif->bss_status &= ~QTNF_STATE_AP_CONFIG;
netif_carrier_off(vif->netdev);
}
......@@ -615,9 +572,6 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_connect_params *sme)
{
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
struct qtnf_wmac *mac = wiphy_priv(wiphy);
struct cfg80211_chan_def chandef;
struct qtnf_bss_config *bss_cfg;
int ret;
if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
......@@ -626,49 +580,10 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev,
if (vif->sta_state != QTNF_STA_DISCONNECTED)
return -EBUSY;
bss_cfg = &vif->bss_cfg;
memset(bss_cfg, 0, sizeof(*bss_cfg));
if (sme->channel) {
/* FIXME: need to set proper nl80211_channel_type value */
cfg80211_chandef_create(&chandef, sme->channel,
NL80211_CHAN_HT20);
/* fall-back to minimal safe chandef description */
if (!cfg80211_chandef_valid(&chandef))
cfg80211_chandef_create(&chandef, sme->channel,
NL80211_CHAN_HT20);
memcpy(&mac->chandef, &chandef, sizeof(mac->chandef));
}
bss_cfg->ssid_len = sme->ssid_len;
memcpy(&bss_cfg->ssid, sme->ssid, bss_cfg->ssid_len);
bss_cfg->auth_type = sme->auth_type;
bss_cfg->privacy = sme->privacy;
bss_cfg->mfp = sme->mfp;
if ((sme->bg_scan_period > 0) &&
(sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD))
bss_cfg->bg_scan_period = sme->bg_scan_period;
else if (sme->bg_scan_period == -1)
bss_cfg->bg_scan_period = QTNF_DEFAULT_BG_SCAN_PERIOD;
else
bss_cfg->bg_scan_period = 0; /* disabled */
bss_cfg->connect_flags = 0;
if (sme->flags & ASSOC_REQ_DISABLE_HT)
bss_cfg->connect_flags |= QLINK_STA_CONNECT_DISABLE_HT;
if (sme->flags & ASSOC_REQ_DISABLE_VHT)
bss_cfg->connect_flags |= QLINK_STA_CONNECT_DISABLE_VHT;
if (sme->flags & ASSOC_REQ_USE_RRM)
bss_cfg->connect_flags |= QLINK_STA_CONNECT_USE_RRM;
memcpy(&bss_cfg->crypto, &sme->crypto, sizeof(bss_cfg->crypto));
if (sme->bssid)
ether_addr_copy(bss_cfg->bssid, sme->bssid);
ether_addr_copy(vif->bssid, sme->bssid);
else
eth_zero_addr(bss_cfg->bssid);
eth_zero_addr(vif->bssid);
ret = qtnf_cmd_send_connect(vif, sme);
if (ret) {
......@@ -717,15 +632,15 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev,
int idx, struct survey_info *survey)
{
struct qtnf_wmac *mac = wiphy_priv(wiphy);
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct ieee80211_supported_band *sband;
struct cfg80211_chan_def *chandef;
const struct cfg80211_chan_def *chandef = &wdev->chandef;
struct ieee80211_channel *chan;
struct qtnf_chan_stats stats;
struct qtnf_vif *vif;
int ret;
vif = qtnf_netdev_get_priv(dev);
chandef = &mac->chandef;
sband = wiphy->bands[NL80211_BAND_2GHZ];
if (sband && idx >= sband->n_channels) {
......@@ -792,46 +707,35 @@ static int
qtnf_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
struct cfg80211_chan_def *chandef)
{
struct qtnf_wmac *mac = wiphy_priv(wiphy);
struct net_device *ndev = wdev->netdev;
struct qtnf_vif *vif;
int ret;
if (!ndev)
return -ENODEV;
vif = qtnf_netdev_get_priv(wdev->netdev);
switch (vif->wdev.iftype) {
case NL80211_IFTYPE_STATION:
if (vif->sta_state == QTNF_STA_DISCONNECTED) {
pr_warn("%s: STA disconnected\n", ndev->name);
return -ENODATA;
}
break;
case NL80211_IFTYPE_AP:
if (!(vif->bss_status & QTNF_STATE_AP_START)) {
pr_warn("%s: AP not started\n", ndev->name);
return -ENODATA;
}
break;
default:
pr_err("unsupported vif type (%d)\n", vif->wdev.iftype);
return -ENODATA;
ret = qtnf_cmd_get_channel(vif, chandef);
if (ret) {
pr_err("%s: failed to get channel: %d\n", ndev->name, ret);
goto out;
}
if (!cfg80211_chandef_valid(&mac->chandef)) {
pr_err("invalid channel settings on %s\n", ndev->name);
return -ENODATA;
if (!cfg80211_chandef_valid(chandef)) {
pr_err("%s: bad chan freq1=%u freq2=%u bw=%u\n", ndev->name,
chandef->center_freq1, chandef->center_freq2,
chandef->width);
ret = -ENODATA;
}
memcpy(chandef, &mac->chandef, sizeof(*chandef));
return 0;
out:
return ret;
}
static int qtnf_channel_switch(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_csa_settings *params)
{
struct qtnf_wmac *mac = wiphy_priv(wiphy);
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
int ret;
......@@ -839,41 +743,12 @@ static int qtnf_channel_switch(struct wiphy *wiphy, struct net_device *dev,
params->chandef.chan->hw_value, params->count,
params->radar_required, params->block_tx);
switch (vif->wdev.iftype) {
case NL80211_IFTYPE_AP:
if (!(vif->bss_status & QTNF_STATE_AP_START)) {
pr_warn("AP not started on %s\n", dev->name);
return -ENOTCONN;
}
break;
default:
pr_err("unsupported vif type (%d) on %s\n",
vif->wdev.iftype, dev->name);
return -EOPNOTSUPP;
}
if (vif->vifid != 0) {
if (!(mac->status & QTNF_MAC_CSA_ACTIVE))
return -EOPNOTSUPP;
if (!cfg80211_chandef_identical(&params->chandef,
&mac->csa_chandef))
return -EINVAL;
return 0;
}
if (!cfg80211_chandef_valid(&params->chandef)) {
pr_err("%s: invalid channel\n", dev->name);
return -EINVAL;
}
if (cfg80211_chandef_identical(&params->chandef, &mac->chandef)) {
pr_err("%s: switch request to the same channel\n", dev->name);
return -EALREADY;
}
ret = qtnf_cmd_send_chan_switch(mac, params);
ret = qtnf_cmd_send_chan_switch(vif, params);
if (ret)
pr_warn("%s: failed to switch to channel (%u)\n",
dev->name, params->chandef.chan->hw_value);
......@@ -1119,7 +994,7 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev)
break;
case QTNF_STA_CONNECTING:
cfg80211_connect_result(vif->netdev,
vif->bss_cfg.bssid, NULL, 0,
vif->bssid, NULL, 0,
NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
......@@ -1147,7 +1022,7 @@ void qtnf_cfg80211_vif_reset(struct qtnf_vif *vif)
switch (vif->sta_state) {
case QTNF_STA_CONNECTING:
cfg80211_connect_result(vif->netdev,
vif->bss_cfg.bssid, NULL, 0,
vif->bssid, NULL, 0,
NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
......
......@@ -173,7 +173,6 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif)
goto out;
}
vif->bss_status |= QTNF_STATE_AP_START;
netif_carrier_on(vif->netdev);
out:
......@@ -181,62 +180,68 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif)
return ret;
}
int qtnf_cmd_send_config_ap(struct qtnf_vif *vif)
int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
const struct cfg80211_ap_settings *s)
{
struct sk_buff *cmd_skb;
struct qtnf_bss_config *bss_cfg = &vif->bss_cfg;
struct cfg80211_chan_def *chandef = &vif->mac->chandef;
struct qlink_tlv_channel *qchan;
struct qlink_auth_encr aen;
struct qlink_cmd_config_ap *cmd;
struct qlink_auth_encr *aen;
u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
int i;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_CONFIG_AP,
sizeof(struct qlink_cmd));
sizeof(*cmd));
if (unlikely(!cmd_skb))
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, bss_cfg->ssid,
bss_cfg->ssid_len);
qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_BCN_PERIOD,
bss_cfg->bcn_period);
qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_DTIM, bss_cfg->dtim);
qchan = skb_put_zero(cmd_skb, sizeof(*qchan));
qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
qchan->hdr.len = cpu_to_le16(sizeof(*qchan) -
sizeof(struct qlink_tlv_hdr));
qchan->hw_value = cpu_to_le16(
ieee80211_frequency_to_channel(chandef->chan->center_freq));
memset(&aen, 0, sizeof(aen));
aen.auth_type = bss_cfg->auth_type;
aen.privacy = !!bss_cfg->privacy;
aen.mfp = bss_cfg->mfp;
aen.wpa_versions = cpu_to_le32(bss_cfg->crypto.wpa_versions);
aen.cipher_group = cpu_to_le32(bss_cfg->crypto.cipher_group);
aen.n_ciphers_pairwise = cpu_to_le32(
bss_cfg->crypto.n_ciphers_pairwise);
cmd = (struct qlink_cmd_config_ap *)cmd_skb->data;
cmd->dtim_period = s->dtim_period;
cmd->beacon_interval = cpu_to_le16(s->beacon_interval);
cmd->hidden_ssid = qlink_hidden_ssid_nl2q(s->hidden_ssid);
cmd->inactivity_timeout = cpu_to_le16(s->inactivity_timeout);
cmd->smps_mode = s->smps_mode;
cmd->p2p_ctwindow = s->p2p_ctwindow;
cmd->p2p_opp_ps = s->p2p_opp_ps;
cmd->pbss = s->pbss;
cmd->ht_required = s->ht_required;
cmd->vht_required = s->vht_required;
aen = &cmd->aen;
aen->auth_type = s->auth_type;
aen->privacy = !!s->privacy;
aen->mfp = 0;
aen->wpa_versions = cpu_to_le32(s->crypto.wpa_versions);
aen->cipher_group = cpu_to_le32(s->crypto.cipher_group);
aen->n_ciphers_pairwise = cpu_to_le32(s->crypto.n_ciphers_pairwise);
for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
aen.ciphers_pairwise[i] = cpu_to_le32(
bss_cfg->crypto.ciphers_pairwise[i]);
aen.n_akm_suites = cpu_to_le32(
bss_cfg->crypto.n_akm_suites);
aen->ciphers_pairwise[i] =
cpu_to_le32(s->crypto.ciphers_pairwise[i]);
aen->n_akm_suites = cpu_to_le32(s->crypto.n_akm_suites);
for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
aen.akm_suites[i] = cpu_to_le32(
bss_cfg->crypto.akm_suites[i]);
aen.control_port = bss_cfg->crypto.control_port;
aen.control_port_no_encrypt =
bss_cfg->crypto.control_port_no_encrypt;
aen.control_port_ethertype = cpu_to_le16(be16_to_cpu(
bss_cfg->crypto.control_port_ethertype));
aen->akm_suites[i] = cpu_to_le32(s->crypto.akm_suites[i]);
aen->control_port = s->crypto.control_port;
aen->control_port_no_encrypt = s->crypto.control_port_no_encrypt;
aen->control_port_ethertype =
cpu_to_le16(be16_to_cpu(s->crypto.control_port_ethertype));
if (s->ssid && s->ssid_len > 0 && s->ssid_len <= IEEE80211_MAX_SSID_LEN)
qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, s->ssid,
s->ssid_len);
qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_CRYPTO, (u8 *)&aen,
sizeof(aen));
if (cfg80211_chandef_valid(&s->chandef)) {
struct qlink_tlv_chandef *chtlv =
(struct qlink_tlv_chandef *)skb_put(cmd_skb,
sizeof(*chtlv));
chtlv->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANDEF);
chtlv->hdr.len = cpu_to_le16(sizeof(*chtlv) -
sizeof(chtlv->hdr));
qlink_chandef_cfg2q(&s->chandef, &chtlv->chan);
}
qtnf_bus_lock(vif->mac->bus);
ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
......@@ -250,8 +255,6 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif)
goto out;
}
vif->bss_status |= QTNF_STATE_AP_CONFIG;
out:
qtnf_bus_unlock(vif->mac->bus);
return ret;
......@@ -283,9 +286,6 @@ int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif)
goto out;
}
vif->bss_status &= ~QTNF_STATE_AP_START;
vif->bss_status &= ~QTNF_STATE_AP_CONFIG;
netif_carrier_off(vif->netdev);
out:
......@@ -2037,11 +2037,11 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
{
struct sk_buff *cmd_skb;
struct qlink_cmd_connect *cmd;
struct qtnf_bss_config *bss_cfg = &vif->bss_cfg;
struct qlink_auth_encr aen;
struct qlink_auth_encr *aen;
u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
int i;
u32 connect_flags = 0;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_CONNECT,
......@@ -2049,52 +2049,65 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
if (unlikely(!cmd_skb))
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
cmd = (struct qlink_cmd_connect *)cmd_skb->data;
ether_addr_copy(cmd->bssid, bss_cfg->bssid);
ether_addr_copy(cmd->bssid, vif->bssid);
if (sme->channel)
cmd->channel = cpu_to_le16(sme->channel->hw_value);
else
cmd->channel = 0;
if ((sme->bg_scan_period > 0) &&
(sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD))
cmd->bg_scan_period = cpu_to_le16(sme->bg_scan_period);
else if (sme->bg_scan_period == -1)
cmd->bg_scan_period = cpu_to_le16(QTNF_DEFAULT_BG_SCAN_PERIOD);
else
cmd->bg_scan_period = 0; /* disabled */
if (vif->mac->chandef.chan)
cmd->channel = cpu_to_le16(vif->mac->chandef.chan->hw_value);
if (sme->flags & ASSOC_REQ_DISABLE_HT)
connect_flags |= QLINK_STA_CONNECT_DISABLE_HT;
if (sme->flags & ASSOC_REQ_DISABLE_VHT)
connect_flags |= QLINK_STA_CONNECT_DISABLE_VHT;
if (sme->flags & ASSOC_REQ_USE_RRM)
connect_flags |= QLINK_STA_CONNECT_USE_RRM;
cmd->bg_scan_period = cpu_to_le16(bss_cfg->bg_scan_period);
cmd->flags = cpu_to_le32(connect_flags);
memset(&aen, 0, sizeof(aen));
aen.auth_type = bss_cfg->auth_type;
aen.privacy = !!bss_cfg->privacy;
aen.mfp = bss_cfg->mfp;
aen.wpa_versions = cpu_to_le32(bss_cfg->crypto.wpa_versions);
aen.cipher_group = cpu_to_le32(bss_cfg->crypto.cipher_group);
aen.n_ciphers_pairwise = cpu_to_le32(
bss_cfg->crypto.n_ciphers_pairwise);
aen = &cmd->aen;
aen->auth_type = sme->auth_type;
aen->privacy = !!sme->privacy;
aen->mfp = sme->mfp;
aen->wpa_versions = cpu_to_le32(sme->crypto.wpa_versions);
aen->cipher_group = cpu_to_le32(sme->crypto.cipher_group);
aen->n_ciphers_pairwise = cpu_to_le32(sme->crypto.n_ciphers_pairwise);
for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++)
aen.ciphers_pairwise[i] = cpu_to_le32(
bss_cfg->crypto.ciphers_pairwise[i]);
aen->ciphers_pairwise[i] =
cpu_to_le32(sme->crypto.ciphers_pairwise[i]);
aen.n_akm_suites = cpu_to_le32(bss_cfg->crypto.n_akm_suites);
aen->n_akm_suites = cpu_to_le32(sme->crypto.n_akm_suites);
for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++)
aen.akm_suites[i] = cpu_to_le32(
bss_cfg->crypto.akm_suites[i]);
aen->akm_suites[i] = cpu_to_le32(sme->crypto.akm_suites[i]);
aen.control_port = bss_cfg->crypto.control_port;
aen.control_port_no_encrypt =
bss_cfg->crypto.control_port_no_encrypt;
aen.control_port_ethertype = cpu_to_le16(be16_to_cpu(
bss_cfg->crypto.control_port_ethertype));
aen->control_port = sme->crypto.control_port;
aen->control_port_no_encrypt =
sme->crypto.control_port_no_encrypt;
aen->control_port_ethertype =
cpu_to_le16(be16_to_cpu(sme->crypto.control_port_ethertype));
qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, bss_cfg->ssid,
bss_cfg->ssid_len);
qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_CRYPTO, (u8 *)&aen,
sizeof(aen));
qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, sme->ssid,
sme->ssid_len);
if (sme->ie_len != 0)
qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET,
sme->ie,
sme->ie_len);
qtnf_bus_lock(vif->mac->bus);
ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
if (unlikely(ret))
......@@ -2304,15 +2317,16 @@ int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel,
return ret;
}
int qtnf_cmd_send_chan_switch(struct qtnf_wmac *mac,
int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif,
struct cfg80211_csa_settings *params)
{
struct qtnf_wmac *mac = vif->mac;
struct qlink_cmd_chan_switch *cmd;
struct sk_buff *cmd_skb;
u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0x0,
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, vif->vifid,
QLINK_CMD_CHAN_SWITCH,
sizeof(*cmd));
......@@ -2334,9 +2348,6 @@ int qtnf_cmd_send_chan_switch(struct qtnf_wmac *mac,
switch (res_code) {
case QLINK_CMD_RESULT_OK:
memcpy(&mac->csa_chandef, &params->chandef,
sizeof(mac->csa_chandef));
mac->status |= QTNF_MAC_CSA_ACTIVE;
ret = 0;
break;
case QLINK_CMD_RESULT_ENOTFOUND:
......@@ -2358,3 +2369,41 @@ int qtnf_cmd_send_chan_switch(struct qtnf_wmac *mac,
qtnf_bus_unlock(mac->bus);
return ret;
}
int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef)
{
struct qtnf_bus *bus = vif->mac->bus;
const struct qlink_resp_channel_get *resp;
struct sk_buff *cmd_skb;
struct sk_buff *resp_skb = NULL;
u16 res_code = QLINK_CMD_RESULT_OK;
int ret;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_CHAN_GET,
sizeof(struct qlink_cmd));
if (unlikely(!cmd_skb))
return -ENOMEM;
qtnf_bus_lock(bus);
ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, &res_code,
sizeof(*resp), NULL);
qtnf_bus_unlock(bus);
if (unlikely(ret))
goto out;
if (unlikely(res_code != QLINK_CMD_RESULT_OK)) {
ret = -ENODATA;
goto out;
}
resp = (const struct qlink_resp_channel_get *)resp_skb->data;
qlink_chandef_q2cfg(priv_to_wiphy(vif->mac), &resp->chan, chdef);
out:
consume_skb(resp_skb);
return ret;
}
......@@ -33,7 +33,8 @@ int qtnf_cmd_send_del_intf(struct qtnf_vif *vif);
int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
struct ieee80211_supported_band *band);
int qtnf_cmd_send_regulatory_config(struct qtnf_wmac *mac, const char *alpha2);
int qtnf_cmd_send_config_ap(struct qtnf_vif *vif);
int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
const struct cfg80211_ap_settings *s);
int qtnf_cmd_send_start_ap(struct qtnf_vif *vif);
int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif);
int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg);
......@@ -73,7 +74,8 @@ int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif,
int qtnf_cmd_reg_notify(struct qtnf_bus *bus, struct regulatory_request *req);
int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel,
struct qtnf_chan_stats *stats);
int qtnf_cmd_send_chan_switch(struct qtnf_wmac *mac,
int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif,
struct cfg80211_csa_settings *params);
int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef);
#endif /* QLINK_COMMANDS_H_ */
......@@ -52,27 +52,11 @@
#define QTNF_DEF_WDOG_TIMEOUT 5
#define QTNF_TX_TIMEOUT_TRSHLD 100
#define QTNF_STATE_AP_CONFIG BIT(2)
#define QTNF_STATE_AP_START BIT(1)
extern const struct net_device_ops qtnf_netdev_ops;
struct qtnf_bus;
struct qtnf_vif;
struct qtnf_bss_config {
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 bssid[ETH_ALEN];
size_t ssid_len;
u8 dtim;
u16 bcn_period;
u16 auth_type;
bool privacy;
enum nl80211_mfp mfp;
struct cfg80211_crypto_settings crypto;
u16 bg_scan_period;
u32 connect_flags;
};
struct qtnf_sta_node {
struct list_head list;
u8 mac_addr[ETH_ALEN];
......@@ -89,12 +73,10 @@ enum qtnf_sta_state {
QTNF_STA_CONNECTED
};
enum qtnf_mac_status {
QTNF_MAC_CSA_ACTIVE = BIT(0)
};
struct qtnf_vif {
struct wireless_dev wdev;
u8 bssid[ETH_ALEN];
u8 mac_addr[ETH_ALEN];
u8 vifid;
u8 bss_priority;
u8 bss_status;
......@@ -102,9 +84,8 @@ struct qtnf_vif {
u16 mgmt_frames_bitmask;
struct net_device *netdev;
struct qtnf_wmac *mac;
u8 mac_addr[ETH_ALEN];
struct work_struct reset_work;
struct qtnf_bss_config bss_cfg;
struct qtnf_sta_list sta_list;
unsigned long cons_tx_timeout_cnt;
};
......@@ -141,13 +122,10 @@ struct qtnf_wmac {
u8 macid;
u8 wiphy_registered;
u8 macaddr[ETH_ALEN];
u32 status;
struct qtnf_bus *bus;
struct qtnf_mac_info macinfo;
struct qtnf_vif iflist[QTNF_MAX_INTF];
struct cfg80211_scan_request *scan_req;
struct cfg80211_chan_def chandef;
struct cfg80211_chan_def csa_chandef;
struct mutex mac_lock; /* lock during wmac speicific ops */
struct timer_list scan_timeout;
};
......
......@@ -25,6 +25,7 @@
#include "trans.h"
#include "util.h"
#include "event.h"
#include "qlink_util.h"
static int
qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif,
......@@ -52,12 +53,6 @@ qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif,
return -EPROTO;
}
if (!(vif->bss_status & QTNF_STATE_AP_START)) {
pr_err("VIF%u.%u: STA_ASSOC event when AP is not started\n",
mac->macid, vif->vifid);
return -EPROTO;
}
sta_addr = sta_assoc->sta_addr;
frame_control = le16_to_cpu(sta_assoc->frame_control);
......@@ -126,12 +121,6 @@ qtnf_event_handle_sta_deauth(struct qtnf_wmac *mac, struct qtnf_vif *vif,
return -EPROTO;
}
if (!(vif->bss_status & QTNF_STATE_AP_START)) {
pr_err("VIF%u.%u: STA_DEAUTH event when AP is not started\n",
mac->macid, vif->vifid);
return -EPROTO;
}
sta_addr = sta_deauth->sta_addr;
reason = le16_to_cpu(sta_deauth->reason);
......@@ -357,40 +346,29 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
{
struct wiphy *wiphy = priv_to_wiphy(mac);
struct cfg80211_chan_def chandef;
struct ieee80211_channel *chan;
struct qtnf_vif *vif;
int freq;
int i;
if (len < sizeof(*data)) {
pr_err("payload is too short\n");
pr_err("MAC%u: payload is too short\n", mac->macid);
return -EINVAL;
}
freq = le32_to_cpu(data->freq);
chan = ieee80211_get_channel(wiphy, freq);
if (!chan) {
pr_err("channel at %d MHz not found\n", freq);
return -EINVAL;
}
if (!wiphy->registered)
return 0;
pr_debug("MAC%d switch to new channel %u MHz\n", mac->macid, freq);
qlink_chandef_q2cfg(wiphy, &data->chan, &chandef);
if (mac->status & QTNF_MAC_CSA_ACTIVE) {
mac->status &= ~QTNF_MAC_CSA_ACTIVE;
if (chan->hw_value != mac->csa_chandef.chan->hw_value)
pr_warn("unexpected switch to %u during CSA to %u\n",
chan->hw_value,
mac->csa_chandef.chan->hw_value);
if (!cfg80211_chandef_valid(&chandef)) {
pr_err("MAC%u: bad channel f1=%u f2=%u bw=%u\n", mac->macid,
chandef.center_freq1, chandef.center_freq2,
chandef.width);
return -EINVAL;
}
/* FIXME: need to figure out proper nl80211_channel_type value */
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20);
/* fall-back to minimal safe chandef description */
if (!cfg80211_chandef_valid(&chandef))
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20);
memcpy(&mac->chandef, &chandef, sizeof(mac->chandef));
pr_debug("MAC%d: new channel ieee=%u freq1=%u freq2=%u bw=%u\n",
mac->macid, chandef.chan->hw_value, chandef.center_freq1,
chandef.center_freq2, chandef.width);
for (i = 0; i < QTNF_MAX_INTF; i++) {
vif = &mac->iflist[i];
......
......@@ -108,16 +108,48 @@ enum qlink_sta_flags {
};
enum qlink_channel_width {
QLINK_CHAN_WIDTH_5 = BIT(0),
QLINK_CHAN_WIDTH_10 = BIT(1),
QLINK_CHAN_WIDTH_20_NOHT = BIT(2),
QLINK_CHAN_WIDTH_20 = BIT(3),
QLINK_CHAN_WIDTH_40 = BIT(4),
QLINK_CHAN_WIDTH_80 = BIT(5),
QLINK_CHAN_WIDTH_80P80 = BIT(6),
QLINK_CHAN_WIDTH_160 = BIT(7),
QLINK_CHAN_WIDTH_5 = 0,
QLINK_CHAN_WIDTH_10,
QLINK_CHAN_WIDTH_20_NOHT,
QLINK_CHAN_WIDTH_20,
QLINK_CHAN_WIDTH_40,
QLINK_CHAN_WIDTH_80,
QLINK_CHAN_WIDTH_80P80,
QLINK_CHAN_WIDTH_160,
};
/**
* struct qlink_chandef - qlink channel definition
*
* @center_freq1: center frequency of first segment
* @center_freq2: center frequency of second segment (80+80 only)
* @width: channel width, one of @enum qlink_channel_width
*/
struct qlink_chandef {
__le16 center_freq1;
__le16 center_freq2;
u8 width;
u8 rsvd[3];
} __packed;
#define QLINK_MAX_NR_CIPHER_SUITES 5
#define QLINK_MAX_NR_AKM_SUITES 2
struct qlink_auth_encr {
__le32 wpa_versions;
__le32 cipher_group;
__le32 n_ciphers_pairwise;
__le32 ciphers_pairwise[QLINK_MAX_NR_CIPHER_SUITES];
__le32 n_akm_suites;
__le32 akm_suites[QLINK_MAX_NR_AKM_SUITES];
__le16 control_port_ethertype;
u8 auth_type;
u8 privacy;
u8 mfp;
u8 control_port;
u8 control_port_no_encrypt;
} __packed;
/* QLINK Command messages related definitions
*/
......@@ -155,6 +187,7 @@ enum qlink_cmd_type {
QLINK_CMD_REG_NOTIFY = 0x0019,
QLINK_CMD_CHANS_INFO_GET = 0x001A,
QLINK_CMD_CHAN_SWITCH = 0x001B,
QLINK_CMD_CHAN_GET = 0x001C,
QLINK_CMD_CONFIG_AP = 0x0020,
QLINK_CMD_START_AP = 0x0021,
QLINK_CMD_STOP_AP = 0x0022,
......@@ -384,8 +417,9 @@ enum qlink_sta_connect_flags {
* struct qlink_cmd_connect - data for QLINK_CMD_CONNECT command
*
* @flags: for future use.
* @freq: center frequence of a channel which should be used to connect.
* @channel: channel which should be used to connect.
* @bg_scan_period: period of background scan.
* @aen: authentication information.
* @bssid: BSSID of the BSS to connect to.
* @payload: variable portion of connection request.
*/
......@@ -394,6 +428,7 @@ struct qlink_cmd_connect {
__le32 flags;
__le16 channel;
__le16 bg_scan_period;
struct qlink_auth_encr aen;
u8 bssid[ETH_ALEN];
u8 payload[0];
} __packed;
......@@ -506,6 +541,46 @@ struct qlink_cmd_chan_switch {
u8 beacon_count;
} __packed;
/**
* enum qlink_hidden_ssid - values for %NL80211_ATTR_HIDDEN_SSID
*
* Refer to &enum nl80211_hidden_ssid
*/
enum qlink_hidden_ssid {
QLINK_HIDDEN_SSID_NOT_IN_USE,
QLINK_HIDDEN_SSID_ZERO_LEN,
QLINK_HIDDEN_SSID_ZERO_CONTENTS
};
/**
* struct qlink_cmd_config_ap - data for QLINK_CMD_CONFIG_AP command
*
* @beacon_interval: beacon interval
* @inactivity_timeout: station's inactivity period in seconds
* @dtim_period: DTIM period
* @hidden_ssid: whether to hide the SSID, one of &enum qlink_hidden_ssid
* @smps_mode: SMPS mode
* @ht_required: stations must support HT
* @vht_required: stations must support VHT
* @aen: encryption info
* @info: variable configurations
*/
struct qlink_cmd_config_ap {
struct qlink_cmd chdr;
__le16 beacon_interval;
__le16 inactivity_timeout;
u8 dtim_period;
u8 hidden_ssid;
u8 smps_mode;
u8 p2p_ctwindow;
u8 p2p_opp_ps;
u8 pbss;
u8 ht_required;
u8 vht_required;
struct qlink_auth_encr aen;
u8 info[0];
} __packed;
/* QLINK Command Responses messages related definitions
*/
......@@ -680,6 +755,16 @@ struct qlink_resp_get_chan_stats {
u8 info[0];
} __packed;
/**
* struct qlink_resp_channel_get - response for QLINK_CMD_CHAN_GET command
*
* @chan: definition of current operating channel.
*/
struct qlink_resp_channel_get {
struct qlink_resp rhdr;
struct qlink_chandef chan;
} __packed;
/* QLINK Events messages related definitions
*/
......@@ -764,11 +849,11 @@ struct qlink_event_bss_leave {
/**
* struct qlink_event_freq_change - data for QLINK_EVENT_FREQ_CHANGE event
*
* @freq: new operating frequency in MHz
* @chan: new operating channel definition
*/
struct qlink_event_freq_change {
struct qlink_event ehdr;
__le32 freq;
struct qlink_chandef chan;
} __packed;
enum qlink_rxmgmt_flags {
......@@ -856,10 +941,9 @@ enum qlink_tlv_id {
QTN_TLV_ID_RTS_THRESH = 0x0202,
QTN_TLV_ID_SRETRY_LIMIT = 0x0203,
QTN_TLV_ID_LRETRY_LIMIT = 0x0204,
QTN_TLV_ID_BCN_PERIOD = 0x0205,
QTN_TLV_ID_DTIM = 0x0206,
QTN_TLV_ID_REG_RULE = 0x0207,
QTN_TLV_ID_CHANNEL = 0x020F,
QTN_TLV_ID_CHANDEF = 0x0210,
QTN_TLV_ID_COVERAGE_CLASS = 0x0213,
QTN_TLV_ID_IFACE_LIMIT = 0x0214,
QTN_TLV_ID_NUM_IFACE_COMB = 0x0215,
......@@ -868,7 +952,6 @@ enum qlink_tlv_id {
QTN_TLV_ID_STA_GENERIC_INFO = 0x0301,
QTN_TLV_ID_KEY = 0x0302,
QTN_TLV_ID_SEQ = 0x0303,
QTN_TLV_ID_CRYPTO = 0x0304,
QTN_TLV_ID_IE_SET = 0x0305,
};
......@@ -1047,22 +1130,16 @@ struct qlink_tlv_channel {
u8 rsvd[2];
} __packed;
#define QLINK_MAX_NR_CIPHER_SUITES 5
#define QLINK_MAX_NR_AKM_SUITES 2
struct qlink_auth_encr {
__le32 wpa_versions;
__le32 cipher_group;
__le32 n_ciphers_pairwise;
__le32 ciphers_pairwise[QLINK_MAX_NR_CIPHER_SUITES];
__le32 n_akm_suites;
__le32 akm_suites[QLINK_MAX_NR_AKM_SUITES];
__le16 control_port_ethertype;
u8 auth_type;
u8 privacy;
u8 mfp;
u8 control_port;
u8 control_port_no_encrypt;
/**
* struct qlink_tlv_chandef - data for QTN_TLV_ID_CHANDEF TLV
*
* Channel definition.
*
* @chan: channel definition data.
*/
struct qlink_tlv_chandef {
struct qlink_tlv_hdr hdr;
struct qlink_chandef chan;
} __packed;
struct qlink_chan_stats {
......
......@@ -49,29 +49,126 @@ u8 qlink_chan_width_mask_to_nl(u16 qlink_mask)
{
u8 result = 0;
if (qlink_mask & QLINK_CHAN_WIDTH_5)
if (qlink_mask & BIT(QLINK_CHAN_WIDTH_5))
result |= BIT(NL80211_CHAN_WIDTH_5);
if (qlink_mask & QLINK_CHAN_WIDTH_10)
if (qlink_mask & BIT(QLINK_CHAN_WIDTH_10))
result |= BIT(NL80211_CHAN_WIDTH_10);
if (qlink_mask & QLINK_CHAN_WIDTH_20_NOHT)
if (qlink_mask & BIT(QLINK_CHAN_WIDTH_20_NOHT))
result |= BIT(NL80211_CHAN_WIDTH_20_NOHT);
if (qlink_mask & QLINK_CHAN_WIDTH_20)
if (qlink_mask & BIT(QLINK_CHAN_WIDTH_20))
result |= BIT(NL80211_CHAN_WIDTH_20);
if (qlink_mask & QLINK_CHAN_WIDTH_40)
if (qlink_mask & BIT(QLINK_CHAN_WIDTH_40))
result |= BIT(NL80211_CHAN_WIDTH_40);
if (qlink_mask & QLINK_CHAN_WIDTH_80)
if (qlink_mask & BIT(QLINK_CHAN_WIDTH_80))
result |= BIT(NL80211_CHAN_WIDTH_80);
if (qlink_mask & QLINK_CHAN_WIDTH_80P80)
if (qlink_mask & BIT(QLINK_CHAN_WIDTH_80P80))
result |= BIT(NL80211_CHAN_WIDTH_80P80);
if (qlink_mask & QLINK_CHAN_WIDTH_160)
if (qlink_mask & BIT(QLINK_CHAN_WIDTH_160))
result |= BIT(NL80211_CHAN_WIDTH_160);
return result;
}
static enum nl80211_chan_width qlink_chanwidth_to_nl(u8 qlw)
{
switch (qlw) {
case QLINK_CHAN_WIDTH_20_NOHT:
return NL80211_CHAN_WIDTH_20_NOHT;
case QLINK_CHAN_WIDTH_20:
return NL80211_CHAN_WIDTH_20;
case QLINK_CHAN_WIDTH_40:
return NL80211_CHAN_WIDTH_40;
case QLINK_CHAN_WIDTH_80:
return NL80211_CHAN_WIDTH_80;
case QLINK_CHAN_WIDTH_80P80:
return NL80211_CHAN_WIDTH_80P80;
case QLINK_CHAN_WIDTH_160:
return NL80211_CHAN_WIDTH_160;
case QLINK_CHAN_WIDTH_5:
return NL80211_CHAN_WIDTH_5;
case QLINK_CHAN_WIDTH_10:
return NL80211_CHAN_WIDTH_10;
default:
return -1;
}
}
void qlink_chandef_q2cfg(struct wiphy *wiphy,
const struct qlink_chandef *qch,
struct cfg80211_chan_def *chdef)
{
chdef->center_freq1 = le16_to_cpu(qch->center_freq1);
chdef->center_freq2 = le16_to_cpu(qch->center_freq2);
chdef->width = qlink_chanwidth_to_nl(qch->width);
switch (chdef->width) {
case NL80211_CHAN_WIDTH_20_NOHT:
case NL80211_CHAN_WIDTH_20:
case NL80211_CHAN_WIDTH_5:
case NL80211_CHAN_WIDTH_10:
chdef->chan = ieee80211_get_channel(wiphy, chdef->center_freq1);
break;
case NL80211_CHAN_WIDTH_40:
case NL80211_CHAN_WIDTH_80:
case NL80211_CHAN_WIDTH_80P80:
case NL80211_CHAN_WIDTH_160:
chdef->chan = ieee80211_get_channel(wiphy,
chdef->center_freq1 - 10);
break;
default:
chdef->chan = NULL;
break;
}
}
static u8 qlink_chanwidth_nl_to_qlink(enum nl80211_chan_width nlwidth)
{
switch (nlwidth) {
case NL80211_CHAN_WIDTH_20_NOHT:
return QLINK_CHAN_WIDTH_20_NOHT;
case NL80211_CHAN_WIDTH_20:
return QLINK_CHAN_WIDTH_20;
case NL80211_CHAN_WIDTH_40:
return QLINK_CHAN_WIDTH_40;
case NL80211_CHAN_WIDTH_80:
return QLINK_CHAN_WIDTH_80;
case NL80211_CHAN_WIDTH_80P80:
return QLINK_CHAN_WIDTH_80P80;
case NL80211_CHAN_WIDTH_160:
return QLINK_CHAN_WIDTH_160;
case NL80211_CHAN_WIDTH_5:
return QLINK_CHAN_WIDTH_5;
case NL80211_CHAN_WIDTH_10:
return QLINK_CHAN_WIDTH_10;
default:
return -1;
}
}
void qlink_chandef_cfg2q(const struct cfg80211_chan_def *chdef,
struct qlink_chandef *qch)
{
qch->center_freq1 = cpu_to_le16(chdef->center_freq1);
qch->center_freq2 = cpu_to_le16(chdef->center_freq2);
qch->width = qlink_chanwidth_nl_to_qlink(chdef->width);
}
enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val)
{
switch (nl_val) {
case NL80211_HIDDEN_SSID_ZERO_LEN:
return QLINK_HIDDEN_SSID_ZERO_LEN;
case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
return QLINK_HIDDEN_SSID_ZERO_CONTENTS;
case NL80211_HIDDEN_SSID_NOT_IN_USE:
default:
return QLINK_HIDDEN_SSID_NOT_IN_USE;
}
}
......@@ -19,6 +19,7 @@
#include <linux/types.h>
#include <linux/skbuff.h>
#include <net/cfg80211.h>
#include "qlink.h"
......@@ -62,5 +63,11 @@ static inline void qtnf_cmd_skb_put_tlv_u16(struct sk_buff *skb,
u16 qlink_iface_type_to_nl_mask(u16 qlink_type);
u8 qlink_chan_width_mask_to_nl(u16 qlink_mask);
void qlink_chandef_q2cfg(struct wiphy *wiphy,
const struct qlink_chandef *qch,
struct cfg80211_chan_def *chdef);
void qlink_chandef_cfg2q(const struct cfg80211_chan_def *chdef,
struct qlink_chandef *qch);
enum qlink_hidden_ssid qlink_hidden_ssid_nl2q(enum nl80211_hidden_ssid nl_val);
#endif /* _QTN_FMAC_QLINK_UTIL_H_ */
......@@ -614,7 +614,10 @@ static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv)
dev_info(&priv->udev->dev, "Vendor: %.7s\n", efuse->vendor_name);
dev_info(&priv->udev->dev, "Product: %.11s\n", efuse->device_name);
dev_info(&priv->udev->dev, "Serial: %.11s\n", efuse->serial);
if (memchr_inv(efuse->serial, 0xff, 11))
dev_info(&priv->udev->dev, "Serial: %.11s\n", efuse->serial);
else
dev_info(&priv->udev->dev, "Serial not available.\n");
if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) {
unsigned char *raw = priv->efuse_wifi.raw;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册