summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKalle Valo <kvalo@codeaurora.org>2020-12-12 06:51:34 +0200
committerKalle Valo <kvalo@codeaurora.org>2020-12-12 06:51:34 +0200
commit7ab250385ec276b7b37a2ecc96d375a75b573bd4 (patch)
treec9b027b073a85ea22304722db936072368d10f24
parent7f469b6dc484cd5b2ea61763607892626afc2b21 (diff)
parentd1b0c33850d29b325fb4b26e9b0ea3e473125237 (diff)
downloadlinux-7ab250385ec276b7b37a2ecc96d375a75b573bd4.tar.gz
linux-7ab250385ec276b7b37a2ecc96d375a75b573bd4.tar.bz2
linux-7ab250385ec276b7b37a2ecc96d375a75b573bd4.zip
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for v5.11. Major changes: ath11k * suspend support for QCA6390 PCI devices * support TXOP duration based RTS threshold * mesh: add support for 256 bitmap in blockack frames in 11ax
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c54
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h4
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c6
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/sdio.c8
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/Makefile3
-rw-r--r--drivers/net/wireless/ath/ath11k/ahb.c9
-rw-r--r--drivers/net/wireless/ath/ath11k/ce.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/ce.h2
-rw-r--r--drivers/net/wireless/ath/ath11k/core.c100
-rw-r--r--drivers/net/wireless/ath/ath11k/core.h12
-rw-r--r--drivers/net/wireless/ath/ath11k/debugfs.c1
-rw-r--r--drivers/net/wireless/ath/ath11k/dp.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/dp.h2
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_rx.c48
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_rx.h3
-rw-r--r--drivers/net/wireless/ath/ath11k/hif.h32
-rw-r--r--drivers/net/wireless/ath/ath11k/htc.c31
-rw-r--r--drivers/net/wireless/ath/ath11k/htc.h10
-rw-r--r--drivers/net/wireless/ath/ath11k/hw.h7
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c48
-rw-r--r--drivers/net/wireless/ath/ath11k/mhi.c27
-rw-r--r--drivers/net/wireless/ath/ath11k/mhi.h3
-rw-r--r--drivers/net/wireless/ath/ath11k/pci.c227
-rw-r--r--drivers/net/wireless/ath/ath11k/pci.h25
-rw-r--r--drivers/net/wireless/ath/ath11k/qmi.c41
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.c178
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.h170
-rw-r--r--drivers/net/wireless/ath/ath11k/wow.c73
-rw-r--r--drivers/net/wireless/ath/ath11k/wow.h10
-rw-r--r--drivers/net/wireless/ath/ath5k/mac80211-ops.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/common-debug.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_debug.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c7
-rw-r--r--drivers/net/wireless/ath/carl9170/debug.c4
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c1
-rw-r--r--drivers/net/wireless/ath/wcn36xx/smd.c2
40 files changed, 1033 insertions, 131 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 796107b14d9f..eeb6ff6aa2e1 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1350,7 +1350,8 @@ out:
static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
const char *boardname,
- const char *fallback_boardname,
+ const char *fallback_boardname1,
+ const char *fallback_boardname2,
const char *filename)
{
size_t len, magic_len;
@@ -1399,8 +1400,11 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
ret = ath10k_core_search_bd(ar, boardname, data, len);
/* if we didn't find it and have a fallback name, try that */
- if (ret == -ENOENT && fallback_boardname)
- ret = ath10k_core_search_bd(ar, fallback_boardname, data, len);
+ if (ret == -ENOENT && fallback_boardname1)
+ ret = ath10k_core_search_bd(ar, fallback_boardname1, data, len);
+
+ if (ret == -ENOENT && fallback_boardname2)
+ ret = ath10k_core_search_bd(ar, fallback_boardname2, data, len);
if (ret == -ENOENT) {
ath10k_err(ar,
@@ -1420,7 +1424,8 @@ err:
}
static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
- size_t name_len, bool with_variant)
+ size_t name_len, bool with_variant,
+ bool with_chip_id)
{
/* strlen(',variant=') + strlen(ar->id.bdf_ext) */
char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 };
@@ -1439,7 +1444,7 @@ static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
}
if (ar->id.qmi_ids_valid) {
- if (with_variant && ar->id.bdf_ext[0] != '\0')
+ if (with_chip_id)
scnprintf(name, name_len,
"bus=%s,qmi-board-id=%x,qmi-chip-id=%x%s",
ath10k_bus_str(ar->hif.bus),
@@ -1483,21 +1488,36 @@ static int ath10k_core_create_eboard_name(struct ath10k *ar, char *name,
int ath10k_core_fetch_board_file(struct ath10k *ar, int bd_ie_type)
{
- char boardname[100], fallback_boardname[100];
+ char boardname[100], fallback_boardname1[100], fallback_boardname2[100];
int ret;
if (bd_ie_type == ATH10K_BD_IE_BOARD) {
+ /* With variant and chip id */
ret = ath10k_core_create_board_name(ar, boardname,
- sizeof(boardname), true);
+ sizeof(boardname), true,
+ true);
if (ret) {
ath10k_err(ar, "failed to create board name: %d", ret);
return ret;
}
- ret = ath10k_core_create_board_name(ar, fallback_boardname,
- sizeof(boardname), false);
+ /* Without variant and only chip-id */
+ ret = ath10k_core_create_board_name(ar, fallback_boardname1,
+ sizeof(boardname), false,
+ true);
if (ret) {
- ath10k_err(ar, "failed to create fallback board name: %d", ret);
+ ath10k_err(ar, "failed to create 1st fallback board name: %d",
+ ret);
+ return ret;
+ }
+
+ /* Without variant and without chip-id */
+ ret = ath10k_core_create_board_name(ar, fallback_boardname2,
+ sizeof(boardname), false,
+ false);
+ if (ret) {
+ ath10k_err(ar, "failed to create 2nd fallback board name: %d",
+ ret);
return ret;
}
} else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) {
@@ -1511,7 +1531,8 @@ int ath10k_core_fetch_board_file(struct ath10k *ar, int bd_ie_type)
ar->bd_api = 2;
ret = ath10k_core_fetch_board_data_api_n(ar, boardname,
- fallback_boardname,
+ fallback_boardname1,
+ fallback_boardname2,
ATH10K_BOARD_API2_FILE);
if (!ret)
goto success;
@@ -2273,6 +2294,17 @@ static int ath10k_init_hw_params(struct ath10k *ar)
return 0;
}
+void ath10k_core_start_recovery(struct ath10k *ar)
+{
+ if (test_and_set_bit(ATH10K_FLAG_RESTARTING, &ar->dev_flags)) {
+ ath10k_warn(ar, "already restarting\n");
+ return;
+ }
+
+ queue_work(ar->workqueue, &ar->restart_work);
+}
+EXPORT_SYMBOL(ath10k_core_start_recovery);
+
static void ath10k_core_restart(struct work_struct *work)
{
struct ath10k *ar = container_of(work, struct ath10k, restart_work);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index f3853bd26275..51f7e960e297 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -865,6 +865,9 @@ enum ath10k_dev_flags {
/* Per Station statistics service */
ATH10K_FLAG_PEER_STATS,
+
+ /* Indicates that ath10k device is during recovery process and not complete */
+ ATH10K_FLAG_RESTARTING,
};
enum ath10k_cal_mode {
@@ -1320,6 +1323,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
const struct ath10k_fw_components *fw_components);
int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
void ath10k_core_stop(struct ath10k *ar);
+void ath10k_core_start_recovery(struct ath10k *ar);
int ath10k_core_register(struct ath10k *ar,
const struct ath10k_bus_params *bus_params);
void ath10k_core_unregister(struct ath10k *ar);
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index b72cd81fdc79..fd052f6ed019 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -583,7 +583,7 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
ret = ath10k_debug_fw_assert(ar);
} else if (!strcmp(buf, "hw-restart")) {
ath10k_info(ar, "user requested hw restart\n");
- queue_work(ar->workqueue, &ar->restart_work);
+ ath10k_core_start_recovery(ar);
ret = 0;
} else {
ret = -EINVAL;
@@ -2005,7 +2005,7 @@ static ssize_t ath10k_write_btcoex(struct file *file,
}
} else {
ath10k_info(ar, "restarting firmware due to btcoex change");
- queue_work(ar->workqueue, &ar->restart_work);
+ ath10k_core_start_recovery(ar);
}
if (val)
@@ -2136,7 +2136,7 @@ static ssize_t ath10k_write_peer_stats(struct file *file,
ath10k_info(ar, "restarting firmware due to Peer stats change");
- queue_work(ar->workqueue, &ar->restart_work);
+ ath10k_core_start_recovery(ar);
ret = count;
exit:
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index dc32c7852a24..7d98250380ec 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -7932,6 +7932,7 @@ static void ath10k_reconfig_complete(struct ieee80211_hw *hw,
ath10k_info(ar, "device successfully recovered\n");
ar->state = ATH10K_STATE_ON;
ieee80211_wake_queues(ar->hw);
+ clear_bit(ATH10K_FLAG_RESTARTING, &ar->dev_flags);
}
mutex_unlock(&ar->conf_mutex);
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 8ab262931dce..2328df09875c 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -1774,7 +1774,7 @@ static void ath10k_pci_fw_dump_work(struct work_struct *work)
mutex_unlock(&ar->dump_mutex);
- queue_work(ar->workqueue, &ar->restart_work);
+ ath10k_core_start_recovery(ar);
}
static void ath10k_pci_fw_crashed_dump(struct ath10k *ar)
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index aa1f86028f01..c415090d1f37 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -561,7 +561,7 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH);
ret = -ENOMEM;
- queue_work(ar->workqueue, &ar->restart_work);
+ ath10k_core_start_recovery(ar);
ath10k_warn(ar, "exceeds length, start recovery\n");
goto err;
@@ -960,7 +960,7 @@ static int ath10k_sdio_mbox_read_int_status(struct ath10k *ar,
ret = ath10k_sdio_read(ar, MBOX_HOST_INT_STATUS_ADDRESS,
irq_proc_reg, sizeof(*irq_proc_reg));
if (ret) {
- queue_work(ar->workqueue, &ar->restart_work);
+ ath10k_core_start_recovery(ar);
ath10k_warn(ar, "read int status fail, start recovery\n");
goto out;
}
@@ -2237,7 +2237,7 @@ static bool ath10k_sdio_is_fast_dump_supported(struct ath10k *ar)
ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio hi_option_flag2 %x\n", param);
- return param & HI_OPTION_SDIO_CRASH_DUMP_ENHANCEMENT_FW;
+ return !!(param & HI_OPTION_SDIO_CRASH_DUMP_ENHANCEMENT_FW);
}
static void ath10k_sdio_dump_registers(struct ath10k *ar,
@@ -2501,7 +2501,7 @@ void ath10k_sdio_fw_crashed_dump(struct ath10k *ar)
ath10k_sdio_enable_intrs(ar);
- queue_work(ar->workqueue, &ar->restart_work);
+ ath10k_core_start_recovery(ar);
}
static int ath10k_sdio_probe(struct sdio_func *func,
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index fd41f25456dc..bf9a8cb713dc 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -1305,7 +1305,7 @@ int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type)
switch (type) {
case ATH10K_QMI_EVENT_FW_READY_IND:
if (test_bit(ATH10K_SNOC_FLAG_REGISTERED, &ar_snoc->flags)) {
- queue_work(ar->workqueue, &ar->restart_work);
+ ath10k_core_start_recovery(ar);
break;
}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index c491acebdb46..1f33947e2088 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1937,7 +1937,7 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
if (ret == -EAGAIN) {
ath10k_warn(ar, "wmi command %d timeout, restarting hardware\n",
cmd_id);
- queue_work(ar->workqueue, &ar->restart_work);
+ ath10k_core_start_recovery(ar);
}
return ret;
diff --git a/drivers/net/wireless/ath/ath11k/Makefile b/drivers/net/wireless/ath/ath11k/Makefile
index c41d87bd025a..c1fce4159f1f 100644
--- a/drivers/net/wireless/ath/ath11k/Makefile
+++ b/drivers/net/wireless/ath/ath11k/Makefile
@@ -16,7 +16,8 @@ ath11k-y += core.o \
ce.o \
peer.o \
dbring.o \
- hw.o
+ hw.o \
+ wow.o
ath11k-$(CONFIG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o
ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o
diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
index c7843f461dd2..d4ef45cd0685 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -747,6 +747,13 @@ static int ath11k_ahb_remove(struct platform_device *pdev)
struct ath11k_base *ab = platform_get_drvdata(pdev);
unsigned long left;
+ if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
+ ath11k_ahb_power_down(ab);
+ ath11k_debugfs_soc_destroy(ab);
+ ath11k_qmi_deinit_service(ab);
+ goto qmi_fail;
+ }
+
reinit_completion(&ab->driver_recovery);
if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags)) {
@@ -760,8 +767,8 @@ static int ath11k_ahb_remove(struct platform_device *pdev)
cancel_work_sync(&ab->restart_work);
ath11k_core_deinit(ab);
+qmi_fail:
ath11k_ahb_free_irq(ab);
-
ath11k_hal_srng_deinit(ab);
ath11k_ce_free_pipes(ab);
ath11k_core_free(ab);
diff --git a/drivers/net/wireless/ath/ath11k/ce.c b/drivers/net/wireless/ath/ath11k/ce.c
index 9d730f8ac816..987c65010272 100644
--- a/drivers/net/wireless/ath/ath11k/ce.c
+++ b/drivers/net/wireless/ath/ath11k/ce.c
@@ -195,7 +195,7 @@ static bool ath11k_ce_need_shadow_fix(int ce_id)
return false;
}
-static void ath11k_ce_stop_shadow_timers(struct ath11k_base *ab)
+void ath11k_ce_stop_shadow_timers(struct ath11k_base *ab)
{
int i;
diff --git a/drivers/net/wireless/ath/ath11k/ce.h b/drivers/net/wireless/ath/ath11k/ce.h
index 269b599ac0b0..d6eeef919349 100644
--- a/drivers/net/wireless/ath/ath11k/ce.h
+++ b/drivers/net/wireless/ath/ath11k/ce.h
@@ -190,4 +190,6 @@ int ath11k_ce_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
int ath11k_ce_attr_attach(struct ath11k_base *ab);
void ath11k_ce_get_shadow_config(struct ath11k_base *ab,
u32 **shadow_cfg, u32 *shadow_cfg_len);
+void ath11k_ce_stop_shadow_timers(struct ath11k_base *ab);
+
#endif
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index da20ed752ca5..b97c38b9a270 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -13,6 +13,7 @@
#include "dp_rx.h"
#include "debug.h"
#include "hif.h"
+#include "wow.h"
unsigned int ath11k_debug_mask;
EXPORT_SYMBOL(ath11k_debug_mask);
@@ -51,7 +52,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq8074,
.svc_to_ce_map_len = 21,
.single_pdev_only = false,
- .needs_band_to_mac = true,
.rxdma1_enable = true,
.num_rxmda_per_pdev = 1,
.rx_mac_buf_ring = false,
@@ -67,6 +67,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = false,
.idle_ps = false,
.cold_boot_calib = true,
+ .supports_suspend = false,
},
{
.hw_rev = ATH11K_HW_IPQ6018_HW10,
@@ -89,7 +90,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq6018,
.svc_to_ce_map_len = 19,
.single_pdev_only = false,
- .needs_band_to_mac = true,
.rxdma1_enable = true,
.num_rxmda_per_pdev = 1,
.rx_mac_buf_ring = false,
@@ -105,6 +105,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = false,
.idle_ps = false,
.cold_boot_calib = true,
+ .supports_suspend = false,
},
{
.name = "qca6390 hw2.0",
@@ -127,7 +128,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
.svc_to_ce_map_len = 14,
.single_pdev_only = true,
- .needs_band_to_mac = false,
.rxdma1_enable = false,
.num_rxmda_per_pdev = 2,
.rx_mac_buf_ring = true,
@@ -142,9 +142,91 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = true,
.idle_ps = true,
.cold_boot_calib = false,
+ .supports_suspend = true,
},
};
+int ath11k_core_suspend(struct ath11k_base *ab)
+{
+ int ret;
+
+ if (!ab->hw_params.supports_suspend)
+ return -EOPNOTSUPP;
+
+ /* TODO: there can frames in queues so for now add delay as a hack.
+ * Need to implement to handle and remove this delay.
+ */
+ msleep(500);
+
+ ret = ath11k_dp_rx_pktlog_stop(ab, true);
+ if (ret) {
+ ath11k_warn(ab, "failed to stop dp rx (and timer) pktlog during suspend: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = ath11k_wow_enable(ab);
+ if (ret) {
+ ath11k_warn(ab, "failed to enable wow during suspend: %d\n", ret);
+ return ret;
+ }
+
+ ret = ath11k_dp_rx_pktlog_stop(ab, false);
+ if (ret) {
+ ath11k_warn(ab, "failed to stop dp rx pktlog during suspend: %d\n",
+ ret);
+ return ret;
+ }
+
+ ath11k_ce_stop_shadow_timers(ab);
+ ath11k_dp_stop_shadow_timers(ab);
+
+ ath11k_hif_irq_disable(ab);
+ ath11k_hif_ce_irq_disable(ab);
+
+ ret = ath11k_hif_suspend(ab);
+ if (!ret) {
+ ath11k_warn(ab, "failed to suspend hif: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(ath11k_core_suspend);
+
+int ath11k_core_resume(struct ath11k_base *ab)
+{
+ int ret;
+
+ if (!ab->hw_params.supports_suspend)
+ return -EOPNOTSUPP;
+
+ ret = ath11k_hif_resume(ab);
+ if (ret) {
+ ath11k_warn(ab, "failed to resume hif during resume: %d\n", ret);
+ return ret;
+ }
+
+ ath11k_hif_ce_irq_enable(ab);
+ ath11k_hif_irq_enable(ab);
+
+ ret = ath11k_dp_rx_pktlog_start(ab);
+ if (ret) {
+ ath11k_warn(ab, "failed to start rx pktlog during resume: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = ath11k_wow_wakeup(ab);
+ if (ret) {
+ ath11k_warn(ab, "failed to wakeup wow during resume: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(ath11k_core_resume);
+
int ath11k_core_check_dt(struct ath11k_base *ab)
{
size_t max_len = sizeof(ab->qmi.target.bdf_ext);
@@ -646,6 +728,15 @@ static int ath11k_core_start(struct ath11k_base *ab,
goto err_reo_cleanup;
}
+ /* put hardware to DBS mode */
+ if (ab->hw_params.single_pdev_only) {
+ ret = ath11k_wmi_set_hw_mode(ab, WMI_HOST_HW_MODE_DBS);
+ if (ret) {
+ ath11k_err(ab, "failed to send dbs mode: %d\n", ret);
+ goto err_hif_stop;
+ }
+ }
+
ret = ath11k_dp_tx_htt_h2t_ver_req_msg(ab);
if (ret) {
ath11k_err(ab, "failed to send htt version request message: %d\n",
@@ -962,6 +1053,9 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
init_waitqueue_head(&ab->qmi.cold_boot_waitq);
INIT_WORK(&ab->restart_work, ath11k_core_restart);
timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
+ init_completion(&ab->htc_suspend);
+ init_completion(&ab->wow.wakeup_completed);
+
ab->dev = dev;
ab->bus_params = *bus_params;
ab->hif.bus = bus;
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 317b15e333d3..799bf3de1117 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -185,6 +185,8 @@ enum ath11k_dev_flags {
ATH11K_FLAG_RECOVERY,
ATH11K_FLAG_UNREGISTERING,
ATH11K_FLAG_REGISTERED,
+ ATH11K_FLAG_QMI_FAIL,
+ ATH11K_FLAG_HTC_SUSPEND_COMPLETE,
};
enum ath11k_monitor_flags {
@@ -464,6 +466,7 @@ struct ath11k {
struct ieee80211_sband_iftype_data
iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES];
} mac;
+
unsigned long dev_flags;
unsigned int filter_flags;
unsigned long monitor_flags;
@@ -670,6 +673,10 @@ struct ath11k_base {
const struct ath11k_hif_ops *ops;
} hif;
+ struct {
+ struct completion wakeup_completed;
+ } wow;
+
struct ath11k_ce ce;
struct timer_list rx_replenish_retry;
struct ath11k_hal hal;
@@ -731,6 +738,9 @@ struct ath11k_base {
u32 num_db_cap;
struct timer_list mon_reap_timer;
+
+ struct completion htc_suspend;
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
@@ -887,6 +897,8 @@ void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd);
int ath11k_core_check_dt(struct ath11k_base *ath11k);
void ath11k_core_halt(struct ath11k *ar);
+int ath11k_core_resume(struct ath11k_base *ab);
+int ath11k_core_suspend(struct ath11k_base *ab);
const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
const char *filename);
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
index 1b914e67d314..554feaf1ed5c 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
@@ -867,6 +867,7 @@ void ath11k_debugfs_soc_destroy(struct ath11k_base *ab)
debugfs_remove_recursive(ab->debugfs_ath11k);
ab->debugfs_ath11k = NULL;
}
+EXPORT_SYMBOL(ath11k_debugfs_soc_destroy);
void ath11k_debugfs_fw_stats_init(struct ath11k *ar)
{
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index f977056ae5e8..04f6c4e0658b 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -304,7 +304,7 @@ int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,
return 0;
}
-static void ath11k_dp_stop_shadow_timers(struct ath11k_base *ab)
+void ath11k_dp_stop_shadow_timers(struct ath11k_base *ab)
{
int i;
diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h
index d4fd02375fad..ee768ccce46e 100644
--- a/drivers/net/wireless/ath/ath11k/dp.h
+++ b/drivers/net/wireless/ath/ath11k/dp.h
@@ -40,6 +40,7 @@ struct dp_rx_tid {
#define DP_REO_DESC_FREE_THRESHOLD 64
#define DP_REO_DESC_FREE_TIMEOUT_MS 1000
+#define DP_MON_PURGE_TIMEOUT_MS 100
#define DP_MON_SERVICE_BUDGET 128
struct dp_reo_cache_flush_elem {
@@ -1640,5 +1641,6 @@ void ath11k_dp_shadow_stop_timer(struct ath11k_base *ab,
void ath11k_dp_shadow_init_timer(struct ath11k_base *ab,
struct ath11k_hp_update_timer *update_timer,
u32 interval, u32 ring_id);
+void ath11k_dp_stop_shadow_timers(struct ath11k_base *ab);
#endif
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 5de619d5c4e2..205c0f1a40e9 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -274,6 +274,28 @@ static void ath11k_dp_service_mon_ring(struct timer_list *t)
msecs_to_jiffies(ATH11K_MON_TIMER_INTERVAL));
}
+static int ath11k_dp_purge_mon_ring(struct ath11k_base *ab)
+{
+ int i, reaped = 0;
+ unsigned long timeout = jiffies + msecs_to_jiffies(DP_MON_PURGE_TIMEOUT_MS);
+
+ do {
+ for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++)
+ reaped += ath11k_dp_rx_process_mon_rings(ab, i,
+ NULL,
+ DP_MON_SERVICE_BUDGET);
+
+ /* nothing more to reap */
+ if (reaped < DP_MON_SERVICE_BUDGET)
+ return 0;
+
+ } while (time_before(jiffies, timeout));
+
+ ath11k_warn(ab, "dp mon ring purge timeout");
+
+ return -ETIMEDOUT;
+}
+
/* Returns number of Rx buffers replenished */
int ath11k_dp_rxbufs_replenish(struct ath11k_base *ab, int mac_id,
struct dp_rxdma_ring *rx_ring,
@@ -5026,3 +5048,29 @@ int ath11k_dp_rx_pdev_mon_detach(struct ath11k *ar)
ath11k_dp_mon_link_free(ar);
return 0;
}
+
+int ath11k_dp_rx_pktlog_start(struct ath11k_base *ab)
+{
+ /* start reap timer */
+ mod_timer(&ab->mon_reap_timer,
+ jiffies + msecs_to_jiffies(ATH11K_MON_TIMER_INTERVAL));
+
+ return 0;
+}
+
+int ath11k_dp_rx_pktlog_stop(struct ath11k_base *ab, bool stop_timer)
+{
+ int ret;
+
+ if (stop_timer)
+ del_timer_sync(&ab->mon_reap_timer);
+
+ /* reap all the monitor related rings */
+ ret = ath11k_dp_purge_mon_ring(ab);
+ if (ret) {
+ ath11k_warn(ab, "failed to purge dp mon ring: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.h b/drivers/net/wireless/ath/ath11k/dp_rx.h
index fbea45f79c9b..bf399312b5ff 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.h
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.h
@@ -91,4 +91,7 @@ int ath11k_dp_rx_pdev_mon_detach(struct ath11k *ar);
int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar);
int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id);
+int ath11k_dp_rx_pktlog_start(struc