wireless-drivers-next patches for 5.4

Second set of patches for 5.4. Lots of changes for iwlwifi and mt76,
 but also smaller changes to other drivers.
 
 Major changes:
 
 iwlwifi
 
 * remove broken and unused runtime power management mode for PCIe
   devices, removes IWLWIFI_PCIE_RTPM Kconfig option as well
 
 * support new ACPI value for per-platform antenna gain
 
 * support for single antenna diversity
 
 * support for new WoWLAN FW API
 
 brcmfmac
 
 * add reset debugfs file for testing firmware restart
 
 mt76
 
 * DFS pattern detector for mt7615 (DFS channels not enabled yet)
 
 * Channel Switch Announcement (CSA) support for mt7615
 
 * new device support for mt76x0
 
 * support for more ciphers in mt7615
 
 * smart carrier sense on mt7615
 
 * survey support on mt7615
 
 * multiple interfaces on mt76x02u
 
 rtw88
 
 * enable MSI interrupt
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJdc1+yAAoJEG4XJFUm622bd/UH+wUmM+7VaS+QZGQg3myyKGS6
 eXVR1n/sT1L+0gnOUopooHGOjGAYPQZgMlC4r4oSd1PrmfJ+0yqhfjODNZyOSRU3
 amYnBCesrvMohU9rd8iApxE83L+fr1P59gNfX/LsRxqdU9WmaAjX8nVUirc/w7iX
 fGw7B4HqMchp+g73Svdy1Qk0d35laI6JexqeldPS8K0Qf4jwiwxM3kPL17W2Mznn
 Osmcg+GHhy62Ov5yz71m0wAyxzcY4jMBtQuISn1vsKyZi17ndKgG2dPFXen29gDg
 cRQshHx3UjIaR8XPJg7jmiomLrCNytFod+7IEO2Tz+iacFa6IRcKFOxzjtWTvzQ=
 =lHhS
 -----END PGP SIGNATURE-----

Merge tag 'wireless-drivers-next-for-davem-2019-09-07' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Valo says:

====================
wireless-drivers-next patches for 5.4

Second set of patches for 5.4. Lots of changes for iwlwifi and mt76,
but also smaller changes to other drivers.

Major changes:

iwlwifi

* remove broken and unused runtime power management mode for PCIe
  devices, removes IWLWIFI_PCIE_RTPM Kconfig option as well

* support new ACPI value for per-platform antenna gain

* support for single antenna diversity

* support for new WoWLAN FW API

brcmfmac

* add reset debugfs file for testing firmware restart

mt76

* DFS pattern detector for mt7615 (DFS channels not enabled yet)

* Channel Switch Announcement (CSA) support for mt7615

* new device support for mt76x0

* support for more ciphers in mt7615

* smart carrier sense on mt7615

* survey support on mt7615

* multiple interfaces on mt76x02u

rtw88

* enable MSI interrupt
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2019-09-07 10:06:30 +02:00
commit 742ca7812b
216 changed files with 5188 additions and 6226 deletions

View File

@ -59,22 +59,6 @@ static inline void mips_write32(struct bcma_drv_mips *mcore,
bcma_write32(mcore->core, offset, value); bcma_write32(mcore->core, offset, value);
} }
static const u32 ipsflag_irq_mask[] = {
0,
BCMA_MIPS_IPSFLAG_IRQ1,
BCMA_MIPS_IPSFLAG_IRQ2,
BCMA_MIPS_IPSFLAG_IRQ3,
BCMA_MIPS_IPSFLAG_IRQ4,
};
static const u32 ipsflag_irq_shift[] = {
0,
BCMA_MIPS_IPSFLAG_IRQ1_SHIFT,
BCMA_MIPS_IPSFLAG_IRQ2_SHIFT,
BCMA_MIPS_IPSFLAG_IRQ3_SHIFT,
BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
};
static u32 bcma_core_mips_irqflag(struct bcma_device *dev) static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
{ {
u32 flag; u32 flag;

View File

@ -78,7 +78,7 @@ static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u16 device, u8 address)
v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD); v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
} }
v = BCMA_CORE_PCI_MDIODATA_START; v |= BCMA_CORE_PCI_MDIODATA_START;
v |= BCMA_CORE_PCI_MDIODATA_READ; v |= BCMA_CORE_PCI_MDIODATA_READ;
v |= BCMA_CORE_PCI_MDIODATA_TA; v |= BCMA_CORE_PCI_MDIODATA_TA;
@ -121,7 +121,7 @@ static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u16 device,
v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD); v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
} }
v = BCMA_CORE_PCI_MDIODATA_START; v |= BCMA_CORE_PCI_MDIODATA_START;
v |= BCMA_CORE_PCI_MDIODATA_WRITE; v |= BCMA_CORE_PCI_MDIODATA_WRITE;
v |= BCMA_CORE_PCI_MDIODATA_TA; v |= BCMA_CORE_PCI_MDIODATA_TA;
v |= data; v |= data;

View File

@ -4222,10 +4222,8 @@ brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len,
vndr_ies->count++; vndr_ies->count++;
brcmf_dbg(TRACE, "** OUI %02x %02x %02x, type 0x%02x\n", brcmf_dbg(TRACE, "** OUI %3ph, type 0x%02x\n",
parsed_info->vndrie.oui[0], parsed_info->vndrie.oui,
parsed_info->vndrie.oui[1],
parsed_info->vndrie.oui[2],
parsed_info->vndrie.oui_type); parsed_info->vndrie.oui_type);
if (vndr_ies->count >= VNDR_IE_PARSE_LIMIT) if (vndr_ies->count >= VNDR_IE_PARSE_LIMIT)
@ -4244,9 +4242,7 @@ next:
static u32 static u32
brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd) brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)
{ {
strscpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN);
strncpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN - 1);
iebuf[VNDR_IE_CMD_LEN - 1] = '\0';
put_unaligned_le32(1, &iebuf[VNDR_IE_COUNT_OFFSET]); put_unaligned_le32(1, &iebuf[VNDR_IE_COUNT_OFFSET]);
@ -4351,12 +4347,10 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
for (i = 0; i < old_vndr_ies.count; i++) { for (i = 0; i < old_vndr_ies.count; i++) {
vndrie_info = &old_vndr_ies.ie_info[i]; vndrie_info = &old_vndr_ies.ie_info[i];
brcmf_dbg(TRACE, "DEL ID : %d, Len: %d , OUI:%02x:%02x:%02x\n", brcmf_dbg(TRACE, "DEL ID : %d, Len: %d , OUI:%3ph\n",
vndrie_info->vndrie.id, vndrie_info->vndrie.id,
vndrie_info->vndrie.len, vndrie_info->vndrie.len,
vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui);
vndrie_info->vndrie.oui[1],
vndrie_info->vndrie.oui[2]);
del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag, del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
vndrie_info->ie_ptr, vndrie_info->ie_ptr,
@ -4388,12 +4382,10 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
remained_buf_len -= (vndrie_info->ie_len + remained_buf_len -= (vndrie_info->ie_len +
VNDR_IE_VSIE_OFFSET); VNDR_IE_VSIE_OFFSET);
brcmf_dbg(TRACE, "ADDED ID : %d, Len: %d, OUI:%02x:%02x:%02x\n", brcmf_dbg(TRACE, "ADDED ID : %d, Len: %d, OUI:%3ph\n",
vndrie_info->vndrie.id, vndrie_info->vndrie.id,
vndrie_info->vndrie.len, vndrie_info->vndrie.len,
vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui);
vndrie_info->vndrie.oui[1],
vndrie_info->vndrie.oui[2]);
del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag, del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
vndrie_info->ie_ptr, vndrie_info->ie_ptr,

View File

@ -696,8 +696,10 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
return 0; return 0;
} }
static int brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) int brcmf_chip_get_raminfo(struct brcmf_chip *pub)
{ {
struct brcmf_chip_priv *ci = container_of(pub, struct brcmf_chip_priv,
pub);
struct brcmf_core_priv *mem_core; struct brcmf_core_priv *mem_core;
struct brcmf_core *mem; struct brcmf_core *mem;
@ -979,7 +981,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
brcmf_chip_set_passive(&ci->pub); brcmf_chip_set_passive(&ci->pub);
} }
return brcmf_chip_get_raminfo(ci); return brcmf_chip_get_raminfo(&ci->pub);
} }
static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id) static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id)

View File

@ -69,6 +69,7 @@ struct brcmf_buscore_ops {
void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec); void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
}; };
int brcmf_chip_get_raminfo(struct brcmf_chip *pub);
struct brcmf_chip *brcmf_chip_attach(void *ctx, struct brcmf_chip *brcmf_chip_attach(void *ctx,
const struct brcmf_buscore_ops *ops); const struct brcmf_buscore_ops *ops);
void brcmf_chip_detach(struct brcmf_chip *chip); void brcmf_chip_detach(struct brcmf_chip *chip);

View File

@ -1086,6 +1086,29 @@ static void brcmf_core_bus_reset(struct work_struct *work)
brcmf_bus_reset(drvr->bus_if); brcmf_bus_reset(drvr->bus_if);
} }
static ssize_t bus_reset_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct brcmf_pub *drvr = file->private_data;
u8 value;
if (kstrtou8_from_user(user_buf, count, 0, &value))
return -EINVAL;
if (value != 1)
return -EINVAL;
schedule_work(&drvr->bus_reset);
return count;
}
static const struct file_operations bus_reset_fops = {
.open = simple_open,
.llseek = no_llseek,
.write = bus_reset_write,
};
static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops) static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)
{ {
int ret = -1; int ret = -1;
@ -1161,6 +1184,8 @@ static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)
/* populate debugfs */ /* populate debugfs */
brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read); brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read);
debugfs_create_file("reset", 0600, brcmf_debugfs_get_devdir(drvr), drvr,
&bus_reset_fops);
brcmf_feat_debugfs_create(drvr); brcmf_feat_debugfs_create(drvr);
brcmf_proto_debugfs_create(drvr); brcmf_proto_debugfs_create(drvr);
brcmf_bus_debugfs_create(bus_if); brcmf_bus_debugfs_create(bus_if);

View File

@ -121,6 +121,10 @@ int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data, int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data,
size_t len); size_t len);
#else #else
static inline struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr)
{
return ERR_PTR(-ENOENT);
}
static inline static inline
int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
int (*read_fn)(struct seq_file *seq, void *data)) int (*read_fn)(struct seq_file *seq, void *data))

View File

@ -1468,7 +1468,6 @@ static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data)
seq_printf(seq, "\nh2d_flowrings: depth %u\n", seq_printf(seq, "\nh2d_flowrings: depth %u\n",
BRCMF_H2D_TXFLOWRING_MAX_ITEM); BRCMF_H2D_TXFLOWRING_MAX_ITEM);
seq_puts(seq, "Active flowrings:\n"); seq_puts(seq, "Active flowrings:\n");
hash = msgbuf->flow->hash;
for (i = 0; i < msgbuf->flow->nrofrings; i++) { for (i = 0; i < msgbuf->flow->nrofrings; i++) {
if (!msgbuf->flow->rings[i]) if (!msgbuf->flow->rings[i])
continue; continue;

View File

@ -1770,6 +1770,12 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len; nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;
kfree(fwreq); kfree(fwreq);
ret = brcmf_chip_get_raminfo(devinfo->ci);
if (ret) {
brcmf_err(bus, "Failed to get RAM info\n");
goto fail;
}
/* Some of the firmwares have the size of the memory of the device /* Some of the firmwares have the size of the memory of the device
* defined inside the firmware. This is because part of the memory in * defined inside the firmware. This is because part of the memory in
* the device is shared and the devision is determined by FW. Parse * the device is shared and the devision is determined by FW. Parse

View File

@ -20035,7 +20035,7 @@ static void wlc_phy_radio_init_2056(struct brcms_phy *pi)
break; break;
default: default:
break; return;
} }
} }

View File

@ -5441,11 +5441,18 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
Cmd cmd; Cmd cmd;
Resp rsp; Resp rsp;
if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN; if (ai->flags & FLAG_RADIO_MASK) {
kfree(data->rbuffer);
kfree(file->private_data);
return -ENETDOWN;
}
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.cmd=CMD_LISTBSS; cmd.cmd=CMD_LISTBSS;
if (down_interruptible(&ai->sem)) if (down_interruptible(&ai->sem)) {
kfree(data->rbuffer);
kfree(file->private_data);
return -ERESTARTSYS; return -ERESTARTSYS;
}
issuecommand(ai, &cmd, &rsp); issuecommand(ai, &cmd, &rsp);
up(&ai->sem); up(&ai->sem);
data->readlen = 0; data->readlen = 0;

View File

@ -2721,7 +2721,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv)
/* Do not load eeprom data on fatal error or suspend */ /* Do not load eeprom data on fatal error or suspend */
ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0); ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0);
} else { } else {
IPW_DEBUG_INFO("Enabling FW initializationg of SRAM\n"); IPW_DEBUG_INFO("Enabling FW initialization of SRAM\n");
/* Load eeprom data on fatal error or suspend */ /* Load eeprom data on fatal error or suspend */
ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 1); ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 1);

View File

@ -92,20 +92,6 @@ config IWLWIFI_BCAST_FILTERING
If unsure, don't enable this option, as some programs might If unsure, don't enable this option, as some programs might
expect incoming broadcasts for their normal operations. expect incoming broadcasts for their normal operations.
config IWLWIFI_PCIE_RTPM
bool "Enable runtime power management mode for PCIe devices"
depends on IWLMVM && PM && EXPERT
help
Say Y here to enable runtime power management for PCIe
devices. If enabled, the device will go into low power mode
when idle for a short period of time, allowing for improved
power saving during runtime. Note that this feature requires
a tight integration with the platform. It is not recommended
to enable this feature without proper validation with the
specific target platform.
If unsure, say N.
menu "Debugging Options" menu "Debugging Options"
config IWLWIFI_DEBUG config IWLWIFI_DEBUG

View File

@ -2,7 +2,7 @@
/****************************************************************************** /******************************************************************************
* *
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
@ -69,16 +69,16 @@ static const struct iwl_eeprom_params iwl1000_eeprom_params = {
.fw_name_pre = IWL1000_FW_PRE, \ .fw_name_pre = IWL1000_FW_PRE, \
.ucode_api_max = IWL1000_UCODE_API_MAX, \ .ucode_api_max = IWL1000_UCODE_API_MAX, \
.ucode_api_min = IWL1000_UCODE_API_MIN, \ .ucode_api_min = IWL1000_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_1000, \ .trans.device_family = IWL_DEVICE_FAMILY_1000, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \ .max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \ .max_data_size = IWLAGN_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_1000_EEPROM_VERSION, \ .nvm_ver = EEPROM_1000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ .nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
.base_params = &iwl1000_base_params, \ .trans.base_params = &iwl1000_base_params, \
.eeprom_params = &iwl1000_eeprom_params, \ .eeprom_params = &iwl1000_eeprom_params, \
.led_mode = IWL_LED_BLINK, \ .led_mode = IWL_LED_BLINK, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
const struct iwl_cfg iwl1000_bgn_cfg = { const struct iwl_cfg iwl1000_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1000 BGN", .name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
@ -95,17 +95,17 @@ const struct iwl_cfg iwl1000_bg_cfg = {
.fw_name_pre = IWL100_FW_PRE, \ .fw_name_pre = IWL100_FW_PRE, \
.ucode_api_max = IWL100_UCODE_API_MAX, \ .ucode_api_max = IWL100_UCODE_API_MAX, \
.ucode_api_min = IWL100_UCODE_API_MIN, \ .ucode_api_min = IWL100_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_100, \ .trans.device_family = IWL_DEVICE_FAMILY_100, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \ .max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \ .max_data_size = IWLAGN_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_1000_EEPROM_VERSION, \ .nvm_ver = EEPROM_1000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ .nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
.base_params = &iwl1000_base_params, \ .trans.base_params = &iwl1000_base_params, \
.eeprom_params = &iwl1000_eeprom_params, \ .eeprom_params = &iwl1000_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.rx_with_siso_diversity = true, \ .rx_with_siso_diversity = true, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
const struct iwl_cfg iwl100_bgn_cfg = { const struct iwl_cfg iwl100_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 100 BGN", .name = "Intel(R) Centrino(R) Wireless-N 100 BGN",

View File

@ -2,7 +2,7 @@
/****************************************************************************** /******************************************************************************
* *
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
@ -95,16 +95,16 @@ static const struct iwl_eeprom_params iwl20x0_eeprom_params = {
.fw_name_pre = IWL2000_FW_PRE, \ .fw_name_pre = IWL2000_FW_PRE, \
.ucode_api_max = IWL2000_UCODE_API_MAX, \ .ucode_api_max = IWL2000_UCODE_API_MAX, \
.ucode_api_min = IWL2000_UCODE_API_MIN, \ .ucode_api_min = IWL2000_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_2000, \ .trans.device_family = IWL_DEVICE_FAMILY_2000, \
.max_inst_size = IWL60_RTC_INST_SIZE, \ .max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \ .nvm_ver = EEPROM_2000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
.base_params = &iwl2000_base_params, \ .trans.base_params = &iwl2000_base_params, \
.eeprom_params = &iwl20x0_eeprom_params, \ .eeprom_params = &iwl20x0_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
const struct iwl_cfg iwl2000_2bgn_cfg = { const struct iwl_cfg iwl2000_2bgn_cfg = {
@ -123,16 +123,16 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = {
.fw_name_pre = IWL2030_FW_PRE, \ .fw_name_pre = IWL2030_FW_PRE, \
.ucode_api_max = IWL2030_UCODE_API_MAX, \ .ucode_api_max = IWL2030_UCODE_API_MAX, \
.ucode_api_min = IWL2030_UCODE_API_MIN, \ .ucode_api_min = IWL2030_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_2030, \ .trans.device_family = IWL_DEVICE_FAMILY_2030, \
.max_inst_size = IWL60_RTC_INST_SIZE, \ .max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \ .nvm_ver = EEPROM_2000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
.base_params = &iwl2030_base_params, \ .trans.base_params = &iwl2030_base_params, \
.eeprom_params = &iwl20x0_eeprom_params, \ .eeprom_params = &iwl20x0_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
const struct iwl_cfg iwl2030_2bgn_cfg = { const struct iwl_cfg iwl2030_2bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 2230 BGN", .name = "Intel(R) Centrino(R) Wireless-N 2230 BGN",
@ -144,17 +144,17 @@ const struct iwl_cfg iwl2030_2bgn_cfg = {
.fw_name_pre = IWL105_FW_PRE, \ .fw_name_pre = IWL105_FW_PRE, \
.ucode_api_max = IWL105_UCODE_API_MAX, \ .ucode_api_max = IWL105_UCODE_API_MAX, \
.ucode_api_min = IWL105_UCODE_API_MIN, \ .ucode_api_min = IWL105_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_105, \ .trans.device_family = IWL_DEVICE_FAMILY_105, \
.max_inst_size = IWL60_RTC_INST_SIZE, \ .max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \ .nvm_ver = EEPROM_2000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
.base_params = &iwl2000_base_params, \ .trans.base_params = &iwl2000_base_params, \
.eeprom_params = &iwl20x0_eeprom_params, \ .eeprom_params = &iwl20x0_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.rx_with_siso_diversity = true, \ .rx_with_siso_diversity = true, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
const struct iwl_cfg iwl105_bgn_cfg = { const struct iwl_cfg iwl105_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 105 BGN", .name = "Intel(R) Centrino(R) Wireless-N 105 BGN",
@ -172,17 +172,17 @@ const struct iwl_cfg iwl105_bgn_d_cfg = {
.fw_name_pre = IWL135_FW_PRE, \ .fw_name_pre = IWL135_FW_PRE, \
.ucode_api_max = IWL135_UCODE_API_MAX, \ .ucode_api_max = IWL135_UCODE_API_MAX, \
.ucode_api_min = IWL135_UCODE_API_MIN, \ .ucode_api_min = IWL135_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_135, \ .trans.device_family = IWL_DEVICE_FAMILY_135, \
.max_inst_size = IWL60_RTC_INST_SIZE, \ .max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \ .nvm_ver = EEPROM_2000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
.base_params = &iwl2030_base_params, \ .trans.base_params = &iwl2030_base_params, \
.eeprom_params = &iwl20x0_eeprom_params, \ .eeprom_params = &iwl20x0_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.rx_with_siso_diversity = true, \ .rx_with_siso_diversity = true, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
const struct iwl_cfg iwl135_bgn_cfg = { const struct iwl_cfg iwl135_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 135 BGN", .name = "Intel(R) Centrino(R) Wireless-N 135 BGN",

View File

@ -56,7 +56,7 @@
#include "iwl-config.h" #include "iwl-config.h"
/* Highest firmware API version supported */ /* Highest firmware API version supported */
#define IWL_22000_UCODE_API_MAX 48 #define IWL_22000_UCODE_API_MAX 50
/* Lowest firmware API version supported */ /* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN 39 #define IWL_22000_UCODE_API_MIN 39
@ -76,7 +76,6 @@
#define IWL_22000_HR_FW_PRE "iwlwifi-Qu-a0-hr-a0-" #define IWL_22000_HR_FW_PRE "iwlwifi-Qu-a0-hr-a0-"
#define IWL_22000_HR_CDB_FW_PRE "iwlwifi-QuIcp-z0-hrcdb-a0-" #define IWL_22000_HR_CDB_FW_PRE "iwlwifi-QuIcp-z0-hrcdb-a0-"
#define IWL_22000_HR_A_F0_FW_PRE "iwlwifi-QuQnj-f0-hr-a0-" #define IWL_22000_HR_A_F0_FW_PRE "iwlwifi-QuQnj-f0-hr-a0-"
#define IWL_22000_HR_B_F0_FW_PRE "iwlwifi-Qu-b0-hr-b0-"
#define IWL_22000_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-" #define IWL_22000_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-"
#define IWL_22000_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-" #define IWL_22000_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-"
#define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-" #define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-"
@ -99,8 +98,6 @@
IWL_22000_JF_FW_PRE __stringify(api) ".ucode" IWL_22000_JF_FW_PRE __stringify(api) ".ucode"
#define IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(api) \ #define IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(api) \
IWL_22000_HR_A_F0_FW_PRE __stringify(api) ".ucode" IWL_22000_HR_A_F0_FW_PRE __stringify(api) ".ucode"
#define IWL_22000_HR_B_F0_QNJ_MODULE_FIRMWARE(api) \
IWL_22000_HR_B_F0_FW_PRE __stringify(api) ".ucode"
#define IWL_22000_QU_B_HR_B_MODULE_FIRMWARE(api) \ #define IWL_22000_QU_B_HR_B_MODULE_FIRMWARE(api) \
IWL_22000_QU_B_HR_B_FW_PRE __stringify(api) ".ucode" IWL_22000_QU_B_HR_B_FW_PRE __stringify(api) ".ucode"
#define IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(api) \ #define IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(api) \
@ -172,15 +169,15 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
.smem_len = IWL_22000_SMEM_LEN, \ .smem_len = IWL_22000_SMEM_LEN, \
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \ .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
.apmg_not_supported = true, \ .apmg_not_supported = true, \
.mq_rx_supported = true, \ .trans.mq_rx_supported = true, \
.vht_mu_mimo_supported = true, \ .vht_mu_mimo_supported = true, \
.mac_addr_from_csr = true, \ .mac_addr_from_csr = true, \
.ht_params = &iwl_22000_ht_params, \ .ht_params = &iwl_22000_ht_params, \
.nvm_ver = IWL_22000_NVM_VERSION, \ .nvm_ver = IWL_22000_NVM_VERSION, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.use_tfh = true, \ .trans.use_tfh = true, \
.rf_id = true, \ .trans.rf_id = true, \
.gen2 = true, \ .trans.gen2 = true, \
.nvm_type = IWL_NVM_EXT, \ .nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true, \ .dbgc_supported = true, \
.min_umac_error_event_table = 0x400000, \ .min_umac_error_event_table = 0x400000, \
@ -191,28 +188,25 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
.fw_mon_smem_cycle_cnt_ptr_addr = 0xa0c174, \ .fw_mon_smem_cycle_cnt_ptr_addr = 0xa0c174, \
.fw_mon_smem_cycle_cnt_ptr_msk = 0xfffff .fw_mon_smem_cycle_cnt_ptr_msk = 0xfffff
#define IWL_DEVICE_AX200_COMMON \
IWL_DEVICE_22000_COMMON, \
.umac_prph_offset = 0x300000
#define IWL_DEVICE_22500 \ #define IWL_DEVICE_22500 \
IWL_DEVICE_22000_COMMON, \ IWL_DEVICE_22000_COMMON, \
.device_family = IWL_DEVICE_FAMILY_22000, \ .trans.device_family = IWL_DEVICE_FAMILY_22000, \
.base_params = &iwl_22000_base_params, \ .trans.base_params = &iwl_22000_base_params, \
.csr = &iwl_csr_v1, \ .trans.csr = &iwl_csr_v1, \
.gp2_reg_addr = 0xa02c68 .gp2_reg_addr = 0xa02c68
#define IWL_DEVICE_22560 \ #define IWL_DEVICE_22560 \
IWL_DEVICE_22000_COMMON, \ IWL_DEVICE_22000_COMMON, \
.device_family = IWL_DEVICE_FAMILY_22560, \ .trans.device_family = IWL_DEVICE_FAMILY_22560, \
.base_params = &iwl_22560_base_params, \ .trans.base_params = &iwl_22560_base_params, \
.csr = &iwl_csr_v2 .trans.csr = &iwl_csr_v2
#define IWL_DEVICE_AX210 \ #define IWL_DEVICE_AX210 \
IWL_DEVICE_AX200_COMMON, \ IWL_DEVICE_22000_COMMON, \
.device_family = IWL_DEVICE_FAMILY_AX210, \ .trans.umac_prph_offset = 0x300000, \
.base_params = &iwl_22560_base_params, \ .trans.device_family = IWL_DEVICE_FAMILY_AX210, \
.csr = &iwl_csr_v1, \ .trans.base_params = &iwl_22560_base_params, \
.trans.csr = &iwl_csr_v1, \
.min_txq_size = 128, \ .min_txq_size = 128, \
.gp2_reg_addr = 0xd02c68, \ .gp2_reg_addr = 0xd02c68, \
.min_256_ba_txq_size = 512 .min_256_ba_txq_size = 512
@ -246,6 +240,7 @@ const struct iwl_cfg iwl_ax101_cfg_qu_hr = {
* HT size; mac80211 would otherwise pick the HE max (256) by default. * HT size; mac80211 would otherwise pick the HE max (256) by default.
*/ */
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.tx_with_siso_diversity = true,
}; };
const struct iwl_cfg iwl_ax201_cfg_qu_hr = { const struct iwl_cfg iwl_ax201_cfg_qu_hr = {
@ -342,7 +337,7 @@ const struct iwl_cfg iwl_ax200_cfg_cc = {
* HT size; mac80211 would otherwise pick the HE max (256) by default. * HT size; mac80211 would otherwise pick the HE max (256) by default.
*/ */
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.bisr_workaround = 1, .trans.bisr_workaround = 1,
}; };
const struct iwl_cfg killer1650x_2ax_cfg = { const struct iwl_cfg killer1650x_2ax_cfg = {
@ -355,7 +350,7 @@ const struct iwl_cfg killer1650x_2ax_cfg = {
* HT size; mac80211 would otherwise pick the HE max (256) by default. * HT size; mac80211 would otherwise pick the HE max (256) by default.
*/ */
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.bisr_workaround = 1, .trans.bisr_workaround = 1,
}; };
const struct iwl_cfg killer1650w_2ax_cfg = { const struct iwl_cfg killer1650w_2ax_cfg = {
@ -368,7 +363,7 @@ const struct iwl_cfg killer1650w_2ax_cfg = {
* HT size; mac80211 would otherwise pick the HE max (256) by default. * HT size; mac80211 would otherwise pick the HE max (256) by default.
*/ */
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.bisr_workaround = 1, .trans.bisr_workaround = 1,
}; };
/* /*
@ -663,7 +658,6 @@ const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = {
MODULE_FIRMWARE(IWL_22000_HR_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_HR_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_JF_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_JF_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_HR_B_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));

View File

@ -67,16 +67,16 @@ static const struct iwl_eeprom_params iwl5000_eeprom_params = {
.fw_name_pre = IWL5000_FW_PRE, \ .fw_name_pre = IWL5000_FW_PRE, \
.ucode_api_max = IWL5000_UCODE_API_MAX, \ .ucode_api_max = IWL5000_UCODE_API_MAX, \
.ucode_api_min = IWL5000_UCODE_API_MIN, \ .ucode_api_min = IWL5000_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_5000, \ .trans.device_family = IWL_DEVICE_FAMILY_5000, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \ .max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \ .max_data_size = IWLAGN_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_5000_EEPROM_VERSION, \ .nvm_ver = EEPROM_5000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_5000_TX_POWER_VERSION, \ .nvm_calib_ver = EEPROM_5000_TX_POWER_VERSION, \
.base_params = &iwl5000_base_params, \ .trans.base_params = &iwl5000_base_params, \
.eeprom_params = &iwl5000_eeprom_params, \ .eeprom_params = &iwl5000_eeprom_params, \
.led_mode = IWL_LED_BLINK, \ .led_mode = IWL_LED_BLINK, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
const struct iwl_cfg iwl5300_agn_cfg = { const struct iwl_cfg iwl5300_agn_cfg = {
.name = "Intel(R) Ultimate N WiFi Link 5300 AGN", .name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
@ -115,34 +115,34 @@ const struct iwl_cfg iwl5350_agn_cfg = {
.fw_name_pre = IWL5000_FW_PRE, .fw_name_pre = IWL5000_FW_PRE,
.ucode_api_max = IWL5000_UCODE_API_MAX, .ucode_api_max = IWL5000_UCODE_API_MAX,
.ucode_api_min = IWL5000_UCODE_API_MIN, .ucode_api_min = IWL5000_UCODE_API_MIN,
.device_family = IWL_DEVICE_FAMILY_5000, .trans.device_family = IWL_DEVICE_FAMILY_5000,
.max_inst_size = IWLAGN_RTC_INST_SIZE, .max_inst_size = IWLAGN_RTC_INST_SIZE,
.max_data_size = IWLAGN_RTC_DATA_SIZE, .max_data_size = IWLAGN_RTC_DATA_SIZE,
.nvm_ver = EEPROM_5050_EEPROM_VERSION, .nvm_ver = EEPROM_5050_EEPROM_VERSION,
.nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION, .nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION,
.base_params = &iwl5000_base_params, .trans.base_params = &iwl5000_base_params,
.eeprom_params = &iwl5000_eeprom_params, .eeprom_params = &iwl5000_eeprom_params,
.ht_params = &iwl5000_ht_params, .ht_params = &iwl5000_ht_params,
.led_mode = IWL_LED_BLINK, .led_mode = IWL_LED_BLINK,
.internal_wimax_coex = true, .internal_wimax_coex = true,
.csr = &iwl_csr_v1, .trans.csr = &iwl_csr_v1,
}; };
#define IWL_DEVICE_5150 \ #define IWL_DEVICE_5150 \
.fw_name_pre = IWL5150_FW_PRE, \ .fw_name_pre = IWL5150_FW_PRE, \
.ucode_api_max = IWL5150_UCODE_API_MAX, \ .ucode_api_max = IWL5150_UCODE_API_MAX, \
.ucode_api_min = IWL5150_UCODE_API_MIN, \ .ucode_api_min = IWL5150_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_5150, \ .trans.device_family = IWL_DEVICE_FAMILY_5150, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \ .max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \ .max_data_size = IWLAGN_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_5050_EEPROM_VERSION, \ .nvm_ver = EEPROM_5050_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ .nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION, \
.base_params = &iwl5000_base_params, \ .trans.base_params = &iwl5000_base_params, \
.eeprom_params = &iwl5000_eeprom_params, \ .eeprom_params = &iwl5000_eeprom_params, \
.led_mode = IWL_LED_BLINK, \ .led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true, \ .internal_wimax_coex = true, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
const struct iwl_cfg iwl5150_agn_cfg = { const struct iwl_cfg iwl5150_agn_cfg = {
.name = "Intel(R) WiMAX/WiFi Link 5150 AGN", .name = "Intel(R) WiMAX/WiFi Link 5150 AGN",

View File

@ -2,7 +2,7 @@
/****************************************************************************** /******************************************************************************
* *
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
@ -116,16 +116,16 @@ static const struct iwl_eeprom_params iwl6000_eeprom_params = {
.fw_name_pre = IWL6005_FW_PRE, \ .fw_name_pre = IWL6005_FW_PRE, \
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \ .ucode_api_max = IWL6000G2_UCODE_API_MAX, \
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \ .ucode_api_min = IWL6000G2_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_6005, \ .trans.device_family = IWL_DEVICE_FAMILY_6005, \
.max_inst_size = IWL60_RTC_INST_SIZE, \ .max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_6005_EEPROM_VERSION, \ .nvm_ver = EEPROM_6005_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ .nvm_calib_ver = EEPROM_6005_TX_POWER_VERSION, \
.base_params = &iwl6000_g2_base_params, \ .trans.base_params = &iwl6000_g2_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \ .eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
const struct iwl_cfg iwl6005_2agn_cfg = { const struct iwl_cfg iwl6005_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205 AGN", .name = "Intel(R) Centrino(R) Advanced-N 6205 AGN",
@ -171,16 +171,16 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = {
.fw_name_pre = IWL6030_FW_PRE, \ .fw_name_pre = IWL6030_FW_PRE, \
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \ .ucode_api_max = IWL6000G2_UCODE_API_MAX, \
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \ .ucode_api_min = IWL6000G2_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_6030, \ .trans.device_family = IWL_DEVICE_FAMILY_6030, \
.max_inst_size = IWL60_RTC_INST_SIZE, \ .max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_6030_EEPROM_VERSION, \ .nvm_ver = EEPROM_6030_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ .nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
.base_params = &iwl6000_g2_base_params, \ .trans.base_params = &iwl6000_g2_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \ .eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
const struct iwl_cfg iwl6030_2agn_cfg = { const struct iwl_cfg iwl6030_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6230 AGN", .name = "Intel(R) Centrino(R) Advanced-N 6230 AGN",
@ -208,16 +208,16 @@ const struct iwl_cfg iwl6030_2bg_cfg = {
.fw_name_pre = IWL6030_FW_PRE, \ .fw_name_pre = IWL6030_FW_PRE, \
.ucode_api_max = IWL6035_UCODE_API_MAX, \ .ucode_api_max = IWL6035_UCODE_API_MAX, \
.ucode_api_min = IWL6035_UCODE_API_MIN, \ .ucode_api_min = IWL6035_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_6030, \ .trans.device_family = IWL_DEVICE_FAMILY_6030, \
.max_inst_size = IWL60_RTC_INST_SIZE, \ .max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_6030_EEPROM_VERSION, \ .nvm_ver = EEPROM_6030_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ .nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
.base_params = &iwl6000_g2_base_params, \ .trans.base_params = &iwl6000_g2_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \ .eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
const struct iwl_cfg iwl6035_2agn_cfg = { const struct iwl_cfg iwl6035_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6235 AGN", .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN",
@ -262,18 +262,18 @@ const struct iwl_cfg iwl130_bg_cfg = {
.fw_name_pre = IWL6000_FW_PRE, \ .fw_name_pre = IWL6000_FW_PRE, \
.ucode_api_max = IWL6000_UCODE_API_MAX, \ .ucode_api_max = IWL6000_UCODE_API_MAX, \
.ucode_api_min = IWL6000_UCODE_API_MIN, \ .ucode_api_min = IWL6000_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_6000i, \ .trans.device_family = IWL_DEVICE_FAMILY_6000i, \
.max_inst_size = IWL60_RTC_INST_SIZE, \ .max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \
.valid_tx_ant = ANT_BC, /* .cfg overwrite */ \ .valid_tx_ant = ANT_BC, /* .cfg overwrite */ \
.valid_rx_ant = ANT_BC, /* .cfg overwrite */ \ .valid_rx_ant = ANT_BC, /* .cfg overwrite */ \
.nvm_ver = EEPROM_6000_EEPROM_VERSION, \ .nvm_ver = EEPROM_6000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ .nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION, \
.base_params = &iwl6000_base_params, \ .trans.base_params = &iwl6000_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \ .eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_BLINK, \ .led_mode = IWL_LED_BLINK, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
const struct iwl_cfg iwl6000i_2agn_cfg = { const struct iwl_cfg iwl6000i_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6200 AGN", .name = "Intel(R) Centrino(R) Advanced-N 6200 AGN",
@ -295,19 +295,19 @@ const struct iwl_cfg iwl6000i_2bg_cfg = {
.fw_name_pre = IWL6050_FW_PRE, \ .fw_name_pre = IWL6050_FW_PRE, \
.ucode_api_max = IWL6050_UCODE_API_MAX, \ .ucode_api_max = IWL6050_UCODE_API_MAX, \
.ucode_api_min = IWL6050_UCODE_API_MIN, \ .ucode_api_min = IWL6050_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_6050, \ .trans.device_family = IWL_DEVICE_FAMILY_6050, \
.max_inst_size = IWL60_RTC_INST_SIZE, \ .max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \
.valid_tx_ant = ANT_AB, /* .cfg overwrite */ \ .valid_tx_ant = ANT_AB, /* .cfg overwrite */ \
.valid_rx_ant = ANT_AB, /* .cfg overwrite */ \ .valid_rx_ant = ANT_AB, /* .cfg overwrite */ \
.nvm_ver = EEPROM_6050_EEPROM_VERSION, \ .nvm_ver = EEPROM_6050_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6050_TX_POWER_VERSION, \ .nvm_calib_ver = EEPROM_6050_TX_POWER_VERSION, \
.base_params = &iwl6050_base_params, \ .trans.base_params = &iwl6050_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \ .eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_BLINK, \ .led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true, \ .internal_wimax_coex = true, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
const struct iwl_cfg iwl6050_2agn_cfg = { const struct iwl_cfg iwl6050_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN", .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN",
@ -324,17 +324,17 @@ const struct iwl_cfg iwl6050_2abg_cfg = {
.fw_name_pre = IWL6050_FW_PRE, \ .fw_name_pre = IWL6050_FW_PRE, \
.ucode_api_max = IWL6050_UCODE_API_MAX, \ .ucode_api_max = IWL6050_UCODE_API_MAX, \
.ucode_api_min = IWL6050_UCODE_API_MIN, \ .ucode_api_min = IWL6050_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_6150, \ .trans.device_family = IWL_DEVICE_FAMILY_6150, \
.max_inst_size = IWL60_RTC_INST_SIZE, \ .max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_6150_EEPROM_VERSION, \ .nvm_ver = EEPROM_6150_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6150_TX_POWER_VERSION, \ .nvm_calib_ver = EEPROM_6150_TX_POWER_VERSION, \
.base_params = &iwl6050_base_params, \ .trans.base_params = &iwl6050_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \ .eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_BLINK, \ .led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true, \ .internal_wimax_coex = true, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
const struct iwl_cfg iwl6150_bgn_cfg = { const struct iwl_cfg iwl6150_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN", .name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN",
@ -352,16 +352,16 @@ const struct iwl_cfg iwl6000_3agn_cfg = {
.fw_name_pre = IWL6000_FW_PRE, .fw_name_pre = IWL6000_FW_PRE,
.ucode_api_max = IWL6000_UCODE_API_MAX, .ucode_api_max = IWL6000_UCODE_API_MAX,
.ucode_api_min = IWL6000_UCODE_API_MIN, .ucode_api_min = IWL6000_UCODE_API_MIN,
.device_family = IWL_DEVICE_FAMILY_6000, .trans.device_family = IWL_DEVICE_FAMILY_6000,
.max_inst_size = IWL60_RTC_INST_SIZE, .max_inst_size = IWL60_RTC_INST_SIZE,
.max_data_size = IWL60_RTC_DATA_SIZE, .max_data_size = IWL60_RTC_DATA_SIZE,
.nvm_ver = EEPROM_6000_EEPROM_VERSION, .nvm_ver = EEPROM_6000_EEPROM_VERSION,
.nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION, .nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION,
.base_params = &iwl6000_base_params, .trans.base_params = &iwl6000_base_params,
.eeprom_params = &iwl6000_eeprom_params, .eeprom_params = &iwl6000_eeprom_params,
.ht_params = &iwl6000_ht_params, .ht_params = &iwl6000_ht_params,
.led_mode = IWL_LED_BLINK, .led_mode = IWL_LED_BLINK,
.csr = &iwl_csr_v1, .trans.csr = &iwl_csr_v1,
}; };
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));

View File

@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH * Copyright(c) 2015 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH * Copyright(c) 2015 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -148,14 +148,14 @@ static const struct iwl_ht_params iwl7000_ht_params = {
}; };
#define IWL_DEVICE_7000_COMMON \ #define IWL_DEVICE_7000_COMMON \
.device_family = IWL_DEVICE_FAMILY_7000, \ .trans.device_family = IWL_DEVICE_FAMILY_7000, \
.base_params = &iwl7000_base_params, \ .trans.base_params = &iwl7000_base_params, \
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = 0, \ .nvm_hw_section_num = 0, \
.non_shared_ant = ANT_A, \ .non_shared_ant = ANT_A, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.dccm_offset = IWL7000_DCCM_OFFSET, \ .dccm_offset = IWL7000_DCCM_OFFSET, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
#define IWL_DEVICE_7000 \ #define IWL_DEVICE_7000 \
IWL_DEVICE_7000_COMMON, \ IWL_DEVICE_7000_COMMON, \

View File

@ -8,7 +8,7 @@
* Copyright(c) 2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH * Copyright(c) 2016 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -30,7 +30,7 @@
* *
* Copyright(c) 2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -134,8 +134,8 @@ static const struct iwl_tt_params iwl8000_tt_params = {
}; };
#define IWL_DEVICE_8000_COMMON \ #define IWL_DEVICE_8000_COMMON \
.device_family = IWL_DEVICE_FAMILY_8000, \ .trans.device_family = IWL_DEVICE_FAMILY_8000, \
.base_params = &iwl8000_base_params, \ .trans.base_params = &iwl8000_base_params, \
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = 10, \ .nvm_hw_section_num = 10, \
.features = NETIF_F_RXCSUM, \ .features = NETIF_F_RXCSUM, \
@ -152,7 +152,7 @@ static const struct iwl_tt_params iwl8000_tt_params = {
.nvm_type = IWL_NVM_EXT, \ .nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true, \ .dbgc_supported = true, \
.min_umac_error_event_table = 0x800000, \ .min_umac_error_event_table = 0x800000, \
.csr = &iwl_csr_v1 .trans.csr = &iwl_csr_v1
#define IWL_DEVICE_8000 \ #define IWL_DEVICE_8000 \
IWL_DEVICE_8000_COMMON, \ IWL_DEVICE_8000_COMMON, \

View File

@ -122,8 +122,8 @@ static const struct iwl_tt_params iwl9000_tt_params = {
#define IWL_DEVICE_9000 \ #define IWL_DEVICE_9000 \
.ucode_api_max = IWL9000_UCODE_API_MAX, \ .ucode_api_max = IWL9000_UCODE_API_MAX, \
.ucode_api_min = IWL9000_UCODE_API_MIN, \ .ucode_api_min = IWL9000_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_9000, \ .trans.device_family = IWL_DEVICE_FAMILY_9000, \
.base_params = &iwl9000_base_params, \ .trans.base_params = &iwl9000_base_params, \
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = 10, \ .nvm_hw_section_num = 10, \
.non_shared_ant = ANT_B, \ .non_shared_ant = ANT_B, \
@ -136,14 +136,14 @@ static const struct iwl_tt_params iwl9000_tt_params = {
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \ .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
.thermal_params = &iwl9000_tt_params, \ .thermal_params = &iwl9000_tt_params, \
.apmg_not_supported = true, \ .apmg_not_supported = true, \
.mq_rx_supported = true, \ .trans.mq_rx_supported = true, \
.vht_mu_mimo_supported = true, \ .vht_mu_mimo_supported = true, \
.mac_addr_from_csr = true, \ .mac_addr_from_csr = true, \
.rf_id = true, \ .trans.rf_id = true, \
.nvm_type = IWL_NVM_EXT, \ .nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true, \ .dbgc_supported = true, \
.min_umac_error_event_table = 0x800000, \ .min_umac_error_event_table = 0x800000, \
.csr = &iwl_csr_v1, \ .trans.csr = &iwl_csr_v1, \
.d3_debug_data_base_addr = 0x401000, \ .d3_debug_data_base_addr = 0x401000, \
.d3_debug_data_length = 92 * 1024, \ .d3_debug_data_length = 92 * 1024, \
.ht_params = &iwl9000_ht_params, \ .ht_params = &iwl9000_ht_params, \

View File

@ -2,6 +2,7 @@
/****************************************************************************** /******************************************************************************
* *
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2019 Intel Corporation
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
@ -483,7 +484,7 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
/* NIC configuration for 6000 series */ /* NIC configuration for 6000 series */
static void iwl6000_nic_config(struct iwl_priv *priv) static void iwl6000_nic_config(struct iwl_priv *priv)
{ {
switch (priv->cfg->device_family) { switch (priv->trans->trans_cfg->device_family) {
case IWL_DEVICE_FAMILY_6005: case IWL_DEVICE_FAMILY_6005:
case IWL_DEVICE_FAMILY_6030: case IWL_DEVICE_FAMILY_6030:
case IWL_DEVICE_FAMILY_6000: case IWL_DEVICE_FAMILY_6000:

View File

@ -2,6 +2,7 @@
/****************************************************************************** /******************************************************************************
* *
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2019 Intel Corporation
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
@ -120,9 +121,9 @@ static int iwl_led_cmd(struct iwl_priv *priv,
} }
led_cmd.on = iwl_blink_compensation(priv, on, led_cmd.on = iwl_blink_compensation(priv, on,
priv->cfg->base_params->led_compensation); priv->trans->trans_cfg->base_params->led_compensation);
led_cmd.off = iwl_blink_compensation(priv, off, led_cmd.off = iwl_blink_compensation(priv, off,
priv->cfg->base_params->led_compensation); priv->trans->trans_cfg->base_params->led_compensation);
ret = iwl_send_led_cmd(priv, &led_cmd); ret = iwl_send_led_cmd(priv, &led_cmd);
if (!ret) { if (!ret) {

View File

@ -2,7 +2,7 @@
/****************************************************************************** /******************************************************************************
* *
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018 - 2019 Intel Corporation
* *
* Portions of this file are derived from the ipw3945 project, as well * Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files. * as portions of the ieee80211 subsystem header files.
@ -1099,7 +1099,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
goto done; goto done;
} }
scd_queues = BIT(priv->cfg->base_params->num_of_queues) - 1; scd_queues = BIT(priv->trans->trans_cfg->base_params->num_of_queues) - 1;
scd_queues &= ~(BIT(IWL_IPAN_CMD_QUEUE_NUM) | scd_queues &= ~(BIT(IWL_IPAN_CMD_QUEUE_NUM) |
BIT(IWL_DEFAULT_CMD_QUEUE_NUM)); BIT(IWL_DEFAULT_CMD_QUEUE_NUM));

View File

@ -3,7 +3,7 @@
* *
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH * Copyright(c) 2015 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018 - 2019 Intel Corporation
* *
* Portions of this file are derived from the ipw3945 project, as well * Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files. * as portions of the ieee80211 subsystem header files.
@ -1267,7 +1267,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
priv->cfg = cfg; priv->cfg = cfg;
priv->fw = fw; priv->fw = fw;
switch (priv->cfg->device_family) { switch (priv->trans->trans_cfg->device_family) {
case IWL_DEVICE_FAMILY_1000: case IWL_DEVICE_FAMILY_1000:
case IWL_DEVICE_FAMILY_100: case IWL_DEVICE_FAMILY_100:
priv->lib = &iwl_dvm_1000_cfg; priv->lib = &iwl_dvm_1000_cfg;
@ -1342,7 +1342,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
driver_data[2]); driver_data[2]);
WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE < WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE <
priv->cfg->base_params->num_of_queues); priv->trans->trans_cfg->base_params->num_of_queues);
ucode_flags = fw->ucode_capa.flags; ucode_flags = fw->ucode_capa.flags;
@ -1405,7 +1405,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
/* Reset chip to save power until we load uCode during "up". */ /* Reset chip to save power until we load uCode during "up". */
iwl_trans_stop_device(priv->trans); iwl_trans_stop_device(priv->trans);
priv->nvm_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg, priv->nvm_data = iwl_parse_eeprom_data(priv->trans, priv->cfg,
priv->eeprom_blob, priv->eeprom_blob,
priv->eeprom_blob_size); priv->eeprom_blob_size);
if (!priv->nvm_data) if (!priv->nvm_data)

View File

@ -2,6 +2,7 @@
/****************************************************************************** /******************************************************************************
* *
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2019 Intel Corporation
* *
* Portions of this file are derived from the ipw3945 project, as well * Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files. * as portions of the ieee80211 subsystem header files.
@ -199,7 +200,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
else else
cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
if (priv->cfg->base_params->shadow_reg_enable) if (priv->trans->trans_cfg->base_params->shadow_reg_enable)
cmd->flags |= IWL_POWER_SHADOW_REG_ENA; cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
else else
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;

View File

@ -2,6 +2,7 @@
/****************************************************************************** /******************************************************************************
* *
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2019 Intel Corporation
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <linuxwifi@intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
@ -467,7 +468,7 @@ static int iwlagn_alloc_agg_txq(struct iwl_priv *priv, int mq)
int q; int q;
for (q = IWLAGN_FIRST_AMPDU_QUEUE; for (q = IWLAGN_FIRST_AMPDU_QUEUE;
q < priv->cfg->base_params->num_of_queues; q++) { q < priv->trans->trans_cfg->base_params->num_of_queues; q++) {
if (!test_and_set_bit(q, priv->agg_q_alloc)) { if (!test_and_set_bit(q, priv->agg_q_alloc)) {
priv->queue_to_mac80211[q] = mq; priv->queue_to_mac80211[q] = mq;
return q; return q;
@ -1281,7 +1282,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
* (in Tx queue's circular buffer) of first TFD/frame in window */ * (in Tx queue's circular buffer) of first TFD/frame in window */
u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
if (scd_flow >= priv->cfg->base_params->num_of_queues) { if (scd_flow >= priv->trans->trans_cfg->base_params->num_of_queues) {
IWL_ERR(priv, IWL_ERR(priv,
"BUG_ON scd_flow is bigger than number of queues\n"); "BUG_ON scd_flow is bigger than number of queues\n");
return; return;

View File

@ -68,6 +68,7 @@
#define ACPI_WRDD_METHOD "WRDD" #define ACPI_WRDD_METHOD "WRDD"
#define ACPI_SPLC_METHOD "SPLC" #define ACPI_SPLC_METHOD "SPLC"
#define ACPI_ECKV_METHOD "ECKV" #define ACPI_ECKV_METHOD "ECKV"
#define ACPI_PPAG_METHOD "PPAG"
#define ACPI_WIFI_DOMAIN (0x07) #define ACPI_WIFI_DOMAIN (0x07)
@ -92,6 +93,17 @@
#define ACPI_WGDS_NUM_BANDS 2 #define ACPI_WGDS_NUM_BANDS 2
#define ACPI_WGDS_TABLE_SIZE 3 #define ACPI_WGDS_TABLE_SIZE 3
#define ACPI_PPAG_NUM_CHAINS 2
#define ACPI_PPAG_NUM_SUB_BANDS 5
#define ACPI_PPAG_WIFI_DATA_SIZE ((ACPI_PPAG_NUM_CHAINS * \
ACPI_PPAG_NUM_SUB_BANDS) + 3)
/* PPAG gain value bounds in 1/8 dBm */
#define ACPI_PPAG_MIN_LB -16
#define ACPI_PPAG_MAX_LB 24
#define ACPI_PPAG_MIN_HB -16
#define ACPI_PPAG_MAX_HB 40
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
void *iwl_acpi_get_object(struct device *dev, acpi_string method); void *iwl_acpi_get_object(struct device *dev, acpi_string method);

View File

@ -474,6 +474,13 @@ enum iwl_legacy_cmds {
*/ */
REPLY_RX_MPDU_CMD = 0xc1, REPLY_RX_MPDU_CMD = 0xc1,
/**
* @BAR_FRAME_RELEASE: Frame release from BAR notification, used for
* multi-TID BAR (previously, the BAR frame itself was reported
* instead). Uses &struct iwl_bar_frame_release.
*/
BAR_FRAME_RELEASE = 0xc2,
/** /**
* @FRAME_RELEASE: * @FRAME_RELEASE:
* Frame release (reorder helper) notification, uses * Frame release (reorder helper) notification, uses

View File

@ -396,6 +396,7 @@ enum iwl_wowlan_flags {
* @is_11n_connection: indicates HT connection * @is_11n_connection: indicates HT connection
* @offloading_tid: TID reserved for firmware use * @offloading_tid: TID reserved for firmware use
* @flags: extra flags, see &enum iwl_wowlan_flags * @flags: extra flags, see &enum iwl_wowlan_flags
* @sta_id: station ID for wowlan.
* @reserved: reserved * @reserved: reserved
*/ */
struct iwl_wowlan_config_cmd { struct iwl_wowlan_config_cmd {
@ -406,8 +407,9 @@ struct iwl_wowlan_config_cmd {
u8 is_11n_connection; u8 is_11n_connection;
u8 offloading_tid; u8 offloading_tid;
u8 flags; u8 flags;
u8 reserved[2]; u8 sta_id;
} __packed; /* WOWLAN_CONFIG_API_S_VER_4 */ u8 reserved;
} __packed; /* WOWLAN_CONFIG_API_S_VER_5 */
/* /*
* WOWLAN_TSC_RSC_PARAMS * WOWLAN_TSC_RSC_PARAMS

View File

@ -140,17 +140,6 @@ struct iwl_fw_ini_hcmd_tlv {
struct iwl_fw_ini_hcmd hcmd; struct iwl_fw_ini_hcmd hcmd;
} __packed; /* FW_DEBUG_TLV_HCMD_API_S_VER_1 */ } __packed; /* FW_DEBUG_TLV_HCMD_API_S_VER_1 */
/**
* struct iwl_fw_ini_debug_flow_tlv - (IWL_UCODE_TLV_TYPE_DEBUG_FLOW)
*
* @header: header
* @debug_flow_cfg: &enum iwl_fw_ini_debug_flow
*/
struct iwl_fw_ini_debug_flow_tlv {
struct iwl_fw_ini_header header;
__le32 debug_flow_cfg;
} __packed; /* FW_DEBUG_TLV_FLOW_TLV_S_VER_1 */
#define IWL_FW_INI_MAX_REGION_ID 64 #define IWL_FW_INI_MAX_REGION_ID 64
#define IWL_FW_INI_MAX_NAME 32 #define IWL_FW_INI_MAX_NAME 32
@ -408,27 +397,6 @@ enum iwl_fw_ini_trigger_id {
IWL_FW_TRIGGER_ID_NUM, IWL_FW_TRIGGER_ID_NUM,
}; /* FW_DEBUG_TLV_TRIGGER_ID_E_VER_1 */ }; /* FW_DEBUG_TLV_TRIGGER_ID_E_VER_1 */
/**
* enum iwl_fw_ini_apply_point
*
* @IWL_FW_INI_APPLY_INVALID: invalid
* @IWL_FW_INI_APPLY_EARLY: pre loading FW
* @IWL_FW_INI_APPLY_AFTER_ALIVE: first cmd from host after alive
* @IWL_FW_INI_APPLY_POST_INIT: last cmd in initialization sequence
* @IWL_FW_INI_APPLY_MISSED_BEACONS: missed beacons notification
* @IWL_FW_INI_APPLY_SCAN_COMPLETE: scan completed
* @IWL_FW_INI_APPLY_NUM: number of apply points
*/
enum iwl_fw_ini_apply_point {
IWL_FW_INI_APPLY_INVALID,
IWL_FW_INI_APPLY_EARLY,
IWL_FW_INI_APPLY_AFTER_ALIVE,
IWL_FW_INI_APPLY_POST_INIT,
IWL_FW_INI_APPLY_MISSED_BEACONS,
IWL_FW_INI_APPLY_SCAN_COMPLETE,
IWL_FW_INI_APPLY_NUM,
}; /* FW_DEBUG_TLV_APPLY_POINT_E_VER_1 */
/** /**
* enum iwl_fw_ini_allocation_id * enum iwl_fw_ini_allocation_id
* *
@ -439,6 +407,7 @@ enum iwl_fw_ini_apply_point {
* @IWL_FW_INI_ALLOCATION_ID_SDFX: for SDFX module * @IWL_FW_INI_ALLOCATION_ID_SDFX: for SDFX module
* @IWL_FW_INI_ALLOCATION_ID_FW_DUMP: used for crash and runtime dumps * @IWL_FW_INI_ALLOCATION_ID_FW_DUMP: used for crash and runtime dumps
* @IWL_FW_INI_ALLOCATION_ID_USER_DEFINED: for future user scenarios * @IWL_FW_INI_ALLOCATION_ID_USER_DEFINED: for future user scenarios
* @IWL_FW_INI_ALLOCATION_NUM: number of allocation ids
*/ */
enum iwl_fw_ini_allocation_id { enum iwl_fw_ini_allocation_id {
IWL_FW_INI_ALLOCATION_INVALID, IWL_FW_INI_ALLOCATION_INVALID,
@ -448,6 +417,7 @@ enum iwl_fw_ini_allocation_id {
IWL_FW_INI_ALLOCATION_ID_SDFX, IWL_FW_INI_ALLOCATION_ID_SDFX,
IWL_FW_INI_ALLOCATION_ID_FW_DUMP, IWL_FW_INI_ALLOCATION_ID_FW_DUMP,
IWL_FW_INI_ALLOCATION_ID_USER_DEFINED, IWL_FW_INI_ALLOCATION_ID_USER_DEFINED,
IWL_FW_INI_ALLOCATION_NUM,
}; /* FW_DEBUG_TLV_ALLOCATION_ID_E_VER_1 */ }; /* FW_DEBUG_TLV_ALLOCATION_ID_E_VER_1 */
/** /**
@ -519,4 +489,72 @@ enum iwl_fw_ini_region_type {
IWL_FW_INI_REGION_NUM IWL_FW_INI_REGION_NUM
}; /* FW_DEBUG_TLV_REGION_TYPE_E_VER_1 */ }; /* FW_DEBUG_TLV_REGION_TYPE_E_VER_1 */
/**
* enum iwl_fw_ini_time_point
*
* Hard coded time points in which the driver can send hcmd or perform dump
* collection
*
* @IWL_FW_INI_TIME_POINT_EARLY: pre loading the FW
* @IWL_FW_INI_TIME_POINT_AFTER_ALIVE: first cmd from host after alive notif
* @IWL_FW_INI_TIME_POINT_POST_INIT: last cmd in series of init sequence
* @IWL_FW_INI_TIME_POINT_FW_ASSERT: FW assert
* @IWL_FW_INI_TIME_POINT_FW_HW_ERROR: FW HW error
* @IWL_FW_INI_TIME_POINT_FW_TFD_Q_HANG: TFD queue hang
* @IWL_FW_INI_TIME_POINT_FW_DHC_NOTIFOCATION: DHC cmd response and notif
* @IWL_FW_INI_TIME_POINT_FW_RSP_OR_NOTIF: FW response or notification.
* data field holds id and group
* @IWL_FW_INI_TIME_POINT_USER_TRIGGER: user trigger time point
* @IWL_FW_INI_TIME_POINT_PERIODIC: periodic timepoint that fires in constant
* intervals. data field holds the interval time in msec
* @IWL_FW_INI_TIME_POINT_WDG_TIMEOUT: watchdog timeout
* @IWL_FW_INI_TIME_POINT_HOST_ASSERT: Unused
* @IWL_FW_INI_TIME_POINT_HOST_ALIVE_TIMEOUT: alive timeout
* @IWL_FW_INI_TIME_POINT_HOST_DEVICE_ENABLE: device enable
* @IWL_FW_INI_TIME_POINT_HOST_DEVICE_DISABLE: device disable
* @IWL_FW_INI_TIME_POINT_HOST_D3_START: D3 start
* @IWL_FW_INI_TIME_POINT_HOST_D3_END: D3 end
* @IWL_FW_INI_TIME_POINT_MISSED_BEACONS: missed beacons
* @IWL_FW_INI_TIME_POINT_ASSOC_FAILED: association failure
* @IWL_FW_INI_TIME_POINT_TX_FAILED: Tx frame failed
* @IWL_FW_INI_TIME_POINT_TX_WFD_ACTION_FRAME_FAILED: wifi direct action
* frame failed
* @IWL_FW_INI_TIME_POINT_TX_LATENCY_THRESHOLD: Tx latency threshold
* @IWL_FW_INI_TIME_POINT_HANG_OCCURRED: hang occurred
* @IWL_FW_INI_TIME_POINT_EAPOL_FAILED: EAPOL failed
* @IWL_FW_INI_TIME_POINT_FAKE_TX: fake Tx
* @IWL_FW_INI_TIME_POINT_DEASSOC: de association
* @IWL_FW_INI_TIME_POINT_NUM: number of time points
*/
enum iwl_fw_ini_time_point {
IWL_FW_INI_TIME_POINT_INVALID,
IWL_FW_INI_TIME_POINT_EARLY,
IWL_FW_INI_TIME_POINT_AFTER_ALIVE,
IWL_FW_INI_TIME_POINT_POST_INIT,
IWL_FW_INI_TIME_POINT_FW_ASSERT,
IWL_FW_INI_TIME_POINT_FW_HW_ERROR,
IWL_FW_INI_TIME_POINT_FW_TFD_Q_HANG,
IWL_FW_INI_TIME_POINT_FW_DHC_NOTIFOCATION,
IWL_FW_INI_TIME_POINT_FW_RSP_OR_NOTIF,
IWL_FW_INI_TIME_POINT_USER_TRIGGER,
IWL_FW_INI_TIME_POINT_PERIODIC,
IWL_FW_INI_TIME_POINT_WDG_TIMEOUT,
IWL_FW_INI_TIME_POINT_HOST_ASSERT,
IWL_FW_INI_TIME_POINT_HOST_ALIVE_TIMEOUT,
IWL_FW_INI_TIME_POINT_HOST_DEVICE_ENABLE,
IWL_FW_INI_TIME_POINT_HOST_DEVICE_DISABLE,
IWL_FW_INI_TIME_POINT_HOST_D3_START,
IWL_FW_INI_TIME_POINT_HOST_D3_END,
IWL_FW_INI_TIME_POINT_MISSED_BEACONS,
IWL_FW_INI_TIME_POINT_ASSOC_FAILED,
IWL_FW_INI_TIME_POINT_TX_FAILED,
IWL_FW_INI_TIME_POINT_TX_WFD_ACTION_FRAME_FAILED,
IWL_FW_INI_TIME_POINT_TX_LATENCY_THRESHOLD,
IWL_FW_INI_TIME_POINT_HANG_OCCURRED,
IWL_FW_INI_TIME_POINT_EAPOL_FAILED,
IWL_FW_INI_TIME_POINT_FAKE_TX,
IWL_FW_INI_TIME_POINT_DEASSOC,
IWL_FW_INI_TIME_POINT_NUM,
}; /* FW_TLV_DEBUG_TIME_POINT_API_E */
#endif #endif

View File

@ -8,7 +8,7 @@
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -31,7 +31,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -80,6 +80,19 @@ enum iwl_debug_cmds {
* &struct iwl_dbg_mem_access_rsp * &struct iwl_dbg_mem_access_rsp
*/ */
UMAC_RD_WR = 0x1, UMAC_RD_WR = 0x1,
/**
* @DBGC_SUSPEND_RESUME:
* DBGC suspend/resume commad. Uses a single dword as data:
* 0 - resume DBGC recording
* 1 - suspend DBGC recording
*/
DBGC_SUSPEND_RESUME = 0x7,
/**
* @BUFFER_ALLOCATION:
* passes DRAM buffers to a DBGC
* &struct iwl_buf_alloc_cmd
*/
BUFFER_ALLOCATION = 0x8,
/** /**
* @MFU_ASSERT_DUMP_NTF: * @MFU_ASSERT_DUMP_NTF:
* &struct iwl_mfu_assert_dump_notif * &struct iwl_mfu_assert_dump_notif
@ -102,6 +115,16 @@ enum {
FW_ERR_FATAL = 0xFF FW_ERR_FATAL = 0xFF
}; };
/** enum iwl_dbg_suspend_resume_cmds - dbgc suspend resume operations
* dbgc suspend resume command operations
* @DBGC_RESUME_CMD: resume dbgc recording
* @DBGC_SUSPEND_CMD: stop dbgc recording
*/
enum iwl_dbg_suspend_resume_cmds {
DBGC_RESUME_CMD,
DBGC_SUSPEND_CMD,
};
/** /**
* struct iwl_error_resp - FW error indication * struct iwl_error_resp - FW error indication
* ( REPLY_ERROR = 0x2 ) * ( REPLY_ERROR = 0x2 )
@ -335,49 +358,39 @@ struct iwl_dbg_mem_access_rsp {
__le32 data[]; __le32 data[];
} __packed; /* DEBUG_(U|L)MAC_RD_WR_RSP_API_S_VER_1 */ } __packed; /* DEBUG_(U|L)MAC_RD_WR_RSP_API_S_VER_1 */
#define LDBG_CFG_COMMAND_SIZE 80 /**
#define BUFFER_ALLOCATION 0x27 * struct iwl_dbg_suspend_resume_cmd - dbgc suspend resume command
#define START_DEBUG_RECORDING 0x29 * @operation: suspend or resume operation, uses
#define STOP_DEBUG_RECORDING 0x2A * &enum iwl_dbg_suspend_resume_cmds
*/
struct iwl_dbg_suspend_resume_cmd {
__le32 operation;
} __packed;
/* maximum fragments to be allocated per target of allocationId */ #define BUF_ALLOC_MAX_NUM_FRAGS 16
#define IWL_BUFFER_LOCATION_MAX_FRAGS 2
/** /**
* struct iwl_fragment_data single fragment structure * struct iwl_buf_alloc_frag - a DBGC fragment
* @address: 64bit start address * @addr: base address of the fragment
* @size: size in bytes * @size: size of the fragment
*/ */
struct iwl_fragment_data { struct iwl_buf_alloc_frag {
__le64 address; __le64 addr;
__le32 size; __le32 size;
} __packed; /* FRAGMENT_STRUCTURE_API_S_VER_1 */ } __packed; /* FRAGMENT_STRUCTURE_API_S_VER_1 */
/** /**
* struct iwl_buffer_allocation_cmd - buffer allocation command structure * struct iwl_buf_alloc_cmd - buffer allocation command
* @allocation_id: id of the allocation * @alloc_id: &enum iwl_fw_ini_allocation_id
* @buffer_location: location of the buffer * @buf_location: &enum iwl_fw_ini_buffer_location
* @num_frags: number of fragments * @num_frags: number of fragments
* @fragments: memory fragments * @frags: fragments array
*/ */
struct iwl_buffer_allocation_cmd { struct iwl_buf_alloc_cmd {
__le32 allocation_id; __le32 alloc_id;
__le32 buffer_location; __le32 buf_location;
__le32 num_frags; __le32 num_frags;
struct iwl_fragment_data fragments[IWL_BUFFER_LOCATION_MAX_FRAGS]; struct iwl_buf_alloc_frag frags[BUF_ALLOC_MAX_NUM_FRAGS];
} __packed; /* BUFFER_ALLOCATION_CMD_API_S_VER_1 */ } __packed; /* BUFFER_ALLOCATION_CMD_API_S_VER_2 */
/**
* struct iwl_ldbg_config_cmd - LDBG config command
* @type: configuration type
* @pad: reserved space for type-dependent data
*/
struct iwl_ldbg_config_cmd {
__le32 type;
union {
u8 pad[LDBG_CFG_COMMAND_SIZE - sizeof(__le32)];
struct iwl_buffer_allocation_cmd buffer_allocation;
}; /* LDBG_CFG_BODY_API_U_VER_2 (partially) */
} __packed; /* LDBG_CFG_CMD_API_S_VER_2 */
#endif /* __iwl_fw_api_debug_h__ */ #endif /* __iwl_fw_api_debug_h__ */

View File

@ -82,7 +82,7 @@ enum iwl_location_subcmd_ids {
TOF_RANGE_ABORT_CMD = 0x2, TOF_RANGE_ABORT_CMD = 0x2,
/** /**
* @TOF_RANGE_REQ_EXT_CMD: TOF extended ranging config, * @TOF_RANGE_REQ_EXT_CMD: TOF extended ranging config,
* uses &struct iwl_tof_range_request_ext_cmd * uses &struct iwl_tof_range_req_ext_cmd
*/ */
TOF_RANGE_REQ_EXT_CMD = 0x3, TOF_RANGE_REQ_EXT_CMD = 0x3,
/** /**
@ -292,7 +292,7 @@ struct iwl_tof_responder_dyn_config_cmd {
} __packed; /* TOF_RESPONDER_DYN_CONFIG_CMD_API_S_VER_2 */ } __packed; /* TOF_RESPONDER_DYN_CONFIG_CMD_API_S_VER_2 */
/** /**
* struct iwl_tof_range_request_ext_cmd - extended range req for WLS * struct iwl_tof_range_req_ext_cmd - extended range req for WLS
* @tsf_timer_offset_msec: the recommended time offset (mSec) from the AP's TSF * @tsf_timer_offset_msec: the recommended time offset (mSec) from the AP's TSF
* @reserved: reserved * @reserved: reserved
* @min_delta_ftm: Minimal time between two consecutive measurements, * @min_delta_ftm: Minimal time between two consecutive measurements,

View File

@ -500,6 +500,9 @@ struct iwl_he_pkt_ext {
* enabled AGG, i.e. both BACK and non-BACK frames in a single AGG * enabled AGG, i.e. both BACK and non-BACK frames in a single AGG
* @STA_CTXT_HE_MU_EDCA_CW: indicates that there is an element of MU EDCA * @STA_CTXT_HE_MU_EDCA_CW: indicates that there is an element of MU EDCA
* parameter set, i.e. the backoff counters for trig-based ACs * parameter set, i.e. the backoff counters for trig-based ACs
* @STA_CTXT_HE_RU_2MHZ_BLOCK: indicates that 26-tone RU OFDMA transmission are
* not allowed (as there are OBSS that might classify such transmissions as
* radar pulses).
*/ */
enum iwl_he_sta_ctxt_flags { enum iwl_he_sta_ctxt_flags {
STA_CTXT_HE_REF_BSSID_VALID = BIT(4), STA_CTXT_HE_REF_BSSID_VALID = BIT(4),
@ -511,6 +514,7 @@ enum iwl_he_sta_ctxt_flags {
STA_CTXT_HE_CONST_TRIG_RND_ALLOC = BIT(10), STA_CTXT_HE_CONST_TRIG_RND_ALLOC = BIT(10),
STA_CTXT_HE_ACK_ENABLED = BIT(11), STA_CTXT_HE_ACK_ENABLED = BIT(11),
STA_CTXT_HE_MU_EDCA_CW = BIT(12), STA_CTXT_HE_MU_EDCA_CW = BIT(12),
STA_CTXT_HE_RU_2MHZ_BLOCK = BIT(14),
}; };
/** /**

View File

@ -8,6 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -30,6 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -89,6 +91,11 @@ enum iwl_phy_ops_subcmd_ids {
*/ */
GEO_TX_POWER_LIMIT = 0x05, GEO_TX_POWER_LIMIT = 0x05,
/**
* @PER_PLATFORM_ANT_GAIN_CMD: &struct iwl_ppag_table_cmd
*/
PER_PLATFORM_ANT_GAIN_CMD = 0x07,
/** /**
* @CT_KILL_NOTIFICATION: &struct ct_kill_notif * @CT_KILL_NOTIFICATION: &struct ct_kill_notif
*/ */

View File

@ -449,6 +449,18 @@ struct iwl_geo_tx_power_profiles_resp {
__le32 profile_idx; __le32 profile_idx;
} __packed; /* GEO_TX_POWER_LIMIT_RESP */ } __packed; /* GEO_TX_POWER_LIMIT_RESP */
/**
* struct iwl_ppag_table_cmd - struct for PER_PLATFORM_ANT_GAIN_CMD cmd.
* @enabled: 1 if PPAG is enabled, 0 otherwise
* @gain: table of antenna gain values per chain and sub-band
* @reserved: reserved
*/
struct iwl_ppag_table_cmd {
__le32 enabled;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS];
s8 reserved[2];
} __packed; /* PER_PLATFORM_ANT_GAIN_CMD */
/** /**
* struct iwl_beacon_filter_cmd * struct iwl_beacon_filter_cmd
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command) * REPLY_BEACON_FILTERING_CMD = 0xd2 (command)

View File

@ -7,7 +7,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2017 Intel Deutschland GmbH * Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -29,7 +29,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2017 Intel Deutschland GmbH * Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -166,8 +166,16 @@ enum iwl_tlc_mng_ht_rates {
IWL_TLC_MNG_HT_RATE_MAX = IWL_TLC_MNG_HT_RATE_MCS11, IWL_TLC_MNG_HT_RATE_MAX = IWL_TLC_MNG_HT_RATE_MCS11,
}; };
/* Maximum supported tx antennas number */ enum IWL_TLC_MNG_NSS {
#define MAX_NSS 2 IWL_TLC_NSS_1,
IWL_TLC_NSS_2,
IWL_TLC_NSS_MAX
};
enum IWL_TLC_HT_BW_RATES {
IWL_TLC_HT_BW_NONE_160,
IWL_TLC_HT_BW_160,
};
/** /**
* struct tlc_config_cmd - TLC configuration * struct tlc_config_cmd - TLC configuration
@ -195,7 +203,7 @@ struct iwl_tlc_config_cmd {
u8 amsdu; u8 amsdu;
__le16 flags; __le16 flags;
__le16 non_ht_rates; __le16 non_ht_rates;
__le16 ht_rates[MAX_NSS][2]; __le16 ht_rates[IWL_TLC_NSS_MAX][2];
__le16 max_mpdu_len; __le16 max_mpdu_len;
u8 sgi_ch_width_supp; u8 sgi_ch_width_supp;
u8 reserved2[1]; u8 reserved2[1];

View File

@ -746,6 +746,38 @@ struct iwl_frame_release {
__le16 nssn; __le16 nssn;
}; };
/**
* enum iwl_bar_frame_release_sta_tid - STA/TID information for BAR release
* @IWL_BAR_FRAME_RELEASE_TID_MASK: TID mask
* @IWL_BAR_FRAME_RELEASE_STA_MASK: STA mask
*/
enum iwl_bar_frame_release_sta_tid {
IWL_BAR_FRAME_RELEASE_TID_MASK = 0x0000000f,
IWL_BAR_FRAME_RELEASE_STA_MASK = 0x000001f0,
};
/**
* enum iwl_bar_frame_release_ba_info - BA information for BAR release
* @IWL_BAR_FRAME_RELEASE_NSSN_MASK: NSSN mask
* @IWL_BAR_FRAME_RELEASE_SN_MASK: SN mask (ignored by driver)
* @IWL_BAR_FRAME_RELEASE_BAID_MASK: BAID mask
*/
enum iwl_bar_frame_release_ba_info {
IWL_BAR_FRAME_RELEASE_NSSN_MASK = 0x00000fff,
IWL_BAR_FRAME_RELEASE_SN_MASK = 0x00fff000,
IWL_BAR_FRAME_RELEASE_BAID_MASK = 0x3f000000,
};
/**
* struct iwl_bar_frame_release - frame release from BAR info
* @sta_tid: STA & TID information, see &enum iwl_bar_frame_release_sta_tid.
* @ba_info: BA information, see &enum iwl_bar_frame_release_ba_info.
*/
struct iwl_bar_frame_release {
__le32 sta_tid;
__le32 ba_info;
} __packed; /* RX_BAR_TO_FRAME_RELEASE_API_S_VER_1 */
enum iwl_rss_hash_func_en { enum iwl_rss_hash_func_en {
IWL_RSS_HASH_TYPE_IPV4_TCP, IWL_RSS_HASH_TYPE_IPV4_TCP,
IWL_RSS_HASH_TYPE_IPV4_UDP, IWL_RSS_HASH_TYPE_IPV4_UDP,

View File

@ -93,6 +93,8 @@ struct iwl_ssid_ie {
#define IWL_SCAN_SHORT_BLACKLIST_LEN 16 #define IWL_SCAN_SHORT_BLACKLIST_LEN 16
#define IWL_SCAN_MAX_PROFILES 11 #define IWL_SCAN_MAX_PROFILES 11
#define SCAN_OFFLOAD_PROBE_REQ_SIZE 512 #define SCAN_OFFLOAD_PROBE_REQ_SIZE 512
#define SCAN_NUM_BAND_PROBE_DATA_V_1 2
#define SCAN_NUM_BAND_PROBE_DATA_V_2 3
/* Default watchdog (in MS) for scheduled scan iteration */ /* Default watchdog (in MS) for scheduled scan iteration */
#define IWL_SCHED_SCAN_WATCHDOG cpu_to_le16(15000) #define IWL_SCHED_SCAN_WATCHDOG cpu_to_le16(15000)
@ -251,9 +253,22 @@ struct iwl_scan_probe_segment {
* @common_data: last (and common) part of the probe * @common_data: last (and common) part of the probe
* @buf: raw data block * @buf: raw data block
*/ */
struct iwl_scan_probe_req_v1 {
struct iwl_scan_probe_segment mac_header;
struct iwl_scan_probe_segment band_data[SCAN_NUM_BAND_PROBE_DATA_V_1];
struct iwl_scan_probe_segment common_data;
u8 buf[SCAN_OFFLOAD_PROBE_REQ_SIZE];
} __packed;
/* iwl_scan_probe_req - PROBE_REQUEST_FRAME_API_S_VER_v2
* @mac_header: first (and common) part of the probe
* @band_data: band specific data
* @common_data: last (and common) part of the probe
* @buf: raw data block
*/
struct iwl_scan_probe_req { struct iwl_scan_probe_req {
struct iwl_scan_probe_segment mac_header; struct iwl_scan_probe_segment mac_header;
struct iwl_scan_probe_segment band_data[2]; struct iwl_scan_probe_segment band_data[SCAN_NUM_BAND_PROBE_DATA_V_2];
struct iwl_scan_probe_segment common_data; struct iwl_scan_probe_segment common_data;
u8 buf[SCAN_OFFLOAD_PROBE_REQ_SIZE]; u8 buf[SCAN_OFFLOAD_PROBE_REQ_SIZE];
} __packed; } __packed;
@ -608,15 +623,29 @@ enum iwl_umac_scan_general_flags2 {
* struct iwl_scan_channel_cfg_umac * struct iwl_scan_channel_cfg_umac
* @flags: bitmap - 0-19: directed scan to i'th ssid. * @flags: bitmap - 0-19: directed scan to i'th ssid.
* @channel_num: channel number 1-13 etc. * @channel_num: channel number 1-13 etc.
* @band: band of channel: 0 for 2GHz, 1 for 5GHz
* @iter_count: repetition count for the channel. * @iter_count: repetition count for the channel.
* @iter_interval: interval between two scan iterations on one channel. * @iter_interval: interval between two scan iterations on one channel.
*/ */
struct iwl_scan_channel_cfg_umac { struct iwl_scan_channel_cfg_umac {
__le32 flags; __le32 flags;
/* Both versions are of the same size, so use a union without adjusting
* the command size later
*/
union {
struct {
u8 channel_num; u8 channel_num;
u8 iter_count; u8 iter_count;
__le16 iter_interval; __le16 iter_interval;
} __packed; /* SCAN_CHANNEL_CFG_S_VER2 */ } v1; /* SCAN_CHANNEL_CFG_S_VER1 */
struct {
u8 channel_num;
u8 band;
u8 iter_count;
u8 iter_interval;
} v2; /* SCAN_CHANNEL_CFG_S_VER2 */
};
} __packed;
/** /**
* struct iwl_scan_umac_schedule * struct iwl_scan_umac_schedule
@ -630,6 +659,16 @@ struct iwl_scan_umac_schedule {
u8 reserved; u8 reserved;
} __packed; /* SCAN_SCHED_PARAM_API_S_VER_1 */ } __packed; /* SCAN_SCHED_PARAM_API_S_VER_1 */
struct iwl_scan_req_umac_tail_v1 {
/* SCAN_PERIODIC_PARAMS_API_S_VER_1 */
struct iwl_scan_umac_schedule schedule[IWL_MAX_SCHED_SCAN_PLANS];
__le16 delay;
__le16 reserved;
/* SCAN_PROBE_PARAMS_API_S_VER_1 */
struct iwl_scan_probe_req_v1 preq;
struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
} __packed;
/** /**
* struct iwl_scan_req_umac_tail - the rest of the UMAC scan request command * struct iwl_scan_req_umac_tail - the rest of the UMAC scan request command
* parameters following channels configuration array. * parameters following channels configuration array.
@ -639,12 +678,12 @@ struct iwl_scan_umac_schedule {
* @preq: probe request with IEs blocks * @preq: probe request with IEs blocks
* @direct_scan: list of SSIDs for directed active scan * @direct_scan: list of SSIDs for directed active scan
*/ */
struct iwl_scan_req_umac_tail { struct iwl_scan_req_umac_tail_v2 {
/* SCAN_PERIODIC_PARAMS_API_S_VER_1 */ /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */
struct iwl_scan_umac_schedule schedule[IWL_MAX_SCHED_SCAN_PLANS]; struct iwl_scan_umac_schedule schedule[IWL_MAX_SCHED_SCAN_PLANS];
__le16 delay; __le16 delay;
__le16 reserved; __le16 reserved;
/* SCAN_PROBE_PARAMS_API_S_VER_1 */ /* SCAN_PROBE_PARAMS_API_S_VER_2 */
struct iwl_scan_probe_req preq; struct iwl_scan_probe_req preq;
struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX]; struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
} __packed; } __packed;

File diff suppressed because it is too large Load Diff

View File

@ -202,7 +202,7 @@ _iwl_fw_dbg_trigger_on(struct iwl_fw_runtime *fwrt,
{ {
struct iwl_fw_dbg_trigger_tlv *trig; struct iwl_fw_dbg_trigger_tlv *trig;
if (fwrt->trans->dbg.ini_valid) if (iwl_trans_dbg_ini_valid(fwrt->trans))
return NULL; return NULL;
if (!iwl_fw_dbg_trigger_enabled(fwrt->fw, id)) if (!iwl_fw_dbg_trigger_enabled(fwrt->fw, id))
@ -229,8 +229,9 @@ iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_trigger *trig; struct iwl_fw_ini_trigger *trig;
u32 usec; u32 usec;
if (!fwrt->trans->dbg.ini_valid || id == IWL_FW_TRIGGER_ID_INVALID || if (!iwl_trans_dbg_ini_valid(fwrt->trans) ||
id >= IWL_FW_TRIGGER_ID_NUM || !fwrt->dump.active_trigs[id].active) id == IWL_FW_TRIGGER_ID_INVALID || id >= IWL_FW_TRIGGER_ID_NUM ||
!fwrt->dump.active_trigs[id].active)
return false; return false;
trig = fwrt->dump.active_trigs[id].trig; trig = fwrt->dump.active_trigs[id].trig;
@ -262,69 +263,9 @@ _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt,
_iwl_fw_dbg_trigger_simple_stop((fwrt), (wdev), \ _iwl_fw_dbg_trigger_simple_stop((fwrt), (wdev), \
iwl_fw_dbg_get_trigger((fwrt)->fw,\ iwl_fw_dbg_get_trigger((fwrt)->fw,\
(trig))) (trig)))
int iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
static inline void struct iwl_fw_dbg_params *params,
_iwl_fw_dbg_stop_recording(struct iwl_trans *trans, bool stop);
struct iwl_fw_dbg_params *params)
{
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
return;
}
if (params) {
params->in_sample = iwl_read_umac_prph(trans, DBGC_IN_SAMPLE);
params->out_ctrl = iwl_read_umac_prph(trans, DBGC_OUT_CTRL);
}
iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, 0);
/* wait for the DBGC to finish writing the internal buffer to DRAM to
* avoid halting the HW while writing
*/
usleep_range(700, 1000);
iwl_write_umac_prph(trans, DBGC_OUT_CTRL, 0);
#ifdef CONFIG_IWLWIFI_DEBUGFS
trans->dbg.rec_on = false;
#endif
}
static inline void
iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
struct iwl_fw_dbg_params *params)
{
/* if the FW crashed or not debug monitor cfg was given, there is
* no point in stopping
*/
if (test_bit(STATUS_FW_ERROR, &trans->status) ||
(!trans->dbg.dest_tlv &&
trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID))
return;
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
IWL_ERR(trans,
"WRT: unsupported device family %d for debug stop recording\n",
trans->cfg->device_family);
return;
}
_iwl_fw_dbg_stop_recording(trans, params);
}
static inline void
_iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
struct iwl_fw_dbg_params *params)
{
if (WARN_ON(!params))
return;
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
} else {
iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample);
iwl_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl);
}
}
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
static inline void iwl_fw_set_dbg_rec_on(struct iwl_fw_runtime *fwrt) static inline void iwl_fw_set_dbg_rec_on(struct iwl_fw_runtime *fwrt)
@ -336,30 +277,6 @@ static inline void iwl_fw_set_dbg_rec_on(struct iwl_fw_runtime *fwrt)
} }
#endif #endif
static inline void
iwl_fw_dbg_restart_recording(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_params *params)
{
/* if the FW crashed or not debug monitor cfg was given, there is
* no point in restarting
*/
if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status) ||
(!fwrt->trans->dbg.dest_tlv &&
fwrt->trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID))
return;
if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
IWL_ERR(fwrt,
"WRT: unsupported device family %d for debug restart recording\n",
fwrt->trans->cfg->device_family);
return;
}
_iwl_fw_dbg_restart_recording(fwrt->trans, params);
#ifdef CONFIG_IWLWIFI_DEBUGFS
iwl_fw_set_dbg_rec_on(fwrt);
#endif
}
static inline void iwl_fw_dump_conf_clear(struct iwl_fw_runtime *fwrt) static inline void iwl_fw_dump_conf_clear(struct iwl_fw_runtime *fwrt)
{ {
fwrt->dump.conf = FW_DBG_INVALID; fwrt->dump.conf = FW_DBG_INVALID;
@ -385,7 +302,7 @@ static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt)
static inline bool iwl_fw_dbg_is_paging_enabled(struct iwl_fw_runtime *fwrt) static inline bool iwl_fw_dbg_is_paging_enabled(struct iwl_fw_runtime *fwrt)
{ {
return iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PAGING) && return iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PAGING) &&
!fwrt->trans->cfg->gen2 && !fwrt->trans->trans_cfg->gen2 &&
fwrt->cur_fw_img < IWL_UCODE_TYPE_MAX && fwrt->cur_fw_img < IWL_UCODE_TYPE_MAX &&
fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size && fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size &&
fwrt->fw_paging_db[0].fw_paging_block; fwrt->fw_paging_db[0].fw_paging_block;
@ -397,24 +314,13 @@ static inline void iwl_fw_flush_dumps(struct iwl_fw_runtime *fwrt)
{ {
int i; int i;
del_timer(&fwrt->dump.periodic_trig); iwl_dbg_tlv_del_timers(fwrt->trans);
for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) { for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) {
flush_delayed_work(&fwrt->dump.wks[i].wk); flush_delayed_work(&fwrt->dump.wks[i].wk);
fwrt->dump.wks[i].ini_trig_id = IWL_FW_TRIGGER_ID_INVALID; fwrt->dump.wks[i].ini_trig_id = IWL_FW_TRIGGER_ID_INVALID;
} }
} }
static inline void iwl_fw_cancel_dumps(struct iwl_fw_runtime *fwrt)
{
int i;
del_timer(&fwrt->dump.periodic_trig);
for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) {
cancel_delayed_work_sync(&fwrt->dump.wks[i].wk);
fwrt->dump.wks[i].ini_trig_id = IWL_FW_TRIGGER_ID_INVALID;
}
}
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt) static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt)
{ {
@ -451,10 +357,7 @@ static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {}
#endif /* CONFIG_IWLWIFI_DEBUGFS */ #endif /* CONFIG_IWLWIFI_DEBUGFS */
void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, void iwl_fw_dbg_stop_sync(struct iwl_fw_runtime *fwrt);
enum iwl_fw_ini_apply_point apply_point);
void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt);
static inline void iwl_fw_lmac1_set_alive_err_table(struct iwl_trans *trans, static inline void iwl_fw_lmac1_set_alive_err_table(struct iwl_trans *trans,
u32 lmac_error_event_table) u32 lmac_error_event_table)
@ -478,7 +381,7 @@ static inline void iwl_fw_umac_set_alive_err_table(struct iwl_trans *trans,
static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt) static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt)
{ {
if (fwrt->trans->dbg.ini_valid && fwrt->trans->dbg.hw_error) { if (iwl_trans_dbg_ini_valid(fwrt->trans) && fwrt->trans->dbg.hw_error) {
_iwl_fw_dbg_ini_collect(fwrt, IWL_FW_TRIGGER_ID_FW_HW_ERROR); _iwl_fw_dbg_ini_collect(fwrt, IWL_FW_TRIGGER_ID_FW_HW_ERROR);
fwrt->trans->dbg.hw_error = false; fwrt->trans->dbg.hw_error = false;
} else { } else {
@ -486,8 +389,6 @@ static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt)
} }
} }
void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t);
void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt); void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt);
static inline void iwl_fwrt_update_fw_versions(struct iwl_fw_runtime *fwrt, static inline void iwl_fwrt_update_fw_versions(struct iwl_fw_runtime *fwrt,

View File

@ -287,6 +287,28 @@ struct iwl_fw_error_dump_mem {
/* Use bit 31 as dump info type to avoid colliding with region types */ /* Use bit 31 as dump info type to avoid colliding with region types */
#define IWL_INI_DUMP_INFO_TYPE BIT(31) #define IWL_INI_DUMP_INFO_TYPE BIT(31)
/**
* struct iwl_fw_ini_dump_entry
* @list: list of dump entries
* @size: size of the data
* @data: entry data
*/
struct iwl_fw_ini_dump_entry {
struct list_head list;
u32 size;
u8 data[];
} __packed;
/**
* struct iwl_fw_error_dump_file - header of dump file
* @barker: must be %IWL_FW_INI_ERROR_DUMP_BARKER
* @file_len: the length of all the file including the header
*/
struct iwl_fw_ini_dump_file_hdr {
__le32 barker;
__le32 file_len;
} __packed;
/** /**
* struct iwl_fw_ini_fifo_hdr - fifo range header * struct iwl_fw_ini_fifo_hdr - fifo range header
* @fifo_num: the fifo number. In case of umac rx fifo, set BIT(31) to * @fifo_num: the fifo number. In case of umac rx fifo, set BIT(31) to
@ -301,10 +323,10 @@ struct iwl_fw_ini_fifo_hdr {
/** /**
* struct iwl_fw_ini_error_dump_range - range of memory * struct iwl_fw_ini_error_dump_range - range of memory
* @range_data_size: the size of this range, in bytes * @range_data_size: the size of this range, in bytes
* @internal_base_addr - base address of internal memory range * @internal_base_addr: base address of internal memory range
* @dram_base_addr - base address of dram monitor range * @dram_base_addr: base address of dram monitor range
* @page_num - page number of memory range * @page_num: page number of memory range
* @fifo_hdr - fifo header of memory range * @fifo_hdr: fifo header of memory range
* @data: the actual memory * @data: the actual memory
*/ */
struct iwl_fw_ini_error_dump_range { struct iwl_fw_ini_error_dump_range {
@ -432,10 +454,10 @@ struct iwl_fw_error_dump_rb {
/** /**
* struct iwl_fw_ini_monitor_dump - ini monitor dump * struct iwl_fw_ini_monitor_dump - ini monitor dump
* @header - header of the region * @header: header of the region
* @write_ptr - write pointer position in the buffer * @write_ptr: write pointer position in the buffer
* @cycle_cnt - cycles count * @cycle_cnt: cycles count
* @ranges - the memory ranges of this this region * @ranges: the memory ranges of this this region
*/ */
struct iwl_fw_ini_monitor_dump { struct iwl_fw_ini_monitor_dump {
struct iwl_fw_ini_error_dump_header header; struct iwl_fw_ini_error_dump_header header;

View File

@ -157,8 +157,7 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_TLV_DEBUG_BASE + 2, IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_TLV_DEBUG_BASE + 2,
IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_TLV_DEBUG_BASE + 3, IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_TLV_DEBUG_BASE + 3,
IWL_UCODE_TLV_TYPE_TRIGGERS = IWL_UCODE_TLV_DEBUG_BASE + 4, IWL_UCODE_TLV_TYPE_TRIGGERS = IWL_UCODE_TLV_DEBUG_BASE + 4,
IWL_UCODE_TLV_TYPE_DEBUG_FLOW = IWL_UCODE_TLV_DEBUG_BASE + 5, IWL_UCODE_TLV_DEBUG_MAX = IWL_UCODE_TLV_TYPE_TRIGGERS,
IWL_UCODE_TLV_DEBUG_MAX = IWL_UCODE_TLV_TYPE_DEBUG_FLOW,
/* TLVs 0x1000-0x2000 are for internal driver usage */ /* TLVs 0x1000-0x2000 are for internal driver usage */
IWL_UCODE_TLV_FW_DBG_DUMP_LST = 0x1000, IWL_UCODE_TLV_FW_DBG_DUMP_LST = 0x1000,
@ -323,6 +322,7 @@ enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_FTM_RTT_ACCURACY = (__force iwl_ucode_tlv_api_t)54, IWL_UCODE_TLV_API_FTM_RTT_ACCURACY = (__force iwl_ucode_tlv_api_t)54,
IWL_UCODE_TLV_API_SAR_TABLE_VER = (__force iwl_ucode_tlv_api_t)55, IWL_UCODE_TLV_API_SAR_TABLE_VER = (__force iwl_ucode_tlv_api_t)55,
IWL_UCODE_TLV_API_ADWELL_HB_DEF_N_AP = (__force iwl_ucode_tlv_api_t)57, IWL_UCODE_TLV_API_ADWELL_HB_DEF_N_AP = (__force iwl_ucode_tlv_api_t)57,
IWL_UCODE_TLV_API_SCAN_EXT_CHAN_VER = (__force iwl_ucode_tlv_api_t)58,
NUM_IWL_UCODE_TLV_API NUM_IWL_UCODE_TLV_API
#ifdef __CHECKER__ #ifdef __CHECKER__
@ -441,9 +441,11 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA = (__force iwl_ucode_tlv_capa_t)44, IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA = (__force iwl_ucode_tlv_capa_t)44,
IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2 = (__force iwl_ucode_tlv_capa_t)45, IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2 = (__force iwl_ucode_tlv_capa_t)45,
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD = (__force iwl_ucode_tlv_capa_t)46, IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD = (__force iwl_ucode_tlv_capa_t)46,
IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48,
IWL_UCODE_TLV_CAPA_FTM_CALIBRATED = (__force iwl_ucode_tlv_capa_t)47, IWL_UCODE_TLV_CAPA_FTM_CALIBRATED = (__force iwl_ucode_tlv_capa_t)47,
IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48,
IWL_UCODE_TLV_CAPA_CS_MODIFY = (__force iwl_ucode_tlv_capa_t)49, IWL_UCODE_TLV_CAPA_CS_MODIFY = (__force iwl_ucode_tlv_capa_t)49,
IWL_UCODE_TLV_CAPA_SET_LTR_GEN2 = (__force iwl_ucode_tlv_capa_t)50,
IWL_UCODE_TLV_CAPA_SET_PPAG = (__force iwl_ucode_tlv_capa_t)52,
/* set 2 */ /* set 2 */
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
@ -465,6 +467,8 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT = (__force iwl_ucode_tlv_capa_t)88, IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT = (__force iwl_ucode_tlv_capa_t)88,
IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT = (__force iwl_ucode_tlv_capa_t)89, IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT = (__force iwl_ucode_tlv_capa_t)89,
IWL_UCODE_TLV_CAPA_CSI_REPORTING = (__force iwl_ucode_tlv_capa_t)90, IWL_UCODE_TLV_CAPA_CSI_REPORTING = (__force iwl_ucode_tlv_capa_t)90,
IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP = (__force iwl_ucode_tlv_capa_t)92,
IWL_UCODE_TLV_CAPA_DBG_BUF_ALLOC_CMD_SUPP = (__force iwl_ucode_tlv_capa_t)93,
/* set 3 */ /* set 3 */
IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96, IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96,
@ -521,6 +525,10 @@ enum iwl_fw_phy_cfg {
FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS, FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS,
FW_PHY_CFG_RX_CHAIN_POS = 20, FW_PHY_CFG_RX_CHAIN_POS = 20,
FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS, FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS,
FW_PHY_CFG_CHAIN_SAD_POS = 23,
FW_PHY_CFG_CHAIN_SAD_ENABLED = 0x1 << FW_PHY_CFG_CHAIN_SAD_POS,
FW_PHY_CFG_CHAIN_SAD_ANT_A = 0x2 << FW_PHY_CFG_CHAIN_SAD_POS,
FW_PHY_CFG_CHAIN_SAD_ANT_B = 0x4 << FW_PHY_CFG_CHAIN_SAD_POS,
FW_PHY_CFG_SHARED_CLK = BIT(31), FW_PHY_CFG_SHARED_CLK = BIT(31),
}; };
@ -965,4 +973,19 @@ struct iwl_fw_cmd_version {
u8 notif_ver; u8 notif_ver;
} __packed; } __packed;
static inline size_t _iwl_tlv_array_len(const struct iwl_ucode_tlv *tlv,
size_t fixed_size, size_t var_size)
{
size_t var_len = le32_to_cpu(tlv->length) - fixed_size;
if (WARN_ON(var_len % var_size))
return 0;
return var_len / var_size;
}
#define iwl_tlv_array_len(_tlv_ptr, _struct_ptr, _memb) \
_iwl_tlv_array_len((_tlv_ptr), sizeof(*(_struct_ptr)), \
sizeof(_struct_ptr->_memb[0]))
#endif /* __iwl_fw_file_h__ */ #endif /* __iwl_fw_file_h__ */

View File

@ -227,15 +227,6 @@ struct iwl_fw_dbg {
u32 dump_mask; u32 dump_mask;
}; };
/**
* @tlv: the buffer allocation tlv
* @is_alloc: indicates if the buffer was already allocated
*/
struct iwl_fw_ini_allocation_data {
struct iwl_fw_ini_allocation_tlv tlv;
u32 is_alloc;
} __packed;
/** /**
* struct iwl_fw_ini_active_triggers * struct iwl_fw_ini_active_triggers
* @active: is this trigger active * @active: is this trigger active

View File

@ -81,8 +81,6 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
INIT_DELAYED_WORK(&fwrt->dump.wks[i].wk, iwl_fw_error_dump_wk); INIT_DELAYED_WORK(&fwrt->dump.wks[i].wk, iwl_fw_error_dump_wk);
} }
iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir); iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir);
timer_setup(&fwrt->dump.periodic_trig,
iwl_fw_dbg_periodic_trig_handler, 0);
} }
IWL_EXPORT_SYMBOL(iwl_fw_runtime_init); IWL_EXPORT_SYMBOL(iwl_fw_runtime_init);

View File

@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -322,7 +322,7 @@ int iwl_init_paging(struct iwl_fw_runtime *fwrt, enum iwl_ucode_type type)
const struct fw_img *fw = &fwrt->fw->img[type]; const struct fw_img *fw = &fwrt->fw->img[type];
int ret; int ret;
if (fwrt->trans->cfg->gen2) if (fwrt->trans->trans_cfg->gen2)
return 0; return 0;
/* /*

View File

@ -64,7 +64,6 @@
#include "iwl-trans.h" #include "iwl-trans.h"
#include "img.h" #include "img.h"
#include "fw/api/debug.h" #include "fw/api/debug.h"
#include "fw/api/dbg-tlv.h"
#include "fw/api/paging.h" #include "fw/api/paging.h"
#include "iwl-eeprom-parse.h" #include "iwl-eeprom-parse.h"
@ -91,6 +90,20 @@ struct iwl_fwrt_shared_mem_cfg {
#define IWL_FW_RUNTIME_DUMP_WK_NUM 5 #define IWL_FW_RUNTIME_DUMP_WK_NUM 5
/**
* struct iwl_txf_iter_data - Tx fifo iterator data struct
* @fifo: fifo number
* @lmac: lmac number
* @fifo_size: fifo size
* @internal_txf: non zero if fifo is internal Tx fifo
*/
struct iwl_txf_iter_data {
int fifo;
int lmac;
u32 fifo_size;
u8 internal_txf;
};
/** /**
* struct iwl_fw_runtime - runtime data for firmware * struct iwl_fw_runtime - runtime data for firmware
* @fw: firmware image * @fw: firmware image
@ -144,8 +157,8 @@ struct iwl_fw_runtime {
struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM]; struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM];
u32 lmac_err_id[MAX_NUM_LMAC]; u32 lmac_err_id[MAX_NUM_LMAC];
u32 umac_err_id; u32 umac_err_id;
void *fifo_iter;
struct timer_list periodic_trig; struct iwl_txf_iter_data txf_iter_data;
u8 img_name[IWL_FW_INI_MAX_IMG_NAME_LEN]; u8 img_name[IWL_FW_INI_MAX_IMG_NAME_LEN];
u8 internal_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN]; u8 internal_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
@ -190,6 +203,10 @@ static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt)
kfree(active->trig); kfree(active->trig);
active->trig = NULL; active->trig = NULL;
} }
iwl_dbg_tlv_del_timers(fwrt->trans);
for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++)
cancel_delayed_work_sync(&fwrt->dump.wks[i].wk);
} }
void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt); void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt);

View File

@ -151,7 +151,7 @@ void iwl_get_shared_mem_conf(struct iwl_fw_runtime *fwrt)
} }
pkt = cmd.resp_pkt; pkt = cmd.resp_pkt;
if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000)
iwl_parse_shared_mem_22000(fwrt, pkt); iwl_parse_shared_mem_22000(fwrt, pkt);
else else
iwl_parse_shared_mem(fwrt, pkt); iwl_parse_shared_mem(fwrt, pkt);

View File

@ -161,7 +161,8 @@ static inline u8 num_of_ant(u8 mask)
!!((mask) & ANT_C); !!((mask) & ANT_C);
} }
/* /**
* struct iwl_base_params - params not likely to change within a device family
* @max_ll_items: max number of OTP blocks * @max_ll_items: max number of OTP blocks
* @shadow_ram_support: shadow support for OTP memory * @shadow_ram_support: shadow support for OTP memory
* @led_compensation: compensate on the led on/off time per HW according * @led_compensation: compensate on the led on/off time per HW according
@ -330,8 +331,37 @@ struct iwl_csr_params {
u32 mac_addr1_strap; u32 mac_addr1_strap;
}; };
/**
* struct iwl_cfg_trans - information needed to start the trans
*
* These values cannot be changed when multiple configs are used for a
* single PCI ID, because they are needed before the HW REV or RFID
* can be read.
*
* @base_params: pointer to basic parameters
* @csr: csr flags and addresses that are different across devices
* @device_family: the device family
* @umac_prph_offset: offset to add to UMAC periphery address
* @rf_id: need to read rf_id to determine the firmware image
* @use_tfh: use TFH
* @gen2: 22000 and on transport operation
* @mq_rx_supported: multi-queue rx support
*/
struct iwl_cfg_trans_params {
const struct iwl_base_params *base_params;
const struct iwl_csr_params *csr;
enum iwl_device_family device_family;
u32 umac_prph_offset;
u32 rf_id:1,
use_tfh:1,
gen2:1,
mq_rx_supported:1,
bisr_workaround:1;
};
/** /**
* struct iwl_cfg * struct iwl_cfg
* @trans: the trans-specific configuration part
* @name: Official name of the device * @name: Official name of the device
* @fw_name_pre: Firmware filename prefix. The api version and extension * @fw_name_pre: Firmware filename prefix. The api version and extension
* (.ucode) will be added to filename before loading from disk. The * (.ucode) will be added to filename before loading from disk. The
@ -346,10 +376,10 @@ struct iwl_csr_params {
* @nvm_ver: NVM version * @nvm_ver: NVM version
* @nvm_calib_ver: NVM calibration version * @nvm_calib_ver: NVM calibration version
* @lib: pointer to the lib ops * @lib: pointer to the lib ops
* @base_params: pointer to basic parameters
* @ht_params: point to ht parameters * @ht_params: point to ht parameters
* @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
* @rx_with_siso_diversity: 1x1 device with rx antenna diversity * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
* @tx_with_siso_diversity: 1x1 device with tx antenna diversity
* @internal_wimax_coex: internal wifi/wimax combo device * @internal_wimax_coex: internal wifi/wimax combo device
* @high_temp: Is this NIC is designated to be in high temperature. * @high_temp: Is this NIC is designated to be in high temperature.
* @host_interrupt_operation_mode: device needs host interrupt operation * @host_interrupt_operation_mode: device needs host interrupt operation
@ -358,7 +388,6 @@ struct iwl_csr_params {
* @mac_addr_from_csr: read HW address from CSR registers * @mac_addr_from_csr: read HW address from CSR registers
* @features: hw features, any combination of feature_whitelist * @features: hw features, any combination of feature_whitelist
* @pwr_tx_backoffs: translation table between power limits and backoffs * @pwr_tx_backoffs: translation table between power limits and backoffs
* @csr: csr flags and addresses that are different across devices
* @max_rx_agg_size: max RX aggregation size of the ADDBA request/response * @max_rx_agg_size: max RX aggregation size of the ADDBA request/response
* @max_tx_agg_size: max TX aggregation size of the ADDBA request/response * @max_tx_agg_size: max TX aggregation size of the ADDBA request/response
* @max_ht_ampdu_factor: the exponent of the max length of A-MPDU that the * @max_ht_ampdu_factor: the exponent of the max length of A-MPDU that the
@ -371,18 +400,14 @@ struct iwl_csr_params {
* @dccm2_len: length of the second DCCM * @dccm2_len: length of the second DCCM
* @smem_offset: offset from which the SMEM begins * @smem_offset: offset from which the SMEM begins
* @smem_len: the length of SMEM * @smem_len: the length of SMEM
* @mq_rx_supported: multi-queue rx support
* @vht_mu_mimo_supported: VHT MU-MIMO support * @vht_mu_mimo_supported: VHT MU-MIMO support
* @rf_id: need to read rf_id to determine the firmware image
* @integrated: discrete or integrated * @integrated: discrete or integrated
* @gen2: 22000 and on transport operation
* @cdb: CDB support * @cdb: CDB support
* @nvm_type: see &enum iwl_nvm_type * @nvm_type: see &enum iwl_nvm_type
* @d3_debug_data_base_addr: base address where D3 debug data is stored * @d3_debug_data_base_addr: base address where D3 debug data is stored
* @d3_debug_data_length: length of the D3 debug data * @d3_debug_data_length: length of the D3 debug data
* @bisr_workaround: BISR hardware workaround (for 22260 series devices) * @bisr_workaround: BISR hardware workaround (for 22260 series devices)
* @min_txq_size: minimum number of slots required in a TX queue * @min_txq_size: minimum number of slots required in a TX queue
* @umac_prph_offset: offset to add to UMAC periphery address
* @uhb_supported: ultra high band channels supported * @uhb_supported: ultra high band channels supported
* @min_256_ba_txq_size: minimum number of slots required in a TX queue which * @min_256_ba_txq_size: minimum number of slots required in a TX queue which
* supports 256 BA aggregation * supports 256 BA aggregation
@ -392,19 +417,16 @@ struct iwl_csr_params {
* and/or the uCode API version instead. * and/or the uCode API version instead.
*/ */
struct iwl_cfg { struct iwl_cfg {
struct iwl_cfg_trans_params trans;
/* params specific to an individual device within a device family */ /* params specific to an individual device within a device family */
const char *name; const char *name;
const char *fw_name_pre; const char *fw_name_pre;
/* params not likely to change within a device family */
const struct iwl_base_params *base_params;
/* params likely to change within a device family */ /* params likely to change within a device family */
const struct iwl_ht_params *ht_params; const struct iwl_ht_params *ht_params;
const struct iwl_eeprom_params *eeprom_params; const struct iwl_eeprom_params *eeprom_params;
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs; const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
const char *default_nvm_file_C_step; const char *default_nvm_file_C_step;
const struct iwl_tt_params *thermal_params; const struct iwl_tt_params *thermal_params;
const struct iwl_csr_params *csr;
enum iwl_device_family device_family;
enum iwl_led_mode led_mode; enum iwl_led_mode led_mode;
enum iwl_nvm_type nvm_type; enum iwl_nvm_type nvm_type;
u32 max_data_size; u32 max_data_size;
@ -420,6 +442,7 @@ struct iwl_cfg {
u16 nvm_ver; u16 nvm_ver;
u16 nvm_calib_ver; u16 nvm_calib_ver;
u32 rx_with_siso_diversity:1, u32 rx_with_siso_diversity:1,
tx_with_siso_diversity:1,
bt_shared_single_ant:1, bt_shared_single_ant:1,
internal_wimax_coex:1, internal_wimax_coex:1,
host_interrupt_operation_mode:1, host_interrupt_operation_mode:1,
@ -428,15 +451,10 @@ struct iwl_cfg {
lp_xtal_workaround:1, lp_xtal_workaround:1,
disable_dummy_notification:1, disable_dummy_notification:1,
apmg_not_supported:1, apmg_not_supported:1,
mq_rx_supported:1,
vht_mu_mimo_supported:1, vht_mu_mimo_supported:1,
rf_id:1,
integrated:1, integrated:1,
use_tfh:1,
gen2:1,
cdb:1, cdb:1,
dbgc_supported:1, dbgc_supported:1,
bisr_workaround:1,
uhb_supported:1; uhb_supported:1;
u8 valid_tx_ant; u8 valid_tx_ant;
u8 valid_rx_ant; u8 valid_rx_ant;
@ -453,7 +471,6 @@ struct iwl_cfg {
u32 d3_debug_data_base_addr; u32 d3_debug_data_base_addr;
u32 d3_debug_data_length; u32 d3_debug_data_length;
u32 min_txq_size; u32 min_txq_size;
u32 umac_prph_offset;
u32 fw_mon_smem_write_ptr_addr; u32 fw_mon_smem_write_ptr_addr;
u32 fw_mon_smem_write_ptr_msk; u32 fw_mon_smem_write_ptr_msk;
u32 fw_mon_smem_cycle_cnt_ptr_addr; u32 fw_mon_smem_cycle_cnt_ptr_addr;

View File

@ -60,149 +60,112 @@
*****************************************************************************/ *****************************************************************************/
#include <linux/firmware.h> #include <linux/firmware.h>
#include "iwl-drv.h"
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-dbg-tlv.h" #include "iwl-dbg-tlv.h"
#include "fw/dbg.h"
#include "fw/runtime.h"
void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv, /**
bool ext) * enum iwl_dbg_tlv_type - debug TLV types
{ * @IWL_DBG_TLV_TYPE_DEBUG_INFO: debug info TLV
struct iwl_apply_point_data *data; * @IWL_DBG_TLV_TYPE_BUF_ALLOC: buffer allocation TLV
struct iwl_fw_ini_header *header = (void *)&tlv->data[0]; * @IWL_DBG_TLV_TYPE_HCMD: host command TLV
u32 apply_point = le32_to_cpu(header->apply_point); * @IWL_DBG_TLV_TYPE_REGION: region TLV
* @IWL_DBG_TLV_TYPE_TRIGGER: trigger TLV
int copy_size = le32_to_cpu(tlv->length) + sizeof(*tlv); * @IWL_DBG_TLV_TYPE_NUM: number of debug TLVs
int offset_size = copy_size;
if (le32_to_cpu(header->tlv_version) != 1)
return;
if (WARN_ONCE(apply_point >= IWL_FW_INI_APPLY_NUM,
"Invalid apply point id %d\n", apply_point))
return;
if (ext)
data = &trans->dbg.apply_points_ext[apply_point];
else
data = &trans->dbg.apply_points[apply_point];
/* add room for is_alloc field in &iwl_fw_ini_allocation_data struct */
if (le32_to_cpu(tlv->type) == IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION) {
struct iwl_fw_ini_allocation_data *buf_alloc =
(void *)tlv->data;
offset_size += sizeof(buf_alloc->is_alloc);
}
/*
* Make sure we still have room to copy this TLV. Offset points to the
* location the last copy ended.
*/ */
if (WARN_ONCE(data->offset + offset_size > data->size, enum iwl_dbg_tlv_type {
"Not enough memory for apply point %d\n", IWL_DBG_TLV_TYPE_DEBUG_INFO =
apply_point)) IWL_UCODE_TLV_TYPE_DEBUG_INFO - IWL_UCODE_TLV_DEBUG_BASE,
return; IWL_DBG_TLV_TYPE_BUF_ALLOC,
IWL_DBG_TLV_TYPE_HCMD,
IWL_DBG_TLV_TYPE_REGION,
IWL_DBG_TLV_TYPE_TRIGGER,
IWL_DBG_TLV_TYPE_NUM,
};
memcpy(data->data + data->offset, (void *)tlv, copy_size); /**
data->offset += offset_size; * struct iwl_dbg_tlv_ver_data - debug TLV version struct
* @min_ver: min version supported
* @max_ver: max version supported
*/
struct iwl_dbg_tlv_ver_data {
int min_ver;
int max_ver;
};
static const struct iwl_dbg_tlv_ver_data
dbg_ver_table[IWL_DBG_TLV_TYPE_NUM] = {
[IWL_DBG_TLV_TYPE_DEBUG_INFO] = {.min_ver = 1, .max_ver = 1,},
[IWL_DBG_TLV_TYPE_BUF_ALLOC] = {.min_ver = 1, .max_ver = 1,},
[IWL_DBG_TLV_TYPE_HCMD] = {.min_ver = 1, .max_ver = 1,},
[IWL_DBG_TLV_TYPE_REGION] = {.min_ver = 1, .max_ver = 1,},
[IWL_DBG_TLV_TYPE_TRIGGER] = {.min_ver = 1, .max_ver = 1,},
};
static bool iwl_dbg_tlv_ver_support(struct iwl_ucode_tlv *tlv)
{
struct iwl_fw_ini_header *hdr = (void *)&tlv->data[0];
u32 type = le32_to_cpu(tlv->type);
u32 tlv_idx = type - IWL_UCODE_TLV_DEBUG_BASE;
u32 ver = le32_to_cpu(hdr->tlv_version);
if (ver < dbg_ver_table[tlv_idx].min_ver ||
ver > dbg_ver_table[tlv_idx].max_ver)
return false;
return true;
} }
void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data, void iwl_dbg_tlv_alloc(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
bool ext) bool ext)
{ {
struct iwl_ucode_tlv *tlv; struct iwl_fw_ini_header *hdr = (void *)&tlv->data[0];
u32 size[IWL_FW_INI_APPLY_NUM] = {0}; u32 type = le32_to_cpu(tlv->type);
int i; u32 pnt = le32_to_cpu(hdr->apply_point);
u32 tlv_idx = type - IWL_UCODE_TLV_DEBUG_BASE;
while (len >= sizeof(*tlv)) { enum iwl_ini_cfg_state *cfg_state = ext ?
u32 tlv_len, tlv_type, apply; &trans->dbg.external_ini_cfg : &trans->dbg.internal_ini_cfg;
struct iwl_fw_ini_header *hdr;
len -= sizeof(*tlv);
tlv = (void *)data;
tlv_len = le32_to_cpu(tlv->length);
tlv_type = le32_to_cpu(tlv->type);
if (len < tlv_len)
return;
len -= ALIGN(tlv_len, 4);
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
if (tlv_type < IWL_UCODE_TLV_DEBUG_BASE ||
tlv_type > IWL_UCODE_TLV_DEBUG_MAX)
continue;
hdr = (void *)&tlv->data[0];
apply = le32_to_cpu(hdr->apply_point);
if (le32_to_cpu(hdr->tlv_version) != 1)
continue;
IWL_DEBUG_FW(trans, "WRT: read TLV 0x%x, apply point %d\n", IWL_DEBUG_FW(trans, "WRT: read TLV 0x%x, apply point %d\n",
le32_to_cpu(tlv->type), apply); type, pnt);
if (WARN_ON(apply >= IWL_FW_INI_APPLY_NUM)) if (tlv_idx >= IWL_DBG_TLV_TYPE_NUM) {
continue; IWL_ERR(trans, "WRT: Unsupported TLV 0x%x\n", type);
goto out_err;
/* add room for is_alloc field in &iwl_fw_ini_allocation_data
* struct
*/
if (tlv_type == IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION) {
struct iwl_fw_ini_allocation_data *buf_alloc =
(void *)tlv->data;
size[apply] += sizeof(buf_alloc->is_alloc);
} }
size[apply] += sizeof(*tlv) + tlv_len; if (!iwl_dbg_tlv_ver_support(tlv)) {
IWL_ERR(trans, "WRT: Unsupported TLV 0x%x version %u\n", type,
le32_to_cpu(hdr->tlv_version));
goto out_err;
} }
for (i = 0; i < ARRAY_SIZE(size); i++) { if (*cfg_state == IWL_INI_CFG_STATE_NOT_LOADED)
void *mem; *cfg_state = IWL_INI_CFG_STATE_LOADED;
if (!size[i])
continue;
mem = kzalloc(size[i], GFP_KERNEL);
if (!mem) {
IWL_ERR(trans, "No memory for apply point %d\n", i);
return; return;
out_err:
*cfg_state = IWL_INI_CFG_STATE_CORRUPTED;
} }
if (ext) { void iwl_dbg_tlv_del_timers(struct iwl_trans *trans)
trans->dbg.apply_points_ext[i].data = mem;
trans->dbg.apply_points_ext[i].size = size[i];
} else {
trans->dbg.apply_points[i].data = mem;
trans->dbg.apply_points[i].size = size[i];
}
trans->dbg.ini_valid = true;
}
}
void iwl_fw_dbg_free(struct iwl_trans *trans)
{ {
int i; /* will be used later */
for (i = 0; i < ARRAY_SIZE(trans->dbg.apply_points); i++) {
kfree(trans->dbg.apply_points[i].data);
trans->dbg.apply_points[i].size = 0;
trans->dbg.apply_points[i].offset = 0;
kfree(trans->dbg.apply_points_ext[i].data);
trans->dbg.apply_points_ext[i].size = 0;
trans->dbg.apply_points_ext[i].offset = 0;
} }
IWL_EXPORT_SYMBOL(iwl_dbg_tlv_del_timers);
void iwl_dbg_tlv_free(struct iwl_trans *trans)
{
/* will be used again later */
} }
static int iwl_parse_fw_dbg_tlv(struct iwl_trans *trans, const u8 *data, static int iwl_dbg_tlv_parse_bin(struct iwl_trans *trans, const u8 *data,
size_t len) size_t len)
{ {
struct iwl_ucode_tlv *tlv; struct iwl_ucode_tlv *tlv;
enum iwl_ucode_tlv_type tlv_type;
u32 tlv_len; u32 tlv_len;
while (len >= sizeof(*tlv)) { while (len >= sizeof(*tlv)) {
@ -210,7 +173,6 @@ static int iwl_parse_fw_dbg_tlv(struct iwl_trans *trans, const u8 *data,
tlv = (void *)data; tlv = (void *)data;
tlv_len = le32_to_cpu(tlv->length); tlv_len = le32_to_cpu(tlv->length);
tlv_type = le32_to_cpu(tlv->type);
if (len < tlv_len) { if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n", IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
@ -220,39 +182,33 @@ static int iwl_parse_fw_dbg_tlv(struct iwl_trans *trans, const u8 *data,
len -= ALIGN(tlv_len, 4); len -= ALIGN(tlv_len, 4);
data += sizeof(*tlv) + ALIGN(tlv_len, 4); data += sizeof(*tlv) + ALIGN(tlv_len, 4);
switch (tlv_type) { iwl_dbg_tlv_alloc(trans, tlv, true);
case IWL_UCODE_TLV_TYPE_DEBUG_INFO:
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
case IWL_UCODE_TLV_TYPE_HCMD:
case IWL_UCODE_TLV_TYPE_REGIONS:
case IWL_UCODE_TLV_TYPE_TRIGGERS:
case IWL_UCODE_TLV_TYPE_DEBUG_FLOW:
iwl_fw_dbg_copy_tlv(trans, tlv, true);
break;
default:
WARN_ONCE(1, "Invalid TLV %x\n", tlv_type);
break;
}
} }
return 0; return 0;
} }
void iwl_load_fw_dbg_tlv(struct device *dev, struct iwl_trans *trans) void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans)
{ {
const struct firmware *fw; const struct firmware *fw;
int res; int res;
if (trans->dbg.external_ini_loaded || !iwlwifi_mod_params.enable_ini) if (!iwlwifi_mod_params.enable_ini)
return; return;
res = request_firmware(&fw, "iwl-dbg-tlv.ini", dev); res = request_firmware(&fw, "iwl-dbg-tlv.ini", dev);
if (res) if (res)
return; return;
iwl_alloc_dbg_tlv(trans, fw->size, fw->data, true); iwl_dbg_tlv_parse_bin(trans, fw->data, fw->size);
iwl_parse_fw_dbg_tlv(trans, fw->data, fw->size);
trans->dbg.external_ini_loaded = true;
release_firmware(fw); release_firmware(fw);
} }
void iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
enum iwl_fw_ini_time_point tp_id,
union iwl_dbg_tlv_tp_data *tp_data)
{
/* will be used later */
}
IWL_EXPORT_SYMBOL(iwl_dbg_tlv_time_point);

View File

@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * GPL LICENSE SUMMARY
* *
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -28,7 +28,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -66,22 +66,32 @@
/** /**
* struct iwl_apply_point_data * struct iwl_apply_point_data
* @data: start address of this apply point data * @list: list to go through the TLVs of the apply point
* @size total size of the data * @tlv: a debug TLV
* @offset: current offset of the copied data
*/ */
struct iwl_apply_point_data { struct iwl_apply_point_data {
void *data; struct list_head list;
int size; struct iwl_ucode_tlv tlv;
int offset; };
/**
* union iwl_dbg_tlv_tp_data - data that is given in a time point
* @fw_pkt: a packet received from the FW
*/
union iwl_dbg_tlv_tp_data {
struct iwl_rx_packet *fw_pkt;
}; };
struct iwl_trans; struct iwl_trans;
void iwl_load_fw_dbg_tlv(struct device *dev, struct iwl_trans *trans); struct iwl_fw_runtime;
void iwl_fw_dbg_free(struct iwl_trans *trans);
void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv, void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans);
bool ext); void iwl_dbg_tlv_free(struct iwl_trans *trans);
void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data, void iwl_dbg_tlv_alloc(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
bool ext); bool ext);
void iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
enum iwl_fw_ini_time_point tp_id,
union iwl_dbg_tlv_tp_data *tp_data);
void iwl_dbg_tlv_del_timers(struct iwl_trans *trans);
#endif /* __iwl_dbg_tlv_h__*/ #endif /* __iwl_dbg_tlv_h__*/

View File

@ -75,7 +75,6 @@ static inline size_t iwl_rx_trace_len(const struct iwl_trans *trans,
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <linux/device.h> #include <linux/device.h>
#include "iwl-trans.h"
#if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__) #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__)

View File

@ -215,7 +215,7 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
const struct iwl_cfg *cfg = drv->trans->cfg; const struct iwl_cfg *cfg = drv->trans->cfg;
char tag[8]; char tag[8];
if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_9000 && if (drv->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
(CSR_HW_REV_STEP(drv->trans->hw_rev) != SILICON_B_STEP && (CSR_HW_REV_STEP(drv->trans->hw_rev) != SILICON_B_STEP &&
CSR_HW_REV_STEP(drv->trans->hw_rev) != SILICON_C_STEP)) { CSR_HW_REV_STEP(drv->trans->hw_rev) != SILICON_C_STEP)) {
IWL_ERR(drv, IWL_ERR(drv,
@ -647,9 +647,6 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
len -= sizeof(*ucode); len -= sizeof(*ucode);
if (iwlwifi_mod_params.enable_ini)
iwl_alloc_dbg_tlv(drv->trans, len, data, false);
while (len >= sizeof(*tlv)) { while (len >= sizeof(*tlv)) {
len -= sizeof(*tlv); len -= sizeof(*tlv);
tlv = (void *)data; tlv = (void *)data;
@ -1123,7 +1120,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
if (tlv_len != sizeof(*dbg_ptrs)) if (tlv_len != sizeof(*dbg_ptrs))
goto invalid_tlv_len; goto invalid_tlv_len;
if (drv->trans->cfg->device_family < if (drv->trans->trans_cfg->device_family <
IWL_DEVICE_FAMILY_22000) IWL_DEVICE_FAMILY_22000)
break; break;
drv->trans->dbg.umac_error_event_table = drv->trans->dbg.umac_error_event_table =
@ -1139,7 +1136,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
if (tlv_len != sizeof(*dbg_ptrs)) if (tlv_len != sizeof(*dbg_ptrs))
goto invalid_tlv_len; goto invalid_tlv_len;
if (drv->trans->cfg->device_family < if (drv->trans->trans_cfg->device_family <
IWL_DEVICE_FAMILY_22000) IWL_DEVICE_FAMILY_22000)
break; break;
drv->trans->dbg.lmac_error_event_table[0] = drv->trans->dbg.lmac_error_event_table[0] =
@ -1154,9 +1151,8 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
case IWL_UCODE_TLV_TYPE_HCMD: case IWL_UCODE_TLV_TYPE_HCMD:
case IWL_UCODE_TLV_TYPE_REGIONS: case IWL_UCODE_TLV_TYPE_REGIONS:
case IWL_UCODE_TLV_TYPE_TRIGGERS: case IWL_UCODE_TLV_TYPE_TRIGGERS:
case IWL_UCODE_TLV_TYPE_DEBUG_FLOW:
if (iwlwifi_mod_params.enable_ini) if (iwlwifi_mod_params.enable_ini)
iwl_fw_dbg_copy_tlv(drv->trans, tlv, false); iwl_dbg_tlv_alloc(drv->trans, tlv, false);
break; break;
case IWL_UCODE_TLV_CMD_VERSIONS: case IWL_UCODE_TLV_CMD_VERSIONS:
if (tlv_len % sizeof(struct iwl_fw_cmd_version)) { if (tlv_len % sizeof(struct iwl_fw_cmd_version)) {
@ -1526,14 +1522,14 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
fw->init_evtlog_size = (pieces->init_evtlog_size - 16)/12; fw->init_evtlog_size = (pieces->init_evtlog_size - 16)/12;
else else
fw->init_evtlog_size = fw->init_evtlog_size =
drv->trans->cfg->base_params->max_event_log_size; drv->trans->trans_cfg->base_params->max_event_log_size;
fw->init_errlog_ptr = pieces->init_errlog_ptr; fw->init_errlog_ptr = pieces->init_errlog_ptr;
fw->inst_evtlog_ptr = pieces->inst_evtlog_ptr; fw->inst_evtlog_ptr = pieces->inst_evtlog_ptr;
if (pieces->inst_evtlog_size) if (pieces->inst_evtlog_size)
fw->inst_evtlog_size = (pieces->inst_evtlog_size - 16)/12; fw->inst_evtlog_size = (pieces->inst_evtlog_size - 16)/12;
else else
fw->inst_evtlog_size = fw->inst_evtlog_size =
drv->trans->cfg->base_params->max_event_log_size; drv->trans->trans_cfg->base_params->max_event_log_size;
fw->inst_errlog_ptr = pieces->inst_errlog_ptr; fw->inst_errlog_ptr = pieces->inst_errlog_ptr;
/* /*
@ -1640,7 +1636,7 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
init_completion(&drv->request_firmware_complete); init_completion(&drv->request_firmware_complete);
INIT_LIST_HEAD(&drv->list); INIT_LIST_HEAD(&drv->list);
iwl_load_fw_dbg_tlv(drv->trans->dev, drv->trans); iwl_dbg_tlv_load_bin(drv->trans->dev, drv->trans);
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
/* Create the device debugfs entries. */ /* Create the device debugfs entries. */
@ -1662,8 +1658,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
err_fw: err_fw:
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
debugfs_remove_recursive(drv->dbgfs_drv); debugfs_remove_recursive(drv->dbgfs_drv);
iwl_dbg_tlv_free(drv->trans);
#endif #endif
iwl_fw_dbg_free(drv->trans);
kfree(drv); kfree(drv);
err: err:
return ERR_PTR(ret); return ERR_PTR(ret);
@ -1693,7 +1689,7 @@ void iwl_drv_stop(struct iwl_drv *drv)
debugfs_remove_recursive(drv->dbgfs_drv); debugfs_remove_recursive(drv->dbgfs_drv);
#endif #endif
iwl_fw_dbg_free(drv->trans); iwl_dbg_tlv_free(drv->trans);
kfree(drv); kfree(drv);
} }
@ -1704,8 +1700,6 @@ struct iwl_mod_params iwlwifi_mod_params = {
.fw_restart = true, .fw_restart = true,
.bt_coex_active = true, .bt_coex_active = true,
.power_level = IWL_POWER_INDEX_1, .power_level = IWL_POWER_INDEX_1,
.d0i3_disable = true,
.d0i3_timeout = 1000,
.uapsd_disable = IWL_DISABLE_UAPSD_BSS | IWL_DISABLE_UAPSD_P2P_CLIENT, .uapsd_disable = IWL_DISABLE_UAPSD_BSS | IWL_DISABLE_UAPSD_P2P_CLIENT,
/* the rest are 0 by default */ /* the rest are 0 by default */
}; };
@ -1823,9 +1817,6 @@ MODULE_PARM_DESC(antenna_coupling,
module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, 0444); module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, 0444);
MODULE_PARM_DESC(nvm_file, "NVM file name"); MODULE_PARM_DESC(nvm_file, "NVM file name");
module_param_named(d0i3_disable, iwlwifi_mod_params.d0i3_disable, bool, 0444);
MODULE_PARM_DESC(d0i3_disable, "disable d0i3 functionality (default: Y)");
module_param_named(lar_disable, iwlwifi_mod_params.lar_disable, bool, 0444); module_param_named(lar_disable, iwlwifi_mod_params.lar_disable, bool, 0444);
MODULE_PARM_DESC(lar_disable, "disable LAR functionality (default: N)"); MODULE_PARM_DESC(lar_disable, "disable LAR functionality (default: N)");
@ -1873,9 +1864,6 @@ module_param_named(fw_monitor, iwlwifi_mod_params.fw_monitor, bool, 0444);
MODULE_PARM_DESC(fw_monitor, MODULE_PARM_DESC(fw_monitor,
"firmware monitor - to debug FW (default: false - needs lots of memory)"); "firmware monitor - to debug FW (default: false - needs lots of memory)");
module_param_named(d0i3_timeout, iwlwifi_mod_params.d0i3_timeout, uint, 0444);
MODULE_PARM_DESC(d0i3_timeout, "Timeout to D0i3 entry when idle (ms)");
module_param_named(disable_11ac, iwlwifi_mod_params.disable_11ac, bool, 0444); module_param_named(disable_11ac, iwlwifi_mod_params.disable_11ac, bool, 0444);
MODULE_PARM_DESC(disable_11ac, "Disable VHT capabilities (default: false)"); MODULE_PARM_DESC(disable_11ac, "Disable VHT capabilities (default: false)");

View File

@ -7,7 +7,7 @@
* *
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Mobile Communications GmbH * Copyright(c) 2015 Intel Mobile Communications GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -29,7 +29,7 @@
* *
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Mobile Communications GmbH * Copyright(c) 2015 Intel Mobile Communications GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -728,12 +728,13 @@ int iwl_init_sband_channels(struct iwl_nvm_data *data,
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, void iwl_init_ht_hw_capab(struct iwl_trans *trans,
struct iwl_nvm_data *data, struct iwl_nvm_data *data,
struct ieee80211_sta_ht_cap *ht_info, struct ieee80211_sta_ht_cap *ht_info,
enum nl80211_band band, enum nl80211_band band,
u8 tx_chains, u8 rx_chains) u8 tx_chains, u8 rx_chains)
{ {
const struct iwl_cfg *cfg = trans->cfg;
int max_bit_rate = 0; int max_bit_rate = 0;
tx_chains = hweight8(tx_chains); tx_chains = hweight8(tx_chains);
@ -765,7 +766,7 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
if (cfg->ht_params->ldpc) if (cfg->ht_params->ldpc)
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
if ((cfg->mq_rx_supported && if ((trans->trans_cfg->mq_rx_supported &&
iwlwifi_mod_params.amsdu_size == IWL_AMSDU_DEF) || iwlwifi_mod_params.amsdu_size == IWL_AMSDU_DEF) ||
iwlwifi_mod_params.amsdu_size >= IWL_AMSDU_8K) iwlwifi_mod_params.amsdu_size >= IWL_AMSDU_8K)
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
@ -805,10 +806,11 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
} }
} }
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, static void iwl_init_sbands(struct iwl_trans *trans, const struct iwl_cfg *cfg,
struct iwl_nvm_data *data, struct iwl_nvm_data *data,
const u8 *eeprom, size_t eeprom_size) const u8 *eeprom, size_t eeprom_size)
{ {
struct device *dev = trans->dev;
int n_channels = iwl_init_channel_map(dev, cfg, data, int n_channels = iwl_init_channel_map(dev, cfg, data,
eeprom, eeprom_size); eeprom, eeprom_size);
int n_used = 0; int n_used = 0;
@ -820,7 +822,7 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
sband->n_bitrates = N_RATES_24; sband->n_bitrates = N_RATES_24;
n_used += iwl_init_sband_channels(data, sband, n_channels, n_used += iwl_init_sband_channels(data, sband, n_channels,
NL80211_BAND_2GHZ); NL80211_BAND_2GHZ);
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_2GHZ, iwl_init_ht_hw_capab(trans, data, &sband->ht_cap, NL80211_BAND_2GHZ,
data->valid_tx_ant, data->valid_rx_ant); data->valid_tx_ant, data->valid_rx_ant);
sband = &data->bands[NL80211_BAND_5GHZ]; sband = &data->bands[NL80211_BAND_5GHZ];
@ -829,7 +831,7 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
sband->n_bitrates = N_RATES_52; sband->n_bitrates = N_RATES_52;
n_used += iwl_init_sband_channels(data, sband, n_channels, n_used += iwl_init_sband_channels(data, sband, n_channels,
NL80211_BAND_5GHZ); NL80211_BAND_5GHZ);
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_5GHZ, iwl_init_ht_hw_capab(trans, data, &sband->ht_cap, NL80211_BAND_5GHZ,
data->valid_tx_ant, data->valid_rx_ant); data->valid_tx_ant, data->valid_rx_ant);
if (n_channels != n_used) if (n_channels != n_used)
@ -840,10 +842,11 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
/* EEPROM data functions */ /* EEPROM data functions */
struct iwl_nvm_data * struct iwl_nvm_data *
iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg, iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
const u8 *eeprom, size_t eeprom_size) const u8 *eeprom, size_t eeprom_size)
{ {
struct iwl_nvm_data *data; struct iwl_nvm_data *data;
struct device *dev = trans->dev;
const void *tmp; const void *tmp;
u16 radio_cfg, sku; u16 radio_cfg, sku;
@ -918,7 +921,7 @@ iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg,
goto err_free; goto err_free;
} }
iwl_init_sbands(dev, cfg, data, eeprom, eeprom_size); iwl_init_sbands(trans, cfg, data, eeprom, eeprom_size);
return data; return data;
err_free: err_free:

View File

@ -116,14 +116,14 @@ struct iwl_nvm_data {
* later with iwl_free_nvm_data(). * later with iwl_free_nvm_data().
*/ */
struct iwl_nvm_data * struct iwl_nvm_data *
iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg, iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
const u8 *eeprom, size_t eeprom_size); const u8 *eeprom, size_t eeprom_size);
int iwl_init_sband_channels(struct iwl_nvm_data *data, int iwl_init_sband_channels(struct iwl_nvm_data *data,
struct ieee80211_supported_band *sband, struct ieee80211_supported_band *sband,
int n_channels, enum nl80211_band band); int n_channels, enum nl80211_band band);
void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, void iwl_init_ht_hw_capab(struct iwl_trans *trans,
struct iwl_nvm_data *data, struct iwl_nvm_data *data,
struct ieee80211_sta_ht_cap *ht_info, struct ieee80211_sta_ht_cap *ht_info,
enum nl80211_band band, enum nl80211_band band,

View File

@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY * GPL LICENSE SUMMARY
* *
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -27,7 +27,7 @@
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -193,7 +193,7 @@ static int iwl_init_otp_access(struct iwl_trans *trans)
{ {
int ret; int ret;
ret = iwl_finish_nic_init(trans); ret = iwl_finish_nic_init(trans, trans->trans_cfg);
if (ret) if (ret)
return ret; return ret;
@ -207,7 +207,7 @@ static int iwl_init_otp_access(struct iwl_trans *trans)
* CSR auto clock gate disable bit - * CSR auto clock gate disable bit -
* this is only applicable for HW with OTP shadow RAM * this is only applicable for HW with OTP shadow RAM
*/ */
if (trans->cfg->base_params->shadow_ram_support) if (trans->trans_cfg->base_params->shadow_ram_support)
iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
CSR_RESET_LINK_PWR_MGMT_DISABLED); CSR_RESET_LINK_PWR_MGMT_DISABLED);
@ -328,7 +328,7 @@ static int iwl_find_otp_image(struct iwl_trans *trans,
} }
/* more in the link list, continue */ /* more in the link list, continue */
usedblocks++; usedblocks++;
} while (usedblocks <= trans->cfg->base_params->max_ll_items); } while (usedblocks <= trans->trans_cfg->base_params->max_ll_items);
/* OTP has no valid blocks */ /* OTP has no valid blocks */
IWL_DEBUG_EEPROM(trans->dev, "OTP has no valid blocks\n"); IWL_DEBUG_EEPROM(trans->dev, "OTP has no valid blocks\n");
@ -361,7 +361,7 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
if (nvm_is_otp < 0) if (nvm_is_otp < 0)
return nvm_is_otp; return nvm_is_otp;
sz = trans->cfg->base_params->eeprom_size; sz = trans->trans_cfg->base_params->eeprom_size;
IWL_DEBUG_EEPROM(trans->dev, "NVM size = %d\n", sz); IWL_DEBUG_EEPROM(trans->dev, "NVM size = %d\n", sz);
e = kmalloc(sz, GFP_KERNEL); e = kmalloc(sz, GFP_KERNEL);
@ -396,7 +396,7 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
/* traversing the linked list if no shadow ram supported */ /* traversing the linked list if no shadow ram supported */
if (!trans->cfg->base_params->shadow_ram_support) { if (!trans->trans_cfg->base_params->shadow_ram_support) {
ret = iwl_find_otp_image(trans, &validblockaddr); ret = iwl_find_otp_image(trans, &validblockaddr);
if (ret) if (ret)
goto err_unlock; goto err_unlock;

View File

@ -7,7 +7,7 @@
* *
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -29,7 +29,7 @@
* *
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -127,7 +127,7 @@
static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans, static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
unsigned int chnl) unsigned int chnl)
{ {
if (trans->cfg->use_tfh) { if (trans->trans_cfg->use_tfh) {
WARN_ON_ONCE(chnl >= 64); WARN_ON_ONCE(chnl >= 64);
return TFH_TFDQ_CBB_TABLE + 8 * chnl; return TFH_TFDQ_CBB_TABLE + 8 * chnl;
} }

View File

@ -304,10 +304,10 @@ IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
void iwl_force_nmi(struct iwl_trans *trans) void iwl_force_nmi(struct iwl_trans *trans)
{ {
if (trans->cfg->device_family < IWL_DEVICE_FAMILY_9000) if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
iwl_write_prph(trans, DEVICE_SET_NMI_REG, iwl_write_prph(trans, DEVICE_SET_NMI_REG,
DEVICE_SET_NMI_VAL_DRV); DEVICE_SET_NMI_VAL_DRV);
else if (trans->cfg->device_family < IWL_DEVICE_FAMILY_AX210) else if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER, iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,
UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER_MSK); UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER_MSK);
else else
@ -458,7 +458,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf)
FH_TSSR_TX_ERROR_REG FH_TSSR_TX_ERROR_REG
}; };
if (trans->cfg->mq_rx_supported) if (trans->trans_cfg->mq_rx_supported)
return iwl_dump_rfh(trans, buf); return iwl_dump_rfh(trans, buf);
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
@ -492,11 +492,12 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf)
return 0; return 0;
} }
int iwl_finish_nic_init(struct iwl_trans *trans) int iwl_finish_nic_init(struct iwl_trans *trans,
const struct iwl_cfg_trans_params *cfg_trans)
{ {
int err; int err;
if (trans->cfg->bisr_workaround) { if (cfg_trans->bisr_workaround) {
/* ensure the TOP FSM isn't still in previous reset */ /* ensure the TOP FSM isn't still in previous reset */
mdelay(2); mdelay(2);
} }
@ -506,9 +507,9 @@ int iwl_finish_nic_init(struct iwl_trans *trans)
* D0U* --> D0A* (powered-up active) state. * D0U* --> D0A* (powered-up active) state.
*/ */
iwl_set_bit(trans, CSR_GP_CNTRL, iwl_set_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_init_done)); BIT(cfg_trans->csr->flag_init_done));
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) if (cfg_trans->device_family == IWL_DEVICE_FAMILY_8000)
udelay(2); udelay(2);
/* /*
@ -517,13 +518,13 @@ int iwl_finish_nic_init(struct iwl_trans *trans)
* and accesses to uCode SRAM. * and accesses to uCode SRAM.
*/ */
err = iwl_poll_bit(trans, CSR_GP_CNTRL, err = iwl_poll_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_mac_clock_ready), BIT(cfg_trans->csr->flag_mac_clock_ready),
BIT(trans->cfg->csr->flag_mac_clock_ready), BIT(cfg_trans->csr->flag_mac_clock_ready),
25000); 25000);
if (err < 0) if (err < 0)
IWL_DEBUG_INFO(trans, "Failed to wake NIC\n"); IWL_DEBUG_INFO(trans, "Failed to wake NIC\n");
if (trans->cfg->bisr_workaround) { if (cfg_trans->bisr_workaround) {
/* ensure BISR shift has finished */ /* ensure BISR shift has finished */
udelay(200); udelay(200);
} }

View File

@ -99,7 +99,8 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
void iwl_force_nmi(struct iwl_trans *trans); void iwl_force_nmi(struct iwl_trans *trans);
int iwl_finish_nic_init(struct iwl_trans *trans); int iwl_finish_nic_init(struct iwl_trans *trans,
const struct iwl_cfg_trans_params *cfg_trans);
/* Error handling */ /* Error handling */
int iwl_dump_fh(struct iwl_trans *trans, char **buf); int iwl_dump_fh(struct iwl_trans *trans, char **buf);
@ -111,35 +112,38 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf);
*/ */
static inline u32 iwl_umac_prph(struct iwl_trans *trans, u32 ofs) static inline u32 iwl_umac_prph(struct iwl_trans *trans, u32 ofs)
{ {
return ofs + trans->cfg->umac_prph_offset; return ofs + trans->cfg->trans.umac_prph_offset;
} }
static inline u32 iwl_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs) static inline u32 iwl_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs)
{ {
return iwl_read_prph_no_grab(trans, ofs + trans->cfg->umac_prph_offset); return iwl_read_prph_no_grab(trans, ofs +
trans->cfg->trans.umac_prph_offset);
} }
static inline u32 iwl_read_umac_prph(struct iwl_trans *trans, u32 ofs) static inline u32 iwl_read_umac_prph(struct iwl_trans *trans, u32 ofs)
{ {
return iwl_read_prph(trans, ofs + trans->cfg->umac_prph_offset); return iwl_read_prph(trans, ofs + trans->cfg->trans.umac_prph_offset);
} }
static inline void iwl_write_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs, static inline void iwl_write_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs,
u32 val) u32 val)
{ {
iwl_write_prph_no_grab(trans, ofs + trans->cfg->umac_prph_offset, val); iwl_write_prph_no_grab(trans, ofs + trans->cfg->trans.umac_prph_offset,
val);
} }
static inline void iwl_write_umac_prph(struct iwl_trans *trans, u32 ofs, static inline void iwl_write_umac_prph(struct iwl_trans *trans, u32 ofs,
u32 val) u32 val)
{ {
iwl_write_prph(trans, ofs + trans->cfg->umac_prph_offset, val); iwl_write_prph(trans, ofs + trans->cfg->trans.umac_prph_offset, val);
} }
static inline int iwl_poll_umac_prph_bit(struct iwl_trans *trans, u32 addr, static inline int iwl_poll_umac_prph_bit(struct iwl_trans *trans, u32 addr,
u32 bits, u32 mask, int timeout) u32 bits, u32 mask, int timeout)
{ {
return iwl_poll_prph_bit(trans, addr + trans->cfg->umac_prph_offset, return iwl_poll_prph_bit(trans, addr +
trans->cfg->trans.umac_prph_offset,
bits, mask, timeout); bits, mask, timeout);
} }

View File

@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY * GPL LICENSE SUMMARY
* *
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -27,7 +27,7 @@
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -115,9 +115,6 @@ enum iwl_uapsd_disable {
* @nvm_file: specifies a external NVM file * @nvm_file: specifies a external NVM file
* @uapsd_disable: disable U-APSD, see &enum iwl_uapsd_disable, default = * @uapsd_disable: disable U-APSD, see &enum iwl_uapsd_disable, default =
* IWL_DISABLE_UAPSD_BSS | IWL_DISABLE_UAPSD_P2P_CLIENT * IWL_DISABLE_UAPSD_BSS | IWL_DISABLE_UAPSD_P2P_CLIENT
* @d0i3_disable: disable d0i3, default = 1,
* @d0i3_timeout: time to wait after no refs are taken before
* entering D0i3 (in msecs)
* @lar_disable: disable LAR (regulatory), default = 0 * @lar_disable: disable LAR (regulatory), default = 0
* @fw_monitor: allow to use firmware monitor * @fw_monitor: allow to use firmware monitor
* @disable_11ac: disable VHT capabilities, default = false. * @disable_11ac: disable VHT capabilities, default = false.
@ -139,8 +136,6 @@ struct iwl_mod_params {
int antenna_coupling; int antenna_coupling;
char *nvm_file; char *nvm_file;
u32 uapsd_disable; u32 uapsd_disable;
bool d0i3_disable;
unsigned int d0i3_timeout;
bool lar_disable; bool lar_disable;
bool fw_monitor; bool fw_monitor;
bool disable_11ac; bool disable_11ac;

View File

@ -393,11 +393,12 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
return n_channels; return n_channels;
} }
static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
struct iwl_nvm_data *data, struct iwl_nvm_data *data,
struct ieee80211_sta_vht_cap *vht_cap, struct ieee80211_sta_vht_cap *vht_cap,
u8 tx_chains, u8 rx_chains) u8 tx_chains, u8 rx_chains)
{ {
const struct iwl_cfg *cfg = trans->cfg;
int num_rx_ants = num_of_ant(rx_chains); int num_rx_ants = num_of_ant(rx_chains);
int num_tx_ants = num_of_ant(tx_chains); int num_tx_ants = num_of_ant(tx_chains);
unsigned int max_ampdu_exponent = (cfg->max_vht_ampdu_exponent ?: unsigned int max_ampdu_exponent = (cfg->max_vht_ampdu_exponent ?:
@ -434,14 +435,14 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
switch (iwlwifi_mod_params.amsdu_size) { switch (iwlwifi_mod_params.amsdu_size) {
case IWL_AMSDU_DEF: case IWL_AMSDU_DEF:
if (cfg->mq_rx_supported) if (trans->trans_cfg->mq_rx_supported)
vht_cap->cap |= vht_cap->cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
else else
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895; vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
break; break;
case IWL_AMSDU_2K: case IWL_AMSDU_2K:
if (cfg->mq_rx_supported) if (trans->trans_cfg->mq_rx_supported)
vht_cap->cap |= vht_cap->cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
else else
@ -669,11 +670,13 @@ static void iwl_init_he_hw_capab(struct ieee80211_supported_band *sband,
} }
} }
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, static void iwl_init_sbands(struct iwl_trans *trans,
struct iwl_nvm_data *data, struct iwl_nvm_data *data,
const void *nvm_ch_flags, u8 tx_chains, const void *nvm_ch_flags, u8 tx_chains,
u8 rx_chains, u32 sbands_flags, bool v4) u8 rx_chains, u32 sbands_flags, bool v4)
{ {
struct device *dev = trans->dev;
const struct iwl_cfg *cfg = trans->cfg;
int n_channels; int n_channels;
int n_used = 0; int n_used = 0;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
@ -686,7 +689,7 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
sband->n_bitrates = N_RATES_24; sband->n_bitrates = N_RATES_24;
n_used += iwl_init_sband_channels(data, sband, n_channels, n_used += iwl_init_sband_channels(data, sband, n_channels,
NL80211_BAND_2GHZ); NL80211_BAND_2GHZ);
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_2GHZ, iwl_init_ht_hw_capab(trans, data, &sband->ht_cap, NL80211_BAND_2GHZ,
tx_chains, rx_chains); tx_chains, rx_chains);
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax) if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
@ -698,10 +701,10 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
sband->n_bitrates = N_RATES_52; sband->n_bitrates = N_RATES_52;
n_used += iwl_init_sband_channels(data, sband, n_channels, n_used += iwl_init_sband_channels(data, sband, n_channels,
NL80211_BAND_5GHZ); NL80211_BAND_5GHZ);
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_5GHZ, iwl_init_ht_hw_capab(trans, data, &sband->ht_cap, NL80211_BAND_5GHZ,
tx_chains, rx_chains); tx_chains, rx_chains);
if (data->sku_cap_11ac_enable && !iwlwifi_mod_params.disable_11ac) if (data->sku_cap_11ac_enable && !iwlwifi_mod_params.disable_11ac)
iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap, iwl_init_vht_hw_capab(trans, data, &sband->vht_cap,
tx_chains, rx_chains); tx_chains, rx_chains);
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax) if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
@ -793,10 +796,10 @@ static void iwl_set_hw_address_from_csr(struct iwl_trans *trans,
{ {
__le32 mac_addr0 = __le32 mac_addr0 =
cpu_to_le32(iwl_read32(trans, cpu_to_le32(iwl_read32(trans,
trans->cfg->csr->mac_addr0_strap)); trans->trans_cfg->csr->mac_addr0_strap));
__le32 mac_addr1 = __le32 mac_addr1 =
cpu_to_le32(iwl_read32(trans, cpu_to_le32(iwl_read32(trans,
trans->cfg->csr->mac_addr1_strap)); trans->trans_cfg->csr->mac_addr1_strap));
iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr); iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
/* /*
@ -807,9 +810,9 @@ static void iwl_set_hw_address_from_csr(struct iwl_trans *trans,
return; return;
mac_addr0 = cpu_to_le32(iwl_read32(trans, mac_addr0 = cpu_to_le32(iwl_read32(trans,
trans->cfg->csr->mac_addr0_otp)); trans->trans_cfg->csr->mac_addr0_otp));
mac_addr1 = cpu_to_le32(iwl_read32(trans, mac_addr1 = cpu_to_le32(iwl_read32(trans,
trans->cfg->csr->mac_addr1_otp)); trans->trans_cfg->csr->mac_addr1_otp));
iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr); iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
} }
@ -896,7 +899,7 @@ static int iwl_set_hw_address(struct iwl_trans *trans,
} }
static bool static bool
iwl_nvm_no_wide_in_5ghz(struct device *dev, const struct iwl_cfg *cfg, iwl_nvm_no_wide_in_5ghz(struct iwl_trans *trans, const struct iwl_cfg *cfg,
const __be16 *nvm_hw) const __be16 *nvm_hw)
{ {
/* /*
@ -908,7 +911,7 @@ iwl_nvm_no_wide_in_5ghz(struct device *dev, const struct iwl_cfg *cfg,
* in 5GHz otherwise the FW will throw a sysassert when we try * in 5GHz otherwise the FW will throw a sysassert when we try
* to use them. * to use them.
*/ */
if (cfg->device_family == IWL_DEVICE_FAMILY_7000) { if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
/* /*
* Unlike the other sections in the NVM, the hw * Unlike the other sections in the NVM, the hw
* section uses big-endian. * section uses big-endian.
@ -917,7 +920,7 @@ iwl_nvm_no_wide_in_5ghz(struct device *dev, const struct iwl_cfg *cfg,
u8 sku = (subsystem_id & 0x1e) >> 1; u8 sku = (subsystem_id & 0x1e) >> 1;
if (sku == 5 || sku == 9) { if (sku == 5 || sku == 9) {
IWL_DEBUG_EEPROM(dev, IWL_DEBUG_EEPROM(trans->dev,
"disabling wide channels in 5GHz (0x%0x %d)\n", "disabling wide channels in 5GHz (0x%0x %d)\n",
subsystem_id, sku); subsystem_id, sku);
return true; return true;
@ -934,7 +937,6 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
const __le16 *mac_override, const __le16 *phy_sku, const __le16 *mac_override, const __le16 *phy_sku,
u8 tx_chains, u8 rx_chains, bool lar_fw_supported) u8 tx_chains, u8 rx_chains, bool lar_fw_supported)
{ {
struct device *dev = trans->dev;
struct iwl_nvm_data *data; struct iwl_nvm_data *data;
bool lar_enabled; bool lar_enabled;
u32 sku, radio_cfg; u32 sku, radio_cfg;
@ -942,7 +944,11 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
u16 lar_config; u16 lar_config;
const __le16 *ch_section; const __le16 *ch_section;
if (cfg->nvm_type != IWL_NVM_EXT) if (cfg->uhb_supported)
data = kzalloc(struct_size(data, channels,
IWL_NVM_NUM_CHANNELS_UHB),
GFP_KERNEL);
else if (cfg->nvm_type != IWL_NVM_EXT)
data = kzalloc(struct_size(data, channels, data = kzalloc(struct_size(data, channels,
IWL_NVM_NUM_CHANNELS), IWL_NVM_NUM_CHANNELS),
GFP_KERNEL); GFP_KERNEL);
@ -1012,10 +1018,10 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if (lar_fw_supported && lar_enabled) if (lar_fw_supported && lar_enabled)
sbands_flags |= IWL_NVM_SBANDS_FLAGS_LAR; sbands_flags |= IWL_NVM_SBANDS_FLAGS_LAR;
if (iwl_nvm_no_wide_in_5ghz(dev, cfg, nvm_hw)) if (iwl_nvm_no_wide_in_5ghz(trans, cfg, nvm_hw))
sbands_flags |= IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ; sbands_flags |= IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ;
iwl_init_sbands(dev, cfg, data, ch_section, tx_chains, rx_chains, iwl_init_sbands(trans, data, ch_section, tx_chains, rx_chains,
sbands_flags, false); sbands_flags, false);
data->calib_version = 255; data->calib_version = 255;
@ -1066,11 +1072,6 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
return flags; return flags;
} }
struct regdb_ptrs {
struct ieee80211_wmm_rule *rule;
u32 token;
};
struct ieee80211_regdomain * struct ieee80211_regdomain *
iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, __le32 *channels, u16 fw_mcc, int num_of_ch, __le32 *channels, u16 fw_mcc,
@ -1082,7 +1083,6 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
const u16 *nvm_chan; const u16 *nvm_chan;
struct ieee80211_regdomain *regd, *copy_rd; struct ieee80211_regdomain *regd, *copy_rd;
struct ieee80211_reg_rule *rule; struct ieee80211_reg_rule *rule;
struct regdb_ptrs *regdb_ptrs;
enum nl80211_band band; enum nl80211_band band;
int center_freq, prev_center_freq = 0; int center_freq, prev_center_freq = 0;
int valid_rules = 0; int valid_rules = 0;
@ -1114,12 +1114,6 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
if (!regd) if (!regd)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
regdb_ptrs = kcalloc(num_of_ch, sizeof(*regdb_ptrs), GFP_KERNEL);
if (!regdb_ptrs) {
copy_rd = ERR_PTR(-ENOMEM);
goto out;
}
/* set alpha2 from FW. */ /* set alpha2 from FW. */
regd->alpha2[0] = fw_mcc >> 8; regd->alpha2[0] = fw_mcc >> 8;
regd->alpha2[1] = fw_mcc & 0xff; regd->alpha2[1] = fw_mcc & 0xff;
@ -1191,8 +1185,6 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
if (!copy_rd) if (!copy_rd)
copy_rd = ERR_PTR(-ENOMEM); copy_rd = ERR_PTR(-ENOMEM);
out:
kfree(regdb_ptrs);
kfree(regd); kfree(regd);
return copy_rd; return copy_rd;
} }
@ -1311,7 +1303,7 @@ int iwl_read_external_nvm(struct iwl_trans *trans,
le32_to_cpu(dword_buff[3])); le32_to_cpu(dword_buff[3]));
/* nvm file validation, dword_buff[2] holds the file version */ /* nvm file validation, dword_buff[2] holds the file version */
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 && if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
CSR_HW_REV_STEP(trans->hw_rev) == SILICON_C_STEP && CSR_HW_REV_STEP(trans->hw_rev) == SILICON_C_STEP &&
le32_to_cpu(dword_buff[2]) < 0xE4A) { le32_to_cpu(dword_buff[2]) < 0xE4A) {
ret = -EFAULT; ret = -EFAULT;
@ -1495,7 +1487,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
channel_profile = v4 ? (void *)rsp->regulatory.channel_profile : channel_profile = v4 ? (void *)rsp->regulatory.channel_profile :
(void *)rsp_v3->regulatory.channel_profile; (void *)rsp_v3->regulatory.channel_profile;
iwl_init_sbands(trans->dev, trans->cfg, nvm, iwl_init_sbands(trans, nvm,
channel_profile, channel_profile,
nvm->valid_tx_ant & fw->valid_tx_ant, nvm->valid_tx_ant & fw->valid_tx_ant,
nvm->valid_rx_ant & fw->valid_rx_ant, nvm->valid_rx_ant & fw->valid_rx_ant,

View File

@ -8,7 +8,7 @@
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH * Copyright(c) 2015 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -31,7 +31,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH * Copyright(c) 2015 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -140,9 +140,6 @@ struct iwl_cfg;
* @nic_config: configure NIC, called before firmware is started. * @nic_config: configure NIC, called before firmware is started.
* May sleep * May sleep
* @wimax_active: invoked when WiMax becomes active. May sleep * @wimax_active: invoked when WiMax becomes active. May sleep
* @enter_d0i3: configure the fw to enter d0i3. return 1 to indicate d0i3
* entrance is aborted (e.g. due to held reference). May sleep.
* @exit_d0i3: configure the fw to exit d0i3. May sleep.
*/ */
struct iwl_op_mode_ops { struct iwl_op_mode_ops {
struct iwl_op_mode *(*start)(struct iwl_trans *trans, struct iwl_op_mode *(*start)(struct iwl_trans *trans,
@ -164,8 +161,6 @@ struct iwl_op_mode_ops {
void (*cmd_queue_full)(struct iwl_op_mode *op_mode); void (*cmd_queue_full)(struct iwl_op_mode *op_mode);
void (*nic_config)(struct iwl_op_mode *op_mode); void (*nic_config)(struct iwl_op_mode *op_mode);
void (*wimax_active)(struct iwl_op_mode *op_mode); void (*wimax_active)(struct iwl_op_mode *op_mode);
int (*enter_d0i3)(struct iwl_op_mode *op_mode);
int (*exit_d0i3)(struct iwl_op_mode *op_mode);
}; };
int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops); int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops);
@ -258,22 +253,4 @@ static inline void iwl_op_mode_wimax_active(struct iwl_op_mode *op_mode)
op_mode->ops->wimax_active(op_mode); op_mode->ops->wimax_active(op_mode);
} }
static inline int iwl_op_mode_enter_d0i3(struct iwl_op_mode *op_mode)
{
might_sleep();
if (!op_mode->ops->enter_d0i3)
return 0;
return op_mode->ops->enter_d0i3(op_mode);
}
static inline int iwl_op_mode_exit_d0i3(struct iwl_op_mode *op_mode)
{
might_sleep();
if (!op_mode->ops->exit_d0i3)
return 0;
return op_mode->ops->exit_d0i3(op_mode);
}
#endif /* __iwl_op_mode_h__ */ #endif /* __iwl_op_mode_h__ */

View File

@ -451,6 +451,8 @@ enum {
#define UREG_DOORBELL_TO_ISR6 0xA05C04 #define UREG_DOORBELL_TO_ISR6 0xA05C04
#define UREG_DOORBELL_TO_ISR6_NMI_BIT BIT(0) #define UREG_DOORBELL_TO_ISR6_NMI_BIT BIT(0)
#define UREG_DOORBELL_TO_ISR6_SUSPEND BIT(18)
#define UREG_DOORBELL_TO_ISR6_RESUME BIT(19)
#define FSEQ_ERROR_CODE 0xA340C8 #define FSEQ_ERROR_CODE 0xA340C8
#define FSEQ_TOP_INIT_VERSION 0xA34038 #define FSEQ_TOP_INIT_VERSION 0xA34038
@ -460,4 +462,7 @@ enum {
#define FSEQ_ALIVE_TOKEN 0xA340F0 #define FSEQ_ALIVE_TOKEN 0xA340F0
#define FSEQ_CNVI_ID 0xA3408C #define FSEQ_CNVI_ID 0xA3408C
#define FSEQ_CNVR_ID 0xA34090 #define FSEQ_CNVR_ID 0xA34090
#define IWL_D3_SLEEP_STATUS_SUSPEND 0xD3
#define IWL_D3_SLEEP_STATUS_RESUME 0xD0
#endif /* __iwl_prph_h__ */ #endif /* __iwl_prph_h__ */

View File

@ -66,7 +66,6 @@
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
struct device *dev, struct device *dev,
const struct iwl_cfg *cfg,
const struct iwl_trans_ops *ops) const struct iwl_trans_ops *ops)
{ {
struct iwl_trans *trans; struct iwl_trans *trans;
@ -84,7 +83,6 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
#endif #endif
trans->dev = dev; trans->dev = dev;
trans->cfg = cfg;
trans->ops = ops; trans->ops = ops;
trans->num_rx_queues = 1; trans->num_rx_queues = 1;
@ -202,17 +200,3 @@ int iwl_cmd_groups_verify_sorted(const struct iwl_trans_config *trans)
return 0; return 0;
} }
IWL_EXPORT_SYMBOL(iwl_cmd_groups_verify_sorted); 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);

View File

@ -159,13 +159,6 @@ static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt)
* @CMD_ASYNC: Return right away and don't wait for the response * @CMD_ASYNC: Return right away and don't wait for the response
* @CMD_WANT_SKB: Not valid with CMD_ASYNC. The caller needs the buffer of * @CMD_WANT_SKB: Not valid with CMD_ASYNC. The caller needs the buffer of
* the response. The caller needs to call iwl_free_resp when done. * the response. The caller needs to call iwl_free_resp when done.
* @CMD_HIGH_PRIO: The command is high priority - it goes to the front of the
* command queue, but after other high priority commands. Valid only
* with CMD_ASYNC.
* @CMD_SEND_IN_IDLE: The command should be sent even when the trans is idle.
* @CMD_MAKE_TRANS_IDLE: The command response should mark the trans as idle.
* @CMD_WAKE_UP_TRANS: The command response should wake up the trans
* (i.e. mark it as non-idle).
* @CMD_WANT_ASYNC_CALLBACK: the op_mode's async callback function must be * @CMD_WANT_ASYNC_CALLBACK: the op_mode's async callback function must be
* called after this command completes. Valid only with CMD_ASYNC. * called after this command completes. Valid only with CMD_ASYNC.
*/ */
@ -173,11 +166,7 @@ enum CMD_MODE {
CMD_ASYNC = BIT(0), CMD_ASYNC = BIT(0),
CMD_WANT_SKB = BIT(1), CMD_WANT_SKB = BIT(1),
CMD_SEND_IN_RFKILL = BIT(2), CMD_SEND_IN_RFKILL = BIT(2),
CMD_HIGH_PRIO = BIT(3), CMD_WANT_ASYNC_CALLBACK = BIT(3),
CMD_SEND_IN_IDLE = BIT(4),
CMD_MAKE_TRANS_IDLE = BIT(5),
CMD_WAKE_UP_TRANS = BIT(6),
CMD_WANT_ASYNC_CALLBACK = BIT(7),
}; };
#define DEF_CMD_PAYLOAD_SIZE 320 #define DEF_CMD_PAYLOAD_SIZE 320
@ -463,9 +452,8 @@ struct iwl_trans_rxq_dma_data {
* *
* All the handlers MUST be implemented * All the handlers MUST be implemented
* *
* @start_hw: starts the HW. If low_power is true, the NIC needs to be taken * @start_hw: starts the HW. From that point on, the HW can send interrupts.
* out of a low power state. From that point on, the HW can send * May sleep.
* interrupts. May sleep.
* @op_mode_leave: Turn off the HW RF kill indication if on * @op_mode_leave: Turn off the HW RF kill indication if on
* May sleep * May sleep
* @start_fw: allocates and inits all the resources for the transport * @start_fw: allocates and inits all the resources for the transport
@ -475,9 +463,8 @@ struct iwl_trans_rxq_dma_data {
* the SCD base address in SRAM, then provide it here, or 0 otherwise. * the SCD base address in SRAM, then provide it here, or 0 otherwise.
* May sleep * May sleep
* @stop_device: stops the whole device (embedded CPU put to reset) and stops * @stop_device: stops the whole device (embedded CPU put to reset) and stops
* the HW. If low_power is true, the NIC will be put in low power state. * the HW. From that point on, the HW will be stopped but will still issue
* From that point on, the HW will be stopped but will still issue an * an interrupt if the HW RF kill switch is triggered.
* interrupt if the HW RF kill switch is triggered.
* This callback must do the right thing and not crash even if %start_hw() * This callback must do the right thing and not crash even if %start_hw()
* was called but not &start_fw(). May sleep. * was called but not &start_fw(). May sleep.
* @d3_suspend: put the device into the correct mode for WoWLAN during * @d3_suspend: put the device into the correct mode for WoWLAN during
@ -535,11 +522,6 @@ struct iwl_trans_rxq_dma_data {
* @release_nic_access: let the NIC go to sleep. The "flags" parameter * @release_nic_access: let the NIC go to sleep. The "flags" parameter
* must be the same one that was sent before to the grab_nic_access. * must be the same one that was sent before to the grab_nic_access.
* @set_bits_mask - set SRAM register according to value and mask. * @set_bits_mask - set SRAM register according to value and mask.
* @ref: grab a reference to the transport/FW layers, disallowing
* certain low power states
* @unref: release a reference previously taken with @ref. Note that
* initially the reference count is 1, making an initial @unref
* necessary to allow low power states.
* @dump_data: return a vmalloc'ed buffer with debug data, maybe containing last * @dump_data: return a vmalloc'ed buffer with debug data, maybe containing last
* TX'ed commands and similar. The buffer will be vfree'd by the caller. * TX'ed commands and similar. The buffer will be vfree'd by the caller.
* Note that the transport must fill in the proper file headers. * Note that the transport must fill in the proper file headers.
@ -548,14 +530,14 @@ struct iwl_trans_rxq_dma_data {
*/ */
struct iwl_trans_ops { struct iwl_trans_ops {
int (*start_hw)(struct iwl_trans *iwl_trans, bool low_power); int (*start_hw)(struct iwl_trans *iwl_trans);
void (*op_mode_leave)(struct iwl_trans *iwl_trans); void (*op_mode_leave)(struct iwl_trans *iwl_trans);
int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw, int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw,
bool run_in_rfkill); bool run_in_rfkill);
void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr);
void (*stop_device)(struct iwl_trans *trans, bool low_power); void (*stop_device)(struct iwl_trans *trans);
void (*d3_suspend)(struct iwl_trans *trans, bool test, bool reset); int (*d3_suspend)(struct iwl_trans *trans, bool test, bool reset);
int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status, int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status,
bool test, bool reset); bool test, bool reset);
@ -566,6 +548,8 @@ struct iwl_trans_ops {
void (*reclaim)(struct iwl_trans *trans, int queue, int ssn, void (*reclaim)(struct iwl_trans *trans, int queue, int ssn,
struct sk_buff_head *skbs); struct sk_buff_head *skbs);
void (*set_q_ptrs)(struct iwl_trans *trans, int queue, int ptr);
bool (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn, bool (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn,
const struct iwl_trans_txq_scd_cfg *cfg, const struct iwl_trans_txq_scd_cfg *cfg,
unsigned int queue_wdg_timeout); unsigned int queue_wdg_timeout);
@ -607,8 +591,6 @@ struct iwl_trans_ops {
unsigned long *flags); unsigned long *flags);
void (*set_bits_mask)(struct iwl_trans *trans, u32 reg, u32 mask, void (*set_bits_mask)(struct iwl_trans *trans, u32 reg, u32 mask,
u32 value); u32 value);
void (*ref)(struct iwl_trans *trans);
void (*unref)(struct iwl_trans *trans);
int (*suspend)(struct iwl_trans *trans); int (*suspend)(struct iwl_trans *trans);
void (*resume)(struct iwl_trans *trans); void (*resume)(struct iwl_trans *trans);
@ -632,9 +614,6 @@ enum iwl_trans_state {
/** /**
* DOC: Platform power management * DOC: Platform power management
* *
* There are two types of platform power management: system-wide
* (WoWLAN) and runtime.
*
* In system-wide power management the entire platform goes into a low * In system-wide power management the entire platform goes into a low
* power state (e.g. idle or suspend to RAM) at the same time and the * power state (e.g. idle or suspend to RAM) at the same time and the
* device is configured as a wakeup source for the entire platform. * device is configured as a wakeup source for the entire platform.
@ -643,54 +622,46 @@ enum iwl_trans_state {
* put the platform in low power mode). The device's behavior in this * put the platform in low power mode). The device's behavior in this
* mode is dictated by the wake-on-WLAN configuration. * mode is dictated by the wake-on-WLAN configuration.
* *
* In runtime power management, only the devices which are themselves
* idle enter a low power state. This is done at runtime, which means
* that the entire system is still running normally. This mode is
* usually triggered automatically by the device driver and requires
* the ability to enter and exit the low power modes in a very short
* time, so there is not much impact in usability.
*
* The terms used for the device's behavior are as follows: * The terms used for the device's behavior are as follows:
* *
* - D0: the device is fully powered and the host is awake; * - D0: the device is fully powered and the host is awake;
* - D3: the device is in low power mode and only reacts to * - D3: the device is in low power mode and only reacts to
* specific events (e.g. magic-packet received or scan * specific events (e.g. magic-packet received or scan
* results found); * results found);
* - D0I3: the device is in low power mode and reacts to any
* activity (e.g. RX);
* *
* These terms reflect the power modes in the firmware and are not to * These terms reflect the power modes in the firmware and are not to
* be confused with the physical device power state. The NIC can be * be confused with the physical device power state.
* in D0I3 mode even if, for instance, the PCI device is in D3 state.
*/ */
/** /**
* enum iwl_plat_pm_mode - platform power management mode * enum iwl_plat_pm_mode - platform power management mode
* *
* This enumeration describes the device's platform power management * This enumeration describes the device's platform power management
* behavior when in idle mode (i.e. runtime power management) or when * behavior when in system-wide suspend (i.e WoWLAN).
* in system-wide suspend (i.e WoWLAN).
* *
* @IWL_PLAT_PM_MODE_DISABLED: power management is disabled for this * @IWL_PLAT_PM_MODE_DISABLED: power management is disabled for this
* device. At runtime, this means that nothing happens and the * device. In system-wide suspend mode, it means that the all
* device always remains in active. In system-wide suspend mode, * connections will be closed automatically by mac80211 before
* it means that the all connections will be closed automatically * the platform is suspended.
* by mac80211 before the platform is suspended.
* @IWL_PLAT_PM_MODE_D3: the device goes into D3 mode (i.e. WoWLAN). * @IWL_PLAT_PM_MODE_D3: the device goes into D3 mode (i.e. WoWLAN).
* For runtime power management, this mode is not officially
* supported.
* @IWL_PLAT_PM_MODE_D0I3: the device goes into D0I3 mode.
*/ */
enum iwl_plat_pm_mode { enum iwl_plat_pm_mode {
IWL_PLAT_PM_MODE_DISABLED, IWL_PLAT_PM_MODE_DISABLED,
IWL_PLAT_PM_MODE_D3, IWL_PLAT_PM_MODE_D3,
IWL_PLAT_PM_MODE_D0I3,
}; };
/* Max time to wait for trans to become idle/non-idle on d0i3 /**
* enter/exit (in msecs). * enum iwl_ini_cfg_state
* @IWL_INI_CFG_STATE_NOT_LOADED: no debug cfg was given
* @IWL_INI_CFG_STATE_LOADED: debug cfg was found and loaded
* @IWL_INI_CFG_STATE_CORRUPTED: debug cfg was found and some of the TLVs
* are corrupted. The rest of the debug TLVs will still be used
*/ */
#define IWL_TRANS_IDLE_TIMEOUT 2000 enum iwl_ini_cfg_state {
IWL_INI_CFG_STATE_NOT_LOADED,
IWL_INI_CFG_STATE_LOADED,
IWL_INI_CFG_STATE_CORRUPTED,
};
/* Max time to wait for nmi interrupt */ /* Max time to wait for nmi interrupt */
#define IWL_TRANS_NMI_TIMEOUT (HZ / 4) #define IWL_TRANS_NMI_TIMEOUT (HZ / 4)
@ -733,8 +704,8 @@ struct iwl_self_init_dram {
* @umac_error_event_table: addr of umac error table * @umac_error_event_table: addr of umac error table
* @error_event_table_tlv_status: bitmap that indicates what error table * @error_event_table_tlv_status: bitmap that indicates what error table
* pointers was recevied via TLV. uses enum &iwl_error_event_table_status * pointers was recevied via TLV. uses enum &iwl_error_event_table_status
* @external_ini_loaded: indicates if an external ini cfg was given * @internal_ini_cfg: internal debug cfg state. Uses &enum iwl_ini_cfg_state
* @ini_valid: indicates if debug ini mode is on * @external_ini_cfg: external debug cfg state. Uses &enum iwl_ini_cfg_state
* @num_blocks: number of blocks in fw_mon * @num_blocks: number of blocks in fw_mon
* @fw_mon: address of the buffers for firmware monitor * @fw_mon: address of the buffers for firmware monitor
* @hw_error: equals true if hw error interrupt was received from the FW * @hw_error: equals true if hw error interrupt was received from the FW
@ -752,14 +723,11 @@ struct iwl_trans_debug {
u32 umac_error_event_table; u32 umac_error_event_table;
unsigned int error_event_table_tlv_status; unsigned int error_event_table_tlv_status;
bool external_ini_loaded; enum iwl_ini_cfg_state internal_ini_cfg;
bool ini_valid; enum iwl_ini_cfg_state external_ini_cfg;
struct iwl_apply_point_data apply_points[IWL_FW_INI_APPLY_NUM];
struct iwl_apply_point_data apply_points_ext[IWL_FW_INI_APPLY_NUM];
int num_blocks; int num_blocks;
struct iwl_dram_data fw_mon[IWL_FW_INI_APPLY_NUM]; struct iwl_dram_data fw_mon[IWL_FW_INI_ALLOCATION_NUM];
bool hw_error; bool hw_error;
enum iwl_fw_ini_buffer_location ini_dest; enum iwl_fw_ini_buffer_location ini_dest;
@ -770,6 +738,7 @@ struct iwl_trans_debug {
* *
* @ops - pointer to iwl_trans_ops * @ops - pointer to iwl_trans_ops
* @op_mode - pointer to the op_mode * @op_mode - pointer to the op_mode
* @trans_cfg: the trans-specific configuration part
* @cfg - pointer to the configuration * @cfg - pointer to the configuration
* @drv - pointer to iwl_drv * @drv - pointer to iwl_drv
* @status: a bit-mask of transport status flags * @status: a bit-mask of transport status flags
@ -797,13 +766,11 @@ struct iwl_trans_debug {
* @system_pm_mode: the system-wide power management mode in use. * @system_pm_mode: the system-wide power management mode in use.
* This mode is set dynamically, depending on the WoWLAN values * This mode is set dynamically, depending on the WoWLAN values
* configured from the userspace at runtime. * configured from the userspace at runtime.
* @runtime_pm_mode: the runtime power management mode in use. This
* mode is set during the initialization phase and is not
* supposed to change during runtime.
*/ */
struct iwl_trans { struct iwl_trans {
const struct iwl_trans_ops *ops; const struct iwl_trans_ops *ops;
struct iwl_op_mode *op_mode; struct iwl_op_mode *op_mode;
const struct iwl_cfg_trans_params *trans_cfg;
const struct iwl_cfg *cfg; const struct iwl_cfg *cfg;
struct iwl_drv *drv; struct iwl_drv *drv;
enum iwl_trans_state state; enum iwl_trans_state state;
@ -844,8 +811,6 @@ struct iwl_trans {
struct iwl_self_init_dram init_dram; struct iwl_self_init_dram init_dram;
enum iwl_plat_pm_mode system_pm_mode; enum iwl_plat_pm_mode system_pm_mode;
enum iwl_plat_pm_mode runtime_pm_mode;
bool suspending;
/* pointer to trans specific struct */ /* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */ /*Ensure that this pointer will always be aligned to sizeof pointer */
@ -864,16 +829,11 @@ static inline void iwl_trans_configure(struct iwl_trans *trans,
WARN_ON(iwl_cmd_groups_verify_sorted(trans_cfg)); WARN_ON(iwl_cmd_groups_verify_sorted(trans_cfg));
} }
static inline int _iwl_trans_start_hw(struct iwl_trans *trans, bool low_power) static inline int iwl_trans_start_hw(struct iwl_trans *trans)
{ {
might_sleep(); might_sleep();
return trans->ops->start_hw(trans, low_power); return trans->ops->start_hw(trans);
}
static inline int iwl_trans_start_hw(struct iwl_trans *trans)
{
return trans->ops->start_hw(trans, true);
} }
static inline void iwl_trans_op_mode_leave(struct iwl_trans *trans) static inline void iwl_trans_op_mode_leave(struct iwl_trans *trans)
@ -909,27 +869,23 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans,
return trans->ops->start_fw(trans, fw, run_in_rfkill); return trans->ops->start_fw(trans, fw, run_in_rfkill);
} }
static inline void _iwl_trans_stop_device(struct iwl_trans *trans, static inline void iwl_trans_stop_device(struct iwl_trans *trans)
bool low_power)
{ {
might_sleep(); might_sleep();
trans->ops->stop_device(trans, low_power); trans->ops->stop_device(trans);
trans->state = IWL_TRANS_NO_FW; trans->state = IWL_TRANS_NO_FW;
} }
static inline void iwl_trans_stop_device(struct iwl_trans *trans) static inline int iwl_trans_d3_suspend(struct iwl_trans *trans, bool test,
{
_iwl_trans_stop_device(trans, true);
}
static inline void iwl_trans_d3_suspend(struct iwl_trans *trans, bool test,
bool reset) bool reset)
{ {
might_sleep(); might_sleep();
if (trans->ops->d3_suspend) if (!trans->ops->d3_suspend)
trans->ops->d3_suspend(trans, test, reset); return 0;
return trans->ops->d3_suspend(trans, test, reset);
} }
static inline int iwl_trans_d3_resume(struct iwl_trans *trans, static inline int iwl_trans_d3_resume(struct iwl_trans *trans,
@ -1004,6 +960,17 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue,
trans->ops->reclaim(trans, queue, ssn, skbs); trans->ops->reclaim(trans, queue, ssn, skbs);
} }
static inline void iwl_trans_set_q_ptrs(struct iwl_trans *trans, int queue,
int ptr)
{
if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return;
}
trans->ops->set_q_ptrs(trans, queue, ptr);
}
static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue, static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue,
bool configure_scd) bool configure_scd)
{ {
@ -1261,16 +1228,19 @@ static inline void iwl_trans_sync_nmi(struct iwl_trans *trans)
trans->ops->sync_nmi(trans); trans->ops->sync_nmi(trans);
} }
static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans)
{
return trans->dbg.internal_ini_cfg != IWL_INI_CFG_STATE_NOT_LOADED ||
trans->dbg.external_ini_cfg != IWL_INI_CFG_STATE_NOT_LOADED;
}
/***************************************************** /*****************************************************
* transport helper functions * transport helper functions
*****************************************************/ *****************************************************/
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
struct device *dev, struct device *dev,
const struct iwl_cfg *cfg,
const struct iwl_trans_ops *ops); const struct iwl_trans_ops *ops);
void iwl_trans_free(struct iwl_trans *trans); 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 * driver (transport) register/unregister functions

View File

@ -153,5 +153,6 @@
#define IWL_MVM_FTM_INITIATOR_DYNACK true #define IWL_MVM_FTM_INITIATOR_DYNACK true
#define IWL_MVM_D3_DEBUG false #define IWL_MVM_D3_DEBUG false
#define IWL_MVM_USE_TWT false #define IWL_MVM_USE_TWT false
#define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 10
#endif /* __MVM_CONSTANTS_H */ #endif /* __MVM_CONSTANTS_H */

View File

@ -735,32 +735,8 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
return 0; return 0;
} }
static void static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
iwl_mvm_iter_d0i3_ap_keys(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
void (*iter)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key,
void *data),
void *data)
{
struct ieee80211_sta *ap_sta;
rcu_read_lock();
ap_sta = rcu_dereference(mvm->fw_id_to_mac_id[mvm->d0i3_ap_sta_id]);
if (IS_ERR_OR_NULL(ap_sta))
goto out;
ieee80211_iter_keys_rcu(mvm->hw, vif, iter, data);
out:
rcu_read_unlock();
}
int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool d0i3,
u32 cmd_flags) u32 cmd_flags)
{ {
struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
@ -768,7 +744,7 @@ int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
bool unified = fw_has_capa(&mvm->fw->ucode_capa, bool unified = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
struct wowlan_key_data key_data = { struct wowlan_key_data key_data = {
.configure_keys = !d0i3 && !unified, .configure_keys = !unified,
.use_rsc_tsc = false, .use_rsc_tsc = false,
.tkip = &tkip_cmd, .tkip = &tkip_cmd,
.use_tkip = false, .use_tkip = false,
@ -784,10 +760,7 @@ int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
* if we have to configure keys, call ieee80211_iter_keys(), * if we have to configure keys, call ieee80211_iter_keys(),
* as we need non-atomic context in order to take the * as we need non-atomic context in order to take the
* required locks. * required locks.
* for the d0i3 we can't use ieee80211_iter_keys(), as
* taking (almost) any mutex might result in deadlock.
*/ */
if (!d0i3) {
/* /*
* Note that currently we don't propagate cmd_flags * Note that currently we don't propagate cmd_flags
* to the iterator. In case of key_data.configure_keys, * to the iterator. In case of key_data.configure_keys,
@ -795,14 +768,8 @@ int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
* iwl_mvm_wowlan_program_keys() will take care of * iwl_mvm_wowlan_program_keys() will take care of
* locking/unlocking mvm->mutex. * locking/unlocking mvm->mutex.
*/ */
ieee80211_iter_keys(mvm->hw, vif, ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_wowlan_program_keys,
iwl_mvm_wowlan_program_keys,
&key_data); &key_data);
} else {
iwl_mvm_iter_d0i3_ap_keys(mvm, vif,
iwl_mvm_wowlan_program_keys,
&key_data);
}
if (key_data.error) { if (key_data.error) {
ret = -EIO; ret = -EIO;
@ -830,7 +797,7 @@ int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
} }
/* configure rekey data only if offloaded rekey is supported (d3) */ /* configure rekey data only if offloaded rekey is supported (d3) */
if (mvmvif->rekey_data.valid && !d0i3) { if (mvmvif->rekey_data.valid) {
memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd)); memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd));
memcpy(kek_kck_cmd.kck, mvmvif->rekey_data.kck, memcpy(kek_kck_cmd.kck, mvmvif->rekey_data.kck,
NL80211_KCK_LEN); NL80211_KCK_LEN);
@ -864,6 +831,8 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
bool unified_image = fw_has_capa(&mvm->fw->ucode_capa, bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
mvm->offload_tid = wowlan_config_cmd->offloading_tid;
if (!unified_image) { if (!unified_image) {
ret = iwl_mvm_switch_to_d3(mvm); ret = iwl_mvm_switch_to_d3(mvm);
if (ret) if (ret)
@ -881,8 +850,7 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
* that isn't really a problem though. * that isn't really a problem though.
*/ */
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
ret = iwl_mvm_wowlan_config_key_params(mvm, vif, false, ret = iwl_mvm_wowlan_config_key_params(mvm, vif, CMD_ASYNC);
CMD_ASYNC);
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
if (ret) if (ret)
return ret; return ret;
@ -936,6 +904,8 @@ iwl_mvm_netdetect_config(struct iwl_mvm *mvm,
wowlan_config_cmd.wakeup_filter |= wowlan_config_cmd.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT); cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
wowlan_config_cmd.sta_id = mvm->aux_sta.sta_id;
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0, ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
sizeof(wowlan_config_cmd), sizeof(wowlan_config_cmd),
&wowlan_config_cmd); &wowlan_config_cmd);
@ -1043,6 +1013,8 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
} else { } else {
struct iwl_wowlan_config_cmd wowlan_config_cmd = {}; struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
wowlan_config_cmd.sta_id = mvmvif->ap_sta_id;
ap_sta = rcu_dereference_protected( ap_sta = rcu_dereference_protected(
mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
lockdep_is_held(&mvm->mutex)); lockdep_is_held(&mvm->mutex));
@ -1082,8 +1054,8 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
* recording before entering D3. In later devices the FW stops the * recording before entering D3. In later devices the FW stops the
* recording automatically. * recording automatically.
*/ */
if (mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_9000) if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
iwl_fw_dbg_stop_recording(mvm->trans, NULL); iwl_fw_dbg_stop_restart_recording(&mvm->fwrt, NULL, true);
/* must be last -- this switches firmware state */ /* must be last -- this switches firmware state */
ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd); ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd);
@ -1100,13 +1072,12 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
iwl_trans_d3_suspend(mvm->trans, test, !unified_image); ret = iwl_trans_d3_suspend(mvm->trans, test, !unified_image);
out: out:
if (ret < 0) { if (ret < 0) {
iwl_mvm_free_nd(mvm); iwl_mvm_free_nd(mvm);
if (!unified_image) { if (!unified_image) {
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
if (mvm->fw_restart > 0) { if (mvm->fw_restart > 0) {
mvm->fw_restart--; mvm->fw_restart--;
ieee80211_restart_hw(mvm->hw); ieee80211_restart_hw(mvm->hw);
@ -1119,37 +1090,12 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
return ret; return ret;
} }
static int iwl_mvm_enter_d0i3_sync(struct iwl_mvm *mvm)
{
struct iwl_notification_wait wait_d3;
static const u16 d3_notif[] = { D3_CONFIG_CMD };
int ret;
iwl_init_notification_wait(&mvm->notif_wait, &wait_d3,
d3_notif, ARRAY_SIZE(d3_notif),
NULL, NULL);
ret = iwl_mvm_enter_d0i3(mvm->hw->priv);
if (ret)
goto remove_notif;
ret = iwl_wait_notification(&mvm->notif_wait, &wait_d3, HZ);
WARN_ON_ONCE(ret);
return ret;
remove_notif:
iwl_remove_notification(&mvm->notif_wait, &wait_d3);
return ret;
}
int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_trans *trans = mvm->trans; struct iwl_trans *trans = mvm->trans;
int ret; int ret;
/* make sure the d0i3 exit work is not pending */
flush_work(&mvm->d0i3_exit_work);
iwl_mvm_pause_tcm(mvm, true); iwl_mvm_pause_tcm(mvm, true);
iwl_fw_runtime_suspend(&mvm->fwrt); iwl_fw_runtime_suspend(&mvm->fwrt);
@ -1158,25 +1104,6 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
if (ret) if (ret)
return ret; return ret;
if (wowlan->any) {
trans->system_pm_mode = IWL_PLAT_PM_MODE_D0I3;
if (iwl_mvm_enter_d0i3_on_suspend(mvm)) {
ret = iwl_mvm_enter_d0i3_sync(mvm);
if (ret)
return ret;
}
mutex_lock(&mvm->d0i3_suspend_mutex);
__set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
mutex_unlock(&mvm->d0i3_suspend_mutex);
iwl_trans_d3_suspend(trans, false, false);
return 0;
}
trans->system_pm_mode = IWL_PLAT_PM_MODE_D3; trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
return __iwl_mvm_suspend(hw, wowlan, false); return __iwl_mvm_suspend(hw, wowlan, false);
@ -1735,6 +1662,13 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
mvm_ap_sta->tid_data[i].seq_number = seq; mvm_ap_sta->tid_data[i].seq_number = seq;
} }
if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
i = mvm->offload_tid;
iwl_trans_set_q_ptrs(mvm->trans,
mvm_ap_sta->tid_data[i].txq_id,
mvm_ap_sta->tid_data[i].seq_number >> 4);
}
/* now we have all the data we need, unlock to avoid mac80211 issues */ /* now we have all the data we need, unlock to avoid mac80211 issues */
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
@ -1752,30 +1686,6 @@ out_unlock:
return false; return false;
} }
void iwl_mvm_d0i3_update_keys(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_wowlan_status *status)
{
struct iwl_mvm_d3_gtk_iter_data gtkdata = {
.mvm = mvm,
.status = status,
};
/*
* rekey handling requires taking locks that can't be taken now.
* however, d0i3 doesn't offload rekey, so we're fine.
*/
if (WARN_ON_ONCE(status->num_of_gtk_rekeys))
return;
/* find last GTK that we used initially, if any */
gtkdata.find_phase = true;
iwl_mvm_iter_d0i3_ap_keys(mvm, vif, iwl_mvm_d3_update_keys, &gtkdata);
gtkdata.find_phase = false;
iwl_mvm_iter_d0i3_ap_keys(mvm, vif, iwl_mvm_d3_update_keys, &gtkdata);
}
#define ND_QUERY_BUF_LEN (sizeof(struct iwl_scan_offload_profile_match) * \ #define ND_QUERY_BUF_LEN (sizeof(struct iwl_scan_offload_profile_match) * \
IWL_SCAN_MAX_PROFILES) IWL_SCAN_MAX_PROFILES)
@ -2024,15 +1934,6 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
if (IS_ERR_OR_NULL(vif)) if (IS_ERR_OR_NULL(vif))
goto err; goto err;
ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test, !unified_image);
if (ret)
goto err;
if (d3_status != IWL_D3_STATUS_ALIVE) {
IWL_INFO(mvm, "Device was reset during suspend\n");
goto err;
}
iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt); iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);
if (iwl_mvm_check_rt_status(mvm, vif)) { if (iwl_mvm_check_rt_status(mvm, vif)) {
@ -2044,6 +1945,15 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
goto err; goto err;
} }
ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test, !unified_image);
if (ret)
goto err;
if (d3_status != IWL_D3_STATUS_ALIVE) {
IWL_INFO(mvm, "Device was reset during suspend\n");
goto err;
}
if (d0i3_first) { if (d0i3_first) {
ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, 0, 0, NULL); ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, 0, 0, NULL);
if (ret < 0) { if (ret < 0) {
@ -2059,6 +1969,9 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
*/ */
iwl_mvm_update_changed_regdom(mvm); iwl_mvm_update_changed_regdom(mvm);
/* Re-configure PPAG settings */
iwl_mvm_ppag_send_cmd(mvm);
if (!unified_image) if (!unified_image)
/* Re-configure default SAR profile */ /* Re-configure default SAR profile */
iwl_mvm_sar_select_profile(mvm, 1, 1); iwl_mvm_sar_select_profile(mvm, 1, 1);
@ -2115,14 +2028,6 @@ out:
* 2. We are using a unified image but had an error while exiting D3 * 2. We are using a unified image but had an error while exiting D3
*/ */
set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
/*
* When switching images we return 1, which causes mac80211
* to do a reconfig with IEEE80211_RECONFIG_TYPE_RESTART.
* This type of reconfig calls iwl_mvm_restart_complete(),
* where we unref the IWL_MVM_REF_UCODE_DOWN, so we need
* to take the reference here.
*/
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
return 1; return 1;
} }
@ -2134,52 +2039,11 @@ static int iwl_mvm_resume_d3(struct iwl_mvm *mvm)
return __iwl_mvm_resume(mvm, false); return __iwl_mvm_resume(mvm, false);
} }
static int iwl_mvm_resume_d0i3(struct iwl_mvm *mvm)
{
bool exit_now;
enum iwl_d3_status d3_status;
struct iwl_trans *trans = mvm->trans;
iwl_trans_d3_resume(trans, &d3_status, false, false);
/*
* make sure to clear D0I3_DEFER_WAKEUP before
* calling iwl_trans_resume(), which might wait
* for d0i3 exit completion.
*/
mutex_lock(&mvm->d0i3_suspend_mutex);
__clear_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
exit_now = __test_and_clear_bit(D0I3_PENDING_WAKEUP,
&mvm->d0i3_suspend_flags);
mutex_unlock(&mvm->d0i3_suspend_mutex);
if (exit_now) {
IWL_DEBUG_RPM(mvm, "Run deferred d0i3 exit\n");
_iwl_mvm_exit_d0i3(mvm);
}
iwl_trans_resume(trans);
if (iwl_mvm_enter_d0i3_on_suspend(mvm)) {
int ret = iwl_mvm_exit_d0i3(mvm->hw->priv);
if (ret)
return ret;
/*
* d0i3 exit will be deferred until reconfig_complete.
* make sure there we are out of d0i3.
*/
}
return 0;
}
int iwl_mvm_resume(struct ieee80211_hw *hw) int iwl_mvm_resume(struct ieee80211_hw *hw)
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret; int ret;
if (mvm->trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3)
ret = iwl_mvm_resume_d0i3(mvm);
else
ret = iwl_mvm_resume_d3(mvm); ret = iwl_mvm_resume_d3(mvm);
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;

View File

@ -1056,19 +1056,11 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf, static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
int ret;
if (!iwl_mvm_firmware_running(mvm)) if (!iwl_mvm_firmware_running(mvm))
return -EIO; return -EIO;
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI);
if (ret)
return ret;
iwl_force_nmi(mvm->trans); iwl_force_nmi(mvm->trans);
iwl_mvm_unref(mvm, IWL_MVM_REF_NMI);
return count; return count;
} }
@ -1181,8 +1173,8 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
struct iwl_rx_mpdu_desc *desc; struct iwl_rx_mpdu_desc *desc;
int bin_len = count / 2; int bin_len = count / 2;
int ret = -EINVAL; int ret = -EINVAL;
size_t mpdu_cmd_hdr_size = size_t mpdu_cmd_hdr_size = (mvm->trans->trans_cfg->device_family >=
(mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) ? IWL_DEVICE_FAMILY_22560) ?
sizeof(struct iwl_rx_mpdu_desc) : sizeof(struct iwl_rx_mpdu_desc) :
IWL_RX_DESC_SIZE_V1; IWL_RX_DESC_SIZE_V1;
@ -1190,7 +1182,7 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
return -EIO; return -EIO;
/* supporting only 9000 descriptor */ /* supporting only 9000 descriptor */
if (!mvm->trans->cfg->mq_rx_supported) if (!mvm->trans->trans_cfg->mq_rx_supported)
return -ENOTSUPP; return -ENOTSUPP;
rxb._page = alloc_pages(GFP_ATOMIC, 0); rxb._page = alloc_pages(GFP_ATOMIC, 0);
@ -1380,19 +1372,12 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
char *buf, size_t count, char *buf, size_t count,
loff_t *ppos) loff_t *ppos)
{ {
int ret;
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
if (ret)
return ret;
if (count == 0) if (count == 0)
return 0; return 0;
iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf, iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf,
(count - 1), NULL); (count - 1), NULL);
iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
return count; return count;
} }
@ -1579,87 +1564,6 @@ static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm,
} }
#endif #endif
#define PRINT_MVM_REF(ref) do { \
if (mvm->refs[ref]) \
pos += scnprintf(buf + pos, bufsz - pos, \
"\t(0x%lx): %d %s\n", \
BIT(ref), mvm->refs[ref], #ref); \
} while (0)
static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
int i, pos = 0;
char buf[256];
const size_t bufsz = sizeof(buf);
u32 refs = 0;
for (i = 0; i < IWL_MVM_REF_COUNT; i++)
if (mvm->refs[i])
refs |= BIT(i);
pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%x\n",
refs);
PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN);
PRINT_MVM_REF(IWL_MVM_REF_SCAN);
PRINT_MVM_REF(IWL_MVM_REF_ROC);
PRINT_MVM_REF(IWL_MVM_REF_ROC_AUX);
PRINT_MVM_REF(IWL_MVM_REF_P2P_CLIENT);
PRINT_MVM_REF(IWL_MVM_REF_AP_IBSS);
PRINT_MVM_REF(IWL_MVM_REF_USER);
PRINT_MVM_REF(IWL_MVM_REF_TX);
PRINT_MVM_REF(IWL_MVM_REF_TX_AGG);
PRINT_MVM_REF(IWL_MVM_REF_ADD_IF);
PRINT_MVM_REF(IWL_MVM_REF_START_AP);
PRINT_MVM_REF(IWL_MVM_REF_BSS_CHANGED);
PRINT_MVM_REF(IWL_MVM_REF_PREPARE_TX);
PRINT_MVM_REF(IWL_MVM_REF_PROTECT_TDLS);
PRINT_MVM_REF(IWL_MVM_REF_CHECK_CTKILL);
PRINT_MVM_REF(IWL_MVM_REF_PRPH_READ);
PRINT_MVM_REF(IWL_MVM_REF_PRPH_WRITE);
PRINT_MVM_REF(IWL_MVM_REF_NMI);
PRINT_MVM_REF(IWL_MVM_REF_TM_CMD);
PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK);
PRINT_MVM_REF(IWL_MVM_REF_PROTECT_CSA);
PRINT_MVM_REF(IWL_MVM_REF_FW_DBG_COLLECT);
PRINT_MVM_REF(IWL_MVM_REF_INIT_UCODE);
PRINT_MVM_REF(IWL_MVM_REF_SENDING_CMD);
PRINT_MVM_REF(IWL_MVM_REF_RX);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
{
unsigned long value;
int ret;
bool taken;
ret = kstrtoul(buf, 10, &value);
if (ret < 0)
return ret;
mutex_lock(&mvm->mutex);
taken = mvm->refs[IWL_MVM_REF_USER];
if (value == 1 && !taken)
iwl_mvm_ref(mvm, IWL_MVM_REF_USER);
else if (value == 0 && taken)
iwl_mvm_unref(mvm, IWL_MVM_REF_USER);
else
ret = -EINVAL;
mutex_unlock(&mvm->mutex);
if (ret < 0)
return ret;
return count;
}
#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \ #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
_MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm) _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
@ -1692,21 +1596,14 @@ iwl_dbgfs_prph_reg_read(struct file *file,
int pos = 0; int pos = 0;
char buf[32]; char buf[32];
const size_t bufsz = sizeof(buf); const size_t bufsz = sizeof(buf);
int ret;
if (!mvm->dbgfs_prph_reg_addr) if (!mvm->dbgfs_prph_reg_addr)
return -EINVAL; return -EINVAL;
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_READ);
if (ret)
return ret;
pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n", pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
mvm->dbgfs_prph_reg_addr, mvm->dbgfs_prph_reg_addr,
iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr)); iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_READ);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos); return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
} }
@ -1716,7 +1613,6 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
{ {
u8 args; u8 args;
u32 value; u32 value;
int ret;
args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value); args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
/* if we only want to set the reg address - nothing more to do */ /* if we only want to set the reg address - nothing more to do */
@ -1727,13 +1623,8 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
if (args != 2) if (args != 2)
return -EINVAL; return -EINVAL;
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
if (ret)
return ret;
iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value); iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
out: out:
return count; return count;
} }
@ -1867,6 +1758,38 @@ iwl_dbgfs_uapsd_noagg_bssids_read(struct file *file, char __user *user_buf,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos); return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
} }
static ssize_t
iwl_dbgfs_ltr_config_write(struct iwl_mvm *mvm,
char *buf, size_t count, loff_t *ppos)
{
int ret;
struct iwl_ltr_config_cmd ltr_config = {0};
if (!iwl_mvm_firmware_running(mvm))
return -EIO;
if (sscanf(buf, "%x,%x,%x,%x,%x,%x,%x",
&ltr_config.flags,
&ltr_config.static_long,
&ltr_config.static_short,
&ltr_config.ltr_cfg_values[0],
&ltr_config.ltr_cfg_values[1],
&ltr_config.ltr_cfg_values[2],
&ltr_config.ltr_cfg_values[3]) != 7) {
return -EINVAL;
}
mutex_lock(&mvm->mutex);
ret = iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, sizeof(ltr_config),
&ltr_config);
mutex_unlock(&mvm->mutex);
if (ret)
IWL_ERR(mvm, "failed to send ltr configuration cmd\n");
return ret ?: count;
}
MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64); MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
/* Device wide debugfs entries */ /* Device wide debugfs entries */
@ -1892,7 +1815,6 @@ MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10); MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10); MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64); MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64);
MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl, MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
@ -1916,6 +1838,8 @@ MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(amsdu_len, 16);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32); MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32);
MVM_DEBUGFS_WRITE_FILE_OPS(ltr_config, 512);
static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf, static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
@ -2091,7 +2015,6 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
MVM_DEBUGFS_ADD_FILE(bt_force_ant, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(bt_force_ant, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, 0600); MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, 0600); MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, 0600); MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200);
@ -2104,6 +2027,9 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
#endif #endif
MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600); MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600);
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_LTR_GEN2))
MVM_DEBUGFS_ADD_FILE(ltr_config, mvm->debugfs_dir, 0200);
debugfs_create_bool("enable_scan_iteration_notif", 0600, debugfs_create_bool("enable_scan_iteration_notif", 0600,
mvm->debugfs_dir, &mvm->scan_iter_notif_enabled); mvm->debugfs_dir, &mvm->scan_iter_notif_enabled);
debugfs_create_bool("drop_bcn_ap_mode", 0600, mvm->debugfs_dir, debugfs_create_bool("drop_bcn_ap_mode", 0600, mvm->debugfs_dir,

View File

@ -357,13 +357,14 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
iwl_fw_dbg_error_collect(&mvm->fwrt, iwl_fw_dbg_error_collect(&mvm->fwrt,
FW_DBG_TRIGGER_ALIVE_TIMEOUT); FW_DBG_TRIGGER_ALIVE_TIMEOUT);
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000)
IWL_ERR(mvm, IWL_ERR(mvm,
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS), iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS),
iwl_read_umac_prph(trans, iwl_read_umac_prph(trans,
UMAG_SB_CPU_2_STATUS)); UMAG_SB_CPU_2_STATUS));
else if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) else if (trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_8000)
IWL_ERR(mvm, IWL_ERR(mvm,
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
iwl_read_prph(trans, SB_CPU_1_STATUS), iwl_read_prph(trans, SB_CPU_1_STATUS),
@ -430,7 +431,7 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
iwl_wait_init_complete, iwl_wait_init_complete,
NULL); NULL);
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_EARLY); iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_EARLY, NULL);
/* Will also start the device */ /* Will also start the device */
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR); ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
@ -438,7 +439,8 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret); IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
goto error; goto error;
} }
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_AFTER_ALIVE); iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_AFTER_ALIVE,
NULL);
/* Send init config command to mark that we are sending NVM access /* Send init config command to mark that we are sending NVM access
* commands * commands
@ -557,7 +559,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
goto remove_notif; goto remove_notif;
} }
if (mvm->cfg->device_family < IWL_DEVICE_FAMILY_8000) { if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000) {
ret = iwl_mvm_send_bt_init_conf(mvm); ret = iwl_mvm_send_bt_init_conf(mvm);
if (ret) if (ret)
goto remove_notif; goto remove_notif;
@ -1002,6 +1004,113 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0, sizeof(cmd), &cmd); return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0, sizeof(cmd), &cmd);
} }
static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
{
union acpi_object *wifi_pkg, *data, *enabled;
int i, j, ret, tbl_rev;
int idx = 2;
mvm->ppag_table.enabled = cpu_to_le32(0);
data = iwl_acpi_get_object(mvm->dev, ACPI_PPAG_METHOD);
if (IS_ERR(data))
return PTR_ERR(data);
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
ACPI_PPAG_WIFI_DATA_SIZE, &tbl_rev);
if (IS_ERR(wifi_pkg) || tbl_rev != 0) {
ret = PTR_ERR(wifi_pkg);
goto out_free;
}
enabled = &wifi_pkg->package.elements[1];
if (enabled->type != ACPI_TYPE_INTEGER ||
(enabled->integer.value != 0 && enabled->integer.value != 1)) {
ret = -EINVAL;
goto out_free;
}
mvm->ppag_table.enabled = cpu_to_le32(enabled->integer.value);
if (!mvm->ppag_table.enabled) {
ret = 0;
goto out_free;
}
/*
* read, verify gain values and save them into the PPAG table.
* first sub-band (j=0) corresponds to Low-Band (2.4GHz), and the
* following sub-bands to High-Band (5GHz).
*/
for (i = 0; i < ACPI_PPAG_NUM_CHAINS; i++) {
for (j = 0; j < ACPI_PPAG_NUM_SUB_BANDS; j++) {
union acpi_object *ent;
ent = &wifi_pkg->package.elements[idx++];
if (ent->type != ACPI_TYPE_INTEGER ||
(j == 0 && ent->integer.value > ACPI_PPAG_MAX_LB) ||
(j == 0 && ent->integer.value < ACPI_PPAG_MIN_LB) ||
(j != 0 && ent->integer.value > ACPI_PPAG_MAX_HB) ||
(j != 0 && ent->integer.value < ACPI_PPAG_MIN_HB)) {
mvm->ppag_table.enabled = cpu_to_le32(0);
ret = -EINVAL;
goto out_free;
}
mvm->ppag_table.gain[i][j] = ent->integer.value;
}
}
ret = 0;
out_free:
kfree(data);
return ret;
}
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
{
int i, j, ret;
if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) {
IWL_DEBUG_RADIO(mvm,
"PPAG capability not supported by FW, command not sent.\n");
return 0;
}
IWL_DEBUG_RADIO(mvm, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");
IWL_DEBUG_RADIO(mvm, "PPAG is %s\n",
mvm->ppag_table.enabled ? "enabled" : "disabled");
for (i = 0; i < ACPI_PPAG_NUM_CHAINS; i++) {
for (j = 0; j < ACPI_PPAG_NUM_SUB_BANDS; j++) {
IWL_DEBUG_RADIO(mvm,
"PPAG table: chain[%d] band[%d]: gain = %d\n",
i, j, mvm->ppag_table.gain[i][j]);
}
}
ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(PHY_OPS_GROUP,
PER_PLATFORM_ANT_GAIN_CMD),
0, sizeof(mvm->ppag_table),
&mvm->ppag_table);
if (ret < 0)
IWL_ERR(mvm, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",
ret);
return ret;
}
static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
{
int ret;
ret = iwl_mvm_get_ppag_table(mvm);
if (ret < 0) {
IWL_DEBUG_RADIO(mvm,
"PPAG BIOS table invalid or unavailable. (%d)\n",
ret);
return 0;
}
return iwl_mvm_ppag_send_cmd(mvm);
}
#else /* CONFIG_ACPI */ #else /* CONFIG_ACPI */
static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm) static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm)
{ {
@ -1033,6 +1142,16 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
{ {
return -ENOENT; return -ENOENT;
} }
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
{
return -ENOENT;
}
static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
{
return -ENOENT;
}
#endif /* CONFIG_ACPI */ #endif /* CONFIG_ACPI */
void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags) void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
@ -1140,17 +1259,13 @@ static int iwl_mvm_load_rt_fw(struct iwl_mvm *mvm)
return ret; return ret;
} }
/* iwl_fw_dbg_stop_sync(&mvm->fwrt);
* Stop and start the transport without entering low power iwl_trans_stop_device(mvm->trans);
* mode. This will save the state of other components on the ret = iwl_trans_start_hw(mvm->trans);
* device that are triggered by the INIT firwmare (MFUART).
*/
_iwl_trans_stop_device(mvm->trans, false);
ret = _iwl_trans_start_hw(mvm->trans, false);
if (ret) if (ret)
return ret; return ret;
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_EARLY); iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_EARLY, NULL);
mvm->rfkill_safe_init_done = false; mvm->rfkill_safe_init_done = false;
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR); ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
@ -1159,7 +1274,8 @@ static int iwl_mvm_load_rt_fw(struct iwl_mvm *mvm)
mvm->rfkill_safe_init_done = true; mvm->rfkill_safe_init_done = true;
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_AFTER_ALIVE); iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_AFTER_ALIVE,
NULL);
return iwl_init_paging(&mvm->fwrt, mvm->fwrt.cur_fw_img); return iwl_init_paging(&mvm->fwrt, mvm->fwrt.cur_fw_img);
} }
@ -1169,6 +1285,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
int ret, i; int ret, i;
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
struct ieee80211_supported_band *sband = NULL;
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
@ -1191,7 +1308,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret) if (ret)
IWL_ERR(mvm, "Failed to initialize Smart Fifo\n"); IWL_ERR(mvm, "Failed to initialize Smart Fifo\n");
if (!mvm->trans->dbg.ini_valid) { if (!iwl_trans_dbg_ini_valid(mvm->trans)) {
mvm->fwrt.dump.conf = FW_DBG_INVALID; mvm->fwrt.dump.conf = FW_DBG_INVALID;
/* if we have a destination, assume EARLY START */ /* if we have a destination, assume EARLY START */
if (mvm->fw->dbg.dest_tlv) if (mvm->fw->dbg.dest_tlv)
@ -1219,7 +1336,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error; goto error;
/* Init RSS configuration */ /* Init RSS configuration */
if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) { if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
ret = iwl_configure_rxq(mvm); ret = iwl_configure_rxq(mvm);
if (ret) { if (ret) {
IWL_ERR(mvm, "Failed to configure RX queues: %d\n", IWL_ERR(mvm, "Failed to configure RX queues: %d\n",
@ -1246,9 +1363,11 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
/* reset quota debouncing buffer - 0xff will yield invalid data */ /* reset quota debouncing buffer - 0xff will yield invalid data */
memset(&mvm->last_quota_cmd, 0xff, sizeof(mvm->last_quota_cmd)); memset(&mvm->last_quota_cmd, 0xff, sizeof(mvm->last_quota_cmd));
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_DQA_SUPPORT)) {
ret = iwl_mvm_send_dqa_cmd(mvm); ret = iwl_mvm_send_dqa_cmd(mvm);
if (ret) if (ret)
goto error; goto error;
}
/* Add auxiliary station for scanning */ /* Add auxiliary station for scanning */
ret = iwl_mvm_add_aux_sta(mvm); ret = iwl_mvm_add_aux_sta(mvm);
@ -1256,7 +1375,15 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error; goto error;
/* Add all the PHY contexts */ /* Add all the PHY contexts */
chan = &mvm->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[0]; i = 0;
while (!sband && i < NUM_NL80211_BANDS)
sband = mvm->hw->wiphy->bands[i++];
if (WARN_ON_ONCE(!sband))
goto error;
chan = &sband->channels[0];
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
for (i = 0; i < NUM_PHY_CTX; i++) { for (i = 0; i < NUM_PHY_CTX; i++) {
/* /*
@ -1270,7 +1397,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error; goto error;
} }
#ifdef CONFIG_THERMAL
if (iwl_mvm_is_tt_in_fw(mvm)) { if (iwl_mvm_is_tt_in_fw(mvm)) {
/* in order to give the responsibility of ct-kill and /* in order to give the responsibility of ct-kill and
* TX backoff to FW we need to send empty temperature reporting * TX backoff to FW we need to send empty temperature reporting
@ -1282,6 +1408,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
iwl_mvm_tt_tx_backoff(mvm, 0); iwl_mvm_tt_tx_backoff(mvm, 0);
} }
#ifdef CONFIG_THERMAL
/* TODO: read the budget from BIOS / Platform NVM */ /* TODO: read the budget from BIOS / Platform NVM */
/* /*
@ -1294,11 +1421,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret) if (ret)
goto error; goto error;
} }
#else
/* Initialize tx backoffs to the minimal possible */
iwl_mvm_tt_tx_backoff(mvm, 0);
#endif #endif
if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_LTR_GEN2))
WARN_ON(iwl_mvm_config_ltr(mvm)); WARN_ON(iwl_mvm_config_ltr(mvm));
ret = iwl_mvm_power_update_device(mvm); ret = iwl_mvm_power_update_device(mvm);
@ -1323,16 +1448,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error; goto error;
} }
/* allow FW/transport low power modes if not during restart */
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_UPDATE_DB); iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_UPDATE_DB);
if (iwl_acpi_get_eckv(mvm->dev, &mvm->ext_clock_valid)) if (iwl_acpi_get_eckv(mvm->dev, &mvm->ext_clock_valid))
IWL_DEBUG_INFO(mvm, "ECKV table doesn't exist in BIOS\n"); IWL_DEBUG_INFO(mvm, "ECKV table doesn't exist in BIOS\n");
ret = iwl_mvm_ppag_init(mvm);
if (ret)
goto error;
ret = iwl_mvm_sar_init(mvm); ret = iwl_mvm_sar_init(mvm);
if (ret == 0) { if (ret == 0) {
ret = iwl_mvm_sar_geo_init(mvm); ret = iwl_mvm_sar_geo_init(mvm);

View File

@ -7,7 +7,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2017 Intel Deutschland GmbH * Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -29,7 +29,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2017 Intel Deutschland GmbH * Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -156,7 +156,7 @@ void iwl_mvm_leds_sync(struct iwl_mvm *mvm)
* if we control through the register, we're doing it * if we control through the register, we're doing it
* even when the firmware isn't up, so no need to sync * even when the firmware isn't up, so no need to sync
*/ */
if (mvm->cfg->device_family < IWL_DEVICE_FAMILY_8000) if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000)
return; return;
iwl_mvm_led_set(mvm, mvm->led.brightness > 0); iwl_mvm_led_set(mvm, mvm->led.brightness > 0);

View File

@ -1431,6 +1431,9 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD) else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD)
ieee80211_beacon_loss(vif); ieee80211_beacon_loss(vif);
iwl_dbg_tlv_time_point(&mvm->fwrt,
IWL_FW_INI_TIME_POINT_MISSED_BEACONS, NULL);
trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif), trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
FW_DBG_TRIGGER_MISSED_BEACONS); FW_DBG_TRIGGER_MISSED_BEACONS);
if (!trigger) if (!trigger)
@ -1447,8 +1450,6 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
rx_missed_bcon >= stop_trig_missed_bcon) rx_missed_bcon >= stop_trig_missed_bcon)
iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL); iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL);
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_MISSED_BEACONS);
out: out:
rcu_read_unlock(); rcu_read_unlock();
} }
@ -1594,6 +1595,8 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
RCU_INIT_POINTER(mvm->csa_vif, NULL); RCU_INIT_POINTER(mvm->csa_vif, NULL);
return; return;
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
iwl_mvm_csa_client_absent(mvm, vif); iwl_mvm_csa_client_absent(mvm, vif);
cancel_delayed_work(&mvmvif->csa_work); cancel_delayed_work(&mvmvif->csa_work);
ieee80211_chswitch_done(vif, true); ieee80211_chswitch_done(vif, true);

View File

@ -213,91 +213,6 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key); struct ieee80211_key_conf *key);
void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
{
if (!iwl_mvm_is_d0i3_supported(mvm))
return;
IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type);
spin_lock_bh(&mvm->refs_lock);
mvm->refs[ref_type]++;
spin_unlock_bh(&mvm->refs_lock);
iwl_trans_ref(mvm->trans);
}
void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
{
if (!iwl_mvm_is_d0i3_supported(mvm))
return;
IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type);
spin_lock_bh(&mvm->refs_lock);
if (WARN_ON(!mvm->refs[ref_type])) {
spin_unlock_bh(&mvm->refs_lock);
return;
}
mvm->refs[ref_type]--;
spin_unlock_bh(&mvm->refs_lock);
iwl_trans_unref(mvm->trans);
}
static void iwl_mvm_unref_all_except(struct iwl_mvm *mvm,
enum iwl_mvm_ref_type except_ref)
{
int i, j;
if (!iwl_mvm_is_d0i3_supported(mvm))
return;
spin_lock_bh(&mvm->refs_lock);
for (i = 0; i < IWL_MVM_REF_COUNT; i++) {
if (except_ref == i || !mvm->refs[i])
continue;
IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d (%d)\n",
i, mvm->refs[i]);
for (j = 0; j < mvm->refs[i]; j++)
iwl_trans_unref(mvm->trans);
mvm->refs[i] = 0;
}
spin_unlock_bh(&mvm->refs_lock);
}
bool iwl_mvm_ref_taken(struct iwl_mvm *mvm)
{
int i;
bool taken = false;
if (!iwl_mvm_is_d0i3_supported(mvm))
return true;
spin_lock_bh(&mvm->refs_lock);
for (i = 0; i < IWL_MVM_REF_COUNT; i++) {
if (mvm->refs[i]) {
taken = true;
break;
}
}
spin_unlock_bh(&mvm->refs_lock);
return taken;
}
int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
{
iwl_mvm_ref(mvm, ref_type);
if (!wait_event_timeout(mvm->d0i3_exit_waitq,
!test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status),
HZ)) {
WARN_ON_ONCE(1);
iwl_mvm_unref(mvm, ref_type);
return -EIO;
}
return 0;
}
static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm) static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm)
{ {
int i; int i;
@ -485,7 +400,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
* for older devices. We also don't see this issue on any newer * for older devices. We also don't see this issue on any newer
* devices. * devices.
*/ */
if (mvm->cfg->device_family >= IWL_DEVICE_FAMILY_9000) if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000)
ieee80211_hw_set(hw, TX_AMSDU); ieee80211_hw_set(hw, TX_AMSDU);
ieee80211_hw_set(hw, TX_FRAG_LIST); ieee80211_hw_set(hw, TX_FRAG_LIST);
@ -762,12 +677,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
if (iwl_mvm_is_d0i3_supported(mvm) &&
device_can_wakeup(mvm->trans->dev)) {
mvm->wowlan.flags = WIPHY_WOWLAN_ANY;
hw->wiphy->wowlan = &mvm->wowlan;
}
if ((unified || mvm->fw->img[IWL_UCODE_WOWLAN].num_sec) && if ((unified || mvm->fw->img[IWL_UCODE_WOWLAN].num_sec) &&
mvm->trans->ops->d3_suspend && mvm->trans->ops->d3_suspend &&
mvm->trans->ops->d3_resume && mvm->trans->ops->d3_resume &&
@ -833,46 +742,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
return ret; return ret;
} }
static bool iwl_mvm_defer_tx(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct sk_buff *skb)
{
struct iwl_mvm_sta *mvmsta;
bool defer = false;
/*
* double check the IN_D0I3 flag both before and after
* taking the spinlock, in order to prevent taking
* the spinlock when not needed.
*/
if (likely(!test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status)))
return false;
spin_lock(&mvm->d0i3_tx_lock);
/*
* testing the flag again ensures the skb dequeue
* loop (on d0i3 exit) hasn't run yet.
*/
if (!test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status))
goto out;
mvmsta = iwl_mvm_sta_from_mac80211(sta);
if (mvmsta->sta_id == IWL_MVM_INVALID_STA ||
mvmsta->sta_id != mvm->d0i3_ap_sta_id)
goto out;
__skb_queue_tail(&mvm->d0i3_tx, skb);
/* trigger wakeup */
iwl_mvm_ref(mvm, IWL_MVM_REF_TX);
iwl_mvm_unref(mvm, IWL_MVM_REF_TX);
defer = true;
out:
spin_unlock(&mvm->d0i3_tx_lock);
return defer;
}
static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control, struct ieee80211_tx_control *control,
struct sk_buff *skb) struct sk_buff *skb)
@ -917,8 +786,6 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
} }
if (sta) { if (sta) {
if (iwl_mvm_defer_tx(mvm, sta, skb))
return;
if (iwl_mvm_tx_skb(mvm, skb, sta)) if (iwl_mvm_tx_skb(mvm, skb, sta))
goto drop; goto drop;
return; return;
@ -1086,7 +953,6 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret; int ret;
bool tx_agg_ref = false;
struct ieee80211_sta *sta = params->sta; struct ieee80211_sta *sta = params->sta;
enum ieee80211_ampdu_mlme_action action = params->action; enum ieee80211_ampdu_mlme_action action = params->action;
u16 tid = params->tid; u16 tid = params->tid;
@ -1101,31 +967,6 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
if (!(mvm->nvm_data->sku_cap_11n_enable)) if (!(mvm->nvm_data->sku_cap_11n_enable))
return -EACCES; return -EACCES;
/* return from D0i3 before starting a new Tx aggregation */
switch (action) {
case IEEE80211_AMPDU_TX_START:
case IEEE80211_AMPDU_TX_STOP_CONT:
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
case IEEE80211_AMPDU_TX_OPERATIONAL:
/*
* for tx start, wait synchronously until D0i3 exit to
* get the correct sequence number for the tid.
* additionally, some other ampdu actions use direct
* target access, which is not handled automatically
* by the trans layer (unlike commands), so wait for
* d0i3 exit in these cases as well.
*/
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_TX_AGG);
if (ret)
return ret;
tx_agg_ref = true;
break;
default:
break;
}
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
switch (action) { switch (action) {
@ -1186,13 +1027,6 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
} }
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
/*
* If the tid is marked as started, we won't use it for offloaded
* traffic on the next D0i3 entry. It's safe to unref.
*/
if (tx_agg_ref)
iwl_mvm_unref(mvm, IWL_MVM_REF_TX_AGG);
return ret; return ret;
} }
@ -1216,11 +1050,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
{ {
/* cleanup all stale references (scan, roc), but keep the
* ucode_down ref until reconfig is complete
*/
iwl_mvm_unref_all_except(mvm, IWL_MVM_REF_UCODE_DOWN);
iwl_mvm_stop_device(mvm); iwl_mvm_stop_device(mvm);
mvm->cur_aid = 0; mvm->cur_aid = 0;
@ -1242,7 +1071,6 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
ieee80211_iterate_interfaces(mvm->hw, 0, iwl_mvm_cleanup_iterator, mvm); ieee80211_iterate_interfaces(mvm->hw, 0, iwl_mvm_cleanup_iterator, mvm);
mvm->p2p_device_vif = NULL; mvm->p2p_device_vif = NULL;
mvm->d0i3_ap_sta_id = IWL_MVM_INVALID_STA;
iwl_mvm_reset_phy_ctxts(mvm); iwl_mvm_reset_phy_ctxts(mvm);
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
@ -1251,9 +1079,6 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
ieee80211_wake_queues(mvm->hw); ieee80211_wake_queues(mvm->hw);
/* clear any stale d0i3 state */
clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
mvm->vif_count = 0; mvm->vif_count = 0;
mvm->rx_ba_sessions = 0; mvm->rx_ba_sessions = 0;
mvm->fwrt.dump.conf = FW_DBG_INVALID; mvm->fwrt.dump.conf = FW_DBG_INVALID;
@ -1278,18 +1103,13 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm)
clear_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); clear_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
/* Clean up some internal and mac80211 state on restart */ /* Clean up some internal and mac80211 state on restart */
iwl_mvm_restart_cleanup(mvm); iwl_mvm_restart_cleanup(mvm);
} else {
/* Hold the reference to prevent runtime suspend while
* the start procedure runs. It's a bit confusing
* that the UCODE_DOWN reference is taken, but it just
* means "UCODE is not UP yet". ( TODO: rename this
* reference).
*/
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
} }
ret = iwl_mvm_up(mvm); ret = iwl_mvm_up(mvm);
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_POST_INIT); iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_POST_INIT,
NULL);
iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_PERIODIC,
NULL);
if (ret && test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { if (ret && test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
/* Something went wrong - we need to finish some cleanup /* Something went wrong - we need to finish some cleanup
@ -1297,9 +1117,6 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm)
* would do. * would do.
*/ */
clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
#ifdef CONFIG_PM
iwl_mvm_d0i3_enable_tx(mvm, NULL);
#endif
} }
return ret; return ret;
@ -1310,19 +1127,6 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret; int ret;
/* Some hw restart cleanups must not hold the mutex */
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
/*
* Make sure we are out of d0i3. This is needed
* to make sure the reference accounting is correct
* (and there is no stale d0i3_exit_work).
*/
wait_event_timeout(mvm->d0i3_exit_waitq,
!test_bit(IWL_MVM_STATUS_IN_D0I3,
&mvm->status),
HZ);
}
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
ret = __iwl_mvm_mac_start(mvm); ret = __iwl_mvm_mac_start(mvm);
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
@ -1337,17 +1141,12 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
#ifdef CONFIG_PM
iwl_mvm_d0i3_enable_tx(mvm, NULL);
#endif
ret = iwl_mvm_update_quotas(mvm, true, NULL); ret = iwl_mvm_update_quotas(mvm, true, NULL);
if (ret) if (ret)
IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n", IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n",
ret); ret);
/* allow transport/FW low power modes */
iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_END_OF_RECOVERY); iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_END_OF_RECOVERY);
/* /*
@ -1359,17 +1158,6 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
} }
static void iwl_mvm_resume_complete(struct iwl_mvm *mvm)
{
if (iwl_mvm_is_d0i3_supported(mvm) &&
iwl_mvm_enter_d0i3_on_suspend(mvm))
WARN_ONCE(!wait_event_timeout(mvm->d0i3_exit_waitq,
!test_bit(IWL_MVM_STATUS_IN_D0I3,
&mvm->status),
HZ),
"D0i3 exit on resume timed out\n");
}
static void static void
iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw, iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
enum ieee80211_reconfig_type reconfig_type) enum ieee80211_reconfig_type reconfig_type)
@ -1381,7 +1169,6 @@ iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
iwl_mvm_restart_complete(mvm); iwl_mvm_restart_complete(mvm);
break; break;
case IEEE80211_RECONFIG_TYPE_SUSPEND: case IEEE80211_RECONFIG_TYPE_SUSPEND:
iwl_mvm_resume_complete(mvm);
break; break;
} }
} }
@ -1443,7 +1230,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
flush_work(&mvm->d0i3_exit_work);
flush_work(&mvm->async_handlers_wk); flush_work(&mvm->async_handlers_wk);
flush_work(&mvm->add_stream_wk); flush_work(&mvm->add_stream_wk);
@ -1457,7 +1243,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
*/ */
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
iwl_fw_cancel_dumps(&mvm->fwrt);
cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork); cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork);
cancel_delayed_work_sync(&mvm->scan_timeout_dwork); cancel_delayed_work_sync(&mvm->scan_timeout_dwork);
iwl_fw_free_dump_desc(&mvm->fwrt); iwl_fw_free_dump_desc(&mvm->fwrt);
@ -1543,16 +1328,21 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
goto out_unlock; goto out_unlock;
} }
if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false); iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0); ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
if (ret) if (ret)
goto out_unlock; goto out_unlock;
iwl_mvm_stop_session_protection(mvm, vif); iwl_mvm_stop_session_protection(mvm, vif);
} }
}
mvmvif->ps_disabled = false; mvmvif->ps_disabled = false;
@ -1611,15 +1401,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
mvmvif->mvm = mvm; mvmvif->mvm = mvm;
RCU_INIT_POINTER(mvmvif->probe_resp_data, NULL); RCU_INIT_POINTER(mvmvif->probe_resp_data, NULL);
/*
* make sure D0i3 exit is completed, otherwise a target access
* during tx queue configuration could be done when still in
* D0i3 state.
*/
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_ADD_IF);
if (ret)
return ret;
/* /*
* Not much to do here. The stack will not allow interface * Not much to do here. The stack will not allow interface
* types or combinations that we didn't advertise, so we * types or combinations that we didn't advertise, so we
@ -1755,8 +1536,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
out_unlock: out_unlock:
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
iwl_mvm_unref(mvm, IWL_MVM_REF_ADD_IF);
return ret; return ret;
} }
@ -2254,6 +2033,10 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
flags = 0; flags = 0;
/* Block 26-tone RU OFDMA transmissions */
if (mvmvif->he_ru_2mhz_block)
flags |= STA_CTXT_HE_RU_2MHZ_BLOCK;
/* HTC flags */ /* HTC flags */
if (sta->he_cap.he_cap_elem.mac_cap_info[0] & if (sta->he_cap.he_cap_elem.mac_cap_info[0] &
IEEE80211_HE_MAC_CAP0_HTC_HE) IEEE80211_HE_MAC_CAP0_HTC_HE)
@ -2520,7 +2303,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
iwl_mvm_sf_update(mvm, vif, false); iwl_mvm_sf_update(mvm, vif, false);
iwl_mvm_power_vif_assoc(mvm, vif); iwl_mvm_power_vif_assoc(mvm, vif);
if (vif->p2p) { if (vif->p2p) {
iwl_mvm_ref(mvm, IWL_MVM_REF_P2P_CLIENT);
iwl_mvm_update_smps(mvm, vif, iwl_mvm_update_smps(mvm, vif,
IWL_MVM_SMPS_REQ_PROT, IWL_MVM_SMPS_REQ_PROT,
IEEE80211_SMPS_DYNAMIC); IEEE80211_SMPS_DYNAMIC);
@ -2556,9 +2338,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
IWL_ERR(mvm, IWL_ERR(mvm,
"failed to remove AP station\n"); "failed to remove AP station\n");
if (mvm->d0i3_ap_sta_id == mvmvif->ap_sta_id)
mvm->d0i3_ap_sta_id =
IWL_MVM_INVALID_STA;
mvmvif->ap_sta_id = IWL_MVM_INVALID_STA; mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
} }
@ -2567,9 +2346,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
if (ret) if (ret)
IWL_ERR(mvm, "failed to update quotas\n"); IWL_ERR(mvm, "failed to update quotas\n");
if (vif->p2p)
iwl_mvm_unref(mvm, IWL_MVM_REF_P2P_CLIENT);
/* this will take the cleared BSSID from bss_conf */ /* this will take the cleared BSSID from bss_conf */
ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
if (ret) if (ret)
@ -2657,14 +2433,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret, i; int ret, i;
/*
* iwl_mvm_mac_ctxt_add() might read directly from the device
* (the system time), so make sure it is available.
*/
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_START_AP);
if (ret)
return ret;
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
/* Send the beacon template */ /* Send the beacon template */
@ -2760,8 +2528,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
if (vif->p2p && mvm->p2p_device_vif) if (vif->p2p && mvm->p2p_device_vif)
iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL); iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL);
iwl_mvm_ref(mvm, IWL_MVM_REF_AP_IBSS);
iwl_mvm_bt_coex_vif_change(mvm); iwl_mvm_bt_coex_vif_change(mvm);
/* we don't support TDLS during DCM */ /* we don't support TDLS during DCM */
@ -2783,7 +2549,6 @@ out_remove:
iwl_mvm_mac_ctxt_remove(mvm, vif); iwl_mvm_mac_ctxt_remove(mvm, vif);
out_unlock: out_unlock:
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
iwl_mvm_unref(mvm, IWL_MVM_REF_START_AP);
return ret; return ret;
} }
@ -2821,8 +2586,6 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
iwl_mvm_bt_coex_vif_change(mvm); iwl_mvm_bt_coex_vif_change(mvm);
iwl_mvm_unref(mvm, IWL_MVM_REF_AP_IBSS);
/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */ /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
if (vif->p2p && mvm->p2p_device_vif) if (vif->p2p && mvm->p2p_device_vif)
iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL); iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL);
@ -2896,14 +2659,6 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
/*
* iwl_mvm_bss_info_changed_station() might call
* iwl_mvm_protect_session(), which reads directly from
* the device (the system time), so make sure it is available.
*/
if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_BSS_CHANGED))
return;
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
if (changes & BSS_CHANGED_IDLE && !bss_conf->idle) if (changes & BSS_CHANGED_IDLE && !bss_conf->idle)
@ -2927,7 +2682,6 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
} }
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
iwl_mvm_unref(mvm, IWL_MVM_REF_BSS_CHANGED);
} }
static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
@ -3205,6 +2959,51 @@ iwl_mvm_tdls_check_trigger(struct iwl_mvm *mvm,
peer_addr, action); peer_addr, action);
} }
struct iwl_mvm_he_obss_narrow_bw_ru_data {
bool tolerated;
};
static void iwl_mvm_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy,
struct cfg80211_bss *bss,
void *_data)
{
struct iwl_mvm_he_obss_narrow_bw_ru_data *data = _data;
const struct element *elem;
elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, bss->ies->data,
bss->ies->len);
if (!elem || elem->datalen < 10 ||
!(elem->data[10] &
WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT)) {
data->tolerated = false;
}
}
static void iwl_mvm_check_he_obss_narrow_bw_ru(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_he_obss_narrow_bw_ru_data iter_data = {
.tolerated = true,
};
if (!(vif->bss_conf.chandef.chan->flags & IEEE80211_CHAN_RADAR)) {
mvmvif->he_ru_2mhz_block = false;
return;
}
cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chandef,
iwl_mvm_check_he_obss_narrow_bw_ru_iter,
&iter_data);
/*
* If there is at least one AP on radar channel that cannot
* tolerate 26-tone RU UL OFDMA transmissions using HE TB PPDU.
*/
mvmvif->he_ru_2mhz_block = !iter_data.tolerated;
}
static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
@ -3306,6 +3105,11 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
iwl_mvm_cfg_he_sta(mvm, vif, mvm_sta->sta_id); iwl_mvm_cfg_he_sta(mvm, vif, mvm_sta->sta_id);
} else if (vif->type == NL80211_IFTYPE_STATION) { } else if (vif->type == NL80211_IFTYPE_STATION) {
vif->bss_conf.he_support = sta->he_cap.has_he; vif->bss_conf.he_support = sta->he_cap.has_he;
mvmvif->he_ru_2mhz_block = false;
if (sta->he_cap.has_he)
iwl_mvm_check_he_obss_narrow_bw_ru(hw, vif);
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
} }
@ -3447,13 +3251,6 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS; u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS;
u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS; u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS;
/*
* iwl_mvm_protect_session() reads directly from the device
* (the system time), so make sure it is available.
*/
if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PREPARE_TX))
return;
if (req_duration > duration) if (req_duration > duration)
duration = req_duration; duration = req_duration;
@ -3461,8 +3258,6 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
/* Try really hard to protect the session and hear a beacon */ /* Try really hard to protect the session and hear a beacon */
iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500, false); iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500, false);
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
iwl_mvm_unref(mvm, IWL_MVM_REF_PREPARE_TX);
} }
static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
@ -3537,7 +3332,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
switch (key->cipher) { switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_TKIP:
if (!mvm->trans->cfg->gen2) { if (!mvm->trans->trans_cfg->gen2) {
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
} else if (vif->type == NL80211_IFTYPE_STATION) { } else if (vif->type == NL80211_IFTYPE_STATION) {
@ -4278,23 +4073,12 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) { IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
u32 duration = 3 * vif->bss_conf.beacon_int; u32 duration = 3 * vif->bss_conf.beacon_int;
/* iwl_mvm_protect_session() reads directly from the
* device (the system time), so make sure it is
* available.
*/
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA);
if (ret)
goto out_remove_binding;
/* Protect the session to make sure we hear the first /* Protect the session to make sure we hear the first
* beacon on the new channel. * beacon on the new channel.
*/ */
iwl_mvm_protect_session(mvm, vif, duration, duration, iwl_mvm_protect_session(mvm, vif, duration, duration,
vif->bss_conf.beacon_int / 2, vif->bss_conf.beacon_int / 2,
true); true);
iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA);
} }
iwl_mvm_update_quotas(mvm, false, NULL); iwl_mvm_update_quotas(mvm, false, NULL);
@ -4644,6 +4428,42 @@ static int iwl_mvm_schedule_client_csa(struct iwl_mvm *mvm,
0, sizeof(cmd), &cmd); 0, sizeof(cmd), &cmd);
} }
static int iwl_mvm_old_pre_chan_sw_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_channel_switch *chsw)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u32 apply_time;
/* 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
* TE (this might result with some packet loss or connection
* loss).
*/
if (chsw->count <= 1)
apply_time = 0;
else
apply_time = chsw->device_timestamp +
((vif->bss_conf.beacon_int * (chsw->count - 1) -
IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT) * 1024);
if (chsw->block_tx)
iwl_mvm_csa_client_absent(mvm, vif);
if (mvmvif->bf_data.bf_enabled) {
int ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
if (ret)
return ret;
}
iwl_mvm_schedule_csa_period(mvm, vif, vif->bss_conf.beacon_int,
apply_time);
return 0;
}
#define IWL_MAX_CSA_BLOCK_TX 1500 #define IWL_MAX_CSA_BLOCK_TX 1500
static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
@ -4652,7 +4472,6 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct ieee80211_vif *csa_vif; struct ieee80211_vif *csa_vif;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u32 apply_time;
int ret; int ret;
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
@ -4696,21 +4515,7 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
break; break;
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
/* 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
* TE (this might result with some packet loss or connection
* loss).
*/
if (chsw->count <= 1)
apply_time = 0;
else
apply_time = chsw->device_timestamp +
((vif->bss_conf.beacon_int * (chsw->count - 1) -
IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT) * 1024);
if (chsw->block_tx) { if (chsw->block_tx) {
iwl_mvm_csa_client_absent(mvm, vif);
/* /*
* In case of undetermined / long time with immediate * In case of undetermined / long time with immediate
* quiet monitor status to gracefully disconnect * quiet monitor status to gracefully disconnect
@ -4722,19 +4527,14 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
msecs_to_jiffies(IWL_MAX_CSA_BLOCK_TX)); msecs_to_jiffies(IWL_MAX_CSA_BLOCK_TX));
} }
if (mvmvif->bf_data.bf_enabled) { if (!fw_has_capa(&mvm->fw->ucode_capa,
ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
ret = iwl_mvm_old_pre_chan_sw_sta(mvm, vif, chsw);
if (ret) if (ret)
goto out_unlock; goto out_unlock;
} } else {
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
iwl_mvm_schedule_client_csa(mvm, vif, chsw); iwl_mvm_schedule_client_csa(mvm, vif, chsw);
else }
iwl_mvm_schedule_csa_period(mvm, vif,
vif->bss_conf.beacon_int,
apply_time);
mvmvif->csa_count = chsw->count; mvmvif->csa_count = chsw->count;
mvmvif->csa_misbehave = false; mvmvif->csa_misbehave = false;

View File

@ -258,38 +258,6 @@ enum iwl_mvm_smps_type_request {
NUM_IWL_MVM_SMPS_REQ, NUM_IWL_MVM_SMPS_REQ,
}; };
enum iwl_mvm_ref_type {
IWL_MVM_REF_UCODE_DOWN,
IWL_MVM_REF_SCAN,
IWL_MVM_REF_ROC,
IWL_MVM_REF_ROC_AUX,
IWL_MVM_REF_P2P_CLIENT,
IWL_MVM_REF_AP_IBSS,
IWL_MVM_REF_USER,
IWL_MVM_REF_TX,
IWL_MVM_REF_TX_AGG,
IWL_MVM_REF_ADD_IF,
IWL_MVM_REF_START_AP,
IWL_MVM_REF_BSS_CHANGED,
IWL_MVM_REF_PREPARE_TX,
IWL_MVM_REF_PROTECT_TDLS,
IWL_MVM_REF_CHECK_CTKILL,
IWL_MVM_REF_PRPH_READ,
IWL_MVM_REF_PRPH_WRITE,
IWL_MVM_REF_NMI,
IWL_MVM_REF_TM_CMD,
IWL_MVM_REF_EXIT_WORK,
IWL_MVM_REF_PROTECT_CSA,
IWL_MVM_REF_FW_DBG_COLLECT,
IWL_MVM_REF_INIT_UCODE,
IWL_MVM_REF_SENDING_CMD,
IWL_MVM_REF_RX,
/* update debugfs.c when changing this */
IWL_MVM_REF_COUNT,
};
enum iwl_bt_force_ant_mode { enum iwl_bt_force_ant_mode {
BT_FORCE_ANT_DIS = 0, BT_FORCE_ANT_DIS = 0,
BT_FORCE_ANT_AUTO, BT_FORCE_ANT_AUTO,
@ -504,6 +472,9 @@ struct iwl_mvm_vif {
/* we can only have 2 GTK + 2 IGTK active at a time */ /* we can only have 2 GTK + 2 IGTK active at a time */
struct ieee80211_key_conf *ap_early_keys[4]; struct ieee80211_key_conf *ap_early_keys[4];
/* 26-tone RU OFDMA transmissions should be blocked */
bool he_ru_2mhz_block;
}; };
static inline struct iwl_mvm_vif * static inline struct iwl_mvm_vif *
@ -617,11 +588,6 @@ struct iwl_mvm_frame_stats {
int last_frame_idx; int last_frame_idx;
}; };
enum {
D0I3_DEFER_WAKEUP,
D0I3_PENDING_WAKEUP,
};
#define IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE 0xff #define IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE 0xff
#define IWL_MVM_DEBUG_SET_TEMPERATURE_MIN -100 #define IWL_MVM_DEBUG_SET_TEMPERATURE_MIN -100
#define IWL_MVM_DEBUG_SET_TEMPERATURE_MAX 200 #define IWL_MVM_DEBUG_SET_TEMPERATURE_MAX 200
@ -695,6 +661,12 @@ struct iwl_mvm_tcm {
* @valid: reordering is valid for this queue * @valid: reordering is valid for this queue
* @lock: protect reorder buffer internal state * @lock: protect reorder buffer internal state
* @mvm: mvm pointer, needed for frame timer context * @mvm: mvm pointer, needed for frame timer context
* @consec_oldsn_drops: consecutive drops due to old SN
* @consec_oldsn_ampdu_gp2: A-MPDU GP2 timestamp to track
* when to apply old SN consecutive drop workaround
* @consec_oldsn_prev_drop: track whether or not an MPDU
* that was single/part of the previous A-MPDU was
* dropped due to old SN
*/ */
struct iwl_mvm_reorder_buffer { struct iwl_mvm_reorder_buffer {
u16 head_sn; u16 head_sn;
@ -708,6 +680,9 @@ struct iwl_mvm_reorder_buffer {
bool valid; bool valid;
spinlock_t lock; spinlock_t lock;
struct iwl_mvm *mvm; struct iwl_mvm *mvm;
unsigned int consec_oldsn_drops;
u32 consec_oldsn_ampdu_gp2;
unsigned int consec_oldsn_prev_drop:1;
} ____cacheline_aligned_in_smp; } ____cacheline_aligned_in_smp;
/** /**
@ -1011,10 +986,6 @@ struct iwl_mvm {
unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)]; unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)];
u8 fw_key_deleted[STA_KEY_MAX_NUM]; u8 fw_key_deleted[STA_KEY_MAX_NUM];
/* references taken by the driver and spinlock protecting them */
spinlock_t refs_lock;
u8 refs[IWL_MVM_REF_COUNT];
u8 vif_count; u8 vif_count;
struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER]; struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER];
@ -1039,6 +1010,7 @@ struct iwl_mvm {
struct ieee80211_channel **nd_channels; struct ieee80211_channel **nd_channels;
int n_nd_channels; int n_nd_channels;
bool net_detect; bool net_detect;
u8 offload_tid;
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
bool d3_wake_sysassert; bool d3_wake_sysassert;
bool d3_test_active; bool d3_test_active;
@ -1048,17 +1020,6 @@ struct iwl_mvm {
#endif #endif
#endif #endif
/* d0i3 */
u8 d0i3_ap_sta_id;
bool d0i3_offloading;
struct work_struct d0i3_exit_work;
struct sk_buff_head d0i3_tx;
/* protect d0i3_suspend_flags */
struct mutex d0i3_suspend_mutex;
unsigned long d0i3_suspend_flags;
/* sync d0i3_tx queue and IWL_MVM_STATUS_IN_D0I3 status flag */
spinlock_t d0i3_tx_lock;
wait_queue_head_t d0i3_exit_waitq;
wait_queue_head_t rx_sync_waitq; wait_queue_head_t rx_sync_waitq;
/* BT-Coex */ /* BT-Coex */
@ -1184,6 +1145,8 @@ struct iwl_mvm {
struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM]; struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
struct iwl_mvm_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES]; struct iwl_mvm_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
u32 geo_rev; u32 geo_rev;
struct iwl_ppag_table_cmd ppag_table;
u32 ppag_rev;
#endif #endif
}; };
@ -1201,7 +1164,6 @@ struct iwl_mvm {
* @IWL_MVM_STATUS_ROC_RUNNING: remain-on-channel is running * @IWL_MVM_STATUS_ROC_RUNNING: remain-on-channel is running
* @IWL_MVM_STATUS_HW_RESTART_REQUESTED: HW restart was requested * @IWL_MVM_STATUS_HW_RESTART_REQUESTED: HW restart was requested
* @IWL_MVM_STATUS_IN_HW_RESTART: HW restart is active * @IWL_MVM_STATUS_IN_HW_RESTART: HW restart is active
* @IWL_MVM_STATUS_IN_D0I3: NIC is in D0i3
* @IWL_MVM_STATUS_ROC_AUX_RUNNING: AUX remain-on-channel is running * @IWL_MVM_STATUS_ROC_AUX_RUNNING: AUX remain-on-channel is running
* @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running * @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running
* @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA * @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA
@ -1212,7 +1174,6 @@ enum iwl_mvm_status {
IWL_MVM_STATUS_ROC_RUNNING, IWL_MVM_STATUS_ROC_RUNNING,
IWL_MVM_STATUS_HW_RESTART_REQUESTED, IWL_MVM_STATUS_HW_RESTART_REQUESTED,
IWL_MVM_STATUS_IN_HW_RESTART, IWL_MVM_STATUS_IN_HW_RESTART,
IWL_MVM_STATUS_IN_D0I3,
IWL_MVM_STATUS_ROC_AUX_RUNNING, IWL_MVM_STATUS_ROC_AUX_RUNNING,
IWL_MVM_STATUS_FIRMWARE_RUNNING, IWL_MVM_STATUS_FIRMWARE_RUNNING,
IWL_MVM_STATUS_NEED_FLUSH_P2P, IWL_MVM_STATUS_NEED_FLUSH_P2P,
@ -1291,13 +1252,6 @@ iwl_mvm_rcu_dereference_vif_id(struct iwl_mvm *mvm, u8 vif_id, bool rcu)
lockdep_is_held(&mvm->mutex)); lockdep_is_held(&mvm->mutex));
} }
static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)
{
return !iwlwifi_mod_params.d0i3_disable &&
fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_D0I3_SUPPORT);
}
static inline bool iwl_mvm_is_adaptive_dwell_supported(struct iwl_mvm *mvm) static inline bool iwl_mvm_is_adaptive_dwell_supported(struct iwl_mvm *mvm)
{ {
return fw_has_api(&mvm->fw->ucode_capa, return fw_has_api(&mvm->fw->ucode_capa,
@ -1333,19 +1287,6 @@ static inline bool iwl_mvm_is_short_beacon_notif_supported(struct iwl_mvm *mvm)
IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF); IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF);
} }
static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm)
{
/* For now we only use this mode to differentiate between
* slave transports, which handle D0i3 entry in suspend by
* themselves in conjunction with runtime PM D0i3. So, this
* function is used to check whether we need to do anything
* when entering suspend or if the transport layer has already
* done it.
*/
return (mvm->trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3) &&
(mvm->trans->runtime_pm_mode != IWL_PLAT_PM_MODE_D0I3);
}
static inline bool iwl_mvm_is_dqa_data_queue(struct iwl_mvm *mvm, u8 queue) static inline bool iwl_mvm_is_dqa_data_queue(struct iwl_mvm *mvm, u8 queue)
{ {
return (queue >= IWL_MVM_DQA_MIN_DATA_QUEUE) && return (queue >= IWL_MVM_DQA_MIN_DATA_QUEUE) &&
@ -1424,13 +1365,13 @@ static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm)
static inline bool iwl_mvm_has_new_tx_api(struct iwl_mvm *mvm) static inline bool iwl_mvm_has_new_tx_api(struct iwl_mvm *mvm)
{ {
/* TODO - replace with TLV once defined */ /* TODO - replace with TLV once defined */
return mvm->trans->cfg->use_tfh; return mvm->trans->trans_cfg->use_tfh;
} }
static inline bool iwl_mvm_has_unified_ucode(struct iwl_mvm *mvm) static inline bool iwl_mvm_has_unified_ucode(struct iwl_mvm *mvm)
{ {
/* TODO - better define this */ /* TODO - better define this */
return mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000; return mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000;
} }
static inline bool iwl_mvm_is_cdb_supported(struct iwl_mvm *mvm) static inline bool iwl_mvm_is_cdb_supported(struct iwl_mvm *mvm)
@ -1455,7 +1396,13 @@ static inline bool iwl_mvm_cdb_scan_api(struct iwl_mvm *mvm)
* but then there's a little bit of code in scan that won't make * but then there's a little bit of code in scan that won't make
* any sense... * any sense...
*/ */
return mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000; return mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000;
}
static inline bool iwl_mvm_is_scan_ext_chan_supported(struct iwl_mvm *mvm)
{
return fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_SCAN_EXT_CHAN_VER);
} }
static inline bool iwl_mvm_has_new_rx_stats_api(struct iwl_mvm *mvm) static inline bool iwl_mvm_has_new_rx_stats_api(struct iwl_mvm *mvm)
@ -1487,7 +1434,6 @@ iwl_mvm_get_agg_status(struct iwl_mvm *mvm, void *tx_resp)
static inline bool iwl_mvm_is_tt_in_fw(struct iwl_mvm *mvm) static inline bool iwl_mvm_is_tt_in_fw(struct iwl_mvm *mvm)
{ {
#ifdef CONFIG_THERMAL
/* these two TLV are redundant since the responsibility to CT-kill by /* these two TLV are redundant since the responsibility to CT-kill by
* FW happens only after we send at least one command of * FW happens only after we send at least one command of
* temperature THs report. * temperature THs report.
@ -1496,9 +1442,6 @@ static inline bool iwl_mvm_is_tt_in_fw(struct iwl_mvm *mvm)
IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW) && IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW) &&
fw_has_capa(&mvm->fw->ucode_capa, fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT); IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT);
#else /* CONFIG_THERMAL */
return false;
#endif /* CONFIG_THERMAL */
} }
static inline bool iwl_mvm_is_ctdp_supported(struct iwl_mvm *mvm) static inline bool iwl_mvm_is_ctdp_supported(struct iwl_mvm *mvm)
@ -1663,6 +1606,8 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue); struct iwl_rx_cmd_buffer *rxb, int queue);
void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi, void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue); struct iwl_rx_cmd_buffer *rxb, int queue);
void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue);
int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask, int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
const u8 *data, u32 count, bool async); const u8 *data, u32 count, bool async);
void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi, void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
@ -1863,30 +1808,9 @@ void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw,
extern const struct file_operations iwl_dbgfs_d3_test_ops; extern const struct file_operations iwl_dbgfs_d3_test_ops;
struct iwl_wowlan_status *iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm); struct iwl_wowlan_status *iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm);
#ifdef CONFIG_PM #ifdef CONFIG_PM
int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool host_awake,
u32 cmd_flags);
void iwl_mvm_d0i3_update_keys(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_wowlan_status *status);
void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
#else #else
static inline int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool host_awake,
u32 cmd_flags)
{
return 0;
}
static inline void iwl_mvm_d0i3_update_keys(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_wowlan_status *status)
{
}
static inline void static inline void
iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif) iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{ {
@ -1900,19 +1824,6 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
bool offload_ns, bool offload_ns,
u32 cmd_flags); u32 cmd_flags);
/* D0i3 */
void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
bool iwl_mvm_ref_taken(struct iwl_mvm *mvm);
#ifdef CONFIG_PM
void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq);
int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode);
int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode);
int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm);
#endif
/* BT Coex */ /* BT Coex */
int iwl_mvm_send_bt_init_conf(struct iwl_mvm *mvm); int iwl_mvm_send_bt_init_conf(struct iwl_mvm *mvm);
void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
@ -1943,9 +1854,6 @@ iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
struct iwl_beacon_filter_cmd *cmd) struct iwl_beacon_filter_cmd *cmd)
{} {}
#endif #endif
int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool enable, u32 flags);
int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
u32 flags); u32 flags);
@ -2025,7 +1933,7 @@ void iwl_mvm_vif_set_low_latency(struct iwl_mvm_vif *mvmvif, bool set,
*/ */
static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm) static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm)
{ {
return ((BIT(mvm->cfg->base_params->num_of_queues) - 1) & return ((BIT(mvm->trans->trans_cfg->base_params->num_of_queues) - 1) &
~BIT(IWL_MVM_DQA_CMD_QUEUE)); ~BIT(IWL_MVM_DQA_CMD_QUEUE));
} }
@ -2034,7 +1942,8 @@ static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
iwl_fw_cancel_timestamp(&mvm->fwrt); iwl_fw_cancel_timestamp(&mvm->fwrt);
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
iwl_fwrt_stop_device(&mvm->fwrt); iwl_fw_dbg_stop_sync(&mvm->fwrt);
iwl_trans_stop_device(mvm->trans);
iwl_free_fw_paging(&mvm->fwrt); iwl_free_fw_paging(&mvm->fwrt);
iwl_fw_dump_conf_clear(&mvm->fwrt); iwl_fw_dump_conf_clear(&mvm->fwrt);
} }
@ -2154,6 +2063,7 @@ void iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm,
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b); 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); int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm);
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm);
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw, void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,

View File

@ -249,7 +249,7 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
while (ret == length) { while (ret == length) {
/* Check no memory assumptions fail and cause an overflow */ /* Check no memory assumptions fail and cause an overflow */
if ((size_read + offset + length) > if ((size_read + offset + length) >
mvm->cfg->base_params->eeprom_size) { mvm->trans->trans_cfg->base_params->eeprom_size) {
IWL_ERR(mvm, "EEPROM size is too small for NVM\n"); IWL_ERR(mvm, "EEPROM size is too small for NVM\n");
return -ENOBUFS; return -ENOBUFS;
} }
@ -372,7 +372,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
/* Read From FW NVM */ /* Read From FW NVM */
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n"); IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");
nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, nvm_buffer = kmalloc(mvm->trans->trans_cfg->base_params->eeprom_size,
GFP_KERNEL); GFP_KERNEL);
if (!nvm_buffer) if (!nvm_buffer)
return -ENOMEM; return -ENOMEM;

View File

@ -173,7 +173,7 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
* unrelated errors. Need to further investigate this, but for now * unrelated errors. Need to further investigate this, but for now
* we'll separate cases. * we'll separate cases.
*/ */
if (mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_8000) if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000)
reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI; reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI;
if (iwl_fw_dbg_is_d3_debug_enabled(&mvm->fwrt)) if (iwl_fw_dbg_is_d3_debug_enabled(&mvm->fwrt))
@ -389,6 +389,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(SCAN_ITERATION_COMPLETE_UMAC), HCMD_NAME(SCAN_ITERATION_COMPLETE_UMAC),
HCMD_NAME(REPLY_RX_PHY_CMD), HCMD_NAME(REPLY_RX_PHY_CMD),
HCMD_NAME(REPLY_RX_MPDU_CMD), HCMD_NAME(REPLY_RX_MPDU_CMD),
HCMD_NAME(BAR_FRAME_RELEASE),
HCMD_NAME(FRAME_RELEASE), HCMD_NAME(FRAME_RELEASE),
HCMD_NAME(BA_NOTIF), HCMD_NAME(BA_NOTIF),
HCMD_NAME(MCC_UPDATE_CMD), HCMD_NAME(MCC_UPDATE_CMD),
@ -414,6 +415,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(SCAN_ITERATION_COMPLETE), HCMD_NAME(SCAN_ITERATION_COMPLETE),
HCMD_NAME(D0I3_END_CMD), HCMD_NAME(D0I3_END_CMD),
HCMD_NAME(LTR_CONFIG), HCMD_NAME(LTR_CONFIG),
HCMD_NAME(LDBG_CONFIG_CMD),
}; };
/* Please keep this array *SORTED* by hex value. /* Please keep this array *SORTED* by hex value.
@ -465,6 +467,8 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
* Access is done through binary search * Access is done through binary search
*/ */
static const struct iwl_hcmd_names iwl_mvm_debug_names[] = { static const struct iwl_hcmd_names iwl_mvm_debug_names[] = {
HCMD_NAME(DBGC_SUSPEND_RESUME),
HCMD_NAME(BUFFER_ALLOCATION),
HCMD_NAME(MFU_ASSERT_DUMP_NTF), HCMD_NAME(MFU_ASSERT_DUMP_NTF),
}; };
@ -514,9 +518,6 @@ static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
/* this forward declaration can avoid to export the function */ /* this forward declaration can avoid to export the function */
static void iwl_mvm_async_handlers_wk(struct work_struct *wk); static void iwl_mvm_async_handlers_wk(struct work_struct *wk);
#ifdef CONFIG_PM
static void iwl_mvm_d0i3_exit_work(struct work_struct *wk);
#endif
static u32 iwl_mvm_min_backoff(struct iwl_mvm *mvm) static u32 iwl_mvm_min_backoff(struct iwl_mvm *mvm)
{ {
@ -564,23 +565,16 @@ unlock:
static int iwl_mvm_fwrt_dump_start(void *ctx) static int iwl_mvm_fwrt_dump_start(void *ctx)
{ {
struct iwl_mvm *mvm = ctx; struct iwl_mvm *mvm = ctx;
int ret = 0;
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_FW_DBG_COLLECT); return 0;
if (ret)
mutex_unlock(&mvm->mutex);
return ret;
} }
static void iwl_mvm_fwrt_dump_end(void *ctx) static void iwl_mvm_fwrt_dump_end(void *ctx)
{ {
struct iwl_mvm *mvm = ctx; struct iwl_mvm *mvm = ctx;
iwl_mvm_unref(mvm, IWL_MVM_REF_FW_DBG_COLLECT);
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
} }
@ -672,7 +666,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if (iwl_mvm_has_new_rx_api(mvm)) { if (iwl_mvm_has_new_rx_api(mvm)) {
op_mode->ops = &iwl_mvm_ops_mq; op_mode->ops = &iwl_mvm_ops_mq;
trans->rx_mpdu_cmd_hdr_size = trans->rx_mpdu_cmd_hdr_size =
(trans->cfg->device_family >= (trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_22560) ? IWL_DEVICE_FAMILY_22560) ?
sizeof(struct iwl_rx_mpdu_desc) : sizeof(struct iwl_rx_mpdu_desc) :
IWL_RX_DESC_SIZE_V1; IWL_RX_DESC_SIZE_V1;
@ -700,7 +694,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->drop_bcn_ap_mode = true; mvm->drop_bcn_ap_mode = true;
mutex_init(&mvm->mutex); mutex_init(&mvm->mutex);
mutex_init(&mvm->d0i3_suspend_mutex);
spin_lock_init(&mvm->async_handlers_lock); spin_lock_init(&mvm->async_handlers_lock);
INIT_LIST_HEAD(&mvm->time_event_list); INIT_LIST_HEAD(&mvm->time_event_list);
INIT_LIST_HEAD(&mvm->aux_roc_te_list); INIT_LIST_HEAD(&mvm->aux_roc_te_list);
@ -710,18 +703,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk); INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk);
INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk); INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk);
#ifdef CONFIG_PM
INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work);
#endif
INIT_DELAYED_WORK(&mvm->tdls_cs.dwork, iwl_mvm_tdls_ch_switch_work); INIT_DELAYED_WORK(&mvm->tdls_cs.dwork, iwl_mvm_tdls_ch_switch_work);
INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk); INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk);
INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk); INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk);
INIT_LIST_HEAD(&mvm->add_stream_txqs); INIT_LIST_HEAD(&mvm->add_stream_txqs);
spin_lock_init(&mvm->d0i3_tx_lock);
spin_lock_init(&mvm->refs_lock);
skb_queue_head_init(&mvm->d0i3_tx);
init_waitqueue_head(&mvm->d0i3_exit_waitq);
init_waitqueue_head(&mvm->rx_sync_waitq); init_waitqueue_head(&mvm->rx_sync_waitq);
atomic_set(&mvm->queue_sync_counter, 0); atomic_set(&mvm->queue_sync_counter, 0);
@ -744,7 +730,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
trans_cfg.no_reclaim_cmds = no_reclaim_cmds; trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
rb_size_default = IWL_AMSDU_2K; rb_size_default = IWL_AMSDU_2K;
else else
rb_size_default = IWL_AMSDU_4K; rb_size_default = IWL_AMSDU_4K;
@ -768,12 +754,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
trans_cfg.rx_buf_size = rb_size_default; trans_cfg.rx_buf_size = rb_size_default;
} }
BUILD_BUG_ON(sizeof(struct iwl_ldbg_config_cmd) !=
LDBG_CFG_COMMAND_SIZE);
trans->wide_cmd_header = true; trans->wide_cmd_header = true;
trans_cfg.bc_table_dword = trans_cfg.bc_table_dword =
mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_22560; mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_22560;
trans_cfg.command_groups = iwl_mvm_groups; trans_cfg.command_groups = iwl_mvm_groups;
trans_cfg.command_groups_size = ARRAY_SIZE(iwl_mvm_groups); trans_cfg.command_groups_size = ARRAY_SIZE(iwl_mvm_groups);
@ -832,13 +815,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
goto out_free; goto out_free;
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE);
err = iwl_run_init_mvm_ucode(mvm, true); err = iwl_run_init_mvm_ucode(mvm, true);
if (err && err != -ERFKILL) if (err && err != -ERFKILL)
iwl_fw_dbg_error_collect(&mvm->fwrt, FW_DBG_TRIGGER_DRIVER); iwl_fw_dbg_error_collect(&mvm->fwrt, FW_DBG_TRIGGER_DRIVER);
if (!iwlmvm_mod_params.init_dbg || !err) if (!iwlmvm_mod_params.init_dbg || !err)
iwl_mvm_stop_device(mvm); iwl_mvm_stop_device(mvm);
iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE);
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
if (err < 0) { if (err < 0) {
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err); IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err);
@ -870,11 +851,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
else else
memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx)); memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
/* The transport always starts with a taken reference, we can
* release it now if d0i3 is supported */
if (iwl_mvm_is_d0i3_supported(mvm))
iwl_trans_unref(mvm->trans);
iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx); iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx);
return op_mode; return op_mode;
@ -898,13 +874,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
int i; int i;
/* If d0i3 is supported, we have released the reference that
* the transport started with, so we should take it back now
* that we are leaving.
*/
if (iwl_mvm_is_d0i3_supported(mvm))
iwl_trans_ref(mvm->trans);
iwl_mvm_leds_exit(mvm); iwl_mvm_leds_exit(mvm);
iwl_mvm_thermal_exit(mvm); iwl_mvm_thermal_exit(mvm);
@ -931,7 +900,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
iwl_fw_runtime_free(&mvm->fwrt); iwl_fw_runtime_free(&mvm->fwrt);
mutex_destroy(&mvm->mutex); mutex_destroy(&mvm->mutex);
mutex_destroy(&mvm->d0i3_suspend_mutex);
ieee80211_free_hw(mvm->hw); ieee80211_free_hw(mvm->hw);
} }
@ -1020,7 +988,10 @@ static void iwl_mvm_rx_common(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt) struct iwl_rx_packet *pkt)
{ {
int i; int i;
union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt };
iwl_dbg_tlv_time_point(&mvm->fwrt,
IWL_FW_INI_TIME_POINT_FW_RSP_OR_NOTIF, &tp_data);
iwl_mvm_rx_check_trigger(mvm, pkt); iwl_mvm_rx_check_trigger(mvm, pkt);
/* /*
@ -1091,6 +1062,8 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
iwl_mvm_rx_queue_notif(mvm, napi, rxb, 0); iwl_mvm_rx_queue_notif(mvm, napi, rxb, 0);
else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE)) else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE))
iwl_mvm_rx_frame_release(mvm, napi, rxb, 0); iwl_mvm_rx_frame_release(mvm, napi, rxb, 0);
else if (cmd == WIDE_ID(LEGACY_GROUP, BAR_FRAME_RELEASE))
iwl_mvm_rx_bar_frame_release(mvm, napi, rxb, 0);
else if (cmd == WIDE_ID(DATA_PATH_GROUP, RX_NO_DATA_NOTIF)) else if (cmd == WIDE_ID(DATA_PATH_GROUP, RX_NO_DATA_NOTIF))
iwl_mvm_rx_monitor_no_data(mvm, napi, rxb, 0); iwl_mvm_rx_monitor_no_data(mvm, napi, rxb, 0);
else else
@ -1234,8 +1207,7 @@ static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
* Stop the device if we run OPERATIONAL firmware or if we are in the * Stop the device if we run OPERATIONAL firmware or if we are in the
* middle of the calibrations. * middle of the calibrations.
*/ */
return state && (mvm->fwrt.cur_fw_img != IWL_UCODE_INIT || return state && rfkill_safe_init_done;
rfkill_safe_init_done);
} }
static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
@ -1267,7 +1239,7 @@ static void iwl_mvm_reprobe_wk(struct work_struct *wk)
void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
{ {
iwl_abort_notification_waits(&mvm->notif_wait); iwl_abort_notification_waits(&mvm->notif_wait);
del_timer(&mvm->fwrt.dump.periodic_trig); iwl_dbg_tlv_del_timers(mvm->trans);
/* /*
* This is a bit racy, but worst case we tell mac80211 about * This is a bit racy, but worst case we tell mac80211 about
@ -1319,9 +1291,6 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
} else if (mvm->fwrt.cur_fw_img == IWL_UCODE_REGULAR && } else if (mvm->fwrt.cur_fw_img == IWL_UCODE_REGULAR &&
mvm->hw_registered && mvm->hw_registered &&
!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) { !test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) {
/* don't let the transport/FW power down */
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
if (mvm->fw->ucode_capa.error_log_size) { if (mvm->fw->ucode_capa.error_log_size) {
u32 src_size = mvm->fw->ucode_capa.error_log_size; u32 src_size = mvm->fw->ucode_capa.error_log_size;
u32 src_addr = mvm->fw->ucode_capa.error_log_addr; u32 src_addr = mvm->fw->ucode_capa.error_log_addr;
@ -1363,422 +1332,6 @@ static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode)
iwl_mvm_nic_restart(mvm, true); iwl_mvm_nic_restart(mvm, true);
} }
#ifdef CONFIG_PM
struct iwl_d0i3_iter_data {
struct iwl_mvm *mvm;
struct ieee80211_vif *connected_vif;
u8 ap_sta_id;
u8 vif_count;
u8 offloading_tid;
bool disable_offloading;
};
static bool iwl_mvm_disallow_offloading(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_d0i3_iter_data *iter_data)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvmsta;
u32 available_tids = 0;
u8 tid;
if (WARN_ON(vif->type != NL80211_IFTYPE_STATION ||
mvmvif->ap_sta_id == IWL_MVM_INVALID_STA))
return false;
mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, mvmvif->ap_sta_id);
if (!mvmsta)
return false;
spin_lock_bh(&mvmsta->lock);
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
/*
* in case of pending tx packets, don't use this tid
* for offloading in order to prevent reuse of the same
* qos seq counters.
*/
if (iwl_mvm_tid_queued(mvm, tid_data))
continue;
if (tid_data->state != IWL_AGG_OFF)
continue;
available_tids |= BIT(tid);
}
spin_unlock_bh(&mvmsta->lock);
/*
* disallow protocol offloading if we have no available tid
* (with no pending frames and no active aggregation,
* as we don't handle "holes" properly - the scheduler needs the
* frame's seq number and TFD index to match)
*/
if (!available_tids)
return true;
/* for simplicity, just use the first available tid */
iter_data->offloading_tid = ffs(available_tids) - 1;
return false;
}
static void iwl_mvm_enter_d0i3_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
struct iwl_d0i3_iter_data *data = _data;
struct iwl_mvm *mvm = data->mvm;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE;
IWL_DEBUG_RPM(mvm, "entering D0i3 - vif %pM\n", vif->addr);
if (vif->type != NL80211_IFTYPE_STATION ||
!vif->bss_conf.assoc)
return;
/*
* in case of pending tx packets or active aggregations,
* avoid offloading features in order to prevent reuse of
* the same qos seq counters.
*/
if (iwl_mvm_disallow_offloading(mvm, vif, data))
data->disable_offloading = true;
iwl_mvm_update_d0i3_power_mode(mvm, vif, true, flags);
iwl_mvm_send_proto_offload(mvm, vif, data->disable_offloading,
false, flags);
/*
* on init/association, mvm already configures POWER_TABLE_CMD
* and REPLY_MCAST_FILTER_CMD, so currently don't
* reconfigure them (we might want to use different
* params later on, though).
*/
data->ap_sta_id = mvmvif->ap_sta_id;
data->vif_count++;
/*
* no new commands can be sent at this stage, so it's safe
* to save the vif pointer during d0i3 entrance.
*/
data->connected_vif = vif;
}
static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm,
struct iwl_wowlan_config_cmd *cmd,
struct iwl_d0i3_iter_data *iter_data)
{
struct ieee80211_sta *ap_sta;
struct iwl_mvm_sta *mvm_ap_sta;
if (iter_data->ap_sta_id == IWL_MVM_INVALID_STA)
return;
rcu_read_lock();
ap_sta = rcu_dereference(mvm->fw_id_to_mac_id[iter_data->ap_sta_id]);
if (IS_ERR_OR_NULL(ap_sta))
goto out;
mvm_ap_sta = iwl_mvm_sta_from_mac80211(ap_sta);
cmd->is_11n_connection = ap_sta->ht_cap.ht_supported;
cmd->offloading_tid = iter_data->offloading_tid;
cmd->flags = ENABLE_L3_FILTERING | ENABLE_NBNS_FILTERING |
ENABLE_DHCP_FILTERING | ENABLE_STORE_BEACON;
/*
* The d0i3 uCode takes care of the nonqos counters,
* so configure only the qos seq ones.
*/
iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, cmd);
out:
rcu_read_unlock();
}
int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
{
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE;
int ret;
struct iwl_d0i3_iter_data d0i3_iter_data = {
.mvm = mvm,
};
struct iwl_wowlan_config_cmd wowlan_config_cmd = {
.wakeup_filter = cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME |
IWL_WOWLAN_WAKEUP_BEACON_MISS |
IWL_WOWLAN_WAKEUP_LINK_CHANGE),
};
struct iwl_d3_manager_config d3_cfg_cmd = {
.min_sleep_time = cpu_to_le32(1000),
.wakeup_flags = cpu_to_le32(IWL_WAKEUP_D3_CONFIG_FW_ERROR),
};
IWL_DEBUG_RPM(mvm, "MVM entering D0i3\n");
if (WARN_ON_ONCE(mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR))
return -EINVAL;
set_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
/*
* iwl_mvm_ref_sync takes a reference before checking the flag.
* so by checking there is no held reference we prevent a state
* in which iwl_mvm_ref_sync continues successfully while we
* configure the firmware to enter d0i3
*/
if (iwl_mvm_ref_taken(mvm)) {
IWL_DEBUG_RPM(mvm->trans, "abort d0i3 due to taken ref\n");
clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
wake_up(&mvm->d0i3_exit_waitq);
return 1;
}
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_enter_d0i3_iterator,
&d0i3_iter_data);
if (d0i3_iter_data.vif_count == 1) {
mvm->d0i3_ap_sta_id = d0i3_iter_data.ap_sta_id;
mvm->d0i3_offloading = !d0i3_iter_data.disable_offloading;
} else {
WARN_ON_ONCE(d0i3_iter_data.vif_count > 1);
mvm->d0i3_ap_sta_id = IWL_MVM_INVALID_STA;
mvm->d0i3_offloading = false;
}
iwl_mvm_pause_tcm(mvm, true);
/* make sure we have no running tx while configuring the seqno */
synchronize_net();
/* Flush the hw queues, in case something got queued during entry */
/* TODO new tx api */
if (iwl_mvm_has_new_tx_api(mvm)) {
WARN_ONCE(1, "d0i3: Need to implement flush TX queue\n");
} else {
ret = iwl_mvm_flush_tx_path(mvm, iwl_mvm_flushable_queues(mvm),
flags);
if (ret)
return ret;
}
/* configure wowlan configuration only if needed */
if (mvm->d0i3_ap_sta_id != IWL_MVM_INVALID_STA) {
/* wake on beacons only if beacon storing isn't supported */
if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BEACON_STORING))
wowlan_config_cmd.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_BCN_FILTERING);
iwl_mvm_wowlan_config_key_params(mvm,
d0i3_iter_data.connected_vif,
true, flags);
iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd,
&d0i3_iter_data);
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags,
sizeof(wowlan_config_cmd),
&wowlan_config_cmd);
if (ret)
return ret;
}
return iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD,
flags | CMD_MAKE_TRANS_IDLE,
sizeof(d3_cfg_cmd), &d3_cfg_cmd);
}
static void iwl_mvm_exit_d0i3_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
struct iwl_mvm *mvm = _data;
u32 flags = CMD_ASYNC | CMD_HIGH_PRIO;
IWL_DEBUG_RPM(mvm, "exiting D0i3 - vif %pM\n", vif->addr);
if (vif->type != NL80211_IFTYPE_STATION ||
!vif->bss_conf.assoc)
return;
iwl_mvm_update_d0i3_power_mode(mvm, vif, false, flags);
}
struct iwl_mvm_d0i3_exit_work_iter_data {
struct iwl_mvm *mvm;
struct iwl_wowlan_status *status;
u32 wakeup_reasons;
};
static void iwl_mvm_d0i3_exit_work_iter(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
struct iwl_mvm_d0i3_exit_work_iter_data *data = _data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u32 reasons = data->wakeup_reasons;
/* consider only the relevant station interface */
if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc ||
data->mvm->d0i3_ap_sta_id != mvmvif->ap_sta_id)
return;
if (reasons & IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)
iwl_mvm_connection_loss(data->mvm, vif, "D0i3");
else if (reasons & IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON)
ieee80211_beacon_loss(vif);
else
iwl_mvm_d0i3_update_keys(data->mvm, vif, data->status);
}
void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq)
{
struct ieee80211_sta *sta = NULL;
struct iwl_mvm_sta *mvm_ap_sta;
int i;
bool wake_queues = false;
lockdep_assert_held(&mvm->mutex);
spin_lock_bh(&mvm->d0i3_tx_lock);
if (mvm->d0i3_ap_sta_id == IWL_MVM_INVALID_STA)
goto out;
IWL_DEBUG_RPM(mvm, "re-enqueue packets\n");
/* get the sta in order to update seq numbers and re-enqueue skbs */
sta = rcu_dereference_protected(
mvm->fw_id_to_mac_id[mvm->d0i3_ap_sta_id],
lockdep_is_held(&mvm->mutex));
if (IS_ERR_OR_NULL(sta)) {
sta = NULL;
goto out;
}
if (mvm->d0i3_offloading && qos_seq) {
/* update qos seq numbers if offloading was enabled */
mvm_ap_sta = iwl_mvm_sta_from_mac80211(sta);
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
u16 seq = le16_to_cpu(qos_seq[i]);
/* firmware stores last-used one, we store next one */
seq += 0x10;
mvm_ap_sta->tid_data[i].seq_number = seq;
}
}
out:
/* re-enqueue (or drop) all packets */
while (!skb_queue_empty(&mvm->d0i3_tx)) {
struct sk_buff *skb = __skb_dequeue(&mvm->d0i3_tx);
if (!sta || iwl_mvm_tx_skb(mvm, skb, sta))
ieee80211_free_txskb(mvm->hw, skb);
/* if the skb_queue is not empty, we need to wake queues */
wake_queues = true;
}
clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
wake_up(&mvm->d0i3_exit_waitq);
mvm->d0i3_ap_sta_id = IWL_MVM_INVALID_STA;
if (wake_queues)
ieee80211_wake_queues(mvm->hw);
spin_unlock_bh(&mvm->d0i3_tx_lock);
}
static void iwl_mvm_d0i3_exit_work(struct work_struct *wk)
{
struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, d0i3_exit_work);
struct iwl_mvm_d0i3_exit_work_iter_data iter_data = {
.mvm = mvm,
};
struct iwl_wowlan_status *status;
u32 wakeup_reasons = 0;
__le16 *qos_seq = NULL;
mutex_lock(&mvm->mutex);
status = iwl_mvm_send_wowlan_get_status(mvm);
if (IS_ERR_OR_NULL(status)) {
/* set to NULL so we don't need to check before kfree'ing */
status = NULL;
goto out;
}
wakeup_reasons = le32_to_cpu(status->wakeup_reasons);
qos_seq = status->qos_seq_ctr;
IWL_DEBUG_RPM(mvm, "wakeup reasons: 0x%x\n", wakeup_reasons);
iter_data.wakeup_reasons = wakeup_reasons;
iter_data.status = status;
ieee80211_iterate_active_interfaces(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_d0i3_exit_work_iter,
&iter_data);
out:
iwl_mvm_d0i3_enable_tx(mvm, qos_seq);
IWL_DEBUG_INFO(mvm, "d0i3 exit completed (wakeup reasons: 0x%x)\n",
wakeup_reasons);
/* qos_seq might point inside resp_pkt, so free it only now */
kfree(status);
/* the FW might have updated the regdomain */
iwl_mvm_update_changed_regdom(mvm);
iwl_mvm_resume_tcm(mvm);
iwl_mvm_unref(mvm, IWL_MVM_REF_EXIT_WORK);
mutex_unlock(&mvm->mutex);
}
int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm)
{
u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE |
CMD_WAKE_UP_TRANS;
int ret;
IWL_DEBUG_RPM(mvm, "MVM exiting D0i3\n");
if (WARN_ON_ONCE(mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR))
return -EINVAL;
mutex_lock(&mvm->d0i3_suspend_mutex);
if (test_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags)) {
IWL_DEBUG_RPM(mvm, "Deferring d0i3 exit until resume\n");
__set_bit(D0I3_PENDING_WAKEUP, &mvm->d0i3_suspend_flags);
mutex_unlock(&mvm->d0i3_suspend_mutex);
return 0;
}
mutex_unlock(&mvm->d0i3_suspend_mutex);
ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, flags, 0, NULL);
if (ret)
goto out;
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_exit_d0i3_iterator,
mvm);
out:
schedule_work(&mvm->d0i3_exit_work);
return ret;
}
int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode)
{
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
iwl_mvm_ref(mvm, IWL_MVM_REF_EXIT_WORK);
return _iwl_mvm_exit_d0i3(mvm);
}
#define IWL_MVM_D0I3_OPS \
.enter_d0i3 = iwl_mvm_enter_d0i3, \
.exit_d0i3 = iwl_mvm_exit_d0i3,
#else /* CONFIG_PM */
#define IWL_MVM_D0I3_OPS
#endif /* CONFIG_PM */
#define IWL_MVM_COMMON_OPS \ #define IWL_MVM_COMMON_OPS \
/* these could be differentiated */ \ /* these could be differentiated */ \
.async_cb = iwl_mvm_async_cb, \ .async_cb = iwl_mvm_async_cb, \
@ -1789,7 +1342,6 @@ int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode)
.nic_error = iwl_mvm_nic_error, \ .nic_error = iwl_mvm_nic_error, \
.cmd_queue_full = iwl_mvm_cmd_queue_full, \ .cmd_queue_full = iwl_mvm_cmd_queue_full, \
.nic_config = iwl_mvm_nic_config, \ .nic_config = iwl_mvm_nic_config, \
IWL_MVM_D0I3_OPS \
/* as we only register one, these MUST be common! */ \ /* as we only register one, these MUST be common! */ \
.start = iwl_op_mode_mvm_start, \ .start = iwl_op_mode_mvm_start, \
.stop = iwl_op_mode_mvm_stop .stop = iwl_op_mode_mvm_stop

View File

@ -289,8 +289,17 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
if (ctxt->ref == 0) { if (ctxt->ref == 0) {
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
struct ieee80211_supported_band *sband = NULL;
enum nl80211_band band = NL80211_BAND_2GHZ;
while (!sband && band < NUM_NL80211_BANDS)
sband = mvm->hw->wiphy->bands[band++];
if (WARN_ON(!sband))
return;
chan = &sband->channels[0];
chan = &mvm->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[0];
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
iwl_mvm_phy_ctxt_changed(mvm, ctxt, &chandef, 1, 1); iwl_mvm_phy_ctxt_changed(mvm, ctxt, &chandef, 1, 1);
} }

View File

@ -127,12 +127,11 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
static static
void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm, void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct iwl_beacon_filter_cmd *cmd, struct iwl_beacon_filter_cmd *cmd)
bool d0i3)
{ {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (vif->bss_conf.cqm_rssi_thold && !d0i3) { if (vif->bss_conf.cqm_rssi_thold) {
cmd->bf_energy_delta = cmd->bf_energy_delta =
cpu_to_le32(vif->bss_conf.cqm_rssi_hyst); cpu_to_le32(vif->bss_conf.cqm_rssi_hyst);
/* fw uses an absolute value for this */ /* fw uses an absolute value for this */
@ -849,8 +848,7 @@ iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct iwl_beacon_filter_cmd *cmd, struct iwl_beacon_filter_cmd *cmd,
u32 cmd_flags, u32 cmd_flags)
bool d0i3)
{ {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret; int ret;
@ -859,13 +857,11 @@ static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
vif->type != NL80211_IFTYPE_STATION || vif->p2p) vif->type != NL80211_IFTYPE_STATION || vif->p2p)
return 0; return 0;
iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd, d0i3); iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd);
if (!d0i3)
iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd); iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd);
ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd, cmd_flags); ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd, cmd_flags);
/* don't change bf_enabled in case of temporary d0i3 configuration */ if (!ret)
if (!ret && !d0i3)
mvmvif->bf_data.bf_enabled = true; mvmvif->bf_data.bf_enabled = true;
return ret; return ret;
@ -880,12 +876,12 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
.bf_enable_beacon_filter = cpu_to_le32(1), .bf_enable_beacon_filter = cpu_to_le32(1),
}; };
return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags, false); return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags);
} }
static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
u32 flags, bool d0i3) u32 flags)
{ {
struct iwl_beacon_filter_cmd cmd = {}; struct iwl_beacon_filter_cmd cmd = {};
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@ -896,8 +892,7 @@ static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags); ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags);
/* don't change bf_enabled in case of temporary d0i3 configuration */ if (!ret)
if (!ret && !d0i3)
mvmvif->bf_data.bf_enabled = false; mvmvif->bf_data.bf_enabled = false;
return ret; return ret;
@ -907,7 +902,7 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
u32 flags) u32 flags)
{ {
return _iwl_mvm_disable_beacon_filter(mvm, vif, flags, false); return _iwl_mvm_disable_beacon_filter(mvm, vif, flags);
} }
static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm) static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm)
@ -958,7 +953,7 @@ static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm,
!vif->bss_conf.ps || !vif->bss_conf.ps ||
iwl_mvm_vif_low_latency(mvmvif)); iwl_mvm_vif_low_latency(mvmvif));
return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false); return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0);
} }
int iwl_mvm_power_update_ps(struct iwl_mvm *mvm) int iwl_mvm_power_update_ps(struct iwl_mvm *mvm)
@ -1022,58 +1017,3 @@ int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
return 0; return 0;
} }
int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool enable, u32 flags)
{
int ret;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mac_power_cmd cmd = {};
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
return 0;
if (!vif->bss_conf.assoc)
return 0;
iwl_mvm_power_build_cmd(mvm, vif, &cmd, !enable);
iwl_mvm_power_log(mvm, &cmd);
#ifdef CONFIG_IWLWIFI_DEBUGFS
memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd));
#endif
ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, flags,
sizeof(cmd), &cmd);
if (ret)
return ret;
/* configure beacon filtering */
if (mvmvif != mvm->bf_allowed_vif)
return 0;
if (enable) {
struct iwl_beacon_filter_cmd cmd_bf = {
IWL_BF_CMD_CONFIG_D0I3,
.bf_enable_beacon_filter = cpu_to_le32(1),
};
/*
* When beacon storing is supported - disable beacon filtering
* altogether - the latest beacon will be sent when exiting d0i3
*/
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BEACON_STORING))
ret = _iwl_mvm_disable_beacon_filter(mvm, vif, flags,
true);
else
ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf,
flags, true);
} else {
if (mvmvif->bf_data.bf_enabled)
ret = iwl_mvm_enable_beacon_filter(mvm, vif, flags);
else
ret = iwl_mvm_disable_beacon_filter(mvm, vif, flags);
}
return ret;
}

View File

@ -193,7 +193,7 @@ rs_fw_vht_set_enabled_rates(const struct ieee80211_sta *sta,
int i, highest_mcs; int i, highest_mcs;
for (i = 0; i < sta->rx_nss; i++) { for (i = 0; i < sta->rx_nss; i++) {
if (i == MAX_NSS) if (i == IWL_TLC_NSS_MAX)
break; break;
highest_mcs = rs_fw_vht_highest_rx_mcs_index(vht_cap, i + 1); highest_mcs = rs_fw_vht_highest_rx_mcs_index(vht_cap, i + 1);
@ -204,9 +204,10 @@ rs_fw_vht_set_enabled_rates(const struct ieee80211_sta *sta,
if (sta->bandwidth == IEEE80211_STA_RX_BW_20) if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
supp &= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9); supp &= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9);
cmd->ht_rates[i][0] = cpu_to_le16(supp); cmd->ht_rates[i][IWL_TLC_HT_BW_NONE_160] = cpu_to_le16(supp);
if (sta->bandwidth == IEEE80211_STA_RX_BW_160) if (sta->bandwidth == IEEE80211_STA_RX_BW_160)
cmd->ht_rates[i][1] = cmd->ht_rates[i][0]; cmd->ht_rates[i][IWL_TLC_HT_BW_160] =
cmd->ht_rates[i][IWL_TLC_HT_BW_NONE_160];
} }
} }
@ -241,7 +242,7 @@ rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta,
le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160); le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160);
int i; int i;
for (i = 0; i < sta->rx_nss && i < MAX_NSS; i++) { for (i = 0; i < sta->rx_nss && i < IWL_TLC_NSS_MAX; i++) {
u16 _mcs_160 = (mcs_160 >> (2 * i)) & 0x3; u16 _mcs_160 = (mcs_160 >> (2 * i)) & 0x3;
u16 _mcs_80 = (mcs_80 >> (2 * i)) & 0x3; u16 _mcs_80 = (mcs_80 >> (2 * i)) & 0x3;
u16 _tx_mcs_160 = (tx_mcs_160 >> (2 * i)) & 0x3; u16 _tx_mcs_160 = (tx_mcs_160 >> (2 * i)) & 0x3;
@ -255,7 +256,7 @@ rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta,
} }
if (_mcs_80 > _tx_mcs_80) if (_mcs_80 > _tx_mcs_80)
_mcs_80 = _tx_mcs_80; _mcs_80 = _tx_mcs_80;
cmd->ht_rates[i][0] = cmd->ht_rates[i][IWL_TLC_HT_BW_NONE_160] =
cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_80)); cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_80));
/* If one side doesn't support - mark both as not supporting */ /* If one side doesn't support - mark both as not supporting */
@ -266,7 +267,7 @@ rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta,
} }
if (_mcs_160 > _tx_mcs_160) if (_mcs_160 > _tx_mcs_160)
_mcs_160 = _tx_mcs_160; _mcs_160 = _tx_mcs_160;
cmd->ht_rates[i][1] = cmd->ht_rates[i][IWL_TLC_HT_BW_160] =
cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_160)); cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_160));
} }
} }
@ -300,8 +301,10 @@ static void rs_fw_set_supp_rates(struct ieee80211_sta *sta,
rs_fw_vht_set_enabled_rates(sta, vht_cap, cmd); rs_fw_vht_set_enabled_rates(sta, vht_cap, cmd);
} else if (ht_cap->ht_supported) { } else if (ht_cap->ht_supported) {
cmd->mode = IWL_TLC_MNG_MODE_HT; cmd->mode = IWL_TLC_MNG_MODE_HT;
cmd->ht_rates[0][0] = cpu_to_le16(ht_cap->mcs.rx_mask[0]); cmd->ht_rates[IWL_TLC_NSS_1][IWL_TLC_HT_BW_NONE_160] =
cmd->ht_rates[1][0] = cpu_to_le16(ht_cap->mcs.rx_mask[1]); cpu_to_le16(ht_cap->mcs.rx_mask[0]);
cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_HT_BW_NONE_160] =
cpu_to_le16(ht_cap->mcs.rx_mask[1]);
} }
} }

View File

@ -3079,11 +3079,7 @@ static void __iwl_mvm_rs_tx_status(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv; struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
/* Treat uninitialized rate scaling data same as non-existing. */ if (!lq_sta->pers.drv) {
if (!lq_sta) {
IWL_DEBUG_RATE(mvm, "Station rate scaling not created yet.\n");
return;
} else if (!lq_sta->pers.drv) {
IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n"); IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n");
return; return;
} }
@ -3342,7 +3338,7 @@ static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm,
if (num_of_ant(ant) == 1) if (num_of_ant(ant) == 1)
lq_cmd->single_stream_ant_msk = ant; lq_cmd->single_stream_ant_msk = ant;
if (!mvm->trans->cfg->gen2) if (!mvm->trans->trans_cfg->gen2)
lq_cmd->agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; lq_cmd->agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
else else
lq_cmd->agg_frame_cnt_limit = lq_cmd->agg_frame_cnt_limit =

View File

@ -8,6 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -29,6 +30,8 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -349,7 +352,6 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
u32 rate_n_flags; u32 rate_n_flags;
u32 rx_pkt_status; u32 rx_pkt_status;
u8 crypt_len = 0; u8 crypt_len = 0;
bool take_ref;
phy_info = &mvm->last_phy_info; phy_info = &mvm->last_phy_info;
rx_res = (struct iwl_rx_mpdu_res_start *)pkt->data; rx_res = (struct iwl_rx_mpdu_res_start *)pkt->data;
@ -557,22 +559,8 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
ieee80211_is_probe_resp(hdr->frame_control))) ieee80211_is_probe_resp(hdr->frame_control)))
rx_status->boottime_ns = ktime_get_boottime_ns(); rx_status->boottime_ns = ktime_get_boottime_ns();
/* Take a reference briefly to kick off a d0i3 entry delay so
* we can handle bursts of RX packets without toggling the
* state too often. But don't do this for beacons if we are
* going to idle because the beacon filtering changes we make
* cause the firmware to send us collateral beacons. */
take_ref = !(test_bit(STATUS_TRANS_GOING_IDLE, &mvm->trans->status) &&
ieee80211_is_beacon(hdr->frame_control));
if (take_ref)
iwl_mvm_ref(mvm, IWL_MVM_REF_RX);
iwl_mvm_pass_packet_to_mac80211(mvm, sta, napi, skb, hdr, len, iwl_mvm_pass_packet_to_mac80211(mvm, sta, napi, skb, hdr, len,
crypt_len, rxb); crypt_len, rxb);
if (take_ref)
iwl_mvm_unref(mvm, IWL_MVM_REF_RX);
} }
struct iwl_mvm_stat_data { struct iwl_mvm_stat_data {

View File

@ -349,7 +349,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
!(status & IWL_RX_MPDU_RES_STATUS_TTAK_OK)) !(status & IWL_RX_MPDU_RES_STATUS_TTAK_OK))
return 0; return 0;
if (mvm->trans->cfg->gen2 && if (mvm->trans->trans_cfg->gen2 &&
!(status & RX_MPDU_RES_STATUS_MIC_OK)) !(status & RX_MPDU_RES_STATUS_MIC_OK))
stats->flag |= RX_FLAG_MMIC_ERROR; stats->flag |= RX_FLAG_MMIC_ERROR;
@ -366,7 +366,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
if (pkt_flags & FH_RSCSR_RADA_EN) { if (pkt_flags & FH_RSCSR_RADA_EN) {
stats->flag |= RX_FLAG_ICV_STRIPPED; stats->flag |= RX_FLAG_ICV_STRIPPED;
if (mvm->trans->cfg->gen2) if (mvm->trans->trans_cfg->gen2)
stats->flag |= RX_FLAG_MMIC_STRIPPED; stats->flag |= RX_FLAG_MMIC_STRIPPED;
} }
@ -377,8 +377,16 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
stats->flag |= RX_FLAG_DECRYPTED; stats->flag |= RX_FLAG_DECRYPTED;
return 0; return 0;
default: default:
/* Expected in monitor (not having the keys) */ /*
if (!mvm->monitor_on) * Sometimes we can get frames that were not decrypted
* because the firmware didn't have the keys yet. This can
* happen after connection where we can get multicast frames
* before the GTK is installed.
* Silently drop those frames.
* Also drop un-decrypted frames in monitor mode.
*/
if (!is_multicast_ether_addr(hdr->addr1) &&
!mvm->monitor_on && net_ratelimit())
IWL_ERR(mvm, "Unhandled alg: 0x%x\n", status); IWL_ERR(mvm, "Unhandled alg: 0x%x\n", status);
} }
@ -781,6 +789,55 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
wake_up(&mvm->rx_sync_waitq); wake_up(&mvm->rx_sync_waitq);
} }
static void iwl_mvm_oldsn_workaround(struct iwl_mvm *mvm,
struct ieee80211_sta *sta, int tid,
struct iwl_mvm_reorder_buffer *buffer,
u32 reorder, u32 gp2, int queue)
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
if (gp2 != buffer->consec_oldsn_ampdu_gp2) {
/* we have a new (A-)MPDU ... */
/*
* reset counter to 0 if we didn't have any oldsn in
* the last A-MPDU (as detected by GP2 being identical)
*/
if (!buffer->consec_oldsn_prev_drop)
buffer->consec_oldsn_drops = 0;
/* either way, update our tracking state */
buffer->consec_oldsn_ampdu_gp2 = gp2;
} else if (buffer->consec_oldsn_prev_drop) {
/*
* tracking state didn't change, and we had an old SN
* indication before - do nothing in this case, we
* already noted this one down and are waiting for the
* next A-MPDU (by GP2)
*/
return;
}
/* return unless this MPDU has old SN */
if (!(reorder & IWL_RX_MPDU_REORDER_BA_OLD_SN))
return;
/* update state */
buffer->consec_oldsn_prev_drop = 1;
buffer->consec_oldsn_drops++;
/* if limit is reached, send del BA and reset state */
if (buffer->consec_oldsn_drops == IWL_MVM_AMPDU_CONSEC_DROPS_DELBA) {
IWL_WARN(mvm,
"reached %d old SN frames from %pM on queue %d, stopping BA session on TID %d\n",
IWL_MVM_AMPDU_CONSEC_DROPS_DELBA,
sta->addr, queue, tid);
ieee80211_stop_rx_ba_session(mvmsta->vif, BIT(tid), sta->addr);
buffer->consec_oldsn_prev_drop = 0;
buffer->consec_oldsn_drops = 0;
}
}
/* /*
* Returns true if the MPDU was buffered\dropped, false if it should be passed * Returns true if the MPDU was buffered\dropped, false if it should be passed
* to upper layer. * to upper layer.
@ -792,6 +849,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
struct sk_buff *skb, struct sk_buff *skb,
struct iwl_rx_mpdu_desc *desc) struct iwl_rx_mpdu_desc *desc)
{ {
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr = iwl_mvm_skb_get_hdr(skb); struct ieee80211_hdr *hdr = iwl_mvm_skb_get_hdr(skb);
struct iwl_mvm_sta *mvm_sta; struct iwl_mvm_sta *mvm_sta;
struct iwl_mvm_baid_data *baid_data; struct iwl_mvm_baid_data *baid_data;
@ -894,6 +952,9 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
min_sn, IWL_MVM_RELEASE_SEND_RSS_SYNC); min_sn, IWL_MVM_RELEASE_SEND_RSS_SYNC);
} }
iwl_mvm_oldsn_workaround(mvm, sta, tid, buffer, reorder,
rx_status->device_timestamp, queue);
/* drop any oudated packets */ /* drop any oudated packets */
if (ieee80211_sn_less(sn, buffer->head_sn)) if (ieee80211_sn_less(sn, buffer->head_sn))
goto drop; goto drop;
@ -1504,7 +1565,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))) if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
return; return;
if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) { if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
rate_n_flags = le32_to_cpu(desc->v3.rate_n_flags); rate_n_flags = le32_to_cpu(desc->v3.rate_n_flags);
channel = desc->v3.channel; channel = desc->v3.channel;
gp2_on_air_rise = le32_to_cpu(desc->v3.gp2_on_air_rise); gp2_on_air_rise = le32_to_cpu(desc->v3.gp2_on_air_rise);
@ -1605,7 +1666,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
if (likely(!(phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD))) { if (likely(!(phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD))) {
u64 tsf_on_air_rise; u64 tsf_on_air_rise;
if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) if (mvm->trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_22560)
tsf_on_air_rise = le64_to_cpu(desc->v3.tsf_on_air_rise); tsf_on_air_rise = le64_to_cpu(desc->v3.tsf_on_air_rise);
else else
tsf_on_air_rise = le64_to_cpu(desc->v1.tsf_on_air_rise); tsf_on_air_rise = le64_to_cpu(desc->v1.tsf_on_air_rise);
@ -1731,7 +1793,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
*qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; *qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
if (mvm->trans->cfg->device_family == if (mvm->trans->trans_cfg->device_family ==
IWL_DEVICE_FAMILY_9000) { IWL_DEVICE_FAMILY_9000) {
iwl_mvm_flip_address(hdr->addr3); iwl_mvm_flip_address(hdr->addr3);
@ -1960,3 +2022,42 @@ void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
le16_to_cpu(release->nssn), le16_to_cpu(release->nssn),
queue, 0); queue, 0);
} }
void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_bar_frame_release *release = (void *)pkt->data;
unsigned int baid = le32_get_bits(release->ba_info,
IWL_BAR_FRAME_RELEASE_BAID_MASK);
unsigned int nssn = le32_get_bits(release->ba_info,
IWL_BAR_FRAME_RELEASE_NSSN_MASK);
unsigned int sta_id = le32_get_bits(release->sta_tid,
IWL_BAR_FRAME_RELEASE_STA_MASK);
unsigned int tid = le32_get_bits(release->sta_tid,
IWL_BAR_FRAME_RELEASE_TID_MASK);
struct iwl_mvm_baid_data *baid_data;
if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID ||
baid >= ARRAY_SIZE(mvm->baid_map)))
return;
rcu_read_lock();
baid_data = rcu_dereference(mvm->baid_map[baid]);
if (!baid_data) {
IWL_DEBUG_RX(mvm,
"Got valid BAID %d but not allocated, invalid BAR release!\n",
baid);
goto out;
}
if (WARN(tid != baid_data->tid || sta_id != baid_data->sta_id,
"baid 0x%x is mapped to sta:%d tid:%d, but BAR release received for sta:%d tid:%d\n",
baid, baid_data->sta_id, baid_data->tid, sta_id,
tid))
goto out;
iwl_mvm_release_frames_from_notif(mvm, napi, baid, nssn, queue, 0);
out:
rcu_read_unlock();
}

View File

@ -77,7 +77,10 @@
#define IWL_SCAN_DWELL_FRAGMENTED 44 #define IWL_SCAN_DWELL_FRAGMENTED 44
#define IWL_SCAN_DWELL_EXTENDED 90 #define IWL_SCAN_DWELL_EXTENDED 90
#define IWL_SCAN_NUM_OF_FRAGS 3 #define IWL_SCAN_NUM_OF_FRAGS 3
#define IWL_SCAN_LAST_2_4_CHN 14
#define IWL_SCAN_BAND_5_2 0
#define IWL_SCAN_BAND_2_4 1
/* adaptive dwell max budget time [TU] for full scan */ /* adaptive dwell max budget time [TU] for full scan */
#define IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300 #define IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300
@ -512,7 +515,6 @@ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm,
mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR; mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
ieee80211_scan_completed(mvm->hw, &info); ieee80211_scan_completed(mvm->hw, &info);
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
cancel_delayed_work(&mvm->scan_timeout_dwork); cancel_delayed_work(&mvm->scan_timeout_dwork);
iwl_mvm_resume_tcm(mvm); iwl_mvm_resume_tcm(mvm);
} else { } else {
@ -957,11 +959,24 @@ static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm,
return flags; return flags;
} }
static void
iwl_mvm_scan_set_legacy_probe_req(struct iwl_scan_probe_req_v1 *p_req,
struct iwl_scan_probe_req *src_p_req)
{
int i;
p_req->mac_header = src_p_req->mac_header;
for (i = 0; i < SCAN_NUM_BAND_PROBE_DATA_V_1; i++)
p_req->band_data[i] = src_p_req->band_data[i];
p_req->common_data = src_p_req->common_data;
memcpy(p_req->buf, src_p_req->buf, sizeof(p_req->buf));
}
static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_mvm_scan_params *params) struct iwl_mvm_scan_params *params)
{ {
struct iwl_scan_req_lmac *cmd = mvm->scan_cmd; struct iwl_scan_req_lmac *cmd = mvm->scan_cmd;
struct iwl_scan_probe_req *preq = struct iwl_scan_probe_req_v1 *preq =
(void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) * (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) *
mvm->fw->ucode_capa.n_scan_channels); mvm->fw->ucode_capa.n_scan_channels);
u32 ssid_bitmap = 0; u32 ssid_bitmap = 0;
@ -1031,7 +1046,7 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_lmac_scan_cfg_channels(mvm, params->channels, iwl_mvm_lmac_scan_cfg_channels(mvm, params->channels,
params->n_channels, ssid_bitmap, cmd); params->n_channels, ssid_bitmap, cmd);
*preq = params->preq; iwl_mvm_scan_set_legacy_probe_req(preq, &params->preq);
return 0; return 0;
} }
@ -1205,7 +1220,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
cmd_size = sizeof(struct iwl_scan_config); cmd_size = sizeof(struct iwl_scan_config);
else else
cmd_size = sizeof(struct iwl_scan_config_v1); cmd_size = sizeof(struct iwl_scan_config_v1);
cmd_size += mvm->fw->ucode_capa.n_scan_channels; cmd_size += num_channels;
cfg = kzalloc(cmd_size, GFP_KERNEL); cfg = kzalloc(cmd_size, GFP_KERNEL);
if (!cfg) if (!cfg)
@ -1385,9 +1400,17 @@ iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm,
for (i = 0; i < n_channels; i++) { for (i = 0; i < n_channels; i++) {
channel_cfg[i].flags = cpu_to_le32(ssid_bitmap); channel_cfg[i].flags = cpu_to_le32(ssid_bitmap);
channel_cfg[i].channel_num = channels[i]->hw_value; channel_cfg[i].v1.channel_num = channels[i]->hw_value;
channel_cfg[i].iter_count = 1; if (iwl_mvm_is_scan_ext_chan_supported(mvm)) {
channel_cfg[i].iter_interval = 0; channel_cfg[i].v2.band =
channels[i]->hw_value <= IWL_SCAN_LAST_2_4_CHN ?
IWL_SCAN_BAND_2_4 : IWL_SCAN_BAND_5_2;
channel_cfg[i].v2.iter_count = 1;
channel_cfg[i].v2.iter_interval = 0;
} else {
channel_cfg[i].v1.iter_count = 1;
channel_cfg[i].v1.iter_interval = 0;
}
} }
} }
@ -1477,9 +1500,12 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_scan_req_umac *cmd = mvm->scan_cmd; struct iwl_scan_req_umac *cmd = mvm->scan_cmd;
struct iwl_scan_umac_chan_param *chan_param; struct iwl_scan_umac_chan_param *chan_param;
void *cmd_data = iwl_mvm_get_scan_req_umac_data(mvm); void *cmd_data = iwl_mvm_get_scan_req_umac_data(mvm);
struct iwl_scan_req_umac_tail *sec_part = cmd_data + void *sec_part = cmd_data + sizeof(struct iwl_scan_channel_cfg_umac) *
sizeof(struct iwl_scan_channel_cfg_umac) *
mvm->fw->ucode_capa.n_scan_channels; mvm->fw->ucode_capa.n_scan_channels;
struct iwl_scan_req_umac_tail_v2 *tail_v2 =
(struct iwl_scan_req_umac_tail_v2 *)sec_part;
struct iwl_scan_req_umac_tail_v1 *tail_v1;
struct iwl_ssid_ie *direct_scan;
int uid, i; int uid, i;
u32 ssid_bitmap = 0; u32 ssid_bitmap = 0;
u8 channel_flags = 0; u8 channel_flags = 0;
@ -1541,18 +1567,12 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
chan_param->flags = channel_flags; chan_param->flags = channel_flags;
chan_param->count = params->n_channels; chan_param->count = params->n_channels;
iwl_scan_build_ssids(params, sec_part->direct_scan, &ssid_bitmap);
iwl_mvm_umac_scan_cfg_channels(mvm, params->channels,
params->n_channels, ssid_bitmap,
cmd_data);
for (i = 0; i < params->n_scan_plans; i++) { for (i = 0; i < params->n_scan_plans; i++) {
struct cfg80211_sched_scan_plan *scan_plan = struct cfg80211_sched_scan_plan *scan_plan =
&params->scan_plans[i]; &params->scan_plans[i];
sec_part->schedule[i].iter_count = scan_plan->iterations; tail_v2->schedule[i].iter_count = scan_plan->iterations;
sec_part->schedule[i].interval = tail_v2->schedule[i].interval =
cpu_to_le16(scan_plan->interval); cpu_to_le16(scan_plan->interval);
} }
@ -1562,12 +1582,24 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* For example, when regular scan is requested the driver sets one scan * For example, when regular scan is requested the driver sets one scan
* plan with one iteration. * plan with one iteration.
*/ */
if (!sec_part->schedule[i - 1].iter_count) if (!tail_v2->schedule[i - 1].iter_count)
sec_part->schedule[i - 1].iter_count = 0xff; tail_v2->schedule[i - 1].iter_count = 0xff;
sec_part->delay = cpu_to_le16(params->delay); tail_v2->delay = cpu_to_le16(params->delay);
sec_part->preq = params->preq;
if (iwl_mvm_is_scan_ext_chan_supported(mvm)) {
tail_v2->preq = params->preq;
direct_scan = tail_v2->direct_scan;
} else {
tail_v1 = (struct iwl_scan_req_umac_tail_v1 *)sec_part;
iwl_mvm_scan_set_legacy_probe_req(&tail_v1->preq,
&params->preq);
direct_scan = tail_v1->direct_scan;
}
iwl_scan_build_ssids(params, direct_scan, &ssid_bitmap);
iwl_mvm_umac_scan_cfg_channels(mvm, params->channels,
params->n_channels, ssid_bitmap,
cmd_data);
return 0; return 0;
} }
@ -1758,7 +1790,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n"); IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n");
mvm->scan_status |= IWL_MVM_SCAN_REGULAR; mvm->scan_status |= IWL_MVM_SCAN_REGULAR;
mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif); mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);
iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
schedule_delayed_work(&mvm->scan_timeout_dwork, schedule_delayed_work(&mvm->scan_timeout_dwork,
msecs_to_jiffies(SCAN_TIMEOUT)); msecs_to_jiffies(SCAN_TIMEOUT));
@ -1884,7 +1915,6 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
memcpy(info.tsf_bssid, mvm->scan_vif->bssid, ETH_ALEN); memcpy(info.tsf_bssid, mvm->scan_vif->bssid, ETH_ALEN);
ieee80211_scan_completed(mvm->hw, &info); ieee80211_scan_completed(mvm->hw, &info);
mvm->scan_vif = NULL; mvm->scan_vif = NULL;
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
cancel_delayed_work(&mvm->scan_timeout_dwork); cancel_delayed_work(&mvm->scan_timeout_dwork);
iwl_mvm_resume_tcm(mvm); iwl_mvm_resume_tcm(mvm);
} else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) { } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
@ -1909,8 +1939,6 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
mvm->last_ebs_successful = false; mvm->last_ebs_successful = false;
mvm->scan_uid_status[uid] = 0; mvm->scan_uid_status[uid] = 0;
iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_SCAN_COMPLETE);
} }
void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm, void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
@ -1999,6 +2027,7 @@ static int iwl_mvm_scan_stop_wait(struct iwl_mvm *mvm, int type)
int iwl_mvm_scan_size(struct iwl_mvm *mvm) int iwl_mvm_scan_size(struct iwl_mvm *mvm)
{ {
int base_size = IWL_SCAN_REQ_UMAC_SIZE_V1; int base_size = IWL_SCAN_REQ_UMAC_SIZE_V1;
int tail_size;
if (iwl_mvm_is_adaptive_dwell_v2_supported(mvm)) if (iwl_mvm_is_adaptive_dwell_v2_supported(mvm))
base_size = IWL_SCAN_REQ_UMAC_SIZE_V8; base_size = IWL_SCAN_REQ_UMAC_SIZE_V8;
@ -2007,16 +2036,21 @@ int iwl_mvm_scan_size(struct iwl_mvm *mvm)
else if (iwl_mvm_cdb_scan_api(mvm)) else if (iwl_mvm_cdb_scan_api(mvm))
base_size = IWL_SCAN_REQ_UMAC_SIZE_V6; base_size = IWL_SCAN_REQ_UMAC_SIZE_V6;
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
if (iwl_mvm_is_scan_ext_chan_supported(mvm))
tail_size = sizeof(struct iwl_scan_req_umac_tail_v2);
else
tail_size = sizeof(struct iwl_scan_req_umac_tail_v1);
return base_size + return base_size +
sizeof(struct iwl_scan_channel_cfg_umac) * sizeof(struct iwl_scan_channel_cfg_umac) *
mvm->fw->ucode_capa.n_scan_channels + mvm->fw->ucode_capa.n_scan_channels +
sizeof(struct iwl_scan_req_umac_tail); tail_size;
}
return sizeof(struct iwl_scan_req_lmac) + return sizeof(struct iwl_scan_req_lmac) +
sizeof(struct iwl_scan_channel_cfg_lmac) * sizeof(struct iwl_scan_channel_cfg_lmac) *
mvm->fw->ucode_capa.n_scan_channels + mvm->fw->ucode_capa.n_scan_channels +
sizeof(struct iwl_scan_probe_req); sizeof(struct iwl_scan_probe_req_v1);
} }
/* /*
@ -2099,10 +2133,6 @@ out:
mvm->scan_status &= ~type; mvm->scan_status &= ~type;
if (type == IWL_MVM_SCAN_REGULAR) { if (type == IWL_MVM_SCAN_REGULAR) {
/* Since the rx handler won't do anything now, we have
* to release the scan reference here.
*/
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
cancel_delayed_work(&mvm->scan_timeout_dwork); cancel_delayed_work(&mvm->scan_timeout_dwork);
if (notify) { if (notify) {
struct cfg80211_scan_info info = { struct cfg80211_scan_info info = {

View File

@ -67,14 +67,6 @@
#include "sta.h" #include "sta.h"
#include "rs.h" #include "rs.h"
static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm);
static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
u32 sta_id,
struct ieee80211_key_conf *key, bool mcast,
u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags,
u8 key_offset, bool mfp);
/* /*
* New version of ADD_STA_sta command added new fields at the end of the * New version of ADD_STA_sta command added new fields at the end of the
* structure, so sending the size of the relevant API's structure is enough to * structure, so sending the size of the relevant API's structure is enough to
@ -1612,7 +1604,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id, mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id,
mvmvif->color); mvmvif->color);
mvm_sta->vif = vif; mvm_sta->vif = vif;
if (!mvm->trans->cfg->gen2) if (!mvm->trans->trans_cfg->gen2)
mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF; mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
else else
mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF; mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF;
@ -1895,10 +1887,6 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
/* unassoc - go ahead - remove the AP STA now */ /* unassoc - go ahead - remove the AP STA now */
mvmvif->ap_sta_id = IWL_MVM_INVALID_STA; mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
/* clear d0i3_ap_sta_id if no longer relevant */
if (mvm->d0i3_ap_sta_id == sta_id)
mvm->d0i3_ap_sta_id = IWL_MVM_INVALID_STA;
} }
/* /*
@ -1966,7 +1954,7 @@ static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 *queue,
u8 sta_id, u8 fifo) u8 sta_id, u8 fifo)
{ {
unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
mvm->cfg->base_params->wd_timeout : mvm->trans->trans_cfg->base_params->wd_timeout :
IWL_WATCHDOG_DISABLED; IWL_WATCHDOG_DISABLED;
if (iwl_mvm_has_new_tx_api(mvm)) { if (iwl_mvm_has_new_tx_api(mvm)) {
@ -2771,13 +2759,6 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
spin_lock_bh(&mvmsta->lock); spin_lock_bh(&mvmsta->lock);
/* possible race condition - we entered D0i3 while starting agg */
if (test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status)) {
spin_unlock_bh(&mvmsta->lock);
IWL_ERR(mvm, "Entered D0i3 while starting Tx agg\n");
return -EIO;
}
/* /*
* Note the possible cases: * Note the possible cases:
* 1. An enabled TXQ - TXQ needs to become agg'ed * 1. An enabled TXQ - TXQ needs to become agg'ed
@ -2832,7 +2813,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* to align the wrap around of ssn so we compare relevant values. * to align the wrap around of ssn so we compare relevant values.
*/ */
normalized_ssn = tid_data->ssn; normalized_ssn = tid_data->ssn;
if (mvm->trans->cfg->gen2) if (mvm->trans->trans_cfg->gen2)
normalized_ssn &= 0xff; normalized_ssn &= 0xff;
if (normalized_ssn == tid_data->next_reclaimed) { if (normalized_ssn == tid_data->next_reclaimed) {
@ -3872,7 +3853,7 @@ u16 iwl_mvm_tid_queued(struct iwl_mvm *mvm, struct iwl_mvm_tid_data *tid_data)
* In 22000 HW, the next_reclaimed index is only 8 bit, so we'll need * In 22000 HW, the next_reclaimed index is only 8 bit, so we'll need
* to align the wrap around of ssn so we compare relevant values. * to align the wrap around of ssn so we compare relevant values.
*/ */
if (mvm->trans->cfg->gen2) if (mvm->trans->trans_cfg->gen2)
sn &= 0xff; sn &= 0xff;
return ieee80211_sn_sub(sn, tid_data->next_reclaimed); return ieee80211_sn_sub(sn, tid_data->next_reclaimed);

View File

@ -205,19 +205,10 @@ void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int; u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int;
/*
* iwl_mvm_protect_session() reads directly from the device
* (the system time), so make sure it is available.
*/
if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_TDLS))
return;
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
/* Protect the session to hear the TDLS setup response on the channel */ /* Protect the session to hear the TDLS setup response on the channel */
iwl_mvm_protect_session(mvm, vif, duration, duration, 100, true); iwl_mvm_protect_session(mvm, vif, duration, duration, 100, true);
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_TDLS);
} }
static const char * static const char *

View File

@ -106,10 +106,8 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
* in the case that the time event actually completed in the firmware * in the case that the time event actually completed in the firmware
* (which is handled in iwl_mvm_te_handle_notif). * (which is handled in iwl_mvm_te_handle_notif).
*/ */
if (test_and_clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status)) clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
iwl_mvm_unref(mvm, IWL_MVM_REF_ROC); clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
if (test_and_clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
iwl_mvm_unref(mvm, IWL_MVM_REF_ROC_AUX);
synchronize_net(); synchronize_net();
@ -357,7 +355,6 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) { if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) {
set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
iwl_mvm_ref(mvm, IWL_MVM_REF_ROC);
ieee80211_ready_on_channel(mvm->hw); ieee80211_ready_on_channel(mvm->hw);
} else if (te_data->id == TE_CHANNEL_SWITCH_PERIOD) { } else if (te_data->id == TE_CHANNEL_SWITCH_PERIOD) {
iwl_mvm_te_handle_notify_csa(mvm, te_data, notif); iwl_mvm_te_handle_notify_csa(mvm, te_data, notif);
@ -405,7 +402,6 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
} else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) { } else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status); set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
te_data->running = true; te_data->running = true;
iwl_mvm_ref(mvm, IWL_MVM_REF_ROC_AUX);
ieee80211_ready_on_channel(mvm->hw); /* Start TE */ ieee80211_ready_on_channel(mvm->hw); /* Start TE */
} else { } else {
IWL_DEBUG_TE(mvm, IWL_DEBUG_TE(mvm,

View File

@ -5,7 +5,7 @@
* *
* GPL LICENSE SUMMARY * GPL LICENSE SUMMARY
* *
* Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014, 2019 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
* *
@ -27,7 +27,7 @@
* *
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014, 2019 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
* All rights reserved. * All rights reserved.
@ -298,16 +298,8 @@ static void check_exit_ctkill(struct work_struct *work)
if (__iwl_mvm_mac_start(mvm)) if (__iwl_mvm_mac_start(mvm))
goto reschedule; goto reschedule;
/* make sure the device is available for direct read/writes */
if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_CHECK_CTKILL)) {
__iwl_mvm_mac_stop(mvm);
goto reschedule;
}
ret = iwl_mvm_get_temp(mvm, &temp); ret = iwl_mvm_get_temp(mvm, &temp);
iwl_mvm_unref(mvm, IWL_MVM_REF_CHECK_CTKILL);
__iwl_mvm_mac_stop(mvm); __iwl_mvm_mac_stop(mvm);
if (ret) if (ret)

View File

@ -546,7 +546,7 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
hdr->frame_control); hdr->frame_control);
} }
if (mvm->trans->cfg->device_family >= if (mvm->trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_22560) { IWL_DEVICE_FAMILY_22560) {
struct iwl_tx_cmd_gen3 *cmd = (void *)dev_cmd->payload; struct iwl_tx_cmd_gen3 *cmd = (void *)dev_cmd->payload;
@ -1169,8 +1169,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
schedule_work(&mvm->add_stream_wk); schedule_work(&mvm->add_stream_wk);
} }
IWL_DEBUG_TX(mvm, "TX to [%d|%d] Q:%d - seq: 0x%x\n", mvmsta->sta_id, IWL_DEBUG_TX(mvm, "TX to [%d|%d] Q:%d - seq: 0x%x len %d\n",
tid, txq_id, IEEE80211_SEQ_TO_SN(seq_number)); mvmsta->sta_id, tid, txq_id,
IEEE80211_SEQ_TO_SN(seq_number), skb->len);
/* From now on, we cannot access info->control */ /* From now on, we cannot access info->control */
iwl_mvm_skb_prepare_status(skb, dev_cmd); iwl_mvm_skb_prepare_status(skb, dev_cmd);
@ -1271,7 +1272,7 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
* to align the wrap around of ssn so we compare relevant values. * to align the wrap around of ssn so we compare relevant values.
*/ */
normalized_ssn = tid_data->ssn; normalized_ssn = tid_data->ssn;
if (mvm->trans->cfg->gen2) if (mvm->trans->trans_cfg->gen2)
normalized_ssn &= 0xff; normalized_ssn &= 0xff;
if (normalized_ssn != tid_data->next_reclaimed) if (normalized_ssn != tid_data->next_reclaimed)

View File

@ -88,17 +88,11 @@ int iwl_mvm_send_cmd(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd)
* the mutex, this ensures we don't try to send two * the mutex, this ensures we don't try to send two
* (or more) synchronous commands at a time. * (or more) synchronous commands at a time.
*/ */
if (!(cmd->flags & CMD_ASYNC)) { if (!(cmd->flags & CMD_ASYNC))
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
if (!(cmd->flags & CMD_SEND_IN_IDLE))
iwl_mvm_ref(mvm, IWL_MVM_REF_SENDING_CMD);
}
ret = iwl_trans_send_cmd(mvm->trans, cmd); ret = iwl_trans_send_cmd(mvm->trans, cmd);
if (!(cmd->flags & (CMD_ASYNC | CMD_SEND_IN_IDLE)))
iwl_mvm_unref(mvm, IWL_MVM_REF_SENDING_CMD);
/* /*
* If the caller wants the SKB, then don't hide any problems, the * If the caller wants the SKB, then don't hide any problems, the
* caller might access the response buffer which will be NULL if * caller might access the response buffer which will be NULL if
@ -537,7 +531,7 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u8 lmac_num)
/* reset the device */ /* reset the device */
iwl_trans_sw_reset(trans); iwl_trans_sw_reset(trans);
err = iwl_finish_nic_init(trans); err = iwl_finish_nic_init(trans, trans->trans_cfg);
if (err) if (err)
return; return;
} }
@ -945,8 +939,9 @@ unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
{ {
struct iwl_fw_dbg_trigger_tlv *trigger; struct iwl_fw_dbg_trigger_tlv *trigger;
struct iwl_fw_dbg_trigger_txq_timer *txq_timer; struct iwl_fw_dbg_trigger_txq_timer *txq_timer;
unsigned int default_timeout = unsigned int default_timeout = cmd_q ?
cmd_q ? IWL_DEF_WD_TIMEOUT : mvm->cfg->base_params->wd_timeout; IWL_DEF_WD_TIMEOUT :
mvm->trans->trans_cfg->base_params->wd_timeout;
if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TXQ_TIMERS)) { if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TXQ_TIMERS)) {
/* /*
@ -990,7 +985,7 @@ unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
return default_timeout; return default_timeout;
default: default:
WARN_ON(1); WARN_ON(1);
return mvm->cfg->base_params->wd_timeout; return mvm->trans->trans_cfg->base_params->wd_timeout;
} }
} }
@ -1436,7 +1431,7 @@ u32 iwl_mvm_get_systime(struct iwl_mvm *mvm)
{ {
u32 reg_addr = DEVICE_SYSTEM_TIME_REG; u32 reg_addr = DEVICE_SYSTEM_TIME_REG;
if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000 && if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000 &&
mvm->trans->cfg->gp2_reg_addr) mvm->trans->cfg->gp2_reg_addr)
reg_addr = mvm->trans->cfg->gp2_reg_addr; reg_addr = mvm->trans->cfg->gp2_reg_addr;

View File

@ -96,7 +96,7 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
cpu_to_le64(trans_pcie->rxq->bd_dma); cpu_to_le64(trans_pcie->rxq->bd_dma);
/* Configure debug, for integration */ /* Configure debug, for integration */
if (!trans->dbg.ini_valid) if (!iwl_trans_dbg_ini_valid(trans))
iwl_pcie_alloc_fw_monitor(trans, 0); iwl_pcie_alloc_fw_monitor(trans, 0);
if (trans->dbg.num_blocks) { if (trans->dbg.num_blocks) {
prph_sc_ctrl->hwm_cfg.hwm_base_addr = prph_sc_ctrl->hwm_cfg.hwm_base_addr =
@ -180,7 +180,7 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL,
CSR_AUTO_FUNC_BOOT_ENA); CSR_AUTO_FUNC_BOOT_ENA);
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1); iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1);
else else
iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT); iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT);

View File

@ -65,7 +65,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/acpi.h> #include <linux/acpi.h>
@ -73,6 +72,7 @@
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-drv.h" #include "iwl-drv.h"
#include "iwl-prph.h"
#include "internal.h" #include "internal.h"
#define IWL_PCI_DEVICE(dev, subdev, cfg) \ #define IWL_PCI_DEVICE(dev, subdev, cfg) \
@ -994,15 +994,22 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
const struct iwl_cfg *cfg_7265d __maybe_unused = NULL; const struct iwl_cfg *cfg_7265d __maybe_unused = NULL;
struct iwl_trans *iwl_trans; struct iwl_trans *iwl_trans;
unsigned long flags;
int ret; int ret;
if (WARN_ONCE(!cfg->csr, "CSR addresses aren't configured\n")) iwl_trans = iwl_trans_pcie_alloc(pdev, ent, &cfg->trans);
return -EINVAL;
iwl_trans = iwl_trans_pcie_alloc(pdev, ent, cfg);
if (IS_ERR(iwl_trans)) if (IS_ERR(iwl_trans))
return PTR_ERR(iwl_trans); return PTR_ERR(iwl_trans);
/* the trans_cfg should never change, so set it now */
iwl_trans->trans_cfg = &cfg->trans;
if (WARN_ONCE(!iwl_trans->trans_cfg->csr,
"CSR addresses aren't configured\n")) {
ret = -EINVAL;
goto out_free_trans;
}
#if IS_ENABLED(CONFIG_IWLMVM) #if IS_ENABLED(CONFIG_IWLMVM)
/* /*
* special-case 7265D, it has the same PCI IDs. * special-case 7265D, it has the same PCI IDs.
@ -1018,29 +1025,70 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
else if (cfg == &iwl7265_n_cfg) else if (cfg == &iwl7265_n_cfg)
cfg_7265d = &iwl7265d_n_cfg; cfg_7265d = &iwl7265d_n_cfg;
if (cfg_7265d && if (cfg_7265d &&
(iwl_trans->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D) { (iwl_trans->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D)
cfg = cfg_7265d; cfg = cfg_7265d;
iwl_trans->cfg = cfg_7265d;
iwl_trans->hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID);
if (cfg == &iwlax210_2ax_cfg_so_hr_a0) {
if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_TY) {
cfg = &iwlax210_2ax_cfg_ty_gf_a0;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) {
cfg = &iwlax210_2ax_cfg_so_jf_a0;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) {
cfg = &iwlax211_2ax_cfg_so_gf_a0;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF4)) {
cfg = &iwlax411_2ax_cfg_so_gf4_a0;
} }
} else if (cfg == &iwl_ax101_cfg_qu_hr) {
if ((CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) ||
(CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR1))) {
cfg = &iwl22000_2ax_cfg_qnj_hr_b0;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) {
cfg = &iwl_ax101_cfg_qu_hr;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) {
cfg = &iwl22000_2ax_cfg_jf;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HRCDB)) {
IWL_ERR(iwl_trans, "RF ID HRCDB is not supported\n");
return -EINVAL;
} else {
IWL_ERR(iwl_trans, "Unrecognized RF ID 0x%08x\n",
CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id));
return -EINVAL;
}
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
((cfg != &iwl_ax200_cfg_cc &&
cfg != &killer1650x_2ax_cfg &&
cfg != &killer1650w_2ax_cfg &&
cfg != &iwl_ax201_cfg_quz_hr) ||
iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0)) {
u32 hw_status;
if (iwl_trans->cfg->rf_id && cfg == &iwl22000_2ac_cfg_hr_cdb && hw_status = iwl_read_prph(iwl_trans, UMAG_GEN_HW_STATUS);
iwl_trans->hw_rev != CSR_HW_REV_TYPE_HR_CDB) { if (CSR_HW_RF_STEP(iwl_trans->hw_rf_id) == SILICON_B_STEP)
u32 rf_id_chp = CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id); /*
u32 jf_chp_id = CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF); * b step fw is the same for physical card and fpga
u32 hr_chp_id = CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR); */
cfg = &iwl22000_2ax_cfg_qnj_hr_b0;
if (rf_id_chp == jf_chp_id) { else if ((hw_status & UMAG_GEN_HW_IS_FPGA) &&
if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ) CSR_HW_RF_STEP(iwl_trans->hw_rf_id) == SILICON_A_STEP) {
cfg = &iwl9560_2ac_cfg_qnj_jf_b0; cfg = &iwl22000_2ax_cfg_qnj_hr_a0_f0;
else } else {
cfg = &iwl22000_2ac_cfg_jf; /*
} else if (rf_id_chp == hr_chp_id) { * a step no FPGA
if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ) */
cfg = &iwl22000_2ax_cfg_qnj_hr_a0;
else
cfg = &iwl22000_2ac_cfg_hr; cfg = &iwl22000_2ac_cfg_hr;
} }
iwl_trans->cfg = cfg;
} }
/* /*
@ -1050,22 +1098,18 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
* thing to do to support Qu C-step. * thing to do to support Qu C-step.
*/ */
if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QU_C0) { if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QU_C0) {
if (iwl_trans->cfg == &iwl_ax101_cfg_qu_hr) if (cfg == &iwl_ax101_cfg_qu_hr)
iwl_trans->cfg = &iwl_ax101_cfg_qu_c0_hr_b0; cfg = &iwl_ax101_cfg_qu_c0_hr_b0;
else if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr) else if (cfg == &iwl_ax201_cfg_qu_hr)
iwl_trans->cfg = &iwl_ax201_cfg_qu_c0_hr_b0; cfg = &iwl_ax201_cfg_qu_c0_hr_b0;
else if (iwl_trans->cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0) else if (cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
iwl_trans->cfg = &iwl9461_2ac_cfg_qu_c0_jf_b0; cfg = &iwl9461_2ac_cfg_qu_c0_jf_b0;
else if (iwl_trans->cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0) else if (cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
iwl_trans->cfg = &iwl9462_2ac_cfg_qu_c0_jf_b0; cfg = &iwl9462_2ac_cfg_qu_c0_jf_b0;
else if (iwl_trans->cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0) else if (cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
iwl_trans->cfg = &iwl9560_2ac_cfg_qu_c0_jf_b0; cfg = &iwl9560_2ac_cfg_qu_c0_jf_b0;
else if (iwl_trans->cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0) else if (cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
iwl_trans->cfg = &iwl9560_2ac_160_cfg_qu_c0_jf_b0; cfg = &iwl9560_2ac_160_cfg_qu_c0_jf_b0;
else if (iwl_trans->cfg == &killer1650s_2ax_cfg_qu_b0_hr_b0)
iwl_trans->cfg = &killer1650s_2ax_cfg_qu_c0_hr_b0;
else if (iwl_trans->cfg == &killer1650i_2ax_cfg_qu_b0_hr_b0)
iwl_trans->cfg = &killer1650i_2ax_cfg_qu_c0_hr_b0;
} }
/* same thing for QuZ... */ /* same thing for QuZ... */
@ -1085,6 +1129,23 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
} }
#endif #endif
/* now set the real cfg we decided to use */
iwl_trans->cfg = cfg;
if (iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_8000 &&
iwl_trans_grab_nic_access(iwl_trans, &flags)) {
u32 hw_step;
hw_step = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG);
hw_step |= ENABLE_WFPM;
iwl_write_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG, hw_step);
hw_step = iwl_read_prph_no_grab(iwl_trans, CNVI_AUX_MISC_CHIP);
hw_step = (hw_step >> HW_STEP_LOCATION_BITS) & 0xF;
if (hw_step == 0x3)
iwl_trans->hw_rev = (iwl_trans->hw_rev & 0xFFFFFFF3) |
(SILICON_C_STEP << 2);
iwl_trans_release_nic_access(iwl_trans, &flags);
}
pci_set_drvdata(pdev, iwl_trans); pci_set_drvdata(pdev, iwl_trans);
iwl_trans->drv = iwl_drv_start(iwl_trans); iwl_trans->drv = iwl_drv_start(iwl_trans);
@ -1097,25 +1158,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* register transport layer debugfs here */ /* register transport layer debugfs here */
iwl_trans_pcie_dbgfs_register(iwl_trans); iwl_trans_pcie_dbgfs_register(iwl_trans);
/* if RTPM is in use, enable it in our device */
if (iwl_trans->runtime_pm_mode != IWL_PLAT_PM_MODE_DISABLED) {
/* We explicitly set the device to active here to
* clear contingent errors.
*/
pm_runtime_set_active(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev,
iwlwifi_mod_params.d0i3_timeout);
pm_runtime_use_autosuspend(&pdev->dev);
/* We are not supposed to call pm_runtime_allow() by
* ourselves, but let userspace enable runtime PM via
* sysfs. However, since we don't enable this from
* userspace yet, we need to allow/forbid() ourselves.
*/
pm_runtime_allow(&pdev->dev);
}
/* The PCI device starts with a reference taken and we are /* The PCI device starts with a reference taken and we are
* supposed to release it here. But to simplify the * supposed to release it here. But to simplify the
* interaction with the opmode, we don't do it now, but let * interaction with the opmode, we don't do it now, but let
@ -1133,15 +1175,6 @@ static void iwl_pci_remove(struct pci_dev *pdev)
{ {
struct iwl_trans *trans = pci_get_drvdata(pdev); struct iwl_trans *trans = pci_get_drvdata(pdev);
/* if RTPM was in use, restore it to the state before probe */
if (trans->runtime_pm_mode != IWL_PLAT_PM_MODE_DISABLED) {
/* We should not call forbid here, but we do for now.
* Check the comment to pm_runtime_allow() in
* iwl_pci_probe().
*/
pm_runtime_forbid(trans->dev);
}
iwl_drv_stop(trans->drv); iwl_drv_stop(trans->drv);
iwl_trans_pcie_free(trans); iwl_trans_pcie_free(trans);
@ -1199,164 +1232,9 @@ static int iwl_pci_resume(struct device *device)
return 0; return 0;
} }
int iwl_pci_fw_enter_d0i3(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret;
if (test_bit(STATUS_FW_ERROR, &trans->status))
return 0;
set_bit(STATUS_TRANS_GOING_IDLE, &trans->status);
/* config the fw */
ret = iwl_op_mode_enter_d0i3(trans->op_mode);
if (ret == 1) {
IWL_DEBUG_RPM(trans, "aborting d0i3 entrance\n");
clear_bit(STATUS_TRANS_GOING_IDLE, &trans->status);
return -EBUSY;
}
if (ret)
goto err;
ret = wait_event_timeout(trans_pcie->d0i3_waitq,
test_bit(STATUS_TRANS_IDLE, &trans->status),
msecs_to_jiffies(IWL_TRANS_IDLE_TIMEOUT));
if (!ret) {
IWL_ERR(trans, "Timeout entering D0i3\n");
ret = -ETIMEDOUT;
goto err;
}
clear_bit(STATUS_TRANS_GOING_IDLE, &trans->status);
return 0;
err:
clear_bit(STATUS_TRANS_GOING_IDLE, &trans->status);
iwl_trans_fw_error(trans);
return ret;
}
int iwl_pci_fw_exit_d0i3(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret;
/* sometimes a D0i3 entry is not followed through */
if (!test_bit(STATUS_TRANS_IDLE, &trans->status))
return 0;
/* config the fw */
ret = iwl_op_mode_exit_d0i3(trans->op_mode);
if (ret)
goto err;
/* we clear STATUS_TRANS_IDLE only when D0I3_END command is completed */
ret = wait_event_timeout(trans_pcie->d0i3_waitq,
!test_bit(STATUS_TRANS_IDLE, &trans->status),
msecs_to_jiffies(IWL_TRANS_IDLE_TIMEOUT));
if (!ret) {
IWL_ERR(trans, "Timeout exiting D0i3\n");
ret = -ETIMEDOUT;
goto err;
}
return 0;
err:
clear_bit(STATUS_TRANS_IDLE, &trans->status);
iwl_trans_fw_error(trans);
return ret;
}
#ifdef CONFIG_IWLWIFI_PCIE_RTPM
static int iwl_pci_runtime_suspend(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
struct iwl_trans *trans = pci_get_drvdata(pdev);
int ret;
IWL_DEBUG_RPM(trans, "entering runtime suspend\n");
if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
ret = iwl_pci_fw_enter_d0i3(trans);
if (ret < 0)
return ret;
}
trans->system_pm_mode = IWL_PLAT_PM_MODE_D0I3;
iwl_trans_d3_suspend(trans, false, false);
return 0;
}
static int iwl_pci_runtime_resume(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
struct iwl_trans *trans = pci_get_drvdata(pdev);
enum iwl_d3_status d3_status;
IWL_DEBUG_RPM(trans, "exiting runtime suspend (resume)\n");
iwl_trans_d3_resume(trans, &d3_status, false, false);
if (test_bit(STATUS_DEVICE_ENABLED, &trans->status))
return iwl_pci_fw_exit_d0i3(trans);
return 0;
}
static int iwl_pci_system_prepare(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
struct iwl_trans *trans = pci_get_drvdata(pdev);
IWL_DEBUG_RPM(trans, "preparing for system suspend\n");
/* This is called before entering system suspend and before
* the runtime resume is called. Set the suspending flag to
* prevent the wakelock from being taken.
*/
trans->suspending = true;
/* Wake the device up from runtime suspend before going to
* platform suspend. This is needed because we don't know
* whether wowlan any is set and, if it's not, mac80211 will
* disconnect (in which case, we can't be in D0i3).
*/
pm_runtime_resume(device);
return 0;
}
static void iwl_pci_system_complete(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
struct iwl_trans *trans = pci_get_drvdata(pdev);
IWL_DEBUG_RPM(trans, "completing system suspend\n");
/* This is called as a counterpart to the prepare op. It is
* called either when suspending fails or when suspend
* completed successfully. Now there's no risk of grabbing
* the wakelock anymore, so we can release the suspending
* flag.
*/
trans->suspending = false;
}
#endif /* CONFIG_IWLWIFI_PCIE_RTPM */
static const struct dev_pm_ops iwl_dev_pm_ops = { static const struct dev_pm_ops iwl_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(iwl_pci_suspend, SET_SYSTEM_SLEEP_PM_OPS(iwl_pci_suspend,
iwl_pci_resume) iwl_pci_resume)
#ifdef CONFIG_IWLWIFI_PCIE_RTPM
SET_RUNTIME_PM_OPS(iwl_pci_runtime_suspend,
iwl_pci_runtime_resume,
NULL)
.prepare = iwl_pci_system_prepare,
.complete = iwl_pci_system_complete,
#endif /* CONFIG_IWLWIFI_PCIE_RTPM */
}; };
#define IWL_PM_OPS (&iwl_dev_pm_ops) #define IWL_PM_OPS (&iwl_dev_pm_ops)

View File

@ -253,7 +253,8 @@ struct iwl_dma_ptr {
*/ */
static inline int iwl_queue_inc_wrap(struct iwl_trans *trans, int index) static inline int iwl_queue_inc_wrap(struct iwl_trans *trans, int index)
{ {
return ++index & (trans->cfg->base_params->max_tfd_queue_size - 1); return ++index &
(trans->trans_cfg->base_params->max_tfd_queue_size - 1);
} }
/** /**
@ -263,7 +264,7 @@ static inline int iwl_queue_inc_wrap(struct iwl_trans *trans, int index)
static inline __le16 iwl_get_closed_rb_stts(struct iwl_trans *trans, static inline __le16 iwl_get_closed_rb_stts(struct iwl_trans *trans,
struct iwl_rxq *rxq) struct iwl_rxq *rxq)
{ {
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) { if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
__le16 *rb_stts = rxq->rb_stts; __le16 *rb_stts = rxq->rb_stts;
return READ_ONCE(*rb_stts); return READ_ONCE(*rb_stts);
@ -280,7 +281,8 @@ static inline __le16 iwl_get_closed_rb_stts(struct iwl_trans *trans,
*/ */
static inline int iwl_queue_dec_wrap(struct iwl_trans *trans, int index) static inline int iwl_queue_dec_wrap(struct iwl_trans *trans, int index)
{ {
return --index & (trans->cfg->base_params->max_tfd_queue_size - 1); return --index &
(trans->trans_cfg->base_params->max_tfd_queue_size - 1);
} }
struct iwl_cmd_meta { struct iwl_cmd_meta {
@ -556,9 +558,10 @@ struct iwl_trans_pcie {
void __iomem *hw_base; void __iomem *hw_base;
bool ucode_write_complete; bool ucode_write_complete;
bool sx_complete;
wait_queue_head_t ucode_write_waitq; wait_queue_head_t ucode_write_waitq;
wait_queue_head_t wait_command_queue; wait_queue_head_t wait_command_queue;
wait_queue_head_t d0i3_waitq; wait_queue_head_t sx_waitq;
u8 page_offs, dev_cmd_offs; u8 page_offs, dev_cmd_offs;
@ -581,7 +584,6 @@ struct iwl_trans_pcie {
/*protect hw register */ /*protect hw register */
spinlock_t reg_lock; spinlock_t reg_lock;
bool cmd_hold_nic_awake; bool cmd_hold_nic_awake;
bool ref_cmd_in_flight;
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
struct cont_rec fw_mon_data; struct cont_rec fw_mon_data;
@ -635,9 +637,10 @@ iwl_trans_pcie_get_trans(struct iwl_trans_pcie *trans_pcie)
* Convention: trans API functions: iwl_trans_pcie_XXX * Convention: trans API functions: iwl_trans_pcie_XXX
* Other functions: iwl_pcie_XXX * Other functions: iwl_pcie_XXX
*/ */
struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, struct iwl_trans
*iwl_trans_pcie_alloc(struct pci_dev *pdev,
const struct pci_device_id *ent, const struct pci_device_id *ent,
const struct iwl_cfg *cfg); const struct iwl_cfg_trans_params *cfg_trans);
void iwl_trans_pcie_free(struct iwl_trans *trans); void iwl_trans_pcie_free(struct iwl_trans *trans);
/***************************************************** /*****************************************************
@ -697,6 +700,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
struct iwl_rx_cmd_buffer *rxb); struct iwl_rx_cmd_buffer *rxb);
void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
struct sk_buff_head *skbs); struct sk_buff_head *skbs);
void iwl_trans_pcie_set_q_ptrs(struct iwl_trans *trans, int txq_id, int ptr);
void iwl_trans_pcie_tx_reset(struct iwl_trans *trans); void iwl_trans_pcie_tx_reset(struct iwl_trans *trans);
void iwl_pcie_gen2_update_byte_tbl(struct iwl_trans_pcie *trans_pcie, void iwl_pcie_gen2_update_byte_tbl(struct iwl_trans_pcie *trans_pcie,
struct iwl_txq *txq, u16 byte_cnt, struct iwl_txq *txq, u16 byte_cnt,
@ -705,7 +709,7 @@ void iwl_pcie_gen2_update_byte_tbl(struct iwl_trans_pcie *trans_pcie,
static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_trans *trans, void *_tfd, static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_trans *trans, void *_tfd,
u8 idx) u8 idx)
{ {
if (trans->cfg->use_tfh) { if (trans->trans_cfg->use_tfh) {
struct iwl_tfh_tfd *tfd = _tfd; struct iwl_tfh_tfd *tfd = _tfd;
struct iwl_tfh_tb *tb = &tfd->tbs[idx]; struct iwl_tfh_tb *tb = &tfd->tbs[idx];
@ -911,7 +915,7 @@ static inline void *iwl_pcie_get_tfd(struct iwl_trans *trans,
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
if (trans->cfg->use_tfh) if (trans->trans_cfg->use_tfh)
idx = iwl_pcie_get_cmd_index(txq, idx); idx = iwl_pcie_get_cmd_index(txq, idx);
return txq->tfds + trans_pcie->tfd_size * idx; return txq->tfds + trans_pcie->tfd_size * idx;
@ -955,7 +959,7 @@ static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
MSIX_HW_INT_CAUSES_REG_RF_KILL); MSIX_HW_INT_CAUSES_REG_RF_KILL);
} }
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_9000) { if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000) {
/* /*
* On 9000-series devices this bit isn't enabled by default, so * On 9000-series devices this bit isn't enabled by default, so
* when we power down the device we need set the bit to allow it * when we power down the device we need set the bit to allow it
@ -1045,7 +1049,7 @@ static inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans,
static inline bool iwl_pcie_dbg_on(struct iwl_trans *trans) static inline bool iwl_pcie_dbg_on(struct iwl_trans *trans)
{ {
return (trans->dbg.dest_tlv || trans->dbg.ini_valid); return (trans->dbg.dest_tlv || iwl_trans_dbg_ini_valid(trans));
} }
void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state); void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state);
@ -1058,9 +1062,6 @@ void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans);
static inline void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) { } static inline void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) { }
#endif #endif
int iwl_pci_fw_exit_d0i3(struct iwl_trans *trans);
int iwl_pci_fw_enter_d0i3(struct iwl_trans *trans);
void iwl_pcie_rx_allocator_work(struct work_struct *data); void iwl_pcie_rx_allocator_work(struct work_struct *data);
/* common functions that are used by gen2 transport */ /* common functions that are used by gen2 transport */
@ -1113,10 +1114,11 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
struct iwl_device_cmd *dev_cmd, int txq_id); struct iwl_device_cmd *dev_cmd, int txq_id);
int iwl_trans_pcie_gen2_send_hcmd(struct iwl_trans *trans, int iwl_trans_pcie_gen2_send_hcmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd); struct iwl_host_cmd *cmd);
void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans);
bool low_power); void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans);
void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power);
void iwl_pcie_gen2_txq_unmap(struct iwl_trans *trans, int txq_id); void iwl_pcie_gen2_txq_unmap(struct iwl_trans *trans, int txq_id);
void iwl_pcie_gen2_tx_free(struct iwl_trans *trans); void iwl_pcie_gen2_tx_free(struct iwl_trans *trans);
void iwl_pcie_gen2_tx_stop(struct iwl_trans *trans); void iwl_pcie_gen2_tx_stop(struct iwl_trans *trans);
void iwl_pcie_d3_complete_suspend(struct iwl_trans *trans,
bool test, bool reset);
#endif /* __iwl_trans_int_pcie_h__ */ #endif /* __iwl_trans_int_pcie_h__ */

View File

@ -200,12 +200,12 @@ static inline __le32 iwl_pcie_dma_addr2rbd_ptr(dma_addr_t dma_addr)
*/ */
int iwl_pcie_rx_stop(struct iwl_trans *trans) int iwl_pcie_rx_stop(struct iwl_trans *trans)
{ {
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) { if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
/* TODO: remove this for 22560 once fw does it */ /* TODO: remove this for 22560 once fw does it */
iwl_write_umac_prph(trans, RFH_RXF_DMA_CFG_GEN3, 0); iwl_write_umac_prph(trans, RFH_RXF_DMA_CFG_GEN3, 0);
return iwl_poll_umac_prph_bit(trans, RFH_GEN_STATUS_GEN3, return iwl_poll_umac_prph_bit(trans, RFH_GEN_STATUS_GEN3,
RXF_DMA_IDLE, RXF_DMA_IDLE, 1000); RXF_DMA_IDLE, RXF_DMA_IDLE, 1000);
} else if (trans->cfg->mq_rx_supported) { } else if (trans->trans_cfg->mq_rx_supported) {
iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0); iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0);
return iwl_poll_prph_bit(trans, RFH_GEN_STATUS, return iwl_poll_prph_bit(trans, RFH_GEN_STATUS,
RXF_DMA_IDLE, RXF_DMA_IDLE, 1000); RXF_DMA_IDLE, RXF_DMA_IDLE, 1000);
@ -232,7 +232,7 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
* 1. shadow registers aren't enabled * 1. shadow registers aren't enabled
* 2. there is a chance that the NIC is asleep * 2. there is a chance that the NIC is asleep
*/ */
if (!trans->cfg->base_params->shadow_reg_enable && if (!trans->trans_cfg->base_params->shadow_reg_enable &&
test_bit(STATUS_TPOWER_PMI, &trans->status)) { test_bit(STATUS_TPOWER_PMI, &trans->status)) {
reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); reg = iwl_read32(trans, CSR_UCODE_DRV_GP1);
@ -240,18 +240,18 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
IWL_DEBUG_INFO(trans, "Rx queue requesting wakeup, GP1 = 0x%x\n", IWL_DEBUG_INFO(trans, "Rx queue requesting wakeup, GP1 = 0x%x\n",
reg); reg);
iwl_set_bit(trans, CSR_GP_CNTRL, iwl_set_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_mac_access_req)); BIT(trans->trans_cfg->csr->flag_mac_access_req));
rxq->need_update = true; rxq->need_update = true;
return; return;
} }
} }
rxq->write_actual = round_down(rxq->write, 8); rxq->write_actual = round_down(rxq->write, 8);
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560) if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22560)
iwl_write32(trans, HBUS_TARG_WRPTR, iwl_write32(trans, HBUS_TARG_WRPTR,
(rxq->write_actual | (rxq->write_actual |
((FIRST_RX_QUEUE + rxq->id) << 16))); ((FIRST_RX_QUEUE + rxq->id) << 16)));
else if (trans->cfg->mq_rx_supported) else if (trans->trans_cfg->mq_rx_supported)
iwl_write32(trans, RFH_Q_FRBDCB_WIDX_TRG(rxq->id), iwl_write32(trans, RFH_Q_FRBDCB_WIDX_TRG(rxq->id),
rxq->write_actual); rxq->write_actual);
else else
@ -279,7 +279,7 @@ static void iwl_pcie_restock_bd(struct iwl_trans *trans,
struct iwl_rxq *rxq, struct iwl_rxq *rxq,
struct iwl_rx_mem_buffer *rxb) struct iwl_rx_mem_buffer *rxb)
{ {
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) { if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
struct iwl_rx_transfer_desc *bd = rxq->bd; struct iwl_rx_transfer_desc *bd = rxq->bd;
BUILD_BUG_ON(sizeof(*bd) != 2 * sizeof(u64)); BUILD_BUG_ON(sizeof(*bd) != 2 * sizeof(u64));
@ -405,7 +405,7 @@ static void iwl_pcie_rxsq_restock(struct iwl_trans *trans,
static static
void iwl_pcie_rxq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq) void iwl_pcie_rxq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq)
{ {
if (trans->cfg->mq_rx_supported) if (trans->trans_cfg->mq_rx_supported)
iwl_pcie_rxmq_restock(trans, rxq); iwl_pcie_rxmq_restock(trans, rxq);
else else
iwl_pcie_rxsq_restock(trans, rxq); iwl_pcie_rxsq_restock(trans, rxq);
@ -682,7 +682,7 @@ static int iwl_pcie_free_bd_size(struct iwl_trans *trans, bool use_rx_td)
if (use_rx_td) if (use_rx_td)
return sizeof(*rx_td); return sizeof(*rx_td);
else else
return trans->cfg->mq_rx_supported ? sizeof(__le64) : return trans->trans_cfg->mq_rx_supported ? sizeof(__le64) :
sizeof(__le32); sizeof(__le32);
} }
@ -690,7 +690,7 @@ static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans,
struct iwl_rxq *rxq) struct iwl_rxq *rxq)
{ {
struct device *dev = trans->dev; struct device *dev = trans->dev;
bool use_rx_td = (trans->cfg->device_family >= bool use_rx_td = (trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_22560); IWL_DEVICE_FAMILY_22560);
int free_size = iwl_pcie_free_bd_size(trans, use_rx_td); int free_size = iwl_pcie_free_bd_size(trans, use_rx_td);
@ -712,7 +712,7 @@ static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans,
rxq->used_bd_dma = 0; rxq->used_bd_dma = 0;
rxq->used_bd = NULL; rxq->used_bd = NULL;
if (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_22560)
return; return;
if (rxq->tr_tail) if (rxq->tr_tail)
@ -735,13 +735,13 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
struct device *dev = trans->dev; struct device *dev = trans->dev;
int i; int i;
int free_size; int free_size;
bool use_rx_td = (trans->cfg->device_family >= bool use_rx_td = (trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_22560); IWL_DEVICE_FAMILY_22560);
size_t rb_stts_size = use_rx_td ? sizeof(__le16) : size_t rb_stts_size = use_rx_td ? sizeof(__le16) :
sizeof(struct iwl_rb_status); sizeof(struct iwl_rb_status);
spin_lock_init(&rxq->lock); spin_lock_init(&rxq->lock);
if (trans->cfg->mq_rx_supported) if (trans->trans_cfg->mq_rx_supported)
rxq->queue_size = MQ_RX_TABLE_SIZE; rxq->queue_size = MQ_RX_TABLE_SIZE;
else else
rxq->queue_size = RX_QUEUE_SIZE; rxq->queue_size = RX_QUEUE_SIZE;
@ -757,7 +757,7 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
if (!rxq->bd) if (!rxq->bd)
goto err; goto err;
if (trans->cfg->mq_rx_supported) { if (trans->trans_cfg->mq_rx_supported) {
rxq->used_bd = dma_alloc_coherent(dev, rxq->used_bd = dma_alloc_coherent(dev,
(use_rx_td ? sizeof(*rxq->cd) : sizeof(__le32)) * rxq->queue_size, (use_rx_td ? sizeof(*rxq->cd) : sizeof(__le32)) * rxq->queue_size,
&rxq->used_bd_dma, &rxq->used_bd_dma,
@ -807,7 +807,7 @@ int iwl_pcie_rx_alloc(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rb_allocator *rba = &trans_pcie->rba; struct iwl_rb_allocator *rba = &trans_pcie->rba;
int i, ret; int i, ret;
size_t rb_stts_size = trans->cfg->device_family >= size_t rb_stts_size = trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_22560 ? IWL_DEVICE_FAMILY_22560 ?
sizeof(__le16) : sizeof(struct iwl_rb_status); sizeof(__le16) : sizeof(struct iwl_rb_status);
@ -1074,8 +1074,8 @@ int _iwl_pcie_rx_init(struct iwl_trans *trans)
rxq->read = 0; rxq->read = 0;
rxq->write = 0; rxq->write = 0;
rxq->write_actual = 0; rxq->write_actual = 0;
memset(rxq->rb_stts, 0, memset(rxq->rb_stts, 0, (trans->trans_cfg->device_family >=
(trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) ? IWL_DEVICE_FAMILY_22560) ?
sizeof(__le16) : sizeof(struct iwl_rb_status)); sizeof(__le16) : sizeof(struct iwl_rb_status));
iwl_pcie_rx_init_rxb_lists(rxq); iwl_pcie_rx_init_rxb_lists(rxq);
@ -1088,7 +1088,7 @@ int _iwl_pcie_rx_init(struct iwl_trans *trans)
} }
/* move the pool to the default queue and allocator ownerships */ /* move the pool to the default queue and allocator ownerships */
queue_size = trans->cfg->mq_rx_supported ? queue_size = trans->trans_cfg->mq_rx_supported ?
MQ_RX_NUM_RBDS : RX_QUEUE_SIZE; MQ_RX_NUM_RBDS : RX_QUEUE_SIZE;
allocator_pool_size = trans->num_rx_queues * allocator_pool_size = trans->num_rx_queues *
(RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC); (RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC);
@ -1120,7 +1120,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
if (ret) if (ret)
return ret; return ret;
if (trans->cfg->mq_rx_supported) if (trans->trans_cfg->mq_rx_supported)
iwl_pcie_rx_mq_hw_init(trans); iwl_pcie_rx_mq_hw_init(trans);
else else
iwl_pcie_rx_hw_init(trans, trans_pcie->rxq); iwl_pcie_rx_hw_init(trans, trans_pcie->rxq);
@ -1151,7 +1151,7 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rb_allocator *rba = &trans_pcie->rba; struct iwl_rb_allocator *rba = &trans_pcie->rba;
int i; int i;
size_t rb_stts_size = trans->cfg->device_family >= size_t rb_stts_size = trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_22560 ? IWL_DEVICE_FAMILY_22560 ?
sizeof(__le16) : sizeof(struct iwl_rb_status); sizeof(__le16) : sizeof(struct iwl_rb_status);
@ -1347,7 +1347,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
} }
page_stolen |= rxcb._page_stolen; page_stolen |= rxcb._page_stolen;
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
break; break;
offset += ALIGN(len, FH_RSCSR_FRAME_ALIGN); offset += ALIGN(len, FH_RSCSR_FRAME_ALIGN);
} }
@ -1392,14 +1392,14 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans,
BUILD_BUG_ON(sizeof(struct iwl_rx_completion_desc) != 32); BUILD_BUG_ON(sizeof(struct iwl_rx_completion_desc) != 32);
if (!trans->cfg->mq_rx_supported) { if (!trans->trans_cfg->mq_rx_supported) {
rxb = rxq->queue[i]; rxb = rxq->queue[i];
rxq->queue[i] = NULL; rxq->queue[i] = NULL;
return rxb; return rxb;
} }
/* used_bd is a 32/16 bit but only 12 are used to retrieve the vid */ /* used_bd is a 32/16 bit but only 12 are used to retrieve the vid */
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
vid = le16_to_cpu(rxq->cd[i].rbid) & 0x0FFF; vid = le16_to_cpu(rxq->cd[i].rbid) & 0x0FFF;
else else
vid = le32_to_cpu(rxq->bd_32[i]) & 0x0FFF; vid = le32_to_cpu(rxq->bd_32[i]) & 0x0FFF;
@ -1515,7 +1515,7 @@ out:
/* Backtrack one entry */ /* Backtrack one entry */
rxq->read = i; rxq->read = i;
/* update cr tail with the rxq read pointer */ /* update cr tail with the rxq read pointer */
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
*rxq->cr_tail = cpu_to_le16(r); *rxq->cr_tail = cpu_to_le16(r);
spin_unlock(&rxq->lock); spin_unlock(&rxq->lock);
@ -1597,7 +1597,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
return; return;
} }
for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { for (i = 0; i < trans->trans_cfg->base_params->num_of_queues; i++) {
if (!trans_pcie->txq[i]) if (!trans_pcie->txq[i])
continue; continue;
del_timer(&trans_pcie->txq[i]->stuck_timer); del_timer(&trans_pcie->txq[i]->stuck_timer);
@ -1838,7 +1838,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
if (inta & CSR_INT_BIT_ALIVE) { if (inta & CSR_INT_BIT_ALIVE) {
IWL_DEBUG_ISR(trans, "Alive interrupt\n"); IWL_DEBUG_ISR(trans, "Alive interrupt\n");
isr_stats->alive++; isr_stats->alive++;
if (trans->cfg->gen2) { if (trans->trans_cfg->gen2) {
/* /*
* We can restock, since firmware configured * We can restock, since firmware configured
* the RFH * the RFH
@ -2179,13 +2179,13 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
if (inta_hw & MSIX_HW_INT_CAUSES_REG_ALIVE) { if (inta_hw & MSIX_HW_INT_CAUSES_REG_ALIVE) {
IWL_DEBUG_ISR(trans, "Alive interrupt\n"); IWL_DEBUG_ISR(trans, "Alive interrupt\n");
isr_stats->alive++; isr_stats->alive++;
if (trans->cfg->gen2) { if (trans->trans_cfg->gen2) {
/* We can restock, since firmware configured the RFH */ /* We can restock, since firmware configured the RFH */
iwl_pcie_rxmq_restock(trans, trans_pcie->rxq); iwl_pcie_rxmq_restock(trans, trans_pcie->rxq);
} }
} }
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560 && if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22560 &&
inta_hw & MSIX_HW_INT_CAUSES_REG_IPC) { inta_hw & MSIX_HW_INT_CAUSES_REG_IPC) {
/* Reflect IML transfer status */ /* Reflect IML transfer status */
int res = iwl_read32(trans, CSR_IML_RESP_ADDR); int res = iwl_read32(trans, CSR_IML_RESP_ADDR);
@ -2196,6 +2196,16 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
iwl_pcie_irq_handle_error(trans); iwl_pcie_irq_handle_error(trans);
} }
} else if (inta_hw & MSIX_HW_INT_CAUSES_REG_WAKEUP) { } else if (inta_hw & MSIX_HW_INT_CAUSES_REG_WAKEUP) {
u32 sleep_notif =
le32_to_cpu(trans_pcie->prph_info->sleep_notif);
if (sleep_notif == IWL_D3_SLEEP_STATUS_SUSPEND ||
sleep_notif == IWL_D3_SLEEP_STATUS_RESUME) {
IWL_DEBUG_ISR(trans,
"Sx interrupt: sleep notification = 0x%x\n",
sleep_notif);
trans_pcie->sx_complete = true;
wake_up(&trans_pcie->sx_waitq);
} else {
/* uCode wakes up after power-down sleep */ /* uCode wakes up after power-down sleep */
IWL_DEBUG_ISR(trans, "Wakeup interrupt\n"); IWL_DEBUG_ISR(trans, "Wakeup interrupt\n");
iwl_pcie_rxq_check_wrptr(trans); iwl_pcie_rxq_check_wrptr(trans);
@ -2203,6 +2213,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
isr_stats->wakeup++; isr_stats->wakeup++;
} }
}
if (inta_hw & MSIX_HW_INT_CAUSES_REG_IML) { if (inta_hw & MSIX_HW_INT_CAUSES_REG_IML) {
/* Reflect IML transfer status */ /* Reflect IML transfer status */

View File

@ -92,7 +92,7 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)
iwl_pcie_apm_config(trans); iwl_pcie_apm_config(trans);
ret = iwl_finish_nic_init(trans); ret = iwl_finish_nic_init(trans, trans->trans_cfg);
if (ret) if (ret)
return ret; return ret;
@ -133,10 +133,10 @@ static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
* D0A* (powered-up Active) --> D0U* (Uninitialized) state. * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
*/ */
iwl_clear_bit(trans, CSR_GP_CNTRL, iwl_clear_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_init_done)); BIT(trans->trans_cfg->csr->flag_init_done));
} }
void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power) void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@ -147,9 +147,6 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
trans_pcie->is_down = true; trans_pcie->is_down = true;
/* Stop dbgc before stopping device */
iwl_fw_dbg_stop_recording(trans, NULL);
/* tell the device to stop sending interrupts */ /* tell the device to stop sending interrupts */
iwl_disable_interrupts(trans); iwl_disable_interrupts(trans);
@ -171,14 +168,14 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
} }
iwl_pcie_ctxt_info_free_paging(trans); iwl_pcie_ctxt_info_free_paging(trans);
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
iwl_pcie_ctxt_info_gen3_free(trans); iwl_pcie_ctxt_info_gen3_free(trans);
else else
iwl_pcie_ctxt_info_free(trans); iwl_pcie_ctxt_info_free(trans);
/* Make sure (redundant) we've released our request to stay awake */ /* Make sure (redundant) we've released our request to stay awake */
iwl_clear_bit(trans, CSR_GP_CNTRL, iwl_clear_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_mac_access_req)); BIT(trans->trans_cfg->csr->flag_mac_access_req));
/* Stop the device, and put it in low power state */ /* Stop the device, and put it in low power state */
iwl_pcie_gen2_apm_stop(trans, false); iwl_pcie_gen2_apm_stop(trans, false);
@ -218,7 +215,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
iwl_pcie_prepare_card_hw(trans); iwl_pcie_prepare_card_hw(trans);
} }
void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power) void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
bool was_in_rfkill; bool was_in_rfkill;
@ -226,7 +223,7 @@ void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
mutex_lock(&trans_pcie->mutex); mutex_lock(&trans_pcie->mutex);
trans_pcie->opmode_down = true; trans_pcie->opmode_down = true;
was_in_rfkill = test_bit(STATUS_RFKILL_OPMODE, &trans->status); was_in_rfkill = test_bit(STATUS_RFKILL_OPMODE, &trans->status);
_iwl_trans_pcie_gen2_stop_device(trans, low_power); _iwl_trans_pcie_gen2_stop_device(trans);
iwl_trans_pcie_handle_stop_rfkill(trans, was_in_rfkill); iwl_trans_pcie_handle_stop_rfkill(trans, was_in_rfkill);
mutex_unlock(&trans_pcie->mutex); mutex_unlock(&trans_pcie->mutex);
} }
@ -343,7 +340,7 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
goto out; goto out;
} }
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
ret = iwl_pcie_ctxt_info_gen3_init(trans, fw); ret = iwl_pcie_ctxt_info_gen3_init(trans, fw);
else else
ret = iwl_pcie_ctxt_info_init(trans, fw); ret = iwl_pcie_ctxt_info_init(trans, fw);

View File

@ -69,7 +69,6 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/pm_runtime.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/wait.h> #include <linux/wait.h>
@ -185,8 +184,8 @@ out:
static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans) static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans)
{ {
/* Reset entire device - do controller reset (results in SHRD_HW_RST) */ /* Reset entire device - do controller reset (results in SHRD_HW_RST) */
iwl_set_bit(trans, trans->cfg->csr->addr_sw_reset, iwl_set_bit(trans, trans->trans_cfg->csr->addr_sw_reset,
BIT(trans->cfg->csr->flag_sw_reset)); BIT(trans->trans_cfg->csr->flag_sw_reset));
usleep_range(5000, 6000); usleep_range(5000, 6000);
} }
@ -216,8 +215,7 @@ static void iwl_pcie_alloc_fw_monitor_block(struct iwl_trans *trans,
for (power = max_power; power >= min_power; power--) { for (power = max_power; power >= min_power; power--) {
size = BIT(power); size = BIT(power);
cpu_addr = dma_alloc_coherent(trans->dev, size, &phys, cpu_addr = dma_alloc_coherent(trans->dev, size, &phys,
GFP_KERNEL | __GFP_NOWARN | GFP_KERNEL | __GFP_NOWARN);
__GFP_ZERO | __GFP_COMP);
if (!cpu_addr) if (!cpu_addr)
continue; continue;
@ -343,7 +341,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
*/ */
/* Disable L0S exit timer (platform NMI Work/Around) */ /* Disable L0S exit timer (platform NMI Work/Around) */
if (trans->cfg->device_family < IWL_DEVICE_FAMILY_8000) if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000)
iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS, iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
@ -367,10 +365,10 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
iwl_pcie_apm_config(trans); iwl_pcie_apm_config(trans);
/* Configure analog phase-lock-loop before activating to D0A */ /* Configure analog phase-lock-loop before activating to D0A */
if (trans->cfg->base_params->pll_cfg) if (trans->trans_cfg->base_params->pll_cfg)
iwl_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); iwl_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL);
ret = iwl_finish_nic_init(trans); ret = iwl_finish_nic_init(trans, trans->trans_cfg);
if (ret) if (ret)
return ret; return ret;
@ -442,7 +440,7 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
iwl_trans_pcie_sw_reset(trans); iwl_trans_pcie_sw_reset(trans);
ret = iwl_finish_nic_init(trans); ret = iwl_finish_nic_init(trans, trans->trans_cfg);
if (WARN_ON(ret)) { if (WARN_ON(ret)) {
/* Release XTAL ON request */ /* Release XTAL ON request */
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
@ -492,7 +490,7 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
* D0A* (powered-up Active) --> D0U* (Uninitialized) state. * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
*/ */
iwl_clear_bit(trans, CSR_GP_CNTRL, iwl_clear_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_init_done)); BIT(trans->trans_cfg->csr->flag_init_done));
/* Activates XTAL resources monitor */ /* Activates XTAL resources monitor */
__iwl_trans_pcie_set_bit(trans, CSR_MONITOR_CFG_REG, __iwl_trans_pcie_set_bit(trans, CSR_MONITOR_CFG_REG,
@ -514,12 +512,12 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans)
int ret; int ret;
/* stop device's busmaster DMA activity */ /* stop device's busmaster DMA activity */
iwl_set_bit(trans, trans->cfg->csr->addr_sw_reset, iwl_set_bit(trans, trans->trans_cfg->csr->addr_sw_reset,
BIT(trans->cfg->csr->flag_stop_master)); BIT(trans->trans_cfg->csr->flag_stop_master));
ret = iwl_poll_bit(trans, trans->cfg->csr->addr_sw_reset, ret = iwl_poll_bit(trans, trans->trans_cfg->csr->addr_sw_reset,
BIT(trans->cfg->csr->flag_master_dis), BIT(trans->trans_cfg->csr->flag_master_dis),
BIT(trans->cfg->csr->flag_master_dis), 100); BIT(trans->trans_cfg->csr->flag_master_dis), 100);
if (ret < 0) if (ret < 0)
IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n"); IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n");
@ -535,10 +533,11 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
iwl_pcie_apm_init(trans); iwl_pcie_apm_init(trans);
/* inform ME that we are leaving */ /* inform ME that we are leaving */
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000)
iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG, iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_WAKE_ME); APMG_PCIDEV_STT_VAL_WAKE_ME);
else if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) { else if (trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_8000) {
iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
CSR_RESET_LINK_PWR_MGMT_DISABLED); CSR_RESET_LINK_PWR_MGMT_DISABLED);
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
@ -568,7 +567,7 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
* D0A* (powered-up Active) --> D0U* (Uninitialized) state. * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
*/ */
iwl_clear_bit(trans, CSR_GP_CNTRL, iwl_clear_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_init_done)); BIT(trans->trans_cfg->csr->flag_init_done));
} }
static int iwl_pcie_nic_init(struct iwl_trans *trans) static int iwl_pcie_nic_init(struct iwl_trans *trans)
@ -595,7 +594,7 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans)
if (iwl_pcie_tx_init(trans)) if (iwl_pcie_tx_init(trans))
return -ENOMEM; return -ENOMEM;
if (trans->cfg->base_params->shadow_reg_enable) { if (trans->trans_cfg->base_params->shadow_reg_enable) {
/* enable shadow regs in HW */ /* enable shadow regs in HW */
iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF); iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF);
IWL_DEBUG_INFO(trans, "Enabling shadow registers in device\n"); IWL_DEBUG_INFO(trans, "Enabling shadow registers in device\n");
@ -833,7 +832,7 @@ static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans,
iwl_enable_interrupts(trans); iwl_enable_interrupts(trans);
if (trans->cfg->use_tfh) { if (trans->trans_cfg->use_tfh) {
if (cpu == 1) if (cpu == 1)
iwl_write_prph(trans, UREG_UCODE_LOAD_STATUS, iwl_write_prph(trans, UREG_UCODE_LOAD_STATUS,
0xFFFF); 0xFFFF);
@ -898,12 +897,12 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans)
const struct iwl_fw_dbg_dest_tlv_v1 *dest = trans->dbg.dest_tlv; const struct iwl_fw_dbg_dest_tlv_v1 *dest = trans->dbg.dest_tlv;
int i; int i;
if (trans->dbg.ini_valid) { if (iwl_trans_dbg_ini_valid(trans)) {
if (!trans->dbg.num_blocks) if (!trans->dbg.num_blocks)
return; return;
IWL_DEBUG_FW(trans, IWL_DEBUG_FW(trans,
"WRT: applying DRAM buffer[0] destination\n"); "WRT: Applying DRAM buffer[0] destination\n");
iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2, iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2,
trans->dbg.fw_mon[0].physical >> trans->dbg.fw_mon[0].physical >>
MON_BUFF_SHIFT_VER2); MON_BUFF_SHIFT_VER2);
@ -965,7 +964,7 @@ monitor:
iwl_write_prph(trans, le32_to_cpu(dest->base_reg), iwl_write_prph(trans, le32_to_cpu(dest->base_reg),
trans->dbg.fw_mon[0].physical >> trans->dbg.fw_mon[0].physical >>
dest->base_shift); dest->base_shift);
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_8000)
iwl_write_prph(trans, le32_to_cpu(dest->end_reg), iwl_write_prph(trans, le32_to_cpu(dest->end_reg),
(trans->dbg.fw_mon[0].physical + (trans->dbg.fw_mon[0].physical +
trans->dbg.fw_mon[0].size - 256) >> trans->dbg.fw_mon[0].size - 256) >>
@ -1007,7 +1006,7 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
/* supported for 7000 only for the moment */ /* supported for 7000 only for the moment */
if (iwlwifi_mod_params.fw_monitor && if (iwlwifi_mod_params.fw_monitor &&
trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) { trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_pcie_alloc_fw_monitor(trans, 0); iwl_pcie_alloc_fw_monitor(trans, 0);
if (trans->dbg.fw_mon[0].size) { if (trans->dbg.fw_mon[0].size) {
@ -1136,7 +1135,7 @@ static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE; int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE;
int i, arr_size = int i, arr_size =
(trans->cfg->device_family != IWL_DEVICE_FAMILY_22560) ? (trans->trans_cfg->device_family != IWL_DEVICE_FAMILY_22560) ?
ARRAY_SIZE(causes_list) : ARRAY_SIZE(causes_list_v2); ARRAY_SIZE(causes_list) : ARRAY_SIZE(causes_list_v2);
/* /*
@ -1146,7 +1145,8 @@ static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
*/ */
for (i = 0; i < arr_size; i++) { for (i = 0; i < arr_size; i++) {
struct iwl_causes_list *causes = struct iwl_causes_list *causes =
(trans->cfg->device_family != IWL_DEVICE_FAMILY_22560) ? (trans->trans_cfg->device_family !=
IWL_DEVICE_FAMILY_22560) ?
causes_list : causes_list_v2; causes_list : causes_list_v2;
iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val); iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val);
@ -1190,7 +1190,7 @@ void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie)
struct iwl_trans *trans = trans_pcie->trans; struct iwl_trans *trans = trans_pcie->trans;
if (!trans_pcie->msix_enabled) { if (!trans_pcie->msix_enabled) {
if (trans->cfg->mq_rx_supported && if (trans->trans_cfg->mq_rx_supported &&
test_bit(STATUS_DEVICE_ENABLED, &trans->status)) test_bit(STATUS_DEVICE_ENABLED, &trans->status))
iwl_write_umac_prph(trans, UREG_CHICK, iwl_write_umac_prph(trans, UREG_CHICK,
UREG_CHICK_MSI_ENABLE); UREG_CHICK_MSI_ENABLE);
@ -1231,7 +1231,7 @@ static void iwl_pcie_init_msix(struct iwl_trans_pcie *trans_pcie)
trans_pcie->hw_mask = trans_pcie->hw_init_mask; trans_pcie->hw_mask = trans_pcie->hw_init_mask;
} }
static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@ -1242,9 +1242,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
trans_pcie->is_down = true; trans_pcie->is_down = true;
/* Stop dbgc before stopping device */
iwl_fw_dbg_stop_recording(trans, NULL);
/* tell the device to stop sending interrupts */ /* tell the device to stop sending interrupts */
iwl_disable_interrupts(trans); iwl_disable_interrupts(trans);
@ -1274,7 +1271,7 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
/* Make sure (redundant) we've released our request to stay awake */ /* Make sure (redundant) we've released our request to stay awake */
iwl_clear_bit(trans, CSR_GP_CNTRL, iwl_clear_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_mac_access_req)); BIT(trans->trans_cfg->csr->flag_mac_access_req));
/* Stop the device, and put it in low power state */ /* Stop the device, and put it in low power state */
iwl_pcie_apm_stop(trans, false); iwl_pcie_apm_stop(trans, false);
@ -1401,7 +1398,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
/* Load the given image to the HW */ /* Load the given image to the HW */
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_8000)
ret = iwl_pcie_load_given_ucode_8000(trans, fw); ret = iwl_pcie_load_given_ucode_8000(trans, fw);
else else
ret = iwl_pcie_load_given_ucode(trans, fw); ret = iwl_pcie_load_given_ucode(trans, fw);
@ -1451,7 +1448,7 @@ void iwl_trans_pcie_handle_stop_rfkill(struct iwl_trans *trans,
iwl_trans_pcie_rf_kill(trans, hw_rfkill); iwl_trans_pcie_rf_kill(trans, hw_rfkill);
} }
static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
bool was_in_rfkill; bool was_in_rfkill;
@ -1459,7 +1456,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
mutex_lock(&trans_pcie->mutex); mutex_lock(&trans_pcie->mutex);
trans_pcie->opmode_down = true; trans_pcie->opmode_down = true;
was_in_rfkill = test_bit(STATUS_RFKILL_OPMODE, &trans->status); was_in_rfkill = test_bit(STATUS_RFKILL_OPMODE, &trans->status);
_iwl_trans_pcie_stop_device(trans, low_power); _iwl_trans_pcie_stop_device(trans);
iwl_trans_pcie_handle_stop_rfkill(trans, was_in_rfkill); iwl_trans_pcie_handle_stop_rfkill(trans, was_in_rfkill);
mutex_unlock(&trans_pcie->mutex); mutex_unlock(&trans_pcie->mutex);
} }
@ -1474,22 +1471,16 @@ void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state)
IWL_WARN(trans, "reporting RF_KILL (radio %s)\n", IWL_WARN(trans, "reporting RF_KILL (radio %s)\n",
state ? "disabled" : "enabled"); state ? "disabled" : "enabled");
if (iwl_op_mode_hw_rf_kill(trans->op_mode, state)) { if (iwl_op_mode_hw_rf_kill(trans->op_mode, state)) {
if (trans->cfg->gen2) if (trans->trans_cfg->gen2)
_iwl_trans_pcie_gen2_stop_device(trans, true); _iwl_trans_pcie_gen2_stop_device(trans);
else else
_iwl_trans_pcie_stop_device(trans, true); _iwl_trans_pcie_stop_device(trans);
} }
} }
static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, void iwl_pcie_d3_complete_suspend(struct iwl_trans *trans,
bool reset) bool test, bool reset)
{ {
if (!reset) {
/* Enable persistence mode to avoid reset */
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_PERSIST_MODE);
}
iwl_disable_interrupts(trans); iwl_disable_interrupts(trans);
/* /*
@ -1504,9 +1495,9 @@ static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test,
iwl_pcie_synchronize_irqs(trans); iwl_pcie_synchronize_irqs(trans);
iwl_clear_bit(trans, CSR_GP_CNTRL, iwl_clear_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_mac_access_req)); BIT(trans->trans_cfg->csr->flag_mac_access_req));
iwl_clear_bit(trans, CSR_GP_CNTRL, iwl_clear_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_init_done)); BIT(trans->trans_cfg->csr->flag_init_done));
if (reset) { if (reset) {
/* /*
@ -1520,6 +1511,42 @@ static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test,
iwl_pcie_set_pwr(trans, true); iwl_pcie_set_pwr(trans, true);
} }
static int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test,
bool reset)
{
int ret;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
/*
* Family IWL_DEVICE_FAMILY_AX210 and above persist mode is set by FW.
*/
if (!reset && trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
/* Enable persistence mode to avoid reset */
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_PERSIST_MODE);
}
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
UREG_DOORBELL_TO_ISR6_SUSPEND);
ret = wait_event_timeout(trans_pcie->sx_waitq,
trans_pcie->sx_complete, 2 * HZ);
/*
* Invalidate it toward resume.
*/
trans_pcie->sx_complete = false;
if (!ret) {
IWL_ERR(trans, "Timeout entering D3\n");
return -ETIMEDOUT;
}
}
iwl_pcie_d3_complete_suspend(trans, test, reset);
return 0;
}
static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
enum iwl_d3_status *status, enum iwl_d3_status *status,
bool test, bool reset) bool test, bool reset)
@ -1531,13 +1558,13 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
if (test) { if (test) {
iwl_enable_interrupts(trans); iwl_enable_interrupts(trans);
*status = IWL_D3_STATUS_ALIVE; *status = IWL_D3_STATUS_ALIVE;
return 0; goto out;
} }
iwl_set_bit(trans, CSR_GP_CNTRL, iwl_set_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_mac_access_req)); BIT(trans->trans_cfg->csr->flag_mac_access_req));
ret = iwl_finish_nic_init(trans); ret = iwl_finish_nic_init(trans, trans->trans_cfg);
if (ret) if (ret)
return ret; return ret;
@ -1557,7 +1584,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
if (!reset) { if (!reset) {
iwl_clear_bit(trans, CSR_GP_CNTRL, iwl_clear_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_mac_access_req)); BIT(trans->trans_cfg->csr->flag_mac_access_req));
} else { } else {
iwl_trans_pcie_tx_reset(trans); iwl_trans_pcie_tx_reset(trans);
@ -1578,17 +1605,38 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
else else
*status = IWL_D3_STATUS_ALIVE; *status = IWL_D3_STATUS_ALIVE;
out:
if (*status == IWL_D3_STATUS_ALIVE &&
trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
trans_pcie->sx_complete = false;
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
UREG_DOORBELL_TO_ISR6_RESUME);
ret = wait_event_timeout(trans_pcie->sx_waitq,
trans_pcie->sx_complete, 2 * HZ);
/*
* Invalidate it toward next suspend.
*/
trans_pcie->sx_complete = false;
if (!ret) {
IWL_ERR(trans, "Timeout exiting D3\n");
return -ETIMEDOUT;
}
}
return 0; return 0;
} }
static void iwl_pcie_set_interrupt_capa(struct pci_dev *pdev, static void
struct iwl_trans *trans) iwl_pcie_set_interrupt_capa(struct pci_dev *pdev,
struct iwl_trans *trans,
const struct iwl_cfg_trans_params *cfg_trans)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int max_irqs, num_irqs, i, ret; int max_irqs, num_irqs, i, ret;
u16 pci_cmd; u16 pci_cmd;
if (!trans->cfg->mq_rx_supported) if (!cfg_trans->mq_rx_supported)
goto enable_msi; goto enable_msi;
max_irqs = min_t(u32, num_online_cpus() + 2, IWL_MAX_RX_HW_QUEUES); max_irqs = min_t(u32, num_online_cpus() + 2, IWL_MAX_RX_HW_QUEUES);
@ -1709,7 +1757,7 @@ static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans)
{ {
u32 hpm, wprot; u32 hpm, wprot;
switch (trans->cfg->device_family) { switch (trans->trans_cfg->device_family) {
case IWL_DEVICE_FAMILY_9000: case IWL_DEVICE_FAMILY_9000:
wprot = PREG_PRPH_WPROT_9000; wprot = PREG_PRPH_WPROT_9000;
break; break;
@ -1736,7 +1784,7 @@ static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans)
return 0; return 0;
} }
static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int err; int err;
@ -1772,20 +1820,16 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
/* ...rfkill can call stop_device and set it false if needed */ /* ...rfkill can call stop_device and set it false if needed */
iwl_pcie_check_hw_rf_kill(trans); iwl_pcie_check_hw_rf_kill(trans);
/* Make sure we sync here, because we'll need full access later */
if (low_power)
pm_runtime_resume(trans->dev);
return 0; return 0;
} }
static int iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret; int ret;
mutex_lock(&trans_pcie->mutex); mutex_lock(&trans_pcie->mutex);
ret = _iwl_trans_pcie_start_hw(trans, low_power); ret = _iwl_trans_pcie_start_hw(trans);
mutex_unlock(&trans_pcie->mutex); mutex_unlock(&trans_pcie->mutex);
return ret; return ret;
@ -1828,7 +1872,7 @@ static u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs)
static u32 iwl_trans_pcie_prph_msk(struct iwl_trans *trans) static u32 iwl_trans_pcie_prph_msk(struct iwl_trans *trans)
{ {
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
return 0x00FFFFFF; return 0x00FFFFFF;
else else
return 0x000FFFFF; return 0x000FFFFF;
@ -1899,7 +1943,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
iwl_pcie_synchronize_irqs(trans); iwl_pcie_synchronize_irqs(trans);
if (trans->cfg->gen2) if (trans->trans_cfg->gen2)
iwl_pcie_gen2_tx_free(trans); iwl_pcie_gen2_tx_free(trans);
else else
iwl_pcie_tx_free(trans); iwl_pcie_tx_free(trans);
@ -1981,8 +2025,8 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans,
/* this bit wakes up the NIC */ /* this bit wakes up the NIC */
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_mac_access_req)); BIT(trans->trans_cfg->csr->flag_mac_access_req));
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_8000)
udelay(2); udelay(2);
/* /*
@ -2006,8 +2050,8 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans,
* and do not save/restore SRAM when power cycling. * and do not save/restore SRAM when power cycling.
*/ */
ret = iwl_poll_bit(trans, CSR_GP_CNTRL, ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_val_mac_access_en), BIT(trans->trans_cfg->csr->flag_val_mac_access_en),
(BIT(trans->cfg->csr->flag_mac_clock_ready) | (BIT(trans->trans_cfg->csr->flag_mac_clock_ready) |
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
if (unlikely(ret < 0)) { if (unlikely(ret < 0)) {
u32 cntrl = iwl_read32(trans, CSR_GP_CNTRL); u32 cntrl = iwl_read32(trans, CSR_GP_CNTRL);
@ -2089,7 +2133,7 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans,
goto out; goto out;
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_mac_access_req)); BIT(trans->trans_cfg->csr->flag_mac_access_req));
/* /*
* Above we read the CSR_GP_CNTRL register, which will flush * Above we read the CSR_GP_CNTRL register, which will flush
* any previous writes, but we need the write that clears the * any previous writes, but we need the write that clears the
@ -2196,7 +2240,7 @@ static void iwl_trans_pcie_block_txq_ptrs(struct iwl_trans *trans, bool block)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int i; int i;
for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { for (i = 0; i < trans->trans_cfg->base_params->num_of_queues; i++) {
struct iwl_txq *txq = trans_pcie->txq[i]; struct iwl_txq *txq = trans_pcie->txq[i];
if (i == trans_pcie->cmd_queue) if (i == trans_pcie->cmd_queue)
@ -2227,7 +2271,7 @@ void iwl_trans_pcie_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq)
bool active; bool active;
u8 fifo; u8 fifo;
if (trans->cfg->use_tfh) { if (trans->trans_cfg->use_tfh) {
IWL_ERR(trans, "Queue %d is stuck %d %d\n", txq_id, IWL_ERR(trans, "Queue %d is stuck %d %d\n", txq_id,
txq->read_ptr, txq->write_ptr); txq->read_ptr, txq->write_ptr);
/* TODO: access new SCD registers and dump them */ /* TODO: access new SCD registers and dump them */
@ -2244,9 +2288,9 @@ void iwl_trans_pcie_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq)
jiffies_to_msecs(txq->wd_timeout), jiffies_to_msecs(txq->wd_timeout),
txq->read_ptr, txq->write_ptr, txq->read_ptr, txq->write_ptr,
iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) &
(trans->cfg->base_params->max_tfd_queue_size - 1), (trans->trans_cfg->base_params->max_tfd_queue_size - 1),
iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)) & iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)) &
(trans->cfg->base_params->max_tfd_queue_size - 1), (trans->trans_cfg->base_params->max_tfd_queue_size - 1),
iwl_read_direct32(trans, FH_TX_TRB_REG(fifo))); iwl_read_direct32(trans, FH_TX_TRB_REG(fifo)));
} }
@ -2335,7 +2379,9 @@ static int iwl_trans_pcie_wait_txqs_empty(struct iwl_trans *trans, u32 txq_bm)
int ret = 0; int ret = 0;
/* waiting for all the tx frames complete might take a while */ /* waiting for all the tx frames complete might take a while */
for (cnt = 0; cnt < trans->cfg->base_params->num_of_queues; cnt++) { for (cnt = 0;
cnt < trans->trans_cfg->base_params->num_of_queues;
cnt++) {
if (cnt == trans_pcie->cmd_queue) if (cnt == trans_pcie->cmd_queue)
continue; continue;
@ -2363,37 +2409,6 @@ static void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg,
spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
} }
static void iwl_trans_pcie_ref(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
if (iwlwifi_mod_params.d0i3_disable)
return;
pm_runtime_get(&trans_pcie->pci_dev->dev);
#ifdef CONFIG_PM
IWL_DEBUG_RPM(trans, "runtime usage count: %d\n",
atomic_read(&trans_pcie->pci_dev->dev.power.usage_count));
#endif /* CONFIG_PM */
}
static void iwl_trans_pcie_unref(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
if (iwlwifi_mod_params.d0i3_disable)
return;
pm_runtime_mark_last_busy(&trans_pcie->pci_dev->dev);
pm_runtime_put_autosuspend(&trans_pcie->pci_dev->dev);
#ifdef CONFIG_PM
IWL_DEBUG_RPM(trans, "runtime usage count: %d\n",
atomic_read(&trans_pcie->pci_dev->dev.power.usage_count));
#endif /* CONFIG_PM */
}
static const char *get_csr_string(int cmd) static const char *get_csr_string(int cmd)
{ {
#define IWL_CMD(x) case x: return #x #define IWL_CMD(x) case x: return #x
@ -2510,7 +2525,8 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
int ret; int ret;
size_t bufsz; size_t bufsz;
bufsz = sizeof(char) * 75 * trans->cfg->base_params->num_of_queues; bufsz = sizeof(char) * 75 *
trans->trans_cfg->base_params->num_of_queues;
if (!trans_pcie->txq_memory) if (!trans_pcie->txq_memory)
return -EAGAIN; return -EAGAIN;
@ -2519,7 +2535,9 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
for (cnt = 0; cnt < trans->cfg->base_params->num_of_queues; cnt++) { for (cnt = 0;
cnt < trans->trans_cfg->base_params->num_of_queues;
cnt++) {
txq = trans_pcie->txq[cnt]; txq = trans_pcie->txq[cnt];
pos += scnprintf(buf + pos, bufsz - pos, pos += scnprintf(buf + pos, bufsz - pos,
"hwq %.2d: read=%u write=%u use=%d stop=%d need_update=%d frozen=%d%s\n", "hwq %.2d: read=%u write=%u use=%d stop=%d need_update=%d frozen=%d%s\n",
@ -2989,7 +3007,7 @@ static u32 iwl_trans_pcie_fh_regs_dump(struct iwl_trans *trans,
(*data)->len = cpu_to_le32(fh_regs_len); (*data)->len = cpu_to_le32(fh_regs_len);
val = (void *)(*data)->data; val = (void *)(*data)->data;
if (!trans->cfg->gen2) if (!trans->trans_cfg->gen2)
for (i = FH_MEM_LOWER_BOUND; i < FH_MEM_UPPER_BOUND; for (i = FH_MEM_LOWER_BOUND; i < FH_MEM_UPPER_BOUND;
i += sizeof(u32)) i += sizeof(u32))
*val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i)); *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
@ -3037,7 +3055,7 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans,
{ {
u32 base, base_high, write_ptr, write_ptr_val, wrap_cnt; u32 base, base_high, write_ptr, write_ptr_val, wrap_cnt;
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
base = DBGC_CUR_DBGBUF_BASE_ADDR_LSB; base = DBGC_CUR_DBGBUF_BASE_ADDR_LSB;
base_high = DBGC_CUR_DBGBUF_BASE_ADDR_MSB; base_high = DBGC_CUR_DBGBUF_BASE_ADDR_MSB;
write_ptr = DBGC_CUR_DBGBUF_STATUS; write_ptr = DBGC_CUR_DBGBUF_STATUS;
@ -3057,7 +3075,7 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans,
cpu_to_le32(iwl_read_prph(trans, wrap_cnt)); cpu_to_le32(iwl_read_prph(trans, wrap_cnt));
fw_mon_data->fw_mon_base_ptr = fw_mon_data->fw_mon_base_ptr =
cpu_to_le32(iwl_read_prph(trans, base)); cpu_to_le32(iwl_read_prph(trans, base));
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
fw_mon_data->fw_mon_base_high_ptr = fw_mon_data->fw_mon_base_high_ptr =
cpu_to_le32(iwl_read_prph(trans, base_high)); cpu_to_le32(iwl_read_prph(trans, base_high));
write_ptr_val &= DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK; write_ptr_val &= DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK;
@ -3074,8 +3092,8 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans,
if (trans->dbg.dest_tlv || if (trans->dbg.dest_tlv ||
(trans->dbg.num_blocks && (trans->dbg.num_blocks &&
(trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 || (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000 ||
trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210))) { trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210))) {
struct iwl_fw_error_dump_fw_mon *fw_mon_data; struct iwl_fw_error_dump_fw_mon *fw_mon_data;
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR); (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR);
@ -3158,7 +3176,7 @@ static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, u32 *len)
trans->dbg.dest_tlv->end_shift; trans->dbg.dest_tlv->end_shift;
/* Make "end" point to the actual end */ /* Make "end" point to the actual end */
if (trans->cfg->device_family >= if (trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_8000 || IWL_DEVICE_FAMILY_8000 ||
trans->dbg.dest_tlv->monitor_mode == MARBH_MODE) trans->dbg.dest_tlv->monitor_mode == MARBH_MODE)
end += (1 << trans->dbg.dest_tlv->end_shift); end += (1 << trans->dbg.dest_tlv->end_shift);
@ -3184,7 +3202,7 @@ static struct iwl_trans_dump_data
u32 len, num_rbs = 0, monitor_len = 0; u32 len, num_rbs = 0, monitor_len = 0;
int i, ptr; int i, ptr;
bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status) && bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status) &&
!trans->cfg->mq_rx_supported && !trans->trans_cfg->mq_rx_supported &&
dump_mask & BIT(IWL_FW_ERROR_DUMP_RB); dump_mask & BIT(IWL_FW_ERROR_DUMP_RB);
if (!dump_mask) if (!dump_mask)
@ -3209,7 +3227,7 @@ static struct iwl_trans_dump_data
/* FH registers */ /* FH registers */
if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) { if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) {
if (trans->cfg->gen2) if (trans->trans_cfg->gen2)
len += sizeof(*data) + len += sizeof(*data) +
(iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2) - (iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2) -
iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2)); iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2));
@ -3233,7 +3251,7 @@ static struct iwl_trans_dump_data
} }
/* Paged memory for gen2 HW */ /* Paged memory for gen2 HW */
if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) if (trans->trans_cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING))
for (i = 0; i < trans->init_dram.paging_cnt; i++) for (i = 0; i < trans->init_dram.paging_cnt; i++)
len += sizeof(*data) + len += sizeof(*data) +
sizeof(struct iwl_fw_error_dump_paging) + sizeof(struct iwl_fw_error_dump_paging) +
@ -3288,7 +3306,8 @@ static struct iwl_trans_dump_data
len += iwl_trans_pcie_dump_rbs(trans, &data, num_rbs); len += iwl_trans_pcie_dump_rbs(trans, &data, num_rbs);
/* Paged memory for gen2 HW */ /* Paged memory for gen2 HW */
if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) { if (trans->trans_cfg->gen2 &&
dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) {
for (i = 0; i < trans->init_dram.paging_cnt; i++) { for (i = 0; i < trans->init_dram.paging_cnt; i++) {
struct iwl_fw_error_dump_paging *paging; struct iwl_fw_error_dump_paging *paging;
u32 page_len = trans->init_dram.paging[i].size; u32 page_len = trans->init_dram.paging[i].size;
@ -3315,18 +3334,11 @@ static struct iwl_trans_dump_data
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int iwl_trans_pcie_suspend(struct iwl_trans *trans) static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
{ {
if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3 &&
(trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3))
return iwl_pci_fw_enter_d0i3(trans);
return 0; return 0;
} }
static void iwl_trans_pcie_resume(struct iwl_trans *trans) static void iwl_trans_pcie_resume(struct iwl_trans *trans)
{ {
if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3 &&
(trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3))
iwl_pci_fw_exit_d0i3(trans);
} }
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
@ -3345,8 +3357,6 @@ static void iwl_trans_pcie_resume(struct iwl_trans *trans)
.grab_nic_access = iwl_trans_pcie_grab_nic_access, \ .grab_nic_access = iwl_trans_pcie_grab_nic_access, \
.release_nic_access = iwl_trans_pcie_release_nic_access, \ .release_nic_access = iwl_trans_pcie_release_nic_access, \
.set_bits_mask = iwl_trans_pcie_set_bits_mask, \ .set_bits_mask = iwl_trans_pcie_set_bits_mask, \
.ref = iwl_trans_pcie_ref, \
.unref = iwl_trans_pcie_unref, \
.dump_data = iwl_trans_pcie_dump_data, \ .dump_data = iwl_trans_pcie_dump_data, \
.d3_suspend = iwl_trans_pcie_d3_suspend, \ .d3_suspend = iwl_trans_pcie_d3_suspend, \
.d3_resume = iwl_trans_pcie_d3_resume, \ .d3_resume = iwl_trans_pcie_d3_resume, \
@ -3400,6 +3410,8 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = {
.tx = iwl_trans_pcie_gen2_tx, .tx = iwl_trans_pcie_gen2_tx,
.reclaim = iwl_trans_pcie_reclaim, .reclaim = iwl_trans_pcie_reclaim,
.set_q_ptrs = iwl_trans_pcie_set_q_ptrs,
.txq_alloc = iwl_trans_pcie_dyn_txq_alloc, .txq_alloc = iwl_trans_pcie_dyn_txq_alloc,
.txq_free = iwl_trans_pcie_dyn_txq_free, .txq_free = iwl_trans_pcie_dyn_txq_free,
.wait_txq_empty = iwl_trans_pcie_wait_txq_empty, .wait_txq_empty = iwl_trans_pcie_wait_txq_empty,
@ -3411,7 +3423,7 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = {
struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
const struct pci_device_id *ent, const struct pci_device_id *ent,
const struct iwl_cfg *cfg) const struct iwl_cfg_trans_params *cfg_trans)
{ {
struct iwl_trans_pcie *trans_pcie; struct iwl_trans_pcie *trans_pcie;
struct iwl_trans *trans; struct iwl_trans *trans;
@ -3421,12 +3433,13 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
if (cfg->gen2) if (cfg_trans->gen2)
trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie),
&pdev->dev, cfg, &trans_ops_pcie_gen2); &pdev->dev, &trans_ops_pcie_gen2);
else else
trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie),
&pdev->dev, cfg, &trans_ops_pcie); &pdev->dev, &trans_ops_pcie);
if (!trans) if (!trans)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@ -3445,7 +3458,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
} }
trans_pcie->debug_rfkill = -1; trans_pcie->debug_rfkill = -1;
if (!cfg->base_params->pcie_l1_allowed) { if (!cfg_trans->base_params->pcie_l1_allowed) {
/* /*
* W/A - seems to solve weird behavior. We need to remove this * W/A - seems to solve weird behavior. We need to remove this
* if we don't want to stay in L1 all the time. This wastes a * if we don't want to stay in L1 all the time. This wastes a
@ -3458,7 +3471,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
trans_pcie->def_rx_queue = 0; trans_pcie->def_rx_queue = 0;
if (cfg->use_tfh) { if (cfg_trans->use_tfh) {
addr_size = 64; addr_size = 64;
trans_pcie->max_tbs = IWL_TFH_NUM_TBS; trans_pcie->max_tbs = IWL_TFH_NUM_TBS;
trans_pcie->tfd_size = sizeof(struct iwl_tfh_tfd); trans_pcie->tfd_size = sizeof(struct iwl_tfh_tfd);
@ -3520,9 +3533,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
* "dash" value). To keep hw_rev backwards compatible - we'll store it * "dash" value). To keep hw_rev backwards compatible - we'll store it
* in the old format. * in the old format.
*/ */
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) { if (cfg_trans->device_family >= IWL_DEVICE_FAMILY_8000) {
unsigned long flags;
trans->hw_rev = (trans->hw_rev & 0xfff0) | trans->hw_rev = (trans->hw_rev & 0xfff0) |
(CSR_HW_REV_STEP(trans->hw_rev << 2) << 2); (CSR_HW_REV_STEP(trans->hw_rev << 2) << 2);
@ -3536,94 +3547,15 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
* in-order to recognize C step driver should read chip version * in-order to recognize C step driver should read chip version
* id located at the AUX bus MISC address space. * id located at the AUX bus MISC address space.
*/ */
ret = iwl_finish_nic_init(trans); ret = iwl_finish_nic_init(trans, cfg_trans);
if (ret) if (ret)
goto out_no_pci; goto out_no_pci;
if (iwl_trans_grab_nic_access(trans, &flags)) {
u32 hw_step;
hw_step = iwl_read_umac_prph_no_grab(trans,
WFPM_CTRL_REG);
hw_step |= ENABLE_WFPM;
iwl_write_umac_prph_no_grab(trans, WFPM_CTRL_REG,
hw_step);
hw_step = iwl_read_prph_no_grab(trans,
CNVI_AUX_MISC_CHIP);
hw_step = (hw_step >> HW_STEP_LOCATION_BITS) & 0xF;
if (hw_step == 0x3)
trans->hw_rev = (trans->hw_rev & 0xFFFFFFF3) |
(SILICON_C_STEP << 2);
iwl_trans_release_nic_access(trans, &flags);
}
} }
IWL_DEBUG_INFO(trans, "HW REV: 0x%0x\n", trans->hw_rev); IWL_DEBUG_INFO(trans, "HW REV: 0x%0x\n", trans->hw_rev);
#if IS_ENABLED(CONFIG_IWLMVM) iwl_pcie_set_interrupt_capa(pdev, trans, cfg_trans);
trans->hw_rf_id = iwl_read32(trans, CSR_HW_RF_ID);
if (cfg == &iwlax210_2ax_cfg_so_hr_a0) {
if (trans->hw_rev == CSR_HW_REV_TYPE_TY) {
trans->cfg = &iwlax210_2ax_cfg_ty_gf_a0;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) {
trans->cfg = &iwlax210_2ax_cfg_so_jf_a0;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) {
trans->cfg = &iwlax211_2ax_cfg_so_gf_a0;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF4)) {
trans->cfg = &iwlax411_2ax_cfg_so_gf4_a0;
}
} else if (cfg == &iwl_ax101_cfg_qu_hr) {
if ((CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) ||
(CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR1))) {
trans->cfg = &iwl22000_2ax_cfg_qnj_hr_b0;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) {
trans->cfg = &iwl_ax101_cfg_qu_hr;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) {
trans->cfg = &iwl22000_2ax_cfg_jf;
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HRCDB)) {
IWL_ERR(trans, "RF ID HRCDB is not supported\n");
ret = -EINVAL;
goto out_no_pci;
} else {
IWL_ERR(trans, "Unrecognized RF ID 0x%08x\n",
CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id));
ret = -EINVAL;
goto out_no_pci;
}
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) {
u32 hw_status;
hw_status = iwl_read_prph(trans, UMAG_GEN_HW_STATUS);
if (CSR_HW_RF_STEP(trans->hw_rf_id) == SILICON_B_STEP)
/*
* b step fw is the same for physical card and fpga
*/
trans->cfg = &iwl22000_2ax_cfg_qnj_hr_b0;
else if ((hw_status & UMAG_GEN_HW_IS_FPGA) &&
CSR_HW_RF_STEP(trans->hw_rf_id) == SILICON_A_STEP) {
trans->cfg = &iwl22000_2ax_cfg_qnj_hr_a0_f0;
} else {
/*
* a step no FPGA
*/
trans->cfg = &iwl22000_2ac_cfg_hr;
}
}
#endif
iwl_pcie_set_interrupt_capa(pdev, trans);
trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; trans->hw_id = (pdev->device << 16) + pdev->subsystem_device;
snprintf(trans->hw_id_str, sizeof(trans->hw_id_str), snprintf(trans->hw_id_str, sizeof(trans->hw_id_str),
"PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device); "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device);
@ -3631,7 +3563,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
/* Initialize the wait queue for commands */ /* Initialize the wait queue for commands */
init_waitqueue_head(&trans_pcie->wait_command_queue); init_waitqueue_head(&trans_pcie->wait_command_queue);
init_waitqueue_head(&trans_pcie->d0i3_waitq); init_waitqueue_head(&trans_pcie->sx_waitq);
if (trans_pcie->msix_enabled) { if (trans_pcie->msix_enabled) {
ret = iwl_pcie_init_msix_handler(pdev, trans_pcie); ret = iwl_pcie_init_msix_handler(pdev, trans_pcie);
@ -3657,12 +3589,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
WQ_HIGHPRI | WQ_UNBOUND, 1); WQ_HIGHPRI | WQ_UNBOUND, 1);
INIT_WORK(&trans_pcie->rba.rx_alloc, iwl_pcie_rx_allocator_work); INIT_WORK(&trans_pcie->rba.rx_alloc, iwl_pcie_rx_allocator_work);
#ifdef CONFIG_IWLWIFI_PCIE_RTPM
trans->runtime_pm_mode = IWL_PLAT_PM_MODE_D0I3;
#else
trans->runtime_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
#endif /* CONFIG_IWLWIFI_PCIE_RTPM */
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
trans_pcie->fw_mon_data.state = IWL_FW_MON_DBGFS_STATE_CLOSED; trans_pcie->fw_mon_data.state = IWL_FW_MON_DBGFS_STATE_CLOSED;
mutex_init(&trans_pcie->fw_mon_data.mutex); mutex_init(&trans_pcie->fw_mon_data.mutex);

View File

@ -50,7 +50,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
*****************************************************************************/ *****************************************************************************/
#include <linux/pm_runtime.h>
#include <net/tso.h> #include <net/tso.h>
#include <linux/tcp.h> #include <linux/tcp.h>
@ -114,7 +113,7 @@ void iwl_pcie_gen2_update_byte_tbl(struct iwl_trans_pcie *trans_pcie,
*/ */
num_fetch_chunks = DIV_ROUND_UP(filled_tfd_size, 64) - 1; num_fetch_chunks = DIV_ROUND_UP(filled_tfd_size, 64) - 1;
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) { if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
/* Starting from 22560, the HW expects bytes */ /* Starting from 22560, the HW expects bytes */
WARN_ON(trans_pcie->bc_table_dword); WARN_ON(trans_pcie->bc_table_dword);
WARN_ON(len > 0x3FFF); WARN_ON(len > 0x3FFF);
@ -548,7 +547,7 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
memset(tfd, 0, sizeof(*tfd)); memset(tfd, 0, sizeof(*tfd));
if (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_22560)
len = sizeof(struct iwl_tx_cmd_gen2); len = sizeof(struct iwl_tx_cmd_gen2);
else else
len = sizeof(struct iwl_tx_cmd_gen3); len = sizeof(struct iwl_tx_cmd_gen3);
@ -630,7 +629,7 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
return -1; return -1;
} }
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) { if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
struct iwl_tx_cmd_gen3 *tx_cmd_gen3 = struct iwl_tx_cmd_gen3 *tx_cmd_gen3 =
(void *)dev_cmd->payload; (void *)dev_cmd->payload;
@ -647,12 +646,8 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
iwl_pcie_gen2_get_num_tbs(trans, tfd)); iwl_pcie_gen2_get_num_tbs(trans, tfd));
/* start timer if queue currently empty */ /* start timer if queue currently empty */
if (txq->read_ptr == txq->write_ptr) { if (txq->read_ptr == txq->write_ptr && txq->wd_timeout)
if (txq->wd_timeout)
mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout); mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout);
IWL_DEBUG_RPM(trans, "Q: %d first tx - take ref\n", txq->id);
iwl_trans_ref(trans);
}
/* Tell device the write index *just past* this latest filled TFD */ /* Tell device the write index *just past* this latest filled TFD */
txq->write_ptr = iwl_queue_inc_wrap(trans, txq->write_ptr); txq->write_ptr = iwl_queue_inc_wrap(trans, txq->write_ptr);
@ -897,12 +892,6 @@ static int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,
mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout); mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout);
spin_lock_irqsave(&trans_pcie->reg_lock, flags); spin_lock_irqsave(&trans_pcie->reg_lock, flags);
if (!(cmd->flags & CMD_SEND_IN_IDLE) &&
!trans_pcie->ref_cmd_in_flight) {
trans_pcie->ref_cmd_in_flight = true;
IWL_DEBUG_RPM(trans, "set ref_cmd_in_flight - ref\n");
iwl_trans_ref(trans);
}
/* Increment and update queue's write index */ /* Increment and update queue's write index */
txq->write_ptr = iwl_queue_inc_wrap(trans, txq->write_ptr); txq->write_ptr = iwl_queue_inc_wrap(trans, txq->write_ptr);
iwl_pcie_gen2_txq_inc_wr_ptr(trans, txq); iwl_pcie_gen2_txq_inc_wr_ptr(trans, txq);
@ -936,16 +925,6 @@ static int iwl_pcie_gen2_send_hcmd_sync(struct iwl_trans *trans,
IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", cmd_str); IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", cmd_str);
if (pm_runtime_suspended(&trans_pcie->pci_dev->dev)) {
ret = wait_event_timeout(trans_pcie->d0i3_waitq,
pm_runtime_active(&trans_pcie->pci_dev->dev),
msecs_to_jiffies(IWL_TRANS_IDLE_TIMEOUT));
if (!ret) {
IWL_ERR(trans, "Timeout exiting D0i3 before hcmd\n");
return -ETIMEDOUT;
}
}
cmd_idx = iwl_pcie_gen2_enqueue_hcmd(trans, cmd); cmd_idx = iwl_pcie_gen2_enqueue_hcmd(trans, cmd);
if (cmd_idx < 0) { if (cmd_idx < 0) {
ret = cmd_idx; ret = cmd_idx;
@ -1070,23 +1049,6 @@ void iwl_pcie_gen2_txq_unmap(struct iwl_trans *trans, int txq_id)
} }
iwl_pcie_gen2_free_tfd(trans, txq); iwl_pcie_gen2_free_tfd(trans, txq);
txq->read_ptr = iwl_queue_inc_wrap(trans, txq->read_ptr); txq->read_ptr = iwl_queue_inc_wrap(trans, txq->read_ptr);
if (txq->read_ptr == txq->write_ptr) {
unsigned long flags;
spin_lock_irqsave(&trans_pcie->reg_lock, flags);
if (txq_id != trans_pcie->cmd_queue) {
IWL_DEBUG_RPM(trans, "Q %d - last tx freed\n",
txq->id);
iwl_trans_unref(trans);
} else if (trans_pcie->ref_cmd_in_flight) {
trans_pcie->ref_cmd_in_flight = false;
IWL_DEBUG_RPM(trans,
"clear ref_cmd_in_flight\n");
iwl_trans_unref(trans);
}
spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
}
} }
while (!skb_queue_empty(&txq->overflow_q)) { while (!skb_queue_empty(&txq->overflow_q)) {
@ -1167,7 +1129,7 @@ int iwl_trans_pcie_dyn_txq_alloc_dma(struct iwl_trans *trans,
if (!txq) if (!txq)
return -ENOMEM; return -ENOMEM;
ret = iwl_pcie_alloc_dma_ptr(trans, &txq->bc_tbl, ret = iwl_pcie_alloc_dma_ptr(trans, &txq->bc_tbl,
(trans->cfg->device_family >= (trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_22560) ? IWL_DEVICE_FAMILY_22560) ?
sizeof(struct iwl_gen3_bc_tbl) : sizeof(struct iwl_gen3_bc_tbl) :
sizeof(struct iwlagn_scd_bc_tbl)); sizeof(struct iwlagn_scd_bc_tbl));
@ -1231,7 +1193,7 @@ int iwl_trans_pcie_txq_alloc_response(struct iwl_trans *trans,
txq->id = qid; txq->id = qid;
trans_pcie->txq[qid] = txq; trans_pcie->txq[qid] = txq;
wr_ptr &= (trans->cfg->base_params->max_tfd_queue_size - 1); wr_ptr &= (trans->trans_cfg->base_params->max_tfd_queue_size - 1);
/* Place first TFD at index corresponding to start sequence number */ /* Place first TFD at index corresponding to start sequence number */
txq->read_ptr = wr_ptr; txq->read_ptr = wr_ptr;

View File

@ -65,7 +65,6 @@
#include <linux/ieee80211.h> #include <linux/ieee80211.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/pm_runtime.h>
#include <net/ip6_checksum.h> #include <net/ip6_checksum.h>
#include <net/tso.h> #include <net/tso.h>
@ -114,17 +113,17 @@ int iwl_queue_space(struct iwl_trans *trans, const struct iwl_txq *q)
* If q->n_window is smaller than max_tfd_queue_size, there is no need * If q->n_window is smaller than max_tfd_queue_size, there is no need
* to reserve any queue entries for this purpose. * to reserve any queue entries for this purpose.
*/ */
if (q->n_window < trans->cfg->base_params->max_tfd_queue_size) if (q->n_window < trans->trans_cfg->base_params->max_tfd_queue_size)
max = q->n_window; max = q->n_window;
else else
max = trans->cfg->base_params->max_tfd_queue_size - 1; max = trans->trans_cfg->base_params->max_tfd_queue_size - 1;
/* /*
* max_tfd_queue_size is a power of 2, so the following is equivalent to * max_tfd_queue_size is a power of 2, so the following is equivalent to
* modulo by max_tfd_queue_size and is well defined. * modulo by max_tfd_queue_size and is well defined.
*/ */
used = (q->write_ptr - q->read_ptr) & used = (q->write_ptr - q->read_ptr) &
(trans->cfg->base_params->max_tfd_queue_size - 1); (trans->trans_cfg->base_params->max_tfd_queue_size - 1);
if (WARN_ON(used > max)) if (WARN_ON(used > max))
return 0; return 0;
@ -293,7 +292,7 @@ static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans,
* 2. NIC is woken up for CMD regardless of shadow outside this function * 2. NIC is woken up for CMD regardless of shadow outside this function
* 3. there is a chance that the NIC is asleep * 3. there is a chance that the NIC is asleep
*/ */
if (!trans->cfg->base_params->shadow_reg_enable && if (!trans->trans_cfg->base_params->shadow_reg_enable &&
txq_id != trans_pcie->cmd_queue && txq_id != trans_pcie->cmd_queue &&
test_bit(STATUS_TPOWER_PMI, &trans->status)) { test_bit(STATUS_TPOWER_PMI, &trans->status)) {
/* /*
@ -307,7 +306,7 @@ static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans,
IWL_DEBUG_INFO(trans, "Tx queue %d requesting wakeup, GP1 = 0x%x\n", IWL_DEBUG_INFO(trans, "Tx queue %d requesting wakeup, GP1 = 0x%x\n",
txq_id, reg); txq_id, reg);
iwl_set_bit(trans, CSR_GP_CNTRL, iwl_set_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_mac_access_req)); BIT(trans->trans_cfg->csr->flag_mac_access_req));
txq->need_update = true; txq->need_update = true;
return; return;
} }
@ -328,7 +327,7 @@ void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int i; int i;
for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { for (i = 0; i < trans->trans_cfg->base_params->num_of_queues; i++) {
struct iwl_txq *txq = trans_pcie->txq[i]; struct iwl_txq *txq = trans_pcie->txq[i];
if (!test_bit(i, trans_pcie->queue_used)) if (!test_bit(i, trans_pcie->queue_used))
@ -347,7 +346,7 @@ static inline dma_addr_t iwl_pcie_tfd_tb_get_addr(struct iwl_trans *trans,
void *_tfd, u8 idx) void *_tfd, u8 idx)
{ {
if (trans->cfg->use_tfh) { if (trans->trans_cfg->use_tfh) {
struct iwl_tfh_tfd *tfd = _tfd; struct iwl_tfh_tfd *tfd = _tfd;
struct iwl_tfh_tb *tb = &tfd->tbs[idx]; struct iwl_tfh_tb *tb = &tfd->tbs[idx];
@ -390,7 +389,7 @@ static inline void iwl_pcie_tfd_set_tb(struct iwl_trans *trans, void *tfd,
static inline u8 iwl_pcie_tfd_get_num_tbs(struct iwl_trans *trans, void *_tfd) static inline u8 iwl_pcie_tfd_get_num_tbs(struct iwl_trans *trans, void *_tfd)
{ {
if (trans->cfg->use_tfh) { if (trans->trans_cfg->use_tfh) {
struct iwl_tfh_tfd *tfd = _tfd; struct iwl_tfh_tfd *tfd = _tfd;
return le16_to_cpu(tfd->num_tbs) & 0x1f; return le16_to_cpu(tfd->num_tbs) & 0x1f;
@ -437,7 +436,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
meta->tbs = 0; meta->tbs = 0;
if (trans->cfg->use_tfh) { if (trans->trans_cfg->use_tfh) {
struct iwl_tfh_tfd *tfd_fh = (void *)tfd; struct iwl_tfh_tfd *tfd_fh = (void *)tfd;
tfd_fh->num_tbs = 0; tfd_fh->num_tbs = 0;
@ -525,14 +524,14 @@ int iwl_pcie_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq,
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
size_t tfd_sz = trans_pcie->tfd_size * size_t tfd_sz = trans_pcie->tfd_size *
trans->cfg->base_params->max_tfd_queue_size; trans->trans_cfg->base_params->max_tfd_queue_size;
size_t tb0_buf_sz; size_t tb0_buf_sz;
int i; int i;
if (WARN_ON(txq->entries || txq->tfds)) if (WARN_ON(txq->entries || txq->tfds))
return -EINVAL; return -EINVAL;
if (trans->cfg->use_tfh) if (trans->trans_cfg->use_tfh)
tfd_sz = trans_pcie->tfd_size * slots_num; tfd_sz = trans_pcie->tfd_size * slots_num;
timer_setup(&txq->stuck_timer, iwl_pcie_txq_stuck_timer, 0); timer_setup(&txq->stuck_timer, iwl_pcie_txq_stuck_timer, 0);
@ -591,7 +590,8 @@ int iwl_pcie_txq_init(struct iwl_trans *trans, struct iwl_txq *txq,
int slots_num, bool cmd_queue) int slots_num, bool cmd_queue)
{ {
int ret; int ret;
u32 tfd_queue_max_size = trans->cfg->base_params->max_tfd_queue_size; u32 tfd_queue_max_size =
trans->trans_cfg->base_params->max_tfd_queue_size;
txq->need_update = false; txq->need_update = false;
@ -639,20 +639,14 @@ static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
lockdep_assert_held(&trans_pcie->reg_lock); lockdep_assert_held(&trans_pcie->reg_lock);
if (trans_pcie->ref_cmd_in_flight) { if (!trans->trans_cfg->base_params->apmg_wake_up_wa)
trans_pcie->ref_cmd_in_flight = false;
IWL_DEBUG_RPM(trans, "clear ref_cmd_in_flight - unref\n");
iwl_trans_unref(trans);
}
if (!trans->cfg->base_params->apmg_wake_up_wa)
return; return;
if (WARN_ON(!trans_pcie->cmd_hold_nic_awake)) if (WARN_ON(!trans_pcie->cmd_hold_nic_awake))
return; return;
trans_pcie->cmd_hold_nic_awake = false; trans_pcie->cmd_hold_nic_awake = false;
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
BIT(trans->cfg->csr->flag_mac_access_req)); BIT(trans->trans_cfg->csr->flag_mac_access_req));
} }
/* /*
@ -683,13 +677,8 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&trans_pcie->reg_lock, flags); spin_lock_irqsave(&trans_pcie->reg_lock, flags);
if (txq_id != trans_pcie->cmd_queue) { if (txq_id == trans_pcie->cmd_queue)
IWL_DEBUG_RPM(trans, "Q %d - last tx freed\n",
txq->id);
iwl_trans_unref(trans);
} else {
iwl_pcie_clear_cmd_in_flight(trans); iwl_pcie_clear_cmd_in_flight(trans);
}
spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
} }
} }
@ -737,7 +726,7 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
if (txq->tfds) { if (txq->tfds) {
dma_free_coherent(dev, dma_free_coherent(dev,
trans_pcie->tfd_size * trans_pcie->tfd_size *
trans->cfg->base_params->max_tfd_queue_size, trans->trans_cfg->base_params->max_tfd_queue_size,
txq->tfds, txq->dma_addr); txq->tfds, txq->dma_addr);
txq->dma_addr = 0; txq->dma_addr = 0;
txq->tfds = NULL; txq->tfds = NULL;
@ -759,7 +748,7 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr) void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int nq = trans->cfg->base_params->num_of_queues; int nq = trans->trans_cfg->base_params->num_of_queues;
int chan; int chan;
u32 reg_val; u32 reg_val;
int clear_dwords = (SCD_TRANS_TBL_OFFSET_QUEUE(nq) - int clear_dwords = (SCD_TRANS_TBL_OFFSET_QUEUE(nq) -
@ -786,7 +775,7 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
/* The chain extension of the SCD doesn't work well. This feature is /* The chain extension of the SCD doesn't work well. This feature is
* enabled by default by the HW, so we need to disable it manually. * enabled by default by the HW, so we need to disable it manually.
*/ */
if (trans->cfg->base_params->scd_chain_ext_wa) if (trans->trans_cfg->base_params->scd_chain_ext_wa)
iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); iwl_write_prph(trans, SCD_CHAINEXT_EN, 0);
iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue, iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue,
@ -808,7 +797,7 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
/* Enable L1-Active */ /* Enable L1-Active */
if (trans->cfg->device_family < IWL_DEVICE_FAMILY_8000) if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000)
iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS); APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
} }
@ -822,13 +811,13 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans)
* we should never get here in gen2 trans mode return early to avoid * we should never get here in gen2 trans mode return early to avoid
* having invalid accesses * having invalid accesses
*/ */
if (WARN_ON_ONCE(trans->cfg->gen2)) if (WARN_ON_ONCE(trans->trans_cfg->gen2))
return; return;
for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues;
txq_id++) { txq_id++) {
struct iwl_txq *txq = trans_pcie->txq[txq_id]; struct iwl_txq *txq = trans_pcie->txq[txq_id];
if (trans->cfg->use_tfh) if (trans->trans_cfg->use_tfh)
iwl_write_direct64(trans, iwl_write_direct64(trans,
FH_MEM_CBBC_QUEUE(trans, txq_id), FH_MEM_CBBC_QUEUE(trans, txq_id),
txq->dma_addr); txq->dma_addr);
@ -911,7 +900,7 @@ int iwl_pcie_tx_stop(struct iwl_trans *trans)
return 0; return 0;
/* Unmap DMA from host system and free skb's */ /* Unmap DMA from host system and free skb's */
for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues;
txq_id++) txq_id++)
iwl_pcie_txq_unmap(trans, txq_id); iwl_pcie_txq_unmap(trans, txq_id);
@ -933,7 +922,7 @@ void iwl_pcie_tx_free(struct iwl_trans *trans)
/* Tx queues */ /* Tx queues */
if (trans_pcie->txq_memory) { if (trans_pcie->txq_memory) {
for (txq_id = 0; for (txq_id = 0;
txq_id < trans->cfg->base_params->num_of_queues; txq_id < trans->trans_cfg->base_params->num_of_queues;
txq_id++) { txq_id++) {
iwl_pcie_txq_free(trans, txq_id); iwl_pcie_txq_free(trans, txq_id);
trans_pcie->txq[txq_id] = NULL; trans_pcie->txq[txq_id] = NULL;
@ -957,9 +946,10 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
int ret; int ret;
int txq_id, slots_num; int txq_id, slots_num;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
u16 bc_tbls_size = trans->cfg->base_params->num_of_queues; u16 bc_tbls_size = trans->trans_cfg->base_params->num_of_queues;
bc_tbls_size *= (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) ? bc_tbls_size *= (trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_22560) ?
sizeof(struct iwl_gen3_bc_tbl) : sizeof(struct iwl_gen3_bc_tbl) :
sizeof(struct iwlagn_scd_bc_tbl); sizeof(struct iwlagn_scd_bc_tbl);
@ -984,7 +974,8 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
goto error; goto error;
} }
trans_pcie->txq_memory = kcalloc(trans->cfg->base_params->num_of_queues, trans_pcie->txq_memory =
kcalloc(trans->trans_cfg->base_params->num_of_queues,
sizeof(struct iwl_txq), GFP_KERNEL); sizeof(struct iwl_txq), GFP_KERNEL);
if (!trans_pcie->txq_memory) { if (!trans_pcie->txq_memory) {
IWL_ERR(trans, "Not enough memory for txq\n"); IWL_ERR(trans, "Not enough memory for txq\n");
@ -993,7 +984,7 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
} }
/* Alloc and init all Tx queues, including the command queue (#4/#9) */ /* Alloc and init all Tx queues, including the command queue (#4/#9) */
for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues;
txq_id++) { txq_id++) {
bool cmd_queue = (txq_id == trans_pcie->cmd_queue); bool cmd_queue = (txq_id == trans_pcie->cmd_queue);
@ -1047,7 +1038,7 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
spin_unlock(&trans_pcie->irq_lock); spin_unlock(&trans_pcie->irq_lock);
/* Alloc and init all Tx queues, including the command queue (#4/#9) */ /* Alloc and init all Tx queues, including the command queue (#4/#9) */
for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues;
txq_id++) { txq_id++) {
bool cmd_queue = (txq_id == trans_pcie->cmd_queue); bool cmd_queue = (txq_id == trans_pcie->cmd_queue);
@ -1075,7 +1066,7 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
} }
iwl_set_bits_prph(trans, SCD_GP_CTRL, SCD_GP_CTRL_AUTO_ACTIVE_MODE); iwl_set_bits_prph(trans, SCD_GP_CTRL, SCD_GP_CTRL_AUTO_ACTIVE_MODE);
if (trans->cfg->base_params->num_of_queues > 20) if (trans->trans_cfg->base_params->num_of_queues > 20)
iwl_set_bits_prph(trans, SCD_GP_CTRL, iwl_set_bits_prph(trans, SCD_GP_CTRL,
SCD_GP_CTRL_ENABLE_31_QUEUES); SCD_GP_CTRL_ENABLE_31_QUEUES);
@ -1147,7 +1138,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
IWL_ERR(trans, IWL_ERR(trans,
"%s: Read index for txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n", "%s: Read index for txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n",
__func__, txq_id, last_to_free, __func__, txq_id, last_to_free,
trans->cfg->base_params->max_tfd_queue_size, trans->trans_cfg->base_params->max_tfd_queue_size,
txq->write_ptr, txq->read_ptr); txq->write_ptr, txq->read_ptr);
goto out; goto out;
} }
@ -1170,7 +1161,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
txq->entries[read_ptr].skb = NULL; txq->entries[read_ptr].skb = NULL;
if (!trans->cfg->use_tfh) if (!trans->trans_cfg->use_tfh)
iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq); iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq);
iwl_pcie_txq_free_tfd(trans, txq); iwl_pcie_txq_free_tfd(trans, txq);
@ -1225,12 +1216,21 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
txq->overflow_tx = false; txq->overflow_tx = false;
} }
if (txq->read_ptr == txq->write_ptr) { out:
IWL_DEBUG_RPM(trans, "Q %d - last tx reclaimed\n", txq->id); spin_unlock_bh(&txq->lock);
iwl_trans_unref(trans);
} }
out: /* Set wr_ptr of specific device and txq */
void iwl_trans_pcie_set_q_ptrs(struct iwl_trans *trans, int txq_id, int ptr)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *txq = trans_pcie->txq[txq_id];
spin_lock_bh(&txq->lock);
txq->write_ptr = ptr;
txq->read_ptr = txq->write_ptr;
spin_unlock_bh(&txq->lock); spin_unlock_bh(&txq->lock);
} }
@ -1238,7 +1238,6 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
const struct iwl_host_cmd *cmd) const struct iwl_host_cmd *cmd)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
const struct iwl_cfg *cfg = trans->cfg;
int ret; int ret;
lockdep_assert_held(&trans_pcie->reg_lock); lockdep_assert_held(&trans_pcie->reg_lock);
@ -1247,32 +1246,25 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
if (test_bit(STATUS_TRANS_DEAD, &trans->status)) if (test_bit(STATUS_TRANS_DEAD, &trans->status))
return -ENODEV; return -ENODEV;
if (!(cmd->flags & CMD_SEND_IN_IDLE) &&
!trans_pcie->ref_cmd_in_flight) {
trans_pcie->ref_cmd_in_flight = true;
IWL_DEBUG_RPM(trans, "set ref_cmd_in_flight - ref\n");
iwl_trans_ref(trans);
}
/* /*
* wake up the NIC to make sure that the firmware will see the host * wake up the NIC to make sure that the firmware will see the host
* command - we will let the NIC sleep once all the host commands * command - we will let the NIC sleep once all the host commands
* returned. This needs to be done only on NICs that have * returned. This needs to be done only on NICs that have
* apmg_wake_up_wa set. * apmg_wake_up_wa set.
*/ */
if (cfg->base_params->apmg_wake_up_wa && if (trans->trans_cfg->base_params->apmg_wake_up_wa &&
!trans_pcie->cmd_hold_nic_awake) { !trans_pcie->cmd_hold_nic_awake) {
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
BIT(cfg->csr->flag_mac_access_req)); BIT(trans->trans_cfg->csr->flag_mac_access_req));
ret = iwl_poll_bit(trans, CSR_GP_CNTRL, ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
BIT(cfg->csr->flag_val_mac_access_en), BIT(trans->trans_cfg->csr->flag_val_mac_access_en),
(BIT(cfg->csr->flag_mac_clock_ready) | (BIT(trans->trans_cfg->csr->flag_mac_clock_ready) |
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP),
15000); 15000);
if (ret < 0) { if (ret < 0) {
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
BIT(cfg->csr->flag_mac_access_req)); BIT(trans->trans_cfg->csr->flag_mac_access_req));
IWL_ERR(trans, "Failed to wake NIC for hcmd\n"); IWL_ERR(trans, "Failed to wake NIC for hcmd\n");
return -EIO; return -EIO;
} }
@ -1302,12 +1294,12 @@ void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
idx = iwl_pcie_get_cmd_index(txq, idx); idx = iwl_pcie_get_cmd_index(txq, idx);
r = iwl_pcie_get_cmd_index(txq, txq->read_ptr); r = iwl_pcie_get_cmd_index(txq, txq->read_ptr);
if (idx >= trans->cfg->base_params->max_tfd_queue_size || if (idx >= trans->trans_cfg->base_params->max_tfd_queue_size ||
(!iwl_queue_used(txq, idx))) { (!iwl_queue_used(txq, idx))) {
WARN_ONCE(test_bit(txq_id, trans_pcie->queue_used), WARN_ONCE(test_bit(txq_id, trans_pcie->queue_used),
"%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n", "%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n",
__func__, txq_id, idx, __func__, txq_id, idx,
trans->cfg->base_params->max_tfd_queue_size, trans->trans_cfg->base_params->max_tfd_queue_size,
txq->write_ptr, txq->read_ptr); txq->write_ptr, txq->read_ptr);
return; return;
} }
@ -1421,7 +1413,7 @@ bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
* this sad hardware issue. * this sad hardware issue.
* This bug has been fixed on devices 9000 and up. * This bug has been fixed on devices 9000 and up.
*/ */
scd_bug = !trans->cfg->mq_rx_supported && scd_bug = !trans->trans_cfg->mq_rx_supported &&
!((ssn - txq->write_ptr) & 0x3f) && !((ssn - txq->write_ptr) & 0x3f) &&
(ssn != txq->write_ptr); (ssn != txq->write_ptr);
if (scd_bug) if (scd_bug)
@ -1867,20 +1859,6 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
wake_up(&trans_pcie->wait_command_queue); wake_up(&trans_pcie->wait_command_queue);
} }
if (meta->flags & CMD_MAKE_TRANS_IDLE) {
IWL_DEBUG_INFO(trans, "complete %s - mark trans as idle\n",
iwl_get_cmd_string(trans, cmd->hdr.cmd));
set_bit(STATUS_TRANS_IDLE, &trans->status);
wake_up(&trans_pcie->d0i3_waitq);
}
if (meta->flags & CMD_WAKE_UP_TRANS) {
IWL_DEBUG_INFO(trans, "complete %s - clear trans idle flag\n",
iwl_get_cmd_string(trans, cmd->hdr.cmd));
clear_bit(STATUS_TRANS_IDLE, &trans->status);
wake_up(&trans_pcie->d0i3_waitq);
}
meta->flags = 0; meta->flags = 0;
spin_unlock_bh(&txq->lock); spin_unlock_bh(&txq->lock);
@ -1927,16 +1905,6 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n",
iwl_get_cmd_string(trans, cmd->id)); iwl_get_cmd_string(trans, cmd->id));
if (pm_runtime_suspended(&trans_pcie->pci_dev->dev)) {
ret = wait_event_timeout(trans_pcie->d0i3_waitq,
pm_runtime_active(&trans_pcie->pci_dev->dev),
msecs_to_jiffies(IWL_TRANS_IDLE_TIMEOUT));
if (!ret) {
IWL_ERR(trans, "Timeout exiting D0i3 before hcmd\n");
return -ETIMEDOUT;
}
}
cmd_idx = iwl_pcie_enqueue_hcmd(trans, cmd); cmd_idx = iwl_pcie_enqueue_hcmd(trans, cmd);
if (cmd_idx < 0) { if (cmd_idx < 0) {
ret = cmd_idx; ret = cmd_idx;
@ -2504,8 +2472,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
wait_write_ptr = ieee80211_has_morefrags(fc); wait_write_ptr = ieee80211_has_morefrags(fc);
/* start timer if queue currently empty */ /* start timer if queue currently empty */
if (txq->read_ptr == txq->write_ptr) { if (txq->read_ptr == txq->write_ptr && txq->wd_timeout) {
if (txq->wd_timeout) {
/* /*
* If the TXQ is active, then set the timer, if not, * If the TXQ is active, then set the timer, if not,
* set the timer in remainder so that the timer will * set the timer in remainder so that the timer will
@ -2518,9 +2485,6 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
else else
txq->frozen_expiry_remainder = txq->wd_timeout; txq->frozen_expiry_remainder = txq->wd_timeout;
} }
IWL_DEBUG_RPM(trans, "Q: %d first tx - take ref\n", txq->id);
iwl_trans_ref(trans);
}
/* Tell device the write index *just past* this latest filled TFD */ /* Tell device the write index *just past* this latest filled TFD */
txq->write_ptr = iwl_queue_inc_wrap(trans, txq->write_ptr); txq->write_ptr = iwl_queue_inc_wrap(trans, txq->write_ptr);

View File

@ -407,10 +407,8 @@ static int prism2_enable_genesis(local_info_t *local, int hcr)
hcr); hcr);
return 0; return 0;
} else { } else {
printk(KERN_DEBUG "Readback test failed, HCR 0x%02x " printk(KERN_DEBUG "Readback test failed, HCR 0x%02x write %4ph read %4ph\n",
"write %02x %02x %02x %02x read %02x %02x %02x %02x\n", hcr, initseq, readbuf);
hcr, initseq[0], initseq[1], initseq[2], initseq[3],
readbuf[0], readbuf[1], readbuf[2], readbuf[3]);
return 1; return 1;
} }
} }

View File

@ -352,8 +352,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len,
/* read CIS; it is in even offsets in the beginning of attr_mem */ /* read CIS; it is in even offsets in the beginning of attr_mem */
for (i = 0; i < CIS_MAX_LEN; i++) for (i = 0; i < CIS_MAX_LEN; i++)
cis[i] = readb(attr_mem + 2 * i); cis[i] = readb(attr_mem + 2 * i);
printk(KERN_DEBUG "%s: CIS: %02x %02x %02x %02x %02x %02x ...\n", printk(KERN_DEBUG "%s: CIS: %6ph ...\n", dev_info, cis);
dev_info, cis[0], cis[1], cis[2], cis[3], cis[4], cis[5]);
/* set reasonable defaults for Prism2 cards just in case CIS parsing /* set reasonable defaults for Prism2 cards just in case CIS parsing
* fails */ * fails */

View File

@ -234,7 +234,7 @@ static int prism2_io_debug_proc_read(char *page, char **start, off_t off,
{ {
local_info_t *local = (local_info_t *) data; local_info_t *local = (local_info_t *) data;
int head = local->io_debug_head; int head = local->io_debug_head;
int start_bytes, left, copy, copied; int start_bytes, left, copy;
if (off + count > PRISM2_IO_DEBUG_SIZE * 4) { if (off + count > PRISM2_IO_DEBUG_SIZE * 4) {
*eof = 1; *eof = 1;
@ -243,7 +243,6 @@ static int prism2_io_debug_proc_read(char *page, char **start, off_t off,
count = PRISM2_IO_DEBUG_SIZE * 4 - off; count = PRISM2_IO_DEBUG_SIZE * 4 - off;
} }
copied = 0;
start_bytes = (PRISM2_IO_DEBUG_SIZE - head) * 4; start_bytes = (PRISM2_IO_DEBUG_SIZE - head) * 4;
left = count; left = count;

View File

@ -1,17 +1,6 @@
// SPDX-License-Identifier: ISC
/* /*
* Copyright (C) 2018 Felix Fietkau <nbd@nbd.name> * Copyright (C) 2018 Felix Fietkau <nbd@nbd.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "mt76.h" #include "mt76.h"
@ -34,7 +23,8 @@ mt76_aggr_release(struct mt76_rx_tid *tid, struct sk_buff_head *frames, int idx)
} }
static void static void
mt76_rx_aggr_release_frames(struct mt76_rx_tid *tid, struct sk_buff_head *frames, mt76_rx_aggr_release_frames(struct mt76_rx_tid *tid,
struct sk_buff_head *frames,
u16 head) u16 head)
{ {
int idx; int idx;
@ -74,15 +64,14 @@ mt76_rx_aggr_check_release(struct mt76_rx_tid *tid, struct sk_buff_head *frames)
for (idx = (tid->head + 1) % tid->size; for (idx = (tid->head + 1) % tid->size;
idx != start && nframes; idx != start && nframes;
idx = (idx + 1) % tid->size) { idx = (idx + 1) % tid->size) {
skb = tid->reorder_buf[idx]; skb = tid->reorder_buf[idx];
if (!skb) if (!skb)
continue; continue;
nframes--; nframes--;
status = (struct mt76_rx_status *)skb->cb; status = (struct mt76_rx_status *)skb->cb;
if (!time_after(jiffies, status->reorder_time + if (!time_after(jiffies,
REORDER_TIMEOUT)) status->reorder_time + REORDER_TIMEOUT))
continue; continue;
mt76_rx_aggr_release_frames(tid, frames, status->seqno); mt76_rx_aggr_release_frames(tid, frames, status->seqno);
@ -233,7 +222,8 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
tid->nframes++; tid->nframes++;
mt76_rx_aggr_release_head(tid, frames); mt76_rx_aggr_release_head(tid, frames);
ieee80211_queue_delayed_work(tid->dev->hw, &tid->reorder_work, REORDER_TIMEOUT); ieee80211_queue_delayed_work(tid->dev->hw, &tid->reorder_work,
REORDER_TIMEOUT);
out: out:
spin_unlock_bh(&tid->lock); spin_unlock_bh(&tid->lock);

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