forked from Minki/linux
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
This commit is contained in:
commit
7ab250385e
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(struct ath11k_base *ab);
|
||||
int ath11k_dp_rx_pktlog_stop(struct ath11k_base *ab, bool stop_timer);
|
||||
|
||||
#endif /* ATH11K_DP_RX_H */
|
||||
|
@ -17,6 +17,8 @@ struct ath11k_hif_ops {
|
||||
void (*stop)(struct ath11k_base *sc);
|
||||
int (*power_up)(struct ath11k_base *sc);
|
||||
void (*power_down)(struct ath11k_base *sc);
|
||||
int (*suspend)(struct ath11k_base *ab);
|
||||
int (*resume)(struct ath11k_base *ab);
|
||||
int (*map_service_to_pipe)(struct ath11k_base *sc, u16 service_id,
|
||||
u8 *ul_pipe, u8 *dl_pipe);
|
||||
int (*get_user_msi_vector)(struct ath11k_base *ab, char *user_name,
|
||||
@ -24,8 +26,22 @@ struct ath11k_hif_ops {
|
||||
u32 *base_vector);
|
||||
void (*get_msi_address)(struct ath11k_base *ab, u32 *msi_addr_lo,
|
||||
u32 *msi_addr_hi);
|
||||
void (*ce_irq_enable)(struct ath11k_base *ab);
|
||||
void (*ce_irq_disable)(struct ath11k_base *ab);
|
||||
};
|
||||
|
||||
static inline void ath11k_hif_ce_irq_enable(struct ath11k_base *ab)
|
||||
{
|
||||
if (ab->hif.ops->ce_irq_enable)
|
||||
ab->hif.ops->ce_irq_enable(ab);
|
||||
}
|
||||
|
||||
static inline void ath11k_hif_ce_irq_disable(struct ath11k_base *ab)
|
||||
{
|
||||
if (ab->hif.ops->ce_irq_disable)
|
||||
ab->hif.ops->ce_irq_disable(ab);
|
||||
}
|
||||
|
||||
static inline int ath11k_hif_start(struct ath11k_base *sc)
|
||||
{
|
||||
return sc->hif.ops->start(sc);
|
||||
@ -56,6 +72,22 @@ static inline void ath11k_hif_power_down(struct ath11k_base *sc)
|
||||
sc->hif.ops->power_down(sc);
|
||||
}
|
||||
|
||||
static inline int ath11k_hif_suspend(struct ath11k_base *ab)
|
||||
{
|
||||
if (ab->hif.ops->suspend)
|
||||
return ab->hif.ops->suspend(ab);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ath11k_hif_resume(struct ath11k_base *ab)
|
||||
{
|
||||
if (ab->hif.ops->resume)
|
||||
return ab->hif.ops->resume(ab);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u32 ath11k_hif_read32(struct ath11k_base *sc, u32 address)
|
||||
{
|
||||
return sc->hif.ops->read32(sc, address);
|
||||
|
@ -60,9 +60,11 @@ static void ath11k_htc_prepare_tx_skb(struct ath11k_htc_ep *ep,
|
||||
memset(hdr, 0, sizeof(*hdr));
|
||||
hdr->htc_info = FIELD_PREP(HTC_HDR_ENDPOINTID, ep->eid) |
|
||||
FIELD_PREP(HTC_HDR_PAYLOADLEN,
|
||||
(skb->len - sizeof(*hdr))) |
|
||||
FIELD_PREP(HTC_HDR_FLAGS,
|
||||
ATH11K_HTC_FLAG_NEED_CREDIT_UPDATE);
|
||||
(skb->len - sizeof(*hdr)));
|
||||
|
||||
if (ep->tx_credit_flow_enabled)
|
||||
hdr->htc_info |= FIELD_PREP(HTC_HDR_FLAGS,
|
||||
ATH11K_HTC_FLAG_NEED_CREDIT_UPDATE);
|
||||
|
||||
spin_lock_bh(&ep->htc->tx_lock);
|
||||
hdr->ctrl_info = FIELD_PREP(HTC_HDR_CONTROLBYTES1, ep->seq_no++);
|
||||
@ -231,6 +233,18 @@ static int ath11k_htc_process_trailer(struct ath11k_htc *htc,
|
||||
return status;
|
||||
}
|
||||
|
||||
static void ath11k_htc_suspend_complete(struct ath11k_base *ab, bool ack)
|
||||
{
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot suspend complete %d\n", ack);
|
||||
|
||||
if (ack)
|
||||
set_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags);
|
||||
else
|
||||
clear_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags);
|
||||
|
||||
complete(&ab->htc_suspend);
|
||||
}
|
||||
|
||||
void ath11k_htc_rx_completion_handler(struct ath11k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@ -328,8 +342,17 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab,
|
||||
|
||||
complete(&htc->ctl_resp);
|
||||
break;
|
||||
case ATH11K_HTC_MSG_SEND_SUSPEND_COMPLETE:
|
||||
ath11k_htc_suspend_complete(ab, true);
|
||||
break;
|
||||
case ATH11K_HTC_MSG_NACK_SUSPEND:
|
||||
ath11k_htc_suspend_complete(ab, false);
|
||||
break;
|
||||
case ATH11K_HTC_MSG_WAKEUP_FROM_SUSPEND_ID:
|
||||
break;
|
||||
default:
|
||||
ath11k_warn(ab, "ignoring unsolicited htc ep0 event\n");
|
||||
ath11k_warn(ab, "ignoring unsolicited htc ep0 event %ld\n",
|
||||
FIELD_GET(HTC_MSG_MESSAGEID, msg->msg_svc_id));
|
||||
break;
|
||||
}
|
||||
goto out;
|
||||
|
@ -65,7 +65,9 @@ enum ath11k_htc_msg_id {
|
||||
ATH11K_HTC_MSG_CONNECT_SERVICE_RESP_ID = 3,
|
||||
ATH11K_HTC_MSG_SETUP_COMPLETE_ID = 4,
|
||||
ATH11K_HTC_MSG_SETUP_COMPLETE_EX_ID = 5,
|
||||
ATH11K_HTC_MSG_SEND_SUSPEND_COMPLETE = 6
|
||||
ATH11K_HTC_MSG_SEND_SUSPEND_COMPLETE = 6,
|
||||
ATH11K_HTC_MSG_NACK_SUSPEND = 7,
|
||||
ATH11K_HTC_MSG_WAKEUP_FROM_SUSPEND_ID = 8,
|
||||
};
|
||||
|
||||
enum ath11k_htc_version {
|
||||
@ -221,10 +223,6 @@ enum ath11k_htc_ep_id {
|
||||
ATH11K_HTC_EP_COUNT,
|
||||
};
|
||||
|
||||
struct ath11k_htc_ops {
|
||||
void (*target_send_suspend_complete)(struct ath11k_base *ar);
|
||||
};
|
||||
|
||||
struct ath11k_htc_ep_ops {
|
||||
void (*ep_tx_complete)(struct ath11k_base *, struct sk_buff *);
|
||||
void (*ep_rx_complete)(struct ath11k_base *, struct sk_buff *);
|
||||
@ -284,8 +282,6 @@ struct ath11k_htc {
|
||||
/* protects endpoints */
|
||||
spinlock_t tx_lock;
|
||||
|
||||
struct ath11k_htc_ops htc_ops;
|
||||
|
||||
u8 control_resp_buffer[ATH11K_HTC_MAX_CTRL_MSG_LEN];
|
||||
int control_resp_len;
|
||||
|
||||
|
@ -143,12 +143,6 @@ struct ath11k_hw_params {
|
||||
|
||||
bool single_pdev_only;
|
||||
|
||||
/* For example on QCA6390 struct
|
||||
* wmi_init_cmd_param::band_to_mac_config needs to be false as the
|
||||
* firmware creates the mapping.
|
||||
*/
|
||||
bool needs_band_to_mac;
|
||||
|
||||
bool rxdma1_enable;
|
||||
int num_rxmda_per_pdev;
|
||||
bool rx_mac_buf_ring;
|
||||
@ -162,6 +156,7 @@ struct ath11k_hw_params {
|
||||
bool supports_shadow_regs;
|
||||
bool idle_ps;
|
||||
bool cold_boot_calib;
|
||||
bool supports_suspend;
|
||||
};
|
||||
|
||||
struct ath11k_hw_ops {
|
||||
|
@ -1925,20 +1925,6 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab, "failed to update bcn template: %d\n",
|
||||
ret);
|
||||
|
||||
if (vif->bss_conf.he_support) {
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
WMI_VDEV_PARAM_BA_MODE,
|
||||
WMI_BA_MODE_BUFFER_SIZE_256);
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab,
|
||||
"failed to set BA BUFFER SIZE 256 for vdev: %d\n",
|
||||
arvif->vdev_id);
|
||||
else
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
||||
"Set BA BUFFER SIZE 256 for VDEV: %d\n",
|
||||
arvif->vdev_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & (BSS_CHANGED_BEACON_INFO | BSS_CHANGED_BEACON)) {
|
||||
@ -1969,9 +1955,33 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid))
|
||||
ether_addr_copy(arvif->bssid, info->bssid);
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED)
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
ath11k_control_beaconing(arvif, info);
|
||||
|
||||
if (arvif->is_up && vif->bss_conf.he_support &&
|
||||
vif->bss_conf.he_oper.params) {
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
WMI_VDEV_PARAM_BA_MODE,
|
||||
WMI_BA_MODE_BUFFER_SIZE_256);
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab,
|
||||
"failed to set BA BUFFER SIZE 256 for vdev: %d\n",
|
||||
arvif->vdev_id);
|
||||
|
||||
param_id = WMI_VDEV_PARAM_HEOPS_0_31;
|
||||
param_value = vif->bss_conf.he_oper.params;
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
param_id, param_value);
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
||||
"he oper param: %x set for VDEV: %d\n",
|
||||
param_value, arvif->vdev_id);
|
||||
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab, "Failed to set he oper params %x for VDEV %d: %i\n",
|
||||
param_value, arvif->vdev_id, ret);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_ERP_CTS_PROT) {
|
||||
u32 cts_prot;
|
||||
|
||||
@ -4136,6 +4146,10 @@ static int ath11k_mac_config_mon_status_default(struct ath11k *ar, bool enable)
|
||||
&tlv_filter);
|
||||
}
|
||||
|
||||
if (enable && !ar->ab->hw_params.rxdma1_enable)
|
||||
mod_timer(&ar->ab->mon_reap_timer, jiffies +
|
||||
msecs_to_jiffies(ATH11K_MON_TIMER_INTERVAL));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -4615,13 +4629,13 @@ err_peer_del:
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
|
||||
arvif->vdev_id, vif->addr);
|
||||
return ret;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ath11k_wait_for_peer_delete_done(ar, arvif->vdev_id,
|
||||
vif->addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err;
|
||||
|
||||
ar->num_peers--;
|
||||
}
|
||||
|
@ -190,6 +190,15 @@ static void ath11k_mhi_op_runtime_put(struct mhi_controller *mhi_cntrl)
|
||||
static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,
|
||||
enum mhi_callback cb)
|
||||
{
|
||||
struct ath11k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev);
|
||||
|
||||
switch (cb) {
|
||||
case MHI_CB_SYS_ERROR:
|
||||
ath11k_warn(ab, "firmware crashed: MHI_CB_SYS_ERROR\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int ath11k_mhi_op_read_reg(struct mhi_controller *mhi_cntrl,
|
||||
@ -214,7 +223,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
|
||||
struct mhi_controller *mhi_ctrl;
|
||||
int ret;
|
||||
|
||||
mhi_ctrl = kzalloc(sizeof(*mhi_ctrl), GFP_KERNEL);
|
||||
mhi_ctrl = mhi_alloc_controller();
|
||||
if (!mhi_ctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -230,7 +239,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
|
||||
ret = ath11k_mhi_get_msi(ab_pci);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to get msi for mhi\n");
|
||||
kfree(mhi_ctrl);
|
||||
mhi_free_controller(mhi_ctrl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -248,7 +257,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
|
||||
ret = mhi_register_controller(mhi_ctrl, &ath11k_mhi_config);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to register to mhi bus, err = %d\n", ret);
|
||||
kfree(mhi_ctrl);
|
||||
mhi_free_controller(mhi_ctrl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -261,6 +270,7 @@ void ath11k_mhi_unregister(struct ath11k_pci *ab_pci)
|
||||
|
||||
mhi_unregister_controller(mhi_ctrl);
|
||||
kfree(mhi_ctrl->irq);
|
||||
mhi_free_controller(mhi_ctrl);
|
||||
}
|
||||
|
||||
static char *ath11k_mhi_state_to_str(enum ath11k_mhi_state mhi_state)
|
||||
@ -409,8 +419,10 @@ static int ath11k_mhi_set_state(struct ath11k_pci *ab_pci,
|
||||
ret = 0;
|
||||
break;
|
||||
case ATH11K_MHI_SUSPEND:
|
||||
ret = mhi_pm_suspend(ab_pci->mhi_ctrl);
|
||||
break;
|
||||
case ATH11K_MHI_RESUME:
|
||||
ret = mhi_pm_resume(ab_pci->mhi_ctrl);
|
||||
break;
|
||||
case ATH11K_MHI_TRIGGER_RDDM:
|
||||
ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl);
|
||||
@ -461,3 +473,12 @@ void ath11k_mhi_stop(struct ath11k_pci *ab_pci)
|
||||
ath11k_mhi_set_state(ab_pci, ATH11K_MHI_DEINIT);
|
||||
}
|
||||
|
||||
void ath11k_mhi_suspend(struct ath11k_pci *ab_pci)
|
||||
{
|
||||
ath11k_mhi_set_state(ab_pci, ATH11K_MHI_SUSPEND);
|
||||
}
|
||||
|
||||
void ath11k_mhi_resume(struct ath11k_pci *ab_pci)
|
||||
{
|
||||
ath11k_mhi_set_state(ab_pci, ATH11K_MHI_RESUME);
|
||||
}
|
||||
|
@ -36,4 +36,7 @@ void ath11k_mhi_unregister(struct ath11k_pci *ar_pci);
|
||||
void ath11k_mhi_set_mhictrl_reset(struct ath11k_base *ab);
|
||||
void ath11k_mhi_clear_vector(struct ath11k_base *ab);
|
||||
|
||||
void ath11k_mhi_suspend(struct ath11k_pci *ar_pci);
|
||||
void ath11k_mhi_resume(struct ath11k_pci *ar_pci);
|
||||
|
||||
#endif
|
||||
|
@ -126,6 +126,7 @@ static inline void ath11k_pci_select_window(struct ath11k_pci *ab_pci, u32 offse
|
||||
if (window != ab_pci->register_window) {
|
||||
iowrite32(WINDOW_ENABLE_BIT | window,
|
||||
ab->mem + WINDOW_REG_ADDRESS);
|
||||
ioread32(ab->mem + WINDOW_REG_ADDRESS);
|
||||
ab_pci->register_window = window;
|
||||
}
|
||||
}
|
||||
@ -239,15 +240,137 @@ static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab)
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause:%d\n", val);
|
||||
}
|
||||
|
||||
static int ath11k_pci_set_link_reg(struct ath11k_base *ab,
|
||||
u32 offset, u32 value, u32 mask)
|
||||
{
|
||||
u32 v;
|
||||
int i;
|
||||
|
||||
v = ath11k_pci_read32(ab, offset);
|
||||
if ((v & mask) == value)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
ath11k_pci_write32(ab, offset, (v & ~mask) | value);
|
||||
|
||||
v = ath11k_pci_read32(ab, offset);
|
||||
if ((v & mask) == value)
|
||||
return 0;
|
||||
|
||||
mdelay(2);
|
||||
}
|
||||
|
||||
ath11k_warn(ab, "failed to set pcie link register 0x%08x: 0x%08x != 0x%08x\n",
|
||||
offset, v & mask, value);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int ath11k_pci_fix_l1ss(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath11k_pci_set_link_reg(ab,
|
||||
PCIE_QSERDES_COM_SYSCLK_EN_SEL_REG,
|
||||
PCIE_QSERDES_COM_SYSCLK_EN_SEL_VAL,
|
||||
PCIE_QSERDES_COM_SYSCLK_EN_SEL_MSK);
|
||||
if (!ret) {
|
||||
ath11k_warn(ab, "failed to set sysclk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath11k_pci_set_link_reg(ab,
|
||||
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG1_REG,
|
||||
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG1_VAL,
|
||||
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK);
|
||||
if (!ret) {
|
||||
ath11k_warn(ab, "failed to set dtct config1 error: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath11k_pci_set_link_reg(ab,
|
||||
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG2_REG,
|
||||
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG2_VAL,
|
||||
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK);
|
||||
if (!ret) {
|
||||
ath11k_warn(ab, "failed to set dtct config2: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath11k_pci_set_link_reg(ab,
|
||||
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG4_REG,
|
||||
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG4_VAL,
|
||||
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK);
|
||||
if (!ret) {
|
||||
ath11k_warn(ab, "failed to set dtct config4: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_pci_enable_ltssm(struct ath11k_base *ab)
|
||||
{
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
val = ath11k_pci_read32(ab, PCIE_PCIE_PARF_LTSSM);
|
||||
|
||||
/* PCIE link seems very unstable after the Hot Reset*/
|
||||
for (i = 0; val != PARM_LTSSM_VALUE && i < 5; i++) {
|
||||
if (val == 0xffffffff)
|
||||
mdelay(5);
|
||||
|
||||
ath11k_pci_write32(ab, PCIE_PCIE_PARF_LTSSM, PARM_LTSSM_VALUE);
|
||||
val = ath11k_pci_read32(ab, PCIE_PCIE_PARF_LTSSM);
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI, "pci ltssm 0x%x\n", val);
|
||||
|
||||
val = ath11k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST);
|
||||
val |= GCC_GCC_PCIE_HOT_RST_VAL | 0x10;
|
||||
ath11k_pci_write32(ab, GCC_GCC_PCIE_HOT_RST, val);
|
||||
val = ath11k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI, "pci pcie_hot_rst 0x%x\n", val);
|
||||
|
||||
mdelay(5);
|
||||
}
|
||||
|
||||
static void ath11k_pci_clear_all_intrs(struct ath11k_base *ab)
|
||||
{
|
||||
/* This is a WAR for PCIE Hotreset.
|
||||
* When target receive Hotreset, but will set the interrupt.
|
||||
* So when download SBL again, SBL will open Interrupt and
|
||||
* receive it, and crash immediately.
|
||||
*/
|
||||
ath11k_pci_write32(ab, PCIE_PCIE_INT_ALL_CLEAR, PCIE_INT_CLEAR_ALL);
|
||||
}
|
||||
|
||||
static void ath11k_pci_set_wlaon_pwr_ctrl(struct ath11k_base *ab)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = ath11k_pci_read32(ab, WLAON_QFPROM_PWR_CTRL_REG);
|
||||
val &= ~QFPROM_PWR_CTRL_VDD4BLOW_MASK;
|
||||
ath11k_pci_write32(ab, WLAON_QFPROM_PWR_CTRL_REG, val);
|
||||
}
|
||||
|
||||
static void ath11k_pci_force_wake(struct ath11k_base *ab)
|
||||
{
|
||||
ath11k_pci_write32(ab, PCIE_SOC_WAKE_PCIE_LOCAL_REG, 1);
|
||||
mdelay(5);
|
||||
}
|
||||
|
||||
static void ath11k_pci_sw_reset(struct ath11k_base *ab)
|
||||
static void ath11k_pci_sw_reset(struct ath11k_base *ab, bool power_on)
|
||||
{
|
||||
ath11k_pci_soc_global_reset(ab);
|
||||
if (power_on) {
|
||||
ath11k_pci_enable_ltssm(ab);
|
||||
ath11k_pci_clear_all_intrs(ab);
|
||||
ath11k_pci_set_wlaon_pwr_ctrl(ab);
|
||||
ath11k_pci_fix_l1ss(ab);
|
||||
}
|
||||
|
||||
ath11k_mhi_clear_vector(ab);
|
||||
ath11k_pci_soc_global_reset(ab);
|
||||
ath11k_mhi_set_mhictrl_reset(ab);
|
||||
@ -264,13 +387,18 @@ int ath11k_pci_get_msi_irq(struct device *dev, unsigned int vector)
|
||||
static void ath11k_pci_get_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo,
|
||||
u32 *msi_addr_hi)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
struct pci_dev *pci_dev = to_pci_dev(ab->dev);
|
||||
|
||||
pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO,
|
||||
msi_addr_lo);
|
||||
|
||||
pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI,
|
||||
msi_addr_hi);
|
||||
if (test_bit(ATH11K_PCI_FLAG_IS_MSI_64, &ab_pci->flags)) {
|
||||
pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI,
|
||||
msi_addr_hi);
|
||||
} else {
|
||||
*msi_addr_hi = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_name,
|
||||
@ -658,6 +786,8 @@ static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
|
||||
}
|
||||
|
||||
ab_pci->msi_ep_base_data = msi_desc->msg.data;
|
||||
if (msi_desc->msi_attrib.is_64)
|
||||
set_bit(ATH11K_PCI_FLAG_IS_MSI_64, &ab_pci->flags);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI, "msi base data is %d\n", ab_pci->msi_ep_base_data);
|
||||
|
||||
@ -763,7 +893,7 @@ static int ath11k_pci_power_up(struct ath11k_base *ab)
|
||||
|
||||
ab_pci->register_window = 0;
|
||||
clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
|
||||
ath11k_pci_sw_reset(ab_pci->ab);
|
||||
ath11k_pci_sw_reset(ab_pci->ab, true);
|
||||
|
||||
ret = ath11k_mhi_start(ab_pci);
|
||||
if (ret) {
|
||||
@ -778,10 +908,28 @@ static void ath11k_pci_power_down(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
|
||||
ath11k_pci_force_wake(ab_pci->ab);
|
||||
ath11k_mhi_stop(ab_pci);
|
||||
clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
|
||||
ath11k_pci_force_wake(ab_pci->ab);
|
||||
ath11k_pci_sw_reset(ab_pci->ab);
|
||||
ath11k_pci_sw_reset(ab_pci->ab, false);
|
||||
}
|
||||
|
||||
static int ath11k_pci_hif_suspend(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_pci *ar_pci = ath11k_pci_priv(ab);
|
||||
|
||||
ath11k_mhi_suspend(ar_pci);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_pci_hif_resume(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_pci *ar_pci = ath11k_pci_priv(ab);
|
||||
|
||||
ath11k_mhi_resume(ar_pci);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_pci_kill_tasklets(struct ath11k_base *ab)
|
||||
@ -798,11 +946,16 @@ static void ath11k_pci_kill_tasklets(struct ath11k_base *ab)
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_pci_stop(struct ath11k_base *ab)
|
||||
static void ath11k_pci_ce_irq_disable_sync(struct ath11k_base *ab)
|
||||
{
|
||||
ath11k_pci_ce_irqs_disable(ab);
|
||||
ath11k_pci_sync_ce_irqs(ab);
|
||||
ath11k_pci_kill_tasklets(ab);
|
||||
}
|
||||
|
||||
static void ath11k_pci_stop(struct ath11k_base *ab)
|
||||
{
|
||||
ath11k_pci_ce_irq_disable_sync(ab);
|
||||
ath11k_ce_cleanup_pipes(ab);
|
||||
}
|
||||
|
||||
@ -818,6 +971,16 @@ static int ath11k_pci_start(struct ath11k_base *ab)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_pci_hif_ce_irq_enable(struct ath11k_base *ab)
|
||||
{
|
||||
ath11k_pci_ce_irqs_enable(ab);
|
||||
}
|
||||
|
||||
static void ath11k_pci_hif_ce_irq_disable(struct ath11k_base *ab)
|
||||
{
|
||||
ath11k_pci_ce_irq_disable_sync(ab);
|
||||
}
|
||||
|
||||
static int ath11k_pci_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
|
||||
u8 *ul_pipe, u8 *dl_pipe)
|
||||
{
|
||||
@ -868,11 +1031,15 @@ static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
|
||||
.write32 = ath11k_pci_write32,
|
||||
.power_down = ath11k_pci_power_down,
|
||||
.power_up = ath11k_pci_power_up,
|
||||
.suspend = ath11k_pci_hif_suspend,
|
||||
.resume = ath11k_pci_hif_resume,
|
||||
.irq_enable = ath11k_pci_ext_irq_enable,
|
||||
.irq_disable = ath11k_pci_ext_irq_disable,
|
||||
.get_msi_address = ath11k_pci_get_msi_address,
|
||||
.get_user_msi_vector = ath11k_get_user_msi_assignment,
|
||||
.map_service_to_pipe = ath11k_pci_map_service_to_pipe,
|
||||
.ce_irq_enable = ath11k_pci_hif_ce_irq_enable,
|
||||
.ce_irq_disable = ath11k_pci_hif_ce_irq_disable,
|
||||
};
|
||||
|
||||
static int ath11k_pci_probe(struct pci_dev *pdev,
|
||||
@ -1007,10 +1174,18 @@ static void ath11k_pci_remove(struct pci_dev *pdev)
|
||||
struct ath11k_base *ab = pci_get_drvdata(pdev);
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
|
||||
if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
|
||||
ath11k_pci_power_down(ab);
|
||||
ath11k_debugfs_soc_destroy(ab);
|
||||
ath11k_qmi_deinit_service(ab);
|
||||
goto qmi_fail;
|
||||
}
|
||||
|
||||
set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
|
||||
|
||||
ath11k_core_deinit(ab);
|
||||
|
||||
qmi_fail:
|
||||
ath11k_mhi_unregister(ab_pci);
|
||||
|
||||
ath11k_pci_free_irq(ab);
|
||||
@ -1029,12 +1204,43 @@ static void ath11k_pci_shutdown(struct pci_dev *pdev)
|
||||
ath11k_pci_power_down(ab);
|
||||
}
|
||||
|
||||
static __maybe_unused int ath11k_pci_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct ath11k_base *ab = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = ath11k_core_suspend(ab);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to suspend core: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __maybe_unused int ath11k_pci_pm_resume(struct device *dev)
|
||||
{
|
||||
struct ath11k_base *ab = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = ath11k_core_resume(ab);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to resume core: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops,
|
||||
ath11k_pci_pm_suspend,
|
||||
ath11k_pci_pm_resume);
|
||||
|
||||
static struct pci_driver ath11k_pci_driver = {
|
||||
.name = "ath11k_pci",
|
||||
.id_table = ath11k_pci_id_table,
|
||||
.probe = ath11k_pci_probe,
|
||||
.remove = ath11k_pci_remove,
|
||||
.shutdown = ath11k_pci_shutdown,
|
||||
#ifdef CONFIG_PM
|
||||
.driver.pm = &ath11k_pci_pm_ops,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int ath11k_pci_init(void)
|
||||
@ -1059,3 +1265,8 @@ module_exit(ath11k_pci_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
/* QCA639x 2.0 firmware files */
|
||||
MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_BOARD_API2_FILE);
|
||||
MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_AMSS_FILE);
|
||||
MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_M3_FILE);
|
||||
|
@ -24,6 +24,30 @@
|
||||
/* register used for handshake mechanism to validate UMAC is awake */
|
||||
#define PCIE_SOC_WAKE_PCIE_LOCAL_REG 0x3004
|
||||
|
||||
#define PCIE_PCIE_PARF_LTSSM 0x1e081b0
|
||||
#define PARM_LTSSM_VALUE 0x111
|
||||
|
||||
#define GCC_GCC_PCIE_HOT_RST 0x1e402bc
|
||||
#define GCC_GCC_PCIE_HOT_RST_VAL 0x10
|
||||
|
||||
#define PCIE_PCIE_INT_ALL_CLEAR 0x1e08228
|
||||
#define PCIE_SMLH_REQ_RST_LINK_DOWN 0x2
|
||||
#define PCIE_INT_CLEAR_ALL 0xffffffff
|
||||
|
||||
#define PCIE_QSERDES_COM_SYSCLK_EN_SEL_REG 0x01e0c0ac
|
||||
#define PCIE_QSERDES_COM_SYSCLK_EN_SEL_VAL 0x10
|
||||
#define PCIE_QSERDES_COM_SYSCLK_EN_SEL_MSK 0xffffffff
|
||||
#define PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG1_REG 0x01e0c628
|
||||
#define PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG1_VAL 0x02
|
||||
#define PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG2_REG 0x01e0c62c
|
||||
#define PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG2_VAL 0x52
|
||||
#define PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG4_REG 0x01e0c634
|
||||
#define PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG4_VAL 0xff
|
||||
#define PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK 0x000000ff
|
||||
|
||||
#define WLAON_QFPROM_PWR_CTRL_REG 0x01f8031c
|
||||
#define QFPROM_PWR_CTRL_VDD4BLOW_MASK 0x4
|
||||
|
||||
struct ath11k_msi_user {
|
||||
char *name;
|
||||
int num_vectors;
|
||||
@ -38,6 +62,7 @@ struct ath11k_msi_config {
|
||||
|
||||
enum ath11k_pci_flags {
|
||||
ATH11K_PCI_FLAG_INIT_DONE,
|
||||
ATH11K_PCI_FLAG_IS_MSI_64,
|
||||
};
|
||||
|
||||
struct ath11k_pci {
|
||||
|
@ -2421,7 +2421,7 @@ ath11k_qmi_driver_event_post(struct ath11k_qmi *qmi,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_qmi_event_server_arrive(struct ath11k_qmi *qmi)
|
||||
static int ath11k_qmi_event_server_arrive(struct ath11k_qmi *qmi)
|
||||
{
|
||||
struct ath11k_base *ab = qmi->ab;
|
||||
int ret;
|
||||
@ -2429,17 +2429,19 @@ static void ath11k_qmi_event_server_arrive(struct ath11k_qmi *qmi)
|
||||
ret = ath11k_qmi_fw_ind_register_send(ab);
|
||||
if (ret < 0) {
|
||||
ath11k_warn(ab, "qmi failed to send FW indication QMI:%d\n", ret);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath11k_qmi_host_cap_send(ab);
|
||||
if (ret < 0) {
|
||||
ath11k_warn(ab, "qmi failed to send host cap QMI:%d\n", ret);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_qmi_event_mem_request(struct ath11k_qmi *qmi)
|
||||
static int ath11k_qmi_event_mem_request(struct ath11k_qmi *qmi)
|
||||
{
|
||||
struct ath11k_base *ab = qmi->ab;
|
||||
int ret;
|
||||
@ -2447,11 +2449,13 @@ static void ath11k_qmi_event_mem_request(struct ath11k_qmi *qmi)
|
||||
ret = ath11k_qmi_respond_fw_mem_request(ab);
|
||||
if (ret < 0) {
|
||||
ath11k_warn(ab, "qmi failed to respond fw mem req:%d\n", ret);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_qmi_event_load_bdf(struct ath11k_qmi *qmi)
|
||||
static int ath11k_qmi_event_load_bdf(struct ath11k_qmi *qmi)
|
||||
{
|
||||
struct ath11k_base *ab = qmi->ab;
|
||||
int ret;
|
||||
@ -2459,7 +2463,7 @@ static void ath11k_qmi_event_load_bdf(struct ath11k_qmi *qmi)
|
||||
ret = ath11k_qmi_request_target_cap(ab);
|
||||
if (ret < 0) {
|
||||
ath11k_warn(ab, "qmi failed to req target capabilities:%d\n", ret);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ab->bus_params.fixed_bdf_addr)
|
||||
@ -2468,14 +2472,16 @@ static void ath11k_qmi_event_load_bdf(struct ath11k_qmi *qmi)
|
||||
ret = ath11k_qmi_load_bdf_qmi(ab);
|
||||
if (ret < 0) {
|
||||
ath11k_warn(ab, "qmi failed to load board data file:%d\n", ret);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath11k_qmi_wlanfw_m3_info_send(ab);
|
||||
if (ret < 0) {
|
||||
ath11k_warn(ab, "qmi failed to send m3 info req:%d\n", ret);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl,
|
||||
@ -2615,7 +2621,7 @@ static int ath11k_qmi_ops_new_server(struct qmi_handle *qmi_hdl,
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wifi fw qmi service connected\n");
|
||||
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_SERVER_ARRIVE, NULL);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_qmi_ops_del_server(struct qmi_handle *qmi_hdl,
|
||||
@ -2639,6 +2645,7 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)
|
||||
event_work);
|
||||
struct ath11k_qmi_driver_event *event;
|
||||
struct ath11k_base *ab = qmi->ab;
|
||||
int ret;
|
||||
|
||||
spin_lock(&qmi->event_lock);
|
||||
while (!list_empty(&qmi->event_list)) {
|
||||
@ -2652,19 +2659,26 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)
|
||||
|
||||
switch (event->type) {
|
||||
case ATH11K_QMI_EVENT_SERVER_ARRIVE:
|
||||
ath11k_qmi_event_server_arrive(qmi);
|
||||
ret = ath11k_qmi_event_server_arrive(qmi);
|
||||
if (ret < 0)
|
||||
set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
|
||||
break;
|
||||
case ATH11K_QMI_EVENT_SERVER_EXIT:
|
||||
set_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);
|
||||
set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
|
||||
break;
|
||||
case ATH11K_QMI_EVENT_REQUEST_MEM:
|
||||
ath11k_qmi_event_mem_request(qmi);
|
||||
ret = ath11k_qmi_event_mem_request(qmi);
|
||||
if (ret < 0)
|
||||
set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
|
||||
break;
|
||||
case ATH11K_QMI_EVENT_FW_MEM_READY:
|
||||
ath11k_qmi_event_load_bdf(qmi);
|
||||
ret = ath11k_qmi_event_load_bdf(qmi);
|
||||
if (ret < 0)
|
||||
set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
|
||||
break;
|
||||
case ATH11K_QMI_EVENT_FW_READY:
|
||||
clear_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
|
||||
if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) {
|
||||
ath11k_hal_dump_srng_stats(ab);
|
||||
queue_work(ab->workqueue, &ab->restart_work);
|
||||
@ -2742,4 +2756,5 @@ void ath11k_qmi_deinit_service(struct ath11k_base *ab)
|
||||
ath11k_qmi_m3_free(ab);
|
||||
ath11k_qmi_free_target_mem_chunk(ab);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_qmi_deinit_service);
|
||||
|
||||
|
@ -1688,7 +1688,8 @@ int ath11k_wmi_vdev_install_key(struct ath11k *ar,
|
||||
|
||||
static inline void
|
||||
ath11k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd,
|
||||
struct peer_assoc_params *param)
|
||||
struct peer_assoc_params *param,
|
||||
bool hw_crypto_disabled)
|
||||
{
|
||||
cmd->peer_flags = 0;
|
||||
|
||||
@ -1742,7 +1743,8 @@ ath11k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd,
|
||||
cmd->peer_flags |= WMI_PEER_AUTH;
|
||||
if (param->need_ptk_4_way) {
|
||||
cmd->peer_flags |= WMI_PEER_NEED_PTK_4_WAY;
|
||||
cmd->peer_flags &= ~WMI_PEER_AUTH;
|
||||
if (!hw_crypto_disabled)
|
||||
cmd->peer_flags &= ~WMI_PEER_AUTH;
|
||||
}
|
||||
if (param->need_gtk_2_way)
|
||||
cmd->peer_flags |= WMI_PEER_NEED_GTK_2_WAY;
|
||||
@ -1809,7 +1811,9 @@ int ath11k_wmi_send_peer_assoc_cmd(struct ath11k *ar,
|
||||
cmd->peer_new_assoc = param->peer_new_assoc;
|
||||
cmd->peer_associd = param->peer_associd;
|
||||
|
||||
ath11k_wmi_copy_peer_flags(cmd, param);
|
||||
ath11k_wmi_copy_peer_flags(cmd, param,
|
||||
test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED,
|
||||
&ar->ab->dev_flags));
|
||||
|
||||
ether_addr_copy(cmd->peer_macaddr.addr, param->peer_mac);
|
||||
|
||||
@ -2209,37 +2213,6 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,
|
||||
}
|
||||
}
|
||||
|
||||
len = params->num_hint_s_ssid * sizeof(struct hint_short_ssid);
|
||||
tlv = ptr;
|
||||
tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_FIXED_STRUCT) |
|
||||
FIELD_PREP(WMI_TLV_LEN, len);
|
||||
ptr += TLV_HDR_SIZE;
|
||||
if (params->num_hint_s_ssid) {
|
||||
s_ssid = ptr;
|
||||
for (i = 0; i < params->num_hint_s_ssid; ++i) {
|
||||
s_ssid->freq_flags = params->hint_s_ssid[i].freq_flags;
|
||||
s_ssid->short_ssid = params->hint_s_ssid[i].short_ssid;
|
||||
s_ssid++;
|
||||
}
|
||||
}
|
||||
ptr += len;
|
||||
|
||||
len = params->num_hint_bssid * sizeof(struct hint_bssid);
|
||||
tlv = ptr;
|
||||
tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_FIXED_STRUCT) |
|
||||
FIELD_PREP(WMI_TLV_LEN, len);
|
||||
ptr += TLV_HDR_SIZE;
|
||||
if (params->num_hint_bssid) {
|
||||
hint_bssid = ptr;
|
||||
for (i = 0; i < params->num_hint_bssid; ++i) {
|
||||
hint_bssid->freq_flags =
|
||||
params->hint_bssid[i].freq_flags;
|
||||
ether_addr_copy(¶ms->hint_bssid[i].bssid.addr[0],
|
||||
&hint_bssid->bssid.addr[0]);
|
||||
hint_bssid++;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ath11k_wmi_cmd_send(wmi, skb,
|
||||
WMI_START_SCAN_CMDID);
|
||||
if (ret) {
|
||||
@ -3475,6 +3448,35 @@ int ath11k_wmi_wait_for_unified_ready(struct ath11k_base *ab)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath11k_wmi_set_hw_mode(struct ath11k_base *ab,
|
||||
enum wmi_host_hw_mode_config_type mode)
|
||||
{
|
||||
struct wmi_pdev_set_hw_mode_cmd_param *cmd;
|
||||
struct sk_buff *skb;
|
||||
struct ath11k_wmi_base *wmi_ab = &ab->wmi_ab;
|
||||
int len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
|
||||
skb = ath11k_wmi_alloc_skb(wmi_ab, len);
|
||||
cmd = (struct wmi_pdev_set_hw_mode_cmd_param *)skb->data;
|
||||
|
||||
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_PDEV_SET_HW_MODE_CMD) |
|
||||
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
|
||||
cmd->pdev_id = WMI_PDEV_ID_SOC;
|
||||
cmd->hw_mode_index = mode;
|
||||
|
||||
ret = ath11k_wmi_cmd_send(&wmi_ab->wmi[0], skb, WMI_PDEV_SET_HW_MODE_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to send WMI_PDEV_SET_HW_MODE_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_cmd_init(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_wmi_base *wmi_sc = &ab->wmi_ab;
|
||||
@ -3493,10 +3495,11 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
|
||||
init_param.hw_mode_id = wmi_sc->preferred_hw_mode;
|
||||
init_param.mem_chunks = wmi_sc->mem_chunks;
|
||||
|
||||
if (ab->hw_params.needs_band_to_mac) {
|
||||
init_param.num_band_to_mac = ab->num_radios;
|
||||
ath11k_fill_band_to_mac_param(ab, init_param.band_to_mac);
|
||||
}
|
||||
if (ab->hw_params.single_pdev_only)
|
||||
init_param.hw_mode_id = WMI_HOST_HW_MODE_MAX;
|
||||
|
||||
init_param.num_band_to_mac = ab->num_radios;
|
||||
ath11k_fill_band_to_mac_param(ab, init_param.band_to_mac);
|
||||
|
||||
return ath11k_init_cmd_send(&wmi_sc->wmi[0], &init_param);
|
||||
}
|
||||
@ -6697,6 +6700,59 @@ static void ath11k_probe_resp_tx_status_event(struct ath11k_base *ab,
|
||||
kfree(tb);
|
||||
}
|
||||
|
||||
static int ath11k_wmi_tlv_wow_wakeup_host_parse(struct ath11k_base *ab,
|
||||
u16 tag, u16 len,
|
||||
const void *ptr, void *data)
|
||||
{
|
||||
struct wmi_wow_ev_arg *ev = data;
|
||||
const char *wow_pg_fault;
|
||||
int wow_pg_len;
|
||||
|
||||
switch (tag) {
|
||||
case WMI_TAG_WOW_EVENT_INFO:
|
||||
memcpy(ev, ptr, sizeof(*ev));
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "wow wakeup host reason %d %s\n",
|
||||
ev->wake_reason, wow_reason(ev->wake_reason));
|
||||
break;
|
||||
|
||||
case WMI_TAG_ARRAY_BYTE:
|
||||
if (ev && ev->wake_reason == WOW_REASON_PAGE_FAULT) {
|
||||
wow_pg_fault = ptr;
|
||||
/* the first 4 bytes are length */
|
||||
wow_pg_len = *(int *)wow_pg_fault;
|
||||
wow_pg_fault += sizeof(int);
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "wow data_len = %d\n",
|
||||
wow_pg_len);
|
||||
ath11k_dbg_dump(ab, ATH11K_DBG_WMI,
|
||||
"wow_event_info_type packet present",
|
||||
"wow_pg_fault ",
|
||||
wow_pg_fault,
|
||||
wow_pg_len);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_wmi_event_wow_wakeup_host(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_wow_ev_arg ev = { };
|
||||
int ret;
|
||||
|
||||
ret = ath11k_wmi_tlv_iter(ab, skb->data, skb->len,
|
||||
ath11k_wmi_tlv_wow_wakeup_host_parse,
|
||||
&ev);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to parse wmi wow tlv: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
complete(&ab->wow.wakeup_completed);
|
||||
}
|
||||
|
||||
static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_cmd_hdr *cmd_hdr;
|
||||
@ -6804,6 +6860,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
case WMI_VDEV_DELETE_RESP_EVENTID:
|
||||
ath11k_vdev_delete_resp_event(ab, skb);
|
||||
break;
|
||||
case WMI_WOW_WAKEUP_HOST_EVENTID:
|
||||
ath11k_wmi_event_wow_wakeup_host(ab, skb);
|
||||
break;
|
||||
/* TODO: Add remaining events */
|
||||
default:
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id);
|
||||
@ -7018,3 +7077,46 @@ void ath11k_wmi_detach(struct ath11k_base *ab)
|
||||
|
||||
ath11k_wmi_free_dbring_caps(ab);
|
||||
}
|
||||
|
||||
int ath11k_wmi_wow_host_wakeup_ind(struct ath11k *ar)
|
||||
{
|
||||
struct wmi_wow_host_wakeup_ind *cmd;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_wow_host_wakeup_ind *)skb->data;
|
||||
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG,
|
||||
WMI_TAG_WOW_HOSTWAKEUP_FROM_SLEEP_CMD) |
|
||||
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow host wakeup ind\n");
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
|
||||
}
|
||||
|
||||
int ath11k_wmi_wow_enable(struct ath11k *ar)
|
||||
{
|
||||
struct wmi_wow_enable_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_wow_enable_cmd *)skb->data;
|
||||
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_WOW_ENABLE_CMD) |
|
||||
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
|
||||
cmd->enable = 1;
|
||||
cmd->pause_iface_config = WOW_IFACE_PAUSE_ENABLED;
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow enable\n");
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
|
||||
}
|
||||
|
@ -1037,7 +1037,7 @@ enum wmi_tlv_vdev_param {
|
||||
WMI_VDEV_PARAM_PROTOTYPE = 0x8000,
|
||||
WMI_VDEV_PARAM_BSS_COLOR,
|
||||
WMI_VDEV_PARAM_SET_HEMU_MODE,
|
||||
WMI_VDEV_PARAM_TX_OFDMA_CPLEN,
|
||||
WMI_VDEV_PARAM_HEOPS_0_31 = 0x8003,
|
||||
};
|
||||
|
||||
enum wmi_tlv_peer_flags {
|
||||
@ -5044,6 +5044,169 @@ struct ath11k_wmi_base {
|
||||
struct ath11k_targ_cap *targ_cap;
|
||||
};
|
||||
|
||||
/* WOW structures */
|
||||
enum wmi_wow_wakeup_event {
|
||||
WOW_BMISS_EVENT = 0,
|
||||
WOW_BETTER_AP_EVENT,
|
||||
WOW_DEAUTH_RECVD_EVENT,
|
||||
WOW_MAGIC_PKT_RECVD_EVENT,
|
||||
WOW_GTK_ERR_EVENT,
|
||||
WOW_FOURWAY_HSHAKE_EVENT,
|
||||
WOW_EAPOL_RECVD_EVENT,
|
||||
WOW_NLO_DETECTED_EVENT,
|
||||
WOW_DISASSOC_RECVD_EVENT,
|
||||
WOW_PATTERN_MATCH_EVENT,
|
||||
WOW_CSA_IE_EVENT,
|
||||
WOW_PROBE_REQ_WPS_IE_EVENT,
|
||||
WOW_AUTH_REQ_EVENT,
|
||||
WOW_ASSOC_REQ_EVENT,
|
||||
WOW_HTT_EVENT,
|
||||
WOW_RA_MATCH_EVENT,
|
||||
WOW_HOST_AUTO_SHUTDOWN_EVENT,
|
||||
WOW_IOAC_MAGIC_EVENT,
|
||||
WOW_IOAC_SHORT_EVENT,
|
||||
WOW_IOAC_EXTEND_EVENT,
|
||||
WOW_IOAC_TIMER_EVENT,
|
||||
WOW_DFS_PHYERR_RADAR_EVENT,
|
||||
WOW_BEACON_EVENT,
|
||||
WOW_CLIENT_KICKOUT_EVENT,
|
||||
WOW_EVENT_MAX,
|
||||
};
|
||||
|
||||
enum wmi_wow_interface_cfg {
|
||||
WOW_IFACE_PAUSE_ENABLED,
|
||||
WOW_IFACE_PAUSE_DISABLED
|
||||
};
|
||||
|
||||
#define C2S(x) case x: return #x
|
||||
|
||||
static inline const char *wow_wakeup_event(enum wmi_wow_wakeup_event ev)
|
||||
{
|
||||
switch (ev) {
|
||||
C2S(WOW_BMISS_EVENT);
|
||||
C2S(WOW_BETTER_AP_EVENT);
|
||||
C2S(WOW_DEAUTH_RECVD_EVENT);
|
||||
C2S(WOW_MAGIC_PKT_RECVD_EVENT);
|
||||
C2S(WOW_GTK_ERR_EVENT);
|
||||
C2S(WOW_FOURWAY_HSHAKE_EVENT);
|
||||
C2S(WOW_EAPOL_RECVD_EVENT);
|
||||
C2S(WOW_NLO_DETECTED_EVENT);
|
||||
C2S(WOW_DISASSOC_RECVD_EVENT);
|
||||
C2S(WOW_PATTERN_MATCH_EVENT);
|
||||
C2S(WOW_CSA_IE_EVENT);
|
||||
C2S(WOW_PROBE_REQ_WPS_IE_EVENT);
|
||||
C2S(WOW_AUTH_REQ_EVENT);
|
||||
C2S(WOW_ASSOC_REQ_EVENT);
|
||||
C2S(WOW_HTT_EVENT);
|
||||
C2S(WOW_RA_MATCH_EVENT);
|
||||
C2S(WOW_HOST_AUTO_SHUTDOWN_EVENT);
|
||||
C2S(WOW_IOAC_MAGIC_EVENT);
|
||||
C2S(WOW_IOAC_SHORT_EVENT);
|
||||
C2S(WOW_IOAC_EXTEND_EVENT);
|
||||
C2S(WOW_IOAC_TIMER_EVENT);
|
||||
C2S(WOW_DFS_PHYERR_RADAR_EVENT);
|
||||
C2S(WOW_BEACON_EVENT);
|
||||
C2S(WOW_CLIENT_KICKOUT_EVENT);
|
||||
C2S(WOW_EVENT_MAX);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
enum wmi_wow_wake_reason {
|
||||
WOW_REASON_UNSPECIFIED = -1,
|
||||
WOW_REASON_NLOD = 0,
|
||||
WOW_REASON_AP_ASSOC_LOST,
|
||||
WOW_REASON_LOW_RSSI,
|
||||
WOW_REASON_DEAUTH_RECVD,
|
||||
WOW_REASON_DISASSOC_RECVD,
|
||||
WOW_REASON_GTK_HS_ERR,
|
||||
WOW_REASON_EAP_REQ,
|
||||
WOW_REASON_FOURWAY_HS_RECV,
|
||||
WOW_REASON_TIMER_INTR_RECV,
|
||||
WOW_REASON_PATTERN_MATCH_FOUND,
|
||||
WOW_REASON_RECV_MAGIC_PATTERN,
|
||||
WOW_REASON_P2P_DISC,
|
||||
WOW_REASON_WLAN_HB,
|
||||
WOW_REASON_CSA_EVENT,
|
||||
WOW_REASON_PROBE_REQ_WPS_IE_RECV,
|
||||
WOW_REASON_AUTH_REQ_RECV,
|
||||
WOW_REASON_ASSOC_REQ_RECV,
|
||||
WOW_REASON_HTT_EVENT,
|
||||
WOW_REASON_RA_MATCH,
|
||||
WOW_REASON_HOST_AUTO_SHUTDOWN,
|
||||
WOW_REASON_IOAC_MAGIC_EVENT,
|
||||
WOW_REASON_IOAC_SHORT_EVENT,
|
||||
WOW_REASON_IOAC_EXTEND_EVENT,
|
||||
WOW_REASON_IOAC_TIMER_EVENT,
|
||||
WOW_REASON_ROAM_HO,
|
||||
WOW_REASON_DFS_PHYERR_RADADR_EVENT,
|
||||
WOW_REASON_BEACON_RECV,
|
||||
WOW_REASON_CLIENT_KICKOUT_EVENT,
|
||||
WOW_REASON_PAGE_FAULT = 0x3a,
|
||||
WOW_REASON_DEBUG_TEST = 0xFF,
|
||||
};
|
||||
|
||||
static inline const char *wow_reason(enum wmi_wow_wake_reason reason)
|
||||
{
|
||||
switch (reason) {
|
||||
C2S(WOW_REASON_UNSPECIFIED);
|
||||
C2S(WOW_REASON_NLOD);
|
||||
C2S(WOW_REASON_AP_ASSOC_LOST);
|
||||
C2S(WOW_REASON_LOW_RSSI);
|
||||
C2S(WOW_REASON_DEAUTH_RECVD);
|
||||
C2S(WOW_REASON_DISASSOC_RECVD);
|
||||
C2S(WOW_REASON_GTK_HS_ERR);
|
||||
C2S(WOW_REASON_EAP_REQ);
|
||||
C2S(WOW_REASON_FOURWAY_HS_RECV);
|
||||
C2S(WOW_REASON_TIMER_INTR_RECV);
|
||||
C2S(WOW_REASON_PATTERN_MATCH_FOUND);
|
||||
C2S(WOW_REASON_RECV_MAGIC_PATTERN);
|
||||
C2S(WOW_REASON_P2P_DISC);
|
||||
C2S(WOW_REASON_WLAN_HB);
|
||||
C2S(WOW_REASON_CSA_EVENT);
|
||||
C2S(WOW_REASON_PROBE_REQ_WPS_IE_RECV);
|
||||
C2S(WOW_REASON_AUTH_REQ_RECV);
|
||||
C2S(WOW_REASON_ASSOC_REQ_RECV);
|
||||
C2S(WOW_REASON_HTT_EVENT);
|
||||
C2S(WOW_REASON_RA_MATCH);
|
||||
C2S(WOW_REASON_HOST_AUTO_SHUTDOWN);
|
||||
C2S(WOW_REASON_IOAC_MAGIC_EVENT);
|
||||
C2S(WOW_REASON_IOAC_SHORT_EVENT);
|
||||
C2S(WOW_REASON_IOAC_EXTEND_EVENT);
|
||||
C2S(WOW_REASON_IOAC_TIMER_EVENT);
|
||||
C2S(WOW_REASON_ROAM_HO);
|
||||
C2S(WOW_REASON_DFS_PHYERR_RADADR_EVENT);
|
||||
C2S(WOW_REASON_BEACON_RECV);
|
||||
C2S(WOW_REASON_CLIENT_KICKOUT_EVENT);
|
||||
C2S(WOW_REASON_PAGE_FAULT);
|
||||
C2S(WOW_REASON_DEBUG_TEST);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#undef C2S
|
||||
|
||||
struct wmi_wow_enable_cmd {
|
||||
u32 tlv_header;
|
||||
u32 enable;
|
||||
u32 pause_iface_config;
|
||||
u32 flags;
|
||||
} __packed;
|
||||
|
||||
struct wmi_wow_host_wakeup_ind {
|
||||
u32 tlv_header;
|
||||
u32 reserved;
|
||||
} __packed;
|
||||
|
||||
struct wmi_wow_ev_arg {
|
||||
u32 vdev_id;
|
||||
u32 flag;
|
||||
enum wmi_wow_wake_reason wake_reason;
|
||||
u32 data_len;
|
||||
};
|
||||
|
||||
int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
|
||||
u32 cmd_id);
|
||||
struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len);
|
||||
@ -5171,4 +5334,9 @@ int ath11k_wmi_fils_discovery(struct ath11k *ar, u32 vdev_id, u32 interval,
|
||||
bool unsol_bcast_probe_resp_enabled);
|
||||
int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id,
|
||||
struct sk_buff *tmpl);
|
||||
int ath11k_wmi_set_hw_mode(struct ath11k_base *ab,
|
||||
enum wmi_host_hw_mode_config_type mode);
|
||||
int ath11k_wmi_wow_host_wakeup_ind(struct ath11k *ar);
|
||||
int ath11k_wmi_wow_enable(struct ath11k *ar);
|
||||
|
||||
#endif
|
||||
|
73
drivers/net/wireless/ath/ath11k/wow.c
Normal file
73
drivers/net/wireless/ath/ath11k/wow.c
Normal file
@ -0,0 +1,73 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "mac.h"
|
||||
#include "core.h"
|
||||
#include "hif.h"
|
||||
#include "debug.h"
|
||||
#include "wmi.h"
|
||||
#include "wow.h"
|
||||
|
||||
int ath11k_wow_enable(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k *ar = ath11k_ab_to_ar(ab, 0);
|
||||
int i, ret;
|
||||
|
||||
clear_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags);
|
||||
|
||||
for (i = 0; i < ATH11K_WOW_RETRY_NUM; i++) {
|
||||
reinit_completion(&ab->htc_suspend);
|
||||
|
||||
ret = ath11k_wmi_wow_enable(ar);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to issue wow enable: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_timeout(&ab->htc_suspend, 3 * HZ);
|
||||
if (ret == 0) {
|
||||
ath11k_warn(ab,
|
||||
"timed out while waiting for htc suspend completion\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (test_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags))
|
||||
/* success, suspend complete received */
|
||||
return 0;
|
||||
|
||||
ath11k_warn(ab, "htc suspend not complete, retrying (try %d)\n",
|
||||
i);
|
||||
msleep(ATH11K_WOW_RETRY_WAIT_MS);
|
||||
}
|
||||
|
||||
ath11k_warn(ab, "htc suspend not complete, failing after %d tries\n", i);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
int ath11k_wow_wakeup(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k *ar = ath11k_ab_to_ar(ab, 0);
|
||||
int ret;
|
||||
|
||||
reinit_completion(&ab->wow.wakeup_completed);
|
||||
|
||||
ret = ath11k_wmi_wow_host_wakeup_ind(ar);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to send wow wakeup indication: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_timeout(&ab->wow.wakeup_completed, 3 * HZ);
|
||||
if (ret == 0) {
|
||||
ath11k_warn(ab, "timed out while waiting for wow wakeup completion\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
10
drivers/net/wireless/ath/ath11k/wow.h
Normal file
10
drivers/net/wireless/ath/ath11k/wow.h
Normal file
@ -0,0 +1,10 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define ATH11K_WOW_RETRY_NUM 3
|
||||
#define ATH11K_WOW_RETRY_WAIT_MS 200
|
||||
|
||||
int ath11k_wow_enable(struct ath11k_base *ab);
|
||||
int ath11k_wow_wakeup(struct ath11k_base *ab);
|
@ -433,6 +433,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (ah->assoc)
|
||||
rfilt |= AR5K_RX_FILTER_BEACON;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ static ssize_t read_file_phy_err(struct file *file, char __user *user_buf,
|
||||
{
|
||||
#define PHY_ERR(s, p) \
|
||||
len += scnprintf(buf + len, size - len, "%22s : %10u\n", s, \
|
||||
rxstats->phy_err_stats[p]);
|
||||
rxstats->phy_err_stats[p])
|
||||
|
||||
struct ath_rx_stats *rxstats = file->private_data;
|
||||
char *buf;
|
||||
|
@ -26,7 +26,7 @@ static struct ath_dfs_pool_stats dfs_pool_stats = { 0 };
|
||||
|
||||
#define ATH9K_DFS_STAT(s, p) \
|
||||
len += scnprintf(buf + len, size - len, "%28s : %10u\n", s, \
|
||||
sc->debug.stats.dfs_stats.p);
|
||||
sc->debug.stats.dfs_stats.p)
|
||||
#define ATH9K_DFS_POOL_STAT(s, p) \
|
||||
len += scnprintf(buf + len, size - len, "%28s : %10u\n", s, \
|
||||
dfs_pool_stats.p);
|
||||
|
@ -297,7 +297,12 @@ static void ath9k_htc_tx_data(struct ath9k_htc_priv *priv,
|
||||
tx_hdr.data_type = ATH9K_HTC_NORMAL;
|
||||
}
|
||||
|
||||
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
/* Transmit all frames that should not be reordered relative
|
||||
* to each other using the same priority. For other QoS data
|
||||
* frames extract the priority from the header.
|
||||
*/
|
||||
if (!(tx_info->control.flags & IEEE80211_TX_CTRL_DONT_REORDER) &&
|
||||
ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
qc = ieee80211_get_qos_ctl(hdr);
|
||||
tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@
|
||||
#include "cmd.h"
|
||||
|
||||
#define ADD(buf, off, max, fmt, args...) \
|
||||
off += scnprintf(&buf[off], max - off, fmt, ##args);
|
||||
off += scnprintf(&buf[off], max - off, fmt, ##args)
|
||||
|
||||
|
||||
struct carl9170_debugfs_fops {
|
||||
@ -818,7 +818,7 @@ void carl9170_debugfs_register(struct ar9170 *ar)
|
||||
#define DEBUGFS_ADD(name) \
|
||||
debugfs_create_file(#name, carl_debugfs_##name ##_ops.attr, \
|
||||
ar->debug_dir, ar, \
|
||||
&carl_debugfs_##name ## _ops.fops);
|
||||
&carl_debugfs_##name ## _ops.fops)
|
||||
|
||||
DEBUGFS_ADD(usb_tx_anch_urbs);
|
||||
DEBUGFS_ADD(usb_rx_pool_urbs);
|
||||
|
@ -840,6 +840,7 @@ static bool carl9170_tx_rts_check(struct ar9170 *ar,
|
||||
case CARL9170_ERP_RTS:
|
||||
if (likely(!multi))
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -2570,7 +2570,7 @@ static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, void *buf, size_t len)
|
||||
case WCN36XX_HAL_SCAN_IND_FAILED:
|
||||
case WCN36XX_HAL_SCAN_IND_DEQUEUED:
|
||||
scan_info.aborted = true;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case WCN36XX_HAL_SCAN_IND_COMPLETED:
|
||||
mutex_lock(&wcn->scan_lock);
|
||||
wcn->scan_req = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user