forked from Minki/linux
wireless-drivers-next patches for 5.5
First set of patches for 5.5. The most active driver here clearly is rtw88, lots of patches for it. More quiet on other drivers, smaller fixes and cleanups all over. This pull request also has a trivial conflict, the report and example resolution here: https://lkml.kernel.org/r/20191031111242.50ab1eca@canb.auug.org.au Major changes: rtw88 * add deep power save support * add mac80211 software tx queue (wake_tx_queue) support * enable hardware rate control * add TX-AMSDU support * add NL80211_EXT_FEATURE_CAN_REPLACE_PTK0 support * add power tracking support * add 802.11ac beamformee support * add set_bitrate_mask support * add phy_info debugfs to show Tx/Rx physical status * add RFE type 3 support for 8822b ath10k * add support for hardware rfkill on devices where firmware supports it rtl8xxxu * add bluetooth co-existence support for single antenna iwlwifi * Revamp the debugging infrastructure -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJdwYyqAAoJEG4XJFUm622b/jMH/0KUcGz8y4gkk2B2lMRyUOTu t84LiSHxcsq6letlr/vak4S6NrxMLP8Z/ByyoKC8o3yeVsdyMNMSLZAztFFhxdXr Haky2SM10q6vnn9s1skXS/qkHSd2WdUFT2DgYxyOPCtJUazVKjcboJ4YX/TUg99a 5eqPpZ4RXtW6uOmWHS7JXtLcCFPywKPBtMAjLEDMYOUSSBWExBNyNZNhznSS3ywY 4VKvc675gXE+WD3qXRhL8EJjyed94yuS3wYbKWp8iTaIRyluDmc5lVhjWH1A0HLE Qb62QL8XLtbX5fcTnaupdAIXwxeIBylOBe8QtW7QUbAnGFf8bexLxfnQM+To4wI= =24zD -----END PGP SIGNATURE----- Merge tag 'wireless-drivers-next-2019-11-05' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next Kalle Valo says: ==================== wireless-drivers-next patches for 5.5 First set of patches for 5.5. The most active driver here clearly is rtw88, lots of patches for it. More quiet on other drivers, smaller fixes and cleanups all over. This pull request also has a trivial conflict, the report and example resolution here: https://lkml.kernel.org/r/20191031111242.50ab1eca@canb.auug.org.au Major changes: rtw88 * add deep power save support * add mac80211 software tx queue (wake_tx_queue) support * enable hardware rate control * add TX-AMSDU support * add NL80211_EXT_FEATURE_CAN_REPLACE_PTK0 support * add power tracking support * add 802.11ac beamformee support * add set_bitrate_mask support * add phy_info debugfs to show Tx/Rx physical status * add RFE type 3 support for 8822b ath10k * add support for hardware rfkill on devices where firmware supports it rtl8xxxu * add bluetooth co-existence support for single antenna iwlwifi * Revamp the debugging infrastructure ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
a3ead21d6e
@ -81,6 +81,12 @@ Optional properties:
|
||||
Definition: Name of external front end module used. Some valid FEM names
|
||||
for example: "microsemi-lx5586", "sky85703-11"
|
||||
and "sky85803" etc.
|
||||
- qcom,snoc-host-cap-8bit-quirk:
|
||||
Usage: Optional
|
||||
Value type: <empty>
|
||||
Definition: Quirk specifying that the firmware expects the 8bit version
|
||||
of the host capability QMI request
|
||||
- qcom,xo-cal-data: xo cal offset to be configured in xo trim register.
|
||||
|
||||
Example (to supply PCI based wifi block details):
|
||||
|
||||
|
@ -233,8 +233,10 @@ static void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
|
||||
|
||||
switch (bus->chipinfo.id) {
|
||||
case BCMA_CHIP_ID_BCM4313:
|
||||
/* enable 12 mA drive strenth for 4313 and set chipControl
|
||||
register bit 1 */
|
||||
/*
|
||||
* enable 12 mA drive strenth for 4313 and set chipControl
|
||||
* register bit 1
|
||||
*/
|
||||
bcma_chipco_chipctl_maskset(cc, 0,
|
||||
~BCMA_CCTRL_4313_12MA_LED_DRIVE,
|
||||
BCMA_CCTRL_4313_12MA_LED_DRIVE);
|
||||
@ -246,8 +248,10 @@ static void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
|
||||
break;
|
||||
case BCMA_CHIP_ID_BCM43224:
|
||||
case BCMA_CHIP_ID_BCM43421:
|
||||
/* enable 12 mA drive strenth for 43224 and set chipControl
|
||||
register bit 15 */
|
||||
/*
|
||||
* enable 12 mA drive strenth for 43224 and set chipControl
|
||||
* register bit 15
|
||||
*/
|
||||
if (bus->chipinfo.rev == 0) {
|
||||
bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL,
|
||||
~BCMA_CCTRL_43224_GPIO_TOGGLE,
|
||||
@ -500,8 +504,10 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
|
||||
case BCMA_CHIP_ID_BCM53572:
|
||||
/* 5357[ab]0, 43236[ab]0, and 6362b0 */
|
||||
|
||||
/* BCM5357 needs to touch PLL1_PLLCTL[02],
|
||||
so offset PLL0_PLLCTL[02] by 6 */
|
||||
/*
|
||||
* BCM5357 needs to touch PLL1_PLLCTL[02],
|
||||
* so offset PLL0_PLLCTL[02] by 6
|
||||
*/
|
||||
phypll_offset = (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
|
||||
bus->chipinfo.id == BCMA_CHIP_ID_BCM4749 ||
|
||||
bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0;
|
||||
@ -619,8 +625,10 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
|
||||
case BCMA_CHIP_ID_BCM43228:
|
||||
case BCMA_CHIP_ID_BCM43428:
|
||||
/* LCNXN */
|
||||
/* PLL Settings for spur avoidance on/off mode,
|
||||
no on2 support for 43228A0 */
|
||||
/*
|
||||
* PLL Settings for spur avoidance on/off mode,
|
||||
* no on2 support for 43228A0
|
||||
*/
|
||||
if (spuravoid == 1) {
|
||||
bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
|
||||
0x01100014);
|
||||
|
@ -1781,8 +1781,8 @@ static int adm8211_probe(struct pci_dev *pdev,
|
||||
{
|
||||
struct ieee80211_hw *dev;
|
||||
struct adm8211_priv *priv;
|
||||
unsigned long mem_addr, mem_len;
|
||||
unsigned int io_addr, io_len;
|
||||
unsigned long mem_len;
|
||||
unsigned int io_len;
|
||||
int err;
|
||||
u32 reg;
|
||||
u8 perm_addr[ETH_ALEN];
|
||||
@ -1794,9 +1794,7 @@ static int adm8211_probe(struct pci_dev *pdev,
|
||||
return err;
|
||||
}
|
||||
|
||||
io_addr = pci_resource_start(pdev, 0);
|
||||
io_len = pci_resource_len(pdev, 0);
|
||||
mem_addr = pci_resource_start(pdev, 1);
|
||||
mem_len = pci_resource_len(pdev, 1);
|
||||
if (io_len < 256 || mem_len < 1024) {
|
||||
printk(KERN_ERR "%s (adm8211): Too short PCI resources\n",
|
||||
|
@ -255,7 +255,8 @@ static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata,
|
||||
|
||||
if (flags & AR5523_CMD_FLAG_MAGIC)
|
||||
hdr->magic = cpu_to_be32(1 << 24);
|
||||
memcpy(hdr + 1, idata, ilen);
|
||||
if (ilen)
|
||||
memcpy(hdr + 1, idata, ilen);
|
||||
|
||||
cmd->odata = odata;
|
||||
cmd->olen = olen;
|
||||
|
@ -1704,9 +1704,6 @@ ath10k_ce_alloc_dest_ring_64(struct ath10k *ar, unsigned int ce_id,
|
||||
/* Correctly initialize memory to 0 to prevent garbage
|
||||
* data crashing system when download firmware
|
||||
*/
|
||||
memset(dest_ring->base_addr_owner_space_unaligned, 0,
|
||||
nentries * sizeof(struct ce_desc_64) + CE_DESC_RING_ALIGN);
|
||||
|
||||
dest_ring->base_addr_owner_space =
|
||||
PTR_ALIGN(dest_ring->base_addr_owner_space_unaligned,
|
||||
CE_DESC_RING_ALIGN);
|
||||
@ -2019,8 +2016,6 @@ void ath10k_ce_alloc_rri(struct ath10k *ar)
|
||||
value |= ar->hw_ce_regs->upd->mask;
|
||||
ath10k_ce_write32(ar, ce_base_addr + ctrl1_regs, value);
|
||||
}
|
||||
|
||||
memset(ce->vaddr_rri, 0, CE_COUNT * sizeof(u32));
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_ce_alloc_rri);
|
||||
|
||||
|
@ -677,13 +677,22 @@ static void ath10k_send_suspend_complete(struct ath10k *ar)
|
||||
complete(&ar->target_suspend);
|
||||
}
|
||||
|
||||
static void ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
{
|
||||
int ret;
|
||||
u32 param = 0;
|
||||
|
||||
ath10k_bmi_write32(ar, hi_mbox_io_block_sz, 256);
|
||||
ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99);
|
||||
ath10k_bmi_read32(ar, hi_acs_flags, ¶m);
|
||||
ret = ath10k_bmi_write32(ar, hi_mbox_io_block_sz, 256);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ath10k_bmi_read32(ar, hi_acs_flags, ¶m);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Data transfer is not initiated, when reduced Tx completion
|
||||
* is used for SDIO. disable it until fixed
|
||||
@ -700,14 +709,23 @@ static void ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
else
|
||||
param |= HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET;
|
||||
|
||||
ath10k_bmi_write32(ar, hi_acs_flags, param);
|
||||
ret = ath10k_bmi_write32(ar, hi_acs_flags, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Explicitly set fwlog prints to zero as target may turn it on
|
||||
* based on scratch registers.
|
||||
*/
|
||||
ath10k_bmi_read32(ar, hi_option_flag, ¶m);
|
||||
ret = ath10k_bmi_read32(ar, hi_option_flag, ¶m);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
param |= HI_OPTION_DISABLE_DBGLOG;
|
||||
ath10k_bmi_write32(ar, hi_option_flag, param);
|
||||
ret = ath10k_bmi_write32(ar, hi_option_flag, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_init_configure_target(struct ath10k *ar)
|
||||
@ -2565,8 +2583,13 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
if (status)
|
||||
goto err;
|
||||
|
||||
if (ar->hif.bus == ATH10K_BUS_SDIO)
|
||||
ath10k_init_sdio(ar, mode);
|
||||
if (ar->hif.bus == ATH10K_BUS_SDIO) {
|
||||
status = ath10k_init_sdio(ar, mode);
|
||||
if (status) {
|
||||
ath10k_err(ar, "failed to init SDIO: %d\n", status);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ar->htc.htc_ops.target_send_suspend_complete =
|
||||
@ -2787,7 +2810,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
|
||||
status = ath10k_hif_set_target_log_mode(ar, fw_diag_log);
|
||||
if (status && status != -EOPNOTSUPP) {
|
||||
ath10k_warn(ar, "set traget log mode faileds: %d\n", status);
|
||||
ath10k_warn(ar, "set target log mode failed: %d\n", status);
|
||||
goto err_hif_stop;
|
||||
}
|
||||
|
||||
|
@ -169,6 +169,7 @@ struct ath10k_wmi {
|
||||
struct wmi_cmd_map *cmd;
|
||||
struct wmi_vdev_param_map *vdev_param;
|
||||
struct wmi_pdev_param_map *pdev_param;
|
||||
struct wmi_peer_param_map *peer_param;
|
||||
const struct wmi_ops *ops;
|
||||
const struct wmi_peer_flags_map *peer_flags;
|
||||
|
||||
@ -963,12 +964,20 @@ struct ath10k {
|
||||
u32 hw_eeprom_rd;
|
||||
u32 ht_cap_info;
|
||||
u32 vht_cap_info;
|
||||
u32 vht_supp_mcs;
|
||||
u32 num_rf_chains;
|
||||
u32 max_spatial_stream;
|
||||
/* protected by conf_mutex */
|
||||
u32 low_2ghz_chan;
|
||||
u32 high_2ghz_chan;
|
||||
u32 low_5ghz_chan;
|
||||
u32 high_5ghz_chan;
|
||||
bool ani_enabled;
|
||||
u32 sys_cap_info;
|
||||
|
||||
/* protected by data_lock */
|
||||
bool hw_rfkill_on;
|
||||
|
||||
/* protected by conf_mutex */
|
||||
u8 ps_state_enable;
|
||||
|
||||
|
@ -703,7 +703,7 @@ static const struct ath10k_mem_region qca99x0_hw20_mem_regions[] = {
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_REG,
|
||||
.start = 0x98000,
|
||||
.start = 0x980000,
|
||||
.len = 0x50000,
|
||||
.name = "IRAM",
|
||||
.section_table = {
|
||||
@ -786,7 +786,7 @@ static const struct ath10k_mem_region qca9984_hw10_mem_regions[] = {
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_REG,
|
||||
.start = 0x98000,
|
||||
.start = 0x980000,
|
||||
.len = 0x50000,
|
||||
.name = "IRAM",
|
||||
.section_table = {
|
||||
@ -891,7 +891,7 @@ static const struct ath10k_mem_region qca4019_hw10_mem_regions[] = {
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_REG,
|
||||
.start = 0x98000,
|
||||
.start = 0x980000,
|
||||
.len = 0x50000,
|
||||
.name = "IRAM",
|
||||
.section_table = {
|
||||
@ -951,6 +951,19 @@ static const struct ath10k_mem_region qca4019_hw10_mem_regions[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ath10k_mem_region wcn399x_hw10_mem_regions[] = {
|
||||
{
|
||||
/* MSA region start is not fixed, hence it is assigned at runtime */
|
||||
.type = ATH10K_MEM_REGION_TYPE_MSA,
|
||||
.len = 0x100000,
|
||||
.name = "DRAM",
|
||||
.section_table = {
|
||||
.sections = NULL,
|
||||
.size = 0,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
{
|
||||
.hw_id = QCA6174_HW_1_0_VERSION,
|
||||
@ -1048,6 +1061,14 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
.size = ARRAY_SIZE(qca4019_hw10_mem_regions),
|
||||
},
|
||||
},
|
||||
{
|
||||
.hw_id = WCN3990_HW_1_0_DEV_VERSION,
|
||||
.hw_rev = ATH10K_HW_WCN3990,
|
||||
.region_table = {
|
||||
.regions = wcn399x_hw10_mem_regions,
|
||||
.size = ARRAY_SIZE(wcn399x_hw10_mem_regions),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar)
|
||||
@ -1208,9 +1229,11 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar)
|
||||
dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
|
||||
dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_RAM_DATA);
|
||||
dump_tlv->tlv_len = cpu_to_le32(crash_data->ramdump_buf_len);
|
||||
memcpy(dump_tlv->tlv_data, crash_data->ramdump_buf,
|
||||
crash_data->ramdump_buf_len);
|
||||
sofar += sizeof(*dump_tlv) + crash_data->ramdump_buf_len;
|
||||
if (crash_data->ramdump_buf_len) {
|
||||
memcpy(dump_tlv->tlv_data, crash_data->ramdump_buf,
|
||||
crash_data->ramdump_buf_len);
|
||||
sofar += sizeof(*dump_tlv) + crash_data->ramdump_buf_len;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&ar->dump_mutex);
|
||||
@ -1257,6 +1280,9 @@ int ath10k_coredump_register(struct ath10k *ar)
|
||||
if (test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask)) {
|
||||
crash_data->ramdump_buf_len = ath10k_coredump_get_ramdump_size(ar);
|
||||
|
||||
if (!crash_data->ramdump_buf_len)
|
||||
return 0;
|
||||
|
||||
crash_data->ramdump_buf = vzalloc(crash_data->ramdump_buf_len);
|
||||
if (!crash_data->ramdump_buf)
|
||||
return -ENOMEM;
|
||||
|
@ -115,6 +115,7 @@ enum ath10k_mem_region_type {
|
||||
ATH10K_MEM_REGION_TYPE_IRAM2 = 5,
|
||||
ATH10K_MEM_REGION_TYPE_IOSRAM = 6,
|
||||
ATH10K_MEM_REGION_TYPE_IOREG = 7,
|
||||
ATH10K_MEM_REGION_TYPE_MSA = 8,
|
||||
};
|
||||
|
||||
/* Define a section of the region which should be copied. As not all parts
|
||||
|
@ -430,7 +430,7 @@ ath10k_dbg_sta_write_peer_debug_trigger(struct file *file,
|
||||
}
|
||||
|
||||
ret = ath10k_wmi_peer_set_param(ar, arsta->arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_DEBUG, peer_debug_trigger);
|
||||
ar->wmi.peer_param->debug, peer_debug_trigger);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set param to trigger peer tid logs for station ret: %d\n",
|
||||
ret);
|
||||
|
@ -2726,7 +2726,7 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
peer = ath10k_peer_find_by_id(ar, peer_id);
|
||||
if (!peer) {
|
||||
if (!peer || !peer->sta) {
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
rcu_read_unlock();
|
||||
continue;
|
||||
|
@ -155,6 +155,9 @@ const struct ath10k_hw_values qca6174_values = {
|
||||
.num_target_ce_config_wlan = 7,
|
||||
.ce_desc_meta_data_mask = 0xFFFC,
|
||||
.ce_desc_meta_data_lsb = 2,
|
||||
.rfkill_pin = 16,
|
||||
.rfkill_cfg = 0,
|
||||
.rfkill_on_level = 1,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_values qca99x0_values = {
|
||||
|
@ -379,6 +379,9 @@ struct ath10k_hw_values {
|
||||
u8 num_target_ce_config_wlan;
|
||||
u16 ce_desc_meta_data_mask;
|
||||
u8 ce_desc_meta_data_lsb;
|
||||
u32 rfkill_pin;
|
||||
u32 rfkill_cfg;
|
||||
bool rfkill_on_level;
|
||||
};
|
||||
|
||||
extern const struct ath10k_hw_values qca988x_values;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/bitfield.h>
|
||||
|
||||
#include "hif.h"
|
||||
#include "core.h"
|
||||
@ -2773,7 +2774,7 @@ static int ath10k_setup_peer_smps(struct ath10k *ar, struct ath10k_vif *arvif,
|
||||
return -EINVAL;
|
||||
|
||||
return ath10k_wmi_peer_set_param(ar, arvif->vdev_id, addr,
|
||||
WMI_PEER_SMPS_STATE,
|
||||
ar->wmi.peer_param->smps_state,
|
||||
ath10k_smps_map[smps]);
|
||||
}
|
||||
|
||||
@ -2930,7 +2931,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
|
||||
* poked with peer param command.
|
||||
*/
|
||||
ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, arvif->bssid,
|
||||
WMI_PEER_DUMMY_VAR, 1);
|
||||
ar->wmi.peer_param->dummy_var, 1);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to poke peer %pM param for ps workaround on vdev %i: %d\n",
|
||||
arvif->bssid, arvif->vdev_id, ret);
|
||||
@ -3708,7 +3709,7 @@ static int ath10k_mac_tx(struct ath10k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ath10k_hw_txrx_mode txmode,
|
||||
enum ath10k_mac_tx_path txpath,
|
||||
struct sk_buff *skb)
|
||||
struct sk_buff *skb, bool noque_offchan)
|
||||
{
|
||||
struct ieee80211_hw *hw = ar->hw;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
@ -3738,10 +3739,10 @@ static int ath10k_mac_tx(struct ath10k *ar,
|
||||
}
|
||||
}
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
|
||||
if (!noque_offchan && info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
|
||||
if (!ath10k_mac_tx_frm_has_freq(ar)) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %pK\n",
|
||||
skb);
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac queued offchannel skb %pK len %d\n",
|
||||
skb, skb->len);
|
||||
|
||||
skb_queue_tail(&ar->offchan_tx_queue, skb);
|
||||
ieee80211_queue_work(hw, &ar->offchan_tx_work);
|
||||
@ -3803,8 +3804,8 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK\n",
|
||||
skb);
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK len %d\n",
|
||||
skb, skb->len);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
peer_addr = ieee80211_get_DA(hdr);
|
||||
@ -3850,7 +3851,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
||||
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
|
||||
txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode);
|
||||
|
||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
|
||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, true);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to transmit offchannel frame: %d\n",
|
||||
ret);
|
||||
@ -3860,8 +3861,8 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
||||
time_left =
|
||||
wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ);
|
||||
if (time_left == 0)
|
||||
ath10k_warn(ar, "timed out waiting for offchannel skb %pK\n",
|
||||
skb);
|
||||
ath10k_warn(ar, "timed out waiting for offchannel skb %pK, len: %d\n",
|
||||
skb, skb->len);
|
||||
|
||||
if (!peer && tmp_peer_created) {
|
||||
ret = ath10k_peer_delete(ar, vdev_id, peer_addr);
|
||||
@ -4065,7 +4066,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
skb = ieee80211_tx_dequeue(hw, txq);
|
||||
skb = ieee80211_tx_dequeue_ni(hw, txq);
|
||||
if (!skb) {
|
||||
spin_lock_bh(&ar->htt.tx_lock);
|
||||
ath10k_htt_tx_dec_pending(htt);
|
||||
@ -4097,7 +4098,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
|
||||
spin_unlock_bh(&ar->htt.tx_lock);
|
||||
}
|
||||
|
||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
|
||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, false);
|
||||
if (unlikely(ret)) {
|
||||
ath10k_warn(ar, "failed to push frame: %d\n", ret);
|
||||
|
||||
@ -4378,7 +4379,7 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
|
||||
spin_unlock_bh(&ar->htt.tx_lock);
|
||||
}
|
||||
|
||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
|
||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, false);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to transmit frame: %d\n", ret);
|
||||
if (is_htt) {
|
||||
@ -4754,6 +4755,63 @@ static int __ath10k_fetch_bb_timing_dt(struct ath10k *ar,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_mac_rfkill_config(struct ath10k *ar)
|
||||
{
|
||||
u32 param;
|
||||
int ret;
|
||||
|
||||
if (ar->hw_values->rfkill_pin == 0) {
|
||||
ath10k_warn(ar, "ath10k does not support hardware rfkill with this device\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac rfkill_pin %d rfkill_cfg %d rfkill_on_level %d",
|
||||
ar->hw_values->rfkill_pin, ar->hw_values->rfkill_cfg,
|
||||
ar->hw_values->rfkill_on_level);
|
||||
|
||||
param = FIELD_PREP(WMI_TLV_RFKILL_CFG_RADIO_LEVEL,
|
||||
ar->hw_values->rfkill_on_level) |
|
||||
FIELD_PREP(WMI_TLV_RFKILL_CFG_GPIO_PIN_NUM,
|
||||
ar->hw_values->rfkill_pin) |
|
||||
FIELD_PREP(WMI_TLV_RFKILL_CFG_PIN_AS_GPIO,
|
||||
ar->hw_values->rfkill_cfg);
|
||||
|
||||
ret = ath10k_wmi_pdev_set_param(ar,
|
||||
ar->wmi.pdev_param->rfkill_config,
|
||||
param);
|
||||
if (ret) {
|
||||
ath10k_warn(ar,
|
||||
"failed to set rfkill config 0x%x: %d\n",
|
||||
param, ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_mac_rfkill_enable_radio(struct ath10k *ar, bool enable)
|
||||
{
|
||||
enum wmi_tlv_rfkill_enable_radio param;
|
||||
int ret;
|
||||
|
||||
if (enable)
|
||||
param = WMI_TLV_RFKILL_ENABLE_RADIO_ON;
|
||||
else
|
||||
param = WMI_TLV_RFKILL_ENABLE_RADIO_OFF;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac rfkill enable %d", param);
|
||||
|
||||
ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->rfkill_enable,
|
||||
param);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set rfkill enable param %d: %d\n",
|
||||
param, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
@ -4788,6 +4846,16 @@ static int ath10k_start(struct ieee80211_hw *hw)
|
||||
goto err;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
if (ar->hw_rfkill_on) {
|
||||
ar->hw_rfkill_on = false;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
goto err;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ret = ath10k_hif_power_up(ar, ATH10K_FIRMWARE_MODE_NORMAL);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "Could not init hif: %d\n", ret);
|
||||
@ -4801,6 +4869,14 @@ static int ath10k_start(struct ieee80211_hw *hw)
|
||||
goto err_power_down;
|
||||
}
|
||||
|
||||
if (ar->sys_cap_info & WMI_TLV_SYS_CAP_INFO_RFKILL) {
|
||||
ret = ath10k_mac_rfkill_config(ar);
|
||||
if (ret && ret != -EOPNOTSUPP) {
|
||||
ath10k_warn(ar, "failed to configure rfkill: %d", ret);
|
||||
goto err_core_stop;
|
||||
}
|
||||
}
|
||||
|
||||
param = ar->wmi.pdev_param->pmf_qos;
|
||||
ret = ath10k_wmi_pdev_set_param(ar, param, 1);
|
||||
if (ret) {
|
||||
@ -4960,7 +5036,8 @@ static void ath10k_stop(struct ieee80211_hw *hw)
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
if (ar->state != ATH10K_STATE_OFF) {
|
||||
ath10k_halt(ar);
|
||||
if (!ar->hw_rfkill_on)
|
||||
ath10k_halt(ar);
|
||||
ar->state = ATH10K_STATE_OFF;
|
||||
}
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
@ -5635,6 +5712,37 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
static void ath10k_recalculate_mgmt_rate(struct ath10k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_chan_def *def)
|
||||
{
|
||||
struct ath10k_vif *arvif = (void *)vif->drv_priv;
|
||||
const struct ieee80211_supported_band *sband;
|
||||
u8 basic_rate_idx;
|
||||
int hw_rate_code;
|
||||
u32 vdev_param;
|
||||
u16 bitrate;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
sband = ar->hw->wiphy->bands[def->chan->band];
|
||||
basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
|
||||
bitrate = sband->bitrates[basic_rate_idx].bitrate;
|
||||
|
||||
hw_rate_code = ath10k_mac_get_rate_hw_value(bitrate);
|
||||
if (hw_rate_code < 0) {
|
||||
ath10k_warn(ar, "bitrate not supported %d\n", bitrate);
|
||||
return;
|
||||
}
|
||||
|
||||
vdev_param = ar->wmi.vdev_param->mgmt_rate;
|
||||
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
|
||||
hw_rate_code);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to set mgmt tx rate %d\n", ret);
|
||||
}
|
||||
|
||||
static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *info,
|
||||
@ -5645,10 +5753,9 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct cfg80211_chan_def def;
|
||||
u32 vdev_param, pdev_param, slottime, preamble;
|
||||
u16 bitrate, hw_value;
|
||||
u8 rate, basic_rate_idx, rateidx;
|
||||
int ret = 0, hw_rate_code, mcast_rate;
|
||||
u8 rate, rateidx;
|
||||
int ret = 0, mcast_rate;
|
||||
enum nl80211_band band;
|
||||
const struct ieee80211_supported_band *sband;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
@ -5872,29 +5979,9 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
arvif->vdev_id, ret);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BASIC_RATES) {
|
||||
if (ath10k_mac_vif_chan(vif, &def)) {
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
sband = ar->hw->wiphy->bands[def.chan->band];
|
||||
basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
|
||||
bitrate = sband->bitrates[basic_rate_idx].bitrate;
|
||||
|
||||
hw_rate_code = ath10k_mac_get_rate_hw_value(bitrate);
|
||||
if (hw_rate_code < 0) {
|
||||
ath10k_warn(ar, "bitrate not supported %d\n", bitrate);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
vdev_param = ar->wmi.vdev_param->mgmt_rate;
|
||||
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
|
||||
hw_rate_code);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to set mgmt tx rate %d\n", ret);
|
||||
}
|
||||
if (changed & BSS_CHANGED_BASIC_RATES &&
|
||||
!ath10k_mac_vif_chan(arvif->vif, &def))
|
||||
ath10k_recalculate_mgmt_rate(ar, vif, &def);
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
@ -6239,7 +6326,7 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
|
||||
if (sta && sta->tdls)
|
||||
ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_AUTHORIZE, 1);
|
||||
ar->wmi.peer_param->authorize, 1);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
@ -6330,7 +6417,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
|
||||
sta->addr, bw, mode);
|
||||
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_PHYMODE, mode);
|
||||
ar->wmi.peer_param->phymode, mode);
|
||||
if (err) {
|
||||
ath10k_warn(ar, "failed to update STA %pM peer phymode %d: %d\n",
|
||||
sta->addr, mode, err);
|
||||
@ -6338,7 +6425,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
|
||||
}
|
||||
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_CHAN_WIDTH, bw);
|
||||
ar->wmi.peer_param->chan_width, bw);
|
||||
if (err)
|
||||
ath10k_warn(ar, "failed to update STA %pM peer bw %d: %d\n",
|
||||
sta->addr, bw, err);
|
||||
@ -6349,7 +6436,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
|
||||
sta->addr, nss);
|
||||
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_NSS, nss);
|
||||
ar->wmi.peer_param->nss, nss);
|
||||
if (err)
|
||||
ath10k_warn(ar, "failed to update STA %pM nss %d: %d\n",
|
||||
sta->addr, nss, err);
|
||||
@ -6360,7 +6447,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
|
||||
sta->addr, smps);
|
||||
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_SMPS_STATE, smps);
|
||||
ar->wmi.peer_param->smps_state, smps);
|
||||
if (err)
|
||||
ath10k_warn(ar, "failed to update STA %pM smps %d: %d\n",
|
||||
sta->addr, smps, err);
|
||||
@ -6434,7 +6521,7 @@ static int ath10k_sta_set_txpwr(struct ieee80211_hw *hw,
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_USE_FIXED_PWR, txpwr);
|
||||
ar->wmi.peer_param->use_fixed_power, txpwr);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set tx power for station ret: %d\n",
|
||||
ret);
|
||||
@ -6549,8 +6636,12 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
if (!sta->tdls)
|
||||
if (!sta->tdls) {
|
||||
ath10k_peer_delete(ar, arvif->vdev_id, sta->addr);
|
||||
ath10k_mac_dec_num_stations(arvif, sta);
|
||||
kfree(arsta->tx_stats);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = ath10k_wmi_update_fw_tdls_state(ar, arvif->vdev_id,
|
||||
WMI_TDLS_ENABLE_ACTIVE);
|
||||
@ -7419,7 +7510,7 @@ static bool ath10k_mac_set_vht_bitrate_mask_fixup(struct ath10k *ar,
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_PARAM_FIXED_RATE, rate);
|
||||
if (err)
|
||||
ath10k_warn(ar, "failed to eanble STA %pM peer fixed rate: %d\n",
|
||||
ath10k_warn(ar, "failed to enable STA %pM peer fixed rate: %d\n",
|
||||
sta->addr, err);
|
||||
|
||||
return true;
|
||||
|
@ -72,6 +72,7 @@ struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar,
|
||||
u8 tid);
|
||||
int ath10k_mac_ext_resource_config(struct ath10k *ar, u32 val);
|
||||
void ath10k_mac_wait_tx_complete(struct ath10k *ar);
|
||||
int ath10k_mac_rfkill_enable_radio(struct ath10k *ar, bool enable);
|
||||
|
||||
static inline void ath10k_tx_h_seq_no(struct ieee80211_vif *vif,
|
||||
struct sk_buff *skb)
|
||||
|
@ -2567,35 +2567,31 @@ static void ath10k_pci_warm_reset_cpu(struct ath10k *ar)
|
||||
|
||||
ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, 0);
|
||||
|
||||
val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
|
||||
SOC_RESET_CONTROL_ADDRESS);
|
||||
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
|
||||
val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
|
||||
val = ath10k_pci_soc_read32(ar, SOC_RESET_CONTROL_ADDRESS);
|
||||
ath10k_pci_soc_write32(ar, SOC_RESET_CONTROL_ADDRESS,
|
||||
val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
|
||||
}
|
||||
|
||||
static void ath10k_pci_warm_reset_ce(struct ath10k *ar)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
|
||||
SOC_RESET_CONTROL_ADDRESS);
|
||||
val = ath10k_pci_soc_read32(ar, SOC_RESET_CONTROL_ADDRESS);
|
||||
|
||||
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
|
||||
val | SOC_RESET_CONTROL_CE_RST_MASK);
|
||||
ath10k_pci_soc_write32(ar, SOC_RESET_CONTROL_ADDRESS,
|
||||
val | SOC_RESET_CONTROL_CE_RST_MASK);
|
||||
msleep(10);
|
||||
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
|
||||
val & ~SOC_RESET_CONTROL_CE_RST_MASK);
|
||||
ath10k_pci_soc_write32(ar, SOC_RESET_CONTROL_ADDRESS,
|
||||
val & ~SOC_RESET_CONTROL_CE_RST_MASK);
|
||||
}
|
||||
|
||||
static void ath10k_pci_warm_reset_clear_lf(struct ath10k *ar)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
|
||||
SOC_LF_TIMER_CONTROL0_ADDRESS);
|
||||
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS +
|
||||
SOC_LF_TIMER_CONTROL0_ADDRESS,
|
||||
val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK);
|
||||
val = ath10k_pci_soc_read32(ar, SOC_LF_TIMER_CONTROL0_ADDRESS);
|
||||
ath10k_pci_soc_write32(ar, SOC_LF_TIMER_CONTROL0_ADDRESS,
|
||||
val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK);
|
||||
}
|
||||
|
||||
static int ath10k_pci_warm_reset(struct ath10k *ar)
|
||||
@ -3490,7 +3486,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
struct ath10k_pci *ar_pci;
|
||||
enum ath10k_hw_rev hw_rev;
|
||||
struct ath10k_bus_params bus_params = {};
|
||||
bool pci_ps;
|
||||
bool pci_ps, is_qca988x = false;
|
||||
int (*pci_soft_reset)(struct ath10k *ar);
|
||||
int (*pci_hard_reset)(struct ath10k *ar);
|
||||
u32 (*targ_cpu_to_ce_addr)(struct ath10k *ar, u32 addr);
|
||||
@ -3500,6 +3496,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
case QCA988X_2_0_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA988X;
|
||||
pci_ps = false;
|
||||
is_qca988x = true;
|
||||
pci_soft_reset = ath10k_pci_warm_reset;
|
||||
pci_hard_reset = ath10k_pci_qca988x_chip_reset;
|
||||
targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr;
|
||||
@ -3619,25 +3616,34 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
goto err_deinit_irq;
|
||||
}
|
||||
|
||||
bus_params.dev_type = ATH10K_DEV_TYPE_LL;
|
||||
bus_params.link_can_suspend = true;
|
||||
/* Read CHIP_ID before reset to catch QCA9880-AR1A v1 devices that
|
||||
* fall off the bus during chip_reset. These chips have the same pci
|
||||
* device id as the QCA9880 BR4A or 2R4E. So that's why the check.
|
||||
*/
|
||||
if (is_qca988x) {
|
||||
bus_params.chip_id =
|
||||
ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
|
||||
if (bus_params.chip_id != 0xffffffff) {
|
||||
if (!ath10k_pci_chip_is_supported(pdev->device,
|
||||
bus_params.chip_id))
|
||||
goto err_unsupported;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ath10k_pci_chip_reset(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to reset chip: %d\n", ret);
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
bus_params.dev_type = ATH10K_DEV_TYPE_LL;
|
||||
bus_params.link_can_suspend = true;
|
||||
bus_params.chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
|
||||
if (bus_params.chip_id == 0xffffffff) {
|
||||
ath10k_err(ar, "failed to get chip id\n");
|
||||
goto err_free_irq;
|
||||
}
|
||||
if (bus_params.chip_id == 0xffffffff)
|
||||
goto err_unsupported;
|
||||
|
||||
if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id)) {
|
||||
ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n",
|
||||
pdev->device, bus_params.chip_id);
|
||||
if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id))
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
ret = ath10k_core_register(ar, &bus_params);
|
||||
if (ret) {
|
||||
@ -3647,6 +3653,10 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
return 0;
|
||||
|
||||
err_unsupported:
|
||||
ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n",
|
||||
pdev->device, bus_params.chip_id);
|
||||
|
||||
err_free_irq:
|
||||
ath10k_pci_free_irq(ar);
|
||||
ath10k_pci_rx_retry_sync(ar);
|
||||
|
@ -111,6 +111,7 @@ static int ath10k_qmi_msa_mem_info_send_sync_msg(struct ath10k_qmi *qmi)
|
||||
struct wlfw_msa_info_resp_msg_v01 resp = {};
|
||||
struct wlfw_msa_info_req_msg_v01 req = {};
|
||||
struct ath10k *ar = qmi->ar;
|
||||
phys_addr_t max_mapped_addr;
|
||||
struct qmi_txn txn;
|
||||
int ret;
|
||||
int i;
|
||||
@ -150,8 +151,20 @@ static int ath10k_qmi_msa_mem_info_send_sync_msg(struct ath10k_qmi *qmi)
|
||||
goto out;
|
||||
}
|
||||
|
||||
max_mapped_addr = qmi->msa_pa + qmi->msa_mem_size;
|
||||
qmi->nr_mem_region = resp.mem_region_info_len;
|
||||
for (i = 0; i < resp.mem_region_info_len; i++) {
|
||||
if (resp.mem_region_info[i].size > qmi->msa_mem_size ||
|
||||
resp.mem_region_info[i].region_addr > max_mapped_addr ||
|
||||
resp.mem_region_info[i].region_addr < qmi->msa_pa ||
|
||||
resp.mem_region_info[i].size +
|
||||
resp.mem_region_info[i].region_addr > max_mapped_addr) {
|
||||
ath10k_err(ar, "received out of range memory region address 0x%llx with size 0x%x, aborting\n",
|
||||
resp.mem_region_info[i].region_addr,
|
||||
resp.mem_region_info[i].size);
|
||||
ret = -EINVAL;
|
||||
goto fail_unwind;
|
||||
}
|
||||
qmi->mem_region[i].addr = resp.mem_region_info[i].region_addr;
|
||||
qmi->mem_region[i].size = resp.mem_region_info[i].size;
|
||||
qmi->mem_region[i].secure = resp.mem_region_info[i].secure_flag;
|
||||
@ -165,6 +178,8 @@ static int ath10k_qmi_msa_mem_info_send_sync_msg(struct ath10k_qmi *qmi)
|
||||
ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi msa mem info request completed\n");
|
||||
return 0;
|
||||
|
||||
fail_unwind:
|
||||
memset(&qmi->mem_region[0], 0, sizeof(qmi->mem_region[0]) * i);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@ -291,10 +306,16 @@ static int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi)
|
||||
struct wlfw_cal_report_resp_msg_v01 resp = {};
|
||||
struct wlfw_cal_report_req_msg_v01 req = {};
|
||||
struct ath10k *ar = qmi->ar;
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct qmi_txn txn;
|
||||
int i, j = 0;
|
||||
int ret;
|
||||
|
||||
if (ar_snoc->xo_cal_supported) {
|
||||
req.xo_cal_data_valid = 1;
|
||||
req.xo_cal_data = ar_snoc->xo_cal_data;
|
||||
}
|
||||
|
||||
ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_cal_report_resp_msg_v01_ei,
|
||||
&resp);
|
||||
if (ret < 0)
|
||||
@ -581,22 +602,29 @@ static int ath10k_qmi_host_cap_send_sync(struct ath10k_qmi *qmi)
|
||||
{
|
||||
struct wlfw_host_cap_resp_msg_v01 resp = {};
|
||||
struct wlfw_host_cap_req_msg_v01 req = {};
|
||||
struct qmi_elem_info *req_ei;
|
||||
struct ath10k *ar = qmi->ar;
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct qmi_txn txn;
|
||||
int ret;
|
||||
|
||||
req.daemon_support_valid = 1;
|
||||
req.daemon_support = 0;
|
||||
|
||||
ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
|
||||
wlfw_host_cap_resp_msg_v01_ei, &resp);
|
||||
ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_host_cap_resp_msg_v01_ei,
|
||||
&resp);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (test_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags))
|
||||
req_ei = wlfw_host_cap_8bit_req_msg_v01_ei;
|
||||
else
|
||||
req_ei = wlfw_host_cap_req_msg_v01_ei;
|
||||
|
||||
ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
|
||||
QMI_WLFW_HOST_CAP_REQ_V01,
|
||||
WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN,
|
||||
wlfw_host_cap_req_msg_v01_ei, &req);
|
||||
req_ei, &req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath10k_err(ar, "failed to send host capability request: %d\n", ret);
|
||||
@ -643,7 +671,7 @@ int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode)
|
||||
wlfw_ini_req_msg_v01_ei, &req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath10k_err(ar, "fail to send fw log reqest: %d\n", ret);
|
||||
ath10k_err(ar, "failed to send fw log request: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -652,7 +680,7 @@ int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode)
|
||||
goto out;
|
||||
|
||||
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
||||
ath10k_err(ar, "fw log request rejectedr: %d\n",
|
||||
ath10k_err(ar, "fw log request rejected: %d\n",
|
||||
resp.resp.error);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
@ -671,6 +699,7 @@ ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
|
||||
struct wlfw_ind_register_resp_msg_v01 resp = {};
|
||||
struct wlfw_ind_register_req_msg_v01 req = {};
|
||||
struct ath10k *ar = qmi->ar;
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct qmi_txn txn;
|
||||
int ret;
|
||||
|
||||
@ -681,6 +710,11 @@ ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
|
||||
req.msa_ready_enable_valid = 1;
|
||||
req.msa_ready_enable = 1;
|
||||
|
||||
if (ar_snoc->xo_cal_supported) {
|
||||
req.xo_cal_enable_valid = 1;
|
||||
req.xo_cal_enable = 1;
|
||||
}
|
||||
|
||||
ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
|
||||
wlfw_ind_register_resp_msg_v01_ei, &resp);
|
||||
if (ret < 0)
|
||||
@ -795,9 +829,13 @@ ath10k_qmi_driver_event_post(struct ath10k_qmi *qmi,
|
||||
static void ath10k_qmi_event_server_exit(struct ath10k_qmi *qmi)
|
||||
{
|
||||
struct ath10k *ar = qmi->ar;
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
|
||||
ath10k_qmi_remove_msa_permission(qmi);
|
||||
ath10k_core_free_board_files(ar);
|
||||
if (!test_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags))
|
||||
ath10k_snoc_fw_crashed_dump(ar);
|
||||
|
||||
ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_DOWN_IND);
|
||||
ath10k_dbg(ar, ATH10K_DBG_QMI, "wifi fw qmi service disconnected\n");
|
||||
}
|
||||
|
@ -1988,6 +1988,28 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
struct qmi_elem_info wlfw_host_cap_8bit_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct wlfw_host_cap_req_msg_v01,
|
||||
daemon_support_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct wlfw_host_cap_req_msg_v01,
|
||||
daemon_support),
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
|
@ -575,6 +575,7 @@ struct wlfw_host_cap_req_msg_v01 {
|
||||
|
||||
#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 189
|
||||
extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[];
|
||||
extern struct qmi_elem_info wlfw_host_cap_8bit_req_msg_v01_ei[];
|
||||
|
||||
struct wlfw_host_cap_resp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
|
@ -2086,9 +2086,6 @@ static int ath10k_sdio_probe(struct sdio_func *func,
|
||||
goto err_free_wq;
|
||||
}
|
||||
|
||||
/* TODO: remove this once SDIO support is fully implemented */
|
||||
ath10k_warn(ar, "WARNING: ath10k SDIO support is work-in-progress, problems may arise!\n");
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_wq:
|
||||
|
@ -9,9 +9,11 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include "ce.h"
|
||||
#include "coredump.h"
|
||||
#include "debug.h"
|
||||
#include "hif.h"
|
||||
#include "htc.h"
|
||||
@ -36,15 +38,15 @@ static char *const ce_name[] = {
|
||||
"WLAN_CE_11",
|
||||
};
|
||||
|
||||
static struct ath10k_vreg_info vreg_cfg[] = {
|
||||
{NULL, "vdd-0.8-cx-mx", 800000, 850000, 0, 0, false},
|
||||
{NULL, "vdd-1.8-xo", 1800000, 1850000, 0, 0, false},
|
||||
{NULL, "vdd-1.3-rfa", 1300000, 1350000, 0, 0, false},
|
||||
{NULL, "vdd-3.3-ch0", 3300000, 3350000, 0, 0, false},
|
||||
static const char * const ath10k_regulators[] = {
|
||||
"vdd-0.8-cx-mx",
|
||||
"vdd-1.8-xo",
|
||||
"vdd-1.3-rfa",
|
||||
"vdd-3.3-ch0",
|
||||
};
|
||||
|
||||
static struct ath10k_clk_info clk_cfg[] = {
|
||||
{NULL, "cxo_ref_clk_pin", 0, false},
|
||||
static const char * const ath10k_clocks[] = {
|
||||
"cxo_ref_clk_pin",
|
||||
};
|
||||
|
||||
static void ath10k_snoc_htc_tx_cb(struct ath10k_ce_pipe *ce_state);
|
||||
@ -976,8 +978,7 @@ static int ath10k_snoc_wlan_enable(struct ath10k *ar,
|
||||
sizeof(struct ath10k_svc_pipe_cfg);
|
||||
cfg.ce_svc_cfg = (struct ath10k_svc_pipe_cfg *)
|
||||
&target_service_to_ce_map_wlan;
|
||||
cfg.num_shadow_reg_cfg = sizeof(target_shadow_reg_cfg_map) /
|
||||
sizeof(struct ath10k_shadow_reg_cfg);
|
||||
cfg.num_shadow_reg_cfg = ARRAY_SIZE(target_shadow_reg_cfg_map);
|
||||
cfg.shadow_reg_cfg = (struct ath10k_shadow_reg_cfg *)
|
||||
&target_shadow_reg_cfg_map;
|
||||
|
||||
@ -1257,10 +1258,29 @@ static int ath10k_snoc_resource_init(struct ath10k *ar)
|
||||
ar_snoc->ce_irqs[i].irq_line = res->start;
|
||||
}
|
||||
|
||||
ret = device_property_read_u32(&pdev->dev, "qcom,xo-cal-data",
|
||||
&ar_snoc->xo_cal_data);
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc xo-cal-data return %d\n", ret);
|
||||
if (ret == 0) {
|
||||
ar_snoc->xo_cal_supported = true;
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "xo cal data %x\n",
|
||||
ar_snoc->xo_cal_data);
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath10k_snoc_quirks_init(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct device *dev = &ar_snoc->dev->dev;
|
||||
|
||||
if (of_property_read_bool(dev->of_node, "qcom,snoc-host-cap-8bit-quirk"))
|
||||
set_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags);
|
||||
}
|
||||
|
||||
int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
@ -1337,296 +1357,102 @@ static void ath10k_snoc_release_resource(struct ath10k *ar)
|
||||
ath10k_ce_free_pipe(ar, i);
|
||||
}
|
||||
|
||||
static int ath10k_get_vreg_info(struct ath10k *ar, struct device *dev,
|
||||
struct ath10k_vreg_info *vreg_info)
|
||||
{
|
||||
struct regulator *reg;
|
||||
int ret = 0;
|
||||
|
||||
reg = devm_regulator_get_optional(dev, vreg_info->name);
|
||||
|
||||
if (IS_ERR(reg)) {
|
||||
ret = PTR_ERR(reg);
|
||||
|
||||
if (ret == -EPROBE_DEFER) {
|
||||
ath10k_err(ar, "EPROBE_DEFER for regulator: %s\n",
|
||||
vreg_info->name);
|
||||
return ret;
|
||||
}
|
||||
if (vreg_info->required) {
|
||||
ath10k_err(ar, "Regulator %s doesn't exist: %d\n",
|
||||
vreg_info->name, ret);
|
||||
return ret;
|
||||
}
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC,
|
||||
"Optional regulator %s doesn't exist: %d\n",
|
||||
vreg_info->name, ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
vreg_info->reg = reg;
|
||||
|
||||
done:
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC,
|
||||
"snog vreg %s min_v %u max_v %u load_ua %u settle_delay %lu\n",
|
||||
vreg_info->name, vreg_info->min_v, vreg_info->max_v,
|
||||
vreg_info->load_ua, vreg_info->settle_delay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_get_clk_info(struct ath10k *ar, struct device *dev,
|
||||
struct ath10k_clk_info *clk_info)
|
||||
{
|
||||
struct clk *handle;
|
||||
int ret = 0;
|
||||
|
||||
handle = devm_clk_get(dev, clk_info->name);
|
||||
if (IS_ERR(handle)) {
|
||||
ret = PTR_ERR(handle);
|
||||
if (clk_info->required) {
|
||||
ath10k_err(ar, "snoc clock %s isn't available: %d\n",
|
||||
clk_info->name, ret);
|
||||
return ret;
|
||||
}
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc ignoring clock %s: %d\n",
|
||||
clk_info->name,
|
||||
ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc clock %s freq %u\n",
|
||||
clk_info->name, clk_info->freq);
|
||||
|
||||
clk_info->handle = handle;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __ath10k_snoc_vreg_on(struct ath10k *ar,
|
||||
struct ath10k_vreg_info *vreg_info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc regulator %s being enabled\n",
|
||||
vreg_info->name);
|
||||
|
||||
ret = regulator_set_voltage(vreg_info->reg, vreg_info->min_v,
|
||||
vreg_info->max_v);
|
||||
if (ret) {
|
||||
ath10k_err(ar,
|
||||
"failed to set regulator %s voltage-min: %d voltage-max: %d\n",
|
||||
vreg_info->name, vreg_info->min_v, vreg_info->max_v);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (vreg_info->load_ua) {
|
||||
ret = regulator_set_load(vreg_info->reg, vreg_info->load_ua);
|
||||
if (ret < 0) {
|
||||
ath10k_err(ar, "failed to set regulator %s load: %d\n",
|
||||
vreg_info->name, vreg_info->load_ua);
|
||||
goto err_set_load;
|
||||
}
|
||||
}
|
||||
|
||||
ret = regulator_enable(vreg_info->reg);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to enable regulator %s\n",
|
||||
vreg_info->name);
|
||||
goto err_enable;
|
||||
}
|
||||
|
||||
if (vreg_info->settle_delay)
|
||||
udelay(vreg_info->settle_delay);
|
||||
|
||||
return 0;
|
||||
|
||||
err_enable:
|
||||
regulator_set_load(vreg_info->reg, 0);
|
||||
err_set_load:
|
||||
regulator_set_voltage(vreg_info->reg, 0, vreg_info->max_v);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __ath10k_snoc_vreg_off(struct ath10k *ar,
|
||||
struct ath10k_vreg_info *vreg_info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc regulator %s being disabled\n",
|
||||
vreg_info->name);
|
||||
|
||||
ret = regulator_disable(vreg_info->reg);
|
||||
if (ret)
|
||||
ath10k_err(ar, "failed to disable regulator %s\n",
|
||||
vreg_info->name);
|
||||
|
||||
ret = regulator_set_load(vreg_info->reg, 0);
|
||||
if (ret < 0)
|
||||
ath10k_err(ar, "failed to set load %s\n", vreg_info->name);
|
||||
|
||||
ret = regulator_set_voltage(vreg_info->reg, 0, vreg_info->max_v);
|
||||
if (ret)
|
||||
ath10k_err(ar, "failed to set voltage %s\n", vreg_info->name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_snoc_vreg_on(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct ath10k_vreg_info *vreg_info;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vreg_cfg); i++) {
|
||||
vreg_info = &ar_snoc->vreg[i];
|
||||
|
||||
if (!vreg_info->reg)
|
||||
continue;
|
||||
|
||||
ret = __ath10k_snoc_vreg_on(ar, vreg_info);
|
||||
if (ret)
|
||||
goto err_reg_config;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_reg_config:
|
||||
for (i = i - 1; i >= 0; i--) {
|
||||
vreg_info = &ar_snoc->vreg[i];
|
||||
|
||||
if (!vreg_info->reg)
|
||||
continue;
|
||||
|
||||
__ath10k_snoc_vreg_off(ar, vreg_info);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_snoc_vreg_off(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct ath10k_vreg_info *vreg_info;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = ARRAY_SIZE(vreg_cfg) - 1; i >= 0; i--) {
|
||||
vreg_info = &ar_snoc->vreg[i];
|
||||
|
||||
if (!vreg_info->reg)
|
||||
continue;
|
||||
|
||||
ret = __ath10k_snoc_vreg_off(ar, vreg_info);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_snoc_clk_init(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct ath10k_clk_info *clk_info;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clk_cfg); i++) {
|
||||
clk_info = &ar_snoc->clk[i];
|
||||
|
||||
if (!clk_info->handle)
|
||||
continue;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc clock %s being enabled\n",
|
||||
clk_info->name);
|
||||
|
||||
if (clk_info->freq) {
|
||||
ret = clk_set_rate(clk_info->handle, clk_info->freq);
|
||||
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to set clock %s freq %u\n",
|
||||
clk_info->name, clk_info->freq);
|
||||
goto err_clock_config;
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(clk_info->handle);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to enable clock %s\n",
|
||||
clk_info->name);
|
||||
goto err_clock_config;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_clock_config:
|
||||
for (i = i - 1; i >= 0; i--) {
|
||||
clk_info = &ar_snoc->clk[i];
|
||||
|
||||
if (!clk_info->handle)
|
||||
continue;
|
||||
|
||||
clk_disable_unprepare(clk_info->handle);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_snoc_clk_deinit(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct ath10k_clk_info *clk_info;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clk_cfg); i++) {
|
||||
clk_info = &ar_snoc->clk[i];
|
||||
|
||||
if (!clk_info->handle)
|
||||
continue;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc clock %s being disabled\n",
|
||||
clk_info->name);
|
||||
|
||||
clk_disable_unprepare(clk_info->handle);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_hw_power_on(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power on\n");
|
||||
|
||||
ret = ath10k_snoc_vreg_on(ar);
|
||||
ret = regulator_bulk_enable(ar_snoc->num_vregs, ar_snoc->vregs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ath10k_snoc_clk_init(ar);
|
||||
ret = clk_bulk_prepare_enable(ar_snoc->num_clks, ar_snoc->clks);
|
||||
if (ret)
|
||||
goto vreg_off;
|
||||
|
||||
return ret;
|
||||
|
||||
vreg_off:
|
||||
ath10k_snoc_vreg_off(ar);
|
||||
regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_hw_power_off(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power off\n");
|
||||
|
||||
ath10k_snoc_clk_deinit(ar);
|
||||
clk_bulk_disable_unprepare(ar_snoc->num_clks, ar_snoc->clks);
|
||||
|
||||
ret = ath10k_snoc_vreg_off(ar);
|
||||
return regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
|
||||
}
|
||||
|
||||
return ret;
|
||||
static void ath10k_msa_dump_memory(struct ath10k *ar,
|
||||
struct ath10k_fw_crash_data *crash_data)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
const struct ath10k_hw_mem_layout *mem_layout;
|
||||
const struct ath10k_mem_region *current_region;
|
||||
struct ath10k_dump_ram_data_hdr *hdr;
|
||||
size_t buf_len;
|
||||
u8 *buf;
|
||||
|
||||
if (!crash_data && !crash_data->ramdump_buf)
|
||||
return;
|
||||
|
||||
mem_layout = ath10k_coredump_get_mem_layout(ar);
|
||||
if (!mem_layout)
|
||||
return;
|
||||
|
||||
current_region = &mem_layout->region_table.regions[0];
|
||||
|
||||
buf = crash_data->ramdump_buf;
|
||||
buf_len = crash_data->ramdump_buf_len;
|
||||
memset(buf, 0, buf_len);
|
||||
|
||||
/* Reserve space for the header. */
|
||||
hdr = (void *)buf;
|
||||
buf += sizeof(*hdr);
|
||||
buf_len -= sizeof(*hdr);
|
||||
|
||||
hdr->region_type = cpu_to_le32(current_region->type);
|
||||
hdr->start = cpu_to_le32((unsigned long)ar_snoc->qmi->msa_va);
|
||||
hdr->length = cpu_to_le32(ar_snoc->qmi->msa_mem_size);
|
||||
|
||||
if (current_region->len < ar_snoc->qmi->msa_mem_size) {
|
||||
memcpy(buf, ar_snoc->qmi->msa_va, current_region->len);
|
||||
ath10k_warn(ar, "msa dump length is less than msa size %x, %x\n",
|
||||
current_region->len, ar_snoc->qmi->msa_mem_size);
|
||||
} else {
|
||||
memcpy(buf, ar_snoc->qmi->msa_va, ar_snoc->qmi->msa_mem_size);
|
||||
}
|
||||
}
|
||||
|
||||
void ath10k_snoc_fw_crashed_dump(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_fw_crash_data *crash_data;
|
||||
char guid[UUID_STRING_LEN + 1];
|
||||
|
||||
mutex_lock(&ar->dump_mutex);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->stats.fw_crash_counter++;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
crash_data = ath10k_coredump_new(ar);
|
||||
|
||||
if (crash_data)
|
||||
scnprintf(guid, sizeof(guid), "%pUl", &crash_data->guid);
|
||||
else
|
||||
scnprintf(guid, sizeof(guid), "n/a");
|
||||
|
||||
ath10k_err(ar, "firmware crashed! (guid %s)\n", guid);
|
||||
ath10k_print_driver_info(ar);
|
||||
ath10k_msa_dump_memory(ar, crash_data);
|
||||
mutex_unlock(&ar->dump_mutex);
|
||||
}
|
||||
|
||||
static const struct of_device_id ath10k_snoc_dt_match[] = {
|
||||
@ -1678,6 +1504,8 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
|
||||
ar->ce_priv = &ar_snoc->ce;
|
||||
msa_size = drv_data->msa_size;
|
||||
|
||||
ath10k_snoc_quirks_init(ar);
|
||||
|
||||
ret = ath10k_snoc_resource_init(ar);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to initialize resource: %d\n", ret);
|
||||
@ -1695,19 +1523,36 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
|
||||
goto err_release_resource;
|
||||
}
|
||||
|
||||
ar_snoc->vreg = vreg_cfg;
|
||||
for (i = 0; i < ARRAY_SIZE(vreg_cfg); i++) {
|
||||
ret = ath10k_get_vreg_info(ar, dev, &ar_snoc->vreg[i]);
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
ar_snoc->num_vregs = ARRAY_SIZE(ath10k_regulators);
|
||||
ar_snoc->vregs = devm_kcalloc(&pdev->dev, ar_snoc->num_vregs,
|
||||
sizeof(*ar_snoc->vregs), GFP_KERNEL);
|
||||
if (!ar_snoc->vregs) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_irq;
|
||||
}
|
||||
for (i = 0; i < ar_snoc->num_vregs; i++)
|
||||
ar_snoc->vregs[i].supply = ath10k_regulators[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(&pdev->dev, ar_snoc->num_vregs,
|
||||
ar_snoc->vregs);
|
||||
if (ret < 0)
|
||||
goto err_free_irq;
|
||||
|
||||
ar_snoc->num_clks = ARRAY_SIZE(ath10k_clocks);
|
||||
ar_snoc->clks = devm_kcalloc(&pdev->dev, ar_snoc->num_clks,
|
||||
sizeof(*ar_snoc->clks), GFP_KERNEL);
|
||||
if (!ar_snoc->clks) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
ar_snoc->clk = clk_cfg;
|
||||
for (i = 0; i < ARRAY_SIZE(clk_cfg); i++) {
|
||||
ret = ath10k_get_clk_info(ar, dev, &ar_snoc->clk[i]);
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
}
|
||||
for (i = 0; i < ar_snoc->num_clks; i++)
|
||||
ar_snoc->clks[i].id = ath10k_clocks[i];
|
||||
|
||||
ret = devm_clk_bulk_get_optional(&pdev->dev, ar_snoc->num_clks,
|
||||
ar_snoc->clks);
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
|
||||
ret = ath10k_hw_power_on(ar);
|
||||
if (ret) {
|
||||
|
@ -42,29 +42,16 @@ struct ath10k_snoc_ce_irq {
|
||||
u32 irq_line;
|
||||
};
|
||||
|
||||
struct ath10k_vreg_info {
|
||||
struct regulator *reg;
|
||||
const char *name;
|
||||
u32 min_v;
|
||||
u32 max_v;
|
||||
u32 load_ua;
|
||||
unsigned long settle_delay;
|
||||
bool required;
|
||||
};
|
||||
|
||||
struct ath10k_clk_info {
|
||||
struct clk *handle;
|
||||
const char *name;
|
||||
u32 freq;
|
||||
bool required;
|
||||
};
|
||||
|
||||
enum ath10k_snoc_flags {
|
||||
ATH10K_SNOC_FLAG_REGISTERED,
|
||||
ATH10K_SNOC_FLAG_UNREGISTERING,
|
||||
ATH10K_SNOC_FLAG_RECOVERY,
|
||||
ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK,
|
||||
};
|
||||
|
||||
struct clk_bulk_data;
|
||||
struct regulator_bulk_data;
|
||||
|
||||
struct ath10k_snoc {
|
||||
struct platform_device *dev;
|
||||
struct ath10k *ar;
|
||||
@ -76,10 +63,14 @@ struct ath10k_snoc {
|
||||
struct ath10k_snoc_ce_irq ce_irqs[CE_COUNT_MAX];
|
||||
struct ath10k_ce ce;
|
||||
struct timer_list rx_post_retry;
|
||||
struct ath10k_vreg_info *vreg;
|
||||
struct ath10k_clk_info *clk;
|
||||
struct regulator_bulk_data *vregs;
|
||||
size_t num_vregs;
|
||||
struct clk_bulk_data *clks;
|
||||
size_t num_clks;
|
||||
struct ath10k_qmi *qmi;
|
||||
unsigned long flags;
|
||||
bool xo_cal_supported;
|
||||
u32 xo_cal_data;
|
||||
};
|
||||
|
||||
static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
|
||||
@ -88,5 +79,6 @@ static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
|
||||
}
|
||||
|
||||
int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type);
|
||||
void ath10k_snoc_fw_crashed_dump(struct ath10k *ar);
|
||||
|
||||
#endif /* _SNOC_H_ */
|
||||
|
@ -435,6 +435,7 @@ static int ath10k_usb_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
|
||||
ath10k_dbg(ar, ATH10K_DBG_USB_BULK,
|
||||
"usb bulk transmit failed: %d\n", ret);
|
||||
usb_unanchor_urb(urb);
|
||||
usb_free_urb(urb);
|
||||
ret = -EINVAL;
|
||||
goto err_free_urb_to_pipe;
|
||||
}
|
||||
|
@ -409,6 +409,49 @@ static int ath10k_wmi_tlv_event_tx_pause(struct ath10k *ar,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_wmi_tlv_event_rfkill_state_change(struct ath10k *ar,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const struct wmi_tlv_rfkill_state_change_ev *ev;
|
||||
const void **tb;
|
||||
bool radio;
|
||||
int ret;
|
||||
|
||||
tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath10k_warn(ar,
|
||||
"failed to parse rfkill state change event: %d\n",
|
||||
ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TLV_TAG_STRUCT_RFKILL_EVENT];
|
||||
if (!ev) {
|
||||
kfree(tb);
|
||||
return;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"wmi tlv rfkill state change gpio %d type %d radio_state %d\n",
|
||||
__le32_to_cpu(ev->gpio_pin_num),
|
||||
__le32_to_cpu(ev->int_type),
|
||||
__le32_to_cpu(ev->radio_state));
|
||||
|
||||
radio = (__le32_to_cpu(ev->radio_state) == WMI_TLV_RFKILL_RADIO_STATE_ON);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
if (!radio)
|
||||
ar->hw_rfkill_on = true;
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
/* notify cfg80211 radio state change */
|
||||
ath10k_mac_rfkill_enable_radio(ar, radio);
|
||||
wiphy_rfkill_set_hw_state(ar->hw->wiphy, !radio);
|
||||
}
|
||||
|
||||
static int ath10k_wmi_tlv_event_temperature(struct ath10k *ar,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@ -629,6 +672,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
case WMI_TLV_TX_PAUSE_EVENTID:
|
||||
ath10k_wmi_tlv_event_tx_pause(ar, skb);
|
||||
break;
|
||||
case WMI_TLV_RFKILL_STATE_CHANGE_EVENTID:
|
||||
ath10k_wmi_tlv_event_rfkill_state_change(ar, skb);
|
||||
break;
|
||||
case WMI_TLV_PDEV_TEMPERATURE_EVENTID:
|
||||
ath10k_wmi_tlv_event_temperature(ar, skb);
|
||||
break;
|
||||
@ -1201,17 +1247,21 @@ static int ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k *ar,
|
||||
arg->max_tx_power = ev->hw_max_tx_power;
|
||||
arg->ht_cap = ev->ht_cap_info;
|
||||
arg->vht_cap = ev->vht_cap_info;
|
||||
arg->vht_supp_mcs = ev->vht_supp_mcs;
|
||||
arg->sw_ver0 = ev->abi.abi_ver0;
|
||||
arg->sw_ver1 = ev->abi.abi_ver1;
|
||||
arg->fw_build = ev->fw_build_vers;
|
||||
arg->phy_capab = ev->phy_capability;
|
||||
arg->num_rf_chains = ev->num_rf_chains;
|
||||
arg->eeprom_rd = reg->eeprom_rd;
|
||||
arg->low_2ghz_chan = reg->low_2ghz_chan;
|
||||
arg->high_2ghz_chan = reg->high_2ghz_chan;
|
||||
arg->low_5ghz_chan = reg->low_5ghz_chan;
|
||||
arg->high_5ghz_chan = reg->high_5ghz_chan;
|
||||
arg->num_mem_reqs = ev->num_mem_reqs;
|
||||
arg->service_map = svc_bmap;
|
||||
arg->service_map_len = ath10k_wmi_tlv_len(svc_bmap);
|
||||
arg->sys_cap_info = ev->sys_cap_info;
|
||||
|
||||
ret = ath10k_wmi_tlv_iter(ar, mem_reqs, ath10k_wmi_tlv_len(mem_reqs),
|
||||
ath10k_wmi_tlv_parse_mem_reqs, arg);
|
||||
@ -1649,8 +1699,9 @@ ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id,
|
||||
static void
|
||||
ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks)
|
||||
{
|
||||
struct host_memory_chunk *chunk;
|
||||
struct host_memory_chunk_tlv *chunk;
|
||||
struct wmi_tlv *tlv;
|
||||
dma_addr_t paddr;
|
||||
int i;
|
||||
__le16 tlv_len, tlv_tag;
|
||||
|
||||
@ -1666,6 +1717,12 @@ ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks)
|
||||
chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len);
|
||||
chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
|
||||
|
||||
if (test_bit(WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
|
||||
ar->wmi.svc_map)) {
|
||||
paddr = ar->wmi.mem_chunks[i].paddr;
|
||||
chunk->ptr_high = __cpu_to_le32(upper_32_bits(paddr));
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi-tlv chunk %d len %d, addr 0x%llx, id 0x%x\n",
|
||||
i,
|
||||
@ -1689,7 +1746,7 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
|
||||
void *ptr;
|
||||
|
||||
chunks_len = ar->wmi.num_mem_chunks *
|
||||
(sizeof(struct host_memory_chunk) + sizeof(*tlv));
|
||||
(sizeof(struct host_memory_chunk_tlv) + sizeof(*tlv));
|
||||
len = (sizeof(*tlv) + sizeof(*cmd)) +
|
||||
(sizeof(*tlv) + sizeof(*cfg)) +
|
||||
(sizeof(*tlv) + chunks_len);
|
||||
@ -4204,6 +4261,26 @@ static struct wmi_pdev_param_map wmi_tlv_pdev_param_map = {
|
||||
.wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.rfkill_config = WMI_TLV_PDEV_PARAM_HW_RFKILL_CONFIG,
|
||||
.rfkill_enable = WMI_TLV_PDEV_PARAM_RFKILL_ENABLE,
|
||||
};
|
||||
|
||||
static struct wmi_peer_param_map wmi_tlv_peer_param_map = {
|
||||
.smps_state = WMI_TLV_PEER_SMPS_STATE,
|
||||
.ampdu = WMI_TLV_PEER_AMPDU,
|
||||
.authorize = WMI_TLV_PEER_AUTHORIZE,
|
||||
.chan_width = WMI_TLV_PEER_CHAN_WIDTH,
|
||||
.nss = WMI_TLV_PEER_NSS,
|
||||
.use_4addr = WMI_TLV_PEER_USE_4ADDR,
|
||||
.membership = WMI_TLV_PEER_MEMBERSHIP,
|
||||
.user_pos = WMI_TLV_PEER_USERPOS,
|
||||
.crit_proto_hint_enabled = WMI_TLV_PEER_CRIT_PROTO_HINT_ENABLED,
|
||||
.tx_fail_cnt_thr = WMI_TLV_PEER_TX_FAIL_CNT_THR,
|
||||
.set_hw_retry_cts2s = WMI_TLV_PEER_SET_HW_RETRY_CTS2S,
|
||||
.ibss_atim_win_len = WMI_TLV_PEER_IBSS_ATIM_WINDOW_LENGTH,
|
||||
.phymode = WMI_TLV_PEER_PHYMODE,
|
||||
.use_fixed_power = WMI_TLV_PEER_USE_FIXED_PWR,
|
||||
.dummy_var = WMI_TLV_PEER_DUMMY_VAR,
|
||||
};
|
||||
|
||||
static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
|
||||
@ -4394,6 +4471,7 @@ void ath10k_wmi_tlv_attach(struct ath10k *ar)
|
||||
ar->wmi.cmd = &wmi_tlv_cmd_map;
|
||||
ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
|
||||
ar->wmi.peer_param = &wmi_tlv_peer_param_map;
|
||||
ar->wmi.ops = &wmi_tlv_ops;
|
||||
ar->wmi.peer_flags = &wmi_tlv_peer_flags_map;
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
#ifndef _WMI_TLV_H
|
||||
#define _WMI_TLV_H
|
||||
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#define WMI_TLV_CMD(grp_id) (((grp_id) << 12) | 0x1)
|
||||
#define WMI_TLV_EV(grp_id) (((grp_id) << 12) | 0x1)
|
||||
#define WMI_TLV_CMD_UNSUPPORTED 0
|
||||
@ -528,6 +530,24 @@ enum wmi_tlv_vdev_param {
|
||||
WMI_TLV_VDEV_PARAM_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE,
|
||||
};
|
||||
|
||||
enum wmi_tlv_peer_param {
|
||||
WMI_TLV_PEER_SMPS_STATE = 0x1, /* see %wmi_peer_smps_state */
|
||||
WMI_TLV_PEER_AMPDU = 0x2,
|
||||
WMI_TLV_PEER_AUTHORIZE = 0x3,
|
||||
WMI_TLV_PEER_CHAN_WIDTH = 0x4,
|
||||
WMI_TLV_PEER_NSS = 0x5,
|
||||
WMI_TLV_PEER_USE_4ADDR = 0x6,
|
||||
WMI_TLV_PEER_MEMBERSHIP = 0x7,
|
||||
WMI_TLV_PEER_USERPOS = 0x8,
|
||||
WMI_TLV_PEER_CRIT_PROTO_HINT_ENABLED = 0x9,
|
||||
WMI_TLV_PEER_TX_FAIL_CNT_THR = 0xa,
|
||||
WMI_TLV_PEER_SET_HW_RETRY_CTS2S = 0xb,
|
||||
WMI_TLV_PEER_IBSS_ATIM_WINDOW_LENGTH = 0xc,
|
||||
WMI_TLV_PEER_PHYMODE = 0xd,
|
||||
WMI_TLV_PEER_USE_FIXED_PWR = 0xe,
|
||||
WMI_TLV_PEER_DUMMY_VAR = 0xff,
|
||||
};
|
||||
|
||||
enum wmi_tlv_peer_flags {
|
||||
WMI_TLV_PEER_AUTH = 0x00000001,
|
||||
WMI_TLV_PEER_QOS = 0x00000002,
|
||||
@ -1409,6 +1429,11 @@ enum wmi_tlv_service {
|
||||
WMI_TLV_SERVICE_WLAN_HPCS_PULSE = 172,
|
||||
WMI_TLV_SERVICE_PER_VDEV_CHAINMASK_CONFIG_SUPPORT = 173,
|
||||
WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI = 174,
|
||||
WMI_TLV_SERVICE_NAN_DISABLE_SUPPORT = 175,
|
||||
WMI_TLV_SERVICE_HTT_H2T_NO_HTC_HDR_LEN_IN_MSG_LEN = 176,
|
||||
WMI_TLV_SERVICE_COEX_SUPPORT_UNEQUAL_ISOLATION = 177,
|
||||
WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT = 178,
|
||||
WMI_TLV_SERVICE_SUPPORT_EXTEND_ADDRESS = 179,
|
||||
|
||||
WMI_TLV_MAX_EXT_SERVICE = 256,
|
||||
};
|
||||
@ -1588,6 +1613,9 @@ wmi_tlv_svc_map_ext(const __le32 *in, unsigned long *out, size_t len)
|
||||
WMI_TLV_MAX_SERVICE);
|
||||
SVCMAP(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,
|
||||
WMI_SERVICE_TX_DATA_ACK_RSSI, WMI_TLV_MAX_SERVICE);
|
||||
SVCMAP(WMI_TLV_SERVICE_SUPPORT_EXTEND_ADDRESS,
|
||||
WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
|
||||
WMI_TLV_MAX_SERVICE);
|
||||
}
|
||||
|
||||
#undef SVCMAP
|
||||
@ -1743,6 +1771,21 @@ struct wmi_tlv_resource_config {
|
||||
__le32 host_capab;
|
||||
} __packed;
|
||||
|
||||
/* structure describing host memory chunk. */
|
||||
struct host_memory_chunk_tlv {
|
||||
/* id of the request that is passed up in service ready */
|
||||
__le32 req_id;
|
||||
|
||||
/* the physical address the memory chunk */
|
||||
__le32 ptr;
|
||||
|
||||
/* size of the chunk */
|
||||
__le32 size;
|
||||
|
||||
/* the upper 32 bit address valid only for more than 32 bit target */
|
||||
__le32 ptr_high;
|
||||
} __packed;
|
||||
|
||||
struct wmi_tlv_init_cmd {
|
||||
struct wmi_tlv_abi_version abi;
|
||||
__le32 num_host_mem_chunks;
|
||||
@ -2235,6 +2278,31 @@ struct wmi_tlv_tdls_peer_event {
|
||||
__le32 vdev_id;
|
||||
} __packed;
|
||||
|
||||
enum wmi_tlv_sys_cap_info_flags {
|
||||
WMI_TLV_SYS_CAP_INFO_RXTX_LED = BIT(0),
|
||||
WMI_TLV_SYS_CAP_INFO_RFKILL = BIT(1),
|
||||
};
|
||||
|
||||
#define WMI_TLV_RFKILL_CFG_GPIO_PIN_NUM GENMASK(5, 0)
|
||||
#define WMI_TLV_RFKILL_CFG_RADIO_LEVEL BIT(6)
|
||||
#define WMI_TLV_RFKILL_CFG_PIN_AS_GPIO GENMASK(10, 7)
|
||||
|
||||
enum wmi_tlv_rfkill_enable_radio {
|
||||
WMI_TLV_RFKILL_ENABLE_RADIO_ON = 0,
|
||||
WMI_TLV_RFKILL_ENABLE_RADIO_OFF = 1,
|
||||
};
|
||||
|
||||
enum wmi_tlv_rfkill_radio_state {
|
||||
WMI_TLV_RFKILL_RADIO_STATE_OFF = 1,
|
||||
WMI_TLV_RFKILL_RADIO_STATE_ON = 2,
|
||||
};
|
||||
|
||||
struct wmi_tlv_rfkill_state_change_ev {
|
||||
__le32 gpio_pin_num;
|
||||
__le32 int_type;
|
||||
__le32 radio_state;
|
||||
};
|
||||
|
||||
void ath10k_wmi_tlv_attach(struct ath10k *ar);
|
||||
|
||||
enum wmi_nlo_auth_algorithm {
|
||||
|
@ -742,6 +742,19 @@ static struct wmi_cmd_map wmi_10_4_cmd_map = {
|
||||
.radar_found_cmdid = WMI_10_4_RADAR_FOUND_CMDID,
|
||||
};
|
||||
|
||||
static struct wmi_peer_param_map wmi_peer_param_map = {
|
||||
.smps_state = WMI_PEER_SMPS_STATE,
|
||||
.ampdu = WMI_PEER_AMPDU,
|
||||
.authorize = WMI_PEER_AUTHORIZE,
|
||||
.chan_width = WMI_PEER_CHAN_WIDTH,
|
||||
.nss = WMI_PEER_NSS,
|
||||
.use_4addr = WMI_PEER_USE_4ADDR,
|
||||
.use_fixed_power = WMI_PEER_USE_FIXED_PWR,
|
||||
.debug = WMI_PEER_DEBUG,
|
||||
.phymode = WMI_PEER_PHYMODE,
|
||||
.dummy_var = WMI_PEER_DUMMY_VAR,
|
||||
};
|
||||
|
||||
/* MAIN WMI VDEV param map */
|
||||
static struct wmi_vdev_param_map wmi_vdev_param_map = {
|
||||
.rts_threshold = WMI_VDEV_PARAM_RTS_THRESHOLD,
|
||||
@ -5344,11 +5357,14 @@ ath10k_wmi_main_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
|
||||
arg->max_tx_power = ev->hw_max_tx_power;
|
||||
arg->ht_cap = ev->ht_cap_info;
|
||||
arg->vht_cap = ev->vht_cap_info;
|
||||
arg->vht_supp_mcs = ev->vht_supp_mcs;
|
||||
arg->sw_ver0 = ev->sw_version;
|
||||
arg->sw_ver1 = ev->sw_version_1;
|
||||
arg->phy_capab = ev->phy_capability;
|
||||
arg->num_rf_chains = ev->num_rf_chains;
|
||||
arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
|
||||
arg->low_2ghz_chan = ev->hal_reg_capabilities.low_2ghz_chan;
|
||||
arg->high_2ghz_chan = ev->hal_reg_capabilities.high_2ghz_chan;
|
||||
arg->low_5ghz_chan = ev->hal_reg_capabilities.low_5ghz_chan;
|
||||
arg->high_5ghz_chan = ev->hal_reg_capabilities.high_5ghz_chan;
|
||||
arg->num_mem_reqs = ev->num_mem_reqs;
|
||||
@ -5383,16 +5399,25 @@ ath10k_wmi_10x_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
|
||||
arg->max_tx_power = ev->hw_max_tx_power;
|
||||
arg->ht_cap = ev->ht_cap_info;
|
||||
arg->vht_cap = ev->vht_cap_info;
|
||||
arg->vht_supp_mcs = ev->vht_supp_mcs;
|
||||
arg->sw_ver0 = ev->sw_version;
|
||||
arg->phy_capab = ev->phy_capability;
|
||||
arg->num_rf_chains = ev->num_rf_chains;
|
||||
arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
|
||||
arg->low_2ghz_chan = ev->hal_reg_capabilities.low_2ghz_chan;
|
||||
arg->high_2ghz_chan = ev->hal_reg_capabilities.high_2ghz_chan;
|
||||
arg->low_5ghz_chan = ev->hal_reg_capabilities.low_5ghz_chan;
|
||||
arg->high_5ghz_chan = ev->hal_reg_capabilities.high_5ghz_chan;
|
||||
arg->num_mem_reqs = ev->num_mem_reqs;
|
||||
arg->service_map = ev->wmi_service_bitmap;
|
||||
arg->service_map_len = sizeof(ev->wmi_service_bitmap);
|
||||
|
||||
/* Deliberately skipping ev->sys_cap_info as WMI and WMI-TLV have
|
||||
* different values. We would need a translation to handle that,
|
||||
* but as we don't currently need anything from sys_cap_info from
|
||||
* WMI interface (only from WMI-TLV) safest it to skip it.
|
||||
*/
|
||||
|
||||
n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
|
||||
ARRAY_SIZE(arg->mem_reqs));
|
||||
for (i = 0; i < n; i++)
|
||||
@ -5432,6 +5457,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
|
||||
ar->hw_max_tx_power = __le32_to_cpu(arg.max_tx_power);
|
||||
ar->ht_cap_info = __le32_to_cpu(arg.ht_cap);
|
||||
ar->vht_cap_info = __le32_to_cpu(arg.vht_cap);
|
||||
ar->vht_supp_mcs = __le32_to_cpu(arg.vht_supp_mcs);
|
||||
ar->fw_version_major =
|
||||
(__le32_to_cpu(arg.sw_ver0) & 0xff000000) >> 24;
|
||||
ar->fw_version_minor = (__le32_to_cpu(arg.sw_ver0) & 0x00ffffff);
|
||||
@ -5441,11 +5467,16 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
|
||||
ar->phy_capability = __le32_to_cpu(arg.phy_capab);
|
||||
ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains);
|
||||
ar->hw_eeprom_rd = __le32_to_cpu(arg.eeprom_rd);
|
||||
ar->low_2ghz_chan = __le32_to_cpu(arg.low_2ghz_chan);
|
||||
ar->high_2ghz_chan = __le32_to_cpu(arg.high_2ghz_chan);
|
||||
ar->low_5ghz_chan = __le32_to_cpu(arg.low_5ghz_chan);
|
||||
ar->high_5ghz_chan = __le32_to_cpu(arg.high_5ghz_chan);
|
||||
ar->sys_cap_info = __le32_to_cpu(arg.sys_cap_info);
|
||||
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
|
||||
arg.service_map, arg.service_map_len);
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sys_cap_info 0x%x\n",
|
||||
ar->sys_cap_info);
|
||||
|
||||
if (ar->num_rf_chains > ar->max_spatial_stream) {
|
||||
ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n",
|
||||
@ -5544,17 +5575,22 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
|
||||
|
||||
skip_mem_alloc:
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x fw_build 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n",
|
||||
"wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_mcs 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x fw_build 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x low_2ghz_chan %d high_2ghz_chan %d low_5ghz_chan %d high_5ghz_chan %d num_mem_reqs 0x%08x\n",
|
||||
__le32_to_cpu(arg.min_tx_power),
|
||||
__le32_to_cpu(arg.max_tx_power),
|
||||
__le32_to_cpu(arg.ht_cap),
|
||||
__le32_to_cpu(arg.vht_cap),
|
||||
__le32_to_cpu(arg.vht_supp_mcs),
|
||||
__le32_to_cpu(arg.sw_ver0),
|
||||
__le32_to_cpu(arg.sw_ver1),
|
||||
__le32_to_cpu(arg.fw_build),
|
||||
__le32_to_cpu(arg.phy_capab),
|
||||
__le32_to_cpu(arg.num_rf_chains),
|
||||
__le32_to_cpu(arg.eeprom_rd),
|
||||
__le32_to_cpu(arg.low_2ghz_chan),
|
||||
__le32_to_cpu(arg.high_2ghz_chan),
|
||||
__le32_to_cpu(arg.low_5ghz_chan),
|
||||
__le32_to_cpu(arg.high_5ghz_chan),
|
||||
__le32_to_cpu(arg.num_mem_reqs));
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
@ -5623,7 +5659,7 @@ int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi event ready sw_version %u abi_version %u mac_addr %pM status %d\n",
|
||||
"wmi event ready sw_version 0x%08x abi_version %u mac_addr %pM status %d\n",
|
||||
__le32_to_cpu(arg.sw_version),
|
||||
__le32_to_cpu(arg.abi_version),
|
||||
arg.mac_addr,
|
||||
@ -9332,6 +9368,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
||||
ar->wmi.cmd = &wmi_10_4_cmd_map;
|
||||
ar->wmi.vdev_param = &wmi_10_4_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_10_4_pdev_param_map;
|
||||
ar->wmi.peer_param = &wmi_peer_param_map;
|
||||
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
|
||||
ar->wmi_key_cipher = wmi_key_cipher_suites;
|
||||
break;
|
||||
@ -9340,6 +9377,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
||||
ar->wmi.ops = &wmi_10_2_4_ops;
|
||||
ar->wmi.vdev_param = &wmi_10_2_4_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_10_2_4_pdev_param_map;
|
||||
ar->wmi.peer_param = &wmi_peer_param_map;
|
||||
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
|
||||
ar->wmi_key_cipher = wmi_key_cipher_suites;
|
||||
break;
|
||||
@ -9348,6 +9386,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
||||
ar->wmi.ops = &wmi_10_2_ops;
|
||||
ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
|
||||
ar->wmi.peer_param = &wmi_peer_param_map;
|
||||
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
|
||||
ar->wmi_key_cipher = wmi_key_cipher_suites;
|
||||
break;
|
||||
@ -9356,6 +9395,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
||||
ar->wmi.ops = &wmi_10_1_ops;
|
||||
ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
|
||||
ar->wmi.peer_param = &wmi_peer_param_map;
|
||||
ar->wmi.peer_flags = &wmi_10x_peer_flags_map;
|
||||
ar->wmi_key_cipher = wmi_key_cipher_suites;
|
||||
break;
|
||||
@ -9364,6 +9404,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
||||
ar->wmi.ops = &wmi_ops;
|
||||
ar->wmi.vdev_param = &wmi_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_pdev_param_map;
|
||||
ar->wmi.peer_param = &wmi_peer_param_map;
|
||||
ar->wmi.peer_flags = &wmi_peer_flags_map;
|
||||
ar->wmi_key_cipher = wmi_key_cipher_suites;
|
||||
break;
|
||||
@ -9440,7 +9481,5 @@ void ath10k_wmi_detach(struct ath10k *ar)
|
||||
}
|
||||
|
||||
cancel_work_sync(&ar->svc_rdy_work);
|
||||
|
||||
if (ar->svc_rdy_skb)
|
||||
dev_kfree_skb(ar->svc_rdy_skb);
|
||||
dev_kfree_skb(ar->svc_rdy_skb);
|
||||
}
|
||||
|
@ -202,6 +202,7 @@ enum wmi_service {
|
||||
WMI_SERVICE_REPORT_AIRTIME,
|
||||
WMI_SERVICE_SYNC_DELETE_CMDS,
|
||||
WMI_SERVICE_TX_PWR_PER_PEER,
|
||||
WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
|
||||
|
||||
/* Remember to add the new value to wmi_service_name()! */
|
||||
|
||||
@ -496,6 +497,7 @@ static inline char *wmi_service_name(enum wmi_service service_id)
|
||||
SVCSTR(WMI_SERVICE_REPORT_AIRTIME);
|
||||
SVCSTR(WMI_SERVICE_SYNC_DELETE_CMDS);
|
||||
SVCSTR(WMI_SERVICE_TX_PWR_PER_PEER);
|
||||
SVCSTR(WMI_SERVICE_SUPPORT_EXTEND_ADDRESS);
|
||||
|
||||
case WMI_SERVICE_MAX:
|
||||
return NULL;
|
||||
@ -3786,6 +3788,8 @@ struct wmi_pdev_param_map {
|
||||
u32 arp_srcaddr;
|
||||
u32 arp_dstaddr;
|
||||
u32 enable_btcoex;
|
||||
u32 rfkill_config;
|
||||
u32 rfkill_enable;
|
||||
};
|
||||
|
||||
#define WMI_PDEV_PARAM_UNSUPPORTED 0
|
||||
@ -5071,6 +5075,25 @@ enum wmi_rate_preamble {
|
||||
/* Value to disable fixed rate setting */
|
||||
#define WMI_FIXED_RATE_NONE (0xff)
|
||||
|
||||
struct wmi_peer_param_map {
|
||||
u32 smps_state;
|
||||
u32 ampdu;
|
||||
u32 authorize;
|
||||
u32 chan_width;
|
||||
u32 nss;
|
||||
u32 use_4addr;
|
||||
u32 membership;
|
||||
u32 use_fixed_power;
|
||||
u32 user_pos;
|
||||
u32 crit_proto_hint_enabled;
|
||||
u32 tx_fail_cnt_thr;
|
||||
u32 set_hw_retry_cts2s;
|
||||
u32 ibss_atim_win_len;
|
||||
u32 debug;
|
||||
u32 phymode;
|
||||
u32 dummy_var;
|
||||
};
|
||||
|
||||
struct wmi_vdev_param_map {
|
||||
u32 rts_threshold;
|
||||
u32 fragmentation_threshold;
|
||||
@ -6842,6 +6865,7 @@ struct wmi_svc_rdy_ev_arg {
|
||||
__le32 max_tx_power;
|
||||
__le32 ht_cap;
|
||||
__le32 vht_cap;
|
||||
__le32 vht_supp_mcs;
|
||||
__le32 sw_ver0;
|
||||
__le32 sw_ver1;
|
||||
__le32 fw_build;
|
||||
@ -6849,8 +6873,11 @@ struct wmi_svc_rdy_ev_arg {
|
||||
__le32 num_rf_chains;
|
||||
__le32 eeprom_rd;
|
||||
__le32 num_mem_reqs;
|
||||
__le32 low_2ghz_chan;
|
||||
__le32 high_2ghz_chan;
|
||||
__le32 low_5ghz_chan;
|
||||
__le32 high_5ghz_chan;
|
||||
__le32 sys_cap_info;
|
||||
const __le32 *service_map;
|
||||
size_t service_map_len;
|
||||
const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS];
|
||||
|
@ -300,8 +300,7 @@ ath5k_pci_remove(struct pci_dev *pdev)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int ath5k_pci_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct ieee80211_hw *hw = dev_get_drvdata(dev);
|
||||
struct ath5k_hw *ah = hw->priv;
|
||||
|
||||
ath5k_led_off(ah);
|
||||
|
@ -3650,7 +3650,7 @@ static int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id,
|
||||
if (wait)
|
||||
return -EINVAL; /* Offload for wait not supported */
|
||||
|
||||
buf = kmalloc(data_len, GFP_KERNEL);
|
||||
buf = kmemdup(data, data_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -3661,7 +3661,6 @@ static int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id,
|
||||
}
|
||||
|
||||
kfree(wmi->last_mgmt_tx_frame);
|
||||
memcpy(buf, data, data_len);
|
||||
wmi->last_mgmt_tx_frame = buf;
|
||||
wmi->last_mgmt_tx_frame_len = data_len;
|
||||
|
||||
@ -3689,7 +3688,7 @@ static int __ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id,
|
||||
if (wait)
|
||||
return -EINVAL; /* Offload for wait not supported */
|
||||
|
||||
buf = kmalloc(data_len, GFP_KERNEL);
|
||||
buf = kmemdup(data, data_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -3700,7 +3699,6 @@ static int __ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id,
|
||||
}
|
||||
|
||||
kfree(wmi->last_mgmt_tx_frame);
|
||||
memcpy(buf, data, data_len);
|
||||
wmi->last_mgmt_tx_frame = buf;
|
||||
wmi->last_mgmt_tx_frame_len = data_len;
|
||||
|
||||
|
@ -4183,7 +4183,7 @@ static void ar9003_hw_thermometer_apply(struct ath_hw *ah)
|
||||
|
||||
static void ar9003_hw_thermo_cal_apply(struct ath_hw *ah)
|
||||
{
|
||||
u32 data, ko, kg;
|
||||
u32 data = 0, ko, kg;
|
||||
|
||||
if (!AR_SREV_9462_20_OR_LATER(ah))
|
||||
return;
|
||||
|
@ -12,7 +12,6 @@
|
||||
* initialize the chip when the user-space is ready to extract the init code.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/firmware.h>
|
||||
|
@ -973,6 +973,8 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||
struct ath_htc_rx_status *rxstatus;
|
||||
struct ath_rx_status rx_stats;
|
||||
bool decrypt_error = false;
|
||||
__be16 rs_datalen;
|
||||
bool is_phyerr;
|
||||
|
||||
if (skb->len < HTC_RX_FRAME_HEADER_SIZE) {
|
||||
ath_err(common, "Corrupted RX frame, dropping (len: %d)\n",
|
||||
@ -982,11 +984,24 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||
|
||||
rxstatus = (struct ath_htc_rx_status *)skb->data;
|
||||
|
||||
if (be16_to_cpu(rxstatus->rs_datalen) -
|
||||
(skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) {
|
||||
rs_datalen = be16_to_cpu(rxstatus->rs_datalen);
|
||||
if (unlikely(rs_datalen -
|
||||
(skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0)) {
|
||||
ath_err(common,
|
||||
"Corrupted RX data len, dropping (dlen: %d, skblen: %d)\n",
|
||||
rxstatus->rs_datalen, skb->len);
|
||||
rs_datalen, skb->len);
|
||||
goto rx_next;
|
||||
}
|
||||
|
||||
is_phyerr = rxstatus->rs_status & ATH9K_RXERR_PHY;
|
||||
/*
|
||||
* Discard zero-length packets and packets smaller than an ACK
|
||||
* which are not PHY_ERROR (short radar pulses have a length of 3)
|
||||
*/
|
||||
if (unlikely(!rs_datalen || (rs_datalen < 10 && !is_phyerr))) {
|
||||
ath_warn(common,
|
||||
"Short RX data len, dropping (dlen: %d)\n",
|
||||
rs_datalen);
|
||||
goto rx_next;
|
||||
}
|
||||
|
||||
@ -1011,7 +1026,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||
* Process PHY errors and return so that the packet
|
||||
* can be dropped.
|
||||
*/
|
||||
if (rx_stats.rs_status & ATH9K_RXERR_PHY) {
|
||||
if (unlikely(is_phyerr)) {
|
||||
/* TODO: Not using DFS processing now. */
|
||||
if (ath_cmn_process_fft(&priv->spec_priv, hdr,
|
||||
&rx_stats, rx_status->mactime)) {
|
||||
|
@ -1021,13 +1021,12 @@ static void ath_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
static int ath_pci_suspend(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct ieee80211_hw *hw = dev_get_drvdata(device);
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
|
||||
if (test_bit(ATH_OP_WOW_ENABLED, &common->op_flags)) {
|
||||
dev_info(&pdev->dev, "WOW is enabled, bypassing PCI suspend\n");
|
||||
dev_info(device, "WOW is enabled, bypassing PCI suspend\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -629,8 +629,7 @@ static int __maybe_unused wil6210_pm_resume(struct device *dev)
|
||||
|
||||
static int __maybe_unused wil6210_pm_runtime_idle(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct wil6210_priv *wil = pci_get_drvdata(pdev);
|
||||
struct wil6210_priv *wil = dev_get_drvdata(dev);
|
||||
|
||||
wil_dbg_pm(wil, "Runtime idle\n");
|
||||
|
||||
@ -644,8 +643,7 @@ static int __maybe_unused wil6210_pm_runtime_resume(struct device *dev)
|
||||
|
||||
static int __maybe_unused wil6210_pm_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct wil6210_priv *wil = pci_get_drvdata(pdev);
|
||||
struct wil6210_priv *wil = dev_get_drvdata(dev);
|
||||
|
||||
if (test_bit(wil_status_suspended, wil->status)) {
|
||||
wil_dbg_pm(wil, "trying to suspend while suspended\n");
|
||||
|
@ -2505,7 +2505,8 @@ int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie)
|
||||
cmd->mgmt_frm_type = type;
|
||||
/* BUG: FW API define ieLen as u8. Will fix FW */
|
||||
cmd->ie_len = cpu_to_le16(ie_len);
|
||||
memcpy(cmd->ie_info, ie, ie_len);
|
||||
if (ie_len)
|
||||
memcpy(cmd->ie_info, ie, ie_len);
|
||||
rc = wmi_send(wil, WMI_SET_APPIE_CMDID, vif->mid, cmd, len);
|
||||
kfree(cmd);
|
||||
out:
|
||||
@ -2541,7 +2542,8 @@ int wmi_update_ft_ies(struct wil6210_vif *vif, u16 ie_len, const void *ie)
|
||||
}
|
||||
|
||||
cmd->ie_len = cpu_to_le16(ie_len);
|
||||
memcpy(cmd->ie_info, ie, ie_len);
|
||||
if (ie_len)
|
||||
memcpy(cmd->ie_info, ie, ie_len);
|
||||
rc = wmi_send(wil, WMI_UPDATE_FT_IES_CMDID, vif->mid, cmd, len);
|
||||
kfree(cmd);
|
||||
|
||||
@ -2715,7 +2717,7 @@ int wmi_get_all_temperatures(struct wil6210_priv *wil,
|
||||
return rc;
|
||||
|
||||
if (reply.evt.status == WMI_FW_STATUS_FAILURE) {
|
||||
wil_err(wil, "Failed geting TEMP_SENSE_ALL\n");
|
||||
wil_err(wil, "Failed getting TEMP_SENSE_ALL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -117,11 +117,9 @@ static int atmel_config_check(struct pcmcia_device *p_dev, void *priv_data)
|
||||
|
||||
static int atmel_config(struct pcmcia_device *link)
|
||||
{
|
||||
struct local_info *dev;
|
||||
int ret;
|
||||
const struct pcmcia_device_id *did;
|
||||
|
||||
dev = link->priv;
|
||||
did = dev_get_drvdata(&link->dev);
|
||||
|
||||
dev_dbg(&link->dev, "atmel_config\n");
|
||||
|
@ -1400,7 +1400,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
|
||||
/* This TX ring is full. */
|
||||
unsigned int skb_mapping = skb_get_queue_mapping(skb);
|
||||
ieee80211_stop_queue(dev->wl->hw, skb_mapping);
|
||||
dev->wl->tx_queue_stopped[skb_mapping] = 1;
|
||||
dev->wl->tx_queue_stopped[skb_mapping] = true;
|
||||
ring->stopped = true;
|
||||
if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
|
||||
b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
|
||||
@ -1566,7 +1566,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
||||
}
|
||||
|
||||
if (dev->wl->tx_queue_stopped[ring->queue_prio]) {
|
||||
dev->wl->tx_queue_stopped[ring->queue_prio] = 0;
|
||||
dev->wl->tx_queue_stopped[ring->queue_prio] = false;
|
||||
} else {
|
||||
/* If the driver queue is running wake the corresponding
|
||||
* mac80211 queue. */
|
||||
|
@ -3600,7 +3600,7 @@ static void b43_tx_work(struct work_struct *work)
|
||||
else
|
||||
err = b43_dma_tx(dev, skb);
|
||||
if (err == -ENOSPC) {
|
||||
wl->tx_queue_stopped[queue_num] = 1;
|
||||
wl->tx_queue_stopped[queue_num] = true;
|
||||
ieee80211_stop_queue(wl->hw, queue_num);
|
||||
skb_queue_head(&wl->tx_queue[queue_num], skb);
|
||||
break;
|
||||
@ -3611,7 +3611,7 @@ static void b43_tx_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
if (!err)
|
||||
wl->tx_queue_stopped[queue_num] = 0;
|
||||
wl->tx_queue_stopped[queue_num] = false;
|
||||
}
|
||||
|
||||
#if B43_DEBUG
|
||||
@ -5603,7 +5603,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
|
||||
/* Initialize queues and flags. */
|
||||
for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) {
|
||||
skb_queue_head_init(&wl->tx_queue[queue_num]);
|
||||
wl->tx_queue_stopped[queue_num] = 0;
|
||||
wl->tx_queue_stopped[queue_num] = false;
|
||||
}
|
||||
|
||||
snprintf(chip_name, ARRAY_SIZE(chip_name),
|
||||
|
@ -1108,7 +1108,8 @@ static int brcmf_ops_sdio_suspend(struct device *dev)
|
||||
struct sdio_func *func;
|
||||
struct brcmf_bus *bus_if;
|
||||
struct brcmf_sdio_dev *sdiodev;
|
||||
mmc_pm_flag_t sdio_flags;
|
||||
mmc_pm_flag_t pm_caps, sdio_flags;
|
||||
int ret = 0;
|
||||
|
||||
func = container_of(dev, struct sdio_func, dev);
|
||||
brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
|
||||
@ -1119,19 +1120,33 @@ static int brcmf_ops_sdio_suspend(struct device *dev)
|
||||
bus_if = dev_get_drvdata(dev);
|
||||
sdiodev = bus_if->bus_priv.sdio;
|
||||
|
||||
brcmf_sdiod_freezer_on(sdiodev);
|
||||
brcmf_sdio_wd_timer(sdiodev->bus, 0);
|
||||
pm_caps = sdio_get_host_pm_caps(func);
|
||||
|
||||
sdio_flags = MMC_PM_KEEP_POWER;
|
||||
if (sdiodev->wowl_enabled) {
|
||||
if (sdiodev->settings->bus.sdio.oob_irq_supported)
|
||||
enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
|
||||
else
|
||||
sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
|
||||
if (pm_caps & MMC_PM_KEEP_POWER) {
|
||||
/* preserve card power during suspend */
|
||||
brcmf_sdiod_freezer_on(sdiodev);
|
||||
brcmf_sdio_wd_timer(sdiodev->bus, 0);
|
||||
|
||||
sdio_flags = MMC_PM_KEEP_POWER;
|
||||
if (sdiodev->wowl_enabled) {
|
||||
if (sdiodev->settings->bus.sdio.oob_irq_supported)
|
||||
enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
|
||||
else
|
||||
sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
|
||||
}
|
||||
|
||||
if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags))
|
||||
brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
|
||||
|
||||
} else {
|
||||
/* power will be cut so remove device, probe again in resume */
|
||||
brcmf_sdiod_intr_unregister(sdiodev);
|
||||
ret = brcmf_sdiod_remove(sdiodev);
|
||||
if (ret)
|
||||
brcmf_err("Failed to remove device on suspend\n");
|
||||
}
|
||||
if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags))
|
||||
brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int brcmf_ops_sdio_resume(struct device *dev)
|
||||
@ -1139,13 +1154,23 @@ static int brcmf_ops_sdio_resume(struct device *dev)
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||
struct sdio_func *func = container_of(dev, struct sdio_func, dev);
|
||||
mmc_pm_flag_t pm_caps = sdio_get_host_pm_caps(func);
|
||||
int ret = 0;
|
||||
|
||||
brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
|
||||
if (func->num != 2)
|
||||
return 0;
|
||||
|
||||
brcmf_sdiod_freezer_off(sdiodev);
|
||||
return 0;
|
||||
if (!(pm_caps & MMC_PM_KEEP_POWER)) {
|
||||
/* bus was powered off and device removed, probe again */
|
||||
ret = brcmf_sdiod_probe(sdiodev);
|
||||
if (ret)
|
||||
brcmf_err("Failed to probe device on resume\n");
|
||||
} else {
|
||||
brcmf_sdiod_freezer_off(sdiodev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops brcmf_sdio_pm_ops = {
|
||||
|
@ -1282,6 +1282,31 @@ static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int brcmf_set_sae_password(struct brcmf_if *ifp, const u8 *pwd_data,
|
||||
u16 pwd_len)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct brcmf_wsec_sae_pwd_le sae_pwd;
|
||||
int err;
|
||||
|
||||
if (pwd_len > BRCMF_WSEC_MAX_SAE_PASSWORD_LEN) {
|
||||
bphy_err(drvr, "sae_password must be less than %d\n",
|
||||
BRCMF_WSEC_MAX_SAE_PASSWORD_LEN);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sae_pwd.key_len = cpu_to_le16(pwd_len);
|
||||
memcpy(sae_pwd.key, pwd_data, pwd_len);
|
||||
|
||||
err = brcmf_fil_iovar_data_set(ifp, "sae_password", &sae_pwd,
|
||||
sizeof(sae_pwd));
|
||||
if (err < 0)
|
||||
bphy_err(drvr, "failed to set SAE password in firmware (len=%u)\n",
|
||||
pwd_len);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy);
|
||||
@ -1505,6 +1530,8 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
|
||||
val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
|
||||
else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
|
||||
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
|
||||
else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3)
|
||||
val = WPA3_AUTH_SAE_PSK;
|
||||
else
|
||||
val = WPA_AUTH_DISABLED;
|
||||
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
|
||||
@ -1537,6 +1564,10 @@ static s32 brcmf_set_auth_type(struct net_device *ndev,
|
||||
val = 1;
|
||||
brcmf_dbg(CONN, "shared key\n");
|
||||
break;
|
||||
case NL80211_AUTHTYPE_SAE:
|
||||
val = 3;
|
||||
brcmf_dbg(CONN, "SAE authentication\n");
|
||||
break;
|
||||
default:
|
||||
val = 2;
|
||||
brcmf_dbg(CONN, "automatic, auth type (%d)\n", sme->auth_type);
|
||||
@ -1647,6 +1678,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
|
||||
u16 count;
|
||||
|
||||
profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
|
||||
profile->is_ft = false;
|
||||
|
||||
if (!sme->crypto.n_akm_suites)
|
||||
return 0;
|
||||
@ -1691,11 +1723,23 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
|
||||
break;
|
||||
case WLAN_AKM_SUITE_FT_8021X:
|
||||
val = WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_FT;
|
||||
profile->is_ft = true;
|
||||
if (sme->want_1x)
|
||||
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
|
||||
break;
|
||||
case WLAN_AKM_SUITE_FT_PSK:
|
||||
val = WPA2_AUTH_PSK | WPA2_AUTH_FT;
|
||||
profile->is_ft = true;
|
||||
break;
|
||||
default:
|
||||
bphy_err(drvr, "invalid cipher group (%d)\n",
|
||||
sme->crypto.cipher_group);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (val & WPA3_AUTH_SAE_PSK) {
|
||||
switch (sme->crypto.akm_suites[0]) {
|
||||
case WLAN_AKM_SUITE_SAE:
|
||||
val = WPA3_AUTH_SAE_PSK;
|
||||
break;
|
||||
default:
|
||||
bphy_err(drvr, "invalid cipher group (%d)\n",
|
||||
@ -1773,7 +1817,8 @@ brcmf_set_sharedkey(struct net_device *ndev,
|
||||
brcmf_dbg(CONN, "wpa_versions 0x%x cipher_pairwise 0x%x\n",
|
||||
sec->wpa_versions, sec->cipher_pairwise);
|
||||
|
||||
if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
|
||||
if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2 |
|
||||
NL80211_WPA_VERSION_3))
|
||||
return 0;
|
||||
|
||||
if (!(sec->cipher_pairwise &
|
||||
@ -1980,7 +2025,13 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (sme->crypto.psk) {
|
||||
if (sme->crypto.sae_pwd) {
|
||||
brcmf_dbg(INFO, "using SAE offload\n");
|
||||
profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE;
|
||||
}
|
||||
|
||||
if (sme->crypto.psk &&
|
||||
profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) {
|
||||
if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) {
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
@ -1998,12 +2049,23 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
|
||||
}
|
||||
}
|
||||
|
||||
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) {
|
||||
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK)
|
||||
err = brcmf_set_pmk(ifp, sme->crypto.psk,
|
||||
BRCMF_WSEC_MAX_PSK_LEN);
|
||||
if (err)
|
||||
else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE) {
|
||||
/* clean up user-space RSNE */
|
||||
if (brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0)) {
|
||||
bphy_err(drvr, "failed to clean up user-space RSNE\n");
|
||||
goto done;
|
||||
}
|
||||
err = brcmf_set_sae_password(ifp, sme->crypto.sae_pwd,
|
||||
sme->crypto.sae_pwd_len);
|
||||
if (!err && sme->crypto.psk)
|
||||
err = brcmf_set_pmk(ifp, sme->crypto.psk,
|
||||
BRCMF_WSEC_MAX_PSK_LEN);
|
||||
}
|
||||
if (err)
|
||||
goto done;
|
||||
|
||||
/* Join with specific BSSID and cached SSID
|
||||
* If SSID is zero join based on BSSID only
|
||||
@ -5359,7 +5421,8 @@ static bool brcmf_is_linkup(struct brcmf_cfg80211_vif *vif,
|
||||
if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
|
||||
brcmf_dbg(CONN, "Processing set ssid\n");
|
||||
memcpy(vif->profile.bssid, e->addr, ETH_ALEN);
|
||||
if (vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_PSK)
|
||||
if (vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_PSK &&
|
||||
vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_SAE)
|
||||
return true;
|
||||
|
||||
set_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state);
|
||||
@ -5554,6 +5617,11 @@ done:
|
||||
cfg80211_roamed(ndev, &roam_info, GFP_KERNEL);
|
||||
brcmf_dbg(CONN, "Report roaming result\n");
|
||||
|
||||
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X && profile->is_ft) {
|
||||
cfg80211_port_authorized(ndev, profile->bssid, GFP_KERNEL);
|
||||
brcmf_dbg(CONN, "Report port authorized\n");
|
||||
}
|
||||
|
||||
set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
|
||||
brcmf_dbg(TRACE, "Exit\n");
|
||||
return err;
|
||||
@ -6664,6 +6732,9 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
|
||||
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK);
|
||||
wiphy_ext_feature_set(wiphy,
|
||||
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X);
|
||||
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SAE))
|
||||
wiphy_ext_feature_set(wiphy,
|
||||
NL80211_EXT_FEATURE_SAE_OFFLOAD);
|
||||
}
|
||||
wiphy->mgmt_stypes = brcmf_txrx_stypes;
|
||||
wiphy->max_remain_on_channel_duration = 5000;
|
||||
|
@ -107,7 +107,8 @@ struct brcmf_cfg80211_security {
|
||||
enum brcmf_profile_fwsup {
|
||||
BRCMF_PROFILE_FWSUP_NONE,
|
||||
BRCMF_PROFILE_FWSUP_PSK,
|
||||
BRCMF_PROFILE_FWSUP_1X
|
||||
BRCMF_PROFILE_FWSUP_1X,
|
||||
BRCMF_PROFILE_FWSUP_SAE
|
||||
};
|
||||
|
||||
/**
|
||||
@ -122,6 +123,7 @@ struct brcmf_cfg80211_profile {
|
||||
struct brcmf_cfg80211_security sec;
|
||||
struct brcmf_wsec_key key[BRCMF_MAX_DEFAULT_KEYS];
|
||||
enum brcmf_profile_fwsup use_fwsup;
|
||||
bool is_ft;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -39,7 +39,8 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
|
||||
{ BRCMF_FEAT_P2P, "p2p" },
|
||||
{ BRCMF_FEAT_MONITOR, "monitor" },
|
||||
{ BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" },
|
||||
{ BRCMF_FEAT_DOT11H, "802.11h" }
|
||||
{ BRCMF_FEAT_DOT11H, "802.11h" },
|
||||
{ BRCMF_FEAT_SAE, "sae" },
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -26,6 +26,7 @@
|
||||
* MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header
|
||||
* MONITOR_FMT_HW_RX_HDR: firmware provides monitor packets with hw/ucode header
|
||||
* DOT11H: firmware supports 802.11h
|
||||
* SAE: simultaneous authentication of equals
|
||||
*/
|
||||
#define BRCMF_FEAT_LIST \
|
||||
BRCMF_FEAT_DEF(MBSS) \
|
||||
@ -45,7 +46,8 @@
|
||||
BRCMF_FEAT_DEF(MONITOR) \
|
||||
BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP) \
|
||||
BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR) \
|
||||
BRCMF_FEAT_DEF(DOT11H)
|
||||
BRCMF_FEAT_DEF(DOT11H) \
|
||||
BRCMF_FEAT_DEF(SAE)
|
||||
|
||||
/*
|
||||
* Quirks:
|
||||
|
@ -61,6 +61,8 @@
|
||||
#define BRCMF_WSEC_MAX_PSK_LEN 32
|
||||
#define BRCMF_WSEC_PASSPHRASE BIT(0)
|
||||
|
||||
#define BRCMF_WSEC_MAX_SAE_PASSWORD_LEN 128
|
||||
|
||||
/* primary (ie tx) key */
|
||||
#define BRCMF_PRIMARY_KEY (1 << 1)
|
||||
#define DOT11_BSSTYPE_ANY 2
|
||||
@ -518,6 +520,17 @@ struct brcmf_wsec_pmk_le {
|
||||
u8 key[2 * BRCMF_WSEC_MAX_PSK_LEN + 1];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_wsec_sae_pwd_le - firmware SAE password material.
|
||||
*
|
||||
* @key_len: number of octets in key materials.
|
||||
* @key: SAE password material.
|
||||
*/
|
||||
struct brcmf_wsec_sae_pwd_le {
|
||||
__le16 key_len;
|
||||
u8 key[BRCMF_WSEC_MAX_SAE_PASSWORD_LEN];
|
||||
};
|
||||
|
||||
/* Used to get specific STA parameters */
|
||||
struct brcmf_scb_val_le {
|
||||
__le32 val;
|
||||
|
@ -1024,8 +1024,6 @@ brcmf_pcie_init_dmabuffer_for_device(struct brcmf_pciedev_info *devinfo,
|
||||
address & 0xffffffff);
|
||||
brcmf_pcie_write_tcm32(devinfo, tcm_dma_phys_addr + 4, address >> 32);
|
||||
|
||||
memset(ring, 0, size);
|
||||
|
||||
return (ring);
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,10 @@ static int brcmf_pno_remove_request(struct brcmf_pno_info *pi, u64 reqid)
|
||||
|
||||
mutex_lock(&pi->req_lock);
|
||||
|
||||
/* Nothing to do if we have no requests */
|
||||
if (pi->n_reqs == 0)
|
||||
goto done;
|
||||
|
||||
/* find request */
|
||||
for (i = 0; i < pi->n_reqs; i++) {
|
||||
if (pi->reqs[i]->reqid == reqid)
|
||||
|
@ -496,13 +496,11 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
|
||||
* table and override CDD later
|
||||
*/
|
||||
if (li_mimo == &locale_bn) {
|
||||
if (li_mimo == &locale_bn) {
|
||||
maxpwr20 = QDB(16);
|
||||
maxpwr40 = 0;
|
||||
maxpwr20 = QDB(16);
|
||||
maxpwr40 = 0;
|
||||
|
||||
if (chan >= 3 && chan <= 11)
|
||||
maxpwr40 = QDB(16);
|
||||
}
|
||||
if (chan >= 3 && chan <= 11)
|
||||
maxpwr40 = QDB(16);
|
||||
|
||||
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
|
||||
txpwr->mcs_20_siso[i] = (u8) maxpwr20;
|
||||
|
@ -1816,8 +1816,7 @@ void brcms_b_phy_reset(struct brcms_hardware *wlc_hw)
|
||||
udelay(2);
|
||||
brcms_b_core_phy_clk(wlc_hw, ON);
|
||||
|
||||
if (pih)
|
||||
wlc_phy_anacore(pih, ON);
|
||||
wlc_phy_anacore(pih, ON);
|
||||
}
|
||||
|
||||
/* switch to and initialize new band */
|
||||
|
@ -231,6 +231,8 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec)
|
||||
#define WPA2_AUTH_FT 0x4000 /* Fast BSS Transition */
|
||||
#define WPA2_AUTH_PSK_SHA256 0x8000 /* PSK with SHA256 key derivation */
|
||||
|
||||
#define WPA3_AUTH_SAE_PSK 0x40000 /* SAE with 4-way handshake */
|
||||
|
||||
#define DOT11_DEFAULT_RTS_LEN 2347
|
||||
#define DOT11_DEFAULT_FRAG_LEN 2346
|
||||
|
||||
|
@ -2301,9 +2301,7 @@ __il3945_down(struct il_priv *il)
|
||||
il3945_hw_txq_ctx_free(il);
|
||||
exit:
|
||||
memset(&il->card_alive, 0, sizeof(struct il_alive_resp));
|
||||
|
||||
if (il->beacon_skb)
|
||||
dev_kfree_skb(il->beacon_skb);
|
||||
dev_kfree_skb(il->beacon_skb);
|
||||
il->beacon_skb = NULL;
|
||||
|
||||
/* clear out any free frames */
|
||||
@ -3846,9 +3844,7 @@ il3945_pci_remove(struct pci_dev *pdev)
|
||||
il_free_channel_map(il);
|
||||
il_free_geos(il);
|
||||
kfree(il->scan_cmd);
|
||||
if (il->beacon_skb)
|
||||
dev_kfree_skb(il->beacon_skb);
|
||||
|
||||
dev_kfree_skb(il->beacon_skb);
|
||||
ieee80211_free_hw(il->hw);
|
||||
}
|
||||
|
||||
|
@ -1072,7 +1072,7 @@ EXPORT_SYMBOL(il_get_channel_info);
|
||||
static void
|
||||
il_build_powertable_cmd(struct il_priv *il, struct il_powertable_cmd *cmd)
|
||||
{
|
||||
const __le32 interval[3][IL_POWER_VEC_SIZE] = {
|
||||
static const __le32 interval[3][IL_POWER_VEC_SIZE] = {
|
||||
SLP_VEC(2, 2, 4, 6, 0xFF),
|
||||
SLP_VEC(2, 4, 7, 10, 10),
|
||||
SLP_VEC(4, 7, 10, 10, 0xFF)
|
||||
@ -5182,8 +5182,7 @@ il_mac_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
memset(&il->current_ht_config, 0, sizeof(struct il_ht_config));
|
||||
|
||||
/* new association get rid of ibss beacon skb */
|
||||
if (il->beacon_skb)
|
||||
dev_kfree_skb(il->beacon_skb);
|
||||
dev_kfree_skb(il->beacon_skb);
|
||||
il->beacon_skb = NULL;
|
||||
il->timestamp = 0;
|
||||
|
||||
@ -5302,10 +5301,7 @@ il_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&il->lock, flags);
|
||||
|
||||
if (il->beacon_skb)
|
||||
dev_kfree_skb(il->beacon_skb);
|
||||
|
||||
dev_kfree_skb(il->beacon_skb);
|
||||
il->beacon_skb = skb;
|
||||
|
||||
timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
|
||||
|
@ -14,7 +14,8 @@ iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o cfg/9000.o cfg/22000.o
|
||||
iwlwifi-objs += iwl-dbg-tlv.o
|
||||
iwlwifi-objs += iwl-trans.o
|
||||
iwlwifi-objs += fw/notif-wait.o
|
||||
iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o fw/dbg.o
|
||||
iwlwifi-objs += fw/dbg.o
|
||||
iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o
|
||||
iwlwifi-$(CONFIG_ACPI) += fw/acpi.o
|
||||
iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += fw/debugfs.o
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/stringify.h>
|
||||
#include "iwl-config.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_22000_UCODE_API_MAX 50
|
||||
@ -183,23 +184,49 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
|
||||
.min_umac_error_event_table = 0x400000, \
|
||||
.d3_debug_data_base_addr = 0x401000, \
|
||||
.d3_debug_data_length = 60 * 1024, \
|
||||
.fw_mon_smem_write_ptr_addr = 0xa0c16c, \
|
||||
.fw_mon_smem_write_ptr_msk = 0xfffff, \
|
||||
.fw_mon_smem_cycle_cnt_ptr_addr = 0xa0c174, \
|
||||
.fw_mon_smem_cycle_cnt_ptr_msk = 0xfffff
|
||||
.mon_smem_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = LDBG_M2S_BUF_WPTR, \
|
||||
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = LDBG_M2S_BUF_WRAP_CNT, \
|
||||
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define IWL_DEVICE_22500 \
|
||||
IWL_DEVICE_22000_COMMON, \
|
||||
.trans.device_family = IWL_DEVICE_FAMILY_22000, \
|
||||
.trans.base_params = &iwl_22000_base_params, \
|
||||
.trans.csr = &iwl_csr_v1, \
|
||||
.gp2_reg_addr = 0xa02c68
|
||||
.gp2_reg_addr = 0xa02c68, \
|
||||
.mon_dram_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = MON_BUFF_WRPTR_VER2, \
|
||||
.mask = 0xffffffff, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = MON_BUFF_CYCLE_CNT_VER2, \
|
||||
.mask = 0xffffffff, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define IWL_DEVICE_22560 \
|
||||
IWL_DEVICE_22000_COMMON, \
|
||||
.trans.device_family = IWL_DEVICE_FAMILY_22560, \
|
||||
.trans.base_params = &iwl_22560_base_params, \
|
||||
.trans.csr = &iwl_csr_v2
|
||||
.trans.csr = &iwl_csr_v2, \
|
||||
.mon_dram_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = MON_BUFF_WRPTR_VER2, \
|
||||
.mask = 0xffffffff, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = MON_BUFF_CYCLE_CNT_VER2, \
|
||||
.mask = 0xffffffff, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define IWL_DEVICE_AX210 \
|
||||
IWL_DEVICE_22000_COMMON, \
|
||||
@ -209,7 +236,21 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
|
||||
.trans.csr = &iwl_csr_v1, \
|
||||
.min_txq_size = 128, \
|
||||
.gp2_reg_addr = 0xd02c68, \
|
||||
.min_256_ba_txq_size = 512
|
||||
.min_256_ba_txq_size = 512, \
|
||||
.mon_dram_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS, \
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = DBGC_DBGBUF_WRAP_AROUND, \
|
||||
.mask = 0xffffffff, \
|
||||
}, \
|
||||
.cur_frag = { \
|
||||
.addr = DBGC_CUR_DBGBUF_STATUS, \
|
||||
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
|
||||
}, \
|
||||
}
|
||||
|
||||
const struct iwl_cfg iwl22000_2ac_cfg_hr = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 22000",
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include <linux/stringify.h>
|
||||
#include "iwl-config.h"
|
||||
#include "fw/file.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL9000_UCODE_API_MAX 46
|
||||
@ -149,10 +150,26 @@ static const struct iwl_tt_params iwl9000_tt_params = {
|
||||
.ht_params = &iwl9000_ht_params, \
|
||||
.nvm_ver = IWL9000_NVM_VERSION, \
|
||||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
|
||||
.fw_mon_smem_write_ptr_addr = 0xa0476c, \
|
||||
.fw_mon_smem_write_ptr_msk = 0xfffff, \
|
||||
.fw_mon_smem_cycle_cnt_ptr_addr = 0xa04774, \
|
||||
.fw_mon_smem_cycle_cnt_ptr_msk = 0xfffff
|
||||
.mon_smem_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = LDBG_M2S_BUF_WPTR, \
|
||||
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = LDBG_M2S_BUF_WRAP_CNT, \
|
||||
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
|
||||
}, \
|
||||
}, \
|
||||
.mon_dram_regs = { \
|
||||
.write_ptr = { \
|
||||
.addr = MON_BUFF_WRPTR_VER2, \
|
||||
.mask = 0xffffffff, \
|
||||
}, \
|
||||
.cycle_cnt = { \
|
||||
.addr = MON_BUFF_CYCLE_CNT_VER2, \
|
||||
.mask = 0xffffffff, \
|
||||
}, \
|
||||
}
|
||||
|
||||
|
||||
const struct iwl_cfg iwl9160_2ac_cfg = {
|
||||
|
@ -64,6 +64,14 @@
|
||||
#ifndef __iwl_fw_api_d3_h__
|
||||
#define __iwl_fw_api_d3_h__
|
||||
|
||||
/**
|
||||
* enum iwl_d0i3_flags - d0i3 flags
|
||||
* @IWL_D0I3_RESET_REQUIRE: FW require reset upon resume
|
||||
*/
|
||||
enum iwl_d0i3_flags {
|
||||
IWL_D0I3_RESET_REQUIRE = BIT(0),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_d3_wakeup_flags - D3 manager wakeup flags
|
||||
* @IWL_WAKEUP_D3_CONFIG_FW_ERROR: wake up on firmware sysassert
|
||||
|
@ -60,52 +60,10 @@
|
||||
|
||||
#include <linux/bitops.h>
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_header: Common Header for all debug group TLV's structures
|
||||
*
|
||||
* @tlv_version: version info
|
||||
* @apply_point: &enum iwl_fw_ini_apply_point
|
||||
* @data: TLV data followed
|
||||
*/
|
||||
struct iwl_fw_ini_header {
|
||||
__le32 tlv_version;
|
||||
__le32 apply_point;
|
||||
u8 data[];
|
||||
} __packed; /* FW_DEBUG_TLV_HEADER_S */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_allocation_tlv - (IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION)
|
||||
* buffer allocation TLV - for debug
|
||||
*
|
||||
* @iwl_fw_ini_header: header
|
||||
* @allocation_id: &enum iwl_fw_ini_allocation_id - to bind allocation and hcmd
|
||||
* if needed (DBGC1/DBGC2/SDFX/...)
|
||||
* @buffer_location: type of iwl_fw_ini_buffer_location
|
||||
* @size: size in bytes
|
||||
* @max_fragments: the maximum allowed fragmentation in the desired memory
|
||||
* allocation above
|
||||
* @min_frag_size: the minimum allowed fragmentation size in bytes
|
||||
*/
|
||||
struct iwl_fw_ini_allocation_tlv {
|
||||
struct iwl_fw_ini_header header;
|
||||
__le32 allocation_id;
|
||||
__le32 buffer_location;
|
||||
__le32 size;
|
||||
__le32 max_fragments;
|
||||
__le32 min_frag_size;
|
||||
} __packed; /* FW_DEBUG_TLV_BUFFER_ALLOCATION_TLV_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_dbg_domain - debug domains
|
||||
* allows to send host cmd or collect memory region if a given domain is enabled
|
||||
*
|
||||
* @IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON: the default domain, always on
|
||||
* @IWL_FW_INI_DBG_DOMAIN_REPORT_PS: power save domain
|
||||
*/
|
||||
enum iwl_fw_ini_dbg_domain {
|
||||
IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON = 0,
|
||||
IWL_FW_INI_DBG_DOMAIN_REPORT_PS,
|
||||
}; /* FW_DEBUG_TLV_DOMAIN_API_E_VER_1 */
|
||||
#define IWL_FW_INI_MAX_REGION_ID 64
|
||||
#define IWL_FW_INI_MAX_NAME 32
|
||||
#define IWL_FW_INI_MAX_CFG_NAME 64
|
||||
#define IWL_FW_INI_DOMAIN_ALWAYS_ON 0
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_hcmd
|
||||
@ -123,279 +81,198 @@ struct iwl_fw_ini_hcmd {
|
||||
} __packed; /* FW_DEBUG_TLV_HCMD_DATA_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_hcmd_tlv - (IWL_UCODE_TLV_TYPE_HCMD)
|
||||
* Generic Host command pass through TLV
|
||||
* struct iwl_fw_ini_header - Common Header for all ini debug TLV's structures
|
||||
*
|
||||
* @header: header
|
||||
* @domain: send command only if the specific domain is enabled
|
||||
* &enum iwl_fw_ini_dbg_domain
|
||||
* @period_msec: period in which the hcmd will be sent to FW. Measured in msec
|
||||
* (0 = one time command).
|
||||
* @hcmd: a variable length host-command to be sent to apply the configuration.
|
||||
* @version: TLV version
|
||||
* @domain: domain of the TLV. One of &enum iwl_fw_ini_dbg_domain
|
||||
* @data: TLV data
|
||||
*/
|
||||
struct iwl_fw_ini_hcmd_tlv {
|
||||
struct iwl_fw_ini_header header;
|
||||
struct iwl_fw_ini_header {
|
||||
__le32 version;
|
||||
__le32 domain;
|
||||
__le32 period_msec;
|
||||
struct iwl_fw_ini_hcmd hcmd;
|
||||
} __packed; /* FW_DEBUG_TLV_HCMD_API_S_VER_1 */
|
||||
|
||||
#define IWL_FW_INI_MAX_REGION_ID 64
|
||||
#define IWL_FW_INI_MAX_NAME 32
|
||||
u8 data[];
|
||||
} __packed; /* FW_TLV_DEBUG_HEADER_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_cfg_dhc - defines dhc response to dump.
|
||||
* struct iwl_fw_ini_region_dev_addr - Configuration to read device addresses
|
||||
*
|
||||
* @id_and_grp: id and group of dhc response.
|
||||
* @desc: dhc response descriptor.
|
||||
* @size: size of each memory chunk
|
||||
* @offset: offset to add to the base address of each chunk
|
||||
*/
|
||||
struct iwl_fw_ini_region_cfg_dhc {
|
||||
__le32 id_and_grp;
|
||||
__le32 desc;
|
||||
} __packed; /* FW_DEBUG_TLV_REGION_DHC_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_cfg_internal - meta data of internal memory region
|
||||
*
|
||||
* @num_of_range: the amount of ranges in the region
|
||||
* @range_data_size: size of the data to read per range, in bytes.
|
||||
*/
|
||||
struct iwl_fw_ini_region_cfg_internal {
|
||||
__le32 num_of_ranges;
|
||||
__le32 range_data_size;
|
||||
} __packed; /* FW_DEBUG_TLV_REGION_NIC_INTERNAL_RANGES_S */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_cfg_fifos - meta data of fifos region
|
||||
*
|
||||
* @fid1: fifo id 1 - bitmap of lmac tx/rx fifos to include in the region
|
||||
* @fid2: fifo id 2 - bitmap of umac rx fifos to include in the region.
|
||||
* It is unused for tx.
|
||||
* @num_of_registers: number of prph registers in the region, each register is
|
||||
* 4 bytes size.
|
||||
* @header_only: none zero value indicates that this region does not include
|
||||
* fifo data and includes only the given registers.
|
||||
*/
|
||||
struct iwl_fw_ini_region_cfg_fifos {
|
||||
__le32 fid1;
|
||||
__le32 fid2;
|
||||
__le32 num_of_registers;
|
||||
__le32 header_only;
|
||||
} __packed; /* FW_DEBUG_TLV_REGION_FIFOS_S */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_cfg
|
||||
*
|
||||
* @region_id: ID of this dump configuration
|
||||
* @region_type: &enum iwl_fw_ini_region_type
|
||||
* @domain: dump this region only if the specific domain is enabled
|
||||
* &enum iwl_fw_ini_dbg_domain
|
||||
* @name_len: name length
|
||||
* @name: file name to use for this region
|
||||
* @internal: used in case the region uses internal memory.
|
||||
* @allocation_id: For DRAM type field substitutes for allocation_id
|
||||
* @fifos: used in case of fifos region.
|
||||
* @dhc_desc: dhc response descriptor.
|
||||
* @notif_id_and_grp: dump this region only if the specific notification
|
||||
* occurred.
|
||||
* @offset: offset to use for each memory base address
|
||||
* @start_addr: array of addresses.
|
||||
*/
|
||||
struct iwl_fw_ini_region_cfg {
|
||||
__le32 region_id;
|
||||
__le32 region_type;
|
||||
__le32 domain;
|
||||
__le32 name_len;
|
||||
u8 name[IWL_FW_INI_MAX_NAME];
|
||||
union {
|
||||
struct iwl_fw_ini_region_cfg_internal internal;
|
||||
__le32 allocation_id;
|
||||
struct iwl_fw_ini_region_cfg_fifos fifos;
|
||||
struct iwl_fw_ini_region_cfg_dhc dhc_desc;
|
||||
__le32 notif_id_and_grp;
|
||||
}; /* FW_DEBUG_TLV_REGION_EXT_INT_PARAMS_API_U_VER_1 */
|
||||
struct iwl_fw_ini_region_dev_addr {
|
||||
__le32 size;
|
||||
__le32 offset;
|
||||
__le32 start_addr[];
|
||||
} __packed; /* FW_DEBUG_TLV_REGION_CONFIG_API_S_VER_1 */
|
||||
} __packed; /* FW_TLV_DEBUG_DEVICE_ADDR_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_tlv - (IWL_UCODE_TLV_TYPE_REGIONS)
|
||||
* defines memory regions to dump
|
||||
* struct iwl_fw_ini_region_fifos - Configuration to read Tx/Rx fifos
|
||||
*
|
||||
* @header: header
|
||||
* @num_regions: how many different region section and IDs are coming next
|
||||
* @region_config: list of dump configurations
|
||||
* @fid: fifos ids array. Used to determine what fifos to collect
|
||||
* @hdr_only: if non zero, collect only the registers
|
||||
* @offset: offset to add to the registers addresses
|
||||
*/
|
||||
struct iwl_fw_ini_region_fifos {
|
||||
__le32 fid[2];
|
||||
__le32 hdr_only;
|
||||
__le32 offset;
|
||||
} __packed; /* FW_TLV_DEBUG_REGION_FIFOS_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_err_table - error table region data
|
||||
*
|
||||
* Configuration to read Umac/Lmac error table
|
||||
*
|
||||
* @version: version of the error table
|
||||
* @base_addr: base address of the error table
|
||||
* @size: size of the error table
|
||||
* @offset: offset to add to &base_addr
|
||||
*/
|
||||
struct iwl_fw_ini_region_err_table {
|
||||
__le32 version;
|
||||
__le32 base_addr;
|
||||
__le32 size;
|
||||
__le32 offset;
|
||||
} __packed; /* FW_TLV_DEBUG_REGION_ERROR_TABLE_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_internal_buffer - internal buffer region data
|
||||
*
|
||||
* Configuration to read internal monitor buffer
|
||||
*
|
||||
* @alloc_id: allocation id one of &enum iwl_fw_ini_allocation_id
|
||||
* @base_addr: internal buffer base address
|
||||
* @size: size internal buffer size
|
||||
*/
|
||||
struct iwl_fw_ini_region_internal_buffer {
|
||||
__le32 alloc_id;
|
||||
__le32 base_addr;
|
||||
__le32 size;
|
||||
} __packed; /* FW_TLV_DEBUG_REGION_INTERNAL_BUFFER_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_region_tlv - region TLV
|
||||
*
|
||||
* Configures parameters for region data collection
|
||||
*
|
||||
* @hdr: debug header
|
||||
* @id: region id. Max id is &IWL_FW_INI_MAX_REGION_ID
|
||||
* @type: region type. One of &enum iwl_fw_ini_region_type
|
||||
* @name: region name
|
||||
* @dev_addr: device address configuration. Used by
|
||||
* &IWL_FW_INI_REGION_DEVICE_MEMORY, &IWL_FW_INI_REGION_PERIPHERY_MAC,
|
||||
* &IWL_FW_INI_REGION_PERIPHERY_PHY, &IWL_FW_INI_REGION_PERIPHERY_AUX,
|
||||
* &IWL_FW_INI_REGION_PAGING, &IWL_FW_INI_REGION_CSR,
|
||||
* &IWL_FW_INI_REGION_DRAM_IMR and &IWL_FW_INI_REGION_PCI_IOSF_CONFIG
|
||||
* @fifos: fifos configuration. Used by &IWL_FW_INI_REGION_TXF and
|
||||
* &IWL_FW_INI_REGION_RXF
|
||||
* @err_table: error table configuration. Used by
|
||||
* IWL_FW_INI_REGION_LMAC_ERROR_TABLE and
|
||||
* IWL_FW_INI_REGION_UMAC_ERROR_TABLE
|
||||
* @internal_buffer: internal monitor buffer configuration. Used by
|
||||
* &IWL_FW_INI_REGION_INTERNAL_BUFFER
|
||||
* @dram_alloc_id: dram allocation id. One of &enum iwl_fw_ini_allocation_id.
|
||||
* Used by &IWL_FW_INI_REGION_DRAM_BUFFER
|
||||
* @tlv_mask: tlv collection mask. Used by &IWL_FW_INI_REGION_TLV
|
||||
* @addrs: array of addresses attached to the end of the region tlv
|
||||
*/
|
||||
struct iwl_fw_ini_region_tlv {
|
||||
struct iwl_fw_ini_header header;
|
||||
__le32 num_regions;
|
||||
struct iwl_fw_ini_region_cfg region_config[];
|
||||
} __packed; /* FW_DEBUG_TLV_REGIONS_API_S_VER_1 */
|
||||
struct iwl_fw_ini_header hdr;
|
||||
__le32 id;
|
||||
__le32 type;
|
||||
u8 name[IWL_FW_INI_MAX_NAME];
|
||||
union {
|
||||
struct iwl_fw_ini_region_dev_addr dev_addr;
|
||||
struct iwl_fw_ini_region_fifos fifos;
|
||||
struct iwl_fw_ini_region_err_table err_table;
|
||||
struct iwl_fw_ini_region_internal_buffer internal_buffer;
|
||||
__le32 dram_alloc_id;
|
||||
__le32 tlv_mask;
|
||||
}; /* FW_TLV_DEBUG_REGION_CONF_PARAMS_API_U_VER_1 */
|
||||
__le32 addrs[];
|
||||
} __packed; /* FW_TLV_DEBUG_REGION_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_trigger
|
||||
* struct iwl_fw_ini_debug_info_tlv
|
||||
*
|
||||
* @trigger_id: &enum iwl_fw_ini_trigger_id
|
||||
* @override_trig: determines how apply trigger in case a trigger with the
|
||||
* same id is already in use. Using the first 2 bytes:
|
||||
* Byte 0: if 0, override trigger configuration, otherwise use the
|
||||
* existing configuration.
|
||||
* Byte 1: if 0, override trigger regions, otherwise append regions to
|
||||
* existing trigger.
|
||||
* @dump_delay: delay from trigger fire to dump, in usec
|
||||
* @occurrences: max amount of times to be fired
|
||||
* @reserved: to align to FW struct
|
||||
* @ignore_consec: ignore consecutive triggers, in usec
|
||||
* @force_restart: force FW restart
|
||||
* @multi_dut: initiate debug dump data on several DUTs
|
||||
* @trigger_data: generic data to be utilized per trigger
|
||||
* @num_regions: number of dump regions defined for this trigger
|
||||
* @data: region IDs
|
||||
* debug configuration name for a specific image
|
||||
*
|
||||
* @hdr: debug header
|
||||
* @image_type: image type
|
||||
* @debug_cfg_name: debug configuration name
|
||||
*/
|
||||
struct iwl_fw_ini_trigger {
|
||||
__le32 trigger_id;
|
||||
__le32 override_trig;
|
||||
struct iwl_fw_ini_debug_info_tlv {
|
||||
struct iwl_fw_ini_header hdr;
|
||||
__le32 image_type;
|
||||
u8 debug_cfg_name[IWL_FW_INI_MAX_CFG_NAME];
|
||||
} __packed; /* FW_TLV_DEBUG_INFO_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_allocation_tlv - Allocates DRAM buffers
|
||||
*
|
||||
* @hdr: debug header
|
||||
* @alloc_id: allocation id. One of &enum iwl_fw_ini_allocation_id
|
||||
* @buf_location: buffer location. One of &enum iwl_fw_ini_buffer_location
|
||||
* @req_size: requested buffer size
|
||||
* @max_frags_num: maximum number of fragments
|
||||
* @min_size: minimum buffer size
|
||||
*/
|
||||
struct iwl_fw_ini_allocation_tlv {
|
||||
struct iwl_fw_ini_header hdr;
|
||||
__le32 alloc_id;
|
||||
__le32 buf_location;
|
||||
__le32 req_size;
|
||||
__le32 max_frags_num;
|
||||
__le32 min_size;
|
||||
} __packed; /* FW_TLV_DEBUG_BUFFER_ALLOCATION_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_trigger_tlv - trigger TLV
|
||||
*
|
||||
* Trigger that upon firing, determines what regions to collect
|
||||
*
|
||||
* @hdr: debug header
|
||||
* @time_point: time point. One of &enum iwl_fw_ini_time_point
|
||||
* @trigger_reason: trigger reason
|
||||
* @apply_policy: uses &enum iwl_fw_ini_trigger_apply_policy
|
||||
* @dump_delay: delay from trigger fire to dump, in usec
|
||||
* @occurrences: max trigger fire occurrences allowed
|
||||
* @reserved: unused
|
||||
* @ignore_consec: ignore consecutive triggers, in usec
|
||||
* @reset_fw: if non zero, will reset and reload the FW
|
||||
* @multi_dut: initiate debug dump data on several DUTs
|
||||
* @regions_mask: mask of regions to collect
|
||||
* @data: trigger data
|
||||
*/
|
||||
struct iwl_fw_ini_trigger_tlv {
|
||||
struct iwl_fw_ini_header hdr;
|
||||
__le32 time_point;
|
||||
__le32 trigger_reason;
|
||||
__le32 apply_policy;
|
||||
__le32 dump_delay;
|
||||
__le32 occurrences;
|
||||
__le32 reserved;
|
||||
__le32 ignore_consec;
|
||||
__le32 force_restart;
|
||||
__le32 reset_fw;
|
||||
__le32 multi_dut;
|
||||
__le32 trigger_data;
|
||||
__le32 num_regions;
|
||||
__le64 regions_mask;
|
||||
__le32 data[];
|
||||
} __packed; /* FW_TLV_DEBUG_TRIGGER_CONFIG_API_S_VER_1 */
|
||||
} __packed; /* FW_TLV_DEBUG_TRIGGER_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_trigger_tlv - (IWL_UCODE_TLV_TYPE_TRIGGERS)
|
||||
* Triggers that hold memory regions to dump in case a trigger fires
|
||||
* struct iwl_fw_ini_hcmd_tlv - Generic Host command pass through TLV
|
||||
*
|
||||
* @header: header
|
||||
* @num_triggers: how many different triggers section and IDs are coming next
|
||||
* @trigger_config: list of trigger configurations
|
||||
* @hdr: debug header
|
||||
* @time_point: time point. One of &enum iwl_fw_ini_time_point
|
||||
* @period_msec: interval at which the hcmd will be sent to the FW.
|
||||
* Measured in msec (0 = one time command)
|
||||
* @hcmd: a variable length host-command to be sent to apply the configuration
|
||||
*/
|
||||
struct iwl_fw_ini_trigger_tlv {
|
||||
struct iwl_fw_ini_header header;
|
||||
__le32 num_triggers;
|
||||
struct iwl_fw_ini_trigger trigger_config[];
|
||||
} __packed; /* FW_TLV_DEBUG_TRIGGERS_API_S_VER_1 */
|
||||
|
||||
#define IWL_FW_INI_MAX_IMG_NAME_LEN 32
|
||||
#define IWL_FW_INI_MAX_DBG_CFG_NAME_LEN 64
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_debug_info_tlv - (IWL_UCODE_TLV_TYPE_DEBUG_INFO)
|
||||
*
|
||||
* holds image name and debug configuration name
|
||||
*
|
||||
* @header: header
|
||||
* @img_name_len: length of the image name string
|
||||
* @img_name: image name string
|
||||
* @dbg_cfg_name_len : length of the debug configuration name string
|
||||
* @dbg_cfg_name: debug configuration name string
|
||||
*/
|
||||
struct iwl_fw_ini_debug_info_tlv {
|
||||
struct iwl_fw_ini_header header;
|
||||
__le32 img_name_len;
|
||||
u8 img_name[IWL_FW_INI_MAX_IMG_NAME_LEN];
|
||||
__le32 dbg_cfg_name_len;
|
||||
u8 dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
|
||||
} __packed; /* FW_DEBUG_TLV_INFO_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_trigger_id
|
||||
*
|
||||
* @IWL_FW_TRIGGER_ID_FW_ASSERT: FW assert
|
||||
* @IWL_FW_TRIGGER_ID_FW_HW_ERROR: HW assert
|
||||
* @IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG: TFD queue hang
|
||||
* @IWL_FW_TRIGGER_ID_FW_DEBUG_HOST_TRIGGER: FW debug notification
|
||||
* @IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFICATION: FW generic notification
|
||||
* @IWL_FW_TRIGGER_ID_USER_TRIGGER: User trigger
|
||||
* @IWL_FW_TRIGGER_ID_PERIODIC_TRIGGER: triggers periodically
|
||||
* @IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY: peer inactivity
|
||||
* @IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED: TX latency
|
||||
* threshold was crossed
|
||||
* @IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED: TX failed
|
||||
* @IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER: Deauth initiated by host
|
||||
* @IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST: stop GO request
|
||||
* @IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST: start GO request
|
||||
* @IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST: join P2P group request
|
||||
* @IWL_FW_TRIGGER_ID_HOST_SCAN_START: scan started event
|
||||
* @IWL_FW_TRIGGER_ID_HOST_SCAN_SUBMITTED: undefined
|
||||
* @IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS: undefined
|
||||
* @IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG: undefined
|
||||
* @IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED: BAR frame was received
|
||||
* @IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED: agg TX failed
|
||||
* @IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED: EAPOL TX failed
|
||||
* @IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED: suspicious TX response
|
||||
* @IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT: received suspicious auth
|
||||
* @IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE: roaming was completed
|
||||
* @IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED: fast assoc failed
|
||||
* @IWL_FW_TRIGGER_ID_HOST_D3_START: D3 start
|
||||
* @IWL_FW_TRIGGER_ID_HOST_D3_END: D3 end
|
||||
* @IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS: missed beacon events
|
||||
* @IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS: P2P missed beacon events
|
||||
* @IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES: undefined
|
||||
* @IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED: undefined
|
||||
* @IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED: authentication / association
|
||||
* failed
|
||||
* @IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE: scan complete event
|
||||
* @IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT: scan abort complete
|
||||
* @IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE: nic alive message was received
|
||||
* @IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE: CSA was completed
|
||||
* @IWL_FW_TRIGGER_ID_NUM: number of trigger IDs
|
||||
*/
|
||||
enum iwl_fw_ini_trigger_id {
|
||||
IWL_FW_TRIGGER_ID_INVALID = 0,
|
||||
|
||||
/* Errors triggers */
|
||||
IWL_FW_TRIGGER_ID_FW_ASSERT = 1,
|
||||
IWL_FW_TRIGGER_ID_FW_HW_ERROR = 2,
|
||||
IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG = 3,
|
||||
|
||||
/* FW triggers */
|
||||
IWL_FW_TRIGGER_ID_FW_DEBUG_HOST_TRIGGER = 4,
|
||||
IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFICATION = 5,
|
||||
|
||||
/* User trigger */
|
||||
IWL_FW_TRIGGER_ID_USER_TRIGGER = 6,
|
||||
|
||||
/* periodic uses the data field for the interval time */
|
||||
IWL_FW_TRIGGER_ID_PERIODIC_TRIGGER = 7,
|
||||
|
||||
/* Host triggers */
|
||||
IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY = 8,
|
||||
IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED = 9,
|
||||
IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED = 10,
|
||||
IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER = 11,
|
||||
IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST = 12,
|
||||
IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST = 13,
|
||||
IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST = 14,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_START = 15,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_SUBMITTED = 16,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS = 17,
|
||||
IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG = 18,
|
||||
IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED = 19,
|
||||
IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED = 20,
|
||||
IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED = 21,
|
||||
IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED = 22,
|
||||
IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT = 23,
|
||||
IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE = 24,
|
||||
IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED = 25,
|
||||
IWL_FW_TRIGGER_ID_HOST_D3_START = 26,
|
||||
IWL_FW_TRIGGER_ID_HOST_D3_END = 27,
|
||||
IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS = 28,
|
||||
IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS = 29,
|
||||
IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES = 30,
|
||||
IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED = 31,
|
||||
IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED = 32,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE = 33,
|
||||
IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT = 34,
|
||||
IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE = 35,
|
||||
IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE = 36,
|
||||
|
||||
IWL_FW_TRIGGER_ID_NUM,
|
||||
}; /* FW_DEBUG_TLV_TRIGGER_ID_E_VER_1 */
|
||||
struct iwl_fw_ini_hcmd_tlv {
|
||||
struct iwl_fw_ini_header hdr;
|
||||
__le32 time_point;
|
||||
__le32 period_msec;
|
||||
struct iwl_fw_ini_hcmd hcmd;
|
||||
} __packed; /* FW_TLV_DEBUG_HCMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_allocation_id
|
||||
@ -404,9 +281,6 @@ enum iwl_fw_ini_trigger_id {
|
||||
* @IWL_FW_INI_ALLOCATION_ID_DBGC1: allocation meant for DBGC1 configuration
|
||||
* @IWL_FW_INI_ALLOCATION_ID_DBGC2: allocation meant for DBGC2 configuration
|
||||
* @IWL_FW_INI_ALLOCATION_ID_DBGC3: allocation meant for DBGC3 configuration
|
||||
* @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_USER_DEFINED: for future user scenarios
|
||||
* @IWL_FW_INI_ALLOCATION_NUM: number of allocation ids
|
||||
*/
|
||||
enum iwl_fw_ini_allocation_id {
|
||||
@ -414,9 +288,6 @@ enum iwl_fw_ini_allocation_id {
|
||||
IWL_FW_INI_ALLOCATION_ID_DBGC1,
|
||||
IWL_FW_INI_ALLOCATION_ID_DBGC2,
|
||||
IWL_FW_INI_ALLOCATION_ID_DBGC3,
|
||||
IWL_FW_INI_ALLOCATION_ID_SDFX,
|
||||
IWL_FW_INI_ALLOCATION_ID_FW_DUMP,
|
||||
IWL_FW_INI_ALLOCATION_ID_USER_DEFINED,
|
||||
IWL_FW_INI_ALLOCATION_NUM,
|
||||
}; /* FW_DEBUG_TLV_ALLOCATION_ID_E_VER_1 */
|
||||
|
||||
@ -435,59 +306,48 @@ enum iwl_fw_ini_buffer_location {
|
||||
IWL_FW_INI_LOCATION_NPK_PATH,
|
||||
}; /* FW_DEBUG_TLV_BUFFER_LOCATION_E_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_debug_flow
|
||||
*
|
||||
* @IWL_FW_INI_DEBUG_INVALID: invalid
|
||||
* @IWL_FW_INI_DEBUG_DBTR_FLOW: undefined
|
||||
* @IWL_FW_INI_DEBUG_TB2DTF_FLOW: undefined
|
||||
*/
|
||||
enum iwl_fw_ini_debug_flow {
|
||||
IWL_FW_INI_DEBUG_INVALID,
|
||||
IWL_FW_INI_DEBUG_DBTR_FLOW,
|
||||
IWL_FW_INI_DEBUG_TB2DTF_FLOW,
|
||||
}; /* FW_DEBUG_TLV_FLOW_E_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_region_type
|
||||
*
|
||||
* @IWL_FW_INI_REGION_INVALID: invalid
|
||||
* @IWL_FW_INI_REGION_TLV: uCode and debug TLVs
|
||||
* @IWL_FW_INI_REGION_INTERNAL_BUFFER: monitor SMEM buffer
|
||||
* @IWL_FW_INI_REGION_DRAM_BUFFER: monitor DRAM buffer
|
||||
* @IWL_FW_INI_REGION_TXF: TX fifos
|
||||
* @IWL_FW_INI_REGION_RXF: RX fifo
|
||||
* @IWL_FW_INI_REGION_LMAC_ERROR_TABLE: lmac error table
|
||||
* @IWL_FW_INI_REGION_UMAC_ERROR_TABLE: umac error table
|
||||
* @IWL_FW_INI_REGION_RSP_OR_NOTIF: FW response or notification data
|
||||
* @IWL_FW_INI_REGION_DEVICE_MEMORY: device internal memory
|
||||
* @IWL_FW_INI_REGION_PERIPHERY_MAC: periphery registers of MAC
|
||||
* @IWL_FW_INI_REGION_PERIPHERY_PHY: periphery registers of PHY
|
||||
* @IWL_FW_INI_REGION_PERIPHERY_AUX: periphery registers of AUX
|
||||
* @IWL_FW_INI_REGION_DRAM_BUFFER: DRAM buffer
|
||||
* @IWL_FW_INI_REGION_DRAM_IMR: IMR memory
|
||||
* @IWL_FW_INI_REGION_INTERNAL_BUFFER: undefined
|
||||
* @IWL_FW_INI_REGION_TXF: TX fifos
|
||||
* @IWL_FW_INI_REGION_RXF: RX fifo
|
||||
* @IWL_FW_INI_REGION_PAGING: paging memory
|
||||
* @IWL_FW_INI_REGION_CSR: CSR registers
|
||||
* @IWL_FW_INI_REGION_NOTIFICATION: FW notification data
|
||||
* @IWL_FW_INI_REGION_DHC: dhc response to dump
|
||||
* @IWL_FW_INI_REGION_LMAC_ERROR_TABLE: lmac error table
|
||||
* @IWL_FW_INI_REGION_UMAC_ERROR_TABLE: umac error table
|
||||
* @IWL_FW_INI_REGION_DRAM_IMR: IMR memory
|
||||
* @IWL_FW_INI_REGION_PCI_IOSF_CONFIG: PCI/IOSF config
|
||||
* @IWL_FW_INI_REGION_NUM: number of region types
|
||||
*/
|
||||
enum iwl_fw_ini_region_type {
|
||||
IWL_FW_INI_REGION_INVALID,
|
||||
IWL_FW_INI_REGION_TLV,
|
||||
IWL_FW_INI_REGION_INTERNAL_BUFFER,
|
||||
IWL_FW_INI_REGION_DRAM_BUFFER,
|
||||
IWL_FW_INI_REGION_TXF,
|
||||
IWL_FW_INI_REGION_RXF,
|
||||
IWL_FW_INI_REGION_LMAC_ERROR_TABLE,
|
||||
IWL_FW_INI_REGION_UMAC_ERROR_TABLE,
|
||||
IWL_FW_INI_REGION_RSP_OR_NOTIF,
|
||||
IWL_FW_INI_REGION_DEVICE_MEMORY,
|
||||
IWL_FW_INI_REGION_PERIPHERY_MAC,
|
||||
IWL_FW_INI_REGION_PERIPHERY_PHY,
|
||||
IWL_FW_INI_REGION_PERIPHERY_AUX,
|
||||
IWL_FW_INI_REGION_DRAM_BUFFER,
|
||||
IWL_FW_INI_REGION_DRAM_IMR,
|
||||
IWL_FW_INI_REGION_INTERNAL_BUFFER,
|
||||
IWL_FW_INI_REGION_TXF,
|
||||
IWL_FW_INI_REGION_RXF,
|
||||
IWL_FW_INI_REGION_PAGING,
|
||||
IWL_FW_INI_REGION_CSR,
|
||||
IWL_FW_INI_REGION_NOTIFICATION,
|
||||
IWL_FW_INI_REGION_DHC,
|
||||
IWL_FW_INI_REGION_LMAC_ERROR_TABLE,
|
||||
IWL_FW_INI_REGION_UMAC_ERROR_TABLE,
|
||||
IWL_FW_INI_REGION_DRAM_IMR,
|
||||
IWL_FW_INI_REGION_PCI_IOSF_CONFIG,
|
||||
IWL_FW_INI_REGION_NUM
|
||||
}; /* FW_DEBUG_TLV_REGION_TYPE_E_VER_1 */
|
||||
}; /* FW_TLV_DEBUG_REGION_TYPE_API_E */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_time_point
|
||||
@ -557,4 +417,22 @@ enum iwl_fw_ini_time_point {
|
||||
IWL_FW_INI_TIME_POINT_NUM,
|
||||
}; /* FW_TLV_DEBUG_TIME_POINT_API_E */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_trigger_apply_policy - Determines how to apply triggers
|
||||
*
|
||||
* @IWL_FW_INI_APPLY_POLICY_MATCH_TIME_POINT: match by time point
|
||||
* @IWL_FW_INI_APPLY_POLICY_MATCH_DATA: match by trigger data
|
||||
* @IWL_FW_INI_APPLY_POLICY_OVERRIDE_REGIONS: override regions mask.
|
||||
* Append otherwise
|
||||
* @IWL_FW_INI_APPLY_POLICY_OVERRIDE_CFG: override trigger configuration
|
||||
* @IWL_FW_INI_APPLY_POLICY_OVERRIDE_DATA: override trigger data.
|
||||
* Append otherwise
|
||||
*/
|
||||
enum iwl_fw_ini_trigger_apply_policy {
|
||||
IWL_FW_INI_APPLY_POLICY_MATCH_TIME_POINT = BIT(0),
|
||||
IWL_FW_INI_APPLY_POLICY_MATCH_DATA = BIT(1),
|
||||
IWL_FW_INI_APPLY_POLICY_OVERRIDE_REGIONS = BIT(8),
|
||||
IWL_FW_INI_APPLY_POLICY_OVERRIDE_CFG = BIT(9),
|
||||
IWL_FW_INI_APPLY_POLICY_OVERRIDE_DATA = BIT(10),
|
||||
};
|
||||
#endif
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications 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
|
||||
* 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) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -77,6 +77,20 @@ enum iwl_mac_conf_subcmd_ids {
|
||||
* @CHANNEL_SWITCH_TIME_EVENT_CMD: &struct iwl_chan_switch_te_cmd
|
||||
*/
|
||||
CHANNEL_SWITCH_TIME_EVENT_CMD = 0x4,
|
||||
/**
|
||||
* @MISSED_VAP_NOTIF: &struct iwl_missed_vap_notif
|
||||
*/
|
||||
MISSED_VAP_NOTIF = 0xFA,
|
||||
/**
|
||||
* @SESSION_PROTECTION_CMD: &struct iwl_mvm_session_prot_cmd
|
||||
*/
|
||||
SESSION_PROTECTION_CMD = 0x5,
|
||||
|
||||
/**
|
||||
* @SESSION_PROTECTION_NOTIF: &struct iwl_mvm_session_prot_notif
|
||||
*/
|
||||
SESSION_PROTECTION_NOTIF = 0xFB,
|
||||
|
||||
/**
|
||||
* @PROBE_RESPONSE_DATA_NOTIF: &struct iwl_probe_resp_data_notif
|
||||
*/
|
||||
@ -130,6 +144,21 @@ struct iwl_probe_resp_data_notif {
|
||||
u8 reserved[3];
|
||||
} __packed; /* PROBE_RESPONSE_DATA_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_missed_vap_notif - notification of missing vap detection
|
||||
*
|
||||
* @mac_id: the mac for which the ucode sends the notification for
|
||||
* @num_beacon_intervals_elapsed: beacons elpased with no vap profile inside
|
||||
* @profile_periodicity: beacons period to have our profile inside
|
||||
* @reserved: reserved for alignment purposes
|
||||
*/
|
||||
struct iwl_missed_vap_notif {
|
||||
__le32 mac_id;
|
||||
u8 num_beacon_intervals_elapsed;
|
||||
u8 profile_periodicity;
|
||||
u8 reserved[2];
|
||||
} __packed; /* MISSED_VAP_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_channel_switch_noa_notif - Channel switch NOA notification
|
||||
*
|
||||
|
@ -260,6 +260,11 @@ enum iwl_rx_mpdu_amsdu_info {
|
||||
IWL_RX_MPDU_AMSDU_LAST_SUBFRAME = 0x80,
|
||||
};
|
||||
|
||||
#define RX_MPDU_BAND_POS 6
|
||||
#define RX_MPDU_BAND_MASK 0xC0
|
||||
#define BAND_IN_RX_STATUS(_val) \
|
||||
(((_val) & RX_MPDU_BAND_MASK) >> RX_MPDU_BAND_POS)
|
||||
|
||||
enum iwl_rx_l3_proto_values {
|
||||
IWL_RX_L3_TYPE_NONE,
|
||||
IWL_RX_L3_TYPE_IPV4,
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications 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
|
||||
* 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) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -393,4 +393,80 @@ struct iwl_hs20_roc_res {
|
||||
__le32 status;
|
||||
} __packed; /* HOT_SPOT_RSP_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_mvm_session_prot_conf_id - session protection's configurations
|
||||
* @SESSION_PROTECT_CONF_ASSOC: Start a session protection for association.
|
||||
* The firmware will allocate two events.
|
||||
* Valid for BSS_STA and P2P_STA.
|
||||
* * A rather short event that can't be fragmented and with a very
|
||||
* high priority. If every goes well (99% of the cases) the
|
||||
* association should complete within this first event. During
|
||||
* that event, no other activity will happen in the firmware,
|
||||
* which is why it can't be too long.
|
||||
* The length of this event is hard-coded in the firmware: 300TUs.
|
||||
* * Another event which can be much longer (it's duration is
|
||||
* configurable by the driver) which has a slightly lower
|
||||
* priority and that can be fragmented allowing other activities
|
||||
* to run while this event is running.
|
||||
* The firmware will automatically remove both events once the driver sets
|
||||
* the BSS MAC as associated. Neither of the events will be removed
|
||||
* for the P2P_STA MAC.
|
||||
* Only the duration is configurable for this protection.
|
||||
* @SESSION_PROTECT_CONF_GO_CLIENT_ASSOC: not used
|
||||
* @SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV: Schedule the P2P Device to be in
|
||||
* listen mode. Will be fragmented. Valid only on the P2P Device MAC.
|
||||
* Valid only on the P2P Device MAC. The firmware will take into account
|
||||
* the duration, the interval and the repetition count.
|
||||
* @SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION: Schedule the P2P Device to be be
|
||||
* able to run the GO Negotiation. Will not be fragmented and not
|
||||
* repetitive. Valid only on the P2P Device MAC. Only the duration will
|
||||
* be taken into account.
|
||||
*/
|
||||
enum iwl_mvm_session_prot_conf_id {
|
||||
SESSION_PROTECT_CONF_ASSOC,
|
||||
SESSION_PROTECT_CONF_GO_CLIENT_ASSOC,
|
||||
SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV,
|
||||
SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION,
|
||||
}; /* SESSION_PROTECTION_CONF_ID_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_session_prot_cmd - configure a session protection
|
||||
* @id_and_color: the id and color of the mac for which this session protection
|
||||
* is sent
|
||||
* @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE
|
||||
* @conf_id: see &enum iwl_mvm_session_prot_conf_id
|
||||
* @duration_tu: the duration of the whole protection in TUs.
|
||||
* @repetition_count: not used
|
||||
* @interval: not used
|
||||
*
|
||||
* Note: the session protection will always be scheduled to start as
|
||||
* early as possible, but the maximum delay is configuration dependent.
|
||||
* The firmware supports only one concurrent session protection per vif.
|
||||
* Adding a new session protection will remove any currently running session.
|
||||
*/
|
||||
struct iwl_mvm_session_prot_cmd {
|
||||
/* COMMON_INDEX_HDR_API_S_VER_1 hdr */
|
||||
__le32 id_and_color;
|
||||
__le32 action;
|
||||
__le32 conf_id;
|
||||
__le32 duration_tu;
|
||||
__le32 repetition_count;
|
||||
__le32 interval;
|
||||
} __packed; /* SESSION_PROTECTION_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_session_prot_notif - session protection started / ended
|
||||
* @mac_id: the mac id for which the session protection started / ended
|
||||
* @status: 1 means success, 0 means failure
|
||||
* @start: 1 means the session protection started, 0 means it ended
|
||||
*
|
||||
* Note that any session protection will always get two notifications: start
|
||||
* and end even the firmware could not schedule it.
|
||||
*/
|
||||
struct iwl_mvm_session_prot_notif {
|
||||
__le32 mac_id;
|
||||
__le32 status;
|
||||
__le32 start;
|
||||
} __packed; /* SESSION_PROTECTION_NOTIFICATION_API_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_time_event_h__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -114,9 +114,8 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
|
||||
bool monitor_only, unsigned int delay);
|
||||
int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_dbg_trigger trig_type);
|
||||
int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_ini_trigger_id id);
|
||||
int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, u32 legacy_trigger_id);
|
||||
int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fwrt_dump_data *dump_data);
|
||||
int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_dbg_trigger trig, const char *str,
|
||||
size_t len, struct iwl_fw_dbg_trigger_tlv *trigger);
|
||||
@ -222,29 +221,6 @@ _iwl_fw_dbg_trigger_on(struct iwl_fw_runtime *fwrt,
|
||||
_iwl_fw_dbg_trigger_on((fwrt), (wdev), (id)); \
|
||||
})
|
||||
|
||||
static inline bool
|
||||
iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_ini_trigger_id id)
|
||||
{
|
||||
struct iwl_fw_ini_trigger *trig;
|
||||
u32 usec;
|
||||
|
||||
if (!iwl_trans_dbg_ini_valid(fwrt->trans) ||
|
||||
id == IWL_FW_TRIGGER_ID_INVALID || id >= IWL_FW_TRIGGER_ID_NUM ||
|
||||
!fwrt->dump.active_trigs[id].active)
|
||||
return false;
|
||||
|
||||
trig = fwrt->dump.active_trigs[id].trig;
|
||||
usec = le32_to_cpu(trig->ignore_consec);
|
||||
|
||||
if (iwl_fw_dbg_no_trig_window(fwrt, id, usec)) {
|
||||
IWL_WARN(fwrt, "Trigger %d fired in no-collect window\n", id);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt,
|
||||
struct wireless_dev *wdev,
|
||||
@ -315,10 +291,8 @@ static inline void iwl_fw_flush_dumps(struct iwl_fw_runtime *fwrt)
|
||||
int i;
|
||||
|
||||
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);
|
||||
fwrt->dump.wks[i].ini_trig_id = IWL_FW_TRIGGER_ID_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
@ -381,12 +355,21 @@ 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)
|
||||
{
|
||||
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);
|
||||
enum iwl_fw_ini_time_point tp_id;
|
||||
|
||||
if (!iwl_trans_dbg_ini_valid(fwrt->trans)) {
|
||||
iwl_fw_dbg_collect_desc(fwrt, &iwl_dump_desc_assert, false, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fwrt->trans->dbg.hw_error) {
|
||||
tp_id = IWL_FW_INI_TIME_POINT_FW_HW_ERROR;
|
||||
fwrt->trans->dbg.hw_error = false;
|
||||
} else {
|
||||
iwl_fw_dbg_collect_desc(fwrt, &iwl_dump_desc_assert, false, 0);
|
||||
tp_id = IWL_FW_INI_TIME_POINT_FW_ASSERT;
|
||||
}
|
||||
|
||||
iwl_dbg_tlv_time_point(fwrt, tp_id, NULL);
|
||||
}
|
||||
|
||||
void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt);
|
||||
|
@ -320,10 +320,45 @@ out:
|
||||
|
||||
FWRT_DEBUGFS_WRITE_FILE_OPS(send_hcmd, 512);
|
||||
|
||||
static ssize_t iwl_dbgfs_fw_dbg_domain_write(struct iwl_fw_runtime *fwrt,
|
||||
char *buf, size_t count)
|
||||
{
|
||||
u32 new_domain;
|
||||
int ret;
|
||||
|
||||
if (!iwl_trans_fw_running(fwrt->trans))
|
||||
return -EIO;
|
||||
|
||||
ret = kstrtou32(buf, 0, &new_domain);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (new_domain != fwrt->trans->dbg.domains_bitmap) {
|
||||
ret = iwl_dbg_tlv_gen_active_trigs(fwrt, new_domain);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_PERIODIC,
|
||||
NULL);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_fw_dbg_domain_read(struct iwl_fw_runtime *fwrt,
|
||||
size_t size, char *buf)
|
||||
{
|
||||
return scnprintf(buf, size, "0x%08x\n",
|
||||
fwrt->trans->dbg.domains_bitmap);
|
||||
}
|
||||
|
||||
FWRT_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_domain, 20);
|
||||
|
||||
void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
|
||||
struct dentry *dbgfs_dir)
|
||||
{
|
||||
INIT_DELAYED_WORK(&fwrt->timestamp.wk, iwl_fw_timestamp_marker_wk);
|
||||
FWRT_DEBUGFS_ADD_FILE(timestamp_marker, dbgfs_dir, 0200);
|
||||
FWRT_DEBUGFS_ADD_FILE(send_hcmd, dbgfs_dir, 0200);
|
||||
FWRT_DEBUGFS_ADD_FILE(fw_dbg_domain, dbgfs_dir, 0600);
|
||||
}
|
||||
|
@ -65,6 +65,7 @@
|
||||
#define __fw_error_dump_h__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include "fw/api/cmdhdr.h"
|
||||
|
||||
#define IWL_FW_ERROR_DUMP_BARKER 0x14789632
|
||||
#define IWL_FW_INI_ERROR_DUMP_BARKER 0x14789633
|
||||
@ -327,6 +328,7 @@ struct iwl_fw_ini_fifo_hdr {
|
||||
* @dram_base_addr: base address of dram monitor range
|
||||
* @page_num: page number of memory range
|
||||
* @fifo_hdr: fifo header of memory range
|
||||
* @fw_pkt: FW packet header of memory range
|
||||
* @data: the actual memory
|
||||
*/
|
||||
struct iwl_fw_ini_error_dump_range {
|
||||
@ -336,6 +338,7 @@ struct iwl_fw_ini_error_dump_range {
|
||||
__le64 dram_base_addr;
|
||||
__le32 page_num;
|
||||
struct iwl_fw_ini_fifo_hdr fifo_hdr;
|
||||
struct iwl_cmd_header fw_pkt_hdr;
|
||||
};
|
||||
__le32 data[];
|
||||
} __packed;
|
||||
@ -379,12 +382,23 @@ struct iwl_fw_ini_error_dump_register {
|
||||
__le32 data;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_dump_cfg_name - configuration name
|
||||
* @image_type: image type the configuration is related to
|
||||
* @cfg_name_len: length of the configuration name
|
||||
* @cfg_name: name of the configuraiton
|
||||
*/
|
||||
struct iwl_fw_ini_dump_cfg_name {
|
||||
__le32 image_type;
|
||||
__le32 cfg_name_len;
|
||||
u8 cfg_name[IWL_FW_INI_MAX_CFG_NAME];
|
||||
} __packed;
|
||||
|
||||
/* struct iwl_fw_ini_dump_info - ini dump information
|
||||
* @version: dump version
|
||||
* @trigger_id: trigger id that caused the dump collection
|
||||
* @trigger_reason: not supported yet
|
||||
* @is_external_cfg: 1 if an external debug configuration was loaded
|
||||
* and 0 otherwise
|
||||
* @time_point: time point that caused the dump collection
|
||||
* @trigger_reason: reason of the trigger
|
||||
* @external_cfg_state: &enum iwl_ini_cfg_state
|
||||
* @ver_type: FW version type
|
||||
* @ver_subtype: FW version subype
|
||||
* @hw_step: HW step
|
||||
@ -397,22 +411,18 @@ struct iwl_fw_ini_error_dump_register {
|
||||
* @lmac_minor: lmac minor version
|
||||
* @umac_major: umac major version
|
||||
* @umac_minor: umac minor version
|
||||
* @fw_mon_mode: FW monitor mode &enum iwl_fw_ini_buffer_location
|
||||
* @regions_mask: bitmap mask of regions ids in the dump
|
||||
* @build_tag_len: length of the build tag
|
||||
* @build_tag: build tag string
|
||||
* @img_name_len: length of the FW image name
|
||||
* @img_name: FW image name
|
||||
* @internal_dbg_cfg_name_len: length of the internal debug configuration name
|
||||
* @internal_dbg_cfg_name: internal debug configuration name
|
||||
* @external_dbg_cfg_name_len: length of the external debug configuration name
|
||||
* @external_dbg_cfg_name: external debug configuration name
|
||||
* @regions_num: number of region ids
|
||||
* @region_ids: region ids the trigger configured to collect
|
||||
* @num_of_cfg_names: number of configuration name structs
|
||||
* @cfg_names: configuration names
|
||||
*/
|
||||
struct iwl_fw_ini_dump_info {
|
||||
__le32 version;
|
||||
__le32 trigger_id;
|
||||
__le32 time_point;
|
||||
__le32 trigger_reason;
|
||||
__le32 is_external_cfg;
|
||||
__le32 external_cfg_state;
|
||||
__le32 ver_type;
|
||||
__le32 ver_subtype;
|
||||
__le32 hw_step;
|
||||
@ -425,17 +435,24 @@ struct iwl_fw_ini_dump_info {
|
||||
__le32 lmac_minor;
|
||||
__le32 umac_major;
|
||||
__le32 umac_minor;
|
||||
__le32 fw_mon_mode;
|
||||
__le64 regions_mask;
|
||||
__le32 build_tag_len;
|
||||
u8 build_tag[FW_VER_HUMAN_READABLE_SZ];
|
||||
__le32 img_name_len;
|
||||
u8 img_name[IWL_FW_INI_MAX_IMG_NAME_LEN];
|
||||
__le32 internal_dbg_cfg_name_len;
|
||||
u8 internal_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
|
||||
__le32 external_dbg_cfg_name_len;
|
||||
u8 external_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
|
||||
__le32 regions_num;
|
||||
__le32 region_ids[];
|
||||
__le32 num_of_cfg_names;
|
||||
struct iwl_fw_ini_dump_cfg_name cfg_names[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_err_table_dump - ini error table dump
|
||||
* @header: header of the region
|
||||
* @version: error table version
|
||||
* @ranges: the memory ranges of this this region
|
||||
*/
|
||||
struct iwl_fw_ini_err_table_dump {
|
||||
struct iwl_fw_ini_error_dump_header header;
|
||||
__le32 version;
|
||||
struct iwl_fw_ini_error_dump_range ranges[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
@ -457,12 +474,14 @@ struct iwl_fw_error_dump_rb {
|
||||
* @header: header of the region
|
||||
* @write_ptr: write pointer position in the buffer
|
||||
* @cycle_cnt: cycles count
|
||||
* @cur_frag: current fragment in use
|
||||
* @ranges: the memory ranges of this this region
|
||||
*/
|
||||
struct iwl_fw_ini_monitor_dump {
|
||||
struct iwl_fw_ini_error_dump_header header;
|
||||
__le32 write_ptr;
|
||||
__le32 cycle_cnt;
|
||||
__le32 cur_frag;
|
||||
struct iwl_fw_ini_error_dump_range ranges[];
|
||||
} __packed;
|
||||
|
||||
|
@ -93,7 +93,7 @@ struct iwl_ucode_header {
|
||||
} u;
|
||||
};
|
||||
|
||||
#define IWL_UCODE_INI_TLV_GROUP 0x1000000
|
||||
#define IWL_UCODE_TLV_DEBUG_BASE 0x1000005
|
||||
|
||||
/*
|
||||
* new TLV uCode file layout
|
||||
@ -151,7 +151,6 @@ enum iwl_ucode_tlv_type {
|
||||
IWL_UCODE_TLV_FW_RECOVERY_INFO = 57,
|
||||
IWL_UCODE_TLV_FW_FSEQ_VERSION = 60,
|
||||
|
||||
IWL_UCODE_TLV_DEBUG_BASE = IWL_UCODE_INI_TLV_GROUP,
|
||||
IWL_UCODE_TLV_TYPE_DEBUG_INFO = IWL_UCODE_TLV_DEBUG_BASE + 0,
|
||||
IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_TLV_DEBUG_BASE + 1,
|
||||
IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_TLV_DEBUG_BASE + 2,
|
||||
@ -326,6 +325,8 @@ enum iwl_ucode_tlv_api {
|
||||
IWL_UCODE_TLV_API_REDUCED_SCAN_CONFIG = (__force iwl_ucode_tlv_api_t)56,
|
||||
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,
|
||||
IWL_UCODE_TLV_API_BAND_IN_RX_DATA = (__force iwl_ucode_tlv_api_t)59,
|
||||
|
||||
|
||||
NUM_IWL_UCODE_TLV_API
|
||||
#ifdef __CHECKER__
|
||||
@ -449,6 +450,7 @@ enum iwl_ucode_tlv_capa {
|
||||
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,
|
||||
IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD = (__force iwl_ucode_tlv_capa_t)54,
|
||||
|
||||
/* set 2 */
|
||||
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
|
||||
|
@ -227,18 +227,6 @@ struct iwl_fw_dbg {
|
||||
u32 dump_mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_active_triggers
|
||||
* @active: is this trigger active
|
||||
* @size: allocated memory size of the trigger
|
||||
* @trig: trigger
|
||||
*/
|
||||
struct iwl_fw_ini_active_triggers {
|
||||
bool active;
|
||||
size_t size;
|
||||
struct iwl_fw_ini_trigger *trig;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw - variables associated with the firmware
|
||||
*
|
||||
|
@ -67,6 +67,8 @@
|
||||
#include "fw/api/paging.h"
|
||||
#include "iwl-eeprom-parse.h"
|
||||
|
||||
#define IWL_FW_DBG_DOMAIN IWL_FW_INI_DOMAIN_ALWAYS_ON
|
||||
|
||||
struct iwl_fw_runtime_ops {
|
||||
int (*dump_start)(void *ctx);
|
||||
void (*dump_end)(void *ctx);
|
||||
@ -90,6 +92,27 @@ struct iwl_fwrt_shared_mem_cfg {
|
||||
|
||||
#define IWL_FW_RUNTIME_DUMP_WK_NUM 5
|
||||
|
||||
/**
|
||||
* struct iwl_fwrt_dump_data - dump data
|
||||
* @trig: trigger the worker was scheduled upon
|
||||
* @fw_pkt: packet received from FW
|
||||
*/
|
||||
struct iwl_fwrt_dump_data {
|
||||
struct iwl_fw_ini_trigger_tlv *trig;
|
||||
struct iwl_rx_packet *fw_pkt;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fwrt_wk_data - dump worker data struct
|
||||
* @idx: index of the worker
|
||||
* @wk: worker
|
||||
*/
|
||||
struct iwl_fwrt_wk_data {
|
||||
u8 idx;
|
||||
struct delayed_work wk;
|
||||
struct iwl_fwrt_dump_data dump_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_txf_iter_data - Tx fifo iterator data struct
|
||||
* @fifo: fifo number
|
||||
@ -104,6 +127,14 @@ struct iwl_txf_iter_data {
|
||||
u8 internal_txf;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_fw_runtime_status - fw runtime status flags
|
||||
* @STATUS_GEN_ACTIVE_TRIGS: generating active trigger list
|
||||
*/
|
||||
enum iwl_fw_runtime_status {
|
||||
STATUS_GEN_ACTIVE_TRIGS,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw_runtime - runtime data for firmware
|
||||
* @fw: firmware image
|
||||
@ -117,6 +148,7 @@ struct iwl_txf_iter_data {
|
||||
* @smem_cfg: saved firmware SMEM configuration
|
||||
* @cur_fw_img: current firmware image, must be maintained by
|
||||
* the driver by calling &iwl_fw_set_current_image()
|
||||
* @status: &enum iwl_fw_runtime_status
|
||||
* @dump: debug dump data
|
||||
*/
|
||||
struct iwl_fw_runtime {
|
||||
@ -137,33 +169,25 @@ struct iwl_fw_runtime {
|
||||
/* memory configuration */
|
||||
struct iwl_fwrt_shared_mem_cfg smem_cfg;
|
||||
|
||||
unsigned long status;
|
||||
|
||||
/* debug */
|
||||
struct {
|
||||
const struct iwl_fw_dump_desc *desc;
|
||||
bool monitor_only;
|
||||
struct {
|
||||
u8 idx;
|
||||
enum iwl_fw_ini_trigger_id ini_trig_id;
|
||||
struct delayed_work wk;
|
||||
} wks[IWL_FW_RUNTIME_DUMP_WK_NUM];
|
||||
struct iwl_fwrt_wk_data wks[IWL_FW_RUNTIME_DUMP_WK_NUM];
|
||||
unsigned long active_wks;
|
||||
|
||||
u8 conf;
|
||||
|
||||
/* ts of the beginning of a non-collect fw dbg data period */
|
||||
unsigned long non_collect_ts_start[IWL_FW_TRIGGER_ID_NUM];
|
||||
unsigned long non_collect_ts_start[IWL_FW_INI_TIME_POINT_NUM];
|
||||
u32 *d3_debug_data;
|
||||
struct iwl_fw_ini_region_cfg *active_regs[IWL_FW_INI_MAX_REGION_ID];
|
||||
struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM];
|
||||
u32 lmac_err_id[MAX_NUM_LMAC];
|
||||
u32 umac_err_id;
|
||||
|
||||
struct iwl_txf_iter_data txf_iter_data;
|
||||
|
||||
u8 img_name[IWL_FW_INI_MAX_IMG_NAME_LEN];
|
||||
u8 internal_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
|
||||
u8 external_dbg_cfg_name[IWL_FW_INI_MAX_DBG_CFG_NAME_LEN];
|
||||
|
||||
struct {
|
||||
u8 type;
|
||||
u8 subtype;
|
||||
@ -194,16 +218,6 @@ static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt)
|
||||
kfree(fwrt->dump.d3_debug_data);
|
||||
fwrt->dump.d3_debug_data = NULL;
|
||||
|
||||
for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++) {
|
||||
struct iwl_fw_ini_active_triggers *active =
|
||||
&fwrt->dump.active_trigs[i];
|
||||
|
||||
active->active = false;
|
||||
active->size = 0;
|
||||
kfree(active->trig);
|
||||
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);
|
||||
|
@ -359,6 +359,28 @@ struct iwl_cfg_trans_params {
|
||||
bisr_workaround:1;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw_mon_reg - FW monitor register info
|
||||
* @addr: register address
|
||||
* @mask: register mask
|
||||
*/
|
||||
struct iwl_fw_mon_reg {
|
||||
u32 addr;
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw_mon_regs - FW monitor registers
|
||||
* @write_ptr: write pointer register
|
||||
* @cycle_cnt: cycle count register
|
||||
* @cur_frag: current fragment in use
|
||||
*/
|
||||
struct iwl_fw_mon_regs {
|
||||
struct iwl_fw_mon_reg write_ptr;
|
||||
struct iwl_fw_mon_reg cycle_cnt;
|
||||
struct iwl_fw_mon_reg cur_frag;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_cfg
|
||||
* @trans: the trans-specific configuration part
|
||||
@ -471,12 +493,10 @@ struct iwl_cfg {
|
||||
u32 d3_debug_data_base_addr;
|
||||
u32 d3_debug_data_length;
|
||||
u32 min_txq_size;
|
||||
u32 fw_mon_smem_write_ptr_addr;
|
||||
u32 fw_mon_smem_write_ptr_msk;
|
||||
u32 fw_mon_smem_cycle_cnt_ptr_addr;
|
||||
u32 fw_mon_smem_cycle_cnt_ptr_msk;
|
||||
u32 gp2_reg_addr;
|
||||
u32 min_256_ba_txq_size;
|
||||
const struct iwl_fw_mon_regs mon_dram_regs;
|
||||
const struct iwl_fw_mon_regs mon_smem_regs;
|
||||
};
|
||||
|
||||
extern const struct iwl_csr_params iwl_csr_v1;
|
||||
|
@ -95,6 +95,20 @@ struct iwl_dbg_tlv_ver_data {
|
||||
int max_ver;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_dbg_tlv_timer_node - timer node struct
|
||||
* @list: list of &struct iwl_dbg_tlv_timer_node
|
||||
* @timer: timer
|
||||
* @fwrt: &struct iwl_fw_runtime
|
||||
* @tlv: TLV attach to the timer node
|
||||
*/
|
||||
struct iwl_dbg_tlv_timer_node {
|
||||
struct list_head list;
|
||||
struct timer_list timer;
|
||||
struct iwl_fw_runtime *fwrt;
|
||||
struct iwl_ucode_tlv *tlv;
|
||||
};
|
||||
|
||||
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,},
|
||||
@ -104,12 +118,27 @@ dbg_ver_table[IWL_DBG_TLV_TYPE_NUM] = {
|
||||
[IWL_DBG_TLV_TYPE_TRIGGER] = {.min_ver = 1, .max_ver = 1,},
|
||||
};
|
||||
|
||||
static int iwl_dbg_tlv_add(struct iwl_ucode_tlv *tlv, struct list_head *list)
|
||||
{
|
||||
u32 len = le32_to_cpu(tlv->length);
|
||||
struct iwl_dbg_tlv_node *node;
|
||||
|
||||
node = kzalloc(sizeof(*node) + len, GFP_KERNEL);
|
||||
if (!node)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(&node->tlv, tlv, sizeof(node->tlv) + len);
|
||||
list_add_tail(&node->list, list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
u32 ver = le32_to_cpu(hdr->version);
|
||||
|
||||
if (ver < dbg_ver_table[tlv_idx].min_ver ||
|
||||
ver > dbg_ver_table[tlv_idx].max_ver)
|
||||
@ -118,27 +147,169 @@ static bool iwl_dbg_tlv_ver_support(struct iwl_ucode_tlv *tlv)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_alloc_debug_info(struct iwl_trans *trans,
|
||||
struct iwl_ucode_tlv *tlv)
|
||||
{
|
||||
struct iwl_fw_ini_debug_info_tlv *debug_info = (void *)tlv->data;
|
||||
|
||||
if (le32_to_cpu(tlv->length) != sizeof(*debug_info))
|
||||
return -EINVAL;
|
||||
|
||||
IWL_DEBUG_FW(trans, "WRT: Loading debug cfg: %s\n",
|
||||
debug_info->debug_cfg_name);
|
||||
|
||||
return iwl_dbg_tlv_add(tlv, &trans->dbg.debug_info_tlv_list);
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_alloc_buf_alloc(struct iwl_trans *trans,
|
||||
struct iwl_ucode_tlv *tlv)
|
||||
{
|
||||
struct iwl_fw_ini_allocation_tlv *alloc = (void *)tlv->data;
|
||||
u32 buf_location = le32_to_cpu(alloc->buf_location);
|
||||
u32 alloc_id = le32_to_cpu(alloc->alloc_id);
|
||||
|
||||
if (le32_to_cpu(tlv->length) != sizeof(*alloc) ||
|
||||
(buf_location != IWL_FW_INI_LOCATION_SRAM_PATH &&
|
||||
buf_location != IWL_FW_INI_LOCATION_DRAM_PATH))
|
||||
return -EINVAL;
|
||||
|
||||
if ((buf_location == IWL_FW_INI_LOCATION_SRAM_PATH &&
|
||||
alloc_id != IWL_FW_INI_ALLOCATION_ID_DBGC1) ||
|
||||
(buf_location == IWL_FW_INI_LOCATION_DRAM_PATH &&
|
||||
(alloc_id == IWL_FW_INI_ALLOCATION_INVALID ||
|
||||
alloc_id >= IWL_FW_INI_ALLOCATION_NUM))) {
|
||||
IWL_ERR(trans,
|
||||
"WRT: Invalid allocation id %u for allocation TLV\n",
|
||||
alloc_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
trans->dbg.fw_mon_cfg[alloc_id] = *alloc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_alloc_hcmd(struct iwl_trans *trans,
|
||||
struct iwl_ucode_tlv *tlv)
|
||||
{
|
||||
struct iwl_fw_ini_hcmd_tlv *hcmd = (void *)tlv->data;
|
||||
u32 tp = le32_to_cpu(hcmd->time_point);
|
||||
|
||||
if (le32_to_cpu(tlv->length) <= sizeof(*hcmd))
|
||||
return -EINVAL;
|
||||
|
||||
/* Host commands can not be sent in early time point since the FW
|
||||
* is not ready
|
||||
*/
|
||||
if (tp == IWL_FW_INI_TIME_POINT_INVALID ||
|
||||
tp >= IWL_FW_INI_TIME_POINT_NUM ||
|
||||
tp == IWL_FW_INI_TIME_POINT_EARLY) {
|
||||
IWL_ERR(trans,
|
||||
"WRT: Invalid time point %u for host command TLV\n",
|
||||
tp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].hcmd_list);
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_alloc_region(struct iwl_trans *trans,
|
||||
struct iwl_ucode_tlv *tlv)
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)tlv->data;
|
||||
struct iwl_ucode_tlv **active_reg;
|
||||
u32 id = le32_to_cpu(reg->id);
|
||||
u32 type = le32_to_cpu(reg->type);
|
||||
u32 tlv_len = sizeof(*tlv) + le32_to_cpu(tlv->length);
|
||||
|
||||
if (le32_to_cpu(tlv->length) < sizeof(*reg))
|
||||
return -EINVAL;
|
||||
|
||||
if (id >= IWL_FW_INI_MAX_REGION_ID) {
|
||||
IWL_ERR(trans, "WRT: Invalid region id %u\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (type <= IWL_FW_INI_REGION_INVALID ||
|
||||
type >= IWL_FW_INI_REGION_NUM) {
|
||||
IWL_ERR(trans, "WRT: Invalid region type %u\n", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
active_reg = &trans->dbg.active_regions[id];
|
||||
if (*active_reg) {
|
||||
IWL_WARN(trans, "WRT: Overriding region id %u\n", id);
|
||||
|
||||
kfree(*active_reg);
|
||||
}
|
||||
|
||||
*active_reg = kmemdup(tlv, tlv_len, GFP_KERNEL);
|
||||
if (!*active_reg)
|
||||
return -ENOMEM;
|
||||
|
||||
IWL_DEBUG_FW(trans, "WRT: Enabling region id %u type %u\n", id, type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_alloc_trigger(struct iwl_trans *trans,
|
||||
struct iwl_ucode_tlv *tlv)
|
||||
{
|
||||
struct iwl_fw_ini_trigger_tlv *trig = (void *)tlv->data;
|
||||
u32 tp = le32_to_cpu(trig->time_point);
|
||||
|
||||
if (le32_to_cpu(tlv->length) < sizeof(*trig))
|
||||
return -EINVAL;
|
||||
|
||||
if (tp <= IWL_FW_INI_TIME_POINT_INVALID ||
|
||||
tp >= IWL_FW_INI_TIME_POINT_NUM) {
|
||||
IWL_ERR(trans,
|
||||
"WRT: Invalid time point %u for trigger TLV\n",
|
||||
tp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!le32_to_cpu(trig->occurrences))
|
||||
trig->occurrences = cpu_to_le32(-1);
|
||||
|
||||
return iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].trig_list);
|
||||
}
|
||||
|
||||
static int (*dbg_tlv_alloc[])(struct iwl_trans *trans,
|
||||
struct iwl_ucode_tlv *tlv) = {
|
||||
[IWL_DBG_TLV_TYPE_DEBUG_INFO] = iwl_dbg_tlv_alloc_debug_info,
|
||||
[IWL_DBG_TLV_TYPE_BUF_ALLOC] = iwl_dbg_tlv_alloc_buf_alloc,
|
||||
[IWL_DBG_TLV_TYPE_HCMD] = iwl_dbg_tlv_alloc_hcmd,
|
||||
[IWL_DBG_TLV_TYPE_REGION] = iwl_dbg_tlv_alloc_region,
|
||||
[IWL_DBG_TLV_TYPE_TRIGGER] = iwl_dbg_tlv_alloc_trigger,
|
||||
};
|
||||
|
||||
void iwl_dbg_tlv_alloc(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
|
||||
bool ext)
|
||||
{
|
||||
struct iwl_fw_ini_header *hdr = (void *)&tlv->data[0];
|
||||
u32 type = le32_to_cpu(tlv->type);
|
||||
u32 pnt = le32_to_cpu(hdr->apply_point);
|
||||
u32 tlv_idx = type - IWL_UCODE_TLV_DEBUG_BASE;
|
||||
enum iwl_ini_cfg_state *cfg_state = ext ?
|
||||
&trans->dbg.external_ini_cfg : &trans->dbg.internal_ini_cfg;
|
||||
int ret;
|
||||
|
||||
IWL_DEBUG_FW(trans, "WRT: read TLV 0x%x, apply point %d\n",
|
||||
type, pnt);
|
||||
|
||||
if (tlv_idx >= IWL_DBG_TLV_TYPE_NUM) {
|
||||
IWL_ERR(trans, "WRT: Unsupported TLV 0x%x\n", type);
|
||||
if (tlv_idx >= ARRAY_SIZE(dbg_tlv_alloc) || !dbg_tlv_alloc[tlv_idx]) {
|
||||
IWL_ERR(trans, "WRT: Unsupported TLV type 0x%x\n", type);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
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));
|
||||
le32_to_cpu(hdr->version));
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
ret = dbg_tlv_alloc[tlv_idx](trans, tlv);
|
||||
if (ret) {
|
||||
IWL_ERR(trans,
|
||||
"WRT: Failed to allocate TLV 0x%x, ret %d, (ext=%d)\n",
|
||||
type, ret, ext);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
@ -153,13 +324,91 @@ out_err:
|
||||
|
||||
void iwl_dbg_tlv_del_timers(struct iwl_trans *trans)
|
||||
{
|
||||
/* will be used later */
|
||||
struct list_head *timer_list = &trans->dbg.periodic_trig_list;
|
||||
struct iwl_dbg_tlv_timer_node *node, *tmp;
|
||||
|
||||
list_for_each_entry_safe(node, tmp, timer_list, list) {
|
||||
del_timer(&node->timer);
|
||||
list_del(&node->list);
|
||||
kfree(node);
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_dbg_tlv_del_timers);
|
||||
|
||||
static void iwl_dbg_tlv_fragments_free(struct iwl_trans *trans,
|
||||
enum iwl_fw_ini_allocation_id alloc_id)
|
||||
{
|
||||
struct iwl_fw_mon *fw_mon;
|
||||
int i;
|
||||
|
||||
if (alloc_id <= IWL_FW_INI_ALLOCATION_INVALID ||
|
||||
alloc_id >= IWL_FW_INI_ALLOCATION_NUM)
|
||||
return;
|
||||
|
||||
fw_mon = &trans->dbg.fw_mon_ini[alloc_id];
|
||||
|
||||
for (i = 0; i < fw_mon->num_frags; i++) {
|
||||
struct iwl_dram_data *frag = &fw_mon->frags[i];
|
||||
|
||||
dma_free_coherent(trans->dev, frag->size, frag->block,
|
||||
frag->physical);
|
||||
|
||||
frag->physical = 0;
|
||||
frag->block = NULL;
|
||||
frag->size = 0;
|
||||
}
|
||||
|
||||
kfree(fw_mon->frags);
|
||||
fw_mon->frags = NULL;
|
||||
fw_mon->num_frags = 0;
|
||||
}
|
||||
|
||||
void iwl_dbg_tlv_free(struct iwl_trans *trans)
|
||||
{
|
||||
/* will be used again later */
|
||||
struct iwl_dbg_tlv_node *tlv_node, *tlv_node_tmp;
|
||||
int i;
|
||||
|
||||
iwl_dbg_tlv_del_timers(trans);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(trans->dbg.active_regions); i++) {
|
||||
struct iwl_ucode_tlv **active_reg =
|
||||
&trans->dbg.active_regions[i];
|
||||
|
||||
kfree(*active_reg);
|
||||
*active_reg = NULL;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(tlv_node, tlv_node_tmp,
|
||||
&trans->dbg.debug_info_tlv_list, list) {
|
||||
list_del(&tlv_node->list);
|
||||
kfree(tlv_node);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(trans->dbg.time_point); i++) {
|
||||
struct iwl_dbg_tlv_time_point_data *tp =
|
||||
&trans->dbg.time_point[i];
|
||||
|
||||
list_for_each_entry_safe(tlv_node, tlv_node_tmp, &tp->trig_list,
|
||||
list) {
|
||||
list_del(&tlv_node->list);
|
||||
kfree(tlv_node);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(tlv_node, tlv_node_tmp, &tp->hcmd_list,
|
||||
list) {
|
||||
list_del(&tlv_node->list);
|
||||
kfree(tlv_node);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(tlv_node, tlv_node_tmp,
|
||||
&tp->active_trig_list, list) {
|
||||
list_del(&tlv_node->list);
|
||||
kfree(tlv_node);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(trans->dbg.fw_mon_ini); i++)
|
||||
iwl_dbg_tlv_fragments_free(trans, i);
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_parse_bin(struct iwl_trans *trans, const u8 *data,
|
||||
@ -196,7 +445,7 @@ void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans)
|
||||
if (!iwlwifi_mod_params.enable_ini)
|
||||
return;
|
||||
|
||||
res = request_firmware(&fw, "iwl-dbg-tlv.ini", dev);
|
||||
res = request_firmware(&fw, "iwl-debug-yoyo.bin", dev);
|
||||
if (res)
|
||||
return;
|
||||
|
||||
@ -205,10 +454,628 @@ void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans)
|
||||
release_firmware(fw);
|
||||
}
|
||||
|
||||
void iwl_dbg_tlv_init(struct iwl_trans *trans)
|
||||
{
|
||||
int i;
|
||||
|
||||
INIT_LIST_HEAD(&trans->dbg.debug_info_tlv_list);
|
||||
INIT_LIST_HEAD(&trans->dbg.periodic_trig_list);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(trans->dbg.time_point); i++) {
|
||||
struct iwl_dbg_tlv_time_point_data *tp =
|
||||
&trans->dbg.time_point[i];
|
||||
|
||||
INIT_LIST_HEAD(&tp->trig_list);
|
||||
INIT_LIST_HEAD(&tp->hcmd_list);
|
||||
INIT_LIST_HEAD(&tp->active_trig_list);
|
||||
}
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_alloc_fragment(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dram_data *frag, u32 pages)
|
||||
{
|
||||
void *block = NULL;
|
||||
dma_addr_t physical;
|
||||
|
||||
if (!frag || frag->size || !pages)
|
||||
return -EIO;
|
||||
|
||||
while (pages) {
|
||||
block = dma_alloc_coherent(fwrt->dev, pages * PAGE_SIZE,
|
||||
&physical,
|
||||
GFP_KERNEL | __GFP_NOWARN);
|
||||
if (block)
|
||||
break;
|
||||
|
||||
IWL_WARN(fwrt, "WRT: Failed to allocate fragment size %lu\n",
|
||||
pages * PAGE_SIZE);
|
||||
|
||||
pages = DIV_ROUND_UP(pages, 2);
|
||||
}
|
||||
|
||||
if (!block)
|
||||
return -ENOMEM;
|
||||
|
||||
frag->physical = physical;
|
||||
frag->block = block;
|
||||
frag->size = pages * PAGE_SIZE;
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_alloc_fragments(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_ini_allocation_id alloc_id)
|
||||
{
|
||||
struct iwl_fw_mon *fw_mon;
|
||||
struct iwl_fw_ini_allocation_tlv *fw_mon_cfg;
|
||||
u32 num_frags, remain_pages, frag_pages;
|
||||
int i;
|
||||
|
||||
if (alloc_id < IWL_FW_INI_ALLOCATION_INVALID ||
|
||||
alloc_id >= IWL_FW_INI_ALLOCATION_NUM)
|
||||
return -EIO;
|
||||
|
||||
fw_mon_cfg = &fwrt->trans->dbg.fw_mon_cfg[alloc_id];
|
||||
fw_mon = &fwrt->trans->dbg.fw_mon_ini[alloc_id];
|
||||
|
||||
if (fw_mon->num_frags ||
|
||||
fw_mon_cfg->buf_location !=
|
||||
cpu_to_le32(IWL_FW_INI_LOCATION_DRAM_PATH))
|
||||
return 0;
|
||||
|
||||
num_frags = le32_to_cpu(fw_mon_cfg->max_frags_num);
|
||||
if (!fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_DBG_BUF_ALLOC_CMD_SUPP)) {
|
||||
if (alloc_id != IWL_FW_INI_ALLOCATION_ID_DBGC1)
|
||||
return -EIO;
|
||||
num_frags = 1;
|
||||
}
|
||||
|
||||
remain_pages = DIV_ROUND_UP(le32_to_cpu(fw_mon_cfg->req_size),
|
||||
PAGE_SIZE);
|
||||
num_frags = min_t(u32, num_frags, BUF_ALLOC_MAX_NUM_FRAGS);
|
||||
num_frags = min_t(u32, num_frags, remain_pages);
|
||||
frag_pages = DIV_ROUND_UP(remain_pages, num_frags);
|
||||
|
||||
fw_mon->frags = kcalloc(num_frags, sizeof(*fw_mon->frags), GFP_KERNEL);
|
||||
if (!fw_mon->frags)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num_frags; i++) {
|
||||
int pages = min_t(u32, frag_pages, remain_pages);
|
||||
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"WRT: Allocating DRAM buffer (alloc_id=%u, fragment=%u, size=0x%lx)\n",
|
||||
alloc_id, i, pages * PAGE_SIZE);
|
||||
|
||||
pages = iwl_dbg_tlv_alloc_fragment(fwrt, &fw_mon->frags[i],
|
||||
pages);
|
||||
if (pages < 0) {
|
||||
u32 alloc_size = le32_to_cpu(fw_mon_cfg->req_size) -
|
||||
(remain_pages * PAGE_SIZE);
|
||||
|
||||
if (alloc_size < le32_to_cpu(fw_mon_cfg->min_size)) {
|
||||
iwl_dbg_tlv_fragments_free(fwrt->trans,
|
||||
alloc_id);
|
||||
return pages;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
remain_pages -= pages;
|
||||
fw_mon->num_frags++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_apply_buffer(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_ini_allocation_id alloc_id)
|
||||
{
|
||||
struct iwl_fw_mon *fw_mon;
|
||||
u32 remain_frags, num_commands;
|
||||
int i, fw_mon_idx = 0;
|
||||
|
||||
if (!fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_DBG_BUF_ALLOC_CMD_SUPP))
|
||||
return 0;
|
||||
|
||||
if (alloc_id < IWL_FW_INI_ALLOCATION_INVALID ||
|
||||
alloc_id >= IWL_FW_INI_ALLOCATION_NUM)
|
||||
return -EIO;
|
||||
|
||||
if (le32_to_cpu(fwrt->trans->dbg.fw_mon_cfg[alloc_id].buf_location) !=
|
||||
IWL_FW_INI_LOCATION_DRAM_PATH)
|
||||
return 0;
|
||||
|
||||
fw_mon = &fwrt->trans->dbg.fw_mon_ini[alloc_id];
|
||||
|
||||
/* the first fragment of DBGC1 is given to the FW via register
|
||||
* or context info
|
||||
*/
|
||||
if (alloc_id == IWL_FW_INI_ALLOCATION_ID_DBGC1)
|
||||
fw_mon_idx++;
|
||||
|
||||
remain_frags = fw_mon->num_frags - fw_mon_idx;
|
||||
if (!remain_frags)
|
||||
return 0;
|
||||
|
||||
num_commands = DIV_ROUND_UP(remain_frags, BUF_ALLOC_MAX_NUM_FRAGS);
|
||||
|
||||
IWL_DEBUG_FW(fwrt, "WRT: Applying DRAM destination (alloc_id=%u)\n",
|
||||
alloc_id);
|
||||
|
||||
for (i = 0; i < num_commands; i++) {
|
||||
u32 num_frags = min_t(u32, remain_frags,
|
||||
BUF_ALLOC_MAX_NUM_FRAGS);
|
||||
struct iwl_buf_alloc_cmd data = {
|
||||
.alloc_id = cpu_to_le32(alloc_id),
|
||||
.num_frags = cpu_to_le32(num_frags),
|
||||
.buf_location =
|
||||
cpu_to_le32(IWL_FW_INI_LOCATION_DRAM_PATH),
|
||||
};
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = WIDE_ID(DEBUG_GROUP, BUFFER_ALLOCATION),
|
||||
.data[0] = &data,
|
||||
.len[0] = sizeof(data),
|
||||
};
|
||||
int ret, j;
|
||||
|
||||
for (j = 0; j < num_frags; j++) {
|
||||
struct iwl_buf_alloc_frag *frag = &data.frags[j];
|
||||
struct iwl_dram_data *fw_mon_frag =
|
||||
&fw_mon->frags[fw_mon_idx++];
|
||||
|
||||
frag->addr = cpu_to_le64(fw_mon_frag->physical);
|
||||
frag->size = cpu_to_le32(fw_mon_frag->size);
|
||||
}
|
||||
ret = iwl_trans_send_cmd(fwrt->trans, &hcmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
remain_frags -= num_frags;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_dbg_tlv_apply_buffers(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < IWL_FW_INI_ALLOCATION_NUM; i++) {
|
||||
ret = iwl_dbg_tlv_apply_buffer(fwrt, i);
|
||||
if (ret)
|
||||
IWL_WARN(fwrt,
|
||||
"WRT: Failed to apply DRAM buffer for allocation id %d, ret=%d\n",
|
||||
i, ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt,
|
||||
struct list_head *hcmd_list)
|
||||
{
|
||||
struct iwl_dbg_tlv_node *node;
|
||||
|
||||
list_for_each_entry(node, hcmd_list, list) {
|
||||
struct iwl_fw_ini_hcmd_tlv *hcmd = (void *)node->tlv.data;
|
||||
struct iwl_fw_ini_hcmd *hcmd_data = &hcmd->hcmd;
|
||||
u32 domain = le32_to_cpu(hcmd->hdr.domain);
|
||||
u16 hcmd_len = le32_to_cpu(node->tlv.length) - sizeof(*hcmd);
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = WIDE_ID(hcmd_data->group, hcmd_data->id),
|
||||
.len = { hcmd_len, },
|
||||
.data = { hcmd_data->data, },
|
||||
};
|
||||
|
||||
if (domain != IWL_FW_INI_DOMAIN_ALWAYS_ON &&
|
||||
!(domain & fwrt->trans->dbg.domains_bitmap))
|
||||
continue;
|
||||
|
||||
iwl_trans_send_cmd(fwrt->trans, &cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_dbg_tlv_periodic_trig_handler(struct timer_list *t)
|
||||
{
|
||||
struct iwl_dbg_tlv_timer_node *timer_node =
|
||||
from_timer(timer_node, t, timer);
|
||||
struct iwl_fwrt_dump_data dump_data = {
|
||||
.trig = (void *)timer_node->tlv->data,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = iwl_fw_dbg_ini_collect(timer_node->fwrt, &dump_data);
|
||||
if (!ret || ret == -EBUSY) {
|
||||
u32 occur = le32_to_cpu(dump_data.trig->occurrences);
|
||||
u32 collect_interval = le32_to_cpu(dump_data.trig->data[0]);
|
||||
|
||||
if (!occur)
|
||||
return;
|
||||
|
||||
mod_timer(t, jiffies + msecs_to_jiffies(collect_interval));
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_dbg_tlv_set_periodic_trigs(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct iwl_dbg_tlv_node *node;
|
||||
struct list_head *trig_list =
|
||||
&fwrt->trans->dbg.time_point[IWL_FW_INI_TIME_POINT_PERIODIC].active_trig_list;
|
||||
|
||||
list_for_each_entry(node, trig_list, list) {
|
||||
struct iwl_fw_ini_trigger_tlv *trig = (void *)node->tlv.data;
|
||||
struct iwl_dbg_tlv_timer_node *timer_node;
|
||||
u32 occur = le32_to_cpu(trig->occurrences), collect_interval;
|
||||
u32 min_interval = 100;
|
||||
|
||||
if (!occur)
|
||||
continue;
|
||||
|
||||
/* make sure there is at least one dword of data for the
|
||||
* interval value
|
||||
*/
|
||||
if (le32_to_cpu(node->tlv.length) <
|
||||
sizeof(*trig) + sizeof(__le32)) {
|
||||
IWL_ERR(fwrt,
|
||||
"WRT: Invalid periodic trigger data was not given\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(trig->data[0]) < min_interval) {
|
||||
IWL_WARN(fwrt,
|
||||
"WRT: Override min interval from %u to %u msec\n",
|
||||
le32_to_cpu(trig->data[0]), min_interval);
|
||||
trig->data[0] = cpu_to_le32(min_interval);
|
||||
}
|
||||
|
||||
collect_interval = le32_to_cpu(trig->data[0]);
|
||||
|
||||
timer_node = kzalloc(sizeof(*timer_node), GFP_KERNEL);
|
||||
if (!timer_node) {
|
||||
IWL_ERR(fwrt,
|
||||
"WRT: Failed to allocate periodic trigger\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
timer_node->fwrt = fwrt;
|
||||
timer_node->tlv = &node->tlv;
|
||||
timer_setup(&timer_node->timer,
|
||||
iwl_dbg_tlv_periodic_trig_handler, 0);
|
||||
|
||||
list_add_tail(&timer_node->list,
|
||||
&fwrt->trans->dbg.periodic_trig_list);
|
||||
|
||||
IWL_DEBUG_FW(fwrt, "WRT: Enabling periodic trigger\n");
|
||||
|
||||
mod_timer(&timer_node->timer,
|
||||
jiffies + msecs_to_jiffies(collect_interval));
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_trig_data_contained(struct iwl_ucode_tlv *new,
|
||||
struct iwl_ucode_tlv *old)
|
||||
{
|
||||
struct iwl_fw_ini_trigger_tlv *new_trig = (void *)new->data;
|
||||
struct iwl_fw_ini_trigger_tlv *old_trig = (void *)old->data;
|
||||
__le32 *new_data = new_trig->data, *old_data = old_trig->data;
|
||||
u32 new_dwords_num = iwl_tlv_array_len(new, new_trig, data);
|
||||
u32 old_dwords_num = iwl_tlv_array_len(new, new_trig, data);
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < new_dwords_num; i++) {
|
||||
bool match = false;
|
||||
|
||||
for (j = 0; j < old_dwords_num; j++) {
|
||||
if (new_data[i] == old_data[j]) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_override_trig_node(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_ucode_tlv *trig_tlv,
|
||||
struct iwl_dbg_tlv_node *node)
|
||||
{
|
||||
struct iwl_ucode_tlv *node_tlv = &node->tlv;
|
||||
struct iwl_fw_ini_trigger_tlv *node_trig = (void *)node_tlv->data;
|
||||
struct iwl_fw_ini_trigger_tlv *trig = (void *)trig_tlv->data;
|
||||
u32 policy = le32_to_cpu(trig->apply_policy);
|
||||
u32 size = le32_to_cpu(trig_tlv->length);
|
||||
u32 trig_data_len = size - sizeof(*trig);
|
||||
u32 offset = 0;
|
||||
|
||||
if (!(policy & IWL_FW_INI_APPLY_POLICY_OVERRIDE_DATA)) {
|
||||
u32 data_len = le32_to_cpu(node_tlv->length) -
|
||||
sizeof(*node_trig);
|
||||
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"WRT: Appending trigger data (time point %u)\n",
|
||||
le32_to_cpu(trig->time_point));
|
||||
|
||||
offset += data_len;
|
||||
size += data_len;
|
||||
} else {
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"WRT: Overriding trigger data (time point %u)\n",
|
||||
le32_to_cpu(trig->time_point));
|
||||
}
|
||||
|
||||
if (size != le32_to_cpu(node_tlv->length)) {
|
||||
struct list_head *prev = node->list.prev;
|
||||
struct iwl_dbg_tlv_node *tmp;
|
||||
|
||||
list_del(&node->list);
|
||||
|
||||
tmp = krealloc(node, sizeof(*node) + size, GFP_KERNEL);
|
||||
if (!tmp) {
|
||||
IWL_WARN(fwrt,
|
||||
"WRT: No memory to override trigger (time point %u)\n",
|
||||
le32_to_cpu(trig->time_point));
|
||||
|
||||
list_add(&node->list, prev);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
list_add(&tmp->list, prev);
|
||||
node_tlv = &tmp->tlv;
|
||||
node_trig = (void *)node_tlv->data;
|
||||
}
|
||||
|
||||
memcpy(node_trig->data + offset, trig->data, trig_data_len);
|
||||
node_tlv->length = cpu_to_le32(size);
|
||||
|
||||
if (policy & IWL_FW_INI_APPLY_POLICY_OVERRIDE_CFG) {
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"WRT: Overriding trigger configuration (time point %u)\n",
|
||||
le32_to_cpu(trig->time_point));
|
||||
|
||||
/* the first 11 dwords are configuration related */
|
||||
memcpy(node_trig, trig, sizeof(__le32) * 11);
|
||||
}
|
||||
|
||||
if (policy & IWL_FW_INI_APPLY_POLICY_OVERRIDE_REGIONS) {
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"WRT: Overriding trigger regions (time point %u)\n",
|
||||
le32_to_cpu(trig->time_point));
|
||||
|
||||
node_trig->regions_mask = trig->regions_mask;
|
||||
} else {
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"WRT: Appending trigger regions (time point %u)\n",
|
||||
le32_to_cpu(trig->time_point));
|
||||
|
||||
node_trig->regions_mask |= trig->regions_mask;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_dbg_tlv_add_active_trigger(struct iwl_fw_runtime *fwrt,
|
||||
struct list_head *trig_list,
|
||||
struct iwl_ucode_tlv *trig_tlv)
|
||||
{
|
||||
struct iwl_fw_ini_trigger_tlv *trig = (void *)trig_tlv->data;
|
||||
struct iwl_dbg_tlv_node *node, *match = NULL;
|
||||
u32 policy = le32_to_cpu(trig->apply_policy);
|
||||
|
||||
list_for_each_entry(node, trig_list, list) {
|
||||
if (!(policy & IWL_FW_INI_APPLY_POLICY_MATCH_TIME_POINT))
|
||||
break;
|
||||
|
||||
if (!(policy & IWL_FW_INI_APPLY_POLICY_MATCH_DATA) ||
|
||||
is_trig_data_contained(trig_tlv, &node->tlv)) {
|
||||
match = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match) {
|
||||
IWL_DEBUG_FW(fwrt, "WRT: Enabling trigger (time point %u)\n",
|
||||
le32_to_cpu(trig->time_point));
|
||||
return iwl_dbg_tlv_add(trig_tlv, trig_list);
|
||||
}
|
||||
|
||||
return iwl_dbg_tlv_override_trig_node(fwrt, trig_tlv, match);
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_dbg_tlv_gen_active_trig_list(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dbg_tlv_time_point_data *tp)
|
||||
{
|
||||
struct iwl_dbg_tlv_node *node, *tmp;
|
||||
struct list_head *trig_list = &tp->trig_list;
|
||||
struct list_head *active_trig_list = &tp->active_trig_list;
|
||||
|
||||
list_for_each_entry_safe(node, tmp, active_trig_list, list) {
|
||||
list_del(&node->list);
|
||||
kfree(node);
|
||||
}
|
||||
|
||||
list_for_each_entry(node, trig_list, list) {
|
||||
struct iwl_ucode_tlv *tlv = &node->tlv;
|
||||
struct iwl_fw_ini_trigger_tlv *trig = (void *)tlv->data;
|
||||
u32 domain = le32_to_cpu(trig->hdr.domain);
|
||||
|
||||
if (domain != IWL_FW_INI_DOMAIN_ALWAYS_ON &&
|
||||
!(domain & fwrt->trans->dbg.domains_bitmap))
|
||||
continue;
|
||||
|
||||
iwl_dbg_tlv_add_active_trigger(fwrt, active_trig_list, tlv);
|
||||
}
|
||||
}
|
||||
|
||||
int iwl_dbg_tlv_gen_active_trigs(struct iwl_fw_runtime *fwrt, u32 new_domain)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (test_and_set_bit(STATUS_GEN_ACTIVE_TRIGS, &fwrt->status))
|
||||
return -EBUSY;
|
||||
|
||||
iwl_fw_flush_dumps(fwrt);
|
||||
|
||||
fwrt->trans->dbg.domains_bitmap = new_domain;
|
||||
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"WRT: Generating active triggers list, domain 0x%x\n",
|
||||
fwrt->trans->dbg.domains_bitmap);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fwrt->trans->dbg.time_point); i++) {
|
||||
struct iwl_dbg_tlv_time_point_data *tp =
|
||||
&fwrt->trans->dbg.time_point[i];
|
||||
|
||||
iwl_dbg_tlv_gen_active_trig_list(fwrt, tp);
|
||||
}
|
||||
|
||||
clear_bit(STATUS_GEN_ACTIVE_TRIGS, &fwrt->status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool iwl_dbg_tlv_check_fw_pkt(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fwrt_dump_data *dump_data,
|
||||
union iwl_dbg_tlv_tp_data *tp_data,
|
||||
u32 trig_data)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = tp_data->fw_pkt;
|
||||
struct iwl_cmd_header *wanted_hdr = (void *)&trig_data;
|
||||
|
||||
if (pkt && ((wanted_hdr->cmd == 0 && wanted_hdr->group_id == 0) ||
|
||||
(pkt->hdr.cmd == wanted_hdr->cmd &&
|
||||
pkt->hdr.group_id == wanted_hdr->group_id))) {
|
||||
struct iwl_rx_packet *fw_pkt =
|
||||
kmemdup(pkt,
|
||||
sizeof(*pkt) + iwl_rx_packet_payload_len(pkt),
|
||||
GFP_ATOMIC);
|
||||
|
||||
if (!fw_pkt)
|
||||
return false;
|
||||
|
||||
dump_data->fw_pkt = fw_pkt;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_dbg_tlv_tp_trigger(struct iwl_fw_runtime *fwrt,
|
||||
struct list_head *active_trig_list,
|
||||
union iwl_dbg_tlv_tp_data *tp_data,
|
||||
bool (*data_check)(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_fwrt_dump_data *dump_data,
|
||||
union iwl_dbg_tlv_tp_data *tp_data,
|
||||
u32 trig_data))
|
||||
{
|
||||
struct iwl_dbg_tlv_node *node;
|
||||
|
||||
list_for_each_entry(node, active_trig_list, list) {
|
||||
struct iwl_fwrt_dump_data dump_data = {
|
||||
.trig = (void *)node->tlv.data,
|
||||
};
|
||||
u32 num_data = iwl_tlv_array_len(&node->tlv, dump_data.trig,
|
||||
data);
|
||||
int ret, i;
|
||||
|
||||
if (!num_data) {
|
||||
ret = iwl_fw_dbg_ini_collect(fwrt, &dump_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_data; i++) {
|
||||
if (!data_check ||
|
||||
data_check(fwrt, &dump_data, tp_data,
|
||||
le32_to_cpu(dump_data.trig->data[i]))) {
|
||||
ret = iwl_fw_dbg_ini_collect(fwrt, &dump_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
enum iwl_fw_ini_buffer_location *ini_dest = &fwrt->trans->dbg.ini_dest;
|
||||
int ret, i;
|
||||
|
||||
iwl_dbg_tlv_gen_active_trigs(fwrt, IWL_FW_DBG_DOMAIN);
|
||||
|
||||
*ini_dest = IWL_FW_INI_LOCATION_INVALID;
|
||||
for (i = 0; i < IWL_FW_INI_ALLOCATION_NUM; i++) {
|
||||
struct iwl_fw_ini_allocation_tlv *fw_mon_cfg =
|
||||
&fwrt->trans->dbg.fw_mon_cfg[i];
|
||||
u32 dest = le32_to_cpu(fw_mon_cfg->buf_location);
|
||||
|
||||
if (dest == IWL_FW_INI_LOCATION_INVALID)
|
||||
continue;
|
||||
|
||||
if (*ini_dest == IWL_FW_INI_LOCATION_INVALID)
|
||||
*ini_dest = dest;
|
||||
|
||||
if (dest != *ini_dest)
|
||||
continue;
|
||||
|
||||
ret = iwl_dbg_tlv_alloc_fragments(fwrt, i);
|
||||
if (ret)
|
||||
IWL_WARN(fwrt,
|
||||
"WRT: Failed to allocate DRAM buffer for allocation id %d, ret=%d\n",
|
||||
i, ret);
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
struct list_head *hcmd_list, *trig_list;
|
||||
|
||||
if (!iwl_trans_dbg_ini_valid(fwrt->trans) ||
|
||||
tp_id == IWL_FW_INI_TIME_POINT_INVALID ||
|
||||
tp_id >= IWL_FW_INI_TIME_POINT_NUM)
|
||||
return;
|
||||
|
||||
hcmd_list = &fwrt->trans->dbg.time_point[tp_id].hcmd_list;
|
||||
trig_list = &fwrt->trans->dbg.time_point[tp_id].active_trig_list;
|
||||
|
||||
switch (tp_id) {
|
||||
case IWL_FW_INI_TIME_POINT_EARLY:
|
||||
iwl_dbg_tlv_init_cfg(fwrt);
|
||||
iwl_dbg_tlv_tp_trigger(fwrt, trig_list, tp_data, NULL);
|
||||
break;
|
||||
case IWL_FW_INI_TIME_POINT_AFTER_ALIVE:
|
||||
iwl_dbg_tlv_apply_buffers(fwrt);
|
||||
iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
|
||||
iwl_dbg_tlv_tp_trigger(fwrt, trig_list, tp_data, NULL);
|
||||
break;
|
||||
case IWL_FW_INI_TIME_POINT_PERIODIC:
|
||||
iwl_dbg_tlv_set_periodic_trigs(fwrt);
|
||||
iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
|
||||
break;
|
||||
case IWL_FW_INI_TIME_POINT_FW_RSP_OR_NOTIF:
|
||||
case IWL_FW_INI_TIME_POINT_MISSED_BEACONS:
|
||||
iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
|
||||
iwl_dbg_tlv_tp_trigger(fwrt, trig_list, tp_data,
|
||||
iwl_dbg_tlv_check_fw_pkt);
|
||||
break;
|
||||
default:
|
||||
iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
|
||||
iwl_dbg_tlv_tp_trigger(fwrt, trig_list, tp_data, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_dbg_tlv_time_point);
|
||||
|
@ -65,11 +65,11 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
* struct iwl_apply_point_data
|
||||
* @list: list to go through the TLVs of the apply point
|
||||
* @tlv: a debug TLV
|
||||
* struct iwl_dbg_tlv_node - debug TLV node
|
||||
* @list: list of &struct iwl_dbg_tlv_node
|
||||
* @tlv: debug TLV
|
||||
*/
|
||||
struct iwl_apply_point_data {
|
||||
struct iwl_dbg_tlv_node {
|
||||
struct list_head list;
|
||||
struct iwl_ucode_tlv tlv;
|
||||
};
|
||||
@ -82,6 +82,18 @@ union iwl_dbg_tlv_tp_data {
|
||||
struct iwl_rx_packet *fw_pkt;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_dbg_tlv_time_point_data
|
||||
* @trig_list: list of triggers
|
||||
* @active_trig_list: list of active triggers
|
||||
* @hcmd_list: list of host commands
|
||||
*/
|
||||
struct iwl_dbg_tlv_time_point_data {
|
||||
struct list_head trig_list;
|
||||
struct list_head active_trig_list;
|
||||
struct list_head hcmd_list;
|
||||
};
|
||||
|
||||
struct iwl_trans;
|
||||
struct iwl_fw_runtime;
|
||||
|
||||
@ -89,9 +101,11 @@ void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans);
|
||||
void iwl_dbg_tlv_free(struct iwl_trans *trans);
|
||||
void iwl_dbg_tlv_alloc(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
|
||||
bool ext);
|
||||
void iwl_dbg_tlv_init(struct iwl_trans *trans);
|
||||
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);
|
||||
int iwl_dbg_tlv_gen_active_trigs(struct iwl_fw_runtime *fwrt, u32 new_domain);
|
||||
void iwl_dbg_tlv_del_timers(struct iwl_trans *trans);
|
||||
|
||||
#endif /* __iwl_dbg_tlv_h__*/
|
||||
|
@ -1560,6 +1560,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
IWL_INFO(drv, "loaded firmware version %s op_mode %s\n",
|
||||
drv->fw.fw_version, op->name);
|
||||
|
||||
iwl_dbg_tlv_load_bin(drv->trans->dev, drv->trans);
|
||||
|
||||
/* add this device to the list of devices using this op_mode */
|
||||
list_add_tail(&drv->list, &op->drv);
|
||||
|
||||
@ -1636,8 +1638,6 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
|
||||
init_completion(&drv->request_firmware_complete);
|
||||
INIT_LIST_HEAD(&drv->list);
|
||||
|
||||
iwl_dbg_tlv_load_bin(drv->trans->dev, drv->trans);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
/* Create the device debugfs entries. */
|
||||
drv->dbgfs_drv = debugfs_create_dir(dev_name(trans->dev),
|
||||
|
@ -256,12 +256,12 @@ static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
|
||||
#undef CHECK_AND_PRINT_I
|
||||
}
|
||||
|
||||
static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
|
||||
static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, enum nl80211_band band,
|
||||
u32 nvm_flags, const struct iwl_cfg *cfg)
|
||||
{
|
||||
u32 flags = IEEE80211_CHAN_NO_HT40;
|
||||
|
||||
if (!is_5ghz && (nvm_flags & NVM_CHANNEL_40MHZ)) {
|
||||
if (band == NL80211_BAND_2GHZ && (nvm_flags & NVM_CHANNEL_40MHZ)) {
|
||||
if (ch_num <= LAST_2GHZ_HT_PLUS)
|
||||
flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
|
||||
if (ch_num >= FIRST_2GHZ_HT_MINUS)
|
||||
@ -299,6 +299,13 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
|
||||
return flags;
|
||||
}
|
||||
|
||||
static enum nl80211_band iwl_nl80211_band_from_channel_idx(int ch_idx)
|
||||
{
|
||||
if (ch_idx >= NUM_2GHZ_CHANNELS)
|
||||
return NL80211_BAND_5GHZ;
|
||||
return NL80211_BAND_2GHZ;
|
||||
}
|
||||
|
||||
static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
const void * const nvm_ch_flags,
|
||||
@ -308,7 +315,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
int n_channels = 0;
|
||||
struct ieee80211_channel *channel;
|
||||
u32 ch_flags;
|
||||
int num_of_ch, num_2ghz_channels = NUM_2GHZ_CHANNELS;
|
||||
int num_of_ch;
|
||||
const u16 *nvm_chan;
|
||||
|
||||
if (cfg->uhb_supported) {
|
||||
@ -323,7 +330,8 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
}
|
||||
|
||||
for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
|
||||
bool is_5ghz = (ch_idx >= num_2ghz_channels);
|
||||
enum nl80211_band band =
|
||||
iwl_nl80211_band_from_channel_idx(ch_idx);
|
||||
|
||||
if (v4)
|
||||
ch_flags =
|
||||
@ -332,12 +340,13 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
ch_flags =
|
||||
__le16_to_cpup((__le16 *)nvm_ch_flags + ch_idx);
|
||||
|
||||
if (is_5ghz && !data->sku_cap_band_52ghz_enable)
|
||||
if (band == NL80211_BAND_5GHZ &&
|
||||
!data->sku_cap_band_52ghz_enable)
|
||||
continue;
|
||||
|
||||
/* workaround to disable wide channels in 5GHz */
|
||||
if ((sbands_flags & IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ) &&
|
||||
is_5ghz) {
|
||||
band == NL80211_BAND_5GHZ) {
|
||||
ch_flags &= ~(NVM_CHANNEL_40MHZ |
|
||||
NVM_CHANNEL_80MHZ |
|
||||
NVM_CHANNEL_160MHZ);
|
||||
@ -362,8 +371,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
n_channels++;
|
||||
|
||||
channel->hw_value = nvm_chan[ch_idx];
|
||||
channel->band = is_5ghz ?
|
||||
NL80211_BAND_5GHZ : NL80211_BAND_2GHZ;
|
||||
channel->band = band;
|
||||
channel->center_freq =
|
||||
ieee80211_channel_to_frequency(
|
||||
channel->hw_value, channel->band);
|
||||
@ -379,7 +387,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
/* don't put limitations in case we're using LAR */
|
||||
if (!(sbands_flags & IWL_NVM_SBANDS_FLAGS_LAR))
|
||||
channel->flags = iwl_get_channel_flags(nvm_chan[ch_idx],
|
||||
ch_idx, is_5ghz,
|
||||
ch_idx, band,
|
||||
ch_flags, cfg);
|
||||
else
|
||||
channel->flags = 0;
|
||||
|
@ -374,6 +374,7 @@
|
||||
#define DBGC_CUR_DBGBUF_STATUS (0xd03c1c)
|
||||
#define DBGC_DBGBUF_WRAP_AROUND (0xd03c2c)
|
||||
#define DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK (0x00ffffff)
|
||||
#define DBGC_CUR_DBGBUF_STATUS_IDX_MSK (0x0f000000)
|
||||
|
||||
#define MON_DMARB_RD_CTL_ADDR (0xa03c60)
|
||||
#define MON_DMARB_RD_DATA_ADDR (0xa03c5c)
|
||||
@ -381,6 +382,12 @@
|
||||
#define DBGC_IN_SAMPLE (0xa03c00)
|
||||
#define DBGC_OUT_CTRL (0xa03c0c)
|
||||
|
||||
/* M2S registers */
|
||||
#define LDBG_M2S_BUF_WPTR (0xa0476c)
|
||||
#define LDBG_M2S_BUF_WRAP_CNT (0xa04774)
|
||||
#define LDBG_M2S_BUF_WPTR_VAL_MSK (0x000fffff)
|
||||
#define LDBG_M2S_BUF_WRAP_CNT_VAL_MSK (0x000fffff)
|
||||
|
||||
/* enable the ID buf for read */
|
||||
#define WFPM_PS_CTL_CLR 0xA0300C
|
||||
#define WFMP_MAC_ADDR_0 0xA03080
|
||||
|
@ -678,6 +678,16 @@ struct iwl_dram_data {
|
||||
int size;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw_mon - fw monitor per allocation id
|
||||
* @num_frags: number of fragments
|
||||
* @frags: an array of DRAM buffer fragments
|
||||
*/
|
||||
struct iwl_fw_mon {
|
||||
u32 num_frags;
|
||||
struct iwl_dram_data *frags;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_self_init_dram - dram data used by self init process
|
||||
* @fw: lmac and umac dram data
|
||||
@ -706,10 +716,17 @@ struct iwl_self_init_dram {
|
||||
* pointers was recevied via TLV. uses enum &iwl_error_event_table_status
|
||||
* @internal_ini_cfg: internal debug cfg state. Uses &enum iwl_ini_cfg_state
|
||||
* @external_ini_cfg: external debug cfg state. Uses &enum iwl_ini_cfg_state
|
||||
* @num_blocks: number of blocks in fw_mon
|
||||
* @fw_mon: address of the buffers for firmware monitor
|
||||
* @fw_mon_cfg: debug buffer allocation configuration
|
||||
* @fw_mon_ini: DRAM buffer fragments per allocation id
|
||||
* @fw_mon: DRAM buffer for firmware monitor
|
||||
* @hw_error: equals true if hw error interrupt was received from the FW
|
||||
* @ini_dest: debug monitor destination uses &enum iwl_fw_ini_buffer_location
|
||||
* @active_regions: active regions
|
||||
* @debug_info_tlv_list: list of debug info TLVs
|
||||
* @time_point: array of debug time points
|
||||
* @periodic_trig_list: periodic triggers list
|
||||
* @domains_bitmap: bitmap of active domains other than
|
||||
* &IWL_FW_INI_DOMAIN_ALWAYS_ON
|
||||
*/
|
||||
struct iwl_trans_debug {
|
||||
u8 n_dest_reg;
|
||||
@ -726,11 +743,21 @@ struct iwl_trans_debug {
|
||||
enum iwl_ini_cfg_state internal_ini_cfg;
|
||||
enum iwl_ini_cfg_state external_ini_cfg;
|
||||
|
||||
int num_blocks;
|
||||
struct iwl_dram_data fw_mon[IWL_FW_INI_ALLOCATION_NUM];
|
||||
struct iwl_fw_ini_allocation_tlv fw_mon_cfg[IWL_FW_INI_ALLOCATION_NUM];
|
||||
struct iwl_fw_mon fw_mon_ini[IWL_FW_INI_ALLOCATION_NUM];
|
||||
|
||||
struct iwl_dram_data fw_mon;
|
||||
|
||||
bool hw_error;
|
||||
enum iwl_fw_ini_buffer_location ini_dest;
|
||||
|
||||
struct iwl_ucode_tlv *active_regions[IWL_FW_INI_MAX_REGION_ID];
|
||||
struct list_head debug_info_tlv_list;
|
||||
struct iwl_dbg_tlv_time_point_data
|
||||
time_point[IWL_FW_INI_TIME_POINT_NUM];
|
||||
struct list_head periodic_trig_list;
|
||||
|
||||
u32 domains_bitmap;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1222,6 +1249,11 @@ static inline void iwl_trans_fw_error(struct iwl_trans *trans)
|
||||
iwl_op_mode_nic_error(trans->op_mode);
|
||||
}
|
||||
|
||||
static inline bool iwl_trans_fw_running(struct iwl_trans *trans)
|
||||
{
|
||||
return trans->state == IWL_TRANS_FW_ALIVE;
|
||||
}
|
||||
|
||||
static inline void iwl_trans_sync_nmi(struct iwl_trans *trans)
|
||||
{
|
||||
if (trans->ops->sync_nmi)
|
||||
|
@ -1955,12 +1955,39 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
|
||||
}
|
||||
|
||||
if (d0i3_first) {
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, 0, 0, NULL);
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = D0I3_END_CMD,
|
||||
.flags = CMD_WANT_SKB,
|
||||
};
|
||||
int len;
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (ret < 0) {
|
||||
IWL_ERR(mvm, "Failed to send D0I3_END_CMD first (%d)\n",
|
||||
ret);
|
||||
goto err;
|
||||
}
|
||||
switch (mvm->cmd_ver.d0i3_resp) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
len = iwl_rx_packet_payload_len(cmd.resp_pkt);
|
||||
if (len != sizeof(u32)) {
|
||||
IWL_ERR(mvm,
|
||||
"Error with D0I3_END_CMD response size (%d)\n",
|
||||
len);
|
||||
goto err;
|
||||
}
|
||||
if (IWL_D0I3_RESET_REQUIRE &
|
||||
le32_to_cpu(*(__le32 *)cmd.resp_pkt->data)) {
|
||||
iwl_write32(mvm->trans, CSR_RESET,
|
||||
CSR_RESET_REG_FLAG_FORCE_NMI);
|
||||
iwl_free_resp(&cmd);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1375,6 +1375,9 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER,
|
||||
NULL);
|
||||
|
||||
iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf,
|
||||
(count - 1), NULL);
|
||||
|
||||
|
@ -855,11 +855,10 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
u8 rate;
|
||||
|
||||
if (info->band == NL80211_BAND_5GHZ || vif->p2p)
|
||||
rate = IWL_FIRST_OFDM_RATE;
|
||||
else
|
||||
if (info->band == NL80211_BAND_2GHZ && !vif->p2p)
|
||||
rate = IWL_FIRST_CCK_RATE;
|
||||
else
|
||||
rate = IWL_FIRST_OFDM_RATE;
|
||||
|
||||
return rate;
|
||||
}
|
||||
@ -1404,6 +1403,7 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
||||
u32 rx_missed_bcon, rx_missed_bcon_since_rx;
|
||||
struct ieee80211_vif *vif;
|
||||
u32 id = le32_to_cpu(mb->mac_id);
|
||||
union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt };
|
||||
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n",
|
||||
@ -1432,7 +1432,7 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
||||
ieee80211_beacon_loss(vif);
|
||||
|
||||
iwl_dbg_tlv_time_point(&mvm->fwrt,
|
||||
IWL_FW_INI_TIME_POINT_MISSED_BEACONS, NULL);
|
||||
IWL_FW_INI_TIME_POINT_MISSED_BEACONS, &tp_data);
|
||||
|
||||
trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
|
||||
FW_DBG_TRIGGER_MISSED_BEACONS);
|
||||
@ -1609,3 +1609,26 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void iwl_mvm_rx_missed_vap_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_missed_vap_notif *mb = (void *)pkt->data;
|
||||
struct ieee80211_vif *vif;
|
||||
u32 id = le32_to_cpu(mb->mac_id);
|
||||
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"missed_vap notify mac_id=%u, num_beacon_intervals_elapsed=%u, profile_periodicity=%u\n",
|
||||
le32_to_cpu(mb->mac_id),
|
||||
mb->num_beacon_intervals_elapsed,
|
||||
mb->profile_periodicity);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
|
||||
if (vif)
|
||||
iwl_mvm_connection_loss(mvm, vif, "missed vap beacon");
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
@ -339,14 +339,14 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
|
||||
return ret;
|
||||
}
|
||||
|
||||
const static u8 he_if_types_ext_capa_sta[] = {
|
||||
static const u8 he_if_types_ext_capa_sta[] = {
|
||||
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
|
||||
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
|
||||
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
|
||||
[9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
|
||||
};
|
||||
|
||||
const static struct wiphy_iftype_ext_capab he_iftypes_ext_capa[] = {
|
||||
static const struct wiphy_iftype_ext_capab he_iftypes_ext_capa[] = {
|
||||
{
|
||||
.iftype = NL80211_IFTYPE_STATION,
|
||||
.extended_capabilities = he_if_types_ext_capa_sta,
|
||||
@ -2280,7 +2280,9 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||
}
|
||||
|
||||
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
|
||||
&mvm->status)) {
|
||||
&mvm->status) &&
|
||||
!fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) {
|
||||
/*
|
||||
* If we're restarting then the firmware will
|
||||
* obviously have lost synchronisation with
|
||||
@ -2294,6 +2296,10 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||
*
|
||||
* Set a large maximum delay to allow for more
|
||||
* than a single interface.
|
||||
*
|
||||
* For new firmware versions, rely on the
|
||||
* firmware. This is relevant for DCM scenarios
|
||||
* only anyway.
|
||||
*/
|
||||
u32 dur = (11 * vif->bss_conf.beacon_int) / 10;
|
||||
iwl_mvm_protect_session(mvm, vif, dur, dur,
|
||||
@ -2384,8 +2390,11 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||
/*
|
||||
* We received a beacon from the associated AP so
|
||||
* remove the session protection.
|
||||
* A firmware with the new API will remove it automatically.
|
||||
*/
|
||||
iwl_mvm_stop_session_protection(mvm, vif);
|
||||
if (!fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
|
||||
iwl_mvm_stop_session_protection(mvm, vif);
|
||||
|
||||
iwl_mvm_sf_update(mvm, vif, false);
|
||||
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
|
||||
@ -3255,8 +3264,22 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
|
||||
duration = req_duration;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
/* Try really hard to protect the session and hear a beacon */
|
||||
iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500, false);
|
||||
/* Try really hard to protect the session and hear a beacon
|
||||
* The new session protection command allows us to protect the
|
||||
* session for a much longer time since the firmware will internally
|
||||
* create two events: a 300TU one with a very high priority that
|
||||
* won't be fragmented which should be enough for 99% of the cases,
|
||||
* and another one (which we configure here to be 900TU long) which
|
||||
* will have a slightly lower priority, but more importantly, can be
|
||||
* fragmented so that it'll allow other activities to run.
|
||||
*/
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
|
||||
iwl_mvm_schedule_session_protection(mvm, vif, 900,
|
||||
min_duration);
|
||||
else
|
||||
iwl_mvm_protect_session(mvm, vif, duration,
|
||||
min_duration, 500, false);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
@ -3613,8 +3636,7 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
|
||||
|
||||
/* Set the channel info data */
|
||||
iwl_mvm_set_chan_info(mvm, &aux_roc_req.channel_info, channel->hw_value,
|
||||
(channel->band == NL80211_BAND_2GHZ) ?
|
||||
PHY_BAND_24 : PHY_BAND_5,
|
||||
iwl_mvm_phy_band_from_nl80211(channel->band),
|
||||
PHY_VHT_CHANNEL_MODE20,
|
||||
0);
|
||||
|
||||
@ -3848,7 +3870,7 @@ static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw,
|
||||
IWL_DEBUG_MAC80211(mvm, "enter\n");
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
iwl_mvm_stop_roc(mvm);
|
||||
iwl_mvm_stop_roc(mvm, vif);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
IWL_DEBUG_MAC80211(mvm, "leave\n");
|
||||
|
@ -1122,6 +1122,10 @@ struct iwl_mvm {
|
||||
int responses[IWL_MVM_TOF_MAX_APS];
|
||||
} ftm_initiator;
|
||||
|
||||
struct {
|
||||
u8 d0i3_resp;
|
||||
} cmd_ver;
|
||||
|
||||
struct ieee80211_vif *nan_vif;
|
||||
#define IWL_MAX_BAID 32
|
||||
struct iwl_mvm_baid_data __rcu *baid_map[IWL_MAX_BAID];
|
||||
@ -1405,12 +1409,19 @@ static inline bool iwl_mvm_is_scan_ext_chan_supported(struct iwl_mvm *mvm)
|
||||
IWL_UCODE_TLV_API_SCAN_EXT_CHAN_VER);
|
||||
}
|
||||
|
||||
|
||||
static inline bool iwl_mvm_is_reduced_config_scan_supported(struct iwl_mvm *mvm)
|
||||
{
|
||||
return fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_REDUCED_SCAN_CONFIG);
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_is_band_in_rx_supported(struct iwl_mvm *mvm)
|
||||
{
|
||||
return fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_BAND_IN_RX_DATA);
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_has_new_rx_stats_api(struct iwl_mvm *mvm)
|
||||
{
|
||||
return fw_has_api(&mvm->fw->ucode_capa,
|
||||
@ -1682,6 +1693,8 @@ void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
void iwl_mvm_rx_missed_vap_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
/* Bindings */
|
||||
@ -2077,6 +2090,19 @@ void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
|
||||
struct dentry *dir);
|
||||
#endif
|
||||
|
||||
static inline u8 iwl_mvm_phy_band_from_nl80211(enum nl80211_band band)
|
||||
{
|
||||
switch (band) {
|
||||
case NL80211_BAND_2GHZ:
|
||||
return PHY_BAND_24;
|
||||
case NL80211_BAND_5GHZ:
|
||||
return PHY_BAND_5;
|
||||
default:
|
||||
WARN_ONCE(1, "Unsupported band (%u)\n", band);
|
||||
return PHY_BAND_5;
|
||||
}
|
||||
}
|
||||
|
||||
/* Channel info utils */
|
||||
static inline bool iwl_mvm_has_ultra_hb_channel(struct iwl_mvm *mvm)
|
||||
{
|
||||
@ -2125,11 +2151,12 @@ iwl_mvm_set_chan_info_chandef(struct iwl_mvm *mvm,
|
||||
struct iwl_fw_channel_info *ci,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
enum nl80211_band band = chandef->chan->band;
|
||||
|
||||
iwl_mvm_set_chan_info(mvm, ci, chandef->chan->hw_value,
|
||||
(chandef->chan->band == NL80211_BAND_2GHZ ?
|
||||
PHY_BAND_24 : PHY_BAND_5),
|
||||
iwl_mvm_get_channel_width(chandef),
|
||||
iwl_mvm_get_ctrl_pos(chandef));
|
||||
iwl_mvm_phy_band_from_nl80211(band),
|
||||
iwl_mvm_get_channel_width(chandef),
|
||||
iwl_mvm_get_ctrl_pos(chandef));
|
||||
}
|
||||
|
||||
#endif /* __IWL_MVM_H__ */
|
||||
|
@ -263,6 +263,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
||||
|
||||
RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif,
|
||||
RX_HANDLER_SYNC),
|
||||
RX_HANDLER_GRP(MAC_CONF_GROUP, SESSION_PROTECTION_NOTIF,
|
||||
iwl_mvm_rx_session_protect_notif, RX_HANDLER_SYNC),
|
||||
RX_HANDLER(MCC_CHUB_UPDATE_CMD, iwl_mvm_rx_chub_update_mcc,
|
||||
RX_HANDLER_ASYNC_LOCKED),
|
||||
|
||||
@ -432,6 +434,8 @@ static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
|
||||
*/
|
||||
static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {
|
||||
HCMD_NAME(CHANNEL_SWITCH_TIME_EVENT_CMD),
|
||||
HCMD_NAME(SESSION_PROTECTION_CMD),
|
||||
HCMD_NAME(SESSION_PROTECTION_NOTIF),
|
||||
HCMD_NAME(CHANNEL_SWITCH_NOA_NOTIF),
|
||||
};
|
||||
|
||||
@ -608,6 +612,27 @@ static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = {
|
||||
.d3_debug_enable = iwl_mvm_d3_debug_enable,
|
||||
};
|
||||
|
||||
static u8 iwl_mvm_lookup_notif_ver(struct iwl_mvm *mvm, u8 grp, u8 cmd, u8 def)
|
||||
{
|
||||
const struct iwl_fw_cmd_version *entry;
|
||||
unsigned int i;
|
||||
|
||||
if (!mvm->fw->ucode_capa.cmd_versions ||
|
||||
!mvm->fw->ucode_capa.n_cmd_versions)
|
||||
return def;
|
||||
|
||||
entry = mvm->fw->ucode_capa.cmd_versions;
|
||||
for (i = 0; i < mvm->fw->ucode_capa.n_cmd_versions; i++, entry++) {
|
||||
if (entry->group == grp && entry->cmd == cmd) {
|
||||
if (entry->notif_ver == IWL_FW_CMD_VER_UNKNOWN)
|
||||
return def;
|
||||
return entry->notif_ver;
|
||||
}
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
static struct iwl_op_mode *
|
||||
iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
const struct iwl_fw *fw, struct dentry *dbgfs_dir)
|
||||
@ -722,6 +747,12 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
|
||||
INIT_DELAYED_WORK(&mvm->cs_tx_unblock_dwork, iwl_mvm_tx_unblock_dwork);
|
||||
|
||||
mvm->cmd_ver.d0i3_resp =
|
||||
iwl_mvm_lookup_notif_ver(mvm, LEGACY_GROUP, D0I3_END_CMD, 0);
|
||||
/* we only support version 1 */
|
||||
if (WARN_ON_ONCE(mvm->cmd_ver.d0i3_resp > 1))
|
||||
goto out_free;
|
||||
|
||||
/*
|
||||
* Populate the state variables that the transport layer needs
|
||||
* to know about.
|
||||
|
@ -350,7 +350,13 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
|
||||
u16 size = le32_to_cpu(notif->amsdu_size);
|
||||
int i;
|
||||
|
||||
if (WARN_ON(sta->max_amsdu_len < size))
|
||||
/*
|
||||
* In debug sta->max_amsdu_len < size
|
||||
* so also check with orig_amsdu_len which holds the original
|
||||
* data before debugfs changed the value
|
||||
*/
|
||||
if (WARN_ON(sta->max_amsdu_len < size &&
|
||||
mvmsta->orig_amsdu_len < size))
|
||||
goto out;
|
||||
|
||||
mvmsta->amsdu_enabled = le32_to_cpu(notif->amsdu_enabled);
|
||||
|
@ -445,10 +445,6 @@ int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
|
||||
void iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
void rs_remove_sta_debugfs(void *mvm, void *mvm_sta);
|
||||
#endif
|
||||
|
||||
void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta);
|
||||
void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
enum nl80211_band band, bool update);
|
||||
|
@ -1542,6 +1542,19 @@ static void iwl_mvm_decode_lsig(struct sk_buff *skb,
|
||||
}
|
||||
}
|
||||
|
||||
static inline u8 iwl_mvm_nl80211_band_from_rx_msdu(u8 phy_band)
|
||||
{
|
||||
switch (phy_band) {
|
||||
case PHY_BAND_24:
|
||||
return NL80211_BAND_2GHZ;
|
||||
case PHY_BAND_5:
|
||||
return NL80211_BAND_5GHZ;
|
||||
default:
|
||||
WARN_ONCE(1, "Unsupported phy band (%u)\n", phy_band);
|
||||
return NL80211_BAND_5GHZ;
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
struct iwl_rx_cmd_buffer *rxb, int queue)
|
||||
{
|
||||
@ -1678,8 +1691,14 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
||||
}
|
||||
|
||||
rx_status->device_timestamp = gp2_on_air_rise;
|
||||
rx_status->band = channel > 14 ? NL80211_BAND_5GHZ :
|
||||
NL80211_BAND_2GHZ;
|
||||
if (iwl_mvm_is_band_in_rx_supported(mvm)) {
|
||||
u8 band = BAND_IN_RX_STATUS(desc->mac_phy_idx);
|
||||
|
||||
rx_status->band = iwl_mvm_nl80211_band_from_rx_msdu(band);
|
||||
} else {
|
||||
rx_status->band = channel > 14 ? NL80211_BAND_5GHZ :
|
||||
NL80211_BAND_2GHZ;
|
||||
}
|
||||
rx_status->freq = ieee80211_channel_to_frequency(channel,
|
||||
rx_status->band);
|
||||
iwl_mvm_get_signal_strength(mvm, rx_status, rate_n_flags, energy_a,
|
||||
|
@ -79,9 +79,6 @@
|
||||
#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 */
|
||||
#define IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300
|
||||
/* adaptive dwell max budget time [TU] for directed scan */
|
||||
@ -196,14 +193,6 @@ static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
|
||||
return cpu_to_le16(rx_chain);
|
||||
}
|
||||
|
||||
static __le32 iwl_mvm_scan_rxon_flags(enum nl80211_band band)
|
||||
{
|
||||
if (band == NL80211_BAND_2GHZ)
|
||||
return cpu_to_le32(PHY_BAND_24);
|
||||
else
|
||||
return cpu_to_le32(PHY_BAND_5);
|
||||
}
|
||||
|
||||
static inline __le32
|
||||
iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum nl80211_band band,
|
||||
bool no_cck)
|
||||
@ -981,6 +970,7 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
mvm->fw->ucode_capa.n_scan_channels);
|
||||
u32 ssid_bitmap = 0;
|
||||
int i;
|
||||
u8 band;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
@ -1000,7 +990,8 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
cmd->scan_flags = cpu_to_le32(iwl_mvm_scan_lmac_flags(mvm, params,
|
||||
vif));
|
||||
|
||||
cmd->flags = iwl_mvm_scan_rxon_flags(params->channels[0]->band);
|
||||
band = iwl_mvm_phy_band_from_nl80211(params->channels[0]->band);
|
||||
cmd->flags = cpu_to_le32(band);
|
||||
cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP |
|
||||
MAC_FILTER_IN_BEACON);
|
||||
iwl_mvm_scan_fill_tx_cmd(mvm, cmd->tx_cmd, params->no_cck);
|
||||
@ -1426,9 +1417,10 @@ iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm,
|
||||
channel_cfg[i].flags = cpu_to_le32(ssid_bitmap);
|
||||
channel_cfg[i].v1.channel_num = channels[i]->hw_value;
|
||||
if (iwl_mvm_is_scan_ext_chan_supported(mvm)) {
|
||||
enum nl80211_band band = channels[i]->band;
|
||||
|
||||
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;
|
||||
iwl_mvm_phy_band_from_nl80211(band);
|
||||
channel_cfg[i].v2.iter_count = 1;
|
||||
channel_cfg[i].v2.iter_interval = 0;
|
||||
} else {
|
||||
|
@ -734,6 +734,11 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* When the firmware supports the session protection API,
|
||||
* this is not needed since it'll automatically remove the
|
||||
* session protection after association + beacon reception.
|
||||
*/
|
||||
void iwl_mvm_stop_session_protection(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
@ -757,6 +762,101 @@ void iwl_mvm_stop_session_protection(struct iwl_mvm *mvm,
|
||||
iwl_mvm_remove_time_event(mvm, mvmvif, te_data);
|
||||
}
|
||||
|
||||
void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_mvm_session_prot_notif *notif = (void *)pkt->data;
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
rcu_read_lock();
|
||||
vif = iwl_mvm_rcu_dereference_vif_id(mvm, le32_to_cpu(notif->mac_id),
|
||||
true);
|
||||
|
||||
if (!vif)
|
||||
goto out_unlock;
|
||||
|
||||
/* The vif is not a P2P_DEVICE, maintain its time_event_data */
|
||||
if (vif->type != NL80211_IFTYPE_P2P_DEVICE) {
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm_time_event_data *te_data =
|
||||
&mvmvif->time_event_data;
|
||||
|
||||
if (!le32_to_cpu(notif->status)) {
|
||||
iwl_mvm_te_check_disconnect(mvm, vif,
|
||||
"Session protection failure");
|
||||
iwl_mvm_te_clear_data(mvm, te_data);
|
||||
}
|
||||
|
||||
if (le32_to_cpu(notif->start)) {
|
||||
spin_lock_bh(&mvm->time_event_lock);
|
||||
te_data->running = le32_to_cpu(notif->start);
|
||||
te_data->end_jiffies =
|
||||
TU_TO_EXP_TIME(te_data->duration);
|
||||
spin_unlock_bh(&mvm->time_event_lock);
|
||||
} else {
|
||||
/*
|
||||
* By now, we should have finished association
|
||||
* and know the dtim period.
|
||||
*/
|
||||
iwl_mvm_te_check_disconnect(mvm, vif,
|
||||
"No beacon heard and the session protection is over already...");
|
||||
iwl_mvm_te_clear_data(mvm, te_data);
|
||||
}
|
||||
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (!le32_to_cpu(notif->status) || !le32_to_cpu(notif->start)) {
|
||||
/* End TE, notify mac80211 */
|
||||
ieee80211_remain_on_channel_expired(mvm->hw);
|
||||
set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status);
|
||||
iwl_mvm_roc_finished(mvm);
|
||||
} else if (le32_to_cpu(notif->start)) {
|
||||
set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
|
||||
ieee80211_ready_on_channel(mvm->hw); /* Start TE */
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_mvm_start_p2p_roc_session_protection(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
int duration,
|
||||
enum ieee80211_roc_type type)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm_session_prot_cmd cmd = {
|
||||
.id_and_color =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
|
||||
mvmvif->color)),
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
|
||||
.duration_tu = cpu_to_le32(MSEC_TO_TU(duration)),
|
||||
};
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
switch (type) {
|
||||
case IEEE80211_ROC_TYPE_NORMAL:
|
||||
cmd.conf_id =
|
||||
cpu_to_le32(SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV);
|
||||
break;
|
||||
case IEEE80211_ROC_TYPE_MGMT_TX:
|
||||
cmd.conf_id =
|
||||
cpu_to_le32(SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION);
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(1, "Got an invalid ROC type\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD,
|
||||
MAC_CONF_GROUP, 0),
|
||||
0, sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
int duration, enum ieee80211_roc_type type)
|
||||
{
|
||||
@ -770,6 +870,12 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
|
||||
return iwl_mvm_start_p2p_roc_session_protection(mvm, vif,
|
||||
duration,
|
||||
type);
|
||||
|
||||
time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
|
||||
time_cmd.id_and_color =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
|
||||
@ -847,11 +953,44 @@ void iwl_mvm_cleanup_roc_te(struct iwl_mvm *mvm)
|
||||
__iwl_mvm_remove_time_event(mvm, te_data, &uid);
|
||||
}
|
||||
|
||||
void iwl_mvm_stop_roc(struct iwl_mvm *mvm)
|
||||
static void iwl_mvm_cancel_session_protection(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_vif *mvmvif)
|
||||
{
|
||||
struct iwl_mvm_session_prot_cmd cmd = {
|
||||
.id_and_color =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
|
||||
mvmvif->color)),
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD,
|
||||
MAC_CONF_GROUP, 0),
|
||||
0, sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
IWL_ERR(mvm,
|
||||
"Couldn't send the SESSION_PROTECTION_CMD: %d\n", ret);
|
||||
}
|
||||
|
||||
void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif;
|
||||
struct iwl_mvm_time_event_data *te_data;
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) {
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
iwl_mvm_cancel_session_protection(mvm, mvmvif);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
|
||||
set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status);
|
||||
|
||||
iwl_mvm_roc_finished(mvm);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
te_data = iwl_mvm_get_roc_te(mvm);
|
||||
if (!te_data) {
|
||||
IWL_WARN(mvm, "No remain on channel event\n");
|
||||
@ -916,3 +1055,51 @@ int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm,
|
||||
|
||||
return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
|
||||
}
|
||||
|
||||
void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 duration, u32 min_duration)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
|
||||
|
||||
struct iwl_mvm_session_prot_cmd cmd = {
|
||||
.id_and_color =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
|
||||
mvmvif->color)),
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
|
||||
.conf_id = cpu_to_le32(SESSION_PROTECT_CONF_ASSOC),
|
||||
.duration_tu = cpu_to_le32(MSEC_TO_TU(duration)),
|
||||
};
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
spin_lock_bh(&mvm->time_event_lock);
|
||||
if (te_data->running &&
|
||||
time_after(te_data->end_jiffies, TU_TO_EXP_TIME(min_duration))) {
|
||||
IWL_DEBUG_TE(mvm, "We have enough time in the current TE: %u\n",
|
||||
jiffies_to_msecs(te_data->end_jiffies - jiffies));
|
||||
spin_unlock_bh(&mvm->time_event_lock);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
iwl_mvm_te_clear_data(mvm, te_data);
|
||||
te_data->duration = le32_to_cpu(cmd.duration_tu);
|
||||
spin_unlock_bh(&mvm->time_event_lock);
|
||||
|
||||
IWL_DEBUG_TE(mvm, "Add new session protection, duration %d TU\n",
|
||||
le32_to_cpu(cmd.duration_tu));
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD,
|
||||
MAC_CONF_GROUP, 0),
|
||||
0, sizeof(cmd), &cmd);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm,
|
||||
"Couldn't send the SESSION_PROTECTION_CMD: %d\n", ret);
|
||||
spin_lock_bh(&mvm->time_event_lock);
|
||||
iwl_mvm_te_clear_data(mvm, te_data);
|
||||
spin_unlock_bh(&mvm->time_event_lock);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2019 Intel Corporation
|
||||
*
|
||||
* 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
|
||||
@ -28,6 +29,7 @@
|
||||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2019 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -178,12 +180,13 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
/**
|
||||
* iwl_mvm_stop_roc - stop remain on channel functionality
|
||||
* @mvm: the mvm component
|
||||
* @vif: the virtual interface for which the roc is stopped
|
||||
*
|
||||
* This function can be used to cancel an ongoing ROC session.
|
||||
* The function is async, it will instruct the FW to stop serving the ROC
|
||||
* session, but will not wait for the actual stopping of the session.
|
||||
*/
|
||||
void iwl_mvm_stop_roc(struct iwl_mvm *mvm);
|
||||
void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
* iwl_mvm_remove_time_event - general function to clean up of time event
|
||||
@ -242,4 +245,20 @@ iwl_mvm_te_scheduled(struct iwl_mvm_time_event_data *te_data)
|
||||
return !!te_data->uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_mvm_schedule_session_protection - schedule a session protection
|
||||
* @mvm: the mvm component
|
||||
* @vif: the virtual interface for which the protection issued
|
||||
* @duration: the duration of the protection
|
||||
*/
|
||||
void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 duration, u32 min_duration);
|
||||
|
||||
/**
|
||||
* iwl_mvm_rx_session_protect_notif - handles %SESSION_PROTECTION_NOTIF
|
||||
*/
|
||||
void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
|
||||
#endif /* __time_event_h__ */
|
||||
|
@ -341,8 +341,11 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
|
||||
rate_idx = rate_lowest_index(
|
||||
&mvm->nvm_data->bands[info->band], sta);
|
||||
|
||||
/* For 5 GHZ band, remap mac80211 rate indices into driver indices */
|
||||
if (info->band == NL80211_BAND_5GHZ)
|
||||
/*
|
||||
* For non 2 GHZ band, remap mac80211 rate
|
||||
* indices into driver indices
|
||||
*/
|
||||
if (info->band != NL80211_BAND_2GHZ)
|
||||
rate_idx += IWL_FIRST_OFDM_RATE;
|
||||
|
||||
/* For 2.4 GHZ band, check that there is no need to remap */
|
||||
@ -935,7 +938,12 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
!(mvmsta->amsdu_enabled & BIT(tid)))
|
||||
return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb);
|
||||
|
||||
max_amsdu_len = iwl_mvm_max_amsdu_size(mvm, sta, tid);
|
||||
/*
|
||||
* Take the min of ieee80211 station and mvm station
|
||||
*/
|
||||
max_amsdu_len =
|
||||
min_t(unsigned int, sta->max_amsdu_len,
|
||||
iwl_mvm_max_amsdu_size(mvm, sta, tid));
|
||||
|
||||
/*
|
||||
* Limit A-MSDU in A-MPDU to 4095 bytes when VHT is not
|
||||
|
@ -217,7 +217,7 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
|
||||
int band_offset = 0;
|
||||
|
||||
/* Legacy rate format, search for match in table */
|
||||
if (band == NL80211_BAND_5GHZ)
|
||||
if (band != NL80211_BAND_2GHZ)
|
||||
band_offset = IWL_FIRST_OFDM_RATE;
|
||||
for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++)
|
||||
if (fw_rate_idx_to_plcp[idx] == rate)
|
||||
|
@ -55,6 +55,66 @@
|
||||
#include "internal.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
static void
|
||||
iwl_pcie_ctxt_info_dbg_enable(struct iwl_trans *trans,
|
||||
struct iwl_prph_scratch_hwm_cfg *dbg_cfg,
|
||||
u32 *control_flags)
|
||||
{
|
||||
enum iwl_fw_ini_allocation_id alloc_id = IWL_FW_INI_ALLOCATION_ID_DBGC1;
|
||||
struct iwl_fw_ini_allocation_tlv *fw_mon_cfg;
|
||||
u32 dbg_flags = 0;
|
||||
|
||||
if (!iwl_trans_dbg_ini_valid(trans)) {
|
||||
struct iwl_dram_data *fw_mon = &trans->dbg.fw_mon;
|
||||
|
||||
iwl_pcie_alloc_fw_monitor(trans, 0);
|
||||
|
||||
if (fw_mon->size) {
|
||||
dbg_flags |= IWL_PRPH_SCRATCH_EDBG_DEST_DRAM;
|
||||
|
||||
IWL_DEBUG_FW(trans,
|
||||
"WRT: Applying DRAM buffer destination\n");
|
||||
|
||||
dbg_cfg->hwm_base_addr = cpu_to_le64(fw_mon->physical);
|
||||
dbg_cfg->hwm_size = cpu_to_le32(fw_mon->size);
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
fw_mon_cfg = &trans->dbg.fw_mon_cfg[alloc_id];
|
||||
|
||||
if (le32_to_cpu(fw_mon_cfg->buf_location) ==
|
||||
IWL_FW_INI_LOCATION_SRAM_PATH) {
|
||||
dbg_flags |= IWL_PRPH_SCRATCH_EDBG_DEST_INTERNAL;
|
||||
|
||||
IWL_DEBUG_FW(trans,
|
||||
"WRT: Applying SMEM buffer destination\n");
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(fw_mon_cfg->buf_location) ==
|
||||
IWL_FW_INI_LOCATION_DRAM_PATH &&
|
||||
trans->dbg.fw_mon_ini[alloc_id].num_frags) {
|
||||
struct iwl_dram_data *frag =
|
||||
&trans->dbg.fw_mon_ini[alloc_id].frags[0];
|
||||
|
||||
dbg_flags |= IWL_PRPH_SCRATCH_EDBG_DEST_DRAM;
|
||||
|
||||
IWL_DEBUG_FW(trans,
|
||||
"WRT: Applying DRAM destination (alloc_id=%u)\n",
|
||||
alloc_id);
|
||||
|
||||
dbg_cfg->hwm_base_addr = cpu_to_le64(frag->physical);
|
||||
dbg_cfg->hwm_size = cpu_to_le32(frag->size);
|
||||
}
|
||||
|
||||
out:
|
||||
if (dbg_flags)
|
||||
*control_flags |= IWL_PRPH_SCRATCH_EARLY_DEBUG_EN | dbg_flags;
|
||||
}
|
||||
|
||||
int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
|
||||
const struct fw_img *fw)
|
||||
{
|
||||
@ -86,24 +146,15 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
|
||||
control_flags = IWL_PRPH_SCRATCH_RB_SIZE_4K |
|
||||
IWL_PRPH_SCRATCH_MTR_MODE |
|
||||
(IWL_PRPH_MTR_FORMAT_256B &
|
||||
IWL_PRPH_SCRATCH_MTR_FORMAT) |
|
||||
IWL_PRPH_SCRATCH_EARLY_DEBUG_EN |
|
||||
IWL_PRPH_SCRATCH_EDBG_DEST_DRAM;
|
||||
prph_sc_ctrl->control.control_flags = cpu_to_le32(control_flags);
|
||||
IWL_PRPH_SCRATCH_MTR_FORMAT);
|
||||
|
||||
/* initialize RX default queue */
|
||||
prph_sc_ctrl->rbd_cfg.free_rbd_addr =
|
||||
cpu_to_le64(trans_pcie->rxq->bd_dma);
|
||||
|
||||
/* Configure debug, for integration */
|
||||
if (!iwl_trans_dbg_ini_valid(trans))
|
||||
iwl_pcie_alloc_fw_monitor(trans, 0);
|
||||
if (trans->dbg.num_blocks) {
|
||||
prph_sc_ctrl->hwm_cfg.hwm_base_addr =
|
||||
cpu_to_le64(trans->dbg.fw_mon[0].physical);
|
||||
prph_sc_ctrl->hwm_cfg.hwm_size =
|
||||
cpu_to_le32(trans->dbg.fw_mon[0].size);
|
||||
}
|
||||
iwl_pcie_ctxt_info_dbg_enable(trans, &prph_sc_ctrl->hwm_cfg,
|
||||
&control_flags);
|
||||
prph_sc_ctrl->control.control_flags = cpu_to_le32(control_flags);
|
||||
|
||||
/* allocate ucode sections in dram and set addresses */
|
||||
ret = iwl_pcie_init_fw_sec(trans, fw, &prph_scratch->dram);
|
||||
|
@ -190,32 +190,36 @@ static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans)
|
||||
|
||||
static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
|
||||
{
|
||||
int i;
|
||||
struct iwl_dram_data *fw_mon = &trans->dbg.fw_mon;
|
||||
|
||||
for (i = 0; i < trans->dbg.num_blocks; i++) {
|
||||
dma_free_coherent(trans->dev, trans->dbg.fw_mon[i].size,
|
||||
trans->dbg.fw_mon[i].block,
|
||||
trans->dbg.fw_mon[i].physical);
|
||||
trans->dbg.fw_mon[i].block = NULL;
|
||||
trans->dbg.fw_mon[i].physical = 0;
|
||||
trans->dbg.fw_mon[i].size = 0;
|
||||
trans->dbg.num_blocks--;
|
||||
}
|
||||
if (!fw_mon->size)
|
||||
return;
|
||||
|
||||
dma_free_coherent(trans->dev, fw_mon->size, fw_mon->block,
|
||||
fw_mon->physical);
|
||||
|
||||
fw_mon->block = NULL;
|
||||
fw_mon->physical = 0;
|
||||
fw_mon->size = 0;
|
||||
}
|
||||
|
||||
static void iwl_pcie_alloc_fw_monitor_block(struct iwl_trans *trans,
|
||||
u8 max_power, u8 min_power)
|
||||
{
|
||||
void *cpu_addr = NULL;
|
||||
dma_addr_t phys = 0;
|
||||
struct iwl_dram_data *fw_mon = &trans->dbg.fw_mon;
|
||||
void *block = NULL;
|
||||
dma_addr_t physical = 0;
|
||||
u32 size = 0;
|
||||
u8 power;
|
||||
|
||||
if (fw_mon->size)
|
||||
return;
|
||||
|
||||
for (power = max_power; power >= min_power; power--) {
|
||||
size = BIT(power);
|
||||
cpu_addr = dma_alloc_coherent(trans->dev, size, &phys,
|
||||
GFP_KERNEL | __GFP_NOWARN);
|
||||
if (!cpu_addr)
|
||||
block = dma_alloc_coherent(trans->dev, size, &physical,
|
||||
GFP_KERNEL | __GFP_NOWARN);
|
||||
if (!block)
|
||||
continue;
|
||||
|
||||
IWL_INFO(trans,
|
||||
@ -224,7 +228,7 @@ static void iwl_pcie_alloc_fw_monitor_block(struct iwl_trans *trans,
|
||||
break;
|
||||
}
|
||||
|
||||
if (WARN_ON_ONCE(!cpu_addr))
|
||||
if (WARN_ON_ONCE(!block))
|
||||
return;
|
||||
|
||||
if (power != max_power)
|
||||
@ -233,10 +237,9 @@ static void iwl_pcie_alloc_fw_monitor_block(struct iwl_trans *trans,
|
||||
(unsigned long)BIT(power - 10),
|
||||
(unsigned long)BIT(max_power - 10));
|
||||
|
||||
trans->dbg.fw_mon[trans->dbg.num_blocks].block = cpu_addr;
|
||||
trans->dbg.fw_mon[trans->dbg.num_blocks].physical = phys;
|
||||
trans->dbg.fw_mon[trans->dbg.num_blocks].size = size;
|
||||
trans->dbg.num_blocks++;
|
||||
fw_mon->block = block;
|
||||
fw_mon->physical = physical;
|
||||
fw_mon->size = size;
|
||||
}
|
||||
|
||||
void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power)
|
||||
@ -253,11 +256,7 @@ void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power)
|
||||
max_power))
|
||||
return;
|
||||
|
||||
/*
|
||||
* This function allocats the default fw monitor.
|
||||
* The optional additional ones will be allocated in runtime
|
||||
*/
|
||||
if (trans->dbg.num_blocks)
|
||||
if (trans->dbg.fw_mon.size)
|
||||
return;
|
||||
|
||||
iwl_pcie_alloc_fw_monitor_block(trans, max_power, 11);
|
||||
@ -891,24 +890,51 @@ static int iwl_pcie_load_cpu_sections(struct iwl_trans *trans,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_pcie_apply_destination_ini(struct iwl_trans *trans)
|
||||
{
|
||||
enum iwl_fw_ini_allocation_id alloc_id = IWL_FW_INI_ALLOCATION_ID_DBGC1;
|
||||
struct iwl_fw_ini_allocation_tlv *fw_mon_cfg =
|
||||
&trans->dbg.fw_mon_cfg[alloc_id];
|
||||
struct iwl_dram_data *frag;
|
||||
|
||||
if (!iwl_trans_dbg_ini_valid(trans))
|
||||
return;
|
||||
|
||||
if (le32_to_cpu(fw_mon_cfg->buf_location) ==
|
||||
IWL_FW_INI_LOCATION_SRAM_PATH) {
|
||||
IWL_DEBUG_FW(trans, "WRT: Applying SMEM buffer destination\n");
|
||||
/* set sram monitor by enabling bit 7 */
|
||||
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(fw_mon_cfg->buf_location) !=
|
||||
IWL_FW_INI_LOCATION_DRAM_PATH ||
|
||||
!trans->dbg.fw_mon_ini[alloc_id].num_frags)
|
||||
return;
|
||||
|
||||
frag = &trans->dbg.fw_mon_ini[alloc_id].frags[0];
|
||||
|
||||
IWL_DEBUG_FW(trans, "WRT: Applying DRAM destination (alloc_id=%u)\n",
|
||||
alloc_id);
|
||||
|
||||
iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2,
|
||||
frag->physical >> MON_BUFF_SHIFT_VER2);
|
||||
iwl_write_umac_prph(trans, MON_BUFF_END_ADDR_VER2,
|
||||
(frag->physical + frag->size - 256) >>
|
||||
MON_BUFF_SHIFT_VER2);
|
||||
}
|
||||
|
||||
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_dram_data *fw_mon = &trans->dbg.fw_mon;
|
||||
int i;
|
||||
|
||||
if (iwl_trans_dbg_ini_valid(trans)) {
|
||||
if (!trans->dbg.num_blocks)
|
||||
return;
|
||||
|
||||
IWL_DEBUG_FW(trans,
|
||||
"WRT: Applying DRAM buffer[0] destination\n");
|
||||
iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2,
|
||||
trans->dbg.fw_mon[0].physical >>
|
||||
MON_BUFF_SHIFT_VER2);
|
||||
iwl_write_umac_prph(trans, MON_BUFF_END_ADDR_VER2,
|
||||
(trans->dbg.fw_mon[0].physical +
|
||||
trans->dbg.fw_mon[0].size - 256) >>
|
||||
MON_BUFF_SHIFT_VER2);
|
||||
iwl_pcie_apply_destination_ini(trans);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -959,20 +985,17 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans)
|
||||
}
|
||||
|
||||
monitor:
|
||||
if (dest->monitor_mode == EXTERNAL_MODE && trans->dbg.fw_mon[0].size) {
|
||||
if (dest->monitor_mode == EXTERNAL_MODE && fw_mon->size) {
|
||||
iwl_write_prph(trans, le32_to_cpu(dest->base_reg),
|
||||
trans->dbg.fw_mon[0].physical >>
|
||||
dest->base_shift);
|
||||
fw_mon->physical >> dest->base_shift);
|
||||
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_8000)
|
||||
iwl_write_prph(trans, le32_to_cpu(dest->end_reg),
|
||||
(trans->dbg.fw_mon[0].physical +
|
||||
trans->dbg.fw_mon[0].size - 256) >>
|
||||
dest->end_shift);
|
||||
(fw_mon->physical + fw_mon->size -
|
||||
256) >> dest->end_shift);
|
||||
else
|
||||
iwl_write_prph(trans, le32_to_cpu(dest->end_reg),
|
||||
(trans->dbg.fw_mon[0].physical +
|
||||
trans->dbg.fw_mon[0].size) >>
|
||||
dest->end_shift);
|
||||
(fw_mon->physical + fw_mon->size) >>
|
||||
dest->end_shift);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1006,14 +1029,14 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
|
||||
/* supported for 7000 only for the moment */
|
||||
if (iwlwifi_mod_params.fw_monitor &&
|
||||
trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
iwl_pcie_alloc_fw_monitor(trans, 0);
|
||||
struct iwl_dram_data *fw_mon = &trans->dbg.fw_mon;
|
||||
|
||||
if (trans->dbg.fw_mon[0].size) {
|
||||
iwl_pcie_alloc_fw_monitor(trans, 0);
|
||||
if (fw_mon->size) {
|
||||
iwl_write_prph(trans, MON_BUFF_BASE_ADDR,
|
||||
trans->dbg.fw_mon[0].physical >> 4);
|
||||
fw_mon->physical >> 4);
|
||||
iwl_write_prph(trans, MON_BUFF_END_ADDR,
|
||||
(trans->dbg.fw_mon[0].physical +
|
||||
trans->dbg.fw_mon[0].size) >> 4);
|
||||
(fw_mon->physical + fw_mon->size) >> 4);
|
||||
}
|
||||
} else if (iwl_pcie_dbg_on(trans)) {
|
||||
iwl_pcie_apply_destination(trans);
|
||||
@ -2801,7 +2824,7 @@ static ssize_t iwl_dbgfs_monitor_data_read(struct file *file,
|
||||
{
|
||||
struct iwl_trans *trans = file->private_data;
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
void *cpu_addr = (void *)trans->dbg.fw_mon[0].block, *curr_buf;
|
||||
void *cpu_addr = (void *)trans->dbg.fw_mon.block, *curr_buf;
|
||||
struct cont_rec *data = &trans_pcie->fw_mon_data;
|
||||
u32 write_ptr_addr, wrap_cnt_addr, write_ptr, wrap_cnt;
|
||||
ssize_t size, bytes_copied = 0;
|
||||
@ -2840,7 +2863,7 @@ static ssize_t iwl_dbgfs_monitor_data_read(struct file *file,
|
||||
|
||||
} else if (data->prev_wrap_cnt == wrap_cnt - 1 &&
|
||||
write_ptr < data->prev_wr_ptr) {
|
||||
size = trans->dbg.fw_mon[0].size - data->prev_wr_ptr;
|
||||
size = trans->dbg.fw_mon.size - data->prev_wr_ptr;
|
||||
curr_buf = cpu_addr + data->prev_wr_ptr;
|
||||
b_full = iwl_write_to_user_buf(user_buf, count,
|
||||
curr_buf, &size,
|
||||
@ -3087,10 +3110,11 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans,
|
||||
struct iwl_fw_error_dump_data **data,
|
||||
u32 monitor_len)
|
||||
{
|
||||
struct iwl_dram_data *fw_mon = &trans->dbg.fw_mon;
|
||||
u32 len = 0;
|
||||
|
||||
if (trans->dbg.dest_tlv ||
|
||||
(trans->dbg.num_blocks &&
|
||||
(fw_mon->size &&
|
||||
(trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000 ||
|
||||
trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210))) {
|
||||
struct iwl_fw_error_dump_fw_mon *fw_mon_data;
|
||||
@ -3101,12 +3125,9 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans,
|
||||
iwl_trans_pcie_dump_pointers(trans, fw_mon_data);
|
||||
|
||||
len += sizeof(**data) + sizeof(*fw_mon_data);
|
||||
if (trans->dbg.num_blocks) {
|
||||
memcpy(fw_mon_data->data,
|
||||
trans->dbg.fw_mon[0].block,
|
||||
trans->dbg.fw_mon[0].size);
|
||||
|
||||
monitor_len = trans->dbg.fw_mon[0].size;
|
||||
if (fw_mon->size) {
|
||||
memcpy(fw_mon_data->data, fw_mon->block, fw_mon->size);
|
||||
monitor_len = fw_mon->size;
|
||||
} else if (trans->dbg.dest_tlv->monitor_mode == SMEM_MODE) {
|
||||
u32 base = le32_to_cpu(fw_mon_data->fw_mon_base_ptr);
|
||||
/*
|
||||
@ -3145,11 +3166,11 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans,
|
||||
|
||||
static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, u32 *len)
|
||||
{
|
||||
if (trans->dbg.num_blocks) {
|
||||
if (trans->dbg.fw_mon.size) {
|
||||
*len += sizeof(struct iwl_fw_error_dump_data) +
|
||||
sizeof(struct iwl_fw_error_dump_fw_mon) +
|
||||
trans->dbg.fw_mon[0].size;
|
||||
return trans->dbg.fw_mon[0].size;
|
||||
trans->dbg.fw_mon.size;
|
||||
return trans->dbg.fw_mon.size;
|
||||
} else if (trans->dbg.dest_tlv) {
|
||||
u32 base, end, cfg_reg, monitor_len;
|
||||
|
||||
@ -3604,6 +3625,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
mutex_init(&trans_pcie->fw_mon_data.mutex);
|
||||
#endif
|
||||
|
||||
iwl_dbg_tlv_init(trans);
|
||||
|
||||
return trans;
|
||||
|
||||
out_free_ict:
|
||||
|
@ -1179,6 +1179,10 @@ static int if_sdio_probe(struct sdio_func *func,
|
||||
|
||||
spin_lock_init(&card->lock);
|
||||
card->workqueue = alloc_workqueue("libertas_sdio", WQ_MEM_RECLAIM, 0);
|
||||
if (unlikely(!card->workqueue)) {
|
||||
ret = -ENOMEM;
|
||||
goto err_queue;
|
||||
}
|
||||
INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker);
|
||||
init_waitqueue_head(&card->pwron_waitq);
|
||||
|
||||
@ -1230,6 +1234,7 @@ err_activate_card:
|
||||
lbs_remove_card(priv);
|
||||
free:
|
||||
destroy_workqueue(card->workqueue);
|
||||
err_queue:
|
||||
while (card->packets) {
|
||||
packet = card->packets;
|
||||
card->packets = card->packets->next;
|
||||
|
@ -1003,7 +1003,6 @@ static int lbs_add_mesh(struct lbs_private *priv)
|
||||
if (priv->mesh_tlv) {
|
||||
sprintf(mesh_wdev->ssid, "mesh");
|
||||
mesh_wdev->mesh_id_up_len = 4;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
mesh_wdev->netdev = mesh_dev;
|
||||
|
@ -687,8 +687,11 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
|
||||
skb_put(skb, MAX_EVENT_SIZE);
|
||||
|
||||
if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE,
|
||||
PCI_DMA_FROMDEVICE))
|
||||
PCI_DMA_FROMDEVICE)) {
|
||||
kfree_skb(skb);
|
||||
kfree(card->evtbd_ring_vbase);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
|
||||
|
||||
@ -1029,8 +1032,10 @@ static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter)
|
||||
}
|
||||
skb_put(skb, MWIFIEX_UPLD_SIZE);
|
||||
if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
|
||||
PCI_DMA_FROMDEVICE))
|
||||
PCI_DMA_FROMDEVICE)) {
|
||||
kfree_skb(skb);
|
||||
return -1;
|
||||
}
|
||||
|
||||
card->cmdrsp_buf = skb;
|
||||
|
||||
|
@ -1270,7 +1270,7 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
|
||||
break;
|
||||
|
||||
case WLAN_EID_FH_PARAMS:
|
||||
if (element_len + 2 < sizeof(*fh_param_set))
|
||||
if (total_ie_len < sizeof(*fh_param_set))
|
||||
return -EINVAL;
|
||||
fh_param_set =
|
||||
(struct ieee_types_fh_param_set *) current_ptr;
|
||||
@ -1280,7 +1280,7 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
|
||||
break;
|
||||
|
||||
case WLAN_EID_DS_PARAMS:
|
||||
if (element_len + 2 < sizeof(*ds_param_set))
|
||||
if (total_ie_len < sizeof(*ds_param_set))
|
||||
return -EINVAL;
|
||||
ds_param_set =
|
||||
(struct ieee_types_ds_param_set *) current_ptr;
|
||||
@ -1293,7 +1293,7 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
|
||||
break;
|
||||
|
||||
case WLAN_EID_CF_PARAMS:
|
||||
if (element_len + 2 < sizeof(*cf_param_set))
|
||||
if (total_ie_len < sizeof(*cf_param_set))
|
||||
return -EINVAL;
|
||||
cf_param_set =
|
||||
(struct ieee_types_cf_param_set *) current_ptr;
|
||||
@ -1303,7 +1303,7 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
|
||||
break;
|
||||
|
||||
case WLAN_EID_IBSS_PARAMS:
|
||||
if (element_len + 2 < sizeof(*ibss_param_set))
|
||||
if (total_ie_len < sizeof(*ibss_param_set))
|
||||
return -EINVAL;
|
||||
ibss_param_set =
|
||||
(struct ieee_types_ibss_param_set *)
|
||||
@ -1460,10 +1460,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
|
||||
break;
|
||||
}
|
||||
|
||||
current_ptr += element_len + 2;
|
||||
|
||||
/* Need to account for IE ID and IE Len */
|
||||
bytes_left -= (element_len + 2);
|
||||
current_ptr += total_ie_len;
|
||||
bytes_left -= total_ie_len;
|
||||
|
||||
} /* while (bytes_left > 2) */
|
||||
return ret;
|
||||
|
@ -77,10 +77,7 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx,
|
||||
for (i = 0; i < ARRAY_SIZE(dev->beacons); i++) {
|
||||
if (vif_idx == i) {
|
||||
force_update = !!dev->beacons[i] ^ !!skb;
|
||||
|
||||
if (dev->beacons[i])
|
||||
dev_kfree_skb(dev->beacons[i]);
|
||||
|
||||
dev_kfree_skb(dev->beacons[i]);
|
||||
dev->beacons[i] = skb;
|
||||
__mt76x02_mac_set_beacon(dev, bcn_idx, skb);
|
||||
} else if (force_update && dev->beacons[i]) {
|
||||
|
@ -27,7 +27,7 @@ mt76_reg_get(void *data, u64 *val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(fops_regval, mt76_reg_get, mt76_reg_set, "0x%08llx\n");
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt76_reg_get, mt76_reg_set, "0x%08llx\n");
|
||||
|
||||
static int
|
||||
mt7601u_ampdu_stat_read(struct seq_file *file, void *data)
|
||||
|
@ -213,7 +213,7 @@ int mt7601u_wait_bbp_ready(struct mt7601u_dev *dev)
|
||||
|
||||
do {
|
||||
val = mt7601u_bbp_rr(dev, MT_BBP_REG_VERSION);
|
||||
if (val && ~val)
|
||||
if (val && val != 0xff)
|
||||
break;
|
||||
} while (--i);
|
||||
|
||||
|
@ -244,8 +244,6 @@ static int pearl_alloc_bd_table(struct qtnf_pcie_pearl_state *ps)
|
||||
|
||||
/* tx bd */
|
||||
|
||||
memset(vaddr, 0, len);
|
||||
|
||||
ps->bd_table_vaddr = vaddr;
|
||||
ps->bd_table_paddr = paddr;
|
||||
ps->bd_table_len = len;
|
||||
|
@ -199,8 +199,6 @@ static int topaz_alloc_bd_table(struct qtnf_pcie_topaz_state *ts,
|
||||
if (!vaddr)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(vaddr, 0, len);
|
||||
|
||||
/* tx bd */
|
||||
|
||||
ts->tx_bd_vbase = vaddr;
|
||||
|
@ -1187,6 +1187,79 @@ struct rtl8723bu_c2h {
|
||||
|
||||
struct rtl8xxxu_fileops;
|
||||
|
||||
/*mlme related.*/
|
||||
enum wireless_mode {
|
||||
WIRELESS_MODE_UNKNOWN = 0,
|
||||
/* Sub-Element */
|
||||
WIRELESS_MODE_B = BIT(0),
|
||||
WIRELESS_MODE_G = BIT(1),
|
||||
WIRELESS_MODE_A = BIT(2),
|
||||
WIRELESS_MODE_N_24G = BIT(3),
|
||||
WIRELESS_MODE_N_5G = BIT(4),
|
||||
WIRELESS_AUTO = BIT(5),
|
||||
WIRELESS_MODE_AC = BIT(6),
|
||||
WIRELESS_MODE_MAX = 0x7F,
|
||||
};
|
||||
|
||||
/* from rtlwifi/wifi.h */
|
||||
enum ratr_table_mode_new {
|
||||
RATEID_IDX_BGN_40M_2SS = 0,
|
||||
RATEID_IDX_BGN_40M_1SS = 1,
|
||||
RATEID_IDX_BGN_20M_2SS_BN = 2,
|
||||
RATEID_IDX_BGN_20M_1SS_BN = 3,
|
||||
RATEID_IDX_GN_N2SS = 4,
|
||||
RATEID_IDX_GN_N1SS = 5,
|
||||
RATEID_IDX_BG = 6,
|
||||
RATEID_IDX_G = 7,
|
||||
RATEID_IDX_B = 8,
|
||||
RATEID_IDX_VHT_2SS = 9,
|
||||
RATEID_IDX_VHT_1SS = 10,
|
||||
RATEID_IDX_MIX1 = 11,
|
||||
RATEID_IDX_MIX2 = 12,
|
||||
RATEID_IDX_VHT_3SS = 13,
|
||||
RATEID_IDX_BGN_3SS = 14,
|
||||
};
|
||||
|
||||
#define BT_INFO_8723B_1ANT_B_FTP BIT(7)
|
||||
#define BT_INFO_8723B_1ANT_B_A2DP BIT(6)
|
||||
#define BT_INFO_8723B_1ANT_B_HID BIT(5)
|
||||
#define BT_INFO_8723B_1ANT_B_SCO_BUSY BIT(4)
|
||||
#define BT_INFO_8723B_1ANT_B_ACL_BUSY BIT(3)
|
||||
#define BT_INFO_8723B_1ANT_B_INQ_PAGE BIT(2)
|
||||
#define BT_INFO_8723B_1ANT_B_SCO_ESCO BIT(1)
|
||||
#define BT_INFO_8723B_1ANT_B_CONNECTION BIT(0)
|
||||
|
||||
enum _BT_8723B_1ANT_STATUS {
|
||||
BT_8723B_1ANT_STATUS_NON_CONNECTED_IDLE = 0x0,
|
||||
BT_8723B_1ANT_STATUS_CONNECTED_IDLE = 0x1,
|
||||
BT_8723B_1ANT_STATUS_INQ_PAGE = 0x2,
|
||||
BT_8723B_1ANT_STATUS_ACL_BUSY = 0x3,
|
||||
BT_8723B_1ANT_STATUS_SCO_BUSY = 0x4,
|
||||
BT_8723B_1ANT_STATUS_ACL_SCO_BUSY = 0x5,
|
||||
BT_8723B_1ANT_STATUS_MAX
|
||||
};
|
||||
|
||||
struct rtl8xxxu_btcoex {
|
||||
u8 bt_status;
|
||||
bool bt_busy;
|
||||
bool has_sco;
|
||||
bool has_a2dp;
|
||||
bool has_hid;
|
||||
bool has_pan;
|
||||
bool hid_only;
|
||||
bool a2dp_only;
|
||||
bool c2h_bt_inquiry;
|
||||
};
|
||||
|
||||
#define RTL8XXXU_RATR_STA_INIT 0
|
||||
#define RTL8XXXU_RATR_STA_HIGH 1
|
||||
#define RTL8XXXU_RATR_STA_MID 2
|
||||
#define RTL8XXXU_RATR_STA_LOW 3
|
||||
|
||||
#define RTL8XXXU_NOISE_FLOOR_MIN -100
|
||||
#define RTL8XXXU_SNR_THRESH_HIGH 50
|
||||
#define RTL8XXXU_SNR_THRESH_LOW 20
|
||||
|
||||
struct rtl8xxxu_priv {
|
||||
struct ieee80211_hw *hw;
|
||||
struct usb_device *udev;
|
||||
@ -1291,6 +1364,17 @@ struct rtl8xxxu_priv {
|
||||
u8 pi_enabled:1;
|
||||
u8 no_pape:1;
|
||||
u8 int_buf[USB_INTR_CONTENT_LENGTH];
|
||||
u8 rssi_level;
|
||||
/*
|
||||
* Only one virtual interface permitted because only STA mode
|
||||
* is supported and no iface_combinations are provided.
|
||||
*/
|
||||
struct ieee80211_vif *vif;
|
||||
struct delayed_work ra_watchdog;
|
||||
struct work_struct c2hcmd_work;
|
||||
struct sk_buff_head c2hcmd_queue;
|
||||
spinlock_t c2hcmd_lock;
|
||||
struct rtl8xxxu_btcoex bt_coex;
|
||||
};
|
||||
|
||||
struct rtl8xxxu_rx_urb {
|
||||
@ -1326,7 +1410,7 @@ struct rtl8xxxu_fileops {
|
||||
void (*set_tx_power) (struct rtl8xxxu_priv *priv, int channel,
|
||||
bool ht40);
|
||||
void (*update_rate_mask) (struct rtl8xxxu_priv *priv,
|
||||
u32 ramask, int sgi);
|
||||
u32 ramask, u8 rateid, int sgi);
|
||||
void (*report_connect) (struct rtl8xxxu_priv *priv,
|
||||
u8 macid, bool connect);
|
||||
void (*fill_txdesc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
|
||||
@ -1341,6 +1425,7 @@ struct rtl8xxxu_fileops {
|
||||
u8 has_s0s1:1;
|
||||
u8 has_tx_report:1;
|
||||
u8 gen2_thermal_meter:1;
|
||||
u8 needs_full_init:1;
|
||||
u32 adda_1t_init;
|
||||
u32 adda_1t_path_on;
|
||||
u32 adda_2t_path_on_a;
|
||||
@ -1411,9 +1496,9 @@ void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw);
|
||||
void rtl8xxxu_gen1_usb_quirks(struct rtl8xxxu_priv *priv);
|
||||
void rtl8xxxu_gen2_usb_quirks(struct rtl8xxxu_priv *priv);
|
||||
void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv,
|
||||
u32 ramask, int sgi);
|
||||
u32 ramask, u8 rateid, int sgi);
|
||||
void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv,
|
||||
u32 ramask, int sgi);
|
||||
u32 ramask, u8 rateid, int sgi);
|
||||
void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv,
|
||||
u8 macid, bool connect);
|
||||
void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
|
||||
@ -1437,6 +1522,8 @@ void rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
|
||||
struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi,
|
||||
bool short_preamble, bool ampdu_enable,
|
||||
u32 rts_rate);
|
||||
void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv,
|
||||
u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5);
|
||||
|
||||
extern struct rtl8xxxu_fileops rtl8192cu_fops;
|
||||
extern struct rtl8xxxu_fileops rtl8192eu_fops;
|
||||
|
@ -1011,7 +1011,7 @@ static void rtl8192eu_phy_iqcalibrate(struct rtl8xxxu_priv *priv,
|
||||
u32 i, val32;
|
||||
int path_a_ok, path_b_ok;
|
||||
int retry = 2;
|
||||
const u32 adda_regs[RTL8XXXU_ADDA_REGS] = {
|
||||
static const u32 adda_regs[RTL8XXXU_ADDA_REGS] = {
|
||||
REG_FPGA0_XCD_SWITCH_CTRL, REG_BLUETOOTH,
|
||||
REG_RX_WAIT_CCA, REG_TX_CCK_RFON,
|
||||
REG_TX_CCK_BBON, REG_TX_OFDM_RFON,
|
||||
@ -1021,11 +1021,11 @@ static void rtl8192eu_phy_iqcalibrate(struct rtl8xxxu_priv *priv,
|
||||
REG_RX_TO_RX, REG_STANDBY,
|
||||
REG_SLEEP, REG_PMPD_ANAEN
|
||||
};
|
||||
const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = {
|
||||
static const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = {
|
||||
REG_TXPAUSE, REG_BEACON_CTRL,
|
||||
REG_BEACON_CTRL_1, REG_GPIO_MUXCFG
|
||||
};
|
||||
const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = {
|
||||
static const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = {
|
||||
REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR,
|
||||
REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B,
|
||||
REG_FPGA0_XAB_RF_SW_CTRL, REG_FPGA0_XA_RF_INT_OE,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user