// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/remoteproc.h>
#include <linux/firmware.h>
#include <linux/of.h>
#include "core.h"
#include "dp_tx.h"
#include "dp_rx.h"
#include "debug.h"
#include "hif.h"
unsigned int ath12k_debug_mask;
module_param_named(debug_mask, ath12k_debug_mask, uint, 0644);
MODULE_PARM_DESC(debug_mask, "Debugging mask");
static int ath12k_core_rfkill_config(struct ath12k_base *ab)
{
struct ath12k *ar;
int ret = 0, i;
if (!(ab->target_caps.sys_cap_info & WMI_SYS_CAP_INFO_RFKILL))
return 0;
for (i = 0; i < ab->num_radios; i++) {
ar = ab->pdevs[i].ar;
ret = ath12k_mac_rfkill_config(ar);
if (ret && ret != -EOPNOTSUPP) {
ath12k_warn(ab, "failed to configure rfkill: %d", ret);
return ret;
}
}
return ret;
}
int ath12k_core_suspend(struct ath12k_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 = ath12k_dp_rx_pktlog_stop(ab, true);
if (ret) {
ath12k_warn(ab, "failed to stop dp rx (and timer) pktlog during suspend: %d\n",
ret);
return ret;
}
ret = ath12k_dp_rx_pktlog_stop(ab, false);
if (ret) {
ath12k_warn(ab, "failed to stop dp rx pktlog during suspend: %d\n",
ret);
return ret;
}
ath12k_hif_irq_disable(ab);
ath12k_hif_ce_irq_disable(ab);
ret = ath12k_hif_suspend(ab);
if (ret) {
ath12k_warn(ab, "failed to suspend hif: %d\n", ret);
return ret;
}
return 0;
}
int ath12k_core_resume(struct ath12k_base *ab)
{
int ret;
if (!ab->hw_params->supports_suspend)
return -EOPNOTSUPP;
ret = ath12k_hif_resume(ab);
if (ret) {
ath12k_warn(ab, "failed to resume hif during resume: %d\n", ret);
return ret;
}
ath12k_hif_ce_irq_enable(ab);
ath12k_hif_irq_enable(ab);
ret = ath12k_dp_rx_pktlog_start(ab);
if (ret) {
ath12k_warn(ab, "failed to start rx pktlog during resume: %d\n",
ret);
return ret;
}
return 0;
}
static int __ath12k_core_create_board_name(struct ath12k_base *ab, char *name,
size_t name_len, bool with_variant,
bool bus_type_mode)
{
/* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */
char variant[9 + ATH12K_QMI_BDF_EXT_STR_LENGTH] = { 0 };
if (with_variant && ab->qmi.target.bdf_ext[0] != '\0')
scnprintf(variant, sizeof(variant), ",variant=%s",
ab->qmi.target.bdf_ext);
switch (ab->id.bdf_search) {
case ATH12K_BDF_SEARCH_BUS_AND_BOARD:
if (bus_type_mode)
scnprintf(name, name_len,
"bus=%s",
ath12k_bus_str(ab->hif.bus));
else
scnprintf(name, name_len,
"bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s",
ath12k_bus_str(ab->hif.bus),
ab->id.vendor, ab->id.device,
ab-&