You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'wireless-drivers-next-for-davem-2016-09-15' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Kalle Valo says: ==================== wireless-drivers-next patches for 4.9 Major changes: iwlwifi * preparation for new a000 HW continues * some DQA improvements * add support for GMAC * add support for 9460, 9270 and 9170 series mwifiex * support random MAC address for scanning * add HT aggregation support for adhoc mode * add custom regulatory domain support * add manufacturing mode support via nl80211 testmode interface bcma * support BCM53573 series of wireless SoCs bitfield.h * add FIELD_PREP() and FIELD_GET() macros mt7601u * convert to use the new bitfield.h macros brcmfmac * add support for bcm4339 chip with modalias sdio:c00v02D0d4339 ath10k * add nl80211 testmode support for 10.4 firmware * hide kernel addresses from logs using %pK format specifier * implement NAPI support * enable peer stats by default ath9k * use ieee80211_tx_status_noskb where possible wil6210 * extract firmware capabilities from the firmware file ath6kl * enable firmware crash dumps on the AR6004 ath-current is also merged to fix a conflict in ath10k. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -36,12 +36,31 @@ u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_chipco_get_alp_clock);
|
||||
|
||||
static bool bcma_core_cc_has_pmu_watchdog(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
|
||||
if (cc->capabilities & BCMA_CC_CAP_PMU) {
|
||||
if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53573) {
|
||||
WARN(bus->chipinfo.rev <= 1, "No watchdog available\n");
|
||||
/* 53573B0 and 53573B1 have bugged PMU watchdog. It can
|
||||
* be enabled but timer can't be bumped. Use CC one
|
||||
* instead.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
u32 nb;
|
||||
|
||||
if (cc->capabilities & BCMA_CC_CAP_PMU) {
|
||||
if (bcma_core_cc_has_pmu_watchdog(cc)) {
|
||||
if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
|
||||
nb = 32;
|
||||
else if (cc->core->id.rev < 26)
|
||||
@@ -95,9 +114,16 @@ static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc)
|
||||
|
||||
int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
struct bcm47xx_wdt wdt = {};
|
||||
struct platform_device *pdev;
|
||||
|
||||
if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53573 &&
|
||||
bus->chipinfo.rev <= 1) {
|
||||
pr_debug("No watchdog on 53573A0 / 53573A1\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
wdt.driver_data = cc;
|
||||
wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt;
|
||||
wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt;
|
||||
@@ -105,7 +131,7 @@ int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc)
|
||||
bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
|
||||
|
||||
pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
|
||||
cc->core->bus->num, &wdt,
|
||||
bus->num, &wdt,
|
||||
sizeof(wdt));
|
||||
if (IS_ERR(pdev))
|
||||
return PTR_ERR(pdev);
|
||||
@@ -217,7 +243,7 @@ u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
|
||||
u32 maxt;
|
||||
|
||||
maxt = bcma_chipco_watchdog_get_max_timer(cc);
|
||||
if (cc->capabilities & BCMA_CC_CAP_PMU) {
|
||||
if (bcma_core_cc_has_pmu_watchdog(cc)) {
|
||||
if (ticks == 1)
|
||||
ticks = 2;
|
||||
else if (ticks > maxt)
|
||||
|
||||
+4
-2
@@ -209,6 +209,8 @@ static void bcma_of_fill_device(struct platform_device *parent,
|
||||
core->dev.of_node = node;
|
||||
|
||||
core->irq = bcma_of_get_irq(parent, core, 0);
|
||||
|
||||
of_dma_configure(&core->dev, node);
|
||||
}
|
||||
|
||||
unsigned int bcma_core_irq(struct bcma_device *core, int num)
|
||||
@@ -248,12 +250,12 @@ void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core)
|
||||
core->irq = bus->host_pci->irq;
|
||||
break;
|
||||
case BCMA_HOSTTYPE_SOC:
|
||||
core->dev.dma_mask = &core->dev.coherent_dma_mask;
|
||||
if (bus->host_pdev) {
|
||||
if (IS_ENABLED(CONFIG_OF) && bus->host_pdev) {
|
||||
core->dma_dev = &bus->host_pdev->dev;
|
||||
core->dev.parent = &bus->host_pdev->dev;
|
||||
bcma_of_fill_device(bus->host_pdev, core);
|
||||
} else {
|
||||
core->dev.dma_mask = &core->dev.coherent_dma_mask;
|
||||
core->dma_dev = &core->dev;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -462,13 +462,13 @@ static void ath10k_ahb_halt_chip(struct ath10k *ar)
|
||||
static irqreturn_t ath10k_ahb_interrupt_handler(int irq, void *arg)
|
||||
{
|
||||
struct ath10k *ar = arg;
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
||||
if (!ath10k_pci_irq_pending(ar))
|
||||
return IRQ_NONE;
|
||||
|
||||
ath10k_pci_disable_and_clear_legacy_irq(ar);
|
||||
tasklet_schedule(&ar_pci->intr_tq);
|
||||
ath10k_pci_irq_msi_fw_mask(ar);
|
||||
napi_schedule(&ar->napi);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@@ -577,7 +577,7 @@ static int ath10k_ahb_resource_init(struct ath10k *ar)
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "irq: %d\n", ar_ahb->irq);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "mem: 0x%p mem_len: %lu gcc mem: 0x%p tcsr_mem: 0x%p\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "mem: 0x%pK mem_len: %lu gcc mem: 0x%pK tcsr_mem: 0x%pK\n",
|
||||
ar_ahb->mem, ar_ahb->mem_len,
|
||||
ar_ahb->gcc_mem, ar_ahb->tcsr_mem);
|
||||
return 0;
|
||||
@@ -717,6 +717,9 @@ static void ath10k_ahb_hif_stop(struct ath10k *ar)
|
||||
synchronize_irq(ar_ahb->irq);
|
||||
|
||||
ath10k_pci_flush(ar);
|
||||
|
||||
napi_synchronize(&ar->napi);
|
||||
napi_disable(&ar->napi);
|
||||
}
|
||||
|
||||
static int ath10k_ahb_hif_power_up(struct ath10k *ar)
|
||||
@@ -748,6 +751,7 @@ static int ath10k_ahb_hif_power_up(struct ath10k *ar)
|
||||
ath10k_err(ar, "could not wake up target CPU: %d\n", ret);
|
||||
goto err_ce_deinit;
|
||||
}
|
||||
napi_enable(&ar->napi);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -831,7 +835,7 @@ static int ath10k_ahb_probe(struct platform_device *pdev)
|
||||
goto err_resource_deinit;
|
||||
}
|
||||
|
||||
ath10k_pci_init_irq_tasklets(ar);
|
||||
ath10k_pci_init_napi(ar);
|
||||
|
||||
ret = ath10k_ahb_request_irq_legacy(ar);
|
||||
if (ret)
|
||||
|
||||
@@ -221,7 +221,7 @@ int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length)
|
||||
u32 txlen;
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi lz data buffer 0x%p length %d\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi lz data buffer 0x%pK length %d\n",
|
||||
buffer, length);
|
||||
|
||||
if (ar->bmi.done_sent) {
|
||||
@@ -287,7 +287,7 @@ int ath10k_bmi_fast_download(struct ath10k *ar,
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI,
|
||||
"bmi fast download address 0x%x buffer 0x%p length %d\n",
|
||||
"bmi fast download address 0x%x buffer 0x%pK length %d\n",
|
||||
address, buffer, length);
|
||||
|
||||
ret = ath10k_bmi_lz_stream_start(ar, address);
|
||||
|
||||
@@ -840,7 +840,7 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,
|
||||
ath10k_ce_src_ring_highmark_set(ar, ctrl_addr, nentries);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"boot init ce src ring id %d entries %d base_addr %p\n",
|
||||
"boot init ce src ring id %d entries %d base_addr %pK\n",
|
||||
ce_id, nentries, src_ring->base_addr_owner_space);
|
||||
|
||||
return 0;
|
||||
@@ -874,7 +874,7 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar,
|
||||
ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, nentries);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"boot ce dest ring id %d entries %d base_addr %p\n",
|
||||
"boot ce dest ring id %d entries %d base_addr %pK\n",
|
||||
ce_id, nentries, dest_ring->base_addr_owner_space);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -60,7 +60,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.otp_exe_param = 0,
|
||||
.channel_counters_freq_hz = 88000,
|
||||
.max_probe_resp_desc_thres = 0,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
|
||||
.cal_data_len = 2116,
|
||||
.fw = {
|
||||
.dir = QCA988X_HW_2_0_FW_DIR,
|
||||
@@ -68,6 +67,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA988X_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA988X_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.hw_ops = &qca988x_ops,
|
||||
},
|
||||
{
|
||||
.id = QCA9887_HW_1_0_VERSION,
|
||||
@@ -79,7 +79,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.otp_exe_param = 0,
|
||||
.channel_counters_freq_hz = 88000,
|
||||
.max_probe_resp_desc_thres = 0,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
|
||||
.cal_data_len = 2116,
|
||||
.fw = {
|
||||
.dir = QCA9887_HW_1_0_FW_DIR,
|
||||
@@ -87,6 +86,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA9887_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9887_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.hw_ops = &qca988x_ops,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_2_1_VERSION,
|
||||
@@ -104,6 +104,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.hw_ops = &qca988x_ops,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_2_1_VERSION,
|
||||
@@ -114,7 +115,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.otp_exe_param = 0,
|
||||
.channel_counters_freq_hz = 88000,
|
||||
.max_probe_resp_desc_thres = 0,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
|
||||
.cal_data_len = 8124,
|
||||
.fw = {
|
||||
.dir = QCA6174_HW_2_1_FW_DIR,
|
||||
@@ -122,6 +122,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.hw_ops = &qca988x_ops,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_3_0_VERSION,
|
||||
@@ -132,7 +133,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.otp_exe_param = 0,
|
||||
.channel_counters_freq_hz = 88000,
|
||||
.max_probe_resp_desc_thres = 0,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
|
||||
.cal_data_len = 8124,
|
||||
.fw = {
|
||||
.dir = QCA6174_HW_3_0_FW_DIR,
|
||||
@@ -140,6 +140,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.hw_ops = &qca988x_ops,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_3_2_VERSION,
|
||||
@@ -150,7 +151,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.otp_exe_param = 0,
|
||||
.channel_counters_freq_hz = 88000,
|
||||
.max_probe_resp_desc_thres = 0,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
|
||||
.cal_data_len = 8124,
|
||||
.fw = {
|
||||
/* uses same binaries as hw3.0 */
|
||||
@@ -159,6 +159,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.hw_ops = &qca988x_ops,
|
||||
},
|
||||
{
|
||||
.id = QCA99X0_HW_2_0_DEV_VERSION,
|
||||
@@ -171,7 +172,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cck_rate_map_rev2 = true,
|
||||
.channel_counters_freq_hz = 150000,
|
||||
.max_probe_resp_desc_thres = 24,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
|
||||
.tx_chain_mask = 0xf,
|
||||
.rx_chain_mask = 0xf,
|
||||
.max_spatial_stream = 4,
|
||||
@@ -182,6 +182,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA99X0_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.sw_decrypt_mcast_mgmt = true,
|
||||
.hw_ops = &qca99x0_ops,
|
||||
},
|
||||
{
|
||||
.id = QCA9984_HW_1_0_DEV_VERSION,
|
||||
@@ -194,7 +196,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cck_rate_map_rev2 = true,
|
||||
.channel_counters_freq_hz = 150000,
|
||||
.max_probe_resp_desc_thres = 24,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
|
||||
.tx_chain_mask = 0xf,
|
||||
.rx_chain_mask = 0xf,
|
||||
.max_spatial_stream = 4,
|
||||
@@ -205,6 +206,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA99X0_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.sw_decrypt_mcast_mgmt = true,
|
||||
.hw_ops = &qca99x0_ops,
|
||||
},
|
||||
{
|
||||
.id = QCA9888_HW_2_0_DEV_VERSION,
|
||||
@@ -216,7 +219,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.continuous_frag_desc = true,
|
||||
.channel_counters_freq_hz = 150000,
|
||||
.max_probe_resp_desc_thres = 24,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
|
||||
.tx_chain_mask = 3,
|
||||
.rx_chain_mask = 3,
|
||||
.max_spatial_stream = 2,
|
||||
@@ -227,6 +229,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA99X0_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.sw_decrypt_mcast_mgmt = true,
|
||||
.hw_ops = &qca99x0_ops,
|
||||
},
|
||||
{
|
||||
.id = QCA9377_HW_1_0_DEV_VERSION,
|
||||
@@ -244,6 +248,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA9377_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.hw_ops = &qca988x_ops,
|
||||
},
|
||||
{
|
||||
.id = QCA9377_HW_1_1_DEV_VERSION,
|
||||
@@ -261,6 +266,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA9377_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.hw_ops = &qca988x_ops,
|
||||
},
|
||||
{
|
||||
.id = QCA4019_HW_1_0_DEV_VERSION,
|
||||
@@ -274,7 +280,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cck_rate_map_rev2 = true,
|
||||
.channel_counters_freq_hz = 125000,
|
||||
.max_probe_resp_desc_thres = 24,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
|
||||
.tx_chain_mask = 0x3,
|
||||
.rx_chain_mask = 0x3,
|
||||
.max_spatial_stream = 2,
|
||||
@@ -285,6 +290,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_size = QCA4019_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA4019_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.sw_decrypt_mcast_mgmt = true,
|
||||
.hw_ops = &qca99x0_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -304,6 +311,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
|
||||
[ATH10K_FW_FEATURE_MFP_SUPPORT] = "mfp",
|
||||
[ATH10K_FW_FEATURE_PEER_FLOW_CONTROL] = "peer-flow-ctrl",
|
||||
[ATH10K_FW_FEATURE_BTCOEX_PARAM] = "btcoex-param",
|
||||
[ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR] = "skip-null-func-war",
|
||||
};
|
||||
|
||||
static unsigned int ath10k_core_get_fw_feature_str(char *buf,
|
||||
@@ -699,7 +707,7 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
|
||||
|
||||
if (!ar->running_fw->fw_file.otp_data ||
|
||||
!ar->running_fw->fw_file.otp_len) {
|
||||
ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %p otp_len %zd)!\n",
|
||||
ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %pK otp_len %zd)!\n",
|
||||
ar->running_fw->fw_file.otp_data,
|
||||
ar->running_fw->fw_file.otp_len);
|
||||
return 0;
|
||||
@@ -745,7 +753,7 @@ static int ath10k_download_fw(struct ath10k *ar)
|
||||
data = ar->running_fw->fw_file.firmware_data;
|
||||
data_len = ar->running_fw->fw_file.firmware_len;
|
||||
|
||||
ret = ath10k_swap_code_seg_configure(ar);
|
||||
ret = ath10k_swap_code_seg_configure(ar, &ar->running_fw->fw_file);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to configure fw code swap: %d\n",
|
||||
ret);
|
||||
@@ -753,7 +761,7 @@ static int ath10k_download_fw(struct ath10k *ar)
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"boot uploading firmware image %p len %d\n",
|
||||
"boot uploading firmware image %pK len %d\n",
|
||||
data, data_len);
|
||||
|
||||
ret = ath10k_bmi_fast_download(ar, address, data, data_len);
|
||||
@@ -787,7 +795,7 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar)
|
||||
if (!IS_ERR(ar->pre_cal_file))
|
||||
release_firmware(ar->pre_cal_file);
|
||||
|
||||
ath10k_swap_code_seg_release(ar);
|
||||
ath10k_swap_code_seg_release(ar, &ar->normal_mode_fw.fw_file);
|
||||
|
||||
ar->normal_mode_fw.fw_file.otp_data = NULL;
|
||||
ar->normal_mode_fw.fw_file.otp_len = 0;
|
||||
@@ -1497,14 +1505,14 @@ static void ath10k_core_restart(struct work_struct *work)
|
||||
|
||||
ieee80211_stop_queues(ar->hw);
|
||||
ath10k_drain_tx(ar);
|
||||
complete_all(&ar->scan.started);
|
||||
complete_all(&ar->scan.completed);
|
||||
complete_all(&ar->scan.on_channel);
|
||||
complete_all(&ar->offchan_tx_completed);
|
||||
complete_all(&ar->install_key_done);
|
||||
complete_all(&ar->vdev_setup_done);
|
||||
complete_all(&ar->thermal.wmi_sync);
|
||||
complete_all(&ar->bss_survey_done);
|
||||
complete(&ar->scan.started);
|
||||
complete(&ar->scan.completed);
|
||||
complete(&ar->scan.on_channel);
|
||||
complete(&ar->offchan_tx_completed);
|
||||
complete(&ar->install_key_done);
|
||||
complete(&ar->vdev_setup_done);
|
||||
complete(&ar->thermal.wmi_sync);
|
||||
complete(&ar->bss_survey_done);
|
||||
wake_up(&ar->htt.empty_tx_wq);
|
||||
wake_up(&ar->wmi.tx_credits_wq);
|
||||
wake_up(&ar->peer_mapping_wq);
|
||||
@@ -1705,6 +1713,55 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_core_reset_rx_filter(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
int vdev_id;
|
||||
int vdev_type;
|
||||
int vdev_subtype;
|
||||
const u8 *vdev_addr;
|
||||
|
||||
vdev_id = 0;
|
||||
vdev_type = WMI_VDEV_TYPE_STA;
|
||||
vdev_subtype = ath10k_wmi_get_vdev_subtype(ar, WMI_VDEV_SUBTYPE_NONE);
|
||||
vdev_addr = ar->mac_addr;
|
||||
|
||||
ret = ath10k_wmi_vdev_create(ar, vdev_id, vdev_type, vdev_subtype,
|
||||
vdev_addr);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to create dummy vdev: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath10k_wmi_vdev_delete(ar, vdev_id);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to delete dummy vdev: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* WMI and HTT may use separate HIF pipes and are not guaranteed to be
|
||||
* serialized properly implicitly.
|
||||
*
|
||||
* Moreover (most) WMI commands have no explicit acknowledges. It is
|
||||
* possible to infer it implicitly by poking firmware with echo
|
||||
* command - getting a reply means all preceding comments have been
|
||||
* (mostly) processed.
|
||||
*
|
||||
* In case of vdev create/delete this is sufficient.
|
||||
*
|
||||
* Without this it's possible to end up with a race when HTT Rx ring is
|
||||
* started before vdev create/delete hack is complete allowing a short
|
||||
* window of opportunity to receive (and Tx ACK) a bunch of frames.
|
||||
*/
|
||||
ret = ath10k_wmi_barrier(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to ping firmware: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
const struct ath10k_fw_components *fw)
|
||||
{
|
||||
@@ -1872,6 +1929,25 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
goto err_hif_stop;
|
||||
}
|
||||
|
||||
/* Some firmware revisions do not properly set up hardware rx filter
|
||||
* registers.
|
||||
*
|
||||
* A known example from QCA9880 and 10.2.4 is that MAC_PCU_ADDR1_MASK
|
||||
* is filled with 0s instead of 1s allowing HW to respond with ACKs to
|
||||
* any frames that matches MAC_PCU_RX_FILTER which is also
|
||||
* misconfigured to accept anything.
|
||||
*
|
||||
* The ADDR1 is programmed using internal firmware structure field and
|
||||
* can't be (easily/sanely) reached from the driver explicitly. It is
|
||||
* possible to implicitly make it correct by creating a dummy vdev and
|
||||
* then deleting it.
|
||||
*/
|
||||
status = ath10k_core_reset_rx_filter(ar);
|
||||
if (status) {
|
||||
ath10k_err(ar, "failed to reset rx filter: %d\n", status);
|
||||
goto err_hif_stop;
|
||||
}
|
||||
|
||||
/* If firmware indicates Full Rx Reorder support it must be used in a
|
||||
* slightly different manner. Let HTT code know.
|
||||
*/
|
||||
@@ -2031,7 +2107,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
|
||||
goto err_free_firmware_files;
|
||||
}
|
||||
|
||||
ret = ath10k_swap_code_seg_init(ar);
|
||||
ret = ath10k_swap_code_seg_init(ar, &ar->normal_mode_fw.fw_file);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to initialize code swap segment: %d\n",
|
||||
ret);
|
||||
@@ -2072,6 +2148,9 @@ static void ath10k_core_register_work(struct work_struct *work)
|
||||
struct ath10k *ar = container_of(work, struct ath10k, register_work);
|
||||
int status;
|
||||
|
||||
/* peer stats are enabled by default */
|
||||
set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
|
||||
|
||||
status = ath10k_core_probe_fw(ar);
|
||||
if (status) {
|
||||
ath10k_err(ar, "could not probe fw (%d)\n", status);
|
||||
@@ -2249,6 +2328,8 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
||||
INIT_WORK(&ar->register_work, ath10k_core_register_work);
|
||||
INIT_WORK(&ar->restart_work, ath10k_core_restart);
|
||||
|
||||
init_dummy_netdev(&ar->napi_dev);
|
||||
|
||||
ret = ath10k_debug_create(ar);
|
||||
if (ret)
|
||||
goto err_free_aux_wq;
|
||||
|
||||
@@ -65,6 +65,10 @@
|
||||
#define ATH10K_KEEPALIVE_MAX_IDLE 3895
|
||||
#define ATH10K_KEEPALIVE_MAX_UNRESPONSIVE 3900
|
||||
|
||||
/* NAPI poll budget */
|
||||
#define ATH10K_NAPI_BUDGET 64
|
||||
#define ATH10K_NAPI_QUOTA_LIMIT 60
|
||||
|
||||
struct ath10k;
|
||||
|
||||
enum ath10k_bus {
|
||||
@@ -142,6 +146,7 @@ struct ath10k_wmi {
|
||||
enum ath10k_htc_ep_id eid;
|
||||
struct completion service_ready;
|
||||
struct completion unified_ready;
|
||||
struct completion barrier;
|
||||
wait_queue_head_t tx_credits_wq;
|
||||
DECLARE_BITMAP(svc_map, WMI_SERVICE_MAX);
|
||||
struct wmi_cmd_map *cmd;
|
||||
@@ -440,7 +445,7 @@ struct ath10k_debug {
|
||||
struct completion tpc_complete;
|
||||
|
||||
/* protected by conf_mutex */
|
||||
u32 fw_dbglog_mask;
|
||||
u64 fw_dbglog_mask;
|
||||
u32 fw_dbglog_level;
|
||||
u32 pktlog_filter;
|
||||
u32 reg_addr;
|
||||
@@ -551,6 +556,13 @@ enum ath10k_fw_features {
|
||||
*/
|
||||
ATH10K_FW_FEATURE_BTCOEX_PARAM = 14,
|
||||
|
||||
/* Older firmware with HTT delivers incorrect tx status for null func
|
||||
* frames to driver, but this fixed in 10.2 and 10.4 firmware versions.
|
||||
* Also this workaround results in reporting of incorrect null func
|
||||
* status for 10.4. This flag is used to skip the workaround.
|
||||
*/
|
||||
ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR = 15,
|
||||
|
||||
/* keep last */
|
||||
ATH10K_FW_FEATURE_COUNT,
|
||||
};
|
||||
@@ -663,6 +675,15 @@ struct ath10k_fw_file {
|
||||
|
||||
const void *codeswap_data;
|
||||
size_t codeswap_len;
|
||||
|
||||
/* The original idea of struct ath10k_fw_file was that it only
|
||||
* contains struct firmware and pointers to various parts (actual
|
||||
* firmware binary, otp, metadata etc) of the file. This seg_info
|
||||
* is actually created separate but as this is used similarly as
|
||||
* the other firmware components it's more convenient to have it
|
||||
* here.
|
||||
*/
|
||||
struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info;
|
||||
};
|
||||
|
||||
struct ath10k_fw_components {
|
||||
@@ -715,53 +736,7 @@ struct ath10k {
|
||||
struct ath10k_htc htc;
|
||||
struct ath10k_htt htt;
|
||||
|
||||
struct ath10k_hw_params {
|
||||
u32 id;
|
||||
u16 dev_id;
|
||||
const char *name;
|
||||
u32 patch_load_addr;
|
||||
int uart_pin;
|
||||
u32 otp_exe_param;
|
||||
|
||||
/* Type of hw cycle counter wraparound logic, for more info
|
||||
* refer enum ath10k_hw_cc_wraparound_type.
|
||||
*/
|
||||
enum ath10k_hw_cc_wraparound_type cc_wraparound_type;
|
||||
|
||||
/* Some of chip expects fragment descriptor to be continuous
|
||||
* memory for any TX operation. Set continuous_frag_desc flag
|
||||
* for the hardware which have such requirement.
|
||||
*/
|
||||
bool continuous_frag_desc;
|
||||
|
||||
/* CCK hardware rate table mapping for the newer chipsets
|
||||
* like QCA99X0, QCA4019 got revised. The CCK h/w rate values
|
||||
* are in a proper order with respect to the rate/preamble
|
||||
*/
|
||||
bool cck_rate_map_rev2;
|
||||
|
||||
u32 channel_counters_freq_hz;
|
||||
|
||||
/* Mgmt tx descriptors threshold for limiting probe response
|
||||
* frames.
|
||||
*/
|
||||
u32 max_probe_resp_desc_thres;
|
||||
|
||||
/* The padding bytes's location is different on various chips */
|
||||
enum ath10k_hw_4addr_pad hw_4addr_pad;
|
||||
|
||||
u32 tx_chain_mask;
|
||||
u32 rx_chain_mask;
|
||||
u32 max_spatial_stream;
|
||||
u32 cal_data_len;
|
||||
|
||||
struct ath10k_hw_params_fw {
|
||||
const char *dir;
|
||||
const char *board;
|
||||
size_t board_size;
|
||||
size_t board_ext_size;
|
||||
} fw;
|
||||
} hw_params;
|
||||
struct ath10k_hw_params hw_params;
|
||||
|
||||
/* contains the firmware images used with ATH10K_FIRMWARE_MODE_NORMAL */
|
||||
struct ath10k_fw_components normal_mode_fw;
|
||||
@@ -774,10 +749,6 @@ struct ath10k {
|
||||
const struct firmware *pre_cal_file;
|
||||
const struct firmware *cal_file;
|
||||
|
||||
struct {
|
||||
struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info;
|
||||
} swap;
|
||||
|
||||
struct {
|
||||
u32 vendor;
|
||||
u32 device;
|
||||
@@ -936,6 +907,10 @@ struct ath10k {
|
||||
struct ath10k_thermal thermal;
|
||||
struct ath10k_wow wow;
|
||||
|
||||
/* NAPI */
|
||||
struct net_device napi_dev;
|
||||
struct napi_struct napi;
|
||||
|
||||
/* must be last */
|
||||
u8 drv_priv[0] __aligned(sizeof(void *));
|
||||
};
|
||||
|
||||
@@ -1228,9 +1228,9 @@ static ssize_t ath10k_read_fw_dbglog(struct file *file,
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
unsigned int len;
|
||||
char buf[64];
|
||||
char buf[96];
|
||||
|
||||
len = scnprintf(buf, sizeof(buf), "0x%08x %u\n",
|
||||
len = scnprintf(buf, sizeof(buf), "0x%16llx %u\n",
|
||||
ar->debug.fw_dbglog_mask, ar->debug.fw_dbglog_level);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
@@ -1242,15 +1242,16 @@ static ssize_t ath10k_write_fw_dbglog(struct file *file,
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
int ret;
|
||||
char buf[64];
|
||||
unsigned int log_level, mask;
|
||||
char buf[96];
|
||||
unsigned int log_level;
|
||||
u64 mask;
|
||||
|
||||
simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
|
||||
|
||||
/* make sure that buf is null terminated */
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
|
||||
ret = sscanf(buf, "%x %u", &mask, &log_level);
|
||||
ret = sscanf(buf, "%llx %u", &mask, &log_level);
|
||||
|
||||
if (!ret)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -44,7 +44,7 @@ static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar)
|
||||
skb_cb = ATH10K_SKB_CB(skb);
|
||||
memset(skb_cb, 0, sizeof(*skb_cb));
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: skb %p\n", __func__, skb);
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: skb %pK\n", __func__, skb);
|
||||
return skb;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
|
||||
{
|
||||
struct ath10k *ar = ep->htc->ar;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %p\n", __func__,
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %pK\n", __func__,
|
||||
ep->eid, skb);
|
||||
|
||||
ath10k_htc_restore_tx_skb(ep->htc, skb);
|
||||
@@ -404,7 +404,7 @@ void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %p\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %pK\n",
|
||||
eid, skb);
|
||||
ep->ep_ops.ep_rx_complete(ar, skb);
|
||||
|
||||
|
||||
@@ -1665,7 +1665,6 @@ struct ath10k_htt {
|
||||
|
||||
/* This is used to group tx/rx completions separately and process them
|
||||
* in batches to reduce cache stalls */
|
||||
struct tasklet_struct txrx_compl_task;
|
||||
struct sk_buff_head rx_compl_q;
|
||||
struct sk_buff_head rx_in_ord_compl_q;
|
||||
struct sk_buff_head tx_fetch_ind_q;
|
||||
@@ -1798,5 +1797,6 @@ int ath10k_htt_tx(struct ath10k_htt *htt,
|
||||
struct sk_buff *msdu);
|
||||
void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
|
||||
struct sk_buff *skb);
|
||||
int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define HTT_RX_RING_REFILL_RESCHED_MS 5
|
||||
|
||||
static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb);
|
||||
static void ath10k_htt_txrx_compl_task(unsigned long ptr);
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_htt_rx_find_skb_paddr(struct ath10k *ar, u32 paddr)
|
||||
@@ -226,7 +225,6 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar)
|
||||
void ath10k_htt_rx_free(struct ath10k_htt *htt)
|
||||
{
|
||||
del_timer_sync(&htt->rx_ring.refill_retry_timer);
|
||||
tasklet_kill(&htt->txrx_compl_task);
|
||||
|
||||
skb_queue_purge(&htt->rx_compl_q);
|
||||
skb_queue_purge(&htt->rx_in_ord_compl_q);
|
||||
@@ -520,9 +518,6 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
|
||||
skb_queue_head_init(&htt->tx_fetch_ind_q);
|
||||
atomic_set(&htt->num_mpdus_ready, 0);
|
||||
|
||||
tasklet_init(&htt->txrx_compl_task, ath10k_htt_txrx_compl_task,
|
||||
(unsigned long)htt);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt rx ring size %d fill_level %d\n",
|
||||
htt->rx_ring.size, htt->rx_ring.fill_level);
|
||||
return 0;
|
||||
@@ -931,7 +926,7 @@ static void ath10k_process_rx(struct ath10k *ar,
|
||||
*status = *rx_status;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_DATA,
|
||||
"rx skb %p len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n",
|
||||
"rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n",
|
||||
skb,
|
||||
skb->len,
|
||||
ieee80211_get_SA(hdr),
|
||||
@@ -958,7 +953,7 @@ static void ath10k_process_rx(struct ath10k *ar,
|
||||
trace_ath10k_rx_hdr(ar, skb->data, skb->len);
|
||||
trace_ath10k_rx_payload(ar, skb->data, skb->len);
|
||||
|
||||
ieee80211_rx(ar->hw, skb);
|
||||
ieee80211_rx_napi(ar->hw, NULL, skb, &ar->napi);
|
||||
}
|
||||
|
||||
static int ath10k_htt_rx_nwifi_hdrlen(struct ath10k *ar,
|
||||
@@ -1056,9 +1051,11 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
|
||||
const u8 first_hdr[64])
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct htt_rx_desc *rxd;
|
||||
size_t hdr_len;
|
||||
u8 da[ETH_ALEN];
|
||||
u8 sa[ETH_ALEN];
|
||||
int l3_pad_bytes;
|
||||
|
||||
/* Delivered decapped frame:
|
||||
* [nwifi 802.11 header] <-- replaced with 802.11 hdr
|
||||
@@ -1072,19 +1069,12 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
|
||||
*/
|
||||
|
||||
/* pull decapped header and copy SA & DA */
|
||||
if ((ar->hw_params.hw_4addr_pad == ATH10K_HW_4ADDR_PAD_BEFORE) &&
|
||||
ieee80211_has_a4(((struct ieee80211_hdr *)first_hdr)->frame_control)) {
|
||||
/* The QCA99X0 4 address mode pad 2 bytes at the
|
||||
* beginning of MSDU
|
||||
*/
|
||||
hdr = (struct ieee80211_hdr *)(msdu->data + 2);
|
||||
/* The skb length need be extended 2 as the 2 bytes at the tail
|
||||
* be excluded due to the padding
|
||||
*/
|
||||
skb_put(msdu, 2);
|
||||
} else {
|
||||
hdr = (struct ieee80211_hdr *)(msdu->data);
|
||||
}
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
|
||||
l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd);
|
||||
skb_put(msdu, l3_pad_bytes);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)(msdu->data + l3_pad_bytes);
|
||||
|
||||
hdr_len = ath10k_htt_rx_nwifi_hdrlen(ar, hdr);
|
||||
ether_addr_copy(da, ieee80211_get_DA(hdr));
|
||||
@@ -1151,6 +1141,8 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar,
|
||||
void *rfc1042;
|
||||
u8 da[ETH_ALEN];
|
||||
u8 sa[ETH_ALEN];
|
||||
int l3_pad_bytes;
|
||||
struct htt_rx_desc *rxd;
|
||||
|
||||
/* Delivered decapped frame:
|
||||
* [eth header] <-- replaced with 802.11 hdr & rfc1042/llc
|
||||
@@ -1161,6 +1153,11 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar,
|
||||
if (WARN_ON_ONCE(!rfc1042))
|
||||
return;
|
||||
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd);
|
||||
skb_put(msdu, l3_pad_bytes);
|
||||
skb_pull(msdu, l3_pad_bytes);
|
||||
|
||||
/* pull decapped header and copy SA & DA */
|
||||
eth = (struct ethhdr *)msdu->data;
|
||||
ether_addr_copy(da, eth->h_dest);
|
||||
@@ -1191,6 +1188,8 @@ static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar,
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
size_t hdr_len;
|
||||
int l3_pad_bytes;
|
||||
struct htt_rx_desc *rxd;
|
||||
|
||||
/* Delivered decapped frame:
|
||||
* [amsdu header] <-- replaced with 802.11 hdr
|
||||
@@ -1198,7 +1197,11 @@ static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar,
|
||||
* [payload]
|
||||
*/
|
||||
|
||||
skb_pull(msdu, sizeof(struct amsdu_subframe_hdr));
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd);
|
||||
|
||||
skb_put(msdu, l3_pad_bytes);
|
||||
skb_pull(msdu, sizeof(struct amsdu_subframe_hdr) + l3_pad_bytes);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)first_hdr;
|
||||
hdr_len = ieee80211_hdrlen(hdr->frame_control);
|
||||
@@ -1527,7 +1530,7 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct ieee80211_rx_status *rx_status = &htt->rx_status;
|
||||
struct sk_buff_head amsdu;
|
||||
int ret;
|
||||
int ret, num_msdus;
|
||||
|
||||
__skb_queue_head_init(&amsdu);
|
||||
|
||||
@@ -1549,13 +1552,14 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
|
||||
return ret;
|
||||
}
|
||||
|
||||
num_msdus = skb_queue_len(&amsdu);
|
||||
ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff);
|
||||
ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0);
|
||||
ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
|
||||
ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
|
||||
ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
|
||||
|
||||
return 0;
|
||||
return num_msdus;
|
||||
}
|
||||
|
||||
static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt,
|
||||
@@ -1579,15 +1583,6 @@ static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt,
|
||||
mpdu_count += mpdu_ranges[i].mpdu_count;
|
||||
|
||||
atomic_add(mpdu_count, &htt->num_mpdus_ready);
|
||||
|
||||
tasklet_schedule(&htt->txrx_compl_task);
|
||||
}
|
||||
|
||||
static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt)
|
||||
{
|
||||
atomic_inc(&htt->num_mpdus_ready);
|
||||
|
||||
tasklet_schedule(&htt->txrx_compl_task);
|
||||
}
|
||||
|
||||
static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
|
||||
@@ -1772,14 +1767,15 @@ static void ath10k_htt_rx_h_rx_offload_prot(struct ieee80211_rx_status *status,
|
||||
RX_FLAG_MMIC_STRIPPED;
|
||||
}
|
||||
|
||||
static void ath10k_htt_rx_h_rx_offload(struct ath10k *ar,
|
||||
struct sk_buff_head *list)
|
||||
static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar,
|
||||
struct sk_buff_head *list)
|
||||
{
|
||||
struct ath10k_htt *htt = &ar->htt;
|
||||
struct ieee80211_rx_status *status = &htt->rx_status;
|
||||
struct htt_rx_offload_msdu *rx;
|
||||
struct sk_buff *msdu;
|
||||
size_t offset;
|
||||
int num_msdu = 0;
|
||||
|
||||
while ((msdu = __skb_dequeue(list))) {
|
||||
/* Offloaded frames don't have Rx descriptor. Instead they have
|
||||
@@ -1819,10 +1815,12 @@ static void ath10k_htt_rx_h_rx_offload(struct ath10k *ar,
|
||||
ath10k_htt_rx_h_rx_offload_prot(status, msdu);
|
||||
ath10k_htt_rx_h_channel(ar, status, NULL, rx->vdev_id);
|
||||
ath10k_process_rx(ar, status, msdu);
|
||||
num_msdu++;
|
||||
}
|
||||
return num_msdu;
|
||||
}
|
||||
|
||||
static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
|
||||
static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct ath10k_htt *htt = &ar->htt;
|
||||
struct htt_resp *resp = (void *)skb->data;
|
||||
@@ -1835,12 +1833,12 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
|
||||
u8 tid;
|
||||
bool offload;
|
||||
bool frag;
|
||||
int ret;
|
||||
int ret, num_msdus = 0;
|
||||
|
||||
lockdep_assert_held(&htt->rx_ring.lock);
|
||||
|
||||
if (htt->rx_confused)
|
||||
return;
|
||||
return -EIO;
|
||||
|
||||
skb_pull(skb, sizeof(resp->hdr));
|
||||
skb_pull(skb, sizeof(resp->rx_in_ord_ind));
|
||||
@@ -1859,7 +1857,7 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
|
||||
|
||||
if (skb->len < msdu_count * sizeof(*resp->rx_in_ord_ind.msdu_descs)) {
|
||||
ath10k_warn(ar, "dropping invalid in order rx indication\n");
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The event can deliver more than 1 A-MSDU. Each A-MSDU is later
|
||||
@@ -1870,14 +1868,14 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
|
||||
if (ret < 0) {
|
||||
ath10k_warn(ar, "failed to pop paddr list: %d\n", ret);
|
||||
htt->rx_confused = true;
|
||||
return;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Offloaded frames are very different and need to be handled
|
||||
* separately.
|
||||
*/
|
||||
if (offload)
|
||||
ath10k_htt_rx_h_rx_offload(ar, &list);
|
||||
num_msdus = ath10k_htt_rx_h_rx_offload(ar, &list);
|
||||
|
||||
while (!skb_queue_empty(&list)) {
|
||||
__skb_queue_head_init(&amsdu);
|
||||
@@ -1890,6 +1888,7 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
|
||||
* better to report something than nothing though. This
|
||||
* should still give an idea about rx rate to the user.
|
||||
*/
|
||||
num_msdus += skb_queue_len(&amsdu);
|
||||
ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id);
|
||||
ath10k_htt_rx_h_filter(ar, &amsdu, status);
|
||||
ath10k_htt_rx_h_mpdu(ar, &amsdu, status);
|
||||
@@ -1902,9 +1901,10 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
|
||||
ath10k_warn(ar, "failed to extract amsdu: %d\n", ret);
|
||||
htt->rx_confused = true;
|
||||
__skb_queue_purge(&list);
|
||||
return;
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
return num_msdus;
|
||||
}
|
||||
|
||||
static void ath10k_htt_rx_tx_fetch_resp_id_confirm(struct ath10k *ar,
|
||||
@@ -2267,7 +2267,6 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
}
|
||||
case HTT_T2H_MSG_TYPE_TX_COMPL_IND:
|
||||
ath10k_htt_rx_tx_compl_ind(htt->ar, skb);
|
||||
tasklet_schedule(&htt->txrx_compl_task);
|
||||
break;
|
||||
case HTT_T2H_MSG_TYPE_SEC_IND: {
|
||||
struct ath10k *ar = htt->ar;
|
||||
@@ -2284,7 +2283,7 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
case HTT_T2H_MSG_TYPE_RX_FRAG_IND: {
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
|
||||
skb->data, skb->len);
|
||||
ath10k_htt_rx_frag_handler(htt);
|
||||
atomic_inc(&htt->num_mpdus_ready);
|
||||
break;
|
||||
}
|
||||
case HTT_T2H_MSG_TYPE_TEST:
|
||||
@@ -2320,8 +2319,7 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
break;
|
||||
}
|
||||
case HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND: {
|
||||
skb_queue_tail(&htt->rx_in_ord_compl_q, skb);
|
||||
tasklet_schedule(&htt->txrx_compl_task);
|
||||
__skb_queue_tail(&htt->rx_in_ord_compl_q, skb);
|
||||
return false;
|
||||
}
|
||||
case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND:
|
||||
@@ -2347,7 +2345,6 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
break;
|
||||
}
|
||||
skb_queue_tail(&htt->tx_fetch_ind_q, tx_fetch_ind);
|
||||
tasklet_schedule(&htt->txrx_compl_task);
|
||||
break;
|
||||
}
|
||||
case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM:
|
||||
@@ -2376,27 +2373,77 @@ void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_htt_rx_pktlog_completion_handler);
|
||||
|
||||
static void ath10k_htt_txrx_compl_task(unsigned long ptr)
|
||||
int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget)
|
||||
{
|
||||
struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct ath10k_htt *htt = &ar->htt;
|
||||
struct htt_tx_done tx_done = {};
|
||||
struct sk_buff_head rx_ind_q;
|
||||
struct sk_buff_head tx_ind_q;
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
int num_mpdus;
|
||||
int quota = 0, done, num_rx_msdus;
|
||||
bool resched_napi = false;
|
||||
|
||||
__skb_queue_head_init(&rx_ind_q);
|
||||
__skb_queue_head_init(&tx_ind_q);
|
||||
|
||||
spin_lock_irqsave(&htt->rx_in_ord_compl_q.lock, flags);
|
||||
skb_queue_splice_init(&htt->rx_in_ord_compl_q, &rx_ind_q);
|
||||
spin_unlock_irqrestore(&htt->rx_in_ord_compl_q.lock, flags);
|
||||
/* Since in-ord-ind can deliver more than 1 A-MSDU in single event,
|
||||
* process it first to utilize full available quota.
|
||||
*/
|
||||
while (quota < budget) {
|
||||
if (skb_queue_empty(&htt->rx_in_ord_compl_q))
|
||||
break;
|
||||
|
||||
spin_lock_irqsave(&htt->tx_fetch_ind_q.lock, flags);
|
||||
skb_queue_splice_init(&htt->tx_fetch_ind_q, &tx_ind_q);
|
||||
spin_unlock_irqrestore(&htt->tx_fetch_ind_q.lock, flags);
|
||||
skb = __skb_dequeue(&htt->rx_in_ord_compl_q);
|
||||
if (!skb) {
|
||||
resched_napi = true;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
spin_lock_bh(&htt->rx_ring.lock);
|
||||
num_rx_msdus = ath10k_htt_rx_in_ord_ind(ar, skb);
|
||||
spin_unlock_bh(&htt->rx_ring.lock);
|
||||
if (num_rx_msdus < 0) {
|
||||
resched_napi = true;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
if (num_rx_msdus > 0)
|
||||
quota += num_rx_msdus;
|
||||
|
||||
if ((quota > ATH10K_NAPI_QUOTA_LIMIT) &&
|
||||
!skb_queue_empty(&htt->rx_in_ord_compl_q)) {
|
||||
resched_napi = true;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
while (quota < budget) {
|
||||
/* no more data to receive */
|
||||
if (!atomic_read(&htt->num_mpdus_ready))
|
||||
break;
|
||||
|
||||
num_rx_msdus = ath10k_htt_rx_handle_amsdu(htt);
|
||||
if (num_rx_msdus < 0) {
|
||||
resched_napi = true;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
quota += num_rx_msdus;
|
||||
atomic_dec(&htt->num_mpdus_ready);
|
||||
if ((quota > ATH10K_NAPI_QUOTA_LIMIT) &&
|
||||
atomic_read(&htt->num_mpdus_ready)) {
|
||||
resched_napi = true;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* From NAPI documentation:
|
||||
* The napi poll() function may also process TX completions, in which
|
||||
* case if it processes the entire TX ring then it should count that
|
||||
* work as the rest of the budget.
|
||||
*/
|
||||
if ((quota < budget) && !kfifo_is_empty(&htt->txdone_fifo))
|
||||
quota = budget;
|
||||
|
||||
/* kfifo_get: called only within txrx_tasklet so it's neatly serialized.
|
||||
* From kfifo_get() documentation:
|
||||
@@ -2406,27 +2453,24 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr)
|
||||
while (kfifo_get(&htt->txdone_fifo, &tx_done))
|
||||
ath10k_txrx_tx_unref(htt, &tx_done);
|
||||
|
||||
ath10k_mac_tx_push_pending(ar);
|
||||
|
||||
spin_lock_irqsave(&htt->tx_fetch_ind_q.lock, flags);
|
||||
skb_queue_splice_init(&htt->tx_fetch_ind_q, &tx_ind_q);
|
||||
spin_unlock_irqrestore(&htt->tx_fetch_ind_q.lock, flags);
|
||||
|
||||
while ((skb = __skb_dequeue(&tx_ind_q))) {
|
||||
ath10k_htt_rx_tx_fetch_ind(ar, skb);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
num_mpdus = atomic_read(&htt->num_mpdus_ready);
|
||||
|
||||
while (num_mpdus) {
|
||||
if (ath10k_htt_rx_handle_amsdu(htt))
|
||||
break;
|
||||
|
||||
num_mpdus--;
|
||||
atomic_dec(&htt->num_mpdus_ready);
|
||||
}
|
||||
|
||||
while ((skb = __skb_dequeue(&rx_ind_q))) {
|
||||
spin_lock_bh(&htt->rx_ring.lock);
|
||||
ath10k_htt_rx_in_ord_ind(ar, skb);
|
||||
spin_unlock_bh(&htt->rx_ring.lock);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
exit:
|
||||
ath10k_htt_rx_msdu_buff_replenish(htt);
|
||||
/* In case of rx failure or more data to read, report budget
|
||||
* to reschedule NAPI poll
|
||||
*/
|
||||
done = resched_napi ? budget : quota;
|
||||
|
||||
return done;
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_htt_txrx_compl_task);
|
||||
|
||||
@@ -390,8 +390,6 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
|
||||
{
|
||||
int size;
|
||||
|
||||
tasklet_kill(&htt->txrx_compl_task);
|
||||
|
||||
idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
|
||||
idr_destroy(&htt->pending_tx);
|
||||
|
||||
|
||||
@@ -219,3 +219,16 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
survey->time = CCNT_TO_MSEC(ar, cc);
|
||||
survey->time_busy = CCNT_TO_MSEC(ar, rcc);
|
||||
}
|
||||
|
||||
const struct ath10k_hw_ops qca988x_ops = {
|
||||
};
|
||||
|
||||
static int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(struct htt_rx_desc *rxd)
|
||||
{
|
||||
return MS(__le32_to_cpu(rxd->msdu_end.qca99x0.info1),
|
||||
RX_MSDU_END_INFO1_L3_HDR_PAD);
|
||||
}
|
||||
|
||||
const struct ath10k_hw_ops qca99x0_ops = {
|
||||
.rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes,
|
||||
};
|
||||
|
||||
@@ -338,11 +338,6 @@ enum ath10k_hw_rate_rev2_cck {
|
||||
ATH10K_HW_RATE_REV2_CCK_SP_11M,
|
||||
};
|
||||
|
||||
enum ath10k_hw_4addr_pad {
|
||||
ATH10K_HW_4ADDR_PAD_AFTER,
|
||||
ATH10K_HW_4ADDR_PAD_BEFORE,
|
||||
};
|
||||
|
||||
enum ath10k_hw_cc_wraparound_type {
|
||||
ATH10K_HW_CC_WRAP_DISABLED = 0,
|
||||
|
||||
@@ -363,6 +358,77 @@ enum ath10k_hw_cc_wraparound_type {
|
||||
ATH10K_HW_CC_WRAP_SHIFTED_EACH = 2,
|
||||
};
|
||||
|
||||
struct ath10k_hw_params {
|
||||
u32 id;
|
||||
u16 dev_id;
|
||||
const char *name;
|
||||
u32 patch_load_addr;
|
||||
int uart_pin;
|
||||
u32 otp_exe_param;
|
||||
|
||||
/* Type of hw cycle counter wraparound logic, for more info
|
||||
* refer enum ath10k_hw_cc_wraparound_type.
|
||||
*/
|
||||
enum ath10k_hw_cc_wraparound_type cc_wraparound_type;
|
||||
|
||||
/* Some of chip expects fragment descriptor to be continuous
|
||||
* memory for any TX operation. Set continuous_frag_desc flag
|
||||
* for the hardware which have such requirement.
|
||||
*/
|
||||
bool continuous_frag_desc;
|
||||
|
||||
/* CCK hardware rate table mapping for the newer chipsets
|
||||
* like QCA99X0, QCA4019 got revised. The CCK h/w rate values
|
||||
* are in a proper order with respect to the rate/preamble
|
||||
*/
|
||||
bool cck_rate_map_rev2;
|
||||
|
||||
u32 channel_counters_freq_hz;
|
||||
|
||||
/* Mgmt tx descriptors threshold for limiting probe response
|
||||
* frames.
|
||||
*/
|
||||
u32 max_probe_resp_desc_thres;
|
||||
|
||||
u32 tx_chain_mask;
|
||||
u32 rx_chain_mask;
|
||||
u32 max_spatial_stream;
|
||||
u32 cal_data_len;
|
||||
|
||||
struct ath10k_hw_params_fw {
|
||||
const char *dir;
|
||||
const char *board;
|
||||
size_t board_size;
|
||||
size_t board_ext_size;
|
||||
} fw;
|
||||
|
||||
/* qca99x0 family chips deliver broadcast/multicast management
|
||||
* frames encrypted and expect software do decryption.
|
||||
*/
|
||||
bool sw_decrypt_mcast_mgmt;
|
||||
|
||||
const struct ath10k_hw_ops *hw_ops;
|
||||
};
|
||||
|
||||
struct htt_rx_desc;
|
||||
|
||||
/* Defines needed for Rx descriptor abstraction */
|
||||
struct ath10k_hw_ops {
|
||||
int (*rx_desc_get_l3_pad_bytes)(struct htt_rx_desc *rxd);
|
||||
};
|
||||
|
||||
extern const struct ath10k_hw_ops qca988x_ops;
|
||||
extern const struct ath10k_hw_ops qca99x0_ops;
|
||||
|
||||
static inline int
|
||||
ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
|
||||
struct htt_rx_desc *rxd)
|
||||
{
|
||||
if (hw->hw_ops->rx_desc_get_l3_pad_bytes)
|
||||
return hw->hw_ops->rx_desc_get_l3_pad_bytes(rxd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Target specific defines for MAIN firmware */
|
||||
#define TARGET_NUM_VDEVS 8
|
||||
#define TARGET_NUM_PEER_AST 2
|
||||
|
||||
@@ -824,7 +824,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
|
||||
if (ar->peer_map[i] == peer) {
|
||||
ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %p idx %d)\n",
|
||||
ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n",
|
||||
peer->addr, peer, i);
|
||||
ar->peer_map[i] = NULL;
|
||||
}
|
||||
@@ -3255,6 +3255,8 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
|
||||
if (ar->htt.target_version_major < 3 &&
|
||||
(ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)) &&
|
||||
!test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
|
||||
ar->running_fw->fw_file.fw_features) &&
|
||||
!test_bit(ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
return ATH10K_HW_TXRX_MGMT;
|
||||
|
||||
@@ -3524,7 +3526,7 @@ static int ath10k_mac_tx(struct ath10k *ar,
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
|
||||
if (!ath10k_mac_tx_frm_has_freq(ar)) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %pK\n",
|
||||
skb);
|
||||
|
||||
skb_queue_tail(&ar->offchan_tx_queue, skb);
|
||||
@@ -3586,7 +3588,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %p\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK\n",
|
||||
skb);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
@@ -3643,7 +3645,7 @@ 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 %p\n",
|
||||
ath10k_warn(ar, "timed out waiting for offchannel skb %pK\n",
|
||||
skb);
|
||||
|
||||
if (!peer && tmp_peer_created) {
|
||||
@@ -3777,7 +3779,9 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
|
||||
enum ath10k_hw_txrx_mode txmode;
|
||||
enum ath10k_mac_tx_path txpath;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_hdr *hdr;
|
||||
size_t skb_len;
|
||||
bool is_mgmt, is_presp;
|
||||
int ret;
|
||||
|
||||
spin_lock_bh(&ar->htt.tx_lock);
|
||||
@@ -3801,6 +3805,22 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
|
||||
skb_len = skb->len;
|
||||
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
|
||||
txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode);
|
||||
is_mgmt = (txpath == ATH10K_MAC_TX_HTT_MGMT);
|
||||
|
||||
if (is_mgmt) {
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
is_presp = ieee80211_is_probe_resp(hdr->frame_control);
|
||||
|
||||
spin_lock_bh(&ar->htt.tx_lock);
|
||||
ret = ath10k_htt_tx_mgmt_inc_pending(htt, is_mgmt, is_presp);
|
||||
|
||||
if (ret) {
|
||||
ath10k_htt_tx_dec_pending(htt);
|
||||
spin_unlock_bh(&ar->htt.tx_lock);
|
||||
return ret;
|
||||
}
|
||||
spin_unlock_bh(&ar->htt.tx_lock);
|
||||
}
|
||||
|
||||
ret = ath10k_mac_tx(ar, vif, sta, txmode, txpath, skb);
|
||||
if (unlikely(ret)) {
|
||||
@@ -3808,6 +3828,8 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
|
||||
|
||||
spin_lock_bh(&ar->htt.tx_lock);
|
||||
ath10k_htt_tx_dec_pending(htt);
|
||||
if (is_mgmt)
|
||||
ath10k_htt_tx_mgmt_dec_pending(htt);
|
||||
spin_unlock_bh(&ar->htt.tx_lock);
|
||||
|
||||
return ret;
|
||||
@@ -3894,7 +3916,7 @@ void __ath10k_scan_finish(struct ath10k *ar)
|
||||
ar->scan.roc_freq = 0;
|
||||
ath10k_offchan_tx_purge(ar);
|
||||
cancel_delayed_work(&ar->scan.timeout);
|
||||
complete_all(&ar->scan.completed);
|
||||
complete(&ar->scan.completed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -4100,13 +4122,29 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
struct ath10k_txq *artxq = (void *)txq->drv_priv;
|
||||
struct ieee80211_txq *f_txq;
|
||||
struct ath10k_txq *f_artxq;
|
||||
int ret = 0;
|
||||
int max = 16;
|
||||
|
||||
spin_lock_bh(&ar->txqs_lock);
|
||||
if (list_empty(&artxq->list))
|
||||
list_add_tail(&artxq->list, &ar->txqs);
|
||||
|
||||
f_artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list);
|
||||
f_txq = container_of((void *)f_artxq, struct ieee80211_txq, drv_priv);
|
||||
list_del_init(&f_artxq->list);
|
||||
|
||||
while (ath10k_mac_tx_can_push(hw, f_txq) && max--) {
|
||||
ret = ath10k_mac_tx_push_txq(hw, f_txq);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
if (ret != -ENOENT)
|
||||
list_add_tail(&f_artxq->list, &ar->txqs);
|
||||
spin_unlock_bh(&ar->txqs_lock);
|
||||
|
||||
ath10k_mac_tx_push_pending(ar);
|
||||
ath10k_htt_tx_txq_update(hw, f_txq);
|
||||
ath10k_htt_tx_txq_update(hw, txq);
|
||||
}
|
||||
|
||||
@@ -5186,7 +5224,7 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
|
||||
|
||||
ret = ath10k_monitor_recalc(ar);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to recalc montior: %d\n", ret);
|
||||
ath10k_warn(ar, "failed to recalc monitor: %d\n", ret);
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
@@ -5984,8 +6022,8 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
||||
* Existing station deletion.
|
||||
*/
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac vdev %d peer delete %pM (sta gone)\n",
|
||||
arvif->vdev_id, sta->addr);
|
||||
"mac vdev %d peer delete %pM sta %pK (sta gone)\n",
|
||||
arvif->vdev_id, sta->addr, sta);
|
||||
|
||||
ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr);
|
||||
if (ret)
|
||||
@@ -6001,7 +6039,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
||||
continue;
|
||||
|
||||
if (peer->sta == sta) {
|
||||
ath10k_warn(ar, "found sta peer %pM (ptr %p id %d) entry on vdev %i after it was supposedly removed\n",
|
||||
ath10k_warn(ar, "found sta peer %pM (ptr %pK id %d) entry on vdev %i after it was supposedly removed\n",
|
||||
sta->addr, peer, i, arvif->vdev_id);
|
||||
peer->sta = NULL;
|
||||
|
||||
@@ -6538,7 +6576,7 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ath10k_mac_update_bss_chan_survey(ar, survey->channel);
|
||||
ath10k_mac_update_bss_chan_survey(ar, &sband->channels[idx]);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
memcpy(survey, ar_survey, sizeof(*survey));
|
||||
@@ -7134,7 +7172,7 @@ ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw,
|
||||
struct ath10k *ar = hw->priv;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac chanctx add freq %hu width %d ptr %p\n",
|
||||
"mac chanctx add freq %hu width %d ptr %pK\n",
|
||||
ctx->def.chan->center_freq, ctx->def.width, ctx);
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
@@ -7158,7 +7196,7 @@ ath10k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
|
||||
struct ath10k *ar = hw->priv;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac chanctx remove freq %hu width %d ptr %p\n",
|
||||
"mac chanctx remove freq %hu width %d ptr %pK\n",
|
||||
ctx->def.chan->center_freq, ctx->def.width, ctx);
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
@@ -7223,7 +7261,7 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac chanctx change freq %hu width %d ptr %p changed %x\n",
|
||||
"mac chanctx change freq %hu width %d ptr %pK changed %x\n",
|
||||
ctx->def.chan->center_freq, ctx->def.width, ctx, changed);
|
||||
|
||||
/* This shouldn't really happen because channel switching should use
|
||||
@@ -7281,7 +7319,7 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac chanctx assign ptr %p vdev_id %i\n",
|
||||
"mac chanctx assign ptr %pK vdev_id %i\n",
|
||||
ctx, arvif->vdev_id);
|
||||
|
||||
if (WARN_ON(arvif->is_started)) {
|
||||
@@ -7342,7 +7380,7 @@ ath10k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac chanctx unassign ptr %p vdev_id %i\n",
|
||||
"mac chanctx unassign ptr %pK vdev_id %i\n",
|
||||
ctx, arvif->vdev_id);
|
||||
|
||||
WARN_ON(!arvif->is_started);
|
||||
|
||||
@@ -1506,12 +1506,10 @@ void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe,
|
||||
ath10k_ce_per_engine_service(ar, pipe);
|
||||
}
|
||||
|
||||
void ath10k_pci_kill_tasklet(struct ath10k *ar)
|
||||
static void ath10k_pci_rx_retry_sync(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
||||
tasklet_kill(&ar_pci->intr_tq);
|
||||
|
||||
del_timer_sync(&ar_pci->rx_post_retry);
|
||||
}
|
||||
|
||||
@@ -1570,7 +1568,7 @@ void ath10k_pci_hif_get_default_pipe(struct ath10k *ar,
|
||||
ul_pipe, dl_pipe);
|
||||
}
|
||||
|
||||
static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
|
||||
void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
@@ -1693,14 +1691,12 @@ static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
|
||||
static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
|
||||
{
|
||||
struct ath10k *ar;
|
||||
struct ath10k_pci *ar_pci;
|
||||
struct ath10k_ce_pipe *ce_pipe;
|
||||
struct ath10k_ce_ring *ce_ring;
|
||||
struct sk_buff *skb;
|
||||
int i;
|
||||
|
||||
ar = pci_pipe->hif_ce_state;
|
||||
ar_pci = ath10k_pci_priv(ar);
|
||||
ce_pipe = pci_pipe->ce_hdl;
|
||||
ce_ring = ce_pipe->src_ring;
|
||||
|
||||
@@ -1753,7 +1749,7 @@ void ath10k_pci_ce_deinit(struct ath10k *ar)
|
||||
|
||||
void ath10k_pci_flush(struct ath10k *ar)
|
||||
{
|
||||
ath10k_pci_kill_tasklet(ar);
|
||||
ath10k_pci_rx_retry_sync(ar);
|
||||
ath10k_pci_buffer_cleanup(ar);
|
||||
}
|
||||
|
||||
@@ -1780,6 +1776,8 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
|
||||
ath10k_pci_irq_disable(ar);
|
||||
ath10k_pci_irq_sync(ar);
|
||||
ath10k_pci_flush(ar);
|
||||
napi_synchronize(&ar->napi);
|
||||
napi_disable(&ar->napi);
|
||||
|
||||
spin_lock_irqsave(&ar_pci->ps_lock, flags);
|
||||
WARN_ON(ar_pci->ps_wake_refcount > 0);
|
||||
@@ -2533,6 +2531,7 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
|
||||
ath10k_err(ar, "could not wake up target CPU: %d\n", ret);
|
||||
goto err_ce;
|
||||
}
|
||||
napi_enable(&ar->napi);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -2725,7 +2724,7 @@ static int ath10k_pci_hif_fetch_cal_eeprom(struct ath10k *ar, void **data,
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
kfree(data);
|
||||
kfree(caldata);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -2772,35 +2771,53 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg)
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) {
|
||||
if (!ath10k_pci_irq_pending(ar))
|
||||
return IRQ_NONE;
|
||||
if ((ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) &&
|
||||
!ath10k_pci_irq_pending(ar))
|
||||
return IRQ_NONE;
|
||||
|
||||
ath10k_pci_disable_and_clear_legacy_irq(ar);
|
||||
}
|
||||
|
||||
tasklet_schedule(&ar_pci->intr_tq);
|
||||
ath10k_pci_disable_and_clear_legacy_irq(ar);
|
||||
ath10k_pci_irq_msi_fw_mask(ar);
|
||||
napi_schedule(&ar->napi);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void ath10k_pci_tasklet(unsigned long data)
|
||||
static int ath10k_pci_napi_poll(struct napi_struct *ctx, int budget)
|
||||
{
|
||||
struct ath10k *ar = (struct ath10k *)data;
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
struct ath10k *ar = container_of(ctx, struct ath10k, napi);
|
||||
int done = 0;
|
||||
|
||||
if (ath10k_pci_has_fw_crashed(ar)) {
|
||||
ath10k_pci_irq_disable(ar);
|
||||
ath10k_pci_fw_crashed_clear(ar);
|
||||
ath10k_pci_fw_crashed_dump(ar);
|
||||
return;
|
||||
napi_complete(ctx);
|
||||
return done;
|
||||
}
|
||||
|
||||
ath10k_ce_per_engine_service_any(ar);
|
||||
|
||||
/* Re-enable legacy irq that was disabled in the irq handler */
|
||||
if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY)
|
||||
done = ath10k_htt_txrx_compl_task(ar, budget);
|
||||
|
||||
if (done < budget) {
|
||||
napi_complete(ctx);
|
||||
/* In case of MSI, it is possible that interrupts are received
|
||||
* while NAPI poll is inprogress. So pending interrupts that are
|
||||
* received after processing all copy engine pipes by NAPI poll
|
||||
* will not be handled again. This is causing failure to
|
||||
* complete boot sequence in x86 platform. So before enabling
|
||||
* interrupts safer to check for pending interrupts for
|
||||
* immediate servicing.
|
||||
*/
|
||||
if (CE_INTERRUPT_SUMMARY(ar)) {
|
||||
napi_reschedule(ctx);
|
||||
goto out;
|
||||
}
|
||||
ath10k_pci_enable_legacy_irq(ar);
|
||||
ath10k_pci_irq_msi_fw_unmask(ar);
|
||||
}
|
||||
|
||||
out:
|
||||
return done;
|
||||
}
|
||||
|
||||
static int ath10k_pci_request_irq_msi(struct ath10k *ar)
|
||||
@@ -2858,11 +2875,10 @@ static void ath10k_pci_free_irq(struct ath10k *ar)
|
||||
free_irq(ar_pci->pdev->irq, ar);
|
||||
}
|
||||
|
||||
void ath10k_pci_init_irq_tasklets(struct ath10k *ar)
|
||||
void ath10k_pci_init_napi(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
||||
tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long)ar);
|
||||
netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_pci_napi_poll,
|
||||
ATH10K_NAPI_BUDGET);
|
||||
}
|
||||
|
||||
static int ath10k_pci_init_irq(struct ath10k *ar)
|
||||
@@ -2870,7 +2886,7 @@ static int ath10k_pci_init_irq(struct ath10k *ar)
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
int ret;
|
||||
|
||||
ath10k_pci_init_irq_tasklets(ar);
|
||||
ath10k_pci_init_napi(ar);
|
||||
|
||||
if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_AUTO)
|
||||
ath10k_info(ar, "limiting irq mode to: %d\n",
|
||||
@@ -3062,7 +3078,7 @@ static int ath10k_pci_claim(struct ath10k *ar)
|
||||
goto err_master;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot pci_mem 0x%p\n", ar_pci->mem);
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot pci_mem 0x%pK\n", ar_pci->mem);
|
||||
return 0;
|
||||
|
||||
err_master:
|
||||
@@ -3131,7 +3147,8 @@ int ath10k_pci_setup_resource(struct ath10k *ar)
|
||||
|
||||
void ath10k_pci_release_resource(struct ath10k *ar)
|
||||
{
|
||||
ath10k_pci_kill_tasklet(ar);
|
||||
ath10k_pci_rx_retry_sync(ar);
|
||||
netif_napi_del(&ar->napi);
|
||||
ath10k_pci_ce_deinit(ar);
|
||||
ath10k_pci_free_pipes(ar);
|
||||
}
|
||||
@@ -3297,7 +3314,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
err_free_irq:
|
||||
ath10k_pci_free_irq(ar);
|
||||
ath10k_pci_kill_tasklet(ar);
|
||||
ath10k_pci_rx_retry_sync(ar);
|
||||
|
||||
err_deinit_irq:
|
||||
ath10k_pci_deinit_irq(ar);
|
||||
|
||||
@@ -177,8 +177,6 @@ struct ath10k_pci {
|
||||
/* Operating interrupt mode */
|
||||
enum ath10k_pci_irq_mode oper_irq_mode;
|
||||
|
||||
struct tasklet_struct intr_tq;
|
||||
|
||||
struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX];
|
||||
|
||||
/* Copy Engine used for Diagnostic Accesses */
|
||||
@@ -294,8 +292,7 @@ void ath10k_pci_free_pipes(struct ath10k *ar);
|
||||
void ath10k_pci_free_pipes(struct ath10k *ar);
|
||||
void ath10k_pci_rx_replenish_retry(unsigned long ptr);
|
||||
void ath10k_pci_ce_deinit(struct ath10k *ar);
|
||||
void ath10k_pci_init_irq_tasklets(struct ath10k *ar);
|
||||
void ath10k_pci_kill_tasklet(struct ath10k *ar);
|
||||
void ath10k_pci_init_napi(struct ath10k *ar);
|
||||
int ath10k_pci_init_pipes(struct ath10k *ar);
|
||||
int ath10k_pci_init_config(struct ath10k *ar);
|
||||
void ath10k_pci_rx_post(struct ath10k *ar);
|
||||
@@ -303,6 +300,7 @@ void ath10k_pci_flush(struct ath10k *ar);
|
||||
void ath10k_pci_enable_legacy_irq(struct ath10k *ar);
|
||||
bool ath10k_pci_irq_pending(struct ath10k *ar);
|
||||
void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar);
|
||||
void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar);
|
||||
int ath10k_pci_wait_for_target_init(struct ath10k *ar);
|
||||
int ath10k_pci_setup_resource(struct ath10k *ar);
|
||||
void ath10k_pci_release_resource(struct ath10k *ar);
|
||||
|
||||
@@ -134,17 +134,18 @@ ath10k_swap_code_seg_alloc(struct ath10k *ar, size_t swap_bin_len)
|
||||
return seg_info;
|
||||
}
|
||||
|
||||
int ath10k_swap_code_seg_configure(struct ath10k *ar)
|
||||
int ath10k_swap_code_seg_configure(struct ath10k *ar,
|
||||
const struct ath10k_fw_file *fw_file)
|
||||
{
|
||||
int ret;
|
||||
struct ath10k_swap_code_seg_info *seg_info = NULL;
|
||||
|
||||
if (!ar->swap.firmware_swap_code_seg_info)
|
||||
if (!fw_file->firmware_swap_code_seg_info)
|
||||
return 0;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot found firmware code swap binary\n");
|
||||
|
||||
seg_info = ar->swap.firmware_swap_code_seg_info;
|
||||
seg_info = fw_file->firmware_swap_code_seg_info;
|
||||
|
||||
ret = ath10k_bmi_write_memory(ar, seg_info->target_addr,
|
||||
&seg_info->seg_hw_info,
|
||||
@@ -158,28 +159,29 @@ int ath10k_swap_code_seg_configure(struct ath10k *ar)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath10k_swap_code_seg_release(struct ath10k *ar)
|
||||
void ath10k_swap_code_seg_release(struct ath10k *ar,
|
||||
struct ath10k_fw_file *fw_file)
|
||||
{
|
||||
ath10k_swap_code_seg_free(ar, ar->swap.firmware_swap_code_seg_info);
|
||||
ath10k_swap_code_seg_free(ar, fw_file->firmware_swap_code_seg_info);
|
||||
|
||||
/* FIXME: these two assignments look to bein wrong place! Shouldn't
|
||||
* they be in ath10k_core_free_firmware_files() like the rest?
|
||||
*/
|
||||
ar->normal_mode_fw.fw_file.codeswap_data = NULL;
|
||||
ar->normal_mode_fw.fw_file.codeswap_len = 0;
|
||||
fw_file->codeswap_data = NULL;
|
||||
fw_file->codeswap_len = 0;
|
||||
|
||||
ar->swap.firmware_swap_code_seg_info = NULL;
|
||||
fw_file->firmware_swap_code_seg_info = NULL;
|
||||
}
|
||||
|
||||
int ath10k_swap_code_seg_init(struct ath10k *ar)
|
||||
int ath10k_swap_code_seg_init(struct ath10k *ar, struct ath10k_fw_file *fw_file)
|
||||
{
|
||||
int ret;
|
||||
struct ath10k_swap_code_seg_info *seg_info;
|
||||
const void *codeswap_data;
|
||||
size_t codeswap_len;
|
||||
|
||||
codeswap_data = ar->normal_mode_fw.fw_file.codeswap_data;
|
||||
codeswap_len = ar->normal_mode_fw.fw_file.codeswap_len;
|
||||
codeswap_data = fw_file->codeswap_data;
|
||||
codeswap_len = fw_file->codeswap_len;
|
||||
|
||||
if (!codeswap_len || !codeswap_data)
|
||||
return 0;
|
||||
@@ -200,7 +202,7 @@ int ath10k_swap_code_seg_init(struct ath10k *ar)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ar->swap.firmware_swap_code_seg_info = seg_info;
|
||||
fw_file->firmware_swap_code_seg_info = seg_info;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
/* Currently only one swap segment is supported */
|
||||
#define ATH10K_SWAP_CODE_SEG_NUM_SUPPORTED 1
|
||||
|
||||
struct ath10k_fw_file;
|
||||
|
||||
struct ath10k_swap_code_seg_tlv {
|
||||
__le32 address;
|
||||
__le32 length;
|
||||
@@ -58,8 +60,11 @@ struct ath10k_swap_code_seg_info {
|
||||
dma_addr_t paddr[ATH10K_SWAP_CODE_SEG_NUM_SUPPORTED];
|
||||
};
|
||||
|
||||
int ath10k_swap_code_seg_configure(struct ath10k *ar);
|
||||
void ath10k_swap_code_seg_release(struct ath10k *ar);
|
||||
int ath10k_swap_code_seg_init(struct ath10k *ar);
|
||||
int ath10k_swap_code_seg_configure(struct ath10k *ar,
|
||||
const struct ath10k_fw_file *fw_file);
|
||||
void ath10k_swap_code_seg_release(struct ath10k *ar,
|
||||
struct ath10k_fw_file *fw_file);
|
||||
int ath10k_swap_code_seg_init(struct ath10k *ar,
|
||||
struct ath10k_fw_file *fw_file);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "wmi.h"
|
||||
#include "hif.h"
|
||||
#include "hw.h"
|
||||
#include "core.h"
|
||||
|
||||
#include "testmode_i.h"
|
||||
|
||||
@@ -45,7 +46,7 @@ bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb)
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
|
||||
"testmode event wmi cmd_id %d skb %p skb->len %d\n",
|
||||
"testmode event wmi cmd_id %d skb %pK skb->len %d\n",
|
||||
cmd_id, skb, skb->len);
|
||||
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
|
||||
@@ -240,6 +241,18 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ar->testmode.utf_mode_fw.fw_file.codeswap_data &&
|
||||
ar->testmode.utf_mode_fw.fw_file.codeswap_len) {
|
||||
ret = ath10k_swap_code_seg_init(ar,
|
||||
&ar->testmode.utf_mode_fw.fw_file);
|
||||
if (ret) {
|
||||
ath10k_warn(ar,
|
||||
"failed to init utf code swap segment: %d\n",
|
||||
ret);
|
||||
goto err_release_utf_mode_fw;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->testmode.utf_monitor = true;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
@@ -279,6 +292,11 @@ err_power_down:
|
||||
ath10k_hif_power_down(ar);
|
||||
|
||||
err_release_utf_mode_fw:
|
||||
if (ar->testmode.utf_mode_fw.fw_file.codeswap_data &&
|
||||
ar->testmode.utf_mode_fw.fw_file.codeswap_len)
|
||||
ath10k_swap_code_seg_release(ar,
|
||||
&ar->testmode.utf_mode_fw.fw_file);
|
||||
|
||||
release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware);
|
||||
ar->testmode.utf_mode_fw.fw_file.firmware = NULL;
|
||||
|
||||
@@ -301,6 +319,11 @@ static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar)
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
if (ar->testmode.utf_mode_fw.fw_file.codeswap_data &&
|
||||
ar->testmode.utf_mode_fw.fw_file.codeswap_len)
|
||||
ath10k_swap_code_seg_release(ar,
|
||||
&ar->testmode.utf_mode_fw.fw_file);
|
||||
|
||||
release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware);
|
||||
ar->testmode.utf_mode_fw.fw_file.firmware = NULL;
|
||||
|
||||
@@ -360,7 +383,7 @@ static int ath10k_tm_cmd_wmi(struct ath10k *ar, struct nlattr *tb[])
|
||||
cmd_id = nla_get_u32(tb[ATH10K_TM_ATTR_WMI_CMDID]);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
|
||||
"testmode cmd wmi cmd_id %d buf %p buf_len %d\n",
|
||||
"testmode cmd wmi cmd_id %d buf %pK buf_len %d\n",
|
||||
cmd_id, buf, buf_len);
|
||||
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", buf, buf_len);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user