Merge: Wireless core and drivers rebase to v6.9 + bug-fixes
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/4417 JIRA: https://issues.redhat.com/browse/RHEL-34696 JIRA: https://issues.redhat.com/browse/RHEL-36253 JIRA: https://issues.redhat.com/browse/RHEL-12349 JIRA: https://issues.redhat.com/browse/RHEL-35199 JIRA: https://issues.redhat.com/browse/RHEL-35142 JIRA: https://issues.redhat.com/browse/RHEL-37357 JIRA: https://issues.redhat.com/browse/RHEL-34187 JIRA: https://issues.redhat.com/browse/RHEL-37028 JIRA: https://issues.redhat.com/browse/RHEL-36900 JIRA: https://issues.redhat.com/browse/RHEL-34868 JIRA: https://issues.redhat.com/browse/RHEL-35148 JIRA: https://issues.redhat.com/browse/RHEL-37341 JIRA: https://issues.redhat.com/browse/RHEL-37345 JIRA: https://issues.redhat.com/browse/RHEL-35152 JIRA: https://issues.redhat.com/browse/RHEL-36809 JIRA: https://issues.redhat.com/browse/RHEL-37161 JIRA: https://issues.redhat.com/browse/RHEL-37165 JIRA: https://issues.redhat.com/browse/RHEL-39799 JIRA: https://issues.redhat.com/browse/RHEL-39803 JIRA: https://issues.redhat.com/browse/RHEL-39754 CVE: CVE-2023-52651 CVE: CVE-2024-27052 CVE: CVE-2024-35946 CVE: CVE-2024-26897 CVE: CVE-2024-35845 CVE: CVE-2024-27434 CVE: CVE-2024-26892 CVE: CVE-2024-27049 CVE: CVE-2024-35938 CVE: CVE-2024-35937 CVE: CVE-2024-27048 CVE: CVE-2024-35789 CVE: CVE-2024-35913 CVE: CVE-2024-35912 CVE: CVE-2024-36922 CVE: CVE-2024-36921 CVE: CVE-2024-36941 Tested: basic testing with several supported WiFi cards (Intel, Qualcomm, Mediatek and Realtek). Wireless core and drivers update to v6.9 and bug-fixes so far. Upstream status: linux.git, wireless-next.git Fixes to be included in next rebases (not very important or still not supported): Omitted-fix: 609c12a2af04 wifi: mac80211: reset negotiated TTLM on disconnect Omitted-fix: 6e16782d6b4a wifi: ath11k: move power type check to ASSOC stage when connecting to 6 GHz AP Omitted-fix: 585ba158233f wifi: iwlwifi: mvm: don't always disable EMLSR due to BT coex Omitted-fix: 40cecacabc46 wifi: mt76: mt7615: add missing chanctx ops Omitted-fix: 0c2fd18f7ec5 wifi: mac80211: fix Spatial Reuse element size check Omitted-fix: 8ecc4d7a7cd3 wifi: mac80211: pass proper link id for channel switch started notification Omitted-fix: ed281c6ab6eb wifi: ath11k: fix WCN6750 firmware crash caused by 17 num_vdevs Omitted-fix: 24de1b7b231c wifi: ath12k: fix flush failure in recovery scenarios Omitted-fix: 819bda58e77b wifi: rtlwifi: Ignore IEEE80211_CONF_CHANGE_RETRY_LIMITS Omitted-fix: 474b9412f33b wifi: mt76: mt7996: fix potential memory leakage when reading chip temperature Omitted-fix: baaf806e4632 wifi: rtw89: wow: refine WoWLAN flows of HCI interrupts and low power mode Omitted-fix: 669b692247d4 wifi: rtw89: fix HW scan not aborting properly Omitted-fix: 3b0989e925f3 wifi: ath12k: avoid duplicated vdev stop Omitted-fix: 0d9c2beed116 wifi: mac80211: fix monitor channel with chanctx emulation Omitted-fix: f3269b7912f7 wifi: nl80211: expose can-monitor channel property Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com> Approved-by: Jan Stancek <jstancek@redhat.com> Approved-by: Ivan Vecera <ivecera@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Lucas Zampieri <lzampier@redhat.com>
This commit is contained in:
commit
6d0aecebb6
|
@ -280,7 +280,7 @@ static u8 bcma_find_pci_capability(struct bcma_drv_pci *pc, unsigned int dev,
|
|||
/* check for Header type 0 */
|
||||
bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val,
|
||||
sizeof(u8));
|
||||
if ((byte_val & 0x7F) != PCI_HEADER_TYPE_NORMAL)
|
||||
if ((byte_val & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_NORMAL)
|
||||
return cap_ptr;
|
||||
|
||||
/* check if the capability pointer field exists */
|
||||
|
|
|
@ -240,15 +240,13 @@ err_unmap_mmio:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int bcma_host_soc_remove(struct platform_device *pdev)
|
||||
static void bcma_host_soc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct bcma_bus *bus = platform_get_drvdata(pdev);
|
||||
|
||||
bcma_bus_unregister(bus);
|
||||
iounmap(bus->mmio);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id bcma_host_soc_of_match[] = {
|
||||
|
@ -263,7 +261,7 @@ static struct platform_driver bcma_host_soc_driver = {
|
|||
.of_match_table = bcma_host_soc_of_match,
|
||||
},
|
||||
.probe = bcma_host_soc_probe,
|
||||
.remove = bcma_host_soc_remove,
|
||||
.remove_new = bcma_host_soc_remove,
|
||||
};
|
||||
|
||||
int __init bcma_host_soc_register_driver(void)
|
||||
|
|
|
@ -68,7 +68,7 @@ static struct attribute *bcma_device_attrs[] = {
|
|||
};
|
||||
ATTRIBUTE_GROUPS(bcma_device);
|
||||
|
||||
static struct bus_type bcma_bus_type = {
|
||||
static const struct bus_type bcma_bus_type = {
|
||||
.name = "bcma",
|
||||
.match = bcma_bus_match,
|
||||
.probe = bcma_device_probe,
|
||||
|
|
|
@ -297,30 +297,30 @@ struct mhi_ring_element {
|
|||
__le32 dword[2];
|
||||
};
|
||||
|
||||
#define MHI_STATE_LIST \
|
||||
mhi_state(RESET, "RESET") \
|
||||
mhi_state(READY, "READY") \
|
||||
mhi_state(M0, "M0") \
|
||||
mhi_state(M1, "M1") \
|
||||
mhi_state(M2, "M2") \
|
||||
mhi_state(M3, "M3") \
|
||||
mhi_state(M3_FAST, "M3_FAST") \
|
||||
mhi_state(BHI, "BHI") \
|
||||
mhi_state_end(SYS_ERR, "SYS ERROR")
|
||||
|
||||
#undef mhi_state
|
||||
#undef mhi_state_end
|
||||
|
||||
#define mhi_state(a, b) case MHI_STATE_##a: return b;
|
||||
#define mhi_state_end(a, b) case MHI_STATE_##a: return b;
|
||||
|
||||
static inline const char *mhi_state_str(enum mhi_state state)
|
||||
{
|
||||
switch (state) {
|
||||
case MHI_STATE_RESET:
|
||||
return "RESET";
|
||||
case MHI_STATE_READY:
|
||||
return "READY";
|
||||
case MHI_STATE_M0:
|
||||
return "M0";
|
||||
case MHI_STATE_M1:
|
||||
return "M1";
|
||||
case MHI_STATE_M2:
|
||||
return "M2";
|
||||
case MHI_STATE_M3:
|
||||
return "M3";
|
||||
case MHI_STATE_M3_FAST:
|
||||
return "M3 FAST";
|
||||
case MHI_STATE_BHI:
|
||||
return "BHI";
|
||||
case MHI_STATE_SYS_ERR:
|
||||
return "SYS ERROR";
|
||||
MHI_STATE_LIST
|
||||
default:
|
||||
return "Unknown state";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _MHI_COMMON_H */
|
||||
|
|
|
@ -1149,8 +1149,9 @@ int mhi_ep_power_up(struct mhi_ep_cntrl *mhi_cntrl)
|
|||
mhi_ep_mmio_mask_interrupts(mhi_cntrl);
|
||||
mhi_ep_mmio_init(mhi_cntrl);
|
||||
|
||||
mhi_cntrl->mhi_event = kzalloc(mhi_cntrl->event_rings * (sizeof(*mhi_cntrl->mhi_event)),
|
||||
GFP_KERNEL);
|
||||
mhi_cntrl->mhi_event = kcalloc(mhi_cntrl->event_rings,
|
||||
sizeof(*mhi_cntrl->mhi_event),
|
||||
GFP_KERNEL);
|
||||
if (!mhi_cntrl->mhi_event)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1496,7 +1497,7 @@ int mhi_ep_register_controller(struct mhi_ep_cntrl *mhi_cntrl,
|
|||
mhi_cntrl->ring_item_cache = kmem_cache_create("mhi_ep_ring_item",
|
||||
sizeof(struct mhi_ep_ring_item), 0,
|
||||
0, NULL);
|
||||
if (!mhi_cntrl->ev_ring_el_cache) {
|
||||
if (!mhi_cntrl->ring_item_cache) {
|
||||
ret = -ENOMEM;
|
||||
goto err_destroy_tre_buf_cache;
|
||||
}
|
||||
|
|
|
@ -395,7 +395,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
|
|||
void *buf;
|
||||
dma_addr_t dma_addr;
|
||||
size_t size, fw_sz;
|
||||
int i, ret;
|
||||
int ret;
|
||||
|
||||
if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
|
||||
dev_err(dev, "Device MHI is not in valid state\n");
|
||||
|
@ -408,15 +408,6 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
|
|||
if (ret)
|
||||
dev_err(dev, "Could not capture serial number via BHI\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mhi_cntrl->oem_pk_hash); i++) {
|
||||
ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_OEMPKHASH(i),
|
||||
&mhi_cntrl->oem_pk_hash[i]);
|
||||
if (ret) {
|
||||
dev_err(dev, "Could not capture OEM PK HASH via BHI\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* wait for ready on pass through or any other execution environment */
|
||||
if (!MHI_FW_LOAD_CAPABLE(mhi_cntrl->ee))
|
||||
goto fw_load_ready_state;
|
||||
|
|
|
@ -20,50 +20,49 @@
|
|||
#include <linux/wait.h>
|
||||
#include "internal.h"
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "trace.h"
|
||||
|
||||
static DEFINE_IDA(mhi_controller_ida);
|
||||
|
||||
#undef mhi_ee
|
||||
#undef mhi_ee_end
|
||||
|
||||
#define mhi_ee(a, b) [MHI_EE_##a] = b,
|
||||
#define mhi_ee_end(a, b) [MHI_EE_##a] = b,
|
||||
|
||||
const char * const mhi_ee_str[MHI_EE_MAX] = {
|
||||
[MHI_EE_PBL] = "PRIMARY BOOTLOADER",
|
||||
[MHI_EE_SBL] = "SECONDARY BOOTLOADER",
|
||||
[MHI_EE_AMSS] = "MISSION MODE",
|
||||
[MHI_EE_RDDM] = "RAMDUMP DOWNLOAD MODE",
|
||||
[MHI_EE_WFW] = "WLAN FIRMWARE",
|
||||
[MHI_EE_PTHRU] = "PASS THROUGH",
|
||||
[MHI_EE_EDL] = "EMERGENCY DOWNLOAD",
|
||||
[MHI_EE_FP] = "FLASH PROGRAMMER",
|
||||
[MHI_EE_DISABLE_TRANSITION] = "DISABLE",
|
||||
[MHI_EE_NOT_SUPPORTED] = "NOT SUPPORTED",
|
||||
MHI_EE_LIST
|
||||
};
|
||||
|
||||
#undef dev_st_trans
|
||||
#undef dev_st_trans_end
|
||||
|
||||
#define dev_st_trans(a, b) [DEV_ST_TRANSITION_##a] = b,
|
||||
#define dev_st_trans_end(a, b) [DEV_ST_TRANSITION_##a] = b,
|
||||
|
||||
const char * const dev_state_tran_str[DEV_ST_TRANSITION_MAX] = {
|
||||
[DEV_ST_TRANSITION_PBL] = "PBL",
|
||||
[DEV_ST_TRANSITION_READY] = "READY",
|
||||
[DEV_ST_TRANSITION_SBL] = "SBL",
|
||||
[DEV_ST_TRANSITION_MISSION_MODE] = "MISSION MODE",
|
||||
[DEV_ST_TRANSITION_FP] = "FLASH PROGRAMMER",
|
||||
[DEV_ST_TRANSITION_SYS_ERR] = "SYS ERROR",
|
||||
[DEV_ST_TRANSITION_DISABLE] = "DISABLE",
|
||||
DEV_ST_TRANSITION_LIST
|
||||
};
|
||||
|
||||
#undef ch_state_type
|
||||
#undef ch_state_type_end
|
||||
|
||||
#define ch_state_type(a, b) [MHI_CH_STATE_TYPE_##a] = b,
|
||||
#define ch_state_type_end(a, b) [MHI_CH_STATE_TYPE_##a] = b,
|
||||
|
||||
const char * const mhi_ch_state_type_str[MHI_CH_STATE_TYPE_MAX] = {
|
||||
[MHI_CH_STATE_TYPE_RESET] = "RESET",
|
||||
[MHI_CH_STATE_TYPE_STOP] = "STOP",
|
||||
[MHI_CH_STATE_TYPE_START] = "START",
|
||||
MHI_CH_STATE_TYPE_LIST
|
||||
};
|
||||
|
||||
#undef mhi_pm_state
|
||||
#undef mhi_pm_state_end
|
||||
|
||||
#define mhi_pm_state(a, b) [MHI_PM_STATE_##a] = b,
|
||||
#define mhi_pm_state_end(a, b) [MHI_PM_STATE_##a] = b,
|
||||
|
||||
static const char * const mhi_pm_state_str[] = {
|
||||
[MHI_PM_STATE_DISABLE] = "DISABLE",
|
||||
[MHI_PM_STATE_POR] = "POWER ON RESET",
|
||||
[MHI_PM_STATE_M0] = "M0",
|
||||
[MHI_PM_STATE_M2] = "M2",
|
||||
[MHI_PM_STATE_M3_ENTER] = "M?->M3",
|
||||
[MHI_PM_STATE_M3] = "M3",
|
||||
[MHI_PM_STATE_M3_EXIT] = "M3->M0",
|
||||
[MHI_PM_STATE_FW_DL_ERR] = "Firmware Download Error",
|
||||
[MHI_PM_STATE_SYS_ERR_DETECT] = "SYS ERROR Detect",
|
||||
[MHI_PM_STATE_SYS_ERR_PROCESS] = "SYS ERROR Process",
|
||||
[MHI_PM_STATE_SHUTDOWN_PROCESS] = "SHUTDOWN Process",
|
||||
[MHI_PM_STATE_LD_ERR_FATAL_DETECT] = "Linkdown or Error Fatal Detect",
|
||||
MHI_PM_STATE_LIST
|
||||
};
|
||||
|
||||
const char *to_mhi_pm_state_str(u32 state)
|
||||
|
@ -97,11 +96,19 @@ static ssize_t oem_pk_hash_show(struct device *dev,
|
|||
{
|
||||
struct mhi_device *mhi_dev = to_mhi_device(dev);
|
||||
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
int i, cnt = 0;
|
||||
u32 hash_segment[MHI_MAX_OEM_PK_HASH_SEGMENTS];
|
||||
int i, cnt = 0, ret;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mhi_cntrl->oem_pk_hash); i++)
|
||||
cnt += sysfs_emit_at(buf, cnt, "OEMPKHASH[%d]: 0x%x\n",
|
||||
i, mhi_cntrl->oem_pk_hash[i]);
|
||||
for (i = 0; i < MHI_MAX_OEM_PK_HASH_SEGMENTS; i++) {
|
||||
ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_OEMPKHASH(i), &hash_segment[i]);
|
||||
if (ret) {
|
||||
dev_err(dev, "Could not capture OEM PK HASH\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MHI_MAX_OEM_PK_HASH_SEGMENTS; i++)
|
||||
cnt += sysfs_emit_at(buf, cnt, "OEMPKHASH[%d]: 0x%x\n", i, hash_segment[i]);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
@ -907,7 +914,6 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
|
|||
struct mhi_chan *mhi_chan;
|
||||
struct mhi_cmd *mhi_cmd;
|
||||
struct mhi_device *mhi_dev;
|
||||
u32 soc_info;
|
||||
int ret, i;
|
||||
|
||||
if (!mhi_cntrl || !mhi_cntrl->cntrl_dev || !mhi_cntrl->regs ||
|
||||
|
@ -982,17 +988,6 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
|
|||
mhi_cntrl->unmap_single = mhi_unmap_single_no_bb;
|
||||
}
|
||||
|
||||
/* Read the MHI device info */
|
||||
ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs,
|
||||
SOC_HW_VERSION_OFFS, &soc_info);
|
||||
if (ret)
|
||||
goto err_destroy_wq;
|
||||
|
||||
mhi_cntrl->family_number = FIELD_GET(SOC_HW_VERSION_FAM_NUM_BMSK, soc_info);
|
||||
mhi_cntrl->device_number = FIELD_GET(SOC_HW_VERSION_DEV_NUM_BMSK, soc_info);
|
||||
mhi_cntrl->major_version = FIELD_GET(SOC_HW_VERSION_MAJOR_VER_BMSK, soc_info);
|
||||
mhi_cntrl->minor_version = FIELD_GET(SOC_HW_VERSION_MINOR_VER_BMSK, soc_info);
|
||||
|
||||
mhi_cntrl->index = ida_alloc(&mhi_controller_ida, GFP_KERNEL);
|
||||
if (mhi_cntrl->index < 0) {
|
||||
ret = mhi_cntrl->index;
|
||||
|
|
|
@ -15,12 +15,6 @@ extern struct bus_type mhi_bus_type;
|
|||
#define MHI_SOC_RESET_REQ_OFFSET 0xb0
|
||||
#define MHI_SOC_RESET_REQ BIT(0)
|
||||
|
||||
#define SOC_HW_VERSION_OFFS 0x224
|
||||
#define SOC_HW_VERSION_FAM_NUM_BMSK GENMASK(31, 28)
|
||||
#define SOC_HW_VERSION_DEV_NUM_BMSK GENMASK(27, 16)
|
||||
#define SOC_HW_VERSION_MAJOR_VER_BMSK GENMASK(15, 8)
|
||||
#define SOC_HW_VERSION_MINOR_VER_BMSK GENMASK(7, 0)
|
||||
|
||||
struct mhi_ctxt {
|
||||
struct mhi_event_ctxt *er_ctxt;
|
||||
struct mhi_chan_ctxt *chan_ctxt;
|
||||
|
@ -42,6 +36,11 @@ enum mhi_ch_state_type {
|
|||
MHI_CH_STATE_TYPE_MAX,
|
||||
};
|
||||
|
||||
#define MHI_CH_STATE_TYPE_LIST \
|
||||
ch_state_type(RESET, "RESET") \
|
||||
ch_state_type(STOP, "STOP") \
|
||||
ch_state_type_end(START, "START")
|
||||
|
||||
extern const char * const mhi_ch_state_type_str[MHI_CH_STATE_TYPE_MAX];
|
||||
#define TO_CH_STATE_TYPE_STR(state) (((state) >= MHI_CH_STATE_TYPE_MAX) ? \
|
||||
"INVALID_STATE" : \
|
||||
|
@ -50,6 +49,18 @@ extern const char * const mhi_ch_state_type_str[MHI_CH_STATE_TYPE_MAX];
|
|||
#define MHI_INVALID_BRSTMODE(mode) (mode != MHI_DB_BRST_DISABLE && \
|
||||
mode != MHI_DB_BRST_ENABLE)
|
||||
|
||||
#define MHI_EE_LIST \
|
||||
mhi_ee(PBL, "PRIMARY BOOTLOADER") \
|
||||
mhi_ee(SBL, "SECONDARY BOOTLOADER") \
|
||||
mhi_ee(AMSS, "MISSION MODE") \
|
||||
mhi_ee(RDDM, "RAMDUMP DOWNLOAD MODE")\
|
||||
mhi_ee(WFW, "WLAN FIRMWARE") \
|
||||
mhi_ee(PTHRU, "PASS THROUGH") \
|
||||
mhi_ee(EDL, "EMERGENCY DOWNLOAD") \
|
||||
mhi_ee(FP, "FLASH PROGRAMMER") \
|
||||
mhi_ee(DISABLE_TRANSITION, "DISABLE") \
|
||||
mhi_ee_end(NOT_SUPPORTED, "NOT SUPPORTED")
|
||||
|
||||
extern const char * const mhi_ee_str[MHI_EE_MAX];
|
||||
#define TO_MHI_EXEC_STR(ee) (((ee) >= MHI_EE_MAX) ? \
|
||||
"INVALID_EE" : mhi_ee_str[ee])
|
||||
|
@ -69,9 +80,20 @@ enum dev_st_transition {
|
|||
DEV_ST_TRANSITION_FP,
|
||||
DEV_ST_TRANSITION_SYS_ERR,
|
||||
DEV_ST_TRANSITION_DISABLE,
|
||||
DEV_ST_TRANSITION_DISABLE_DESTROY_DEVICE,
|
||||
DEV_ST_TRANSITION_MAX,
|
||||
};
|
||||
|
||||
#define DEV_ST_TRANSITION_LIST \
|
||||
dev_st_trans(PBL, "PBL") \
|
||||
dev_st_trans(READY, "READY") \
|
||||
dev_st_trans(SBL, "SBL") \
|
||||
dev_st_trans(MISSION_MODE, "MISSION MODE") \
|
||||
dev_st_trans(FP, "FLASH PROGRAMMER") \
|
||||
dev_st_trans(SYS_ERR, "SYS ERROR") \
|
||||
dev_st_trans(DISABLE, "DISABLE") \
|
||||
dev_st_trans_end(DISABLE_DESTROY_DEVICE, "DISABLE (DESTROY DEVICE)")
|
||||
|
||||
extern const char * const dev_state_tran_str[DEV_ST_TRANSITION_MAX];
|
||||
#define TO_DEV_STATE_TRANS_STR(state) (((state) >= DEV_ST_TRANSITION_MAX) ? \
|
||||
"INVALID_STATE" : dev_state_tran_str[state])
|
||||
|
@ -88,11 +110,27 @@ enum mhi_pm_state {
|
|||
MHI_PM_STATE_FW_DL_ERR,
|
||||
MHI_PM_STATE_SYS_ERR_DETECT,
|
||||
MHI_PM_STATE_SYS_ERR_PROCESS,
|
||||
MHI_PM_STATE_SYS_ERR_FAIL,
|
||||
MHI_PM_STATE_SHUTDOWN_PROCESS,
|
||||
MHI_PM_STATE_LD_ERR_FATAL_DETECT,
|
||||
MHI_PM_STATE_MAX
|
||||
};
|
||||
|
||||
#define MHI_PM_STATE_LIST \
|
||||
mhi_pm_state(DISABLE, "DISABLE") \
|
||||
mhi_pm_state(POR, "POWER ON RESET") \
|
||||
mhi_pm_state(M0, "M0") \
|
||||
mhi_pm_state(M2, "M2") \
|
||||
mhi_pm_state(M3_ENTER, "M?->M3") \
|
||||
mhi_pm_state(M3, "M3") \
|
||||
mhi_pm_state(M3_EXIT, "M3->M0") \
|
||||
mhi_pm_state(FW_DL_ERR, "Firmware Download Error") \
|
||||
mhi_pm_state(SYS_ERR_DETECT, "SYS ERROR Detect") \
|
||||
mhi_pm_state(SYS_ERR_PROCESS, "SYS ERROR Process") \
|
||||
mhi_pm_state(SYS_ERR_FAIL, "SYS ERROR Failure") \
|
||||
mhi_pm_state(SHUTDOWN_PROCESS, "SHUTDOWN Process") \
|
||||
mhi_pm_state_end(LD_ERR_FATAL_DETECT, "Linkdown or Error Fatal Detect")
|
||||
|
||||
#define MHI_PM_DISABLE BIT(0)
|
||||
#define MHI_PM_POR BIT(1)
|
||||
#define MHI_PM_M0 BIT(2)
|
||||
|
@ -104,14 +142,16 @@ enum mhi_pm_state {
|
|||
#define MHI_PM_FW_DL_ERR BIT(7)
|
||||
#define MHI_PM_SYS_ERR_DETECT BIT(8)
|
||||
#define MHI_PM_SYS_ERR_PROCESS BIT(9)
|
||||
#define MHI_PM_SHUTDOWN_PROCESS BIT(10)
|
||||
#define MHI_PM_SYS_ERR_FAIL BIT(10)
|
||||
#define MHI_PM_SHUTDOWN_PROCESS BIT(11)
|
||||
/* link not accessible */
|
||||
#define MHI_PM_LD_ERR_FATAL_DETECT BIT(11)
|
||||
#define MHI_PM_LD_ERR_FATAL_DETECT BIT(12)
|
||||
|
||||
#define MHI_REG_ACCESS_VALID(pm_state) ((pm_state & (MHI_PM_POR | MHI_PM_M0 | \
|
||||
MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \
|
||||
MHI_PM_SYS_ERR_DETECT | MHI_PM_SYS_ERR_PROCESS | \
|
||||
MHI_PM_SHUTDOWN_PROCESS | MHI_PM_FW_DL_ERR)))
|
||||
MHI_PM_SYS_ERR_FAIL | MHI_PM_SHUTDOWN_PROCESS | \
|
||||
MHI_PM_FW_DL_ERR)))
|
||||
#define MHI_PM_IN_ERROR_STATE(pm_state) (pm_state >= MHI_PM_FW_DL_ERR)
|
||||
#define MHI_PM_IN_FATAL_STATE(pm_state) (pm_state == MHI_PM_LD_ERR_FATAL_DETECT)
|
||||
#define MHI_DB_ACCESS_VALID(mhi_cntrl) (mhi_cntrl->pm_state & mhi_cntrl->db_access)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/skbuff.h>
|
||||
#include <linux/slab.h>
|
||||
#include "internal.h"
|
||||
#include "trace.h"
|
||||
|
||||
int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl,
|
||||
void __iomem *base, u32 offset, u32 *out)
|
||||
|
@ -493,11 +494,8 @@ irqreturn_t mhi_intvec_threaded_handler(int irq_number, void *priv)
|
|||
|
||||
state = mhi_get_mhi_state(mhi_cntrl);
|
||||
ee = mhi_get_exec_env(mhi_cntrl);
|
||||
dev_dbg(dev, "local ee: %s state: %s device ee: %s state: %s\n",
|
||||
TO_MHI_EXEC_STR(mhi_cntrl->ee),
|
||||
mhi_state_str(mhi_cntrl->dev_state),
|
||||
TO_MHI_EXEC_STR(ee), mhi_state_str(state));
|
||||
|
||||
trace_mhi_intvec_states(mhi_cntrl, ee, state);
|
||||
if (state == MHI_STATE_SYS_ERR) {
|
||||
dev_dbg(dev, "System error detected\n");
|
||||
pm_state = mhi_tryset_pm_state(mhi_cntrl,
|
||||
|
@ -838,6 +836,8 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl,
|
|||
while (dev_rp != local_rp) {
|
||||
enum mhi_pkt_type type = MHI_TRE_GET_EV_TYPE(local_rp);
|
||||
|
||||
trace_mhi_ctrl_event(mhi_cntrl, local_rp);
|
||||
|
||||
switch (type) {
|
||||
case MHI_PKT_TYPE_BW_REQ_EVENT:
|
||||
{
|
||||
|
@ -1003,6 +1003,8 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl,
|
|||
while (dev_rp != local_rp && event_quota > 0) {
|
||||
enum mhi_pkt_type type = MHI_TRE_GET_EV_TYPE(local_rp);
|
||||
|
||||
trace_mhi_data_event(mhi_cntrl, local_rp);
|
||||
|
||||
chan = MHI_TRE_GET_EV_CHID(local_rp);
|
||||
|
||||
WARN_ON(chan >= mhi_cntrl->max_chan);
|
||||
|
@ -1243,6 +1245,7 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
|
|||
mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(info->len);
|
||||
mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(bei, eot, eob, chain);
|
||||
|
||||
trace_mhi_gen_tre(mhi_cntrl, mhi_chan, mhi_tre);
|
||||
/* increment WP */
|
||||
mhi_add_ring_element(mhi_cntrl, tre_ring);
|
||||
mhi_add_ring_element(mhi_cntrl, buf_ring);
|
||||
|
@ -1337,9 +1340,7 @@ static int mhi_update_channel_state(struct mhi_controller *mhi_cntrl,
|
|||
enum mhi_cmd_type cmd = MHI_CMD_NOP;
|
||||
int ret;
|
||||
|
||||
dev_dbg(dev, "%d: Updating channel state to: %s\n", mhi_chan->chan,
|
||||
TO_CH_STATE_TYPE_STR(to_state));
|
||||
|
||||
trace_mhi_channel_command_start(mhi_cntrl, mhi_chan, to_state, TPS("Updating"));
|
||||
switch (to_state) {
|
||||
case MHI_CH_STATE_TYPE_RESET:
|
||||
write_lock_irq(&mhi_chan->lock);
|
||||
|
@ -1406,9 +1407,7 @@ static int mhi_update_channel_state(struct mhi_controller *mhi_cntrl,
|
|||
write_unlock_irq(&mhi_chan->lock);
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%d: Channel state change to %s successful\n",
|
||||
mhi_chan->chan, TO_CH_STATE_TYPE_STR(to_state));
|
||||
|
||||
trace_mhi_channel_command_end(mhi_cntrl, mhi_chan, to_state, TPS("Updated"));
|
||||
exit_channel_update:
|
||||
mhi_cntrl->runtime_put(mhi_cntrl);
|
||||
mhi_device_put(mhi_cntrl->mhi_dev);
|
||||
|
|
|
@ -538,7 +538,7 @@ static struct mhi_event_config mhi_telit_fn980_hw_v1_events[] = {
|
|||
MHI_EVENT_CONFIG_HW_DATA(2, 2048, 101)
|
||||
};
|
||||
|
||||
static struct mhi_controller_config modem_telit_fn980_hw_v1_config = {
|
||||
static const struct mhi_controller_config modem_telit_fn980_hw_v1_config = {
|
||||
.max_channels = 128,
|
||||
.timeout_ms = 20000,
|
||||
.num_channels = ARRAY_SIZE(mhi_telit_fn980_hw_v1_channels),
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include "internal.h"
|
||||
#include "trace.h"
|
||||
|
||||
/*
|
||||
* Not all MHI state transitions are synchronous. Transitions like Linkdown,
|
||||
|
@ -36,7 +37,10 @@
|
|||
* M0 <--> M0
|
||||
* M0 -> FW_DL_ERR
|
||||
* M0 -> M3_ENTER -> M3 -> M3_EXIT --> M0
|
||||
* L1: SYS_ERR_DETECT -> SYS_ERR_PROCESS --> POR
|
||||
* L1: SYS_ERR_DETECT -> SYS_ERR_PROCESS
|
||||
* SYS_ERR_PROCESS -> SYS_ERR_FAIL
|
||||
* SYS_ERR_FAIL -> SYS_ERR_DETECT
|
||||
* SYS_ERR_PROCESS --> POR
|
||||
* L2: SHUTDOWN_PROCESS -> LD_ERR_FATAL_DETECT
|
||||
* SHUTDOWN_PROCESS -> DISABLE
|
||||
* L3: LD_ERR_FATAL_DETECT <--> LD_ERR_FATAL_DETECT
|
||||
|
@ -93,7 +97,12 @@ static const struct mhi_pm_transitions dev_state_transitions[] = {
|
|||
},
|
||||
{
|
||||
MHI_PM_SYS_ERR_PROCESS,
|
||||
MHI_PM_POR | MHI_PM_SHUTDOWN_PROCESS |
|
||||
MHI_PM_POR | MHI_PM_SYS_ERR_FAIL | MHI_PM_SHUTDOWN_PROCESS |
|
||||
MHI_PM_LD_ERR_FATAL_DETECT
|
||||
},
|
||||
{
|
||||
MHI_PM_SYS_ERR_FAIL,
|
||||
MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS |
|
||||
MHI_PM_LD_ERR_FATAL_DETECT
|
||||
},
|
||||
/* L2 States */
|
||||
|
@ -123,6 +132,7 @@ enum mhi_pm_state __must_check mhi_tryset_pm_state(struct mhi_controller *mhi_cn
|
|||
if (unlikely(!(dev_state_transitions[index].to_states & state)))
|
||||
return cur_state;
|
||||
|
||||
trace_mhi_tryset_pm_state(mhi_cntrl, state);
|
||||
mhi_cntrl->pm_state = state;
|
||||
return mhi_cntrl->pm_state;
|
||||
}
|
||||
|
@ -458,7 +468,8 @@ error_mission_mode:
|
|||
}
|
||||
|
||||
/* Handle shutdown transitions */
|
||||
static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl)
|
||||
static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl,
|
||||
bool destroy_device)
|
||||
{
|
||||
enum mhi_pm_state cur_state;
|
||||
struct mhi_event *mhi_event;
|
||||
|
@ -520,8 +531,16 @@ skip_mhi_reset:
|
|||
dev_dbg(dev, "Waiting for all pending threads to complete\n");
|
||||
wake_up_all(&mhi_cntrl->state_event);
|
||||
|
||||
dev_dbg(dev, "Reset all active channels and remove MHI devices\n");
|
||||
device_for_each_child(&mhi_cntrl->mhi_dev->dev, NULL, mhi_destroy_device);
|
||||
/*
|
||||
* Only destroy the 'struct device' for channels if indicated by the
|
||||
* 'destroy_device' flag. Because, during system suspend or hibernation
|
||||
* state, there is no need to destroy the 'struct device' as the endpoint
|
||||
* device would still be physically attached to the machine.
|
||||
*/
|
||||
if (destroy_device) {
|
||||
dev_dbg(dev, "Reset all active channels and remove MHI devices\n");
|
||||
device_for_each_child(&mhi_cntrl->mhi_dev->dev, NULL, mhi_destroy_device);
|
||||
}
|
||||
|
||||
mutex_lock(&mhi_cntrl->pm_mutex);
|
||||
|
||||
|
@ -629,7 +648,13 @@ static void mhi_pm_sys_error_transition(struct mhi_controller *mhi_cntrl)
|
|||
!in_reset, timeout);
|
||||
if (!ret || in_reset) {
|
||||
dev_err(dev, "Device failed to exit MHI Reset state\n");
|
||||
goto exit_sys_error_transition;
|
||||
write_lock_irq(&mhi_cntrl->pm_lock);
|
||||
cur_state = mhi_tryset_pm_state(mhi_cntrl,
|
||||
MHI_PM_SYS_ERR_FAIL);
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
/* Shutdown may have occurred, otherwise cleanup now */
|
||||
if (cur_state != MHI_PM_SYS_ERR_FAIL)
|
||||
goto exit_sys_error_transition;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -758,7 +783,6 @@ void mhi_pm_st_worker(struct work_struct *work)
|
|||
struct mhi_controller *mhi_cntrl = container_of(work,
|
||||
struct mhi_controller,
|
||||
st_worker);
|
||||
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
||||
|
||||
spin_lock_irq(&mhi_cntrl->transition_lock);
|
||||
list_splice_tail_init(&mhi_cntrl->transition_list, &head);
|
||||
|
@ -766,8 +790,8 @@ void mhi_pm_st_worker(struct work_struct *work)
|
|||
|
||||
list_for_each_entry_safe(itr, tmp, &head, node) {
|
||||
list_del(&itr->node);
|
||||
dev_dbg(dev, "Handling state transition: %s\n",
|
||||
TO_DEV_STATE_TRANS_STR(itr->state));
|
||||
|
||||
trace_mhi_pm_st_transition(mhi_cntrl, itr->state);
|
||||
|
||||
switch (itr->state) {
|
||||
case DEV_ST_TRANSITION_PBL:
|
||||
|
@ -806,7 +830,10 @@ void mhi_pm_st_worker(struct work_struct *work)
|
|||
mhi_pm_sys_error_transition(mhi_cntrl);
|
||||
break;
|
||||
case DEV_ST_TRANSITION_DISABLE:
|
||||
mhi_pm_disable_transition(mhi_cntrl);
|
||||
mhi_pm_disable_transition(mhi_cntrl, false);
|
||||
break;
|
||||
case DEV_ST_TRANSITION_DISABLE_DESTROY_DEVICE:
|
||||
mhi_pm_disable_transition(mhi_cntrl, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1160,7 +1187,8 @@ error_exit:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mhi_async_power_up);
|
||||
|
||||
void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful)
|
||||
static void __mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful,
|
||||
bool destroy_device)
|
||||
{
|
||||
enum mhi_pm_state cur_state, transition_state;
|
||||
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
||||
|
@ -1196,15 +1224,32 @@ void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful)
|
|||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
|
||||
mhi_queue_state_transition(mhi_cntrl, DEV_ST_TRANSITION_DISABLE);
|
||||
if (destroy_device)
|
||||
mhi_queue_state_transition(mhi_cntrl,
|
||||
DEV_ST_TRANSITION_DISABLE_DESTROY_DEVICE);
|
||||
else
|
||||
mhi_queue_state_transition(mhi_cntrl,
|
||||
DEV_ST_TRANSITION_DISABLE);
|
||||
|
||||
/* Wait for shutdown to complete */
|
||||
flush_work(&mhi_cntrl->st_worker);
|
||||
|
||||
disable_irq(mhi_cntrl->irq[0]);
|
||||
}
|
||||
|
||||
void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful)
|
||||
{
|
||||
__mhi_power_down(mhi_cntrl, graceful, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mhi_power_down);
|
||||
|
||||
void mhi_power_down_keep_dev(struct mhi_controller *mhi_cntrl,
|
||||
bool graceful)
|
||||
{
|
||||
__mhi_power_down(mhi_cntrl, graceful, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mhi_power_down_keep_dev);
|
||||
|
||||
int mhi_sync_power_up(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
int ret = mhi_async_power_up(mhi_cntrl);
|
||||
|
|
|
@ -0,0 +1,282 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM mhi_host
|
||||
|
||||
#if !defined(_TRACE_EVENT_MHI_HOST_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_EVENT_MHI_HOST_H
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
#include <linux/trace_seq.h>
|
||||
#include "../common.h"
|
||||
#include "internal.h"
|
||||
|
||||
#undef mhi_state
|
||||
#undef mhi_state_end
|
||||
|
||||
#define mhi_state(a, b) TRACE_DEFINE_ENUM(MHI_STATE_##a);
|
||||
#define mhi_state_end(a, b) TRACE_DEFINE_ENUM(MHI_STATE_##a);
|
||||
|
||||
MHI_STATE_LIST
|
||||
|
||||
#undef mhi_state
|
||||
#undef mhi_state_end
|
||||
|
||||
#define mhi_state(a, b) { MHI_STATE_##a, b },
|
||||
#define mhi_state_end(a, b) { MHI_STATE_##a, b }
|
||||
|
||||
#undef mhi_pm_state
|
||||
#undef mhi_pm_state_end
|
||||
|
||||
#define mhi_pm_state(a, b) TRACE_DEFINE_ENUM(MHI_PM_STATE_##a);
|
||||
#define mhi_pm_state_end(a, b) TRACE_DEFINE_ENUM(MHI_PM_STATE_##a);
|
||||
|
||||
MHI_PM_STATE_LIST
|
||||
|
||||
#undef mhi_pm_state
|
||||
#undef mhi_pm_state_end
|
||||
|
||||
#define mhi_pm_state(a, b) { MHI_PM_STATE_##a, b },
|
||||
#define mhi_pm_state_end(a, b) { MHI_PM_STATE_##a, b }
|
||||
|
||||
#undef mhi_ee
|
||||
#undef mhi_ee_end
|
||||
|
||||
#define mhi_ee(a, b) TRACE_DEFINE_ENUM(MHI_EE_##a);
|
||||
#define mhi_ee_end(a, b) TRACE_DEFINE_ENUM(MHI_EE_##a);
|
||||
|
||||
MHI_EE_LIST
|
||||
|
||||
#undef mhi_ee
|
||||
#undef mhi_ee_end
|
||||
|
||||
#define mhi_ee(a, b) { MHI_EE_##a, b },
|
||||
#define mhi_ee_end(a, b) { MHI_EE_##a, b }
|
||||
|
||||
#undef ch_state_type
|
||||
#undef ch_state_type_end
|
||||
|
||||
#define ch_state_type(a, b) TRACE_DEFINE_ENUM(MHI_CH_STATE_TYPE_##a);
|
||||
#define ch_state_type_end(a, b) TRACE_DEFINE_ENUM(MHI_CH_STATE_TYPE_##a);
|
||||
|
||||
MHI_CH_STATE_TYPE_LIST
|
||||
|
||||
#undef ch_state_type
|
||||
#undef ch_state_type_end
|
||||
|
||||
#define ch_state_type(a, b) { MHI_CH_STATE_TYPE_##a, b },
|
||||
#define ch_state_type_end(a, b) { MHI_CH_STATE_TYPE_##a, b }
|
||||
|
||||
#undef dev_st_trans
|
||||
#undef dev_st_trans_end
|
||||
|
||||
#define dev_st_trans(a, b) TRACE_DEFINE_ENUM(DEV_ST_TRANSITION_##a);
|
||||
#define dev_st_trans_end(a, b) TRACE_DEFINE_ENUM(DEV_ST_TRANSITION_##a);
|
||||
|
||||
DEV_ST_TRANSITION_LIST
|
||||
|
||||
#undef dev_st_trans
|
||||
#undef dev_st_trans_end
|
||||
|
||||
#define dev_st_trans(a, b) { DEV_ST_TRANSITION_##a, b },
|
||||
#define dev_st_trans_end(a, b) { DEV_ST_TRANSITION_##a, b }
|
||||
|
||||
#define TPS(x) tracepoint_string(x)
|
||||
|
||||
TRACE_EVENT(mhi_gen_tre,
|
||||
|
||||
TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
|
||||
struct mhi_ring_element *mhi_tre),
|
||||
|
||||
TP_ARGS(mhi_cntrl, mhi_chan, mhi_tre),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(name, mhi_cntrl->mhi_dev->name)
|
||||
__field(int, ch_num)
|
||||
__field(void *, wp)
|
||||
__field(__le64, tre_ptr)
|
||||
__field(__le32, dword0)
|
||||
__field(__le32, dword1)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, mhi_cntrl->mhi_dev->name);
|
||||
__entry->ch_num = mhi_chan->chan;
|
||||
__entry->wp = mhi_tre;
|
||||
__entry->tre_ptr = mhi_tre->ptr;
|
||||
__entry->dword0 = mhi_tre->dword[0];
|
||||
__entry->dword1 = mhi_tre->dword[1];
|
||||
),
|
||||
|
||||
TP_printk("%s: Chan: %d TRE: 0x%p TRE buf: 0x%llx DWORD0: 0x%08x DWORD1: 0x%08x\n",
|
||||
__get_str(name), __entry->ch_num, __entry->wp, __entry->tre_ptr,
|
||||
__entry->dword0, __entry->dword1)
|
||||
);
|
||||
|
||||
TRACE_EVENT(mhi_intvec_states,
|
||||
|
||||
TP_PROTO(struct mhi_controller *mhi_cntrl, int dev_ee, int dev_state),
|
||||
|
||||
TP_ARGS(mhi_cntrl, dev_ee, dev_state),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(name, mhi_cntrl->mhi_dev->name)
|
||||
__field(int, local_ee)
|
||||
__field(int, state)
|
||||
__field(int, dev_ee)
|
||||
__field(int, dev_state)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, mhi_cntrl->mhi_dev->name);
|
||||
__entry->local_ee = mhi_cntrl->ee;
|
||||
__entry->state = mhi_cntrl->dev_state;
|
||||
__entry->dev_ee = dev_ee;
|
||||
__entry->dev_state = dev_state;
|
||||
),
|
||||
|
||||
TP_printk("%s: Local EE: %s State: %s Device EE: %s Dev State: %s\n",
|
||||
__get_str(name),
|
||||
__print_symbolic(__entry->local_ee, MHI_EE_LIST),
|
||||
__print_symbolic(__entry->state, MHI_STATE_LIST),
|
||||
__print_symbolic(__entry->dev_ee, MHI_EE_LIST),
|
||||
__print_symbolic(__entry->dev_state, MHI_STATE_LIST))
|
||||
);
|
||||
|
||||
TRACE_EVENT(mhi_tryset_pm_state,
|
||||
|
||||
TP_PROTO(struct mhi_controller *mhi_cntrl, int pm_state),
|
||||
|
||||
TP_ARGS(mhi_cntrl, pm_state),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(name, mhi_cntrl->mhi_dev->name)
|
||||
__field(int, pm_state)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, mhi_cntrl->mhi_dev->name);
|
||||
if (pm_state)
|
||||
pm_state = __fls(pm_state);
|
||||
__entry->pm_state = pm_state;
|
||||
),
|
||||
|
||||
TP_printk("%s: PM state: %s\n", __get_str(name),
|
||||
__print_symbolic(__entry->pm_state, MHI_PM_STATE_LIST))
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(mhi_process_event_ring,
|
||||
|
||||
TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_ring_element *rp),
|
||||
|
||||
TP_ARGS(mhi_cntrl, rp),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(name, mhi_cntrl->mhi_dev->name)
|
||||
__field(__le32, dword0)
|
||||
__field(__le32, dword1)
|
||||
__field(int, state)
|
||||
__field(__le64, ptr)
|
||||
__field(void *, rp)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, mhi_cntrl->mhi_dev->name);
|
||||
__entry->rp = rp;
|
||||
__entry->ptr = rp->ptr;
|
||||
__entry->dword0 = rp->dword[0];
|
||||
__entry->dword1 = rp->dword[1];
|
||||
__entry->state = MHI_TRE_GET_EV_STATE(rp);
|
||||
),
|
||||
|
||||
TP_printk("%s: TRE: 0x%p TRE buf: 0x%llx DWORD0: 0x%08x DWORD1: 0x%08x State: %s\n",
|
||||
__get_str(name), __entry->rp, __entry->ptr, __entry->dword0,
|
||||
__entry->dword1, __print_symbolic(__entry->state, MHI_STATE_LIST))
|
||||
);
|
||||
|
||||
DEFINE_EVENT(mhi_process_event_ring, mhi_data_event,
|
||||
|
||||
TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_ring_element *rp),
|
||||
|
||||
TP_ARGS(mhi_cntrl, rp)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(mhi_process_event_ring, mhi_ctrl_event,
|
||||
|
||||
TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_ring_element *rp),
|
||||
|
||||
TP_ARGS(mhi_cntrl, rp)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(mhi_update_channel_state,
|
||||
|
||||
TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, int state,
|
||||
const char *reason),
|
||||
|
||||
TP_ARGS(mhi_cntrl, mhi_chan, state, reason),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(name, mhi_cntrl->mhi_dev->name)
|
||||
__field(int, ch_num)
|
||||
__field(int, state)
|
||||
__field(const char *, reason)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, mhi_cntrl->mhi_dev->name);
|
||||
__entry->ch_num = mhi_chan->chan;
|
||||
__entry->state = state;
|
||||
__entry->reason = reason;
|
||||
),
|
||||
|
||||
TP_printk("%s: chan%d: %s state to: %s\n",
|
||||
__get_str(name), __entry->ch_num, __entry->reason,
|
||||
__print_symbolic(__entry->state, MHI_CH_STATE_TYPE_LIST))
|
||||
);
|
||||
|
||||
DEFINE_EVENT(mhi_update_channel_state, mhi_channel_command_start,
|
||||
|
||||
TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, int state,
|
||||
const char *reason),
|
||||
|
||||
TP_ARGS(mhi_cntrl, mhi_chan, state, reason)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(mhi_update_channel_state, mhi_channel_command_end,
|
||||
|
||||
TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, int state,
|
||||
const char *reason),
|
||||
|
||||
TP_ARGS(mhi_cntrl, mhi_chan, state, reason)
|
||||
);
|
||||
|
||||
TRACE_EVENT(mhi_pm_st_transition,
|
||||
|
||||
TP_PROTO(struct mhi_controller *mhi_cntrl, int state),
|
||||
|
||||
TP_ARGS(mhi_cntrl, state),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(name, mhi_cntrl->mhi_dev->name)
|
||||
__field(int, state)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, mhi_cntrl->mhi_dev->name);
|
||||
__entry->state = state;
|
||||
),
|
||||
|
||||
TP_printk("%s: Handling state transition: %s\n", __get_str(name),
|
||||
__print_symbolic(__entry->state, DEV_ST_TRANSITION_LIST))
|
||||
);
|
||||
|
||||
#endif
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH ../../drivers/bus/mhi/host
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE trace
|
||||
|
||||
#include <trace/define_trace.h>
|
|
@ -1759,6 +1759,10 @@ static int adm8211_alloc_rings(struct ieee80211_hw *dev)
|
|||
}
|
||||
|
||||
static const struct ieee80211_ops adm8211_ops = {
|
||||
.add_chanctx = ieee80211_emulate_add_chanctx,
|
||||
.remove_chanctx = ieee80211_emulate_remove_chanctx,
|
||||
.change_chanctx = ieee80211_emulate_change_chanctx,
|
||||
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
|
||||
.tx = adm8211_tx,
|
||||
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = adm8211_start,
|
||||
|
|
|
@ -1348,6 +1348,10 @@ static void ar5523_configure_filter(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
static const struct ieee80211_ops ar5523_ops = {
|
||||
.add_chanctx = ieee80211_emulate_add_chanctx,
|
||||
.remove_chanctx = ieee80211_emulate_remove_chanctx,
|
||||
.change_chanctx = ieee80211_emulate_change_chanctx,
|
||||
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
|
||||
.start = ar5523_start,
|
||||
.stop = ar5523_stop,
|
||||
.tx = ar5523_tx,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -3613,7 +3613,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
|||
default:
|
||||
ath10k_err(ar, "unsupported core hardware revision %d\n",
|
||||
hw_rev);
|
||||
ret = -ENOTSUPP;
|
||||
ret = -EOPNOTSUPP;
|
||||
goto err_free_mac;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: ISC */
|
||||
/*
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _COREDUMP_H_
|
||||
|
@ -13,7 +13,11 @@
|
|||
|
||||
/**
|
||||
* enum ath10k_fw_crash_dump_type - types of data in the dump file
|
||||
* @ATH10K_FW_CRASH_DUMP_REGDUMP: Register crash dump in binary format
|
||||
* @ATH10K_FW_CRASH_DUMP_REGISTERS: Register crash dump in binary format
|
||||
* @ATH10K_FW_CRASH_DUMP_CE_DATA: Copy Engine crash dump data
|
||||
* @ATH10K_FW_CRASH_DUMP_RAM_DATA: RAM crash dump data, contains multiple
|
||||
* struct ath10k_dump_ram_data_hdr
|
||||
* @ATH10K_FW_CRASH_DUMP_MAX: Maximum enumeration
|
||||
*/
|
||||
enum ath10k_fw_crash_dump_type {
|
||||
ATH10K_FW_CRASH_DUMP_REGISTERS = 0,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
@ -381,7 +382,7 @@ static int ath10k_htt_verify_version(struct ath10k_htt *htt)
|
|||
htt->target_version_major != 3) {
|
||||
ath10k_err(ar, "unsupported htt major version %d. supported versions are 2 and 3\n",
|
||||
htt->target_version_major);
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021, 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021, 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _HTT_H_
|
||||
|
@ -906,7 +906,7 @@ struct htt_data_tx_completion_ext {
|
|||
__le16 msdus_rssi[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief target -> host TX completion indication message definition
|
||||
*
|
||||
* @details
|
||||
|
@ -1474,15 +1474,19 @@ enum htt_q_depth_type {
|
|||
#define HTT_TX_Q_STATE_ENTRY_MULTIPLIER 0
|
||||
|
||||
/**
|
||||
* htt_q_state_conf - part of htt_frag_desc_bank_cfg for host q state config
|
||||
* struct htt_q_state_conf - part of htt_frag_desc_bank_cfg for host q state config
|
||||
*
|
||||
* Defines host q state format and behavior. See htt_q_state.
|
||||
*
|
||||
* @paddr: Queue physical address
|
||||
* @num_peers: Number of supported peers
|
||||
* @num_tids: Number of supported TIDs
|
||||
* @record_size: Defines the size of each host q entry in bytes. In practice
|
||||
* however firmware (at least 10.4.3-00191) ignores this host
|
||||
* configuration value and uses hardcoded value of 1.
|
||||
* @record_multiplier: This is valid only when q depth type is MSDUs. It
|
||||
* defines the exponent for the power of 2 multiplication.
|
||||
* @pad: struct padding for 32-bit alignment
|
||||
*/
|
||||
struct htt_q_state_conf {
|
||||
__le32 paddr;
|
||||
|
@ -1518,7 +1522,7 @@ struct htt_frag_desc_bank_cfg64 {
|
|||
#define HTT_TX_Q_STATE_ENTRY_EXP_LSB 6
|
||||
|
||||
/**
|
||||
* htt_q_state - shared between host and firmware via DMA
|
||||
* struct htt_q_state - shared between host and firmware via DMA
|
||||
*
|
||||
* This structure is used for the host to expose it's software queue state to
|
||||
* firmware so that its rate control can schedule fetch requests for optimized
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "mac.h"
|
||||
|
@ -2034,8 +2034,8 @@ static void ath10k_mac_vif_ap_csa_count_down(struct ath10k_vif *arvif)
|
|||
if (!arvif->is_up)
|
||||
return;
|
||||
|
||||
if (!ieee80211_beacon_cntdwn_is_complete(vif)) {
|
||||
ieee80211_beacon_update_cntdwn(vif);
|
||||
if (!ieee80211_beacon_cntdwn_is_complete(vif, 0)) {
|
||||
ieee80211_beacon_update_cntdwn(vif, 0);
|
||||
|
||||
ret = ath10k_mac_setup_bcn_tmpl(arvif);
|
||||
if (ret)
|
||||
|
@ -2047,7 +2047,7 @@ static void ath10k_mac_vif_ap_csa_count_down(struct ath10k_vif *arvif)
|
|||
ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n",
|
||||
ret);
|
||||
} else {
|
||||
ieee80211_csa_finish(vif);
|
||||
ieee80211_csa_finish(vif, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4056,7 +4056,7 @@ static int ath10k_mac_tx(struct ath10k *ar,
|
|||
!(skb_cb->flags & ATH10K_SKB_F_RAW_TX)) {
|
||||
WARN_ON_ONCE(1);
|
||||
ieee80211_free_txskb(hw, skb);
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7065,7 +7065,7 @@ static int ath10k_mac_set_tid_config(struct ath10k *ar, struct ieee80211_sta *st
|
|||
|
||||
if (sta) {
|
||||
if (!sta->wme)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
arsta = (struct ath10k_sta *)sta->drv_priv;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
|
@ -889,7 +889,7 @@ static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
|
|||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
||||
if (WARN_ON_ONCE(!ar_pci->targ_cpu_to_ce_addr))
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ar_pci->targ_cpu_to_ce_addr(ar, addr);
|
||||
}
|
||||
|
@ -2668,7 +2668,7 @@ static int ath10k_pci_safe_chip_reset(struct ath10k *ar)
|
|||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
||||
if (!ar_pci->pci_soft_reset)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ar_pci->pci_soft_reset(ar);
|
||||
}
|
||||
|
@ -2808,7 +2808,7 @@ static int ath10k_pci_chip_reset(struct ath10k *ar)
|
|||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
||||
if (WARN_ON(!ar_pci->pci_hard_reset))
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ar_pci->pci_hard_reset(ar);
|
||||
}
|
||||
|
@ -3594,7 +3594,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
|||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev, ATH10K_BUS_PCI,
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
|
@ -851,6 +852,10 @@ ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k *ar, struct sk_buff *skb,
|
|||
}
|
||||
|
||||
ev = tb[WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_EVENT];
|
||||
if (!ev) {
|
||||
kfree(tb);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
arg->desc_id = ev->desc_id;
|
||||
arg->status = ev->status;
|
||||
|
@ -1347,7 +1352,7 @@ static int ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k *ar,
|
|||
__le32_to_cpu(ev->abi.abi_ver_ns1) != WMI_TLV_ABI_VER_NS1 ||
|
||||
__le32_to_cpu(ev->abi.abi_ver_ns2) != WMI_TLV_ABI_VER_NS2 ||
|
||||
__le32_to_cpu(ev->abi.abi_ver_ns3) != WMI_TLV_ABI_VER_NS3) {
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
arg->min_tx_power = ev->hw_min_tx_power;
|
||||
|
@ -2119,9 +2124,9 @@ static int ath10k_wmi_tlv_op_get_vdev_subtype(struct ath10k *ar,
|
|||
case WMI_VDEV_SUBTYPE_MESH_11S:
|
||||
return WMI_TLV_VDEV_SUBTYPE_MESH_11S;
|
||||
case WMI_VDEV_SUBTYPE_MESH_NON_11S:
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef _WMI_TLV_H
|
||||
#define _WMI_TLV_H
|
||||
|
@ -2343,7 +2343,7 @@ struct wmi_tlv_adaptive_qcs {
|
|||
} __packed;
|
||||
|
||||
/**
|
||||
* wmi_tlv_tx_pause_id - firmware tx queue pause reason types
|
||||
* enum wmi_tlv_tx_pause_id - firmware tx queue pause reason types
|
||||
*
|
||||
* @WMI_TLV_TX_PAUSE_ID_MCC: used for by multi-channel firmware scheduler.
|
||||
* Only vdev_map is valid.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
|
@ -3884,8 +3884,8 @@ void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
|
|||
* actual channel switch is done
|
||||
*/
|
||||
if (arvif->vif->bss_conf.csa_active &&
|
||||
ieee80211_beacon_cntdwn_is_complete(arvif->vif)) {
|
||||
ieee80211_csa_finish(arvif->vif);
|
||||
ieee80211_beacon_cntdwn_is_complete(arvif->vif, 0)) {
|
||||
ieee80211_csa_finish(arvif->vif, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -6927,14 +6927,14 @@ void ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn,
|
|||
}
|
||||
|
||||
static void
|
||||
ath10k_wmi_put_start_scan_tlvs(struct wmi_start_scan_tlvs *tlvs,
|
||||
ath10k_wmi_put_start_scan_tlvs(u8 *tlvs,
|
||||
const struct wmi_start_scan_arg *arg)
|
||||
{
|
||||
struct wmi_ie_data *ie;
|
||||
struct wmi_chan_list *channels;
|
||||
struct wmi_ssid_list *ssids;
|
||||
struct wmi_bssid_list *bssids;
|
||||
void *ptr = tlvs->tlvs;
|
||||
void *ptr = tlvs;
|
||||
int i;
|
||||
|
||||
if (arg->n_channels) {
|
||||
|
@ -7012,7 +7012,7 @@ ath10k_wmi_op_gen_start_scan(struct ath10k *ar,
|
|||
cmd = (struct wmi_start_scan_cmd *)skb->data;
|
||||
|
||||
ath10k_wmi_put_start_scan_common(&cmd->common, arg);
|
||||
ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg);
|
||||
ath10k_wmi_put_start_scan_tlvs(cmd->tlvs, arg);
|
||||
|
||||
cmd->burst_duration_ms = __cpu_to_le32(0);
|
||||
|
||||
|
@ -7041,7 +7041,7 @@ ath10k_wmi_10x_op_gen_start_scan(struct ath10k *ar,
|
|||
cmd = (struct wmi_10x_start_scan_cmd *)skb->data;
|
||||
|
||||
ath10k_wmi_put_start_scan_common(&cmd->common, arg);
|
||||
ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg);
|
||||
ath10k_wmi_put_start_scan_tlvs(cmd->tlvs, arg);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi 10x start scan\n");
|
||||
return skb;
|
||||
|
@ -8733,9 +8733,9 @@ int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar,
|
|||
return WMI_VDEV_SUBTYPE_LEGACY_PROXY_STA;
|
||||
case WMI_VDEV_SUBTYPE_MESH_11S:
|
||||
case WMI_VDEV_SUBTYPE_MESH_NON_11S:
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int ath10k_wmi_10_2_4_op_get_vdev_subtype(struct ath10k *ar,
|
||||
|
@ -8755,9 +8755,9 @@ static int ath10k_wmi_10_2_4_op_get_vdev_subtype(struct ath10k *ar,
|
|||
case WMI_VDEV_SUBTYPE_MESH_11S:
|
||||
return WMI_VDEV_SUBTYPE_10_2_4_MESH_11S;
|
||||
case WMI_VDEV_SUBTYPE_MESH_NON_11S:
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int ath10k_wmi_10_4_op_get_vdev_subtype(struct ath10k *ar,
|
||||
|
@ -8779,7 +8779,7 @@ static int ath10k_wmi_10_4_op_get_vdev_subtype(struct ath10k *ar,
|
|||
case WMI_VDEV_SUBTYPE_MESH_NON_11S:
|
||||
return WMI_VDEV_SUBTYPE_10_4_MESH_NON_11S;
|
||||
}
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
|
@ -8918,8 +8918,6 @@ ath10k_wmi_10_4_gen_tdls_peer_update(struct ath10k *ar,
|
|||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memset(skb->data, 0, sizeof(*cmd));
|
||||
|
||||
cmd = (struct wmi_10_4_tdls_peer_update_cmd *)skb->data;
|
||||
cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
|
||||
ether_addr_copy(cmd->peer_macaddr.addr, arg->addr);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
||||
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _WMI_H_
|
||||
|
@ -3008,8 +3008,11 @@ enum wmi_coex_version {
|
|||
* @WMI_10_4_TDLS_UAPSD_SLEEP_STA: TDLS sleep sta support enable/disable
|
||||
* @WMI_10_4_TDLS_CONN_TRACKER_IN_HOST_MODE: TDLS connection tracker in host
|
||||
* enable/disable
|
||||
* @WMI_10_4_TDLS_EXPLICIT_MODE_ONLY:Explicit TDLS mode enable/disable
|
||||
* @WMI_10_4_TDLS_EXPLICIT_MODE_ONLY: Explicit TDLS mode enable/disable
|
||||
* @WMI_10_4_TX_DATA_ACK_RSSI: Enable DATA ACK RSSI if firmware is capable
|
||||
* @WMI_10_4_EXT_PEER_TID_CONFIGS_SUPPORT: Firmware supports Extended Peer
|
||||
* TID configuration for QoS related settings
|
||||
* @WMI_10_4_REPORT_AIRTIME: Firmware supports transmit airtime reporting
|
||||
*/
|
||||
enum wmi_10_4_feature_mask {
|
||||
WMI_10_4_LTEU_SUPPORT = BIT(0),
|
||||
|
@ -3069,7 +3072,10 @@ struct host_memory_chunk {
|
|||
struct wmi_host_mem_chunks {
|
||||
__le32 count;
|
||||
/* some fw revisions require at least 1 chunk regardless of count */
|
||||
struct host_memory_chunk items[1];
|
||||
union {
|
||||
struct host_memory_chunk item;
|
||||
DECLARE_FLEX_ARRAY(struct host_memory_chunk, items);
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct wmi_init_cmd {
|
||||
|
@ -3215,23 +3221,16 @@ struct wmi_start_scan_common {
|
|||
__le32 scan_ctrl_flags;
|
||||
} __packed;
|
||||
|
||||
struct wmi_start_scan_tlvs {
|
||||
/* TLV parameters. These includes channel list, ssid list, bssid list,
|
||||
* extra ies.
|
||||
*/
|
||||
u8 tlvs[0];
|
||||
} __packed;
|
||||
|
||||
struct wmi_start_scan_cmd {
|
||||
struct wmi_start_scan_common common;
|
||||
__le32 burst_duration_ms;
|
||||
struct wmi_start_scan_tlvs tlvs;
|
||||
u8 tlvs[];
|
||||
} __packed;
|
||||
|
||||
/* This is the definition from 10.X firmware branch */
|
||||
struct wmi_10x_start_scan_cmd {
|
||||
struct wmi_start_scan_common common;
|
||||
struct wmi_start_scan_tlvs tlvs;
|
||||
u8 tlvs[];
|
||||
} __packed;
|
||||
|
||||
struct wmi_ssid_arg {
|
||||
|
@ -4260,13 +4259,6 @@ struct wmi_peer_sta_ps_state_chg_event {
|
|||
__le32 peer_ps_state;
|
||||
} __packed;
|
||||
|
||||
struct wmi_pdev_chanlist_update_event {
|
||||
/* number of channels */
|
||||
__le32 num_chan;
|
||||
/* array of channels */
|
||||
struct wmi_channel channel_list[1];
|
||||
} __packed;
|
||||
|
||||
#define WMI_MAX_DEBUG_MESG (sizeof(u32) * 32)
|
||||
|
||||
struct wmi_debug_mesg_event {
|
||||
|
@ -5793,30 +5785,6 @@ struct wmi_bcn_prb_info {
|
|||
/* app IE */
|
||||
} __packed;
|
||||
|
||||
struct wmi_bcn_tmpl_cmd {
|
||||
/* unique id identifying the VDEV, generated by the caller */
|
||||
__le32 vdev_id;
|
||||
/* TIM IE offset from the beginning of the template. */
|
||||
__le32 tim_ie_offset;
|
||||
/* beacon probe capabilities and IEs */
|
||||
struct wmi_bcn_prb_info bcn_prb_info;
|
||||
/* beacon buffer length */
|
||||
__le32 buf_len;
|
||||
/* variable length data */
|
||||
u8 data[1];
|
||||
} __packed;
|
||||
|
||||
struct wmi_prb_tmpl_cmd {
|
||||
/* unique id identifying the VDEV, generated by the caller */
|
||||
__le32 vdev_id;
|
||||
/* beacon probe capabilities and IEs */
|
||||
struct wmi_bcn_prb_info bcn_prb_info;
|
||||
/* beacon buffer length */
|
||||
__le32 buf_len;
|
||||
/* Variable length data */
|
||||
u8 data[1];
|
||||
} __packed;
|
||||
|
||||
enum wmi_sta_ps_mode {
|
||||
/* enable power save for the given STA VDEV */
|
||||
WMI_STA_PS_MODE_DISABLED = 0,
|
||||
|
@ -7197,7 +7165,13 @@ struct wmi_tdls_peer_capabilities {
|
|||
__le32 is_peer_responder;
|
||||
__le32 pref_offchan_num;
|
||||
__le32 pref_offchan_bw;
|
||||
struct wmi_channel peer_chan_list[1];
|
||||
union {
|
||||
/* to match legacy implementation allocate room for
|
||||
* at least one record even if peer_chan_len is 0
|
||||
*/
|
||||
struct wmi_channel peer_chan_min_allocation;
|
||||
DECLARE_FLEX_ARRAY(struct wmi_channel, peer_chan_list);
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_tdls_peer_update_cmd {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -413,7 +413,7 @@ static int ath11k_ahb_power_up(struct ath11k_base *ab)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_ahb_power_down(struct ath11k_base *ab)
|
||||
static void ath11k_ahb_power_down(struct ath11k_base *ab, bool is_suspend)
|
||||
{
|
||||
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
|
||||
|
||||
|
@ -1256,7 +1256,7 @@ static void ath11k_ahb_remove(struct platform_device *pdev)
|
|||
struct ath11k_base *ab = platform_get_drvdata(pdev);
|
||||
|
||||
if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
|
||||
ath11k_ahb_power_down(ab);
|
||||
ath11k_ahb_power_down(ab, false);
|
||||
ath11k_debugfs_soc_destroy(ab);
|
||||
ath11k_qmi_deinit_service(ab);
|
||||
goto qmi_fail;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -122,6 +122,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tcl_ring_retry = true,
|
||||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_dual_stations = false,
|
||||
},
|
||||
{
|
||||
.hw_rev = ATH11K_HW_IPQ6018_HW10,
|
||||
|
@ -205,6 +206,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = false,
|
||||
.support_dual_stations = false,
|
||||
},
|
||||
{
|
||||
.name = "qca6390 hw2.0",
|
||||
|
@ -255,7 +257,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.coldboot_cal_ftm = false,
|
||||
.cbcal_restart_fw = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_vdevs = 2 + 1,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
|
||||
|
@ -290,6 +292,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = true,
|
||||
.support_dual_stations = true,
|
||||
},
|
||||
{
|
||||
.name = "qcn9074 hw1.0",
|
||||
|
@ -372,6 +375,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = false,
|
||||
.support_dual_stations = false,
|
||||
},
|
||||
{
|
||||
.name = "wcn6855 hw2.0",
|
||||
|
@ -422,7 +426,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.coldboot_cal_ftm = false,
|
||||
.cbcal_restart_fw = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_vdevs = 2 + 1,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
|
||||
|
@ -457,6 +461,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = true,
|
||||
.support_dual_stations = true,
|
||||
},
|
||||
{
|
||||
.name = "wcn6855 hw2.1",
|
||||
|
@ -505,7 +510,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.coldboot_cal_ftm = false,
|
||||
.cbcal_restart_fw = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_vdevs = 2 + 1,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
|
||||
|
@ -540,6 +545,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = true,
|
||||
.support_dual_stations = true,
|
||||
},
|
||||
{
|
||||
.name = "wcn6750 hw1.0",
|
||||
|
@ -621,6 +627,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tx_ring_size = DP_TCL_DATA_RING_SIZE_WCN6750,
|
||||
.smp2p_wow_exit = true,
|
||||
.support_fw_mac_sequence = true,
|
||||
.support_dual_stations = false,
|
||||
},
|
||||
{
|
||||
.hw_rev = ATH11K_HW_IPQ5018_HW10,
|
||||
|
@ -702,6 +709,93 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = false,
|
||||
.support_dual_stations = false,
|
||||
},
|
||||
{
|
||||
.name = "qca2066 hw2.1",
|
||||
.hw_rev = ATH11K_HW_QCA2066_HW21,
|
||||
.fw = {
|
||||
.dir = "QCA2066/hw2.1",
|
||||
.board_size = 256 * 1024,
|
||||
.cal_offset = 128 * 1024,
|
||||
},
|
||||
.max_radios = 3,
|
||||
.bdf_addr = 0x4B0C0000,
|
||||
.hw_ops = &wcn6855_ops,
|
||||
.ring_mask = &ath11k_hw_ring_mask_qca6390,
|
||||
.internal_sleep_clock = true,
|
||||
.regs = &wcn6855_regs,
|
||||
.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,
|
||||
.host_ce_config = ath11k_host_ce_config_qca6390,
|
||||
.ce_count = 9,
|
||||
.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
|
||||
.target_ce_count = 9,
|
||||
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
|
||||
.svc_to_ce_map_len = 14,
|
||||
.ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,
|
||||
.single_pdev_only = true,
|
||||
.rxdma1_enable = false,
|
||||
.num_rxmda_per_pdev = 2,
|
||||
.rx_mac_buf_ring = true,
|
||||
.vdev_start_delay = true,
|
||||
.htt_peer_map_v2 = false,
|
||||
|
||||
.spectral = {
|
||||
.fft_sz = 0,
|
||||
.fft_pad_sz = 0,
|
||||
.summary_pad_sz = 0,
|
||||
.fft_hdr_len = 0,
|
||||
.max_fft_bins = 0,
|
||||
.fragment_160mhz = false,
|
||||
},
|
||||
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP),
|
||||
.supports_monitor = false,
|
||||
.full_monitor_mode = false,
|
||||
.supports_shadow_regs = true,
|
||||
.idle_ps = true,
|
||||
.supports_sta_ps = true,
|
||||
.coldboot_cal_mm = false,
|
||||
.coldboot_cal_ftm = false,
|
||||
.cbcal_restart_fw = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 2 + 1,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
|
||||
.supports_regdb = true,
|
||||
.fix_l1ss = false,
|
||||
.credit_flow = true,
|
||||
.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
|
||||
.hal_params = &ath11k_hw_hal_params_qca6390,
|
||||
.supports_dynamic_smps_6ghz = false,
|
||||
.alloc_cacheable_memory = false,
|
||||
.supports_rssi_stats = true,
|
||||
.fw_wmi_diag_event = true,
|
||||
.current_cc_support = true,
|
||||
.dbr_debug_support = false,
|
||||
.global_reset = true,
|
||||
.bios_sar_capa = &ath11k_hw_sar_capa_wcn6855,
|
||||
.m3_fw_support = true,
|
||||
.fixed_bdf_addr = false,
|
||||
.fixed_mem_region = false,
|
||||
.static_window_map = false,
|
||||
.hybrid_bus_type = false,
|
||||
.fixed_fw_mem = false,
|
||||
.support_off_channel_tx = true,
|
||||
.supports_multi_bssid = true,
|
||||
|
||||
.sram_dump = {
|
||||
.start = 0x01400000,
|
||||
.end = 0x0177ffff,
|
||||
},
|
||||
|
||||
.tcl_ring_retry = true,
|
||||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = true,
|
||||
.support_dual_stations = true,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -800,12 +894,6 @@ int ath11k_core_suspend(struct ath11k_base *ab)
|
|||
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",
|
||||
|
@ -816,20 +904,49 @@ int ath11k_core_suspend(struct ath11k_base *ab)
|
|||
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;
|
||||
}
|
||||
/* PM framework skips suspend_late/resume_early callbacks
|
||||
* if other devices report errors in their suspend callbacks.
|
||||
* However ath11k_core_resume() would still be called because
|
||||
* here we return success thus kernel put us on dpm_suspended_list.
|
||||
* Since we won't go through a power down/up cycle, there is
|
||||
* no chance to call complete(&ab->restart_completed) in
|
||||
* ath11k_core_restart(), making ath11k_core_resume() timeout.
|
||||
* So call it here to avoid this issue. This also works in case
|
||||
* no error happens thus suspend_late/resume_early get called,
|
||||
* because it will be reinitialized in ath11k_core_resume_early().
|
||||
*/
|
||||
complete(&ab->restart_completed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_suspend);
|
||||
|
||||
int ath11k_core_resume(struct ath11k_base *ab)
|
||||
int ath11k_core_suspend_late(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_pdev *pdev;
|
||||
struct ath11k *ar;
|
||||
|
||||
if (!ab->hw_params.supports_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* so far single_pdev_only chips have supports_suspend as true
|
||||
* and only the first pdev is valid.
|
||||
*/
|
||||
pdev = ath11k_core_get_single_pdev(ab);
|
||||
ar = pdev->ar;
|
||||
if (!ar || ar->state != ATH11K_STATE_OFF)
|
||||
return 0;
|
||||
|
||||
ath11k_hif_irq_disable(ab);
|
||||
ath11k_hif_ce_irq_disable(ab);
|
||||
|
||||
ath11k_hif_power_down(ab, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_suspend_late);
|
||||
|
||||
int ath11k_core_resume_early(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
struct ath11k_pdev *pdev;
|
||||
|
@ -838,7 +955,7 @@ int ath11k_core_resume(struct ath11k_base *ab)
|
|||
if (!ab->hw_params.supports_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* so far signle_pdev_only chips have supports_suspend as true
|
||||
/* so far single_pdev_only chips have supports_suspend as true
|
||||
* and only the first pdev is valid.
|
||||
*/
|
||||
pdev = ath11k_core_get_single_pdev(ab);
|
||||
|
@ -846,29 +963,56 @@ int ath11k_core_resume(struct ath11k_base *ab)
|
|||
if (!ar || ar->state != ATH11K_STATE_OFF)
|
||||
return 0;
|
||||
|
||||
ret = ath11k_hif_resume(ab);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to resume hif during resume: %d\n", ret);
|
||||
return ret;
|
||||
reinit_completion(&ab->restart_completed);
|
||||
ret = ath11k_hif_power_up(ab);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to power up hif during resume: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_resume_early);
|
||||
|
||||
int ath11k_core_resume(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
struct ath11k_pdev *pdev;
|
||||
struct ath11k *ar;
|
||||
long time_left;
|
||||
|
||||
if (!ab->hw_params.supports_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* so far single_pdev_only chips have supports_suspend as true
|
||||
* and only the first pdev is valid.
|
||||
*/
|
||||
pdev = ath11k_core_get_single_pdev(ab);
|
||||
ar = pdev->ar;
|
||||
if (!ar || ar->state != ATH11K_STATE_OFF)
|
||||
return 0;
|
||||
|
||||
time_left = wait_for_completion_timeout(&ab->restart_completed,
|
||||
ATH11K_RESET_TIMEOUT_HZ);
|
||||
if (time_left == 0) {
|
||||
ath11k_warn(ab, "timeout while waiting for restart complete");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
ath11k_hif_ce_irq_enable(ab);
|
||||
ath11k_hif_irq_enable(ab);
|
||||
if (ab->hw_params.current_cc_support &&
|
||||
ar->alpha2[0] != 0 && ar->alpha2[1] != 0) {
|
||||
ret = ath11k_reg_set_cc(ar);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set country code during resume: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ath11k_dp_rx_pktlog_start(ab);
|
||||
if (ret) {
|
||||
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;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_resume);
|
||||
|
||||
|
@ -1775,10 +1919,9 @@ static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab)
|
|||
|
||||
mutex_lock(&ab->core_lock);
|
||||
ath11k_thermal_unregister(ab);
|
||||
ath11k_hif_irq_disable(ab);
|
||||
ath11k_dp_pdev_free(ab);
|
||||
ath11k_spectral_deinit(ab);
|
||||
ath11k_hif_stop(ab);
|
||||
ath11k_ce_cleanup_pipes(ab);
|
||||
ath11k_wmi_detach(ab);
|
||||
ath11k_dp_pdev_reo_cleanup(ab);
|
||||
mutex_unlock(&ab->core_lock);
|
||||
|
@ -1833,23 +1976,20 @@ static void ath11k_update_11d(struct work_struct *work)
|
|||
struct ath11k_base *ab = container_of(work, struct ath11k_base, update_11d_work);
|
||||
struct ath11k *ar;
|
||||
struct ath11k_pdev *pdev;
|
||||
struct wmi_set_current_country_params set_current_param = {};
|
||||
int ret, i;
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
memcpy(&set_current_param.alpha2, &ab->new_alpha2, 2);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "update 11d new cc %c%c\n",
|
||||
set_current_param.alpha2[0],
|
||||
set_current_param.alpha2[1]);
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
ar = pdev->ar;
|
||||
|
||||
memcpy(&ar->alpha2, &set_current_param.alpha2, 2);
|
||||
ret = ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param);
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
memcpy(&ar->alpha2, &ab->new_alpha2, 2);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "update 11d new cc %c%c for pdev %d\n",
|
||||
ar->alpha2[0], ar->alpha2[1], i);
|
||||
|
||||
ret = ath11k_reg_set_cc(ar);
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab,
|
||||
"pdev id %d failed set current country code: %d\n",
|
||||
|
@ -1967,6 +2107,8 @@ static void ath11k_core_restart(struct work_struct *work)
|
|||
|
||||
if (!ab->is_reset)
|
||||
ath11k_core_post_reconfigure_recovery(ab);
|
||||
|
||||
complete(&ab->restart_completed);
|
||||
}
|
||||
|
||||
static void ath11k_core_reset(struct work_struct *work)
|
||||
|
@ -2033,7 +2175,10 @@ static void ath11k_core_reset(struct work_struct *work)
|
|||
time_left = wait_for_completion_timeout(&ab->recovery_start,
|
||||
ATH11K_RECOVER_START_TIMEOUT_HZ);
|
||||
|
||||
ath11k_hif_power_down(ab);
|
||||
ath11k_hif_irq_disable(ab);
|
||||
ath11k_hif_ce_irq_disable(ab);
|
||||
|
||||
ath11k_hif_power_down(ab, false);
|
||||
ath11k_hif_power_up(ab);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n");
|
||||
|
@ -2106,7 +2251,7 @@ void ath11k_core_deinit(struct ath11k_base *ab)
|
|||
|
||||
mutex_unlock(&ab->core_lock);
|
||||
|
||||
ath11k_hif_power_down(ab);
|
||||
ath11k_hif_power_down(ab, false);
|
||||
ath11k_mac_destroy(ab);
|
||||
ath11k_core_soc_destroy(ab);
|
||||
ath11k_fw_destroy(ab);
|
||||
|
@ -2159,6 +2304,7 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
|
|||
timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
|
||||
init_completion(&ab->htc_suspend);
|
||||
init_completion(&ab->wow.wakeup_completed);
|
||||
init_completion(&ab->restart_completed);
|
||||
|
||||
ab->dev = dev;
|
||||
ab->hif.bus = bus;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH11K_CORE_H
|
||||
|
@ -147,6 +147,7 @@ enum ath11k_hw_rev {
|
|||
ATH11K_HW_WCN6855_HW21,
|
||||
ATH11K_HW_WCN6750_HW10,
|
||||
ATH11K_HW_IPQ5018_HW10,
|
||||
ATH11K_HW_QCA2066_HW21,
|
||||
};
|
||||
|
||||
enum ath11k_firmware_mode {
|
||||
|
@ -314,6 +315,43 @@ struct ath11k_rekey_data {
|
|||
bool enable_offload;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ath11k_chan_power_info - TPE containing power info per channel chunk
|
||||
* @chan_cfreq: channel center freq (MHz)
|
||||
* e.g.
|
||||
* channel 37/20 MHz, it is 6135
|
||||
* channel 37/40 MHz, it is 6125
|
||||
* channel 37/80 MHz, it is 6145
|
||||
* channel 37/160 MHz, it is 6185
|
||||
* @tx_power: transmit power (dBm)
|
||||
*/
|
||||
struct ath11k_chan_power_info {
|
||||
u16 chan_cfreq;
|
||||
s8 tx_power;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ath11k_reg_tpc_power_info - regulatory TPC power info
|
||||
* @is_psd_power: is PSD power or not
|
||||
* @eirp_power: Maximum EIRP power (dBm), valid only if power is PSD
|
||||
* @ap_power_type: type of power (SP/LPI/VLP)
|
||||
* @num_pwr_levels: number of power levels
|
||||
* @reg_max: Array of maximum TX power (dBm) per PSD value
|
||||
* @ap_constraint_power: AP constraint power (dBm)
|
||||
* @tpe: TPE values processed from TPE IE
|
||||
* @chan_power_info: power info to send to firmware
|
||||
*/
|
||||
struct ath11k_reg_tpc_power_info {
|
||||
bool is_psd_power;
|
||||
u8 eirp_power;
|
||||
enum wmi_reg_6ghz_ap_type ap_power_type;
|
||||
u8 num_pwr_levels;
|
||||
u8 reg_max[IEEE80211_MAX_NUM_PWR_LEVEL];
|
||||
u8 ap_constraint_power;
|
||||
s8 tpe[IEEE80211_MAX_NUM_PWR_LEVEL];
|
||||
struct ath11k_chan_power_info chan_power_info[IEEE80211_MAX_NUM_PWR_LEVEL];
|
||||
};
|
||||
|
||||
struct ath11k_vif {
|
||||
u32 vdev_id;
|
||||
enum wmi_vdev_type vdev_type;
|
||||
|
@ -368,6 +406,8 @@ struct ath11k_vif {
|
|||
struct ieee80211_chanctx_conf chanctx;
|
||||
struct ath11k_arp_ns_offload arp_ns_offload;
|
||||
struct ath11k_rekey_data rekey_data;
|
||||
|
||||
struct ath11k_reg_tpc_power_info reg_tpc_info;
|
||||
};
|
||||
|
||||
struct ath11k_vif_iter {
|
||||
|
@ -735,6 +775,7 @@ struct ath11k {
|
|||
/* protected by conf_mutex */
|
||||
bool ps_state_enable;
|
||||
bool ps_timekeeper_enable;
|
||||
s8 max_allowed_tx_power;
|
||||
};
|
||||
|
||||
struct ath11k_band_cap {
|
||||
|
@ -918,6 +959,7 @@ struct ath11k_base {
|
|||
* This may or may not be used during the runtime
|
||||
*/
|
||||
struct ieee80211_regdomain *new_regd[MAX_RADIOS];
|
||||
struct cur_regulatory_info *reg_info_store;
|
||||
|
||||
/* Current DFS Regulatory */
|
||||
enum ath11k_dfs_region dfs_region;
|
||||
|
@ -991,6 +1033,8 @@ struct ath11k_base {
|
|||
DECLARE_BITMAP(fw_features, ATH11K_FW_FEATURE_COUNT);
|
||||
} fw;
|
||||
|
||||
struct completion restart_completed;
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
struct {
|
||||
u32 data_pos;
|
||||
|
@ -1190,8 +1234,10 @@ void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd);
|
|||
int ath11k_core_check_dt(struct ath11k_base *ath11k);
|
||||
int ath11k_core_check_smbios(struct ath11k_base *ab);
|
||||
void ath11k_core_halt(struct ath11k *ar);
|
||||
int ath11k_core_resume_early(struct ath11k_base *ab);
|
||||
int ath11k_core_resume(struct ath11k_base *ab);
|
||||
int ath11k_core_suspend(struct ath11k_base *ab);
|
||||
int ath11k_core_suspend_late(struct ath11k_base *ab);
|
||||
void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab);
|
||||
bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab);
|
||||
|
||||
|
|
|
@ -104,11 +104,14 @@ void ath11k_dp_srng_cleanup(struct ath11k_base *ab, struct dp_srng *ring)
|
|||
if (!ring->vaddr_unaligned)
|
||||
return;
|
||||
|
||||
if (ring->cached)
|
||||
if (ring->cached) {
|
||||
dma_unmap_single(ab->dev, ring->paddr_unaligned, ring->size,
|
||||
DMA_FROM_DEVICE);
|
||||
kfree(ring->vaddr_unaligned);
|
||||
else
|
||||
} else {
|
||||
dma_free_coherent(ab->dev, ring->size, ring->vaddr_unaligned,
|
||||
ring->paddr_unaligned);
|
||||
}
|
||||
|
||||
ring->vaddr_unaligned = NULL;
|
||||
}
|
||||
|
@ -249,7 +252,18 @@ int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,
|
|||
|
||||
if (cached) {
|
||||
ring->vaddr_unaligned = kzalloc(ring->size, GFP_KERNEL);
|
||||
ring->paddr_unaligned = virt_to_phys(ring->vaddr_unaligned);
|
||||
if (!ring->vaddr_unaligned)
|
||||
return -ENOMEM;
|
||||
|
||||
ring->paddr_unaligned = dma_map_single(ab->dev,
|
||||
ring->vaddr_unaligned,
|
||||
ring->size,
|
||||
DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(ab->dev, ring->paddr_unaligned)) {
|
||||
kfree(ring->vaddr_unaligned);
|
||||
ring->vaddr_unaligned = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
|
@ -103,7 +103,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
|
|||
|
||||
if (unlikely(!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
|
||||
!ieee80211_is_data(hdr->frame_control)))
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
pool_id = skb_get_queue_mapping(skb) & (ATH11K_HW_MAX_QUEUES - 1);
|
||||
|
||||
|
@ -1018,7 +1018,7 @@ int ath11k_dp_tx_htt_h2t_ver_req_msg(struct ath11k_base *ab)
|
|||
if (dp->htt_tgt_ver_major != HTT_TARGET_VERSION_MAJOR) {
|
||||
ath11k_err(ab, "unsupported htt major version %d supported version is %d\n",
|
||||
dp->htt_tgt_ver_major, HTT_TARGET_VERSION_MAJOR);
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -626,15 +626,30 @@ u32 *ath11k_hal_srng_dst_peek(struct ath11k_base *ab, struct hal_srng *srng)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static u32 *ath11k_hal_srng_dst_peek_with_dma(struct ath11k_base *ab,
|
||||
struct hal_srng *srng, dma_addr_t *paddr)
|
||||
{
|
||||
lockdep_assert_held(&srng->lock);
|
||||
|
||||
if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp) {
|
||||
*paddr = srng->ring_base_paddr +
|
||||
sizeof(*srng->ring_base_vaddr) * srng->u.dst_ring.tp;
|
||||
return srng->ring_base_vaddr + srng->u.dst_ring.tp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ath11k_hal_srng_prefetch_desc(struct ath11k_base *ab,
|
||||
struct hal_srng *srng)
|
||||
{
|
||||
dma_addr_t desc_paddr;
|
||||
u32 *desc;
|
||||
|
||||
/* prefetch only if desc is available */
|
||||
desc = ath11k_hal_srng_dst_peek(ab, srng);
|
||||
desc = ath11k_hal_srng_dst_peek_with_dma(ab, srng, &desc_paddr);
|
||||
if (likely(desc)) {
|
||||
dma_sync_single_for_cpu(ab->dev, virt_to_phys(desc),
|
||||
dma_sync_single_for_cpu(ab->dev, desc_paddr,
|
||||
(srng->entry_size * sizeof(u32)),
|
||||
DMA_FROM_DEVICE);
|
||||
prefetch(desc);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH11K_HAL_H
|
||||
|
@ -674,6 +674,7 @@ struct hal_srng_config {
|
|||
* @HAL_RX_BUF_RBM_SW1_BM: For Tx completion -- returned to host
|
||||
* @HAL_RX_BUF_RBM_SW2_BM: For Tx completion -- returned to host
|
||||
* @HAL_RX_BUF_RBM_SW3_BM: For Rx release -- returned to host
|
||||
* @HAL_RX_BUF_RBM_SW4_BM: For Tx completion -- returned to host
|
||||
*/
|
||||
|
||||
enum hal_rx_buf_return_buf_manager {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
|
@ -246,7 +246,7 @@ int ath11k_hal_reo_cmd_send(struct ath11k_base *ab, struct hal_srng *srng,
|
|||
case HAL_REO_CMD_UNBLOCK_CACHE:
|
||||
case HAL_REO_CMD_FLUSH_TIMEOUT_LIST:
|
||||
ath11k_warn(ab, "Unsupported reo command %d\n", type);
|
||||
ret = -ENOTSUPP;
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
default:
|
||||
ath11k_warn(ab, "Unknown reo command %d\n", type);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _HIF_H_
|
||||
|
@ -18,7 +18,7 @@ struct ath11k_hif_ops {
|
|||
int (*start)(struct ath11k_base *ab);
|
||||
void (*stop)(struct ath11k_base *ab);
|
||||
int (*power_up)(struct ath11k_base *ab);
|
||||
void (*power_down)(struct ath11k_base *ab);
|
||||
void (*power_down)(struct ath11k_base *ab, bool is_suspend);
|
||||
int (*suspend)(struct ath11k_base *ab);
|
||||
int (*resume)(struct ath11k_base *ab);
|
||||
int (*map_service_to_pipe)(struct ath11k_base *ab, u16 service_id,
|
||||
|
@ -67,12 +67,18 @@ static inline void ath11k_hif_irq_disable(struct ath11k_base *ab)
|
|||
|
||||
static inline int ath11k_hif_power_up(struct ath11k_base *ab)
|
||||
{
|
||||
if (!ab->hif.ops->power_up)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ab->hif.ops->power_up(ab);
|
||||
}
|
||||
|
||||
static inline void ath11k_hif_power_down(struct ath11k_base *ab)
|
||||
static inline void ath11k_hif_power_down(struct ath11k_base *ab, bool is_suspend)
|
||||
{
|
||||
ab->hif.ops->power_down(ab);
|
||||
if (!ab->hif.ops->power_down)
|
||||
return;
|
||||
|
||||
ab->hif.ops->power_down(ab, is_suspend);
|
||||
}
|
||||
|
||||
static inline int ath11k_hif_suspend(struct ath11k_base *ab)
|
||||
|
|
|
@ -58,7 +58,7 @@ static void ath11k_hw_wcn6855_tx_mesh_enable(struct ath11k_base *ab,
|
|||
static void ath11k_init_wmi_config_qca6390(struct ath11k_base *ab,
|
||||
struct target_resource_config *config)
|
||||
{
|
||||
config->num_vdevs = 4;
|
||||
config->num_vdevs = ab->hw_params.num_vdevs;
|
||||
config->num_peers = 16;
|
||||
config->num_tids = 32;
|
||||
|
||||
|
|
|
@ -226,6 +226,7 @@ struct ath11k_hw_params {
|
|||
u32 tx_ring_size;
|
||||
bool smp2p_wow_exit;
|
||||
bool support_fw_mac_sequence;
|
||||
bool support_dual_stations;
|
||||
};
|
||||
|
||||
struct ath11k_hw_ops {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH11K_MAC_H
|
||||
|
@ -176,4 +176,7 @@ int ath11k_mac_wait_tx_complete(struct ath11k *ar);
|
|||
int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif,
|
||||
enum wmi_sta_keepalive_method method,
|
||||
u32 interval);
|
||||
void ath11k_mac_fill_reg_tpc_info(struct ath11k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_chanctx_conf *ctx);
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/msi.h>
|
||||
|
@ -20,35 +20,7 @@
|
|||
#define MHI_TIMEOUT_DEFAULT_MS 20000
|
||||
#define RDDM_DUMP_SIZE 0x420000
|
||||
|
||||
static struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
|
||||
{
|
||||
.num = 0,
|
||||
.name = "LOOPBACK",
|
||||
.num_elements = 32,
|
||||
.event_ring = 0,
|
||||
.dir = DMA_TO_DEVICE,
|
||||
.ee_mask = 0x4,
|
||||
.pollcfg = 0,
|
||||
.doorbell = MHI_DB_BRST_DISABLE,
|
||||
.lpm_notify = false,
|
||||
.offload_channel = false,
|
||||
.doorbell_mode_switch = false,
|
||||
.auto_queue = false,
|
||||
},
|
||||
{
|
||||
.num = 1,
|
||||
.name = "LOOPBACK",
|
||||
.num_elements = 32,
|
||||
.event_ring = 0,
|
||||
.dir = DMA_FROM_DEVICE,
|
||||
.ee_mask = 0x4,
|
||||
.pollcfg = 0,
|
||||
.doorbell = MHI_DB_BRST_DISABLE,
|
||||
.lpm_notify = false,
|
||||
.offload_channel = false,
|
||||
.doorbell_mode_switch = false,
|
||||
.auto_queue = false,
|
||||
},
|
||||
static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
|
||||
{
|
||||
.num = 20,
|
||||
.name = "IPCR",
|
||||
|
@ -102,46 +74,18 @@ static struct mhi_event_config ath11k_mhi_events_qca6390[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mhi_controller_config ath11k_mhi_config_qca6390 = {
|
||||
static const struct mhi_controller_config ath11k_mhi_config_qca6390 = {
|
||||
.max_channels = 128,
|
||||
.timeout_ms = 2000,
|
||||
.use_bounce_buf = false,
|
||||
.buf_len = 0,
|
||||
.buf_len = 8192,
|
||||
.num_channels = ARRAY_SIZE(ath11k_mhi_channels_qca6390),
|
||||
.ch_cfg = ath11k_mhi_channels_qca6390,
|
||||
.num_events = ARRAY_SIZE(ath11k_mhi_events_qca6390),
|
||||
.event_cfg = ath11k_mhi_events_qca6390,
|
||||
};
|
||||
|
||||
static struct mhi_channel_config ath11k_mhi_channels_qcn9074[] = {
|
||||
{
|
||||
.num = 0,
|
||||
.name = "LOOPBACK",
|
||||
.num_elements = 32,
|
||||
.event_ring = 1,
|
||||
.dir = DMA_TO_DEVICE,
|
||||
.ee_mask = 0x14,
|
||||
.pollcfg = 0,
|
||||
.doorbell = MHI_DB_BRST_DISABLE,
|
||||
.lpm_notify = false,
|
||||
.offload_channel = false,
|
||||
.doorbell_mode_switch = false,
|
||||
.auto_queue = false,
|
||||
},
|
||||
{
|
||||
.num = 1,
|
||||
.name = "LOOPBACK",
|
||||
.num_elements = 32,
|
||||
.event_ring = 1,
|
||||
.dir = DMA_FROM_DEVICE,
|
||||
.ee_mask = 0x14,
|
||||
.pollcfg = 0,
|
||||
.doorbell = MHI_DB_BRST_DISABLE,
|
||||
.lpm_notify = false,
|
||||
.offload_channel = false,
|
||||
.doorbell_mode_switch = false,
|
||||
.auto_queue = false,
|
||||
},
|
||||
static const struct mhi_channel_config ath11k_mhi_channels_qcn9074[] = {
|
||||
{
|
||||
.num = 20,
|
||||
.name = "IPCR",
|
||||
|
@ -195,7 +139,7 @@ static struct mhi_event_config ath11k_mhi_events_qcn9074[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mhi_controller_config ath11k_mhi_config_qcn9074 = {
|
||||
static const struct mhi_controller_config ath11k_mhi_config_qcn9074 = {
|
||||
.max_channels = 30,
|
||||
.timeout_ms = 10000,
|
||||
.use_bounce_buf = false,
|
||||
|
@ -384,7 +328,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
|
|||
{
|
||||
struct ath11k_base *ab = ab_pci->ab;
|
||||
struct mhi_controller *mhi_ctrl;
|
||||
struct mhi_controller_config *ath11k_mhi_config;
|
||||
const struct mhi_controller_config *ath11k_mhi_config;
|
||||
int ret;
|
||||
|
||||
mhi_ctrl = mhi_alloc_controller();
|
||||
|
@ -423,7 +367,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
|
|||
goto free_controller;
|
||||
} else {
|
||||
mhi_ctrl->iova_start = 0;
|
||||
mhi_ctrl->iova_stop = 0xFFFFFFFF;
|
||||
mhi_ctrl->iova_stop = ab_pci->dma_mask;
|
||||
}
|
||||
|
||||
mhi_ctrl->rddm_size = RDDM_DUMP_SIZE;
|
||||
|
@ -443,6 +387,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
|
|||
case ATH11K_HW_QCA6390_HW20:
|
||||
case ATH11K_HW_WCN6855_HW20:
|
||||
case ATH11K_HW_WCN6855_HW21:
|
||||
case ATH11K_HW_QCA2066_HW21:
|
||||
ath11k_mhi_config = &ath11k_mhi_config_qca6390;
|
||||
break;
|
||||
default:
|
||||
|
@ -497,9 +442,17 @@ int ath11k_mhi_start(struct ath11k_pci *ab_pci)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ath11k_mhi_stop(struct ath11k_pci *ab_pci)
|
||||
void ath11k_mhi_stop(struct ath11k_pci *ab_pci, bool is_suspend)
|
||||
{
|
||||
mhi_power_down(ab_pci->mhi_ctrl, true);
|
||||
/* During suspend we need to use mhi_power_down_keep_dev()
|
||||
* workaround, otherwise ath11k_core_resume() will timeout
|
||||
* during resume.
|
||||
*/
|
||||
if (is_suspend)
|
||||
mhi_power_down_keep_dev(ab_pci->mhi_ctrl, true);
|
||||
else
|
||||
mhi_power_down(ab_pci->mhi_ctrl, true);
|
||||
|
||||
mhi_unprepare_after_power_down(ab_pci->mhi_ctrl);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef _ATH11K_MHI_H
|
||||
#define _ATH11K_MHI_H
|
||||
|
@ -18,7 +18,7 @@
|
|||
#define MHICTRL_RESET_MASK 0x2
|
||||
|
||||
int ath11k_mhi_start(struct ath11k_pci *ar_pci);
|
||||
void ath11k_mhi_stop(struct ath11k_pci *ar_pci);
|
||||
void ath11k_mhi_stop(struct ath11k_pci *ar_pci, bool is_suspend);
|
||||
int ath11k_mhi_register(struct ath11k_pci *ar_pci);
|
||||
void ath11k_mhi_unregister(struct ath11k_pci *ar_pci);
|
||||
void ath11k_mhi_set_mhictrl_reset(struct ath11k_base *ab);
|
||||
|
@ -26,5 +26,4 @@ void ath11k_mhi_clear_vector(struct ath11k_base *ab);
|
|||
|
||||
int ath11k_mhi_suspend(struct ath11k_pci *ar_pci);
|
||||
int ath11k_mhi_resume(struct ath11k_pci *ar_pci);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -18,7 +18,8 @@
|
|||
#include "qmi.h"
|
||||
|
||||
#define ATH11K_PCI_BAR_NUM 0
|
||||
#define ATH11K_PCI_DMA_MASK 32
|
||||
#define ATH11K_PCI_DMA_MASK 36
|
||||
#define ATH11K_PCI_COHERENT_DMA_MASK 32
|
||||
|
||||
#define TCSR_SOC_HW_VERSION 0x0224
|
||||
#define TCSR_SOC_HW_VERSION_MAJOR_MASK GENMASK(11, 8)
|
||||
|
@ -28,6 +29,8 @@
|
|||
#define QCN9074_DEVICE_ID 0x1104
|
||||
#define WCN6855_DEVICE_ID 0x1103
|
||||
|
||||
#define TCSR_SOC_HW_SUB_VER 0x1910010
|
||||
|
||||
static const struct pci_device_id ath11k_pci_id_table[] = {
|
||||
{ PCI_VDEVICE(QCOM, QCA6390_DEVICE_ID) },
|
||||
{ PCI_VDEVICE(QCOM, WCN6855_DEVICE_ID) },
|
||||
|
@ -526,14 +529,24 @@ static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
|
|||
goto disable_device;
|
||||
}
|
||||
|
||||
ret = dma_set_mask_and_coherent(&pdev->dev,
|
||||
DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
|
||||
ret = dma_set_mask(&pdev->dev,
|
||||
DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to set pci dma mask to %d: %d\n",
|
||||
ATH11K_PCI_DMA_MASK, ret);
|
||||
goto release_region;
|
||||
}
|
||||
|
||||
ab_pci->dma_mask = DMA_BIT_MASK(ATH11K_PCI_DMA_MASK);
|
||||
|
||||
ret = dma_set_coherent_mask(&pdev->dev,
|
||||
DMA_BIT_MASK(ATH11K_PCI_COHERENT_DMA_MASK));
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to set pci coherent dma mask to %d: %d\n",
|
||||
ATH11K_PCI_COHERENT_DMA_MASK, ret);
|
||||
goto release_region;
|
||||
}
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
ab->mem_len = pci_resource_len(pdev, ATH11K_PCI_BAR_NUM);
|
||||
|
@ -625,7 +638,7 @@ static int ath11k_pci_power_up(struct ath11k_base *ab)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_pci_power_down(struct ath11k_base *ab)
|
||||
static void ath11k_pci_power_down(struct ath11k_base *ab, bool is_suspend)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
|
||||
|
@ -636,7 +649,7 @@ static void ath11k_pci_power_down(struct ath11k_base *ab)
|
|||
|
||||
ath11k_pci_msi_disable(ab_pci);
|
||||
|
||||
ath11k_mhi_stop(ab_pci);
|
||||
ath11k_mhi_stop(ab_pci, is_suspend);
|
||||
clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags);
|
||||
ath11k_pci_sw_reset(ab_pci->ab, false);
|
||||
}
|
||||
|
@ -731,8 +744,8 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
|
|||
struct ath11k_base *ab;
|
||||
struct ath11k_pci *ab_pci;
|
||||
u32 soc_hw_version_major, soc_hw_version_minor, addr;
|
||||
const struct ath11k_pci_ops *pci_ops;
|
||||
int ret;
|
||||
u32 sub_version;
|
||||
|
||||
ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI);
|
||||
|
||||
|
@ -777,6 +790,12 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
|
|||
|
||||
switch (pci_dev->device) {
|
||||
case QCA6390_DEVICE_ID:
|
||||
ret = ath11k_pcic_register_pci_ops(ab, &ath11k_pci_ops_qca6390);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to register PCI ops: %d\n", ret);
|
||||
goto err_pci_free_region;
|
||||
}
|
||||
|
||||
ath11k_pci_read_hw_version(ab, &soc_hw_version_major,
|
||||
&soc_hw_version_minor);
|
||||
switch (soc_hw_version_major) {
|
||||
|
@ -790,13 +809,21 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
|
|||
goto err_pci_free_region;
|
||||
}
|
||||
|
||||
pci_ops = &ath11k_pci_ops_qca6390;
|
||||
break;
|
||||
case QCN9074_DEVICE_ID:
|
||||
pci_ops = &ath11k_pci_ops_qcn9074;
|
||||
ret = ath11k_pcic_register_pci_ops(ab, &ath11k_pci_ops_qcn9074);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to register PCI ops: %d\n", ret);
|
||||
goto err_pci_free_region;
|
||||
}
|
||||
ab->hw_rev = ATH11K_HW_QCN9074_HW10;
|
||||
break;
|
||||
case WCN6855_DEVICE_ID:
|
||||
ret = ath11k_pcic_register_pci_ops(ab, &ath11k_pci_ops_qca6390);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to register PCI ops: %d\n", ret);
|
||||
goto err_pci_free_region;
|
||||
}
|
||||
ab->id.bdf_search = ATH11K_BDF_SEARCH_BUS_AND_BOARD;
|
||||
ath11k_pci_read_hw_version(ab, &soc_hw_version_major,
|
||||
&soc_hw_version_minor);
|
||||
|
@ -809,7 +836,19 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
|
|||
break;
|
||||
case 0x10:
|
||||
case 0x11:
|
||||
ab->hw_rev = ATH11K_HW_WCN6855_HW21;
|
||||
sub_version = ath11k_pcic_read32(ab, TCSR_SOC_HW_SUB_VER);
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI, "sub_version 0x%x\n",
|
||||
sub_version);
|
||||
switch (sub_version) {
|
||||
case 0x1019A0E1:
|
||||
case 0x1019B0E1:
|
||||
case 0x1019C0E1:
|
||||
case 0x1019D0E1:
|
||||
ab->hw_rev = ATH11K_HW_QCA2066_HW21;
|
||||
break;
|
||||
default:
|
||||
ab->hw_rev = ATH11K_HW_WCN6855_HW21;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto unsupported_wcn6855_soc;
|
||||
|
@ -823,7 +862,6 @@ unsupported_wcn6855_soc:
|
|||
goto err_pci_free_region;
|
||||
}
|
||||
|
||||
pci_ops = &ath11k_pci_ops_qca6390;
|
||||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev, "Unknown PCI device found: 0x%x\n",
|
||||
|
@ -832,12 +870,6 @@ unsupported_wcn6855_soc:
|
|||
goto err_pci_free_region;
|
||||
}
|
||||
|
||||
ret = ath11k_pcic_register_pci_ops(ab, pci_ops);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to register PCI ops: %d\n", ret);
|
||||
goto err_pci_free_region;
|
||||
}
|
||||
|
||||
ret = ath11k_pcic_init_msi_config(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to init msi config: %d\n", ret);
|
||||
|
@ -938,7 +970,7 @@ static void ath11k_pci_remove(struct pci_dev *pdev)
|
|||
ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
|
||||
|
||||
if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
|
||||
ath11k_pci_power_down(ab);
|
||||
ath11k_pci_power_down(ab, false);
|
||||
ath11k_debugfs_soc_destroy(ab);
|
||||
ath11k_qmi_deinit_service(ab);
|
||||
goto qmi_fail;
|
||||
|
@ -966,7 +998,7 @@ static void ath11k_pci_shutdown(struct pci_dev *pdev)
|
|||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
|
||||
ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
|
||||
ath11k_pci_power_down(ab);
|
||||
ath11k_pci_power_down(ab, false);
|
||||
}
|
||||
|
||||
static __maybe_unused int ath11k_pci_pm_suspend(struct device *dev)
|
||||
|
@ -1003,9 +1035,39 @@ static __maybe_unused int ath11k_pci_pm_resume(struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops,
|
||||
ath11k_pci_pm_suspend,
|
||||
ath11k_pci_pm_resume);
|
||||
static __maybe_unused int ath11k_pci_pm_suspend_late(struct device *dev)
|
||||
{
|
||||
struct ath11k_base *ab = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = ath11k_core_suspend_late(ab);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to late suspend core: %d\n", ret);
|
||||
|
||||
/* Similar to ath11k_pci_pm_suspend(), we return success here
|
||||
* even error happens, to allow system suspend/hibernation survive.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused int ath11k_pci_pm_resume_early(struct device *dev)
|
||||
{
|
||||
struct ath11k_base *ab = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = ath11k_core_resume_early(ab);
|
||||
if (ret)
|
||||
ath11k_warn(ab, "failed to early resume core: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops __maybe_unused ath11k_pci_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(ath11k_pci_pm_suspend,
|
||||
ath11k_pci_pm_resume)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(ath11k_pci_pm_suspend_late,
|
||||
ath11k_pci_pm_resume_early)
|
||||
};
|
||||
|
||||
static struct pci_driver ath11k_pci_driver = {
|
||||
.name = "ath11k_pci",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2022,2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef _ATH11K_PCI_H
|
||||
#define _ATH11K_PCI_H
|
||||
|
@ -72,6 +72,7 @@ struct ath11k_pci {
|
|||
/* enum ath11k_pci_flags */
|
||||
unsigned long flags;
|
||||
u16 link_ctl;
|
||||
u64 dma_mask;
|
||||
};
|
||||
|
||||
static inline struct ath11k_pci *ath11k_pci_priv(struct ath11k_base *ab)
|
||||
|
|
|
@ -115,6 +115,17 @@ static const struct ath11k_msi_config ath11k_msi_config[] = {
|
|||
},
|
||||
.hw_rev = ATH11K_HW_WCN6750_HW10,
|
||||
},
|
||||
{
|
||||
.total_vectors = 32,
|
||||
.total_users = 4,
|
||||
.users = (struct ath11k_msi_user[]) {
|
||||
{ .name = "MHI", .num_vectors = 3, .base_vector = 0 },
|
||||
{ .name = "CE", .num_vectors = 10, .base_vector = 3 },
|
||||
{ .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
|
||||
{ .name = "DP", .num_vectors = 18, .base_vector = 14 },
|
||||
},
|
||||
.hw_rev = ATH11K_HW_QCA2066_HW21,
|
||||
},
|
||||
};
|
||||
|
||||
int ath11k_pcic_init_msi_config(struct ath11k_base *ab)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/elf.h>
|
||||
|
@ -2877,7 +2877,7 @@ int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab)
|
|||
}
|
||||
|
||||
/* reset the firmware */
|
||||
ath11k_hif_power_down(ab);
|
||||
ath11k_hif_power_down(ab, false);
|
||||
ath11k_hif_power_up(ab);
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI, "exit wait for cold boot done\n");
|
||||
return 0;
|
||||
|
@ -3249,7 +3249,8 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)
|
|||
case ATH11K_QMI_EVENT_FW_INIT_DONE:
|
||||
clear_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
|
||||
if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) {
|
||||
ath11k_hal_dump_srng_stats(ab);
|
||||
if (ab->is_reset)
|
||||
ath11k_hal_dump_srng_stats(ab);
|
||||
queue_work(ab->workqueue, &ab->restart_work);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,6 @@ ath11k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
|
|||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct wmi_init_country_params init_country_param;
|
||||
struct wmi_set_current_country_params set_current_param = {};
|
||||
struct ath11k *ar = hw->priv;
|
||||
int ret;
|
||||
|
||||
|
@ -83,9 +82,8 @@ ath11k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
|
|||
* reg info
|
||||
*/
|
||||
if (ar->ab->hw_params.current_cc_support) {
|
||||
memcpy(&set_current_param.alpha2, request->alpha2, 2);
|
||||
memcpy(&ar->alpha2, &set_current_param.alpha2, 2);
|
||||
ret = ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param);
|
||||
memcpy(&ar->alpha2, request->alpha2, 2);
|
||||
ret = ath11k_reg_set_cc(ar);
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab,
|
||||
"failed set current country code: %d\n", ret);
|
||||
|
@ -425,6 +423,11 @@ static void ath11k_reg_intersect_rules(struct ieee80211_reg_rule *rule1,
|
|||
/* Use the flags of both the rules */
|
||||
new_rule->flags = rule1->flags | rule2->flags;
|
||||
|
||||
if ((rule1->flags & NL80211_RRF_PSD) && (rule2->flags & NL80211_RRF_PSD))
|
||||
new_rule->psd = min_t(s8, rule1->psd, rule2->psd);
|
||||
else
|
||||
new_rule->flags &= ~NL80211_RRF_PSD;
|
||||
|
||||
/* To be safe, lts use the max cac timeout of both rules */
|
||||
new_rule->dfs_cac_ms = max_t(u32, rule1->dfs_cac_ms,
|
||||
rule2->dfs_cac_ms);
|
||||
|
@ -527,13 +530,14 @@ ath11k_reg_adjust_bw(u16 start_freq, u16 end_freq, u16 max_bw)
|
|||
static void
|
||||
ath11k_reg_update_rule(struct ieee80211_reg_rule *reg_rule, u32 start_freq,
|
||||
u32 end_freq, u32 bw, u32 ant_gain, u32 reg_pwr,
|
||||
u32 reg_flags)
|
||||
s8 psd, u32 reg_flags)
|
||||
{
|
||||
reg_rule->freq_range.start_freq_khz = MHZ_TO_KHZ(start_freq);
|
||||
reg_rule->freq_range.end_freq_khz = MHZ_TO_KHZ(end_freq);
|
||||
reg_rule->freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw);
|
||||
reg_rule->power_rule.max_antenna_gain = DBI_TO_MBI(ant_gain);
|
||||
reg_rule->power_rule.max_eirp = DBM_TO_MBM(reg_pwr);
|
||||
reg_rule->psd = psd;
|
||||
reg_rule->flags = reg_flags;
|
||||
}
|
||||
|
||||
|
@ -563,7 +567,7 @@ ath11k_reg_update_weather_radar_band(struct ath11k_base *ab,
|
|||
reg_rule->start_freq,
|
||||
ETSI_WEATHER_RADAR_BAND_LOW, bw,
|
||||
reg_rule->ant_gain, reg_rule->reg_power,
|
||||
flags);
|
||||
reg_rule->psd_eirp, flags);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_REG,
|
||||
"\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n",
|
||||
|
@ -584,7 +588,7 @@ ath11k_reg_update_weather_radar_band(struct ath11k_base *ab,
|
|||
|
||||
ath11k_reg_update_rule(regd->reg_rules + i, start_freq,
|
||||
end_freq, bw, reg_rule->ant_gain,
|
||||
reg_rule->reg_power, flags);
|
||||
reg_rule->reg_power, reg_rule->psd_eirp, flags);
|
||||
|
||||
regd->reg_rules[i].dfs_cac_ms = ETSI_WEATHER_RADAR_BAND_CAC_TIMEOUT;
|
||||
|
||||
|
@ -605,7 +609,7 @@ ath11k_reg_update_weather_radar_band(struct ath11k_base *ab,
|
|||
ETSI_WEATHER_RADAR_BAND_HIGH,
|
||||
reg_rule->end_freq, bw,
|
||||
reg_rule->ant_gain, reg_rule->reg_power,
|
||||
flags);
|
||||
reg_rule->psd_eirp, flags);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_REG,
|
||||
"\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n",
|
||||
|
@ -618,25 +622,68 @@ ath11k_reg_update_weather_radar_band(struct ath11k_base *ab,
|
|||
*rule_idx = i;
|
||||
}
|
||||
|
||||
enum wmi_reg_6ghz_ap_type
|
||||
ath11k_reg_ap_pwr_convert(enum ieee80211_ap_reg_power power_type)
|
||||
{
|
||||
switch (power_type) {
|
||||
case IEEE80211_REG_LPI_AP:
|
||||
return WMI_REG_INDOOR_AP;
|
||||
case IEEE80211_REG_SP_AP:
|
||||
return WMI_REG_STANDARD_POWER_AP;
|
||||
case IEEE80211_REG_VLP_AP:
|
||||
return WMI_REG_VERY_LOW_POWER_AP;
|
||||
default:
|
||||
return WMI_REG_MAX_AP_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
struct ieee80211_regdomain *
|
||||
ath11k_reg_build_regd(struct ath11k_base *ab,
|
||||
struct cur_regulatory_info *reg_info, bool intersect)
|
||||
struct cur_regulatory_info *reg_info, bool intersect,
|
||||
enum wmi_vdev_type vdev_type,
|
||||
enum ieee80211_ap_reg_power power_type)
|
||||
{
|
||||
struct ieee80211_regdomain *tmp_regd, *default_regd, *new_regd = NULL;
|
||||
struct cur_reg_rule *reg_rule;
|
||||
struct cur_reg_rule *reg_rule, *reg_rule_6ghz;
|
||||
u8 i = 0, j = 0, k = 0;
|
||||
u8 num_rules;
|
||||
u16 max_bw;
|
||||
u32 flags;
|
||||
u32 flags, reg_6ghz_number, max_bw_6ghz;
|
||||
char alpha2[3];
|
||||
|
||||
num_rules = reg_info->num_5ghz_reg_rules + reg_info->num_2ghz_reg_rules;
|
||||
|
||||
/* FIXME: Currently taking reg rules for 6 GHz only from Indoor AP mode list.
|
||||
* This can be updated after complete 6 GHz regulatory support is added.
|
||||
*/
|
||||
if (reg_info->is_ext_reg_event)
|
||||
num_rules += reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP];
|
||||
if (reg_info->is_ext_reg_event) {
|
||||
if (vdev_type == WMI_VDEV_TYPE_STA) {
|
||||
enum wmi_reg_6ghz_ap_type ap_type;
|
||||
|
||||
ap_type = ath11k_reg_ap_pwr_convert(power_type);
|
||||
|
||||
if (ap_type == WMI_REG_MAX_AP_TYPE)
|
||||
ap_type = WMI_REG_INDOOR_AP;
|
||||
|
||||
reg_6ghz_number = reg_info->num_6ghz_rules_client
|
||||
[ap_type][WMI_REG_DEFAULT_CLIENT];
|
||||
|
||||
if (reg_6ghz_number == 0) {
|
||||
ap_type = WMI_REG_INDOOR_AP;
|
||||
reg_6ghz_number = reg_info->num_6ghz_rules_client
|
||||
[ap_type][WMI_REG_DEFAULT_CLIENT];
|
||||
}
|
||||
|
||||
reg_rule_6ghz = reg_info->reg_rules_6ghz_client_ptr
|
||||
[ap_type][WMI_REG_DEFAULT_CLIENT];
|
||||
max_bw_6ghz = reg_info->max_bw_6ghz_client
|
||||
[ap_type][WMI_REG_DEFAULT_CLIENT];
|
||||
} else {
|
||||
reg_6ghz_number = reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP];
|
||||
reg_rule_6ghz =
|
||||
reg_info->reg_rules_6ghz_ap_ptr[WMI_REG_INDOOR_AP];
|
||||
max_bw_6ghz = reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP];
|
||||
}
|
||||
|
||||
num_rules += reg_6ghz_number;
|
||||
}
|
||||
|
||||
if (!num_rules)
|
||||
goto ret;
|
||||
|
@ -683,14 +730,13 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
|
|||
* per other BW rule flags we pass from here
|
||||
*/
|
||||
flags = NL80211_RRF_AUTO_BW;
|
||||
} else if (reg_info->is_ext_reg_event &&
|
||||
reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP] &&
|
||||
(k < reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP])) {
|
||||
reg_rule = reg_info->reg_rules_6ghz_ap_ptr[WMI_REG_INDOOR_AP] +
|
||||
k++;
|
||||
max_bw = min_t(u16, reg_rule->max_bw,
|
||||
reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP]);
|
||||
} else if (reg_info->is_ext_reg_event && reg_6ghz_number &&
|
||||
k < reg_6ghz_number) {
|
||||
reg_rule = reg_rule_6ghz + k++;
|
||||
max_bw = min_t(u16, reg_rule->max_bw, max_bw_6ghz);
|
||||
flags = NL80211_RRF_AUTO_BW;
|
||||
if (reg_rule->psd_flag)
|
||||
flags |= NL80211_RRF_PSD;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -702,7 +748,7 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
|
|||
reg_rule->start_freq,
|
||||
reg_rule->end_freq, max_bw,
|
||||
reg_rule->ant_gain, reg_rule->reg_power,
|
||||
flags);
|
||||
reg_rule->psd_eirp, flags);
|
||||
|
||||
/* Update dfs cac timeout if the dfs domain is ETSI and the
|
||||
* new rule covers weather radar band.
|
||||
|
@ -758,6 +804,159 @@ ret:
|
|||
return new_regd;
|
||||
}
|
||||
|
||||
static bool ath11k_reg_is_world_alpha(char *alpha)
|
||||
{
|
||||
if (alpha[0] == '0' && alpha[1] == '0')
|
||||
return true;
|
||||
|
||||
if (alpha[0] == 'n' && alpha[1] == 'a')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum wmi_vdev_type ath11k_reg_get_ar_vdev_type(struct ath11k *ar)
|
||||
{
|
||||
struct ath11k_vif *arvif;
|
||||
|
||||
/* Currently each struct ath11k maps to one struct ieee80211_hw/wiphy
|
||||
* and one struct ieee80211_regdomain, so it could only store one group
|
||||
* reg rules. It means multi-interface concurrency in the same ath11k is
|
||||
* not support for the regdomain. So get the vdev type of the first entry
|
||||
* now. After concurrency support for the regdomain, this should change.
|
||||
*/
|
||||
arvif = list_first_entry_or_null(&ar->arvifs, struct ath11k_vif, list);
|
||||
if (arvif)
|
||||
return arvif->vdev_type;
|
||||
|
||||
return WMI_VDEV_TYPE_UNSPEC;
|
||||
}
|
||||
|
||||
int ath11k_reg_handle_chan_list(struct ath11k_base *ab,
|
||||
struct cur_regulatory_info *reg_info,
|
||||
enum ieee80211_ap_reg_power power_type)
|
||||
{
|
||||
struct ieee80211_regdomain *regd;
|
||||
bool intersect = false;
|
||||
int pdev_idx;
|
||||
struct ath11k *ar;
|
||||
enum wmi_vdev_type vdev_type;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "event reg handle chan list");
|
||||
|
||||
if (reg_info->status_code != REG_SET_CC_STATUS_PASS) {
|
||||
/* In case of failure to set the requested ctry,
|
||||
* fw retains the current regd. We print a failure info
|
||||
* and return from here.
|
||||
*/
|
||||
ath11k_warn(ab, "Failed to set the requested Country regulatory setting\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdev_idx = reg_info->phy_id;
|
||||
|
||||
/* Avoid default reg rule updates sent during FW recovery if
|
||||
* it is already available
|
||||
*/
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags) &&
|
||||
ab->default_regd[pdev_idx]) {
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
goto retfail;
|
||||
}
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
if (pdev_idx >= ab->num_radios) {
|
||||
/* Process the event for phy0 only if single_pdev_only
|
||||
* is true. If pdev_idx is valid but not 0, discard the
|
||||
* event. Otherwise, it goes to fallback. In either case
|
||||
* ath11k_reg_reset_info() needs to be called to avoid
|
||||
* memory leak issue.
|
||||
*/
|
||||
ath11k_reg_reset_info(reg_info);
|
||||
|
||||
if (ab->hw_params.single_pdev_only &&
|
||||
pdev_idx < ab->hw_params.num_rxmda_per_pdev)
|
||||
return 0;
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
/* Avoid multiple overwrites to default regd, during core
|
||||
* stop-start after mac registration.
|
||||
*/
|
||||
if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] &&
|
||||
!memcmp((char *)ab->default_regd[pdev_idx]->alpha2,
|
||||
(char *)reg_info->alpha2, 2))
|
||||
goto retfail;
|
||||
|
||||
/* Intersect new rules with default regd if a new country setting was
|
||||
* requested, i.e a default regd was already set during initialization
|
||||
* and the regd coming from this event has a valid country info.
|
||||
*/
|
||||
if (ab->default_regd[pdev_idx] &&
|
||||
!ath11k_reg_is_world_alpha((char *)
|
||||
ab->default_regd[pdev_idx]->alpha2) &&
|
||||
!ath11k_reg_is_world_alpha((char *)reg_info->alpha2))
|
||||
intersect = true;
|
||||
|
||||
ar = ab->pdevs[pdev_idx].ar;
|
||||
vdev_type = ath11k_reg_get_ar_vdev_type(ar);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"wmi handle chan list power type %d vdev type %d intersect %d\n",
|
||||
power_type, vdev_type, intersect);
|
||||
|
||||
regd = ath11k_reg_build_regd(ab, reg_info, intersect, vdev_type, power_type);
|
||||
if (!regd) {
|
||||
ath11k_warn(ab, "failed to build regd from reg_info\n");
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
if (power_type == IEEE80211_REG_UNSET_AP) {
|
||||
ath11k_reg_reset_info(&ab->reg_info_store[pdev_idx]);
|
||||
ab->reg_info_store[pdev_idx] = *reg_info;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
if (ab->default_regd[pdev_idx]) {
|
||||
/* The initial rules from FW after WMI Init is to build
|
||||
* the default regd. From then on, any rules updated for
|
||||
* the pdev could be due to user reg changes.
|
||||
* Free previously built regd before assigning the newly
|
||||
* generated regd to ar. NULL pointer handling will be
|
||||
* taken care by kfree itself.
|
||||
*/
|
||||
ar = ab->pdevs[pdev_idx].ar;
|
||||
kfree(ab->new_regd[pdev_idx]);
|
||||
ab->new_regd[pdev_idx] = regd;
|
||||
queue_work(ab->workqueue, &ar->regd_update_work);
|
||||
} else {
|
||||
/* This regd would be applied during mac registration and is
|
||||
* held constant throughout for regd intersection purpose
|
||||
*/
|
||||
ab->default_regd[pdev_idx] = regd;
|
||||
}
|
||||
ab->dfs_region = reg_info->dfs_region;
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
fallback:
|
||||
/* Fallback to older reg (by sending previous country setting
|
||||
* again if fw has succeeded and we failed to process here.
|
||||
* The Regdomain should be uniform across driver and fw. Since the
|
||||
* FW has processed the command and sent a success status, we expect
|
||||
* this function to succeed as well. If it doesn't, CTRY needs to be
|
||||
* reverted at the fw and the old SCAN_CHAN_LIST cmd needs to be sent.
|
||||
*/
|
||||
/* TODO: This is rare, but still should also be handled */
|
||||
WARN_ON(1);
|
||||
|
||||
retfail:
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void ath11k_regd_update_work(struct work_struct *work)
|
||||
{
|
||||
struct ath11k *ar = container_of(work, struct ath11k,
|
||||
|
@ -781,12 +980,46 @@ void ath11k_reg_init(struct ath11k *ar)
|
|||
ar->hw->wiphy->reg_notifier = ath11k_reg_notifier;
|
||||
}
|
||||
|
||||
void ath11k_reg_reset_info(struct cur_regulatory_info *reg_info)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!reg_info)
|
||||
return;
|
||||
|
||||
kfree(reg_info->reg_rules_2ghz_ptr);
|
||||
kfree(reg_info->reg_rules_5ghz_ptr);
|
||||
|
||||
for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) {
|
||||
kfree(reg_info->reg_rules_6ghz_ap_ptr[i]);
|
||||
|
||||
for (j = 0; j < WMI_REG_MAX_CLIENT_TYPE; j++)
|
||||
kfree(reg_info->reg_rules_6ghz_client_ptr[i][j]);
|
||||
}
|
||||
|
||||
memset(reg_info, 0, sizeof(*reg_info));
|
||||
}
|
||||
|
||||
void ath11k_reg_free(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++)
|
||||
ath11k_reg_reset_info(&ab->reg_info_store[i]);
|
||||
|
||||
kfree(ab->reg_info_store);
|
||||
ab->reg_info_store = NULL;
|
||||
|
||||
for (i = 0; i < ab->hw_params.max_radios; i++) {
|
||||
kfree(ab->default_regd[i]);
|
||||
kfree(ab->new_regd[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int ath11k_reg_set_cc(struct ath11k *ar)
|
||||
{
|
||||
struct wmi_set_current_country_params set_current_param = {};
|
||||
|
||||
memcpy(&set_current_param.alpha2, ar->alpha2, 2);
|
||||
return ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH11K_REG_H
|
||||
|
@ -30,11 +30,20 @@ enum ath11k_dfs_region {
|
|||
|
||||
/* ATH11K Regulatory API's */
|
||||
void ath11k_reg_init(struct ath11k *ar);
|
||||
void ath11k_reg_reset_info(struct cur_regulatory_info *reg_info);
|
||||
void ath11k_reg_free(struct ath11k_base *ab);
|
||||
void ath11k_regd_update_work(struct work_struct *work);
|
||||
struct ieee80211_regdomain *
|
||||
ath11k_reg_build_regd(struct ath11k_base *ab,
|
||||
struct cur_regulatory_info *reg_info, bool intersect);
|
||||
struct cur_regulatory_info *reg_info, bool intersect,
|
||||
enum wmi_vdev_type vdev_type,
|
||||
enum ieee80211_ap_reg_power power_type);
|
||||
int ath11k_regd_update(struct ath11k *ar);
|
||||
int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait);
|
||||
enum wmi_reg_6ghz_ap_type
|
||||
ath11k_reg_ap_pwr_convert(enum ieee80211_ap_reg_power power_type);
|
||||
int ath11k_reg_handle_chan_list(struct ath11k_base *ab,
|
||||
struct cur_regulatory_info *reg_info,
|
||||
enum ieee80211_ap_reg_power power_type);
|
||||
int ath11k_reg_set_cc(struct ath11k *ar);
|
||||
#endif
|
||||
|
|
|
@ -198,7 +198,7 @@ static void ath11k_tm_wmi_event_segmented(struct ath11k_base *ab, u32 cmd_id,
|
|||
u16 length;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse ftm event tlv: %d\n", ret);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
|
@ -163,6 +163,9 @@ int ath11k_thermal_register(struct ath11k_base *ab)
|
|||
struct ath11k_pdev *pdev;
|
||||
int i, ret;
|
||||
|
||||
if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
ar = pdev->ar;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/ctype.h>
|
||||
|
@ -238,8 +238,8 @@ static int ath11k_wmi_tlv_parse(struct ath11k_base *ar, const void **tb,
|
|||
(void *)tb);
|
||||
}
|
||||
|
||||
const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr,
|
||||
size_t len, gfp_t gfp)
|
||||
const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab,
|
||||
struct sk_buff *skb, gfp_t gfp)
|
||||
{
|
||||
const void **tb;
|
||||
int ret;
|
||||
|
@ -248,7 +248,7 @@ const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr,
|
|||
if (!tb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = ath11k_wmi_tlv_parse(ab, tb, ptr, len);
|
||||
ret = ath11k_wmi_tlv_parse(ab, tb, skb->data, skb->len);
|
||||
if (ret) {
|
||||
kfree(tb);
|
||||
return ERR_PTR(ret);
|
||||
|
@ -2098,7 +2098,7 @@ void ath11k_wmi_start_scan_init(struct ath11k *ar,
|
|||
WMI_SCAN_EVENT_BSS_CHANNEL |
|
||||
WMI_SCAN_EVENT_FOREIGN_CHAN |
|
||||
WMI_SCAN_EVENT_DEQUEUED;
|
||||
arg->scan_flags |= WMI_SCAN_CHAN_STAT_EVENT;
|
||||
arg->scan_f_chan_stat_evnt = 1;
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE,
|
||||
ar->ab->wmi_ab.svc_map))
|
||||
|
@ -2379,6 +2379,70 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_send_vdev_set_tpc_power(struct ath11k *ar,
|
||||
u32 vdev_id,
|
||||
struct ath11k_reg_tpc_power_info *param)
|
||||
{
|
||||
struct ath11k_pdev_wmi *wmi = ar->wmi;
|
||||
struct wmi_vdev_set_tpc_power_cmd *cmd;
|
||||
struct wmi_vdev_ch_power_info *ch;
|
||||
struct sk_buff *skb;
|
||||
struct wmi_tlv *tlv;
|
||||
u8 *ptr;
|
||||
int i, ret, len, array_len;
|
||||
|
||||
array_len = sizeof(*ch) * param->num_pwr_levels;
|
||||
len = sizeof(*cmd) + TLV_HDR_SIZE + array_len;
|
||||
|
||||
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
ptr = skb->data;
|
||||
|
||||
cmd = (struct wmi_vdev_set_tpc_power_cmd *)ptr;
|
||||
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_VDEV_SET_TPC_POWER_CMD) |
|
||||
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
cmd->vdev_id = vdev_id;
|
||||
cmd->psd_power = param->is_psd_power;
|
||||
cmd->eirp_power = param->eirp_power;
|
||||
cmd->power_type_6ghz = param->ap_power_type;
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
"tpc vdev id %d is psd power %d eirp power %d 6 ghz power type %d\n",
|
||||
vdev_id, param->is_psd_power, param->eirp_power, param->ap_power_type);
|
||||
|
||||
ptr += sizeof(*cmd);
|
||||
tlv = (struct wmi_tlv *)ptr;
|
||||
tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) |
|
||||
FIELD_PREP(WMI_TLV_LEN, array_len);
|
||||
|
||||
ptr += TLV_HDR_SIZE;
|
||||
ch = (struct wmi_vdev_ch_power_info *)ptr;
|
||||
|
||||
for (i = 0; i < param->num_pwr_levels; i++, ch++) {
|
||||
ch->tlv_header = FIELD_PREP(WMI_TLV_TAG,
|
||||
WMI_TAG_VDEV_CH_POWER_INFO) |
|
||||
FIELD_PREP(WMI_TLV_LEN,
|
||||
sizeof(*ch) - TLV_HDR_SIZE);
|
||||
|
||||
ch->chan_cfreq = param->chan_power_info[i].chan_cfreq;
|
||||
ch->tx_power = param->chan_power_info[i].tx_power;
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tpc chan freq %d TX power %d\n",
|
||||
ch->chan_cfreq, ch->tx_power);
|
||||
}
|
||||
|
||||
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_VDEV_SET_TPC_POWER_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to send WMI_VDEV_SET_TPC_POWER_CMDID\n");
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath11k_wmi_send_scan_stop_cmd(struct ath11k *ar,
|
||||
struct scan_cancel_param *param)
|
||||
{
|
||||
|
@ -3930,7 +3994,7 @@ ath11k_wmi_obss_color_collision_event(struct ath11k_base *ab, struct sk_buff *sk
|
|||
struct ath11k_vif *arvif;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -3956,8 +4020,7 @@ ath11k_wmi_obss_color_collision_event(struct ath11k_base *ab, struct sk_buff *sk
|
|||
|
||||
switch (ev->evt_type) {
|
||||
case WMI_BSS_COLOR_COLLISION_DETECTION:
|
||||
ieee80211_obss_color_collision_notify(arvif->vif, ev->obss_color_bitmap,
|
||||
GFP_KERNEL);
|
||||
ieee80211_obss_color_collision_notify(arvif->vif, ev->obss_color_bitmap);
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"OBSS color collision detected vdev:%d, event:%d, bitmap:%08llx\n",
|
||||
ev->vdev_id, ev->evt_type, ev->obss_color_bitmap);
|
||||
|
@ -4749,6 +4812,14 @@ static int ath11k_wmi_tlv_ext_soc_hal_reg_caps_parse(struct ath11k_base *soc,
|
|||
soc->pdevs[0].pdev_id = 0;
|
||||
}
|
||||
|
||||
if (!soc->reg_info_store) {
|
||||
soc->reg_info_store = kcalloc(soc->num_radios,
|
||||
sizeof(*soc->reg_info_store),
|
||||
GFP_ATOMIC);
|
||||
if (!soc->reg_info_store)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4786,6 +4857,7 @@ static void ath11k_wmi_free_dbring_caps(struct ath11k_base *ab)
|
|||
{
|
||||
kfree(ab->db_caps);
|
||||
ab->db_caps = NULL;
|
||||
ab->num_db_cap = 0;
|
||||
}
|
||||
|
||||
static int ath11k_wmi_tlv_dma_ring_caps(struct ath11k_base *ab,
|
||||
|
@ -5003,7 +5075,7 @@ static int ath11k_pull_vdev_start_resp_tlv(struct ath11k_base *ab, struct sk_buf
|
|||
const struct wmi_vdev_start_resp_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5028,6 +5100,7 @@ static int ath11k_pull_vdev_start_resp_tlv(struct ath11k_base *ab, struct sk_buf
|
|||
vdev_rsp->mac_id = ev->mac_id;
|
||||
vdev_rsp->cfgd_tx_streams = ev->cfgd_tx_streams;
|
||||
vdev_rsp->cfgd_rx_streams = ev->cfgd_rx_streams;
|
||||
vdev_rsp->max_allowed_tx_power = ev->max_allowed_tx_power;
|
||||
|
||||
kfree(tb);
|
||||
return 0;
|
||||
|
@ -5102,7 +5175,7 @@ static int ath11k_pull_reg_chan_list_update_ev(struct ath11k_base *ab,
|
|||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "processing regulatory channel list\n");
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5278,7 +5351,7 @@ static int ath11k_pull_reg_chan_list_ext_update_ev(struct ath11k_base *ab,
|
|||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "processing regulatory ext channel list\n");
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5634,7 +5707,7 @@ static int ath11k_pull_peer_del_resp_ev(struct ath11k_base *ab, struct sk_buff *
|
|||
const struct wmi_peer_delete_resp_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5666,7 +5739,7 @@ static int ath11k_pull_vdev_del_resp_ev(struct ath11k_base *ab,
|
|||
const struct wmi_vdev_delete_resp_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5686,15 +5759,15 @@ static int ath11k_pull_vdev_del_resp_ev(struct ath11k_base *ab,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_pull_bcn_tx_status_ev(struct ath11k_base *ab, void *evt_buf,
|
||||
u32 len, u32 *vdev_id,
|
||||
u32 *tx_status)
|
||||
static int ath11k_pull_bcn_tx_status_ev(struct ath11k_base *ab,
|
||||
struct sk_buff *skb,
|
||||
u32 *vdev_id, u32 *tx_status)
|
||||
{
|
||||
const void **tb;
|
||||
const struct wmi_bcn_tx_status_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, evt_buf, len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5722,7 +5795,7 @@ static int ath11k_pull_vdev_stopped_param_tlv(struct ath11k_base *ab, struct sk_
|
|||
const struct wmi_vdev_stopped_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5876,7 +5949,7 @@ static int ath11k_pull_mgmt_tx_compl_param_tlv(struct ath11k_base *ab,
|
|||
const struct wmi_mgmt_tx_compl_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -6052,7 +6125,7 @@ static int ath11k_pull_scan_ev(struct ath11k_base *ab, struct sk_buff *skb,
|
|||
const struct wmi_scan_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -6085,7 +6158,7 @@ static int ath11k_pull_peer_sta_kickout_ev(struct ath11k_base *ab, struct sk_buf
|
|||
const struct wmi_peer_sta_kickout_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -6112,7 +6185,7 @@ static int ath11k_pull_roam_ev(struct ath11k_base *ab, struct sk_buff *skb,
|
|||
const struct wmi_roam_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -6153,14 +6226,14 @@ exit:
|
|||
return idx;
|
||||
}
|
||||
|
||||
static int ath11k_pull_chan_info_ev(struct ath11k_base *ab, u8 *evt_buf,
|
||||
u32 len, struct wmi_chan_info_event *ch_info_ev)
|
||||
static int ath11k_pull_chan_info_ev(struct ath11k_base *ab, struct sk_buff *skb,
|
||||
struct wmi_chan_info_event *ch_info_ev)
|
||||
{
|
||||
const void **tb;
|
||||
const struct wmi_chan_info_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, evt_buf, len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -6199,7 +6272,7 @@ ath11k_pull_pdev_bss_chan_info_ev(struct ath11k_base *ab, struct sk_buff *skb,
|
|||
const struct wmi_pdev_bss_chan_info_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -6239,7 +6312,7 @@ ath11k_pull_vdev_install_key_compl_ev(struct ath11k_base *ab, struct sk_buff *sk
|
|||
const struct wmi_vdev_install_key_compl_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -6270,7 +6343,7 @@ static int ath11k_pull_peer_assoc_conf_ev(struct ath11k_base *ab, struct sk_buff
|
|||
const struct wmi_peer_assoc_conf_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -6995,7 +7068,7 @@ static int ath11k_reg_11d_new_cc_event(struct ath11k_base *ab, struct sk_buff *s
|
|||
const void **tb;
|
||||
int ret, i;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -7060,32 +7133,15 @@ static void ath11k_wmi_htc_tx_complete(struct ath11k_base *ab,
|
|||
wake_up(&wmi->tx_ce_desc_wq);
|
||||
}
|
||||
|
||||
static bool ath11k_reg_is_world_alpha(char *alpha)
|
||||
{
|
||||
if (alpha[0] == '0' && alpha[1] == '0')
|
||||
return true;
|
||||
|
||||
if (alpha[0] == 'n' && alpha[1] == 'a')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ath11k_reg_chan_list_event(struct ath11k_base *ab,
|
||||
struct sk_buff *skb,
|
||||
static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *skb,
|
||||
enum wmi_reg_chan_list_cmd_type id)
|
||||
{
|
||||
struct cur_regulatory_info *reg_info = NULL;
|
||||
struct ieee80211_regdomain *regd = NULL;
|
||||
bool intersect = false;
|
||||
int ret = 0, pdev_idx, i, j;
|
||||
struct ath11k *ar;
|
||||
struct cur_regulatory_info *reg_info;
|
||||
int ret;
|
||||
|
||||
reg_info = kzalloc(sizeof(*reg_info), GFP_ATOMIC);
|
||||
if (!reg_info) {
|
||||
ret = -ENOMEM;
|
||||
goto fallback;
|
||||
}
|
||||
if (!reg_info)
|
||||
return -ENOMEM;
|
||||
|
||||
if (id == WMI_REG_CHAN_LIST_CC_ID)
|
||||
ret = ath11k_pull_reg_chan_list_update_ev(ab, skb, reg_info);
|
||||
|
@ -7093,118 +7149,22 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab,
|
|||
ret = ath11k_pull_reg_chan_list_ext_update_ev(ab, skb, reg_info);
|
||||
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to extract regulatory info from received event\n");
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "event reg chan list id %d", id);
|
||||
|
||||
if (reg_info->status_code != REG_SET_CC_STATUS_PASS) {
|
||||
/* In case of failure to set the requested ctry,
|
||||
* fw retains the current regd. We print a failure info
|
||||
* and return from here.
|
||||
*/
|
||||
ath11k_warn(ab, "Failed to set the requested Country regulatory setting\n");
|
||||
ath11k_warn(ab, "failed to extract regulatory info\n");
|
||||
goto mem_free;
|
||||
}
|
||||
|
||||
pdev_idx = reg_info->phy_id;
|
||||
|
||||
/* Avoid default reg rule updates sent during FW recovery if
|
||||
* it is already available
|
||||
*/
|
||||
spin_lock(&ab->base_lock);
|
||||
if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags) &&
|
||||
ab->default_regd[pdev_idx]) {
|
||||
spin_unlock(&ab->base_lock);
|
||||
ret = ath11k_reg_handle_chan_list(ab, reg_info, IEEE80211_REG_UNSET_AP);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to process regulatory info %d\n", ret);
|
||||
goto mem_free;
|
||||
}
|
||||
spin_unlock(&ab->base_lock);
|
||||
|
||||
if (pdev_idx >= ab->num_radios) {
|
||||
/* Process the event for phy0 only if single_pdev_only
|
||||
* is true. If pdev_idx is valid but not 0, discard the
|
||||
* event. Otherwise, it goes to fallback.
|
||||
*/
|
||||
if (ab->hw_params.single_pdev_only &&
|
||||
pdev_idx < ab->hw_params.num_rxmda_per_pdev)
|
||||
goto mem_free;
|
||||
else
|
||||
goto fallback;
|
||||
}
|
||||
kfree(reg_info);
|
||||
return 0;
|
||||
|
||||
/* Avoid multiple overwrites to default regd, during core
|
||||
* stop-start after mac registration.
|
||||
*/
|
||||
if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] &&
|
||||
!memcmp((char *)ab->default_regd[pdev_idx]->alpha2,
|
||||
(char *)reg_info->alpha2, 2))
|
||||
goto mem_free;
|
||||
|
||||
/* Intersect new rules with default regd if a new country setting was
|
||||
* requested, i.e a default regd was already set during initialization
|
||||
* and the regd coming from this event has a valid country info.
|
||||
*/
|
||||
if (ab->default_regd[pdev_idx] &&
|
||||
!ath11k_reg_is_world_alpha((char *)
|
||||
ab->default_regd[pdev_idx]->alpha2) &&
|
||||
!ath11k_reg_is_world_alpha((char *)reg_info->alpha2))
|
||||
intersect = true;
|
||||
|
||||
regd = ath11k_reg_build_regd(ab, reg_info, intersect);
|
||||
if (!regd) {
|
||||
ath11k_warn(ab, "failed to build regd from reg_info\n");
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
spin_lock(&ab->base_lock);
|
||||
if (ab->default_regd[pdev_idx]) {
|
||||
/* The initial rules from FW after WMI Init is to build
|
||||
* the default regd. From then on, any rules updated for
|
||||
* the pdev could be due to user reg changes.
|
||||
* Free previously built regd before assigning the newly
|
||||
* generated regd to ar. NULL pointer handling will be
|
||||
* taken care by kfree itself.
|
||||
*/
|
||||
ar = ab->pdevs[pdev_idx].ar;
|
||||
kfree(ab->new_regd[pdev_idx]);
|
||||
ab->new_regd[pdev_idx] = regd;
|
||||
queue_work(ab->workqueue, &ar->regd_update_work);
|
||||
} else {
|
||||
/* This regd would be applied during mac registration and is
|
||||
* held constant throughout for regd intersection purpose
|
||||
*/
|
||||
ab->default_regd[pdev_idx] = regd;
|
||||
}
|
||||
ab->dfs_region = reg_info->dfs_region;
|
||||
spin_unlock(&ab->base_lock);
|
||||
|
||||
goto mem_free;
|
||||
|
||||
fallback:
|
||||
/* Fallback to older reg (by sending previous country setting
|
||||
* again if fw has succeeded and we failed to process here.
|
||||
* The Regdomain should be uniform across driver and fw. Since the
|
||||
* FW has processed the command and sent a success status, we expect
|
||||
* this function to succeed as well. If it doesn't, CTRY needs to be
|
||||
* reverted at the fw and the old SCAN_CHAN_LIST cmd needs to be sent.
|
||||
*/
|
||||
/* TODO: This is rare, but still should also be handled */
|
||||
WARN_ON(1);
|
||||
mem_free:
|
||||
if (reg_info) {
|
||||
kfree(reg_info->reg_rules_2ghz_ptr);
|
||||
kfree(reg_info->reg_rules_5ghz_ptr);
|
||||
if (reg_info->is_ext_reg_event) {
|
||||
for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++)
|
||||
kfree(reg_info->reg_rules_6ghz_ap_ptr[i]);
|
||||
|
||||
for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++)
|
||||
for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++)
|
||||
kfree(reg_info->reg_rules_6ghz_client_ptr[j][i]);
|
||||
}
|
||||
kfree(reg_info);
|
||||
}
|
||||
ath11k_reg_reset_info(reg_info);
|
||||
kfree(reg_info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -7362,7 +7322,7 @@ static void ath11k_vdev_start_resp_event(struct ath11k_base *ab, struct sk_buff
|
|||
}
|
||||
|
||||
ar->last_wmi_vdev_start_status = 0;
|
||||
|
||||
ar->max_allowed_tx_power = vdev_start_resp.max_allowed_tx_power;
|
||||
status = vdev_start_resp.status;
|
||||
|
||||
if (WARN_ON_ONCE(status)) {
|
||||
|
@ -7384,8 +7344,7 @@ static void ath11k_bcn_tx_status_event(struct ath11k_base *ab, struct sk_buff *s
|
|||
struct ath11k_vif *arvif;
|
||||
u32 vdev_id, tx_status;
|
||||
|
||||
if (ath11k_pull_bcn_tx_status_ev(ab, skb->data, skb->len,
|
||||
&vdev_id, &tx_status) != 0) {
|
||||
if (ath11k_pull_bcn_tx_status_ev(ab, skb, &vdev_id, &tx_status) != 0) {
|
||||
ath11k_warn(ab, "failed to extract bcn tx status");
|
||||
return;
|
||||
}
|
||||
|
@ -7416,7 +7375,7 @@ static void ath11k_wmi_event_peer_sta_ps_state_chg(struct ath11k_base *ab,
|
|||
enum ath11k_wmi_peer_ps_state peer_previous_ps_state;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -7884,7 +7843,7 @@ static void ath11k_chan_info_event(struct ath11k_base *ab, struct sk_buff *skb)
|
|||
/* HW channel counters frequency value in hertz */
|
||||
u32 cc_freq_hz = ab->cc_freq_hz;
|
||||
|
||||
if (ath11k_pull_chan_info_ev(ab, skb->data, skb->len, &ch_info_ev) != 0) {
|
||||
if (ath11k_pull_chan_info_ev(ab, skb, &ch_info_ev) != 0) {
|
||||
ath11k_warn(ab, "failed to extract chan info event");
|
||||
return;
|
||||
}
|
||||
|
@ -8216,7 +8175,7 @@ static void ath11k_pdev_ctl_failsafe_check_event(struct ath11k_base *ab,
|
|||
const struct wmi_pdev_ctl_failsafe_chk_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -8267,7 +8226,7 @@ ath11k_wmi_process_csa_switch_count_event(struct ath11k_base *ab,
|
|||
}
|
||||
|
||||
if (arvif->is_up && arvif->vif->bss_conf.csa_active)
|
||||
ieee80211_csa_finish(arvif->vif);
|
||||
ieee80211_csa_finish(arvif->vif, 0);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
@ -8281,7 +8240,7 @@ ath11k_wmi_pdev_csa_switch_count_status_event(struct ath11k_base *ab,
|
|||
const u32 *vdev_ids;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -8315,7 +8274,7 @@ ath11k_wmi_pdev_dfs_radar_detected_event(struct ath11k_base *ab, struct sk_buff
|
|||
struct ath11k *ar;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -8369,7 +8328,7 @@ ath11k_wmi_pdev_temperature_event(struct ath11k_base *ab,
|
|||
const struct wmi_pdev_temperature_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -8409,7 +8368,7 @@ static void ath11k_fils_discovery_event(struct ath11k_base *ab,
|
|||
const struct wmi_fils_discovery_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab,
|
||||
|
@ -8441,7 +8400,7 @@ static void ath11k_probe_resp_tx_status_event(struct ath11k_base *ab,
|
|||
const struct wmi_probe_resp_tx_status_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab,
|
||||
|
@ -8567,7 +8526,7 @@ static void ath11k_wmi_twt_add_dialog_event(struct ath11k_base *ab,
|
|||
const struct wmi_twt_add_dialog_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab,
|
||||
|
@ -8604,7 +8563,7 @@ static void ath11k_wmi_gtk_offload_status_event(struct ath11k_base *ab,
|
|||
u64 replay_ctr;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -9793,3 +9752,9 @@ int ath11k_wmi_sta_keepalive(struct ath11k *ar,
|
|||
|
||||
return ath11k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
|
||||
}
|
||||
|
||||
bool ath11k_wmi_supports_6ghz_cc_ext(struct ath11k *ar)
|
||||
{
|
||||
return test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT,
|
||||
ar->ab->wmi_ab.svc_map) && ar->supports_6ghz;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ struct ath11k;
|
|||
struct ath11k_fw_stats;
|
||||
struct ath11k_fw_dbglog;
|
||||
struct ath11k_vif;
|
||||
struct ath11k_reg_tpc_power_info;
|
||||
|
||||
#define PSOC_HOST_MAX_NUM_SS (8)
|
||||
|
||||
|
@ -327,6 +328,22 @@ enum wmi_tlv_cmd_id {
|
|||
WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID,
|
||||
WMI_VDEV_ENCRYPT_DECRYPT_DATA_REQ_CMDID,
|
||||
WMI_VDEV_ADD_MAC_ADDR_TO_RX_FILTER_CMDID,
|
||||
WMI_VDEV_SET_ARP_STAT_CMDID,
|
||||
WMI_VDEV_GET_ARP_STAT_CMDID,
|
||||
WMI_VDEV_GET_TX_POWER_CMDID,
|
||||
WMI_VDEV_LIMIT_OFFCHAN_CMDID,
|
||||
WMI_VDEV_SET_CUSTOM_SW_RETRY_TH_CMDID,
|
||||
WMI_VDEV_CHAINMASK_CONFIG_CMDID,
|
||||
WMI_VDEV_GET_BCN_RECEPTION_STATS_CMDID,
|
||||
WMI_VDEV_GET_MWS_COEX_INFO_CMDID,
|
||||
WMI_VDEV_DELETE_ALL_PEER_CMDID,
|
||||
WMI_VDEV_BSS_MAX_IDLE_TIME_CMDID,
|
||||
WMI_VDEV_AUDIO_SYNC_TRIGGER_CMDID,
|
||||
WMI_VDEV_AUDIO_SYNC_QTIMER_CMDID,
|
||||
WMI_VDEV_SET_PCL_CMDID,
|
||||
WMI_VDEV_GET_BIG_DATA_CMDID,
|
||||
WMI_VDEV_GET_BIG_DATA_P2_CMDID,
|
||||
WMI_VDEV_SET_TPC_POWER_CMDID,
|
||||
WMI_PEER_CREATE_CMDID = WMI_TLV_CMD(WMI_GRP_PEER),
|
||||
WMI_PEER_DELETE_CMDID,
|
||||
WMI_PEER_FLUSH_TIDS_CMDID,
|
||||
|
@ -1880,6 +1897,8 @@ enum wmi_tlv_tag {
|
|||
WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD,
|
||||
WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9,
|
||||
WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT,
|
||||
WMI_TAG_VDEV_SET_TPC_POWER_CMD = 0x3B5,
|
||||
WMI_TAG_VDEV_CH_POWER_INFO,
|
||||
WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD = 0x3D8,
|
||||
WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD,
|
||||
WMI_TAG_MAX
|
||||
|
@ -2114,6 +2133,7 @@ enum wmi_tlv_service {
|
|||
/* The second 128 bits */
|
||||
WMI_MAX_EXT_SERVICE = 256,
|
||||
WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL = 265,
|
||||
WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT = 280,
|
||||
WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
|
||||
WMI_TLV_SERVICE_BIOS_SAR_SUPPORT = 326,
|
||||
WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN = 357,
|
||||
|
@ -3168,6 +3188,41 @@ struct wlan_ssid {
|
|||
u8 ssid[WLAN_SSID_MAX_LEN];
|
||||
};
|
||||
|
||||
struct wmi_vdev_ch_power_info {
|
||||
u32 tlv_header;
|
||||
|
||||
/* Channel center frequency (MHz) */
|
||||
u32 chan_cfreq;
|
||||
|
||||
/* Unit: dBm, either PSD/EIRP power for this frequency or
|
||||
* incremental for non-PSD BW
|
||||
*/
|
||||
u32 tx_power;
|
||||
} __packed;
|
||||
|
||||
struct wmi_vdev_set_tpc_power_cmd {
|
||||
u32 tlv_header;
|
||||
u32 vdev_id;
|
||||
|
||||
/* Value: 0 or 1, is PSD power or not */
|
||||
u32 psd_power;
|
||||
|
||||
/* Maximum EIRP power (dBm units), valid only if power is PSD */
|
||||
u32 eirp_power;
|
||||
|
||||
/* Type: WMI_6GHZ_REG_TYPE, used for halphy CTL lookup */
|
||||
u32 power_type_6ghz;
|
||||
|
||||
/* This fixed_param TLV is followed by the below TLVs:
|
||||
* num_pwr_levels of wmi_vdev_ch_power_info
|
||||
* For PSD power, it is the PSD/EIRP power of the frequency (20 MHz chunks).
|
||||
* For non-PSD power, the power values are for 20, 40, and till
|
||||
* BSS BW power levels.
|
||||
* The num_pwr_levels will be checked by sw how many elements present
|
||||
* in the variable-length array.
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
#define WMI_IE_BITMAP_SIZE 8
|
||||
|
||||
/* prefix used by scan requestor ids on the host */
|
||||
|
@ -3308,24 +3363,19 @@ struct scan_req_params {
|
|||
u32 vdev_id;
|
||||
u32 pdev_id;
|
||||
enum wmi_scan_priority scan_priority;
|
||||
union {
|
||||
struct {
|
||||
u32 scan_ev_started:1,
|
||||
scan_ev_completed:1,
|
||||
scan_ev_bss_chan:1,
|
||||
scan_ev_foreign_chan:1,
|
||||
scan_ev_dequeued:1,
|
||||
scan_ev_preempted:1,
|
||||
scan_ev_start_failed:1,
|
||||
scan_ev_restarted:1,
|
||||
scan_ev_foreign_chn_exit:1,
|
||||
scan_ev_invalid:1,
|
||||
scan_ev_gpio_timeout:1,
|
||||
scan_ev_suspended:1,
|
||||
scan_ev_resumed:1;
|
||||
};
|
||||
u32 scan_events;
|
||||
};
|
||||
u32 scan_ev_started:1,
|
||||
scan_ev_completed:1,
|
||||
scan_ev_bss_chan:1,
|
||||
scan_ev_foreign_chan:1,
|
||||
scan_ev_dequeued:1,
|
||||
scan_ev_preempted:1,
|
||||
scan_ev_start_failed:1,
|
||||
scan_ev_restarted:1,
|
||||
scan_ev_foreign_chn_exit:1,
|
||||
scan_ev_invalid:1,
|
||||
scan_ev_gpio_timeout:1,
|
||||
scan_ev_suspended:1,
|
||||
scan_ev_resumed:1;
|
||||
u32 scan_ctrl_flags_ext;
|
||||
u32 dwell_time_active;
|
||||
u32 dwell_time_active_2g;
|
||||
|
@ -3339,36 +3389,31 @@ struct scan_req_params {
|
|||
u32 idle_time;
|
||||
u32 max_scan_time;
|
||||
u32 probe_delay;
|
||||
union {
|
||||
struct {
|
||||
u32 scan_f_passive:1,
|
||||
scan_f_bcast_probe:1,
|
||||
scan_f_cck_rates:1,
|
||||
scan_f_ofdm_rates:1,
|
||||
scan_f_chan_stat_evnt:1,
|
||||
scan_f_filter_prb_req:1,
|
||||
scan_f_bypass_dfs_chn:1,
|
||||
scan_f_continue_on_err:1,
|
||||
scan_f_offchan_mgmt_tx:1,
|
||||
scan_f_offchan_data_tx:1,
|
||||
scan_f_promisc_mode:1,
|
||||
scan_f_capture_phy_err:1,
|
||||
scan_f_strict_passive_pch:1,
|
||||
scan_f_half_rate:1,
|
||||
scan_f_quarter_rate:1,
|
||||
scan_f_force_active_dfs_chn:1,
|
||||
scan_f_add_tpc_ie_in_probe:1,
|
||||
scan_f_add_ds_ie_in_probe:1,
|
||||
scan_f_add_spoofed_mac_in_probe:1,
|
||||
scan_f_add_rand_seq_in_probe:1,
|
||||
scan_f_en_ie_whitelist_in_probe:1,
|
||||
scan_f_forced:1,
|
||||
scan_f_2ghz:1,
|
||||
scan_f_5ghz:1,
|
||||
scan_f_80mhz:1;
|
||||
};
|
||||
u32 scan_flags;
|
||||
};
|
||||
u32 scan_f_passive:1,
|
||||
scan_f_bcast_probe:1,
|
||||
scan_f_cck_rates:1,
|
||||
scan_f_ofdm_rates:1,
|
||||
scan_f_chan_stat_evnt:1,
|
||||
scan_f_filter_prb_req:1,
|
||||
scan_f_bypass_dfs_chn:1,
|
||||
scan_f_continue_on_err:1,
|
||||
scan_f_offchan_mgmt_tx:1,
|
||||
scan_f_offchan_data_tx:1,
|
||||
scan_f_promisc_mode:1,
|
||||
scan_f_capture_phy_err:1,
|
||||
scan_f_strict_passive_pch:1,
|
||||
scan_f_half_rate:1,
|
||||
scan_f_quarter_rate:1,
|
||||
scan_f_force_active_dfs_chn:1,
|
||||
scan_f_add_tpc_ie_in_probe:1,
|
||||
scan_f_add_ds_ie_in_probe:1,
|
||||
scan_f_add_spoofed_mac_in_probe:1,
|
||||
scan_f_add_rand_seq_in_probe:1,
|
||||
scan_f_en_ie_whitelist_in_probe:1,
|
||||
scan_f_forced:1,
|
||||
scan_f_2ghz:1,
|
||||
scan_f_5ghz:1,
|
||||
scan_f_80mhz:1;
|
||||
enum scan_dwelltime_adaptive_mode adaptive_dwell_time_mode;
|
||||
u32 burst_duration;
|
||||
u32 num_chan;
|
||||
|
@ -4119,6 +4164,7 @@ struct wmi_vdev_start_resp_event {
|
|||
};
|
||||
u32 cfgd_tx_streams;
|
||||
u32 cfgd_rx_streams;
|
||||
s32 max_allowed_tx_power;
|
||||
} __packed;
|
||||
|
||||
/* VDEV start response status codes */
|
||||
|
@ -4951,6 +4997,7 @@ struct ath11k_targ_cap {
|
|||
};
|
||||
|
||||
enum wmi_vdev_type {
|
||||
WMI_VDEV_TYPE_UNSPEC = 0,
|
||||
WMI_VDEV_TYPE_AP = 1,
|
||||
WMI_VDEV_TYPE_STA = 2,
|
||||
WMI_VDEV_TYPE_IBSS = 3,
|
||||
|
@ -6295,8 +6342,8 @@ enum wmi_sta_keepalive_method {
|
|||
#define WMI_STA_KEEPALIVE_INTERVAL_DEFAULT 30
|
||||
#define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0
|
||||
|
||||
const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr,
|
||||
size_t len, gfp_t gfp);
|
||||
const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab,
|
||||
struct sk_buff *skb, gfp_t gfp);
|
||||
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);
|
||||
|
@ -6479,5 +6526,9 @@ int ath11k_wmi_pdev_set_bios_sar_table_param(struct ath11k *ar, const u8 *sar_va
|
|||
int ath11k_wmi_pdev_set_bios_geo_table_param(struct ath11k *ar);
|
||||
int ath11k_wmi_sta_keepalive(struct ath11k *ar,
|
||||
const struct wmi_sta_keepalive_arg *arg);
|
||||
bool ath11k_wmi_supports_6ghz_cc_ext(struct ath11k *ar);
|
||||
int ath11k_wmi_send_vdev_set_tpc_power(struct ath11k *ar,
|
||||
u32 vdev_id,
|
||||
struct ath11k_reg_tpc_power_info *param);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,9 @@ ath12k-y += core.o \
|
|||
hw.o \
|
||||
mhi.o \
|
||||
pci.o \
|
||||
dp_mon.o
|
||||
dp_mon.o \
|
||||
fw.o \
|
||||
p2p.o
|
||||
|
||||
ath12k-$(CONFIG_ATH12K_TRACING) += trace.o
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -14,6 +14,7 @@
|
|||
#include "dp_rx.h"
|
||||
#include "debug.h"
|
||||
#include "hif.h"
|
||||
#include "fw.h"
|
||||
|
||||
unsigned int ath12k_debug_mask;
|
||||
module_param_named(debug_mask, ath12k_debug_mask, uint, 0644);
|
||||
|
@ -104,27 +105,66 @@ int ath12k_core_resume(struct ath12k_base *ab)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath12k_core_create_board_name(struct ath12k_base *ab, char *name,
|
||||
size_t name_len)
|
||||
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 (ab->qmi.target.bdf_ext[0] != '\0')
|
||||
if (with_variant && ab->qmi.target.bdf_ext[0] != '\0')
|
||||
scnprintf(variant, sizeof(variant), ",variant=%s",
|
||||
ab->qmi.target.bdf_ext);
|
||||
|
||||
scnprintf(name, name_len,
|
||||
"bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s",
|
||||
ath12k_bus_str(ab->hif.bus),
|
||||
ab->qmi.target.chip_id,
|
||||
ab->qmi.target.board_id, variant);
|
||||
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->id.subsystem_vendor,
|
||||
ab->id.subsystem_device,
|
||||
ab->qmi.target.chip_id,
|
||||
ab->qmi.target.board_id,
|
||||
variant);
|
||||
break;
|
||||
default:
|
||||
scnprintf(name, name_len,
|
||||
"bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s",
|
||||
ath12k_bus_str(ab->hif.bus),
|
||||
ab->qmi.target.chip_id,
|
||||
ab->qmi.target.board_id, variant);
|
||||
break;
|
||||
}
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot using board name '%s'\n", name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath12k_core_create_board_name(struct ath12k_base *ab, char *name,
|
||||
size_t name_len)
|
||||
{
|
||||
return __ath12k_core_create_board_name(ab, name, name_len, true, false);
|
||||
}
|
||||
|
||||
static int ath12k_core_create_fallback_board_name(struct ath12k_base *ab, char *name,
|
||||
size_t name_len)
|
||||
{
|
||||
return __ath12k_core_create_board_name(ab, name, name_len, false, false);
|
||||
}
|
||||
|
||||
static int ath12k_core_create_bus_type_board_name(struct ath12k_base *ab, char *name,
|
||||
size_t name_len)
|
||||
{
|
||||
return __ath12k_core_create_board_name(ab, name, name_len, false, true);
|
||||
}
|
||||
|
||||
const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab,
|
||||
const char *file)
|
||||
{
|
||||
|
@ -159,7 +199,9 @@ static int ath12k_core_parse_bd_ie_board(struct ath12k_base *ab,
|
|||
struct ath12k_board_data *bd,
|
||||
const void *buf, size_t buf_len,
|
||||
const char *boardname,
|
||||
int bd_ie_type)
|
||||
int ie_id,
|
||||
int name_id,
|
||||
int data_id)
|
||||
{
|
||||
const struct ath12k_fw_ie *hdr;
|
||||
bool name_match_found;
|
||||
|
@ -169,7 +211,7 @@ static int ath12k_core_parse_bd_ie_board(struct ath12k_base *ab,
|
|||
|
||||
name_match_found = false;
|
||||
|
||||
/* go through ATH12K_BD_IE_BOARD_ elements */
|
||||
/* go through ATH12K_BD_IE_BOARD_/ATH12K_BD_IE_REGDB_ elements */
|
||||
while (buf_len > sizeof(struct ath12k_fw_ie)) {
|
||||
hdr = buf;
|
||||
board_ie_id = le32_to_cpu(hdr->id);
|
||||
|
@ -180,48 +222,50 @@ static int ath12k_core_parse_bd_ie_board(struct ath12k_base *ab,
|
|||
buf += sizeof(*hdr);
|
||||
|
||||
if (buf_len < ALIGN(board_ie_len, 4)) {
|
||||
ath12k_err(ab, "invalid ATH12K_BD_IE_BOARD length: %zu < %zu\n",
|
||||
ath12k_err(ab, "invalid %s length: %zu < %zu\n",
|
||||
ath12k_bd_ie_type_str(ie_id),
|
||||
buf_len, ALIGN(board_ie_len, 4));
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (board_ie_id) {
|
||||
case ATH12K_BD_IE_BOARD_NAME:
|
||||
if (board_ie_id == name_id) {
|
||||
ath12k_dbg_dump(ab, ATH12K_DBG_BOOT, "board name", "",
|
||||
board_ie_data, board_ie_len);
|
||||
|
||||
if (board_ie_len != strlen(boardname))
|
||||
break;
|
||||
goto next;
|
||||
|
||||
ret = memcmp(board_ie_data, boardname, strlen(boardname));
|
||||
if (ret)
|
||||
break;
|
||||
goto next;
|
||||
|
||||
name_match_found = true;
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"boot found match for name '%s'",
|
||||
"boot found match %s for name '%s'",
|
||||
ath12k_bd_ie_type_str(ie_id),
|
||||
boardname);
|
||||
break;
|
||||
case ATH12K_BD_IE_BOARD_DATA:
|
||||
} else if (board_ie_id == data_id) {
|
||||
if (!name_match_found)
|
||||
/* no match found */
|
||||
break;
|
||||
goto next;
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"boot found board data for '%s'", boardname);
|
||||
"boot found %s for '%s'",
|
||||
ath12k_bd_ie_type_str(ie_id),
|
||||
boardname);
|
||||
|
||||
bd->data = board_ie_data;
|
||||
bd->len = board_ie_len;
|
||||
|
||||
ret = 0;
|
||||
goto out;
|
||||
default:
|
||||
ath12k_warn(ab, "unknown ATH12K_BD_IE_BOARD found: %d\n",
|
||||
} else {
|
||||
ath12k_warn(ab, "unknown %s id found: %d\n",
|
||||
ath12k_bd_ie_type_str(ie_id),
|
||||
board_ie_id);
|
||||
break;
|
||||
}
|
||||
|
||||
next:
|
||||
/* jump over the padding */
|
||||
board_ie_len = ALIGN(board_ie_len, 4);
|
||||
|
||||
|
@ -238,7 +282,10 @@ out:
|
|||
|
||||
static int ath12k_core_fetch_board_data_api_n(struct ath12k_base *ab,
|
||||
struct ath12k_board_data *bd,
|
||||
const char *boardname)
|
||||
const char *boardname,
|
||||
int ie_id_match,
|
||||
int name_id,
|
||||
int data_id)
|
||||
{
|
||||
size_t len, magic_len;
|
||||
const u8 *data;
|
||||
|
@ -303,22 +350,23 @@ static int ath12k_core_fetch_board_data_api_n(struct ath12k_base *ab,
|
|||
goto err;
|
||||
}
|
||||
|
||||
switch (ie_id) {
|
||||
case ATH12K_BD_IE_BOARD:
|
||||
if (ie_id == ie_id_match) {
|
||||
ret = ath12k_core_parse_bd_ie_board(ab, bd, data,
|
||||
ie_len,
|
||||
boardname,
|
||||
ATH12K_BD_IE_BOARD);
|
||||
ie_id_match,
|
||||
name_id,
|
||||
data_id);
|
||||
if (ret == -ENOENT)
|
||||
/* no match found, continue */
|
||||
break;
|
||||
goto next;
|
||||
else if (ret)
|
||||
/* there was an error, bail out */
|
||||
goto err;
|
||||
/* either found or error, so stop searching */
|
||||
goto out;
|
||||
}
|
||||
|
||||
next:
|
||||
/* jump over the padding */
|
||||
ie_len = ALIGN(ie_len, 4);
|
||||
|
||||
|
@ -328,8 +376,9 @@ static int ath12k_core_fetch_board_data_api_n(struct ath12k_base *ab,
|
|||
|
||||
out:
|
||||
if (!bd->data || !bd->len) {
|
||||
ath12k_err(ab,
|
||||
"failed to fetch board data for %s from %s\n",
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"failed to fetch %s for %s from %s\n",
|
||||
ath12k_bd_ie_type_str(ie_id_match),
|
||||
boardname, filepath);
|
||||
ret = -ENODATA;
|
||||
goto err;
|
||||
|
@ -356,28 +405,56 @@ int ath12k_core_fetch_board_data_api_1(struct ath12k_base *ab,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define BOARD_NAME_SIZE 100
|
||||
#define BOARD_NAME_SIZE 200
|
||||
int ath12k_core_fetch_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd)
|
||||
{
|
||||
char boardname[BOARD_NAME_SIZE];
|
||||
char boardname[BOARD_NAME_SIZE], fallback_boardname[BOARD_NAME_SIZE];
|
||||
char *filename, filepath[100];
|
||||
int bd_api;
|
||||
int ret;
|
||||
|
||||
ret = ath12k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE);
|
||||
filename = ATH12K_BOARD_API2_FILE;
|
||||
|
||||
ret = ath12k_core_create_board_name(ab, boardname, sizeof(boardname));
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to create board name: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bd_api = 2;
|
||||
ret = ath12k_core_fetch_board_data_api_n(ab, bd, boardname);
|
||||
ret = ath12k_core_fetch_board_data_api_n(ab, bd, boardname,
|
||||
ATH12K_BD_IE_BOARD,
|
||||
ATH12K_BD_IE_BOARD_NAME,
|
||||
ATH12K_BD_IE_BOARD_DATA);
|
||||
if (!ret)
|
||||
goto success;
|
||||
|
||||
ret = ath12k_core_create_fallback_board_name(ab, fallback_boardname,
|
||||
sizeof(fallback_boardname));
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to create fallback board name: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath12k_core_fetch_board_data_api_n(ab, bd, fallback_boardname,
|
||||
ATH12K_BD_IE_BOARD,
|
||||
ATH12K_BD_IE_BOARD_NAME,
|
||||
ATH12K_BD_IE_BOARD_DATA);
|
||||
if (!ret)
|
||||
goto success;
|
||||
|
||||
bd_api = 1;
|
||||
ret = ath12k_core_fetch_board_data_api_1(ab, bd, ATH12K_DEFAULT_BOARD_FILE);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to fetch board-2.bin or board.bin from %s\n",
|
||||
ath12k_core_create_firmware_path(ab, filename,
|
||||
filepath, sizeof(filepath));
|
||||
ath12k_err(ab, "failed to fetch board data for %s from %s\n",
|
||||
boardname, filepath);
|
||||
if (memcmp(boardname, fallback_boardname, strlen(boardname)))
|
||||
ath12k_err(ab, "failed to fetch board data for %s from %s\n",
|
||||
fallback_boardname, filepath);
|
||||
|
||||
ath12k_err(ab, "failed to fetch board.bin from %s\n",
|
||||
ab->hw_params->fw.dir);
|
||||
return ret;
|
||||
}
|
||||
|
@ -387,6 +464,79 @@ success:
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ath12k_core_fetch_regdb(struct ath12k_base *ab, struct ath12k_board_data *bd)
|
||||
{
|
||||
char boardname[BOARD_NAME_SIZE], default_boardname[BOARD_NAME_SIZE];
|
||||
int ret;
|
||||
|
||||
ret = ath12k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE);
|
||||
if (ret) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"failed to create board name for regdb: %d", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = ath12k_core_fetch_board_data_api_n(ab, bd, boardname,
|
||||
ATH12K_BD_IE_REGDB,
|
||||
ATH12K_BD_IE_REGDB_NAME,
|
||||
ATH12K_BD_IE_REGDB_DATA);
|
||||
if (!ret)
|
||||
goto exit;
|
||||
|
||||
ret = ath12k_core_create_bus_type_board_name(ab, default_boardname,
|
||||
BOARD_NAME_SIZE);
|
||||
if (ret) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"failed to create default board name for regdb: %d", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = ath12k_core_fetch_board_data_api_n(ab, bd, default_boardname,
|
||||
ATH12K_BD_IE_REGDB,
|
||||
ATH12K_BD_IE_REGDB_NAME,
|
||||
ATH12K_BD_IE_REGDB_DATA);
|
||||
if (!ret)
|
||||
goto exit;
|
||||
|
||||
ret = ath12k_core_fetch_board_data_api_1(ab, bd, ATH12K_REGDB_FILE_NAME);
|
||||
if (ret)
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "failed to fetch %s from %s\n",
|
||||
ATH12K_REGDB_FILE_NAME, ab->hw_params->fw.dir);
|
||||
|
||||
exit:
|
||||
if (!ret)
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "fetched regdb\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 ath12k_core_get_max_station_per_radio(struct ath12k_base *ab)
|
||||
{
|
||||
if (ab->num_radios == 2)
|
||||
return TARGET_NUM_STATIONS_DBS;
|
||||
else if (ab->num_radios == 3)
|
||||
return TARGET_NUM_PEERS_PDEV_DBS_SBS;
|
||||
return TARGET_NUM_STATIONS_SINGLE;
|
||||
}
|
||||
|
||||
u32 ath12k_core_get_max_peers_per_radio(struct ath12k_base *ab)
|
||||
{
|
||||
if (ab->num_radios == 2)
|
||||
return TARGET_NUM_PEERS_PDEV_DBS;
|
||||
else if (ab->num_radios == 3)
|
||||
return TARGET_NUM_PEERS_PDEV_DBS_SBS;
|
||||
return TARGET_NUM_PEERS_PDEV_SINGLE;
|
||||
}
|
||||
|
||||
u32 ath12k_core_get_max_num_tids(struct ath12k_base *ab)
|
||||
{
|
||||
if (ab->num_radios == 2)
|
||||
return TARGET_NUM_TIDS(DBS);
|
||||
else if (ab->num_radios == 3)
|
||||
return TARGET_NUM_TIDS(DBS_SBS);
|
||||
return TARGET_NUM_TIDS(SINGLE);
|
||||
}
|
||||
|
||||
static void ath12k_core_stop(struct ath12k_base *ab)
|
||||
{
|
||||
if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags))
|
||||
|
@ -592,14 +742,14 @@ static int ath12k_core_start(struct ath12k_base *ab,
|
|||
|
||||
ath12k_dp_cc_config(ab);
|
||||
|
||||
ath12k_dp_pdev_pre_alloc(ab);
|
||||
|
||||
ret = ath12k_dp_rx_pdev_reo_setup(ab);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to initialize reo destination rings: %d\n", ret);
|
||||
goto err_mac_destroy;
|
||||
}
|
||||
|
||||
ath12k_dp_hal_rx_desc_init(ab);
|
||||
|
||||
ret = ath12k_wmi_cmd_init(ab);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to send wmi init cmd: %d\n", ret);
|
||||
|
@ -759,20 +909,30 @@ static void ath12k_rfkill_work(struct work_struct *work)
|
|||
{
|
||||
struct ath12k_base *ab = container_of(work, struct ath12k_base, rfkill_work);
|
||||
struct ath12k *ar;
|
||||
struct ath12k_hw *ah;
|
||||
struct ieee80211_hw *hw;
|
||||
bool rfkill_radio_on;
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
rfkill_radio_on = ab->rfkill_radio_on;
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
ar = ab->pdevs[i].ar;
|
||||
if (!ar)
|
||||
for (i = 0; i < ab->num_hw; i++) {
|
||||
ah = ab->ah[i];
|
||||
if (!ah)
|
||||
continue;
|
||||
|
||||
ath12k_mac_rfkill_enable_radio(ar, rfkill_radio_on);
|
||||
wiphy_rfkill_set_hw_state(ar->hw->wiphy, !rfkill_radio_on);
|
||||
for (j = 0; j < ah->num_radio; j++) {
|
||||
ar = &ah->radio[j];
|
||||
if (!ar)
|
||||
continue;
|
||||
|
||||
ath12k_mac_rfkill_enable_radio(ar, rfkill_radio_on);
|
||||
}
|
||||
|
||||
hw = ah->hw;
|
||||
wiphy_rfkill_set_hw_state(hw->wiphy, !rfkill_radio_on);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -801,6 +961,7 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
|
|||
{
|
||||
struct ath12k *ar;
|
||||
struct ath12k_pdev *pdev;
|
||||
struct ath12k_hw *ah;
|
||||
int i;
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
|
@ -810,16 +971,24 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
|
|||
if (ab->is_reset)
|
||||
set_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags);
|
||||
|
||||
for (i = 0; i < ab->num_hw; i++) {
|
||||
if (!ab->ah[i])
|
||||
continue;
|
||||
|
||||
ah = ab->ah[i];
|
||||
ieee80211_stop_queues(ah->hw);
|
||||
}
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
ar = pdev->ar;
|
||||
if (!ar || ar->state == ATH12K_STATE_OFF)
|
||||
continue;
|
||||
|
||||
ieee80211_stop_queues(ar->hw);
|
||||
ath12k_mac_drain_tx(ar);
|
||||
complete(&ar->scan.started);
|
||||
complete(&ar->scan.completed);
|
||||
complete(&ar->scan.on_channel);
|
||||
complete(&ar->peer_assoc_done);
|
||||
complete(&ar->peer_delete_done);
|
||||
complete(&ar->install_key_done);
|
||||
|
@ -856,7 +1025,7 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
|
|||
case ATH12K_STATE_ON:
|
||||
ar->state = ATH12K_STATE_RESTARTING;
|
||||
ath12k_core_halt(ar);
|
||||
ieee80211_restart_hw(ar->hw);
|
||||
ieee80211_restart_hw(ath12k_ar_to_hw(ar));
|
||||
break;
|
||||
case ATH12K_STATE_OFF:
|
||||
ath12k_warn(ab,
|
||||
|
@ -979,6 +1148,8 @@ int ath12k_core_pre_init(struct ath12k_base *ab)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ath12k_fw_map(ab);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1007,6 +1178,7 @@ void ath12k_core_deinit(struct ath12k_base *ab)
|
|||
ath12k_hif_power_down(ab);
|
||||
ath12k_mac_destroy(ab);
|
||||
ath12k_core_soc_destroy(ab);
|
||||
ath12k_fw_unmap(ab);
|
||||
}
|
||||
|
||||
void ath12k_core_free(struct ath12k_base *ab)
|
||||
|
@ -1054,6 +1226,8 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
|
|||
|
||||
ab->dev = dev;
|
||||
ab->hif.bus = bus;
|
||||
ab->qmi.num_radios = U8_MAX;
|
||||
ab->slo_capable = true;
|
||||
|
||||
return ab;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_CORE_H
|
||||
|
@ -13,6 +13,7 @@
|
|||
#include <linux/bitfield.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/firmware.h>
|
||||
#include "qmi.h"
|
||||
#include "htc.h"
|
||||
#include "wmi.h"
|
||||
|
@ -24,6 +25,7 @@
|
|||
#include "hal_rx.h"
|
||||
#include "reg.h"
|
||||
#include "dbring.h"
|
||||
#include "fw.h"
|
||||
|
||||
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
|
||||
|
||||
|
@ -55,6 +57,11 @@
|
|||
#define ATH12K_RECONFIGURE_TIMEOUT_HZ (10 * HZ)
|
||||
#define ATH12K_RECOVER_START_TIMEOUT_HZ (20 * HZ)
|
||||
|
||||
enum ath12k_bdf_search {
|
||||
ATH12K_BDF_SEARCH_DEFAULT,
|
||||
ATH12K_BDF_SEARCH_BUS_AND_BOARD,
|
||||
};
|
||||
|
||||
enum wme_ac {
|
||||
WME_AC_BE,
|
||||
WME_AC_BK,
|
||||
|
@ -259,6 +266,7 @@ struct ath12k_vif {
|
|||
u8 tx_encap_type;
|
||||
u8 vdev_stats_id;
|
||||
u32 punct_bitmap;
|
||||
bool ps;
|
||||
};
|
||||
|
||||
struct ath12k_vif_iter {
|
||||
|
@ -420,7 +428,7 @@ struct ath12k_sta {
|
|||
};
|
||||
|
||||
#define ATH12K_MIN_5G_FREQ 4150
|
||||
#define ATH12K_MIN_6G_FREQ 5945
|
||||
#define ATH12K_MIN_6G_FREQ 5925
|
||||
#define ATH12K_MAX_6G_FREQ 7115
|
||||
#define ATH12K_NUM_CHANS 100
|
||||
#define ATH12K_MAX_5G_CHAN 173
|
||||
|
@ -468,7 +476,7 @@ struct ath12k_per_peer_tx_stats {
|
|||
struct ath12k {
|
||||
struct ath12k_base *ab;
|
||||
struct ath12k_pdev *pdev;
|
||||
struct ieee80211_hw *hw;
|
||||
struct ath12k_hw *ah;
|
||||
struct ath12k_wmi_pdev *wmi;
|
||||
struct ath12k_pdev_dp dp;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
|
@ -532,6 +540,7 @@ struct ath12k {
|
|||
/* pdev_idx starts from 0 whereas pdev->pdev_id starts with 1 */
|
||||
u8 pdev_idx;
|
||||
u8 lmac_id;
|
||||
u8 hw_link_id;
|
||||
|
||||
struct completion peer_assoc_done;
|
||||
struct completion peer_delete_done;
|
||||
|
@ -591,6 +600,13 @@ struct ath12k {
|
|||
int monitor_vdev_id;
|
||||
};
|
||||
|
||||
struct ath12k_hw {
|
||||
struct ieee80211_hw *hw;
|
||||
|
||||
u8 num_radio;
|
||||
struct ath12k radio[] __aligned(sizeof(void *));
|
||||
};
|
||||
|
||||
struct ath12k_band_cap {
|
||||
u32 phy_id;
|
||||
u32 max_bw_supported;
|
||||
|
@ -724,6 +740,16 @@ struct ath12k_base {
|
|||
u8 fw_pdev_count;
|
||||
|
||||
struct ath12k_pdev __rcu *pdevs_active[MAX_RADIOS];
|
||||
|
||||
/* Holds information of wiphy (hw) registration.
|
||||
*
|
||||
* In Multi/Single Link Operation case, all pdevs are registered as
|
||||
* a single wiphy. In other (legacy/Non-MLO) cases, each pdev is
|
||||
* registered as separate wiphys.
|
||||
*/
|
||||
struct ath12k_hw *ah[MAX_RADIOS];
|
||||
u8 num_hw;
|
||||
|
||||
struct ath12k_wmi_hal_reg_capabilities_ext_arg hal_reg_cap[MAX_RADIOS];
|
||||
unsigned long long free_vdev_map;
|
||||
unsigned long long free_vdev_stats_id_map;
|
||||
|
@ -793,10 +819,44 @@ struct ath12k_base {
|
|||
/* true means radio is on */
|
||||
bool rfkill_radio_on;
|
||||
|
||||
struct {
|
||||
enum ath12k_bdf_search bdf_search;
|
||||
u32 vendor;
|
||||
u32 device;
|
||||
u32 subsystem_vendor;
|
||||
u32 subsystem_device;
|
||||
} id;
|
||||
|
||||
struct {
|
||||
u32 api_version;
|
||||
|
||||
const struct firmware *fw;
|
||||
const u8 *amss_data;
|
||||
size_t amss_len;
|
||||
const u8 *amss_dualmac_data;
|
||||
size_t amss_dualmac_len;
|
||||
const u8 *m3_data;
|
||||
size_t m3_len;
|
||||
|
||||
DECLARE_BITMAP(fw_features, ATH12K_FW_FEATURE_COUNT);
|
||||
} fw;
|
||||
|
||||
const struct hal_rx_ops *hal_rx_ops;
|
||||
|
||||
/* slo_capable denotes if the single/multi link operation
|
||||
* is supported within the same chip (SoC).
|
||||
*/
|
||||
bool slo_capable;
|
||||
|
||||
/* must be last */
|
||||
u8 drv_priv[] __aligned(sizeof(void *));
|
||||
};
|
||||
|
||||
struct ath12k_pdev_map {
|
||||
struct ath12k_base *ab;
|
||||
u8 pdev_idx;
|
||||
};
|
||||
|
||||
int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab);
|
||||
int ath12k_core_pre_init(struct ath12k_base *ab);
|
||||
int ath12k_core_init(struct ath12k_base *ath12k);
|
||||
|
@ -810,6 +870,7 @@ int ath12k_core_fetch_board_data_api_1(struct ath12k_base *ab,
|
|||
int ath12k_core_fetch_bdf(struct ath12k_base *ath12k,
|
||||
struct ath12k_board_data *bd);
|
||||
void ath12k_core_free_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd);
|
||||
int ath12k_core_fetch_regdb(struct ath12k_base *ab, struct ath12k_board_data *bd);
|
||||
int ath12k_core_check_dt(struct ath12k_base *ath12k);
|
||||
int ath12k_core_check_smbios(struct ath12k_base *ab);
|
||||
void ath12k_core_halt(struct ath12k *ar);
|
||||
|
@ -818,6 +879,9 @@ int ath12k_core_suspend(struct ath12k_base *ab);
|
|||
|
||||
const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab,
|
||||
const char *filename);
|
||||
u32 ath12k_core_get_max_station_per_radio(struct ath12k_base *ab);
|
||||
u32 ath12k_core_get_max_peers_per_radio(struct ath12k_base *ab);
|
||||
u32 ath12k_core_get_max_num_tids(struct ath12k_base *ab);
|
||||
|
||||
static inline const char *ath12k_scan_state_str(enum ath12k_scan_state state)
|
||||
{
|
||||
|
@ -882,4 +946,18 @@ static inline const char *ath12k_bus_str(enum ath12k_bus bus)
|
|||
return "unknown";
|
||||
}
|
||||
|
||||
static inline struct ath12k_hw *ath12k_hw_to_ah(struct ieee80211_hw *hw)
|
||||
{
|
||||
return hw->priv;
|
||||
}
|
||||
|
||||
static inline struct ath12k *ath12k_ah_to_ar(struct ath12k_hw *ah)
|
||||
{
|
||||
return ah->radio;
|
||||
}
|
||||
|
||||
static inline struct ieee80211_hw *ath12k_ar_to_hw(struct ath12k *ar)
|
||||
{
|
||||
return ar->ah->hw;
|
||||
}
|
||||
#endif /* _CORE_H_ */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <crypto/hash.h>
|
||||
|
@ -997,6 +997,29 @@ void ath12k_dp_pdev_pre_alloc(struct ath12k_base *ab)
|
|||
}
|
||||
}
|
||||
|
||||
bool ath12k_dp_wmask_compaction_rx_tlv_supported(struct ath12k_base *ab)
|
||||
{
|
||||
if (test_bit(WMI_TLV_SERVICE_WMSK_COMPACTION_RX_TLVS, ab->wmi_ab.svc_map) &&
|
||||
ab->hw_params->hal_ops->rxdma_ring_wmask_rx_mpdu_start &&
|
||||
ab->hw_params->hal_ops->rxdma_ring_wmask_rx_msdu_end &&
|
||||
ab->hw_params->hal_ops->get_hal_rx_compact_ops) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ath12k_dp_hal_rx_desc_init(struct ath12k_base *ab)
|
||||
{
|
||||
if (ath12k_dp_wmask_compaction_rx_tlv_supported(ab)) {
|
||||
/* RX TLVS compaction is supported, hence change the hal_rx_ops
|
||||
* to compact hal_rx_ops.
|
||||
*/
|
||||
ab->hal_rx_ops = ab->hw_params->hal_ops->get_hal_rx_compact_ops();
|
||||
}
|
||||
ab->hal.hal_desc_sz =
|
||||
ab->hal_rx_ops->rx_desc_get_desc_size();
|
||||
}
|
||||
|
||||
static void ath12k_dp_service_mon_ring(struct timer_list *t)
|
||||
{
|
||||
struct ath12k_base *ab = from_timer(ab, t, mon_reap_timer);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_DP_H
|
||||
|
@ -150,7 +150,7 @@ struct ath12k_pdev_dp {
|
|||
|
||||
#define DP_RX_HASH_ENABLE 1 /* Enable hash based Rx steering */
|
||||
|
||||
#define DP_BA_WIN_SZ_MAX 256
|
||||
#define DP_BA_WIN_SZ_MAX 1024
|
||||
|
||||
#define DP_TCL_NUM_RING_MAX 4
|
||||
|
||||
|
@ -170,6 +170,7 @@ struct ath12k_pdev_dp {
|
|||
#define DP_REO_CMD_RING_SIZE 128
|
||||
#define DP_REO_STATUS_RING_SIZE 2048
|
||||
#define DP_RXDMA_BUF_RING_SIZE 4096
|
||||
#define DP_RX_MAC_BUF_RING_SIZE 2048
|
||||
#define DP_RXDMA_REFILL_RING_SIZE 2048
|
||||
#define DP_RXDMA_ERR_DST_RING_SIZE 1024
|
||||
#define DP_RXDMA_MON_STATUS_RING_SIZE 1024
|
||||
|
@ -765,6 +766,11 @@ enum htt_stats_internal_ppdu_frametype {
|
|||
#define HTT_RX_RING_SELECTION_CFG_RX_MSDU_START_OFFSET GENMASK(31, 16)
|
||||
#define HTT_RX_RING_SELECTION_CFG_RX_ATTENTION_OFFSET GENMASK(15, 0)
|
||||
|
||||
#define HTT_RX_RING_SELECTION_CFG_WORD_MASK_COMPACT_SET BIT(23)
|
||||
#define HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_MASK GENMASK(15, 0)
|
||||
#define HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_MASK GENMASK(18, 16)
|
||||
#define HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_MASK GENMASK(16, 0)
|
||||
|
||||
enum htt_rx_filter_tlv_flags {
|
||||
HTT_RX_FILTER_TLV_FLAGS_MPDU_START = BIT(0),
|
||||
HTT_RX_FILTER_TLV_FLAGS_MSDU_START = BIT(1),
|
||||
|
@ -1088,6 +1094,11 @@ struct htt_rx_ring_selection_cfg_cmd {
|
|||
__le32 rx_mpdu_offset;
|
||||
__le32 rx_msdu_offset;
|
||||
__le32 rx_attn_offset;
|
||||
__le32 info2;
|
||||
__le32 reserved[2];
|
||||
__le32 rx_mpdu_start_end_mask;
|
||||
__le32 rx_msdu_end_word_mask;
|
||||
__le32 info3;
|
||||
} __packed;
|
||||
|
||||
struct htt_rx_ring_tlv_filter {
|
||||
|
@ -1104,6 +1115,9 @@ struct htt_rx_ring_tlv_filter {
|
|||
u16 rx_msdu_end_offset;
|
||||
u16 rx_msdu_start_offset;
|
||||
u16 rx_attn_offset;
|
||||
u16 rx_mpdu_start_wmask;
|
||||
u16 rx_mpdu_end_wmask;
|
||||
u32 rx_msdu_end_wmask;
|
||||
};
|
||||
|
||||
#define HTT_STATS_FRAME_CTRL_TYPE_MGMT 0x0
|
||||
|
@ -1820,4 +1834,6 @@ struct ath12k_rx_desc_info *ath12k_dp_get_rx_desc(struct ath12k_base *ab,
|
|||
u32 cookie);
|
||||
struct ath12k_tx_desc_info *ath12k_dp_get_tx_desc(struct ath12k_base *ab,
|
||||
u32 desc_id);
|
||||
bool ath12k_dp_wmask_compaction_rx_tlv_supported(struct ath12k_base *ab);
|
||||
void ath12k_dp_hal_rx_desc_init(struct ath12k_base *ab);
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "dp_mon.h"
|
||||
|
@ -864,7 +864,7 @@ static void ath12k_dp_mon_rx_msdus_set_payload(struct ath12k *ar, struct sk_buff
|
|||
{
|
||||
u32 rx_pkt_offset, l2_hdr_offset;
|
||||
|
||||
rx_pkt_offset = ar->ab->hw_params->hal_desc_sz;
|
||||
rx_pkt_offset = ar->ab->hal.hal_desc_sz;
|
||||
l2_hdr_offset = ath12k_dp_rx_h_l3pad(ar->ab,
|
||||
(struct hal_rx_desc *)msdu->data);
|
||||
skb_pull(msdu, rx_pkt_offset + l2_hdr_offset);
|
||||
|
@ -917,7 +917,8 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
|
|||
u8 qos_pkt = 0;
|
||||
|
||||
rx_desc = (struct hal_rx_desc *)head_msdu->data;
|
||||
hdr_desc = ab->hw_params->hal_ops->rx_desc_get_msdu_payload(rx_desc);
|
||||
hdr_desc =
|
||||
ab->hal_rx_ops->rx_desc_get_msdu_payload(rx_desc);
|
||||
|
||||
/* Base size */
|
||||
wh = (struct ieee80211_hdr_3addr *)hdr_desc;
|
||||
|
@ -1130,7 +1131,7 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
|
|||
!(is_mcbc && rx_status->flag & RX_FLAG_DECRYPTED))
|
||||
rx_status->flag |= RX_FLAG_8023;
|
||||
|
||||
ieee80211_rx_napi(ar->hw, pubsta, msdu, napi);
|
||||
ieee80211_rx_napi(ath12k_ar_to_hw(ar), pubsta, msdu, napi);
|
||||
}
|
||||
|
||||
static int ath12k_dp_mon_rx_deliver(struct ath12k *ar, u32 mac_id,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
|
@ -23,34 +23,34 @@
|
|||
static enum hal_encrypt_type ath12k_dp_rx_h_enctype(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
if (!ab->hw_params->hal_ops->rx_desc_encrypt_valid(desc))
|
||||
if (!ab->hal_rx_ops->rx_desc_encrypt_valid(desc))
|
||||
return HAL_ENCRYPT_TYPE_OPEN;
|
||||
|
||||
return ab->hw_params->hal_ops->rx_desc_get_encrypt_type(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_encrypt_type(desc);
|
||||
}
|
||||
|
||||
u8 ath12k_dp_rx_h_decap_type(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_decap_type(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_decap_type(desc);
|
||||
}
|
||||
|
||||
static u8 ath12k_dp_rx_h_mesh_ctl_present(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_mesh_ctl(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_mesh_ctl(desc);
|
||||
}
|
||||
|
||||
static bool ath12k_dp_rx_h_seq_ctrl_valid(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_mpdu_seq_ctl_vld(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_mpdu_seq_ctl_vld(desc);
|
||||
}
|
||||
|
||||
static bool ath12k_dp_rx_h_fc_valid(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_mpdu_fc_valid(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_mpdu_fc_valid(desc);
|
||||
}
|
||||
|
||||
static bool ath12k_dp_rx_h_more_frags(struct ath12k_base *ab,
|
||||
|
@ -58,7 +58,7 @@ static bool ath12k_dp_rx_h_more_frags(struct ath12k_base *ab,
|
|||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)(skb->data + ab->hw_params->hal_desc_sz);
|
||||
hdr = (struct ieee80211_hdr *)(skb->data + ab->hal.hal_desc_sz);
|
||||
return ieee80211_has_morefrags(hdr->frame_control);
|
||||
}
|
||||
|
||||
|
@ -67,156 +67,156 @@ static u16 ath12k_dp_rx_h_frag_no(struct ath12k_base *ab,
|
|||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)(skb->data + ab->hw_params->hal_desc_sz);
|
||||
hdr = (struct ieee80211_hdr *)(skb->data + ab->hal.hal_desc_sz);
|
||||
return le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
|
||||
}
|
||||
|
||||
static u16 ath12k_dp_rx_h_seq_no(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_mpdu_start_seq_no(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_mpdu_start_seq_no(desc);
|
||||
}
|
||||
|
||||
static bool ath12k_dp_rx_h_msdu_done(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->dp_rx_h_msdu_done(desc);
|
||||
return ab->hal_rx_ops->dp_rx_h_msdu_done(desc);
|
||||
}
|
||||
|
||||
static bool ath12k_dp_rx_h_l4_cksum_fail(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->dp_rx_h_l4_cksum_fail(desc);
|
||||
return ab->hal_rx_ops->dp_rx_h_l4_cksum_fail(desc);
|
||||
}
|
||||
|
||||
static bool ath12k_dp_rx_h_ip_cksum_fail(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->dp_rx_h_ip_cksum_fail(desc);
|
||||
return ab->hal_rx_ops->dp_rx_h_ip_cksum_fail(desc);
|
||||
}
|
||||
|
||||
static bool ath12k_dp_rx_h_is_decrypted(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->dp_rx_h_is_decrypted(desc);
|
||||
return ab->hal_rx_ops->dp_rx_h_is_decrypted(desc);
|
||||
}
|
||||
|
||||
u32 ath12k_dp_rx_h_mpdu_err(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->dp_rx_h_mpdu_err(desc);
|
||||
return ab->hal_rx_ops->dp_rx_h_mpdu_err(desc);
|
||||
}
|
||||
|
||||
static u16 ath12k_dp_rx_h_msdu_len(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_msdu_len(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_msdu_len(desc);
|
||||
}
|
||||
|
||||
static u8 ath12k_dp_rx_h_sgi(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_msdu_sgi(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_msdu_sgi(desc);
|
||||
}
|
||||
|
||||
static u8 ath12k_dp_rx_h_rate_mcs(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_msdu_rate_mcs(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_msdu_rate_mcs(desc);
|
||||
}
|
||||
|
||||
static u8 ath12k_dp_rx_h_rx_bw(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_msdu_rx_bw(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_msdu_rx_bw(desc);
|
||||
}
|
||||
|
||||
static u32 ath12k_dp_rx_h_freq(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_msdu_freq(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_msdu_freq(desc);
|
||||
}
|
||||
|
||||
static u8 ath12k_dp_rx_h_pkt_type(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_msdu_pkt_type(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_msdu_pkt_type(desc);
|
||||
}
|
||||
|
||||
static u8 ath12k_dp_rx_h_nss(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return hweight8(ab->hw_params->hal_ops->rx_desc_get_msdu_nss(desc));
|
||||
return hweight8(ab->hal_rx_ops->rx_desc_get_msdu_nss(desc));
|
||||
}
|
||||
|
||||
static u8 ath12k_dp_rx_h_tid(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_mpdu_tid(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_mpdu_tid(desc);
|
||||
}
|
||||
|
||||
static u16 ath12k_dp_rx_h_peer_id(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_mpdu_peer_id(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_mpdu_peer_id(desc);
|
||||
}
|
||||
|
||||
u8 ath12k_dp_rx_h_l3pad(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_l3_pad_bytes(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_l3_pad_bytes(desc);
|
||||
}
|
||||
|
||||
static bool ath12k_dp_rx_h_first_msdu(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_first_msdu(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_first_msdu(desc);
|
||||
}
|
||||
|
||||
static bool ath12k_dp_rx_h_last_msdu(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_last_msdu(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_last_msdu(desc);
|
||||
}
|
||||
|
||||
static void ath12k_dp_rx_desc_end_tlv_copy(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *fdesc,
|
||||
struct hal_rx_desc *ldesc)
|
||||
{
|
||||
ab->hw_params->hal_ops->rx_desc_copy_end_tlv(fdesc, ldesc);
|
||||
ab->hal_rx_ops->rx_desc_copy_end_tlv(fdesc, ldesc);
|
||||
}
|
||||
|
||||
static void ath12k_dp_rxdesc_set_msdu_len(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc,
|
||||
u16 len)
|
||||
{
|
||||
ab->hw_params->hal_ops->rx_desc_set_msdu_len(desc, len);
|
||||
ab->hal_rx_ops->rx_desc_set_msdu_len(desc, len);
|
||||
}
|
||||
|
||||
static bool ath12k_dp_rx_h_is_da_mcbc(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return (ath12k_dp_rx_h_first_msdu(ab, desc) &&
|
||||
ab->hw_params->hal_ops->rx_desc_is_da_mcbc(desc));
|
||||
ab->hal_rx_ops->rx_desc_is_da_mcbc(desc));
|
||||
}
|
||||
|
||||
static bool ath12k_dp_rxdesc_mac_addr2_valid(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_mac_addr2_valid(desc);
|
||||
return ab->hal_rx_ops->rx_desc_mac_addr2_valid(desc);
|
||||
}
|
||||
|
||||
static u8 *ath12k_dp_rxdesc_get_mpdu_start_addr2(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_mpdu_start_addr2(desc);
|
||||
return ab->hal_rx_ops->rx_desc_mpdu_start_addr2(desc);
|
||||
}
|
||||
|
||||
static void ath12k_dp_rx_desc_get_dot11_hdr(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc,
|
||||
struct ieee80211_hdr *hdr)
|
||||
{
|
||||
ab->hw_params->hal_ops->rx_desc_get_dot11_hdr(desc, hdr);
|
||||
ab->hal_rx_ops->rx_desc_get_dot11_hdr(desc, hdr);
|
||||
}
|
||||
|
||||
static void ath12k_dp_rx_desc_get_crypto_header(struct ath12k_base *ab,
|
||||
|
@ -224,13 +224,19 @@ static void ath12k_dp_rx_desc_get_crypto_header(struct ath12k_base *ab,
|
|||
u8 *crypto_hdr,
|
||||
enum hal_encrypt_type enctype)
|
||||
{
|
||||
ab->hw_params->hal_ops->rx_desc_get_crypto_header(desc, crypto_hdr, enctype);
|
||||
ab->hal_rx_ops->rx_desc_get_crypto_header(desc, crypto_hdr, enctype);
|
||||
}
|
||||
|
||||
static u16 ath12k_dp_rxdesc_get_mpdu_frame_ctrl(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hw_params->hal_ops->rx_desc_get_mpdu_frame_ctl(desc);
|
||||
return ab->hal_rx_ops->rx_desc_get_mpdu_frame_ctl(desc);
|
||||
}
|
||||
|
||||
static inline u8 ath12k_dp_rx_get_msdu_src_link(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc)
|
||||
{
|
||||
return ab->hal_rx_ops->rx_desc_get_msdu_src_link_id(desc);
|
||||
}
|
||||
|
||||
static int ath12k_dp_purge_mon_ring(struct ath12k_base *ab)
|
||||
|
@ -1761,7 +1767,7 @@ static int ath12k_dp_rx_msdu_coalesce(struct ath12k *ar,
|
|||
int buf_first_hdr_len, buf_first_len;
|
||||
struct hal_rx_desc *ldesc;
|
||||
int space_extra, rem_len, buf_len;
|
||||
u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz;
|
||||
u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
|
||||
|
||||
/* As the msdu is spread across multiple rx buffers,
|
||||
* find the offset to the start of msdu for computing
|
||||
|
@ -2458,7 +2464,7 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap
|
|||
!(is_mcbc && rx_status->flag & RX_FLAG_DECRYPTED))
|
||||
rx_status->flag |= RX_FLAG_8023;
|
||||
|
||||
ieee80211_rx_napi(ar->hw, pubsta, msdu, napi);
|
||||
ieee80211_rx_napi(ath12k_ar_to_hw(ar), pubsta, msdu, napi);
|
||||
}
|
||||
|
||||
static int ath12k_dp_rx_process_msdu(struct ath12k *ar,
|
||||
|
@ -2473,7 +2479,7 @@ static int ath12k_dp_rx_process_msdu(struct ath12k *ar,
|
|||
u8 l3_pad_bytes;
|
||||
u16 msdu_len;
|
||||
int ret;
|
||||
u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz;
|
||||
u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
|
||||
|
||||
last_buf = ath12k_dp_rx_get_msdu_last_buf(msdu_list, msdu);
|
||||
if (!last_buf) {
|
||||
|
@ -2804,7 +2810,7 @@ static int ath12k_dp_rx_h_verify_tkip_mic(struct ath12k *ar, struct ath12k_peer
|
|||
u8 mic[IEEE80211_CCMP_MIC_LEN];
|
||||
int head_len, tail_len, ret;
|
||||
size_t data_len;
|
||||
u32 hdr_len, hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz;
|
||||
u32 hdr_len, hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
|
||||
u8 *key, *data;
|
||||
u8 key_idx;
|
||||
|
||||
|
@ -2844,7 +2850,7 @@ mic_fail:
|
|||
ath12k_dp_rx_h_ppdu(ar, rx_desc, rxs);
|
||||
ath12k_dp_rx_h_undecap(ar, msdu, rx_desc,
|
||||
HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true);
|
||||
ieee80211_rx(ar->hw, msdu);
|
||||
ieee80211_rx(ath12k_ar_to_hw(ar), msdu);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -2854,7 +2860,7 @@ static void ath12k_dp_rx_h_undecap_frag(struct ath12k *ar, struct sk_buff *msdu,
|
|||
struct ieee80211_hdr *hdr;
|
||||
size_t hdr_len;
|
||||
size_t crypto_len;
|
||||
u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz;
|
||||
u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
|
||||
|
||||
if (!flags)
|
||||
return;
|
||||
|
@ -2892,7 +2898,7 @@ static int ath12k_dp_rx_h_defrag(struct ath12k *ar,
|
|||
bool is_decrypted = false;
|
||||
int msdu_len = 0;
|
||||
int extra_space;
|
||||
u32 flags, hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz;
|
||||
u32 flags, hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
|
||||
|
||||
first_frag = skb_peek(&rx_tid->rx_frags);
|
||||
last_frag = skb_peek_tail(&rx_tid->rx_frags);
|
||||
|
@ -2968,7 +2974,7 @@ static int ath12k_dp_rx_h_defrag_reo_reinject(struct ath12k *ar,
|
|||
struct ath12k_rx_desc_info *desc_info;
|
||||
u8 dst_ind;
|
||||
|
||||
hal_rx_desc_sz = ab->hw_params->hal_desc_sz;
|
||||
hal_rx_desc_sz = ab->hal.hal_desc_sz;
|
||||
link_desc_banks = dp->link_desc_banks;
|
||||
reo_dest_ring = rx_tid->dst_ring_desc;
|
||||
|
||||
|
@ -3122,7 +3128,7 @@ static u64 ath12k_dp_rx_h_get_pn(struct ath12k *ar, struct sk_buff *skb)
|
|||
struct ieee80211_hdr *hdr;
|
||||
u64 pn = 0;
|
||||
u8 *ehdr;
|
||||
u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz;
|
||||
u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)(skb->data + hal_rx_desc_sz);
|
||||
ehdr = skb->data + hal_rx_desc_sz + ieee80211_hdrlen(hdr->frame_control);
|
||||
|
@ -3305,7 +3311,7 @@ ath12k_dp_process_rx_err_buf(struct ath12k *ar, struct hal_reo_dest_ring *desc,
|
|||
struct ath12k_skb_rxcb *rxcb;
|
||||
struct hal_rx_desc *rx_desc;
|
||||
u16 msdu_len;
|
||||
u32 hal_rx_desc_sz = ab->hw_params->hal_desc_sz;
|
||||
u32 hal_rx_desc_sz = ab->hal.hal_desc_sz;
|
||||
struct ath12k_rx_desc_info *desc_info;
|
||||
u64 desc_va;
|
||||
|
||||
|
@ -3486,7 +3492,7 @@ static void ath12k_dp_rx_null_q_desc_sg_drop(struct ath12k *ar,
|
|||
int n_buffs;
|
||||
|
||||
n_buffs = DIV_ROUND_UP(msdu_len,
|
||||
(DP_RX_BUFFER_SIZE - ar->ab->hw_params->hal_desc_sz));
|
||||
(DP_RX_BUFFER_SIZE - ar->ab->hal.hal_desc_sz));
|
||||
|
||||
skb_queue_walk_safe(msdu_list, skb, tmp) {
|
||||
rxcb = ATH12K_SKB_RXCB(skb);
|
||||
|
@ -3510,7 +3516,7 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
|
|||
struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
|
||||
u8 l3pad_bytes;
|
||||
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz;
|
||||
u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
|
||||
|
||||
msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc);
|
||||
|
||||
|
@ -3607,7 +3613,7 @@ static void ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu,
|
|||
struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
|
||||
u8 l3pad_bytes;
|
||||
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz;
|
||||
u32 hal_rx_desc_sz = ar->ab->hal.hal_desc_sz;
|
||||
|
||||
rxcb->is_first_msdu = ath12k_dp_rx_h_first_msdu(ab, desc);
|
||||
rxcb->is_last_msdu = ath12k_dp_rx_h_last_msdu(ab, desc);
|
||||
|
@ -3695,16 +3701,15 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
|
|||
struct hal_rx_wbm_rel_info err_info;
|
||||
struct hal_srng *srng;
|
||||
struct sk_buff *msdu;
|
||||
struct sk_buff_head msdu_list[MAX_RADIOS];
|
||||
struct sk_buff_head msdu_list;
|
||||
struct ath12k_skb_rxcb *rxcb;
|
||||
void *rx_desc;
|
||||
int mac_id;
|
||||
u8 mac_id;
|
||||
int num_buffs_reaped = 0;
|
||||
struct ath12k_rx_desc_info *desc_info;
|
||||
int ret, i;
|
||||
int ret, pdev_id;
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++)
|
||||
__skb_queue_head_init(&msdu_list[i]);
|
||||
__skb_queue_head_init(&msdu_list);
|
||||
|
||||
srng = &ab->hal.srng_list[dp->rx_rel_ring.ring_id];
|
||||
rx_ring = &dp->rx_refill_buf_ring;
|
||||
|
@ -3737,11 +3742,6 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
|
|||
}
|
||||
}
|
||||
|
||||
/* FIXME: Extract mac id correctly. Since descs are not tied
|
||||
* to mac, we can extract from vdev id in ring desc.
|
||||
*/
|
||||
mac_id = 0;
|
||||
|
||||
if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC)
|
||||
ath12k_warn(ab, "WBM RX err, Check HW CC implementation");
|
||||
|
||||
|
@ -3771,7 +3771,8 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
|
|||
rxcb->err_rel_src = err_info.err_rel_src;
|
||||
rxcb->err_code = err_info.err_code;
|
||||
rxcb->rx_desc = (struct hal_rx_desc *)msdu->data;
|
||||
__skb_queue_tail(&msdu_list[mac_id], msdu);
|
||||
|
||||
__skb_queue_tail(&msdu_list, msdu);
|
||||
|
||||
rxcb->is_first_msdu = err_info.first_msdu;
|
||||
rxcb->is_last_msdu = err_info.last_msdu;
|
||||
|
@ -3788,21 +3789,22 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
|
|||
ath12k_dp_rx_bufs_replenish(ab, rx_ring, num_buffs_reaped);
|
||||
|
||||
rcu_read_lock();
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
if (!rcu_dereference(ab->pdevs_active[i])) {
|
||||
__skb_queue_purge(&msdu_list[i]);
|
||||
while ((msdu = __skb_dequeue(&msdu_list))) {
|
||||
mac_id = ath12k_dp_rx_get_msdu_src_link(ab,
|
||||
(struct hal_rx_desc *)msdu->data);
|
||||
pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
|
||||
ar = ab->pdevs[pdev_id].ar;
|
||||
|
||||
if (!ar || !rcu_dereference(ar->ab->pdevs_active[mac_id])) {
|
||||
dev_kfree_skb_any(msdu);
|
||||
continue;
|
||||
}
|
||||
|
||||
ar = ab->pdevs[i].ar;
|
||||
|
||||
if (test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) {
|
||||
__skb_queue_purge(&msdu_list[i]);
|
||||
dev_kfree_skb_any(msdu);
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((msdu = __skb_dequeue(&msdu_list[i])) != NULL)
|
||||
ath12k_dp_rx_wbm_err(ar, napi, msdu, &msdu_list[i]);
|
||||
ath12k_dp_rx_wbm_err(ar, napi, msdu, &msdu_list);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
done:
|
||||
|
@ -3922,7 +3924,7 @@ int ath12k_dp_rxdma_ring_sel_config_qcn9274(struct ath12k_base *ab)
|
|||
struct htt_rx_ring_tlv_filter tlv_filter = {0};
|
||||
u32 ring_id;
|
||||
int ret;
|
||||
u32 hal_rx_desc_sz = ab->hw_params->hal_desc_sz;
|
||||
u32 hal_rx_desc_sz = ab->hal.hal_desc_sz;
|
||||
|
||||
ring_id = dp->rx_refill_buf_ring.refill_buf_ring.ring_id;
|
||||
|
||||
|
@ -3935,14 +3937,20 @@ int ath12k_dp_rxdma_ring_sel_config_qcn9274(struct ath12k_base *ab)
|
|||
tlv_filter.rx_packet_offset = hal_rx_desc_sz;
|
||||
|
||||
tlv_filter.rx_mpdu_start_offset =
|
||||
ab->hw_params->hal_ops->rx_desc_get_mpdu_start_offset();
|
||||
ab->hal_rx_ops->rx_desc_get_mpdu_start_offset();
|
||||
tlv_filter.rx_msdu_end_offset =
|
||||
ab->hw_params->hal_ops->rx_desc_get_msdu_end_offset();
|
||||
ab->hal_rx_ops->rx_desc_get_msdu_end_offset();
|
||||
|
||||
if (ath12k_dp_wmask_compaction_rx_tlv_supported(ab)) {
|
||||
tlv_filter.rx_mpdu_start_wmask =
|
||||
ab->hw_params->hal_ops->rxdma_ring_wmask_rx_mpdu_start();
|
||||
tlv_filter.rx_msdu_end_wmask =
|
||||
ab->hw_params->hal_ops->rxdma_ring_wmask_rx_msdu_end();
|
||||
ath12k_dbg(ab, ATH12K_DBG_DATA,
|
||||
"Configuring compact tlv masks rx_mpdu_start_wmask 0x%x rx_msdu_end_wmask 0x%x\n",
|
||||
tlv_filter.rx_mpdu_start_wmask, tlv_filter.rx_msdu_end_wmask);
|
||||
}
|
||||
|
||||
/* TODO: Selectively subscribe to required qwords within msdu_end
|
||||
* and mpdu_start and setup the mask in below msg
|
||||
* and modify the rx_desc struct
|
||||
*/
|
||||
ret = ath12k_dp_tx_htt_rx_filter_setup(ab, ring_id, 0,
|
||||
HAL_RXDMA_BUF,
|
||||
DP_RXDMA_REFILL_RING_SIZE,
|
||||
|
@ -3957,7 +3965,7 @@ int ath12k_dp_rxdma_ring_sel_config_wcn7850(struct ath12k_base *ab)
|
|||
struct htt_rx_ring_tlv_filter tlv_filter = {0};
|
||||
u32 ring_id;
|
||||
int ret;
|
||||
u32 hal_rx_desc_sz = ab->hw_params->hal_desc_sz;
|
||||
u32 hal_rx_desc_sz = ab->hal.hal_desc_sz;
|
||||
int i;
|
||||
|
||||
ring_id = dp->rx_refill_buf_ring.refill_buf_ring.ring_id;
|
||||
|
@ -3973,9 +3981,9 @@ int ath12k_dp_rxdma_ring_sel_config_wcn7850(struct ath12k_base *ab)
|
|||
tlv_filter.rx_header_offset = offsetof(struct hal_rx_desc_wcn7850, pkt_hdr_tlv);
|
||||
|
||||
tlv_filter.rx_mpdu_start_offset =
|
||||
ab->hw_params->hal_ops->rx_desc_get_mpdu_start_offset();
|
||||
ab->hal_rx_ops->rx_desc_get_mpdu_start_offset();
|
||||
tlv_filter.rx_msdu_end_offset =
|
||||
ab->hw_params->hal_ops->rx_desc_get_msdu_end_offset();
|
||||
ab->hal_rx_ops->rx_desc_get_msdu_end_offset();
|
||||
|
||||
/* TODO: Selectively subscribe to required qwords within msdu_end
|
||||
* and mpdu_start and setup the mask in below msg
|
||||
|
@ -4086,7 +4094,7 @@ int ath12k_dp_rx_alloc(struct ath12k_base *ab)
|
|||
ret = ath12k_dp_srng_setup(ab,
|
||||
&dp->rx_mac_buf_ring[i],
|
||||
HAL_RXDMA_BUF, 1,
|
||||
i, 1024);
|
||||
i, DP_RX_MAC_BUF_RING_SIZE);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to setup rx_mac_buf_ring %d\n",
|
||||
i);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
|
@ -151,7 +151,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
|
|||
|
||||
if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
|
||||
!ieee80211_is_data(hdr->frame_control))
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
pool_id = skb_get_queue_mapping(skb) & (ATH12K_HW_MAX_QUEUES - 1);
|
||||
|
||||
|
@ -401,7 +401,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab,
|
|||
}
|
||||
}
|
||||
|
||||
ieee80211_tx_status_skb(ar->hw, msdu);
|
||||
ieee80211_tx_status_skb(ath12k_ar_to_hw(ar), msdu);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -498,7 +498,7 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar,
|
|||
* Might end up reporting it out-of-band from HTT stats.
|
||||
*/
|
||||
|
||||
ieee80211_tx_status_skb(ar->hw, msdu);
|
||||
ieee80211_tx_status_skb(ath12k_ar_to_hw(ar), msdu);
|
||||
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
|
@ -837,7 +837,7 @@ int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab)
|
|||
if (dp->htt_tgt_ver_major != HTT_TARGET_VERSION_MAJOR) {
|
||||
ath12k_err(ab, "unsupported htt major version %d supported version is %d\n",
|
||||
dp->htt_tgt_ver_major, HTT_TARGET_VERSION_MAJOR);
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -964,6 +964,26 @@ int ath12k_dp_tx_htt_rx_filter_setup(struct ath12k_base *ab, u32 ring_id,
|
|||
HTT_RX_RING_SELECTION_CFG_RX_ATTENTION_OFFSET);
|
||||
}
|
||||
|
||||
if (tlv_filter->rx_mpdu_start_wmask > 0 &&
|
||||
tlv_filter->rx_msdu_end_wmask > 0) {
|
||||
cmd->info2 |=
|
||||
le32_encode_bits(true,
|
||||
HTT_RX_RING_SELECTION_CFG_WORD_MASK_COMPACT_SET);
|
||||
cmd->rx_mpdu_start_end_mask =
|
||||
le32_encode_bits(tlv_filter->rx_mpdu_start_wmask,
|
||||
HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_MASK);
|
||||
/* mpdu_end is not used for any hardwares so far
|
||||
* please assign it in future if any chip is
|
||||
* using through hal ops
|
||||
*/
|
||||
cmd->rx_mpdu_start_end_mask |=
|
||||
le32_encode_bits(tlv_filter->rx_mpdu_end_wmask,
|
||||
HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_MASK);
|
||||
cmd->rx_msdu_end_word_mask =
|
||||
le32_encode_bits(tlv_filter->rx_msdu_end_wmask,
|
||||
HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_MASK);
|
||||
}
|
||||
|
||||
ret = ath12k_htc_send(&ab->htc, ab->dp.eid, skb);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
static int ath12k_fw_request_firmware_api_n(struct ath12k_base *ab,
|
||||
const char *name)
|
||||
{
|
||||
size_t magic_len, len, ie_len;
|
||||
int ie_id, i, index, bit, ret;
|
||||
struct ath12k_fw_ie *hdr;
|
||||
const u8 *data;
|
||||
__le32 *timestamp;
|
||||
|
||||
ab->fw.fw = ath12k_core_firmware_request(ab, name);
|
||||
if (IS_ERR(ab->fw.fw)) {
|
||||
ret = PTR_ERR(ab->fw.fw);
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "failed to load %s: %d\n", name, ret);
|
||||
ab->fw.fw = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
data = ab->fw.fw->data;
|
||||
len = ab->fw.fw->size;
|
||||
|
||||
/* magic also includes the null byte, check that as well */
|
||||
magic_len = strlen(ATH12K_FIRMWARE_MAGIC) + 1;
|
||||
|
||||
if (len < magic_len) {
|
||||
ath12k_err(ab, "firmware image too small to contain magic: %zu\n",
|
||||
len);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (memcmp(data, ATH12K_FIRMWARE_MAGIC, magic_len) != 0) {
|
||||
ath12k_err(ab, "Invalid firmware magic\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* jump over the padding */
|
||||
magic_len = ALIGN(magic_len, 4);
|
||||
|
||||
/* make sure there's space for padding */
|
||||
if (magic_len > len) {
|
||||
ath12k_err(ab, "No space for padding after magic\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
len -= magic_len;
|
||||
data += magic_len;
|
||||
|
||||
/* loop elements */
|
||||
while (len > sizeof(struct ath12k_fw_ie)) {
|
||||
hdr = (struct ath12k_fw_ie *)data;
|
||||
|
||||
ie_id = le32_to_cpu(hdr->id);
|
||||
ie_len = le32_to_cpu(hdr->len);
|
||||
|
||||
len -= sizeof(*hdr);
|
||||
data += sizeof(*hdr);
|
||||
|
||||
if (len < ie_len) {
|
||||
ath12k_err(ab, "Invalid length for FW IE %d (%zu < %zu)\n",
|
||||
ie_id, len, ie_len);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (ie_id) {
|
||||
case ATH12K_FW_IE_TIMESTAMP:
|
||||
if (ie_len != sizeof(u32))
|
||||
break;
|
||||
|
||||
timestamp = (__le32 *)data;
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "found fw timestamp %d\n",
|
||||
le32_to_cpup(timestamp));
|
||||
break;
|
||||
case ATH12K_FW_IE_FEATURES:
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"found firmware features ie (%zd B)\n",
|
||||
ie_len);
|
||||
|
||||
for (i = 0; i < ATH12K_FW_FEATURE_COUNT; i++) {
|
||||
index = i / 8;
|
||||
bit = i % 8;
|
||||
|
||||
if (index == ie_len)
|
||||
break;
|
||||
|
||||
if (data[index] & (1 << bit))
|
||||
__set_bit(i, ab->fw.fw_features);
|
||||
}
|
||||
|
||||
ath12k_dbg_dump(ab, ATH12K_DBG_BOOT, "features", "",
|
||||
ab->fw.fw_features,
|
||||
sizeof(ab->fw.fw_features));
|
||||
break;
|
||||
case ATH12K_FW_IE_AMSS_IMAGE:
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"found fw image ie (%zd B)\n",
|
||||
ie_len);
|
||||
|
||||
ab->fw.amss_data = data;
|
||||
ab->fw.amss_len = ie_len;
|
||||
break;
|
||||
case ATH12K_FW_IE_M3_IMAGE:
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"found m3 image ie (%zd B)\n",
|
||||
ie_len);
|
||||
|
||||
ab->fw.m3_data = data;
|
||||
ab->fw.m3_len = ie_len;
|
||||
break;
|
||||
case ATH12K_FW_IE_AMSS_DUALMAC_IMAGE:
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"found dualmac fw image ie (%zd B)\n",
|
||||
ie_len);
|
||||
ab->fw.amss_dualmac_data = data;
|
||||
ab->fw.amss_dualmac_len = ie_len;
|
||||
break;
|
||||
default:
|
||||
ath12k_warn(ab, "Unknown FW IE: %u\n", ie_id);
|
||||
break;
|
||||
}
|
||||
|
||||
/* jump over the padding */
|
||||
ie_len = ALIGN(ie_len, 4);
|
||||
|
||||
/* make sure there's space for padding */
|
||||
if (ie_len > len)
|
||||
break;
|
||||
|
||||
len -= ie_len;
|
||||
data += ie_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
release_firmware(ab->fw.fw);
|
||||
ab->fw.fw = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ath12k_fw_map(struct ath12k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath12k_fw_request_firmware_api_n(ab, ATH12K_FW_API2_FILE);
|
||||
if (ret == 0)
|
||||
ab->fw.api_version = 2;
|
||||
else
|
||||
ab->fw.api_version = 1;
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "using fw api %d\n",
|
||||
ab->fw.api_version);
|
||||
}
|
||||
|
||||
void ath12k_fw_unmap(struct ath12k_base *ab)
|
||||
{
|
||||
release_firmware(ab->fw.fw);
|
||||
memset(&ab->fw, 0, sizeof(ab->fw));
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_FW_H
|
||||
#define ATH12K_FW_H
|
||||
|
||||
#define ATH12K_FW_API2_FILE "firmware-2.bin"
|
||||
#define ATH12K_FIRMWARE_MAGIC "QCOM-ATH12K-FW"
|
||||
|
||||
enum ath12k_fw_ie_type {
|
||||
ATH12K_FW_IE_TIMESTAMP = 0,
|
||||
ATH12K_FW_IE_FEATURES = 1,
|
||||
ATH12K_FW_IE_AMSS_IMAGE = 2,
|
||||
ATH12K_FW_IE_M3_IMAGE = 3,
|
||||
ATH12K_FW_IE_AMSS_DUALMAC_IMAGE = 4,
|
||||
};
|
||||
|
||||
enum ath12k_fw_features {
|
||||
/* The firmware supports setting the QRTR id via register
|
||||
* PCIE_LOCAL_REG_QRTR_NODE_ID
|
||||
*/
|
||||
ATH12K_FW_FEATURE_MULTI_QRTR_ID = 0,
|
||||
|
||||
/* keep last */
|
||||
ATH12K_FW_FEATURE_COUNT,
|
||||
};
|
||||
|
||||
void ath12k_fw_map(struct ath12k_base *ab);
|
||||
void ath12k_fw_unmap(struct ath12k_base *ab);
|
||||
|
||||
#endif /* ATH12K_FW_H */
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/dma-mapping.h>
|
||||
#include "hal_tx.h"
|
||||
|
@ -449,8 +449,8 @@ static u8 *ath12k_hw_qcn9274_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
|
|||
|
||||
static bool ath12k_hw_qcn9274_rx_desc_is_da_mcbc(struct hal_rx_desc *desc)
|
||||
{
|
||||
return __le16_to_cpu(desc->u.qcn9274.msdu_end.info5) &
|
||||
RX_MSDU_END_INFO5_DA_IS_MCBC;
|
||||
return __le32_to_cpu(desc->u.qcn9274.mpdu_start.info6) &
|
||||
RX_MPDU_START_INFO6_MCAST_BCAST;
|
||||
}
|
||||
|
||||
static void ath12k_hw_qcn9274_rx_desc_get_dot11_hdr(struct hal_rx_desc *desc,
|
||||
|
@ -626,6 +626,21 @@ static int ath12k_hal_srng_create_config_qcn9274(struct ath12k_base *ab)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u16 ath12k_hal_qcn9274_rx_mpdu_start_wmask_get(void)
|
||||
{
|
||||
return QCN9274_MPDU_START_WMASK;
|
||||
}
|
||||
|
||||
static u32 ath12k_hal_qcn9274_rx_msdu_end_wmask_get(void)
|
||||
{
|
||||
return QCN9274_MSDU_END_WMASK;
|
||||
}
|
||||
|
||||
static const struct hal_rx_ops *ath12k_hal_qcn9274_get_hal_rx_compact_ops(void)
|
||||
{
|
||||
return &hal_rx_qcn9274_compact_ops;
|
||||
}
|
||||
|
||||
static bool ath12k_hw_qcn9274_dp_rx_h_msdu_done(struct hal_rx_desc *desc)
|
||||
{
|
||||
return !!le32_get_bits(desc->u.qcn9274.msdu_end.info14,
|
||||
|
@ -680,7 +695,17 @@ static u32 ath12k_hw_qcn9274_dp_rx_h_mpdu_err(struct hal_rx_desc *desc)
|
|||
return errmap;
|
||||
}
|
||||
|
||||
const struct hal_ops hal_qcn9274_ops = {
|
||||
static u32 ath12k_hw_qcn9274_get_rx_desc_size(void)
|
||||
{
|
||||
return sizeof(struct hal_rx_desc_qcn9274);
|
||||
}
|
||||
|
||||
static u8 ath12k_hw_qcn9274_rx_desc_get_msdu_src_link(struct hal_rx_desc *desc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct hal_rx_ops hal_rx_qcn9274_ops = {
|
||||
.rx_desc_get_first_msdu = ath12k_hw_qcn9274_rx_desc_get_first_msdu,
|
||||
.rx_desc_get_last_msdu = ath12k_hw_qcn9274_rx_desc_get_last_msdu,
|
||||
.rx_desc_get_l3_pad_bytes = ath12k_hw_qcn9274_rx_desc_get_l3_pad_bytes,
|
||||
|
@ -712,13 +737,367 @@ const struct hal_ops hal_qcn9274_ops = {
|
|||
.rx_desc_get_dot11_hdr = ath12k_hw_qcn9274_rx_desc_get_dot11_hdr,
|
||||
.rx_desc_get_crypto_header = ath12k_hw_qcn9274_rx_desc_get_crypto_hdr,
|
||||
.rx_desc_get_mpdu_frame_ctl = ath12k_hw_qcn9274_rx_desc_get_mpdu_frame_ctl,
|
||||
.create_srng_config = ath12k_hal_srng_create_config_qcn9274,
|
||||
.tcl_to_wbm_rbm_map = ath12k_hal_qcn9274_tcl_to_wbm_rbm_map,
|
||||
.dp_rx_h_msdu_done = ath12k_hw_qcn9274_dp_rx_h_msdu_done,
|
||||
.dp_rx_h_l4_cksum_fail = ath12k_hw_qcn9274_dp_rx_h_l4_cksum_fail,
|
||||
.dp_rx_h_ip_cksum_fail = ath12k_hw_qcn9274_dp_rx_h_ip_cksum_fail,
|
||||
.dp_rx_h_is_decrypted = ath12k_hw_qcn9274_dp_rx_h_is_decrypted,
|
||||
.dp_rx_h_mpdu_err = ath12k_hw_qcn9274_dp_rx_h_mpdu_err,
|
||||
.rx_desc_get_desc_size = ath12k_hw_qcn9274_get_rx_desc_size,
|
||||
.rx_desc_get_msdu_src_link_id = ath12k_hw_qcn9274_rx_desc_get_msdu_src_link,
|
||||
};
|
||||
|
||||
static bool ath12k_hw_qcn9274_compact_rx_desc_get_first_msdu(struct hal_rx_desc *desc)
|
||||
{
|
||||
return !!le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_FIRST_MSDU);
|
||||
}
|
||||
|
||||
static bool ath12k_hw_qcn9274_compact_rx_desc_get_last_msdu(struct hal_rx_desc *desc)
|
||||
{
|
||||
return !!le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_LAST_MSDU);
|
||||
}
|
||||
|
||||
static u8 ath12k_hw_qcn9274_compact_rx_desc_get_l3_pad_bytes(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
|
||||
RX_MSDU_END_INFO5_L3_HDR_PADDING);
|
||||
}
|
||||
|
||||
static bool ath12k_hw_qcn9274_compact_rx_desc_encrypt_valid(struct hal_rx_desc *desc)
|
||||
{
|
||||
return !!le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info4,
|
||||
RX_MPDU_START_INFO4_ENCRYPT_INFO_VALID);
|
||||
}
|
||||
|
||||
static u32 ath12k_hw_qcn9274_compact_rx_desc_get_encrypt_type(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info2,
|
||||
RX_MPDU_START_INFO2_ENC_TYPE);
|
||||
}
|
||||
|
||||
static u8 ath12k_hw_qcn9274_compact_rx_desc_get_decap_type(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info11,
|
||||
RX_MSDU_END_INFO11_DECAP_FORMAT);
|
||||
}
|
||||
|
||||
static u8 ath12k_hw_qcn9274_compact_rx_desc_get_mesh_ctl(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le32_get_bits(desc->u.qcn9274.msdu_end.info11,
|
||||
RX_MSDU_END_INFO11_MESH_CTRL_PRESENT);
|
||||
}
|
||||
|
||||
static bool
|
||||
ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_seq_ctl_vld(struct hal_rx_desc *desc)
|
||||
{
|
||||
return !!le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info4,
|
||||
RX_MPDU_START_INFO4_MPDU_SEQ_CTRL_VALID);
|
||||
}
|
||||
|
||||
static bool ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_fc_valid(struct hal_rx_desc *desc)
|
||||
{
|
||||
return !!le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info4,
|
||||
RX_MPDU_START_INFO4_MPDU_FCTRL_VALID);
|
||||
}
|
||||
|
||||
static u16
|
||||
ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_start_seq_no(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info4,
|
||||
RX_MPDU_START_INFO4_MPDU_SEQ_NUM);
|
||||
}
|
||||
|
||||
static u16 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_len(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info10,
|
||||
RX_MSDU_END_INFO10_MSDU_LENGTH);
|
||||
}
|
||||
|
||||
static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_sgi(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
|
||||
RX_MSDU_END_INFO12_SGI);
|
||||
}
|
||||
|
||||
static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_rate_mcs(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
|
||||
RX_MSDU_END_INFO12_RATE_MCS);
|
||||
}
|
||||
|
||||
static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_rx_bw(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
|
||||
RX_MSDU_END_INFO12_RECV_BW);
|
||||
}
|
||||
|
||||
static u32 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_freq(struct hal_rx_desc *desc)
|
||||
{
|
||||
return __le32_to_cpu(desc->u.qcn9274_compact.msdu_end.phy_meta_data);
|
||||
}
|
||||
|
||||
static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_pkt_type(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
|
||||
RX_MSDU_END_INFO12_PKT_TYPE);
|
||||
}
|
||||
|
||||
static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_nss(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le32_get_bits(desc->u.qcn9274_compact.msdu_end.info12,
|
||||
RX_MSDU_END_QCN9274_INFO12_MIMO_SS_BITMAP);
|
||||
}
|
||||
|
||||
static u8 ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_tid(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le16_get_bits(desc->u.qcn9274_compact.msdu_end.info5,
|
||||
RX_MSDU_END_QCN9274_INFO5_TID);
|
||||
}
|
||||
|
||||
static u16 ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_peer_id(struct hal_rx_desc *desc)
|
||||
{
|
||||
return __le16_to_cpu(desc->u.qcn9274_compact.mpdu_start.sw_peer_id);
|
||||
}
|
||||
|
||||
static void ath12k_hw_qcn9274_compact_rx_desc_copy_end_tlv(struct hal_rx_desc *fdesc,
|
||||
struct hal_rx_desc *ldesc)
|
||||
{
|
||||
fdesc->u.qcn9274_compact.msdu_end = ldesc->u.qcn9274_compact.msdu_end;
|
||||
}
|
||||
|
||||
static u32 ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_ppdu_id(struct hal_rx_desc *desc)
|
||||
{
|
||||
return __le16_to_cpu(desc->u.qcn9274_compact.mpdu_start.phy_ppdu_id);
|
||||
}
|
||||
|
||||
static void
|
||||
ath12k_hw_qcn9274_compact_rx_desc_set_msdu_len(struct hal_rx_desc *desc, u16 len)
|
||||
{
|
||||
u32 info = __le32_to_cpu(desc->u.qcn9274_compact.msdu_end.info10);
|
||||
|
||||
info = u32_replace_bits(info, len, RX_MSDU_END_INFO10_MSDU_LENGTH);
|
||||
desc->u.qcn9274_compact.msdu_end.info10 = __cpu_to_le32(info);
|
||||
}
|
||||
|
||||
static u8 *ath12k_hw_qcn9274_compact_rx_desc_get_msdu_payload(struct hal_rx_desc *desc)
|
||||
{
|
||||
return &desc->u.qcn9274_compact.msdu_payload[0];
|
||||
}
|
||||
|
||||
static u32 ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_start_offset(void)
|
||||
{
|
||||
return offsetof(struct hal_rx_desc_qcn9274_compact, mpdu_start);
|
||||
}
|
||||
|
||||
static u32 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_end_offset(void)
|
||||
{
|
||||
return offsetof(struct hal_rx_desc_qcn9274_compact, msdu_end);
|
||||
}
|
||||
|
||||
static bool ath12k_hw_qcn9274_compact_rx_desc_mac_addr2_valid(struct hal_rx_desc *desc)
|
||||
{
|
||||
return __le32_to_cpu(desc->u.qcn9274_compact.mpdu_start.info4) &
|
||||
RX_MPDU_START_INFO4_MAC_ADDR2_VALID;
|
||||
}
|
||||
|
||||
static u8 *ath12k_hw_qcn9274_compact_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
|
||||
{
|
||||
return desc->u.qcn9274_compact.mpdu_start.addr2;
|
||||
}
|
||||
|
||||
static bool ath12k_hw_qcn9274_compact_rx_desc_is_da_mcbc(struct hal_rx_desc *desc)
|
||||
{
|
||||
return __le32_to_cpu(desc->u.qcn9274_compact.mpdu_start.info6) &
|
||||
RX_MPDU_START_INFO6_MCAST_BCAST;
|
||||
}
|
||||
|
||||
static void ath12k_hw_qcn9274_compact_rx_desc_get_dot11_hdr(struct hal_rx_desc *desc,
|
||||
struct ieee80211_hdr *hdr)
|
||||
{
|
||||
hdr->frame_control = desc->u.qcn9274_compact.mpdu_start.frame_ctrl;
|
||||
hdr->duration_id = desc->u.qcn9274_compact.mpdu_start.duration;
|
||||
ether_addr_copy(hdr->addr1, desc->u.qcn9274_compact.mpdu_start.addr1);
|
||||
ether_addr_copy(hdr->addr2, desc->u.qcn9274_compact.mpdu_start.addr2);
|
||||
ether_addr_copy(hdr->addr3, desc->u.qcn9274_compact.mpdu_start.addr3);
|
||||
if (__le32_to_cpu(desc->u.qcn9274_compact.mpdu_start.info4) &
|
||||
RX_MPDU_START_INFO4_MAC_ADDR4_VALID) {
|
||||
ether_addr_copy(hdr->addr4, desc->u.qcn9274_compact.mpdu_start.addr4);
|
||||
}
|
||||
hdr->seq_ctrl = desc->u.qcn9274_compact.mpdu_start.seq_ctrl;
|
||||
}
|
||||
|
||||
static void
|
||||
ath12k_hw_qcn9274_compact_rx_desc_get_crypto_hdr(struct hal_rx_desc *desc,
|
||||
u8 *crypto_hdr,
|
||||
enum hal_encrypt_type enctype)
|
||||
{
|
||||
unsigned int key_id;
|
||||
|
||||
switch (enctype) {
|
||||
case HAL_ENCRYPT_TYPE_OPEN:
|
||||
return;
|
||||
case HAL_ENCRYPT_TYPE_TKIP_NO_MIC:
|
||||
case HAL_ENCRYPT_TYPE_TKIP_MIC:
|
||||
crypto_hdr[0] =
|
||||
HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274_compact.mpdu_start.pn[0]);
|
||||
crypto_hdr[1] = 0;
|
||||
crypto_hdr[2] =
|
||||
HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcn9274_compact.mpdu_start.pn[0]);
|
||||
break;
|
||||
case HAL_ENCRYPT_TYPE_CCMP_128:
|
||||
case HAL_ENCRYPT_TYPE_CCMP_256:
|
||||
case HAL_ENCRYPT_TYPE_GCMP_128:
|
||||
case HAL_ENCRYPT_TYPE_AES_GCMP_256:
|
||||
crypto_hdr[0] =
|
||||
HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcn9274_compact.mpdu_start.pn[0]);
|
||||
crypto_hdr[1] =
|
||||
HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274_compact.mpdu_start.pn[0]);
|
||||
crypto_hdr[2] = 0;
|
||||
break;
|
||||
case HAL_ENCRYPT_TYPE_WEP_40:
|
||||
case HAL_ENCRYPT_TYPE_WEP_104:
|
||||
case HAL_ENCRYPT_TYPE_WEP_128:
|
||||
case HAL_ENCRYPT_TYPE_WAPI_GCM_SM4:
|
||||
case HAL_ENCRYPT_TYPE_WAPI:
|
||||
return;
|
||||
}
|
||||
key_id = le32_get_bits(desc->u.qcn9274_compact.mpdu_start.info5,
|
||||
RX_MPDU_START_INFO5_KEY_ID);
|
||||
crypto_hdr[3] = 0x20 | (key_id << 6);
|
||||
crypto_hdr[4] =
|
||||
HAL_RX_MPDU_INFO_PN_GET_BYTE3(desc->u.qcn9274_compact.mpdu_start.pn[0]);
|
||||
crypto_hdr[5] =
|
||||
HAL_RX_MPDU_INFO_PN_GET_BYTE4(desc->u.qcn9274_compact.mpdu_start.pn[0]);
|
||||
crypto_hdr[6] =
|
||||
HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcn9274_compact.mpdu_start.pn[1]);
|
||||
crypto_hdr[7] =
|
||||
HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcn9274_compact.mpdu_start.pn[1]);
|
||||
}
|
||||
|
||||
static u16 ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_frame_ctl(struct hal_rx_desc *desc)
|
||||
{
|
||||
return __le16_to_cpu(desc->u.qcn9274_compact.mpdu_start.frame_ctrl);
|
||||
}
|
||||
|
||||
static bool ath12k_hw_qcn9274_compact_dp_rx_h_msdu_done(struct hal_rx_desc *desc)
|
||||
{
|
||||
return !!le32_get_bits(desc->u.qcn9274_compact.msdu_end.info14,
|
||||
RX_MSDU_END_INFO14_MSDU_DONE);
|
||||
}
|
||||
|
||||
static bool ath12k_hw_qcn9274_compact_dp_rx_h_l4_cksum_fail(struct hal_rx_desc *desc)
|
||||
{
|
||||
return !!le32_get_bits(desc->u.qcn9274_compact.msdu_end.info13,
|
||||
RX_MSDU_END_INFO13_TCP_UDP_CKSUM_FAIL);
|
||||
}
|
||||
|
||||
static bool ath12k_hw_qcn9274_compact_dp_rx_h_ip_cksum_fail(struct hal_rx_desc *desc)
|
||||
{
|
||||
return !!le32_get_bits(desc->u.qcn9274_compact.msdu_end.info13,
|
||||
RX_MSDU_END_INFO13_IP_CKSUM_FAIL);
|
||||
}
|
||||
|
||||
static bool ath12k_hw_qcn9274_compact_dp_rx_h_is_decrypted(struct hal_rx_desc *desc)
|
||||
{
|
||||
return (le32_get_bits(desc->u.qcn9274_compact.msdu_end.info14,
|
||||
RX_MSDU_END_INFO14_DECRYPT_STATUS_CODE) ==
|
||||
RX_DESC_DECRYPT_STATUS_CODE_OK);
|
||||
}
|
||||
|
||||
static u32 ath12k_hw_qcn9274_compact_dp_rx_h_mpdu_err(struct hal_rx_desc *desc)
|
||||
{
|
||||
u32 info = __le32_to_cpu(desc->u.qcn9274_compact.msdu_end.info13);
|
||||
u32 errmap = 0;
|
||||
|
||||
if (info & RX_MSDU_END_INFO13_FCS_ERR)
|
||||
errmap |= HAL_RX_MPDU_ERR_FCS;
|
||||
|
||||
if (info & RX_MSDU_END_INFO13_DECRYPT_ERR)
|
||||
errmap |= HAL_RX_MPDU_ERR_DECRYPT;
|
||||
|
||||
if (info & RX_MSDU_END_INFO13_TKIP_MIC_ERR)
|
||||
errmap |= HAL_RX_MPDU_ERR_TKIP_MIC;
|
||||
|
||||
if (info & RX_MSDU_END_INFO13_A_MSDU_ERROR)
|
||||
errmap |= HAL_RX_MPDU_ERR_AMSDU_ERR;
|
||||
|
||||
if (info & RX_MSDU_END_INFO13_OVERFLOW_ERR)
|
||||
errmap |= HAL_RX_MPDU_ERR_OVERFLOW;
|
||||
|
||||
if (info & RX_MSDU_END_INFO13_MSDU_LEN_ERR)
|
||||
errmap |= HAL_RX_MPDU_ERR_MSDU_LEN;
|
||||
|
||||
if (info & RX_MSDU_END_INFO13_MPDU_LEN_ERR)
|
||||
errmap |= HAL_RX_MPDU_ERR_MPDU_LEN;
|
||||
|
||||
return errmap;
|
||||
}
|
||||
|
||||
static u32 ath12k_hw_qcn9274_compact_get_rx_desc_size(void)
|
||||
{
|
||||
return sizeof(struct hal_rx_desc_qcn9274_compact);
|
||||
}
|
||||
|
||||
static u8 ath12k_hw_qcn9274_compact_rx_desc_get_msdu_src_link(struct hal_rx_desc *desc)
|
||||
{
|
||||
return le64_get_bits(desc->u.qcn9274_compact.msdu_end.msdu_end_tag,
|
||||
RX_MSDU_END_64_TLV_SRC_LINK_ID);
|
||||
}
|
||||
|
||||
const struct hal_rx_ops hal_rx_qcn9274_compact_ops = {
|
||||
.rx_desc_get_first_msdu = ath12k_hw_qcn9274_compact_rx_desc_get_first_msdu,
|
||||
.rx_desc_get_last_msdu = ath12k_hw_qcn9274_compact_rx_desc_get_last_msdu,
|
||||
.rx_desc_get_l3_pad_bytes = ath12k_hw_qcn9274_compact_rx_desc_get_l3_pad_bytes,
|
||||
.rx_desc_encrypt_valid = ath12k_hw_qcn9274_compact_rx_desc_encrypt_valid,
|
||||
.rx_desc_get_encrypt_type = ath12k_hw_qcn9274_compact_rx_desc_get_encrypt_type,
|
||||
.rx_desc_get_decap_type = ath12k_hw_qcn9274_compact_rx_desc_get_decap_type,
|
||||
.rx_desc_get_mesh_ctl = ath12k_hw_qcn9274_compact_rx_desc_get_mesh_ctl,
|
||||
.rx_desc_get_mpdu_seq_ctl_vld =
|
||||
ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_seq_ctl_vld,
|
||||
.rx_desc_get_mpdu_fc_valid = ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_fc_valid,
|
||||
.rx_desc_get_mpdu_start_seq_no =
|
||||
ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_start_seq_no,
|
||||
.rx_desc_get_msdu_len = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_len,
|
||||
.rx_desc_get_msdu_sgi = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_sgi,
|
||||
.rx_desc_get_msdu_rate_mcs = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_rate_mcs,
|
||||
.rx_desc_get_msdu_rx_bw = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_rx_bw,
|
||||
.rx_desc_get_msdu_freq = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_freq,
|
||||
.rx_desc_get_msdu_pkt_type = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_pkt_type,
|
||||
.rx_desc_get_msdu_nss = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_nss,
|
||||
.rx_desc_get_mpdu_tid = ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_tid,
|
||||
.rx_desc_get_mpdu_peer_id = ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_peer_id,
|
||||
.rx_desc_copy_end_tlv = ath12k_hw_qcn9274_compact_rx_desc_copy_end_tlv,
|
||||
.rx_desc_get_mpdu_ppdu_id = ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_ppdu_id,
|
||||
.rx_desc_set_msdu_len = ath12k_hw_qcn9274_compact_rx_desc_set_msdu_len,
|
||||
.rx_desc_get_msdu_payload = ath12k_hw_qcn9274_compact_rx_desc_get_msdu_payload,
|
||||
.rx_desc_get_mpdu_start_offset =
|
||||
ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_start_offset,
|
||||
.rx_desc_get_msdu_end_offset =
|
||||
ath12k_hw_qcn9274_compact_rx_desc_get_msdu_end_offset,
|
||||
.rx_desc_mac_addr2_valid = ath12k_hw_qcn9274_compact_rx_desc_mac_addr2_valid,
|
||||
.rx_desc_mpdu_start_addr2 = ath12k_hw_qcn9274_compact_rx_desc_mpdu_start_addr2,
|
||||
.rx_desc_is_da_mcbc = ath12k_hw_qcn9274_compact_rx_desc_is_da_mcbc,
|
||||
.rx_desc_get_dot11_hdr = ath12k_hw_qcn9274_compact_rx_desc_get_dot11_hdr,
|
||||
.rx_desc_get_crypto_header = ath12k_hw_qcn9274_compact_rx_desc_get_crypto_hdr,
|
||||
.rx_desc_get_mpdu_frame_ctl =
|
||||
ath12k_hw_qcn9274_compact_rx_desc_get_mpdu_frame_ctl,
|
||||
.dp_rx_h_msdu_done = ath12k_hw_qcn9274_compact_dp_rx_h_msdu_done,
|
||||
.dp_rx_h_l4_cksum_fail = ath12k_hw_qcn9274_compact_dp_rx_h_l4_cksum_fail,
|
||||
.dp_rx_h_ip_cksum_fail = ath12k_hw_qcn9274_compact_dp_rx_h_ip_cksum_fail,
|
||||
.dp_rx_h_is_decrypted = ath12k_hw_qcn9274_compact_dp_rx_h_is_decrypted,
|
||||
.dp_rx_h_mpdu_err = ath12k_hw_qcn9274_compact_dp_rx_h_mpdu_err,
|
||||
.rx_desc_get_desc_size = ath12k_hw_qcn9274_compact_get_rx_desc_size,
|
||||
.rx_desc_get_msdu_src_link_id =
|
||||
ath12k_hw_qcn9274_compact_rx_desc_get_msdu_src_link,
|
||||
};
|
||||
|
||||
const struct hal_ops hal_qcn9274_ops = {
|
||||
.create_srng_config = ath12k_hal_srng_create_config_qcn9274,
|
||||
.tcl_to_wbm_rbm_map = ath12k_hal_qcn9274_tcl_to_wbm_rbm_map,
|
||||
.rxdma_ring_wmask_rx_mpdu_start = ath12k_hal_qcn9274_rx_mpdu_start_wmask_get,
|
||||
.rxdma_ring_wmask_rx_msdu_end = ath12k_hal_qcn9274_rx_msdu_end_wmask_get,
|
||||
.get_hal_rx_compact_ops = ath12k_hal_qcn9274_get_hal_rx_compact_ops,
|
||||
};
|
||||
|
||||
static bool ath12k_hw_wcn7850_rx_desc_get_first_msdu(struct hal_rx_desc *desc)
|
||||
|
@ -1134,7 +1513,17 @@ static u32 ath12k_hw_wcn7850_dp_rx_h_mpdu_err(struct hal_rx_desc *desc)
|
|||
return errmap;
|
||||
}
|
||||
|
||||
const struct hal_ops hal_wcn7850_ops = {
|
||||
static u32 ath12k_hw_wcn7850_get_rx_desc_size(void)
|
||||
{
|
||||
return sizeof(struct hal_rx_desc_wcn7850);
|
||||
}
|
||||
|
||||
static u8 ath12k_hw_wcn7850_rx_desc_get_msdu_src_link(struct hal_rx_desc *desc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct hal_rx_ops hal_rx_wcn7850_ops = {
|
||||
.rx_desc_get_first_msdu = ath12k_hw_wcn7850_rx_desc_get_first_msdu,
|
||||
.rx_desc_get_last_msdu = ath12k_hw_wcn7850_rx_desc_get_last_msdu,
|
||||
.rx_desc_get_l3_pad_bytes = ath12k_hw_wcn7850_rx_desc_get_l3_pad_bytes,
|
||||
|
@ -1167,13 +1556,21 @@ const struct hal_ops hal_wcn7850_ops = {
|
|||
.rx_desc_get_dot11_hdr = ath12k_hw_wcn7850_rx_desc_get_dot11_hdr,
|
||||
.rx_desc_get_crypto_header = ath12k_hw_wcn7850_rx_desc_get_crypto_hdr,
|
||||
.rx_desc_get_mpdu_frame_ctl = ath12k_hw_wcn7850_rx_desc_get_mpdu_frame_ctl,
|
||||
.create_srng_config = ath12k_hal_srng_create_config_wcn7850,
|
||||
.tcl_to_wbm_rbm_map = ath12k_hal_wcn7850_tcl_to_wbm_rbm_map,
|
||||
.dp_rx_h_msdu_done = ath12k_hw_wcn7850_dp_rx_h_msdu_done,
|
||||
.dp_rx_h_l4_cksum_fail = ath12k_hw_wcn7850_dp_rx_h_l4_cksum_fail,
|
||||
.dp_rx_h_ip_cksum_fail = ath12k_hw_wcn7850_dp_rx_h_ip_cksum_fail,
|
||||
.dp_rx_h_is_decrypted = ath12k_hw_wcn7850_dp_rx_h_is_decrypted,
|
||||
.dp_rx_h_mpdu_err = ath12k_hw_wcn7850_dp_rx_h_mpdu_err,
|
||||
.rx_desc_get_desc_size = ath12k_hw_wcn7850_get_rx_desc_size,
|
||||
.rx_desc_get_msdu_src_link_id = ath12k_hw_wcn7850_rx_desc_get_msdu_src_link,
|
||||
};
|
||||
|
||||
const struct hal_ops hal_wcn7850_ops = {
|
||||
.create_srng_config = ath12k_hal_srng_create_config_wcn7850,
|
||||
.tcl_to_wbm_rbm_map = ath12k_hal_wcn7850_tcl_to_wbm_rbm_map,
|
||||
.rxdma_ring_wmask_rx_mpdu_start = NULL,
|
||||
.rxdma_ring_wmask_rx_msdu_end = NULL,
|
||||
.get_hal_rx_compact_ops = NULL,
|
||||
};
|
||||
|
||||
static int ath12k_hal_alloc_cont_rdp(struct ath12k_base *ab)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_HAL_H
|
||||
|
@ -1023,6 +1023,8 @@ struct ath12k_hal {
|
|||
/* shadow register configuration */
|
||||
u32 shadow_reg_addr[HAL_SHADOW_NUM_REGS];
|
||||
int num_shadow_reg_configured;
|
||||
|
||||
u32 hal_desc_sz;
|
||||
};
|
||||
|
||||
/* Maps WBM ring number and Return Buffer Manager Id per TCL ring */
|
||||
|
@ -1031,7 +1033,7 @@ struct ath12k_hal_tcl_to_wbm_rbm_map {
|
|||
u8 rbm_id;
|
||||
};
|
||||
|
||||
struct hal_ops {
|
||||
struct hal_rx_ops {
|
||||
bool (*rx_desc_get_first_msdu)(struct hal_rx_desc *desc);
|
||||
bool (*rx_desc_get_last_msdu)(struct hal_rx_desc *desc);
|
||||
u8 (*rx_desc_get_l3_pad_bytes)(struct hal_rx_desc *desc);
|
||||
|
@ -1070,18 +1072,30 @@ struct hal_ops {
|
|||
void (*rx_desc_get_crypto_header)(struct hal_rx_desc *desc,
|
||||
u8 *crypto_hdr,
|
||||
enum hal_encrypt_type enctype);
|
||||
int (*create_srng_config)(struct ath12k_base *ab);
|
||||
bool (*dp_rx_h_msdu_done)(struct hal_rx_desc *desc);
|
||||
bool (*dp_rx_h_l4_cksum_fail)(struct hal_rx_desc *desc);
|
||||
bool (*dp_rx_h_ip_cksum_fail)(struct hal_rx_desc *desc);
|
||||
bool (*dp_rx_h_is_decrypted)(struct hal_rx_desc *desc);
|
||||
u32 (*dp_rx_h_mpdu_err)(struct hal_rx_desc *desc);
|
||||
u32 (*rx_desc_get_desc_size)(void);
|
||||
u8 (*rx_desc_get_msdu_src_link_id)(struct hal_rx_desc *desc);
|
||||
};
|
||||
|
||||
struct hal_ops {
|
||||
int (*create_srng_config)(struct ath12k_base *ab);
|
||||
u16 (*rxdma_ring_wmask_rx_mpdu_start)(void);
|
||||
u32 (*rxdma_ring_wmask_rx_msdu_end)(void);
|
||||
const struct hal_rx_ops *(*get_hal_rx_compact_ops)(void);
|
||||
const struct ath12k_hal_tcl_to_wbm_rbm_map *tcl_to_wbm_rbm_map;
|
||||
};
|
||||
|
||||
extern const struct hal_ops hal_qcn9274_ops;
|
||||
extern const struct hal_ops hal_wcn7850_ops;
|
||||
|
||||
extern const struct hal_rx_ops hal_rx_qcn9274_ops;
|
||||
extern const struct hal_rx_ops hal_rx_qcn9274_compact_ops;
|
||||
extern const struct hal_rx_ops hal_rx_wcn7850_ops;
|
||||
|
||||
u32 ath12k_hal_reo_qdesc_size(u32 ba_window_size, u8 tid);
|
||||
void ath12k_hal_reo_qdesc_setup(struct hal_rx_reo_queue *qdesc,
|
||||
int tid, u32 ba_window_size,
|
||||
|
|
|
@ -2500,13 +2500,13 @@ struct hal_rx_reo_queue {
|
|||
#define HAL_REO_UPD_RX_QUEUE_INFO1_PN_HANDLE_ENABLE BIT(30)
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO1_IGNORE_AMPDU_FLG BIT(31)
|
||||
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO2_BA_WINDOW_SIZE GENMASK(7, 0)
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO2_PN_SIZE GENMASK(9, 8)
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO2_SVLD BIT(10)
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO2_SSN GENMASK(22, 11)
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO2_SEQ_2K_ERR BIT(23)
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO2_PN_ERR BIT(24)
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO2_PN_VALID BIT(25)
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO2_BA_WINDOW_SIZE GENMASK(9, 0)
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO2_PN_SIZE GENMASK(11, 10)
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO2_SVLD BIT(12)
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO2_SSN GENMASK(24, 13)
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO2_SEQ_2K_ERR BIT(25)
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO2_PN_ERR BIT(26)
|
||||
#define HAL_REO_UPD_RX_QUEUE_INFO2_PN_VALID BIT(27)
|
||||
|
||||
struct hal_reo_update_rx_queue {
|
||||
struct hal_reo_cmd_hdr cmd;
|
||||
|
@ -2517,6 +2517,12 @@ struct hal_reo_update_rx_queue {
|
|||
__le32 pn[4];
|
||||
} __packed;
|
||||
|
||||
struct hal_rx_reo_queue_1k {
|
||||
struct hal_desc_header desc_hdr;
|
||||
__le32 rx_bitmap_1023_288[23];
|
||||
__le32 reserved[8];
|
||||
} __packed;
|
||||
|
||||
#define HAL_REO_UNBLOCK_CACHE_INFO0_UNBLK_CACHE BIT(0)
|
||||
#define HAL_REO_UNBLOCK_CACHE_INFO0_RESOURCE_IDX GENMASK(2, 1)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
|
@ -247,7 +247,7 @@ int ath12k_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
|
|||
case HAL_REO_CMD_UNBLOCK_CACHE:
|
||||
case HAL_REO_CMD_FLUSH_TIMEOUT_LIST:
|
||||
ath12k_warn(ab, "Unsupported reo command %d\n", type);
|
||||
ret = -ENOTSUPP;
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
default:
|
||||
ath12k_warn(ab, "Unknown reo command %d\n", type);
|
||||
|
@ -688,23 +688,28 @@ void ath12k_hal_reo_update_rx_reo_queue_status(struct ath12k_base *ab,
|
|||
|
||||
u32 ath12k_hal_reo_qdesc_size(u32 ba_window_size, u8 tid)
|
||||
{
|
||||
u32 num_ext_desc;
|
||||
u32 num_ext_desc, num_1k_desc = 0;
|
||||
|
||||
if (ba_window_size <= 1) {
|
||||
if (tid != HAL_DESC_REO_NON_QOS_TID)
|
||||
num_ext_desc = 1;
|
||||
else
|
||||
num_ext_desc = 0;
|
||||
|
||||
} else if (ba_window_size <= 105) {
|
||||
num_ext_desc = 1;
|
||||
} else if (ba_window_size <= 210) {
|
||||
num_ext_desc = 2;
|
||||
} else {
|
||||
} else if (ba_window_size <= 256) {
|
||||
num_ext_desc = 3;
|
||||
} else {
|
||||
num_ext_desc = 10;
|
||||
num_1k_desc = 1;
|
||||
}
|
||||
|
||||
return sizeof(struct hal_rx_reo_queue) +
|
||||
(num_ext_desc * sizeof(struct hal_rx_reo_queue_ext));
|
||||
(num_ext_desc * sizeof(struct hal_rx_reo_queue_ext)) +
|
||||
(num_1k_desc * sizeof(struct hal_rx_reo_queue_1k));
|
||||
}
|
||||
|
||||
void ath12k_hal_reo_qdesc_setup(struct hal_rx_reo_queue *qdesc,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
|
@ -897,7 +897,6 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.reoq_lut_support = false,
|
||||
.supports_shadow_regs = false,
|
||||
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9274),
|
||||
.num_tcl_banks = 48,
|
||||
.max_tx_ring = 4,
|
||||
|
||||
|
@ -914,6 +913,13 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.rfkill_on_level = 0,
|
||||
|
||||
.rddm_size = 0,
|
||||
|
||||
.def_num_link = 0,
|
||||
.max_mlo_peer = 256,
|
||||
|
||||
.otp_board_id_register = QCN9274_QFPROM_RAW_RFA_PDET_ROW13_LSB,
|
||||
|
||||
.supports_sta_ps = false,
|
||||
},
|
||||
{
|
||||
.name = "wcn7850 hw2.0",
|
||||
|
@ -950,7 +956,10 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.vdev_start_delay = true,
|
||||
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP),
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_DEVICE) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO),
|
||||
.supports_monitor = false,
|
||||
|
||||
.idle_ps = true,
|
||||
|
@ -960,7 +969,6 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.reoq_lut_support = false,
|
||||
.supports_shadow_regs = true,
|
||||
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_wcn7850),
|
||||
.num_tcl_banks = 7,
|
||||
.max_tx_ring = 3,
|
||||
|
||||
|
@ -978,6 +986,13 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.rfkill_on_level = 1,
|
||||
|
||||
.rddm_size = 0x780000,
|
||||
|
||||
.def_num_link = 2,
|
||||
.max_mlo_peer = 32,
|
||||
|
||||
.otp_board_id_register = 0,
|
||||
|
||||
.supports_sta_ps = true,
|
||||
},
|
||||
{
|
||||
.name = "qcn9274 hw2.0",
|
||||
|
@ -987,7 +1002,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.board_size = 256 * 1024,
|
||||
.cal_offset = 128 * 1024,
|
||||
},
|
||||
.max_radios = 1,
|
||||
.max_radios = 2,
|
||||
.single_pdev_only = false,
|
||||
.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9274,
|
||||
.internal_sleep_clock = false,
|
||||
|
@ -1023,7 +1038,6 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.reoq_lut_support = false,
|
||||
.supports_shadow_regs = false,
|
||||
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9274),
|
||||
.num_tcl_banks = 48,
|
||||
.max_tx_ring = 4,
|
||||
|
||||
|
@ -1040,6 +1054,13 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
|||
.rfkill_on_level = 0,
|
||||
|
||||
.rddm_size = 0,
|
||||
|
||||
.def_num_link = 0,
|
||||
.max_mlo_peer = 256,
|
||||
|
||||
.otp_board_id_register = QCN9274_QFPROM_RAW_RFA_PDET_ROW13_LSB,
|
||||
|
||||
.supports_sta_ps = false,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_HW_H
|
||||
|
@ -17,19 +17,30 @@
|
|||
/* Num VDEVS per radio */
|
||||
#define TARGET_NUM_VDEVS (16 + 1)
|
||||
|
||||
#define TARGET_NUM_PEERS_PDEV (512 + TARGET_NUM_VDEVS)
|
||||
#define TARGET_NUM_PEERS_PDEV_SINGLE (TARGET_NUM_STATIONS_SINGLE + \
|
||||
TARGET_NUM_VDEVS)
|
||||
#define TARGET_NUM_PEERS_PDEV_DBS (TARGET_NUM_STATIONS_DBS + \
|
||||
TARGET_NUM_VDEVS)
|
||||
#define TARGET_NUM_PEERS_PDEV_DBS_SBS (TARGET_NUM_STATIONS_DBS_SBS + \
|
||||
TARGET_NUM_VDEVS)
|
||||
|
||||
/* Num of peers for Single Radio mode */
|
||||
#define TARGET_NUM_PEERS_SINGLE (TARGET_NUM_PEERS_PDEV)
|
||||
#define TARGET_NUM_PEERS_SINGLE (TARGET_NUM_PEERS_PDEV_SINGLE)
|
||||
|
||||
/* Num of peers for DBS */
|
||||
#define TARGET_NUM_PEERS_DBS (2 * TARGET_NUM_PEERS_PDEV)
|
||||
#define TARGET_NUM_PEERS_DBS (2 * TARGET_NUM_PEERS_PDEV_DBS)
|
||||
|
||||
/* Num of peers for DBS_SBS */
|
||||
#define TARGET_NUM_PEERS_DBS_SBS (3 * TARGET_NUM_PEERS_PDEV)
|
||||
#define TARGET_NUM_PEERS_DBS_SBS (3 * TARGET_NUM_PEERS_PDEV_DBS_SBS)
|
||||
|
||||
/* Max num of stations (per radio) */
|
||||
#define TARGET_NUM_STATIONS 512
|
||||
/* Max num of stations for Single Radio mode */
|
||||
#define TARGET_NUM_STATIONS_SINGLE 512
|
||||
|
||||
/* Max num of stations for DBS */
|
||||
#define TARGET_NUM_STATIONS_DBS 128
|
||||
|
||||
/* Max num of stations for DBS_SBS */
|
||||
#define TARGET_NUM_STATIONS_DBS_SBS 128
|
||||
|
||||
#define TARGET_NUM_PEERS(x) TARGET_NUM_PEERS_##x
|
||||
#define TARGET_NUM_PEER_KEYS 2
|
||||
|
@ -66,6 +77,8 @@
|
|||
#define TARGET_NUM_WDS_ENTRIES 32
|
||||
#define TARGET_DMA_BURST_SIZE 1
|
||||
#define TARGET_RX_BATCHMODE 1
|
||||
#define TARGET_RX_PEER_METADATA_VER_V1A 2
|
||||
#define TARGET_RX_PEER_METADATA_VER_V1B 3
|
||||
|
||||
#define ATH12K_HW_MAX_QUEUES 4
|
||||
#define ATH12K_QUEUE_LEN 4096
|
||||
|
@ -174,7 +187,6 @@ struct ath12k_hw_params {
|
|||
bool reoq_lut_support:1;
|
||||
bool supports_shadow_regs:1;
|
||||
|
||||
u32 hal_desc_sz;
|
||||
u32 num_tcl_banks;
|
||||
u32 max_tx_ring;
|
||||
|
||||
|
@ -192,6 +204,13 @@ struct ath12k_hw_params {
|
|||
u32 rfkill_on_level;
|
||||
|
||||
u32 rddm_size;
|
||||
|
||||
u8 def_num_link;
|
||||
u16 max_mlo_peer;
|
||||
|
||||
u32 otp_board_id_register;
|
||||
|
||||
bool supports_sta_ps;
|
||||
};
|
||||
|
||||
struct ath12k_hw_ops {
|
||||
|
@ -242,10 +261,16 @@ enum ath12k_bd_ie_board_type {
|
|||
ATH12K_BD_IE_BOARD_DATA = 1,
|
||||
};
|
||||
|
||||
enum ath12k_bd_ie_regdb_type {
|
||||
ATH12K_BD_IE_REGDB_NAME = 0,
|
||||
ATH12K_BD_IE_REGDB_DATA = 1,
|
||||
};
|
||||
|
||||
enum ath12k_bd_ie_type {
|
||||
/* contains sub IEs of enum ath12k_bd_ie_board_type */
|
||||
ATH12K_BD_IE_BOARD = 0,
|
||||
ATH12K_BD_IE_BOARD_EXT = 1,
|
||||
/* contains sub IEs of enum ath12k_bd_ie_regdb_type */
|
||||
ATH12K_BD_IE_REGDB = 1,
|
||||
};
|
||||
|
||||
struct ath12k_hw_regs {
|
||||
|
@ -315,6 +340,18 @@ struct ath12k_hw_regs {
|
|||
u32 hal_reo_status_ring_base;
|
||||
};
|
||||
|
||||
static inline const char *ath12k_bd_ie_type_str(enum ath12k_bd_ie_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case ATH12K_BD_IE_BOARD:
|
||||
return "board data";
|
||||
case ATH12K_BD_IE_REGDB:
|
||||
return "regdb data";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
int ath12k_hw_init(struct ath12k_base *ab);
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_MAC_H
|
||||
|
@ -12,6 +12,8 @@
|
|||
|
||||
struct ath12k;
|
||||
struct ath12k_base;
|
||||
struct ath12k_hw;
|
||||
struct ath12k_pdev_map;
|
||||
|
||||
struct ath12k_generic_iter {
|
||||
struct ath12k *ar;
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/msi.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
|
@ -13,6 +14,8 @@
|
|||
#include "pci.h"
|
||||
|
||||
#define MHI_TIMEOUT_DEFAULT_MS 90000
|
||||
#define OTP_INVALID_BOARD_ID 0xFFFF
|
||||
#define OTP_VALID_DUALMAC_BOARD_ID_MASK 0x1000
|
||||
|
||||
static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
|
||||
{
|
||||
|
@ -358,23 +361,60 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci)
|
|||
{
|
||||
struct ath12k_base *ab = ab_pci->ab;
|
||||
struct mhi_controller *mhi_ctrl;
|
||||
unsigned int board_id;
|
||||
int ret;
|
||||
bool dualmac = false;
|
||||
|
||||
mhi_ctrl = mhi_alloc_controller();
|
||||
if (!mhi_ctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
ath12k_core_create_firmware_path(ab, ATH12K_AMSS_FILE,
|
||||
ab_pci->amss_path,
|
||||
sizeof(ab_pci->amss_path));
|
||||
|
||||
ab_pci->mhi_ctrl = mhi_ctrl;
|
||||
mhi_ctrl->cntrl_dev = ab->dev;
|
||||
mhi_ctrl->fw_image = ab_pci->amss_path;
|
||||
mhi_ctrl->regs = ab->mem;
|
||||
mhi_ctrl->reg_len = ab->mem_len;
|
||||
mhi_ctrl->rddm_size = ab->hw_params->rddm_size;
|
||||
|
||||
if (ab->hw_params->otp_board_id_register) {
|
||||
board_id =
|
||||
ath12k_pci_read32(ab, ab->hw_params->otp_board_id_register);
|
||||
board_id = u32_get_bits(board_id, OTP_BOARD_ID_MASK);
|
||||
|
||||
if (!board_id || (board_id == OTP_INVALID_BOARD_ID)) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"failed to read board id\n");
|
||||
} else if (board_id & OTP_VALID_DUALMAC_BOARD_ID_MASK) {
|
||||
dualmac = true;
|
||||
ab->slo_capable = false;
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"dualmac fw selected for board id: %x\n", board_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (dualmac) {
|
||||
if (ab->fw.amss_dualmac_data && ab->fw.amss_dualmac_len > 0) {
|
||||
/* use MHI firmware file from firmware-N.bin */
|
||||
mhi_ctrl->fw_data = ab->fw.amss_dualmac_data;
|
||||
mhi_ctrl->fw_sz = ab->fw.amss_dualmac_len;
|
||||
} else {
|
||||
ath12k_warn(ab, "dualmac firmware IE not present in firmware-N.bin\n");
|
||||
ret = -ENOENT;
|
||||
goto free_controller;
|
||||
}
|
||||
} else {
|
||||
if (ab->fw.amss_data && ab->fw.amss_len > 0) {
|
||||
/* use MHI firmware file from firmware-N.bin */
|
||||
mhi_ctrl->fw_data = ab->fw.amss_data;
|
||||
mhi_ctrl->fw_sz = ab->fw.amss_len;
|
||||
} else {
|
||||
/* use the old separate mhi.bin MHI firmware file */
|
||||
ath12k_core_create_firmware_path(ab, ATH12K_AMSS_FILE,
|
||||
ab_pci->amss_path,
|
||||
sizeof(ab_pci->amss_path));
|
||||
mhi_ctrl->fw_image = ab_pci->amss_path;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ath12k_mhi_get_msi(ab_pci);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to get msi for mhi\n");
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#include "core.h"
|
||||
#include "mac.h"
|
||||
#include "p2p.h"
|
||||
|
||||
static void ath12k_p2p_noa_ie_fill(u8 *data, size_t len,
|
||||
const struct ath12k_wmi_p2p_noa_info *noa)
|
||||
{
|
||||
struct ieee80211_p2p_noa_attr *noa_attr;
|
||||
u8 ctwindow = le32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_CTWIN_TU);
|
||||
bool oppps = le32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_OPP_PS);
|
||||
__le16 *noa_attr_len;
|
||||
u16 attr_len;
|
||||
u8 noa_descriptors = le32_get_bits(noa->noa_attr,
|
||||
WMI_P2P_NOA_INFO_DESC_NUM);
|
||||
int i;
|
||||
|
||||
/* P2P IE */
|
||||
data[0] = WLAN_EID_VENDOR_SPECIFIC;
|
||||
data[1] = len - 2;
|
||||
data[2] = (WLAN_OUI_WFA >> 16) & 0xff;
|
||||
data[3] = (WLAN_OUI_WFA >> 8) & 0xff;
|
||||
data[4] = (WLAN_OUI_WFA >> 0) & 0xff;
|
||||
data[5] = WLAN_OUI_TYPE_WFA_P2P;
|
||||
|
||||
/* NOA ATTR */
|
||||
data[6] = IEEE80211_P2P_ATTR_ABSENCE_NOTICE;
|
||||
noa_attr_len = (__le16 *)&data[7]; /* 2 bytes */
|
||||
noa_attr = (struct ieee80211_p2p_noa_attr *)&data[9];
|
||||
|
||||
noa_attr->index = le32_get_bits(noa->noa_attr,
|
||||
WMI_P2P_NOA_INFO_INDEX);
|
||||
noa_attr->oppps_ctwindow = ctwindow;
|
||||
if (oppps)
|
||||
noa_attr->oppps_ctwindow |= IEEE80211_P2P_OPPPS_ENABLE_BIT;
|
||||
|
||||
for (i = 0; i < noa_descriptors; i++) {
|
||||
noa_attr->desc[i].count =
|
||||
__le32_to_cpu(noa->descriptors[i].type_count);
|
||||
noa_attr->desc[i].duration = noa->descriptors[i].duration;
|
||||
noa_attr->desc[i].interval = noa->descriptors[i].interval;
|
||||
noa_attr->desc[i].start_time = noa->descriptors[i].start_time;
|
||||
}
|
||||
|
||||
attr_len = 2; /* index + oppps_ctwindow */
|
||||
attr_len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc);
|
||||
*noa_attr_len = __cpu_to_le16(attr_len);
|
||||
}
|
||||
|
||||
static size_t ath12k_p2p_noa_ie_len_compute(const struct ath12k_wmi_p2p_noa_info *noa)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
if (!(le32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_DESC_NUM)) &&
|
||||
!(le32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_OPP_PS)))
|
||||
return 0;
|
||||
|
||||
len += 1 + 1 + 4; /* EID + len + OUI */
|
||||
len += 1 + 2; /* noa attr + attr len */
|
||||
len += 1 + 1; /* index + oppps_ctwindow */
|
||||
len += le32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_DESC_NUM) *
|
||||
sizeof(struct ieee80211_p2p_noa_desc);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void ath12k_p2p_noa_ie_assign(struct ath12k_vif *arvif, void *ie,
|
||||
size_t len)
|
||||
{
|
||||
struct ath12k *ar = arvif->ar;
|
||||
|
||||
lockdep_assert_held(&ar->data_lock);
|
||||
|
||||
kfree(arvif->u.ap.noa_data);
|
||||
|
||||
arvif->u.ap.noa_data = ie;
|
||||
arvif->u.ap.noa_len = len;
|
||||
}
|
||||
|
||||
static void __ath12k_p2p_noa_update(struct ath12k_vif *arvif,
|
||||
const struct ath12k_wmi_p2p_noa_info *noa)
|
||||
{
|
||||
struct ath12k *ar = arvif->ar;
|
||||
void *ie;
|
||||
size_t len;
|
||||
|
||||
lockdep_assert_held(&ar->data_lock);
|
||||
|
||||
ath12k_p2p_noa_ie_assign(arvif, NULL, 0);
|
||||
|
||||
len = ath12k_p2p_noa_ie_len_compute(noa);
|
||||
if (!len)
|
||||
return;
|
||||
|
||||
ie = kmalloc(len, GFP_ATOMIC);
|
||||
if (!ie)
|
||||
return;
|
||||
|
||||
ath12k_p2p_noa_ie_fill(ie, len, noa);
|
||||
ath12k_p2p_noa_ie_assign(arvif, ie, len);
|
||||
}
|
||||
|
||||
void ath12k_p2p_noa_update(struct ath12k_vif *arvif,
|
||||
const struct ath12k_wmi_p2p_noa_info *noa)
|
||||
{
|
||||
struct ath12k *ar = arvif->ar;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
__ath12k_p2p_noa_update(arvif, noa);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
static void ath12k_p2p_noa_update_vdev_iter(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct ath12k_p2p_noa_arg *arg = data;
|
||||
|
||||
if (arvif->vdev_id != arg->vdev_id)
|
||||
return;
|
||||
|
||||
ath12k_p2p_noa_update(arvif, arg->noa);
|
||||
}
|
||||
|
||||
void ath12k_p2p_noa_update_by_vdev_id(struct ath12k *ar, u32 vdev_id,
|
||||
const struct ath12k_wmi_p2p_noa_info *noa)
|
||||
{
|
||||
struct ath12k_p2p_noa_arg arg = {
|
||||
.vdev_id = vdev_id,
|
||||
.noa = noa,
|
||||
};
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(ath12k_ar_to_hw(ar),
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
ath12k_p2p_noa_update_vdev_iter,
|
||||
&arg);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved..
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_P2P_H
|
||||
#define ATH12K_P2P_H
|
||||
|
||||
#include "wmi.h"
|
||||
|
||||
struct ath12k_wmi_p2p_noa_info;
|
||||
|
||||
struct ath12k_p2p_noa_arg {
|
||||
u32 vdev_id;
|
||||
const struct ath12k_wmi_p2p_noa_info *noa;
|
||||
};
|
||||
|
||||
void ath12k_p2p_noa_update(struct ath12k_vif *arvif,
|
||||
const struct ath12k_wmi_p2p_noa_info *noa);
|
||||
void ath12k_p2p_noa_update_by_vdev_id(struct ath12k *ar, u32 vdev_id,
|
||||
const struct ath12k_wmi_p2p_noa_info *noa);
|
||||
|
||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -39,6 +39,10 @@
|
|||
#define QCN9274_DEVICE_ID 0x1109
|
||||
#define WCN7850_DEVICE_ID 0x1107
|
||||
|
||||
#define PCIE_LOCAL_REG_QRTR_NODE_ID 0x1E03164
|
||||
#define DOMAIN_NUMBER_MASK GENMASK(7, 4)
|
||||
#define BUS_NUMBER_MASK GENMASK(3, 0)
|
||||
|
||||
static const struct pci_device_id ath12k_pci_id_table[] = {
|
||||
{ PCI_VDEVICE(QCOM, QCN9274_DEVICE_ID) },
|
||||
{ PCI_VDEVICE(QCOM, WCN7850_DEVICE_ID) },
|
||||
|
@ -201,18 +205,17 @@ static u32 ath12k_pci_get_window_start(struct ath12k_base *ab,
|
|||
/* If offset lies within CE register range, use 2nd window */
|
||||
else if ((offset ^ HAL_CE_WFSS_CE_REG_BASE) < WINDOW_RANGE_MASK)
|
||||
window_start = 2 * WINDOW_START;
|
||||
/* If offset lies within PCI_BAR_WINDOW0_BASE and within PCI_SOC_PCI_REG_BASE
|
||||
* use 0th window
|
||||
*/
|
||||
else if (((offset ^ PCI_BAR_WINDOW0_BASE) < WINDOW_RANGE_MASK) &&
|
||||
!((offset ^ PCI_SOC_PCI_REG_BASE) < PCI_SOC_RANGE_MASK))
|
||||
window_start = 0;
|
||||
else
|
||||
window_start = WINDOW_START;
|
||||
|
||||
return window_start;
|
||||
}
|
||||
|
||||
static inline bool ath12k_pci_is_offset_within_mhi_region(u32 offset)
|
||||
{
|
||||
return (offset >= PCI_MHIREGLEN_REG && offset <= PCI_MHI_REGION_END);
|
||||
}
|
||||
|
||||
static void ath12k_pci_soc_global_reset(struct ath12k_base *ab)
|
||||
{
|
||||
u32 val, delay;
|
||||
|
@ -682,12 +685,22 @@ static void ath12k_pci_init_qmi_ce_config(struct ath12k_base *ab)
|
|||
{
|
||||
struct ath12k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
|
||||
|
||||
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
||||
struct pci_bus *bus = ab_pci->pdev->bus;
|
||||
|
||||
cfg->tgt_ce = ab->hw_params->target_ce_config;
|
||||
cfg->tgt_ce_len = ab->hw_params->target_ce_count;
|
||||
|
||||
cfg->svc_to_ce_map = ab->hw_params->svc_to_ce_map;
|
||||
cfg->svc_to_ce_map_len = ab->hw_params->svc_to_ce_map_len;
|
||||
ab->qmi.service_ins_id = ab->hw_params->qmi_service_ins_id;
|
||||
|
||||
if (test_bit(ATH12K_FW_FEATURE_MULTI_QRTR_ID, ab->fw.fw_features)) {
|
||||
ab_pci->qmi_instance =
|
||||
u32_encode_bits(pci_domain_nr(bus), DOMAIN_NUMBER_MASK) |
|
||||
u32_encode_bits(bus->number, BUS_NUMBER_MASK);
|
||||
ab->qmi.service_ins_id += ab_pci->qmi_instance;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath12k_pci_ce_irqs_enable(struct ath12k_base *ab)
|
||||
|
@ -901,6 +914,26 @@ static void ath12k_pci_aspm_disable(struct ath12k_pci *ab_pci)
|
|||
set_bit(ATH12K_PCI_ASPM_RESTORE, &ab_pci->flags);
|
||||
}
|
||||
|
||||
static void ath12k_pci_update_qrtr_node_id(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
||||
u32 reg;
|
||||
|
||||
/* On platforms with two or more identical mhi devices, qmi service run
|
||||
* with identical qrtr-node-id. Because of this identical ID qrtr-lookup
|
||||
* cannot register more than one qmi service with identical node ID.
|
||||
*
|
||||
* This generates a unique instance ID from PCIe domain number and bus number,
|
||||
* writes to the given register, it is available for firmware when the QMI service
|
||||
* is spawned.
|
||||
*/
|
||||
reg = PCIE_LOCAL_REG_QRTR_NODE_ID & WINDOW_RANGE_MASK;
|
||||
ath12k_pci_write32(ab, reg, ab_pci->qmi_instance);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_PCI, "pci reg 0x%x instance 0x%x read val 0x%x\n",
|
||||
reg, ab_pci->qmi_instance, ath12k_pci_read32(ab, reg));
|
||||
}
|
||||
|
||||
static void ath12k_pci_aspm_restore(struct ath12k_pci *ab_pci)
|
||||
{
|
||||
if (test_and_clear_bit(ATH12K_PCI_ASPM_RESTORE, &ab_pci->flags))
|
||||
|
@ -1138,15 +1171,17 @@ u32 ath12k_pci_read32(struct ath12k_base *ab, u32 offset)
|
|||
if (window_start == WINDOW_START) {
|
||||
spin_lock_bh(&ab_pci->window_lock);
|
||||
ath12k_pci_select_window(ab_pci, offset);
|
||||
val = ioread32(ab->mem + window_start +
|
||||
(offset & WINDOW_RANGE_MASK));
|
||||
|
||||
if (ath12k_pci_is_offset_within_mhi_region(offset)) {
|
||||
offset = offset - PCI_MHIREGLEN_REG;
|
||||
val = ioread32(ab->mem +
|
||||
(offset & WINDOW_RANGE_MASK));
|
||||
} else {
|
||||
val = ioread32(ab->mem + window_start +
|
||||
(offset & WINDOW_RANGE_MASK));
|
||||
}
|
||||
spin_unlock_bh(&ab_pci->window_lock);
|
||||
} else {
|
||||
if ((!window_start) &&
|
||||
(offset >= PCI_MHIREGLEN_REG &&
|
||||
offset <= PCI_MHI_REGION_END))
|
||||
offset = offset - PCI_MHIREGLEN_REG;
|
||||
|
||||
val = ioread32(ab->mem + window_start +
|
||||
(offset & WINDOW_RANGE_MASK));
|
||||
}
|
||||
|
@ -1183,15 +1218,17 @@ void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value)
|
|||
if (window_start == WINDOW_START) {
|
||||
spin_lock_bh(&ab_pci->window_lock);
|
||||
ath12k_pci_select_window(ab_pci, offset);
|
||||
iowrite32(value, ab->mem + window_start +
|
||||
(offset & WINDOW_RANGE_MASK));
|
||||
|
||||
if (ath12k_pci_is_offset_within_mhi_region(offset)) {
|
||||
offset = offset - PCI_MHIREGLEN_REG;
|
||||
iowrite32(value, ab->mem +
|
||||
(offset & WINDOW_RANGE_MASK));
|
||||
} else {
|
||||
iowrite32(value, ab->mem + window_start +
|
||||
(offset & WINDOW_RANGE_MASK));
|
||||
}
|
||||
spin_unlock_bh(&ab_pci->window_lock);
|
||||
} else {
|
||||
if ((!window_start) &&
|
||||
(offset >= PCI_MHIREGLEN_REG &&
|
||||
offset <= PCI_MHI_REGION_END))
|
||||
offset = offset - PCI_MHIREGLEN_REG;
|
||||
|
||||
iowrite32(value, ab->mem + window_start +
|
||||
(offset & WINDOW_RANGE_MASK));
|
||||
}
|
||||
|
@ -1219,6 +1256,9 @@ int ath12k_pci_power_up(struct ath12k_base *ab)
|
|||
|
||||
ath12k_pci_msi_enable(ab_pci);
|
||||
|
||||
if (test_bit(ATH12K_FW_FEATURE_MULTI_QRTR_ID, ab->fw.fw_features))
|
||||
ath12k_pci_update_qrtr_node_id(ab);
|
||||
|
||||
ret = ath12k_mhi_start(ab_pci);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to start mhi: %d\n", ret);
|
||||
|
@ -1310,11 +1350,21 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
|
|||
goto err_free_core;
|
||||
}
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "pci probe %04x:%04x %04x:%04x\n",
|
||||
pdev->vendor, pdev->device,
|
||||
pdev->subsystem_vendor, pdev->subsystem_device);
|
||||
|
||||
ab->id.vendor = pdev->vendor;
|
||||
ab->id.device = pdev->device;
|
||||
ab->id.subsystem_vendor = pdev->subsystem_vendor;
|
||||
ab->id.subsystem_device = pdev->subsystem_device;
|
||||
|
||||
switch (pci_dev->device) {
|
||||
case QCN9274_DEVICE_ID:
|
||||
ab_pci->msi_config = &ath12k_msi_config[0];
|
||||
ab->static_window_map = true;
|
||||
ab_pci->pci_ops = &ath12k_pci_ops_qcn9274;
|
||||
ab->hal_rx_ops = &hal_rx_qcn9274_ops;
|
||||
ath12k_pci_read_hw_version(ab, &soc_hw_version_major,
|
||||
&soc_hw_version_minor);
|
||||
switch (soc_hw_version_major) {
|
||||
|
@ -1333,9 +1383,11 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
|
|||
}
|
||||
break;
|
||||
case WCN7850_DEVICE_ID:
|
||||
ab->id.bdf_search = ATH12K_BDF_SEARCH_BUS_AND_BOARD;
|
||||
ab_pci->msi_config = &ath12k_msi_config[0];
|
||||
ab->static_window_map = false;
|
||||
ab_pci->pci_ops = &ath12k_pci_ops_wcn7850;
|
||||
ab->hal_rx_ops = &hal_rx_wcn7850_ops;
|
||||
ath12k_pci_read_hw_version(ab, &soc_hw_version_major,
|
||||
&soc_hw_version_minor);
|
||||
switch (soc_hw_version_major) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef ATH12K_PCI_H
|
||||
#define ATH12K_PCI_H
|
||||
|
@ -53,6 +53,9 @@
|
|||
#define WLAON_QFPROM_PWR_CTRL_REG 0x01f8031c
|
||||
#define QFPROM_PWR_CTRL_VDD4BLOW_MASK 0x4
|
||||
|
||||
#define QCN9274_QFPROM_RAW_RFA_PDET_ROW13_LSB 0x1E20338
|
||||
#define OTP_BOARD_ID_MASK GENMASK(15, 0)
|
||||
|
||||
#define PCI_BAR_WINDOW0_BASE 0x1E00000
|
||||
#define PCI_BAR_WINDOW0_END 0x1E7FFFC
|
||||
#define PCI_SOC_RANGE_MASK 0x3FFF
|
||||
|
@ -111,6 +114,7 @@ struct ath12k_pci {
|
|||
u16 link_ctl;
|
||||
unsigned long irq_flags;
|
||||
const struct ath12k_pci_ops *pci_ops;
|
||||
u32 qmi_instance;
|
||||
};
|
||||
|
||||
static inline struct ath12k_pci *ath12k_pci_priv(struct ath12k_base *ab)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/elf.h>
|
||||
|
@ -17,7 +17,7 @@
|
|||
#define PLATFORM_CAP_PCIE_GLOBAL_RESET 0x08
|
||||
#define ATH12K_QMI_MAX_CHUNK_SIZE 2097152
|
||||
|
||||
static struct qmi_elem_info wlfw_host_mlo_chip_info_s_v01_ei[] = {
|
||||
static const struct qmi_elem_info wlfw_host_mlo_chip_info_s_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -61,7 +61,7 @@ static struct qmi_elem_info wlfw_host_mlo_chip_info_s_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
|
@ -511,7 +511,7 @@ static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_host_cap_resp_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_host_cap_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
|
@ -528,7 +528,68 @@ static struct qmi_elem_info qmi_wlanfw_host_cap_resp_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_ind_register_req_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_phy_cap_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct qmi_elem_info qmi_wlanfw_phy_cap_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01, resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01,
|
||||
num_phy_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01,
|
||||
num_phy),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01,
|
||||
board_id_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x11,
|
||||
.offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01,
|
||||
board_id),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct qmi_elem_info qmi_wlanfw_ind_register_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
|
@ -753,7 +814,7 @@ static struct qmi_elem_info qmi_wlanfw_ind_register_req_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_ind_register_resp_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_ind_register_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
|
@ -789,7 +850,7 @@ static struct qmi_elem_info qmi_wlanfw_ind_register_resp_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_mem_cfg_s_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_mem_cfg_s_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -821,7 +882,7 @@ static struct qmi_elem_info qmi_wlanfw_mem_cfg_s_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_mem_seg_s_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_mem_seg_s_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -863,7 +924,7 @@ static struct qmi_elem_info qmi_wlanfw_mem_seg_s_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_request_mem_ind_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_request_mem_ind_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_DATA_LEN,
|
||||
.elem_len = 1,
|
||||
|
@ -890,7 +951,7 @@ static struct qmi_elem_info qmi_wlanfw_request_mem_ind_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_mem_seg_resp_s_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_mem_seg_resp_s_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -930,7 +991,7 @@ static struct qmi_elem_info qmi_wlanfw_mem_seg_resp_s_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_respond_mem_req_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_respond_mem_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_DATA_LEN,
|
||||
.elem_len = 1,
|
||||
|
@ -957,7 +1018,7 @@ static struct qmi_elem_info qmi_wlanfw_respond_mem_req_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_respond_mem_resp_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_respond_mem_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
|
@ -975,7 +1036,7 @@ static struct qmi_elem_info qmi_wlanfw_respond_mem_resp_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_cap_req_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_cap_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
|
@ -983,7 +1044,7 @@ static struct qmi_elem_info qmi_wlanfw_cap_req_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_rf_chip_info_s_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_rf_chip_info_s_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -1009,7 +1070,7 @@ static struct qmi_elem_info qmi_wlanfw_rf_chip_info_s_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_rf_board_info_s_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_rf_board_info_s_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -1026,7 +1087,7 @@ static struct qmi_elem_info qmi_wlanfw_rf_board_info_s_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_soc_info_s_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_soc_info_s_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -1042,7 +1103,7 @@ static struct qmi_elem_info qmi_wlanfw_soc_info_s_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_dev_mem_info_s_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_dev_mem_info_s_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -1068,7 +1129,7 @@ static struct qmi_elem_info qmi_wlanfw_dev_mem_info_s_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_fw_version_info_s_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_fw_version_info_s_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -1094,7 +1155,7 @@ static struct qmi_elem_info qmi_wlanfw_fw_version_info_s_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_cap_resp_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_cap_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
|
@ -1348,7 +1409,7 @@ static struct qmi_elem_info qmi_wlanfw_cap_resp_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_bdf_download_req_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_bdf_download_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -1483,7 +1544,7 @@ static struct qmi_elem_info qmi_wlanfw_bdf_download_req_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_bdf_download_resp_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_bdf_download_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
|
@ -1501,7 +1562,7 @@ static struct qmi_elem_info qmi_wlanfw_bdf_download_resp_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_m3_info_req_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_m3_info_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -1525,7 +1586,7 @@ static struct qmi_elem_info qmi_wlanfw_m3_info_req_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_m3_info_resp_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_m3_info_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
|
@ -1542,7 +1603,7 @@ static struct qmi_elem_info qmi_wlanfw_m3_info_resp_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_ce_tgt_pipe_cfg_s_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_ce_tgt_pipe_cfg_s_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -1595,7 +1656,7 @@ static struct qmi_elem_info qmi_wlanfw_ce_tgt_pipe_cfg_s_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_ce_svc_pipe_cfg_s_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_ce_svc_pipe_cfg_s_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -1630,7 +1691,7 @@ static struct qmi_elem_info qmi_wlanfw_ce_svc_pipe_cfg_s_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_shadow_reg_cfg_s_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_shadow_reg_cfg_s_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_2_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -1654,7 +1715,7 @@ static struct qmi_elem_info qmi_wlanfw_shadow_reg_cfg_s_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_shadow_reg_v3_cfg_s_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_shadow_reg_v3_cfg_s_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -1671,7 +1732,7 @@ static struct qmi_elem_info qmi_wlanfw_shadow_reg_v3_cfg_s_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_wlan_mode_req_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_wlan_mode_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
|
@ -1706,7 +1767,7 @@ static struct qmi_elem_info qmi_wlanfw_wlan_mode_req_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_wlan_mode_resp_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_wlan_mode_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
|
@ -1724,7 +1785,7 @@ static struct qmi_elem_info qmi_wlanfw_wlan_mode_resp_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_wlan_cfg_req_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_wlan_cfg_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
|
@ -1862,7 +1923,7 @@ static struct qmi_elem_info qmi_wlanfw_wlan_cfg_req_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_wlan_cfg_resp_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_wlan_cfg_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
|
@ -1879,22 +1940,78 @@ static struct qmi_elem_info qmi_wlanfw_wlan_cfg_resp_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_mem_ready_ind_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_mem_ready_ind_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlanfw_fw_ready_ind_msg_v01_ei[] = {
|
||||
static const struct qmi_elem_info qmi_wlanfw_fw_ready_ind_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
},
|
||||
};
|
||||
|
||||
static void ath12k_host_cap_parse_mlo(struct qmi_wlanfw_host_cap_req_msg_v01 *req)
|
||||
static const struct qmi_elem_info qmi_wlanfw_wlan_ini_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct qmi_wlanfw_wlan_ini_req_msg_v01,
|
||||
enable_fwlog_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct qmi_wlanfw_wlan_ini_req_msg_v01,
|
||||
enable_fwlog),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct qmi_elem_info qmi_wlanfw_wlan_ini_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct qmi_wlanfw_wlan_ini_resp_msg_v01,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab,
|
||||
struct qmi_wlanfw_host_cap_req_msg_v01 *req)
|
||||
{
|
||||
struct wlfw_host_mlo_chip_info_s_v01 *info;
|
||||
u8 hw_link_id = 0;
|
||||
int i;
|
||||
|
||||
if (!ab->qmi.num_radios || ab->qmi.num_radios == U8_MAX) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_QMI,
|
||||
"skip QMI MLO cap due to invalid num_radio %d\n",
|
||||
ab->qmi.num_radios);
|
||||
return;
|
||||
}
|
||||
|
||||
req->mlo_capable_valid = 1;
|
||||
req->mlo_capable = 1;
|
||||
req->mlo_chip_id_valid = 1;
|
||||
|
@ -1905,28 +2022,31 @@ static void ath12k_host_cap_parse_mlo(struct qmi_wlanfw_host_cap_req_msg_v01 *re
|
|||
/* Max peer number generally won't change for the same device
|
||||
* but needs to be synced with host driver.
|
||||
*/
|
||||
req->max_mlo_peer = 32;
|
||||
req->max_mlo_peer = ab->hw_params->max_mlo_peer;
|
||||
req->mlo_num_chips_valid = 1;
|
||||
req->mlo_num_chips = 1;
|
||||
|
||||
info = &req->mlo_chip_info[0];
|
||||
info->chip_id = 0;
|
||||
info->num_local_links = ab->qmi.num_radios;
|
||||
|
||||
for (i = 0; i < info->num_local_links; i++) {
|
||||
info->hw_link_id[i] = hw_link_id;
|
||||
info->valid_mlo_link_id[i] = 1;
|
||||
|
||||
hw_link_id++;
|
||||
}
|
||||
|
||||
req->mlo_chip_info_valid = 1;
|
||||
req->mlo_chip_info[0].chip_id = 0;
|
||||
req->mlo_chip_info[0].num_local_links = 2;
|
||||
req->mlo_chip_info[0].hw_link_id[0] = 0;
|
||||
req->mlo_chip_info[0].hw_link_id[1] = 1;
|
||||
req->mlo_chip_info[0].valid_mlo_link_id[0] = 1;
|
||||
req->mlo_chip_info[0].valid_mlo_link_id[1] = 1;
|
||||
}
|
||||
|
||||
static int ath12k_qmi_host_cap_send(struct ath12k_base *ab)
|
||||
{
|
||||
struct qmi_wlanfw_host_cap_req_msg_v01 req;
|
||||
struct qmi_wlanfw_host_cap_resp_msg_v01 resp;
|
||||
struct qmi_txn txn = {};
|
||||
struct qmi_wlanfw_host_cap_req_msg_v01 req = {};
|
||||
struct qmi_wlanfw_host_cap_resp_msg_v01 resp = {};
|
||||
struct qmi_txn txn;
|
||||
int ret = 0;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
|
||||
req.num_clients_valid = 1;
|
||||
req.num_clients = 1;
|
||||
req.mem_cfg_mode = ab->qmi.target_mem_mode;
|
||||
|
@ -1963,10 +2083,10 @@ static int ath12k_qmi_host_cap_send(struct ath12k_base *ab)
|
|||
*/
|
||||
req.nm_modem |= SLEEP_CLOCK_SELECT_INTERNAL_BIT;
|
||||
req.nm_modem |= PLATFORM_CAP_PCIE_GLOBAL_RESET;
|
||||
|
||||
ath12k_host_cap_parse_mlo(&req);
|
||||
}
|
||||
|
||||
ath12k_host_cap_parse_mlo(ab, &req);
|
||||
|
||||
ret = qmi_txn_init(&ab->qmi.handle, &txn,
|
||||
qmi_wlanfw_host_cap_resp_msg_v01_ei, &resp);
|
||||
if (ret < 0)
|
||||
|
@ -1977,6 +2097,7 @@ static int ath12k_qmi_host_cap_send(struct ath12k_base *ab)
|
|||
QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN,
|
||||
qmi_wlanfw_host_cap_req_msg_v01_ei, &req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath12k_warn(ab, "Failed to send host capability request,err = %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
@ -1996,6 +2117,62 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void ath12k_qmi_phy_cap_send(struct ath12k_base *ab)
|
||||
{
|
||||
struct qmi_wlanfw_phy_cap_req_msg_v01 req = {};
|
||||
struct qmi_wlanfw_phy_cap_resp_msg_v01 resp = {};
|
||||
struct qmi_txn txn;
|
||||
int ret;
|
||||
|
||||
if (!ab->slo_capable)
|
||||
goto out;
|
||||
|
||||
ret = qmi_txn_init(&ab->qmi.handle, &txn,
|
||||
qmi_wlanfw_phy_cap_resp_msg_v01_ei, &resp);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
|
||||
QMI_WLANFW_PHY_CAP_REQ_V01,
|
||||
QMI_WLANFW_PHY_CAP_REQ_MSG_V01_MAX_LEN,
|
||||
qmi_wlanfw_phy_cap_req_msg_v01_ei, &req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath12k_warn(ab, "failed to send phy capability request: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH12K_QMI_WLANFW_TIMEOUT_MS));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!resp.num_phy_valid) {
|
||||
ret = -ENODATA;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ab->qmi.num_radios = resp.num_phy;
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_QMI, "phy capability resp valid %d num_phy %d valid %d board_id %d\n",
|
||||
resp.num_phy_valid, resp.num_phy,
|
||||
resp.board_id_valid, resp.board_id);
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
/* If PHY capability not advertised then rely on default num link */
|
||||
ab->qmi.num_radios = ab->hw_params->def_num_link;
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_QMI,
|
||||
"no valid response from PHY capability, choose default num_phy %d\n",
|
||||
ab->qmi.num_radios);
|
||||
}
|
||||
|
||||
static int ath12k_qmi_fw_ind_register_send(struct ath12k_base *ab)
|
||||
{
|
||||
struct qmi_wlanfw_ind_register_req_msg_v01 *req;
|
||||
|
@ -2040,6 +2217,7 @@ static int ath12k_qmi_fw_ind_register_send(struct ath12k_base *ab)
|
|||
QMI_WLANFW_IND_REGISTER_REQ_MSG_V01_MAX_LEN,
|
||||
qmi_wlanfw_ind_register_req_msg_v01_ei, req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath12k_warn(ab, "Failed to send indication register request, err = %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
|
@ -2068,8 +2246,8 @@ resp_out:
|
|||
static int ath12k_qmi_respond_fw_mem_request(struct ath12k_base *ab)
|
||||
{
|
||||
struct qmi_wlanfw_respond_mem_req_msg_v01 *req;
|
||||
struct qmi_wlanfw_respond_mem_resp_msg_v01 resp;
|
||||
struct qmi_txn txn = {};
|
||||
struct qmi_wlanfw_respond_mem_resp_msg_v01 resp = {};
|
||||
struct qmi_txn txn;
|
||||
int ret = 0, i;
|
||||
bool delayed;
|
||||
|
||||
|
@ -2077,8 +2255,6 @@ static int ath12k_qmi_respond_fw_mem_request(struct ath12k_base *ab)
|
|||
if (!req)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
|
||||
/* Some targets by default request a block of big contiguous
|
||||
* DMA memory, it's hard to allocate from kernel. So host returns
|
||||
* failure to firmware and firmware then request multiple blocks of
|
||||
|
@ -2088,7 +2264,6 @@ static int ath12k_qmi_respond_fw_mem_request(struct ath12k_base *ab)
|
|||
delayed = true;
|
||||
ath12k_dbg(ab, ATH12K_DBG_QMI, "qmi delays mem_request %d\n",
|
||||
ab->qmi.mem_seg_count);
|
||||
memset(req, 0, sizeof(*req));
|
||||
} else {
|
||||
delayed = false;
|
||||
req->mem_seg_len = ab->qmi.mem_seg_count;
|
||||
|
@ -2114,6 +2289,7 @@ static int ath12k_qmi_respond_fw_mem_request(struct ath12k_base *ab)
|
|||
QMI_WLANFW_RESPOND_MEM_REQ_MSG_V01_MAX_LEN,
|
||||
qmi_wlanfw_respond_mem_req_msg_v01_ei, req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath12k_warn(ab, "qmi failed to respond memory request, err = %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
|
@ -2208,17 +2384,14 @@ static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab)
|
|||
|
||||
static int ath12k_qmi_request_target_cap(struct ath12k_base *ab)
|
||||
{
|
||||
struct qmi_wlanfw_cap_req_msg_v01 req;
|
||||
struct qmi_wlanfw_cap_resp_msg_v01 resp;
|
||||
struct qmi_txn txn = {};
|
||||
struct qmi_wlanfw_cap_req_msg_v01 req = {};
|
||||
struct qmi_wlanfw_cap_resp_msg_v01 resp = {};
|
||||
struct qmi_txn txn;
|
||||
unsigned int board_id = ATH12K_BOARD_ID_DEFAULT;
|
||||
int ret = 0;
|
||||
int r;
|
||||
int i;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
|
||||
ret = qmi_txn_init(&ab->qmi.handle, &txn,
|
||||
qmi_wlanfw_cap_resp_msg_v01_ei, &resp);
|
||||
if (ret < 0)
|
||||
|
@ -2229,6 +2402,7 @@ static int ath12k_qmi_request_target_cap(struct ath12k_base *ab)
|
|||
QMI_WLANFW_CAP_REQ_MSG_V01_MAX_LEN,
|
||||
qmi_wlanfw_cap_req_msg_v01_ei, &req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath12k_warn(ab, "qmi failed to send target cap request, err = %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
|
@ -2310,8 +2484,8 @@ static int ath12k_qmi_load_file_target_mem(struct ath12k_base *ab,
|
|||
const u8 *data, u32 len, u8 type)
|
||||
{
|
||||
struct qmi_wlanfw_bdf_download_req_msg_v01 *req;
|
||||
struct qmi_wlanfw_bdf_download_resp_msg_v01 resp;
|
||||
struct qmi_txn txn = {};
|
||||
struct qmi_wlanfw_bdf_download_resp_msg_v01 resp = {};
|
||||
struct qmi_txn txn;
|
||||
const u8 *temp = data;
|
||||
int ret;
|
||||
u32 remaining = len;
|
||||
|
@ -2319,7 +2493,6 @@ static int ath12k_qmi_load_file_target_mem(struct ath12k_base *ab,
|
|||
req = kzalloc(sizeof(*req), GFP_KERNEL);
|
||||
if (!req)
|
||||
return -ENOMEM;
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
|
||||
while (remaining) {
|
||||
req->valid = 1;
|
||||
|
@ -2423,8 +2596,7 @@ static int ath12k_qmi_load_bdf_qmi(struct ath12k_base *ab,
|
|||
|
||||
break;
|
||||
case ATH12K_QMI_BDF_TYPE_REGDB:
|
||||
ret = ath12k_core_fetch_board_data_api_1(ab, &bd,
|
||||
ATH12K_REGDB_FILE_NAME);
|
||||
ret = ath12k_core_fetch_regdb(ab, &bd);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "qmi failed to load regdb bin:\n");
|
||||
goto out;
|
||||
|
@ -2497,37 +2669,56 @@ out:
|
|||
static int ath12k_qmi_m3_load(struct ath12k_base *ab)
|
||||
{
|
||||
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
|
||||
const struct firmware *fw;
|
||||
const struct firmware *fw = NULL;
|
||||
const void *m3_data;
|
||||
char path[100];
|
||||
size_t m3_len;
|
||||
int ret;
|
||||
|
||||
if (m3_mem->vaddr || m3_mem->size)
|
||||
if (m3_mem->vaddr)
|
||||
/* m3 firmware buffer is already available in the DMA buffer */
|
||||
return 0;
|
||||
|
||||
fw = ath12k_core_firmware_request(ab, ATH12K_M3_FILE);
|
||||
if (IS_ERR(fw)) {
|
||||
ret = PTR_ERR(fw);
|
||||
ath12k_core_create_firmware_path(ab, ATH12K_M3_FILE,
|
||||
path, sizeof(path));
|
||||
ath12k_err(ab, "failed to load %s: %d\n", path, ret);
|
||||
return ret;
|
||||
if (ab->fw.m3_data && ab->fw.m3_len > 0) {
|
||||
/* firmware-N.bin had a m3 firmware file so use that */
|
||||
m3_data = ab->fw.m3_data;
|
||||
m3_len = ab->fw.m3_len;
|
||||
} else {
|
||||
/* No m3 file in firmware-N.bin so try to request old
|
||||
* separate m3.bin.
|
||||
*/
|
||||
fw = ath12k_core_firmware_request(ab, ATH12K_M3_FILE);
|
||||
if (IS_ERR(fw)) {
|
||||
ret = PTR_ERR(fw);
|
||||
ath12k_core_create_firmware_path(ab, ATH12K_M3_FILE,
|
||||
path, sizeof(path));
|
||||
ath12k_err(ab, "failed to load %s: %d\n", path, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
m3_data = fw->data;
|
||||
m3_len = fw->size;
|
||||
}
|
||||
|
||||
m3_mem->vaddr = dma_alloc_coherent(ab->dev,
|
||||
fw->size, &m3_mem->paddr,
|
||||
m3_len, &m3_mem->paddr,
|
||||
GFP_KERNEL);
|
||||
if (!m3_mem->vaddr) {
|
||||
ath12k_err(ab, "failed to allocate memory for M3 with size %zu\n",
|
||||
fw->size);
|
||||
release_firmware(fw);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(m3_mem->vaddr, fw->data, fw->size);
|
||||
m3_mem->size = fw->size;
|
||||
memcpy(m3_mem->vaddr, m3_data, m3_len);
|
||||
m3_mem->size = m3_len;
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
release_firmware(fw);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath12k_qmi_m3_free(struct ath12k_base *ab)
|
||||
|
@ -2546,14 +2737,11 @@ static void ath12k_qmi_m3_free(struct ath12k_base *ab)
|
|||
static int ath12k_qmi_wlanfw_m3_info_send(struct ath12k_base *ab)
|
||||
{
|
||||
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
|
||||
struct qmi_wlanfw_m3_info_req_msg_v01 req;
|
||||
struct qmi_wlanfw_m3_info_resp_msg_v01 resp;
|
||||
struct qmi_txn txn = {};
|
||||
struct qmi_wlanfw_m3_info_req_msg_v01 req = {};
|
||||
struct qmi_wlanfw_m3_info_resp_msg_v01 resp = {};
|
||||
struct qmi_txn txn;
|
||||
int ret = 0;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
|
||||
ret = ath12k_qmi_m3_load(ab);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to load m3 firmware: %d", ret);
|
||||
|
@ -2573,6 +2761,7 @@ static int ath12k_qmi_wlanfw_m3_info_send(struct ath12k_base *ab)
|
|||
QMI_WLANFW_M3_INFO_REQ_MSG_V01_MAX_MSG_LEN,
|
||||
qmi_wlanfw_m3_info_req_msg_v01_ei, &req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath12k_warn(ab, "qmi failed to send M3 information request, err = %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
|
@ -2597,14 +2786,11 @@ out:
|
|||
static int ath12k_qmi_wlanfw_mode_send(struct ath12k_base *ab,
|
||||
u32 mode)
|
||||
{
|
||||
struct qmi_wlanfw_wlan_mode_req_msg_v01 req;
|
||||
struct qmi_wlanfw_wlan_mode_resp_msg_v01 resp;
|
||||
struct qmi_txn txn = {};
|
||||
struct qmi_wlanfw_wlan_mode_req_msg_v01 req = {};
|
||||
struct qmi_wlanfw_wlan_mode_resp_msg_v01 resp = {};
|
||||
struct qmi_txn txn;
|
||||
int ret = 0;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
|
||||
req.mode = mode;
|
||||
req.hw_debug_valid = 1;
|
||||
req.hw_debug = 0;
|
||||
|
@ -2619,6 +2805,7 @@ static int ath12k_qmi_wlanfw_mode_send(struct ath12k_base *ab,
|
|||
QMI_WLANFW_WLAN_MODE_REQ_MSG_V01_MAX_LEN,
|
||||
qmi_wlanfw_wlan_mode_req_msg_v01_ei, &req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath12k_warn(ab, "qmi failed to send mode request, mode: %d, err = %d\n",
|
||||
mode, ret);
|
||||
goto out;
|
||||
|
@ -2649,10 +2836,10 @@ out:
|
|||
static int ath12k_qmi_wlanfw_wlan_cfg_send(struct ath12k_base *ab)
|
||||
{
|
||||
struct qmi_wlanfw_wlan_cfg_req_msg_v01 *req;
|
||||
struct qmi_wlanfw_wlan_cfg_resp_msg_v01 resp;
|
||||
struct qmi_wlanfw_wlan_cfg_resp_msg_v01 resp = {};
|
||||
struct ce_pipe_config *ce_cfg;
|
||||
struct service_to_pipe *svc_cfg;
|
||||
struct qmi_txn txn = {};
|
||||
struct qmi_txn txn;
|
||||
int ret = 0, pipe_num;
|
||||
|
||||
ce_cfg = (struct ce_pipe_config *)ab->qmi.ce_cfg.tgt_ce;
|
||||
|
@ -2662,8 +2849,6 @@ static int ath12k_qmi_wlanfw_wlan_cfg_send(struct ath12k_base *ab)
|
|||
if (!req)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
|
||||
req->host_version_valid = 1;
|
||||
strscpy(req->host_version, ATH12K_HOST_VERSION_STRING,
|
||||
sizeof(req->host_version));
|
||||
|
@ -2710,6 +2895,7 @@ static int ath12k_qmi_wlanfw_wlan_cfg_send(struct ath12k_base *ab)
|
|||
QMI_WLANFW_WLAN_CFG_REQ_MSG_V01_MAX_LEN,
|
||||
qmi_wlanfw_wlan_cfg_req_msg_v01_ei, req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath12k_warn(ab, "qmi failed to send wlan config request, err = %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
|
@ -2733,6 +2919,49 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ath12k_qmi_wlanfw_wlan_ini_send(struct ath12k_base *ab)
|
||||
{
|
||||
struct qmi_wlanfw_wlan_ini_resp_msg_v01 resp = {};
|
||||
struct qmi_wlanfw_wlan_ini_req_msg_v01 req = {};
|
||||
struct qmi_txn txn;
|
||||
int ret;
|
||||
|
||||
req.enable_fwlog_valid = true;
|
||||
req.enable_fwlog = 1;
|
||||
|
||||
ret = qmi_txn_init(&ab->qmi.handle, &txn,
|
||||
qmi_wlanfw_wlan_ini_resp_msg_v01_ei, &resp);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
|
||||
ATH12K_QMI_WLANFW_WLAN_INI_REQ_V01,
|
||||
QMI_WLANFW_WLAN_INI_REQ_MSG_V01_MAX_LEN,
|
||||
qmi_wlanfw_wlan_ini_req_msg_v01_ei, &req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath12k_warn(ab, "failed to send QMI wlan ini request: %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH12K_QMI_WLANFW_TIMEOUT_MS));
|
||||
if (ret < 0) {
|
||||
ath12k_warn(ab, "failed to receive QMI wlan ini request: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
||||
ath12k_warn(ab, "QMI wlan ini response failure: %d %d\n",
|
||||
resp.resp.result, resp.resp.error);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ath12k_qmi_firmware_stop(struct ath12k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
@ -2749,6 +2978,12 @@ int ath12k_qmi_firmware_start(struct ath12k_base *ab,
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = ath12k_qmi_wlanfw_wlan_ini_send(ab);
|
||||
if (ret < 0) {
|
||||
ath12k_warn(ab, "qmi failed to send wlan fw ini: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath12k_qmi_wlanfw_wlan_cfg_send(ab);
|
||||
if (ret < 0) {
|
||||
ath12k_warn(ab, "qmi failed to send wlan cfg:%d\n", ret);
|
||||
|
@ -2792,6 +3027,8 @@ static int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi)
|
|||
struct ath12k_base *ab = qmi->ab;
|
||||
int ret;
|
||||
|
||||
ath12k_qmi_phy_cap_send(ab);
|
||||
|
||||
ret = ath12k_qmi_fw_ind_register_send(ab);
|
||||
if (ret < 0) {
|
||||
ath12k_warn(ab, "qmi failed to send FW indication QMI:%d\n", ret);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_QMI_H
|
||||
|
@ -15,7 +15,6 @@
|
|||
#define ATH12K_QMI_MAX_BDF_FILE_NAME_SIZE 64
|
||||
#define ATH12K_QMI_CALDB_ADDRESS 0x4BA00000
|
||||
#define ATH12K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 128
|
||||
#define ATH12K_QMI_WLFW_NODE_ID_BASE 0x07
|
||||
#define ATH12K_QMI_WLFW_SERVICE_ID_V01 0x45
|
||||
#define ATH12K_QMI_WLFW_SERVICE_VERS_V01 0x01
|
||||
#define ATH12K_QMI_WLFW_SERVICE_INS_ID_V01 0x02
|
||||
|
@ -141,6 +140,7 @@ struct ath12k_qmi {
|
|||
u32 target_mem_mode;
|
||||
bool target_mem_delayed;
|
||||
u8 cal_done;
|
||||
u8 num_radios;
|
||||
struct target_info target;
|
||||
struct m3_mem_region m3_mem;
|
||||
unsigned int service_ins_id;
|
||||
|
@ -251,6 +251,22 @@ struct qmi_wlanfw_host_cap_resp_msg_v01 {
|
|||
struct qmi_response_type_v01 resp;
|
||||
};
|
||||
|
||||
#define QMI_WLANFW_PHY_CAP_REQ_MSG_V01_MAX_LEN 0
|
||||
#define QMI_WLANFW_PHY_CAP_REQ_V01 0x0057
|
||||
#define QMI_WLANFW_PHY_CAP_RESP_MSG_V01_MAX_LEN 18
|
||||
#define QMI_WLANFW_PHY_CAP_RESP_V01 0x0057
|
||||
|
||||
struct qmi_wlanfw_phy_cap_req_msg_v01 {
|
||||
};
|
||||
|
||||
struct qmi_wlanfw_phy_cap_resp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
u8 num_phy_valid;
|
||||
u8 num_phy;
|
||||
u8 board_id_valid;
|
||||
u32 board_id;
|
||||
};
|
||||
|
||||
#define QMI_WLANFW_IND_REGISTER_REQ_MSG_V01_MAX_LEN 54
|
||||
#define QMI_WLANFW_IND_REGISTER_REQ_V01 0x0020
|
||||
#define QMI_WLANFW_IND_REGISTER_RESP_MSG_V01_MAX_LEN 18
|
||||
|
@ -559,6 +575,21 @@ struct qmi_wlanfw_wlan_cfg_resp_msg_v01 {
|
|||
struct qmi_response_type_v01 resp;
|
||||
};
|
||||
|
||||
#define ATH12K_QMI_WLANFW_WLAN_INI_REQ_V01 0x002F
|
||||
#define ATH12K_QMI_WLANFW_WLAN_INI_RESP_V01 0x002F
|
||||
#define QMI_WLANFW_WLAN_INI_REQ_MSG_V01_MAX_LEN 7
|
||||
#define QMI_WLANFW_WLAN_INI_RESP_MSG_V01_MAX_LEN 7
|
||||
|
||||
struct qmi_wlanfw_wlan_ini_req_msg_v01 {
|
||||
/* Must be set to true if enable_fwlog is being passed */
|
||||
u8 enable_fwlog_valid;
|
||||
u8 enable_fwlog;
|
||||
};
|
||||
|
||||
struct qmi_wlanfw_wlan_ini_resp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
};
|
||||
|
||||
int ath12k_qmi_firmware_start(struct ath12k_base *ab,
|
||||
u32 mode);
|
||||
void ath12k_qmi_firmware_stop(struct ath12k_base *ab);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/rtnetlink.h>
|
||||
#include "core.h"
|
||||
|
@ -48,7 +48,8 @@ ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
|
|||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct ath12k_wmi_init_country_arg arg;
|
||||
struct ath12k *ar = hw->priv;
|
||||
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
|
||||
struct ath12k *ar = ath12k_ah_to_ar(ah);
|
||||
int ret;
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
|
||||
|
@ -95,7 +96,7 @@ int ath12k_reg_update_chan_list(struct ath12k *ar)
|
|||
struct ieee80211_supported_band **bands;
|
||||
struct ath12k_wmi_scan_chan_list_arg *arg;
|
||||
struct ieee80211_channel *channel;
|
||||
struct ieee80211_hw *hw = ar->hw;
|
||||
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
|
||||
struct ath12k_wmi_channel_arg *ch;
|
||||
enum nl80211_band band;
|
||||
int num_channels = 0;
|
||||
|
@ -103,7 +104,7 @@ int ath12k_reg_update_chan_list(struct ath12k *ar)
|
|||
|
||||
bands = hw->wiphy->bands;
|
||||
for (band = 0; band < NUM_NL80211_BANDS; band++) {
|
||||
if (!bands[band])
|
||||
if (!(ar->mac.sbands[band].channels && bands[band]))
|
||||
continue;
|
||||
|
||||
for (i = 0; i < bands[band]->n_channels; i++) {
|
||||
|
@ -129,7 +130,7 @@ int ath12k_reg_update_chan_list(struct ath12k *ar)
|
|||
ch = arg->channel;
|
||||
|
||||
for (band = 0; band < NUM_NL80211_BANDS; band++) {
|
||||
if (!bands[band])
|
||||
if (!(ar->mac.sbands[band].channels && bands[band]))
|
||||
continue;
|
||||
|
||||
for (i = 0; i < bands[band]->n_channels; i++) {
|
||||
|
@ -199,7 +200,7 @@ static void ath12k_copy_regd(struct ieee80211_regdomain *regd_orig,
|
|||
|
||||
int ath12k_regd_update(struct ath12k *ar, bool init)
|
||||
{
|
||||
struct ieee80211_hw *hw = ar->hw;
|
||||
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
|
||||
struct ieee80211_regdomain *regd, *regd_copy = NULL;
|
||||
int ret, regd_len, pdev_id;
|
||||
struct ath12k_base *ab;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef ATH12K_RX_DESC_H
|
||||
#define ATH12K_RX_DESC_H
|
||||
|
@ -147,6 +147,61 @@ struct rx_mpdu_start_qcn9274 {
|
|||
__le32 res1;
|
||||
} __packed;
|
||||
|
||||
#define QCN9274_MPDU_START_SELECT_MPDU_START_TAG BIT(0)
|
||||
#define QCN9274_MPDU_START_SELECT_INFO0_REO_QUEUE_DESC_LO BIT(1)
|
||||
#define QCN9274_MPDU_START_SELECT_INFO1_PN_31_0 BIT(2)
|
||||
#define QCN9274_MPDU_START_SELECT_PN_95_32 BIT(3)
|
||||
#define QCN9274_MPDU_START_SELECT_PN_127_96_INFO2 BIT(4)
|
||||
#define QCN9274_MPDU_START_SELECT_PEER_MDATA_INFO3_PHY_PPDU_ID BIT(5)
|
||||
#define QCN9274_MPDU_START_SELECT_AST_IDX_SW_PEER_ID_INFO4 BIT(6)
|
||||
#define QCN9274_MPDU_START_SELECT_INFO5_INFO6 BIT(7)
|
||||
#define QCN9274_MPDU_START_SELECT_FRAME_CTRL_DURATION_ADDR1_31_0 BIT(8)
|
||||
#define QCN9274_MPDU_START_SELECT_ADDR2_47_0_ADDR1_47_32 BIT(9)
|
||||
#define QCN9274_MPDU_START_SELECT_ADDR3_47_0_SEQ_CTRL BIT(10)
|
||||
#define QCN9274_MPDU_START_SELECT_ADDR4_47_0_QOS_CTRL BIT(11)
|
||||
#define QCN9274_MPDU_START_SELECT_HT_CTRL_INFO7 BIT(12)
|
||||
#define QCN9274_MPDU_START_SELECT_ML_ADDR1_47_0_ML_ADDR2_15_0 BIT(13)
|
||||
#define QCN9274_MPDU_START_SELECT_ML_ADDR2_47_16_INFO8 BIT(14)
|
||||
#define QCN9274_MPDU_START_SELECT_RES_0_RES_1 BIT(15)
|
||||
|
||||
#define QCN9274_MPDU_START_WMASK (QCN9274_MPDU_START_SELECT_INFO1_PN_31_0 | \
|
||||
QCN9274_MPDU_START_SELECT_PN_95_32 | \
|
||||
QCN9274_MPDU_START_SELECT_PN_127_96_INFO2 | \
|
||||
QCN9274_MPDU_START_SELECT_PEER_MDATA_INFO3_PHY_PPDU_ID | \
|
||||
QCN9274_MPDU_START_SELECT_AST_IDX_SW_PEER_ID_INFO4 | \
|
||||
QCN9274_MPDU_START_SELECT_INFO5_INFO6 | \
|
||||
QCN9274_MPDU_START_SELECT_FRAME_CTRL_DURATION_ADDR1_31_0 | \
|
||||
QCN9274_MPDU_START_SELECT_ADDR2_47_0_ADDR1_47_32 | \
|
||||
QCN9274_MPDU_START_SELECT_ADDR3_47_0_SEQ_CTRL | \
|
||||
QCN9274_MPDU_START_SELECT_ADDR4_47_0_QOS_CTRL)
|
||||
|
||||
/* The below rx_mpdu_start_qcn9274_compact structure is tied with the mask
|
||||
* value QCN9274_MPDU_START_WMASK. If the mask value changes the structure
|
||||
* will also change.
|
||||
*/
|
||||
|
||||
struct rx_mpdu_start_qcn9274_compact {
|
||||
__le32 info1;
|
||||
__le32 pn[4];
|
||||
__le32 info2;
|
||||
__le32 peer_meta_data;
|
||||
__le16 info3;
|
||||
__le16 phy_ppdu_id;
|
||||
__le16 ast_index;
|
||||
__le16 sw_peer_id;
|
||||
__le32 info4;
|
||||
__le32 info5;
|
||||
__le32 info6;
|
||||
__le16 frame_ctrl;
|
||||
__le16 duration;
|
||||
u8 addr1[ETH_ALEN];
|
||||
u8 addr2[ETH_ALEN];
|
||||
u8 addr3[ETH_ALEN];
|
||||
__le16 seq_ctrl;
|
||||
u8 addr4[ETH_ALEN];
|
||||
__le16 qos_ctrl;
|
||||
} __packed;
|
||||
|
||||
/* rx_mpdu_start
|
||||
*
|
||||
* reo_destination_indication
|
||||
|
@ -608,6 +663,8 @@ enum rx_msdu_start_reception_type {
|
|||
RX_MSDU_START_RECEPTION_TYPE_UL_MU_OFDMA_MIMO,
|
||||
};
|
||||
|
||||
#define RX_MSDU_END_64_TLV_SRC_LINK_ID GENMASK(24, 22)
|
||||
|
||||
#define RX_MSDU_END_INFO0_RXPCU_MPDU_FITLER GENMASK(1, 0)
|
||||
#define RX_MSDU_END_INFO0_SW_FRAME_GRP_ID GENMASK(8, 2)
|
||||
|
||||
|
@ -786,6 +843,52 @@ struct rx_msdu_end_qcn9274 {
|
|||
__le32 info14;
|
||||
} __packed;
|
||||
|
||||
#define QCN9274_MSDU_END_SELECT_MSDU_END_TAG BIT(0)
|
||||
#define QCN9274_MSDU_END_SELECT_INFO0_PHY_PPDUID_IP_HDR_CSUM_INFO1 BIT(1)
|
||||
#define QCN9274_MSDU_END_SELECT_INFO2_CUMULATIVE_CSUM_RULE_IND_0 BIT(2)
|
||||
#define QCN9274_MSDU_END_SELECT_IPV6_OP_CRC_INFO3_TYPE13 BIT(3)
|
||||
#define QCN9274_MSDU_END_SELECT_RULE_IND_1_TCP_SEQ_NUM BIT(4)
|
||||
#define QCN9274_MSDU_END_SELECT_TCP_ACK_NUM_INFO4_WINDOW_SIZE BIT(5)
|
||||
#define QCN9274_MSDU_END_SELECT_SA_SW_PER_ID_INFO5_SA_DA_ID BIT(6)
|
||||
#define QCN9274_MSDU_END_SELECT_INFO6_FSE_METADATA BIT(7)
|
||||
#define QCN9274_MSDU_END_SELECT_CCE_MDATA_TCP_UDP_CSUM_INFO7_IP_LEN BIT(8)
|
||||
#define QCN9274_MSDU_END_SELECT_INFO8_INFO9 BIT(9)
|
||||
#define QCN9274_MSDU_END_SELECT_INFO10_INFO11 BIT(10)
|
||||
#define QCN9274_MSDU_END_SELECT_VLAN_CTAG_STAG_CI_PEER_MDATA BIT(11)
|
||||
#define QCN9274_MSDU_END_SELECT_INFO12_AND_FLOW_ID_TOEPLITZ BIT(12)
|
||||
#define QCN9274_MSDU_END_SELECT_PPDU_START_TS_63_32_PHY_MDATA BIT(13)
|
||||
#define QCN9274_MSDU_END_SELECT_PPDU_START_TS_31_0_TOEPLITZ_HASH_2_4 BIT(14)
|
||||
#define QCN9274_MSDU_END_SELECT_RES0_SA_47_0 BIT(15)
|
||||
#define QCN9274_MSDU_END_SELECT_INFO13_INFO14 BIT(16)
|
||||
|
||||
#define QCN9274_MSDU_END_WMASK (QCN9274_MSDU_END_SELECT_MSDU_END_TAG | \
|
||||
QCN9274_MSDU_END_SELECT_SA_SW_PER_ID_INFO5_SA_DA_ID | \
|
||||
QCN9274_MSDU_END_SELECT_INFO10_INFO11 | \
|
||||
QCN9274_MSDU_END_SELECT_INFO12_AND_FLOW_ID_TOEPLITZ | \
|
||||
QCN9274_MSDU_END_SELECT_PPDU_START_TS_63_32_PHY_MDATA | \
|
||||
QCN9274_MSDU_END_SELECT_INFO13_INFO14)
|
||||
|
||||
/* The below rx_msdu_end_qcn9274_compact structure is tied with the mask value
|
||||
* QCN9274_MSDU_END_WMASK. If the mask value changes the structure will also
|
||||
* change.
|
||||
*/
|
||||
|
||||
struct rx_msdu_end_qcn9274_compact {
|
||||
__le64 msdu_end_tag;
|
||||
__le16 sa_sw_peer_id;
|
||||
__le16 info5;
|
||||
__le16 sa_idx;
|
||||
__le16 da_idx_or_sw_peer_id;
|
||||
__le32 info10;
|
||||
__le32 info11;
|
||||
__le32 info12;
|
||||
__le32 flow_id_toeplitz;
|
||||
__le32 ppdu_start_timestamp_63_32;
|
||||
__le32 phy_meta_data;
|
||||
__le32 info13;
|
||||
__le32 info14;
|
||||
} __packed;
|
||||
|
||||
/* These macro definitions are only used for WCN7850 */
|
||||
#define RX_MSDU_END_WCN7850_INFO2_KEY_ID BIT(7, 0)
|
||||
|
||||
|
@ -1450,16 +1553,18 @@ struct rx_msdu_end_wcn7850 {
|
|||
*
|
||||
*/
|
||||
|
||||
/* TODO: Move to compact TLV approach
|
||||
* By default these tlv's are not aligned to 128b boundary
|
||||
* Need to remove unused qwords and make them compact/aligned
|
||||
*/
|
||||
struct hal_rx_desc_qcn9274 {
|
||||
struct rx_msdu_end_qcn9274 msdu_end;
|
||||
struct rx_mpdu_start_qcn9274 mpdu_start;
|
||||
u8 msdu_payload[];
|
||||
} __packed;
|
||||
|
||||
struct hal_rx_desc_qcn9274_compact {
|
||||
struct rx_msdu_end_qcn9274_compact msdu_end;
|
||||
struct rx_mpdu_start_qcn9274_compact mpdu_start;
|
||||
u8 msdu_payload[];
|
||||
} __packed;
|
||||
|
||||
#define RX_BE_PADDING0_BYTES 8
|
||||
#define RX_BE_PADDING1_BYTES 8
|
||||
|
||||
|
@ -1484,6 +1589,7 @@ struct hal_rx_desc_wcn7850 {
|
|||
struct hal_rx_desc {
|
||||
union {
|
||||
struct hal_rx_desc_qcn9274 qcn9274;
|
||||
struct hal_rx_desc_qcn9274_compact qcn9274_compact;
|
||||
struct hal_rx_desc_wcn7850 wcn7850;
|
||||
} u;
|
||||
} __packed;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#if !defined(_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
|
||||
|
@ -140,6 +140,33 @@ TRACE_EVENT(ath12k_htt_rxdesc,
|
|||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(ath12k_wmi_diag,
|
||||
TP_PROTO(struct ath12k_base *ab, const void *data, size_t len),
|
||||
|
||||
TP_ARGS(ab, data, len),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(device, dev_name(ab->dev))
|
||||
__string(driver, dev_driver_string(ab->dev))
|
||||
__field(u16, len)
|
||||
__dynamic_array(u8, data, len)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(device, dev_name(ab->dev));
|
||||
__assign_str(driver, dev_driver_string(ab->dev));
|
||||
__entry->len = len;
|
||||
memcpy(__get_dynamic_array(data), data, len);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s %s tlv diag len %d",
|
||||
__get_str(driver),
|
||||
__get_str(device),
|
||||
__entry->len
|
||||
)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/
|
||||
|
||||
/* we don't want to use include/trace/events */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/ctype.h>
|
||||
|
@ -19,6 +19,7 @@
|
|||
#include "mac.h"
|
||||
#include "hw.h"
|
||||
#include "peer.h"
|
||||
#include "p2p.h"
|
||||
|
||||
struct ath12k_wmi_svc_ready_parse {
|
||||
bool wmi_svc_bitmap_done;
|
||||
|
@ -162,6 +163,14 @@ static const struct ath12k_wmi_tlv_policy ath12k_wmi_tlv_policies[] = {
|
|||
.min_len = sizeof(struct wmi_probe_resp_tx_status_event) },
|
||||
[WMI_TAG_VDEV_DELETE_RESP_EVENT] = {
|
||||
.min_len = sizeof(struct wmi_vdev_delete_resp_event) },
|
||||
[WMI_TAG_TWT_ENABLE_COMPLETE_EVENT] = {
|
||||
.min_len = sizeof(struct wmi_twt_enable_event) },
|
||||
[WMI_TAG_TWT_DISABLE_COMPLETE_EVENT] = {
|
||||
.min_len = sizeof(struct wmi_twt_disable_event) },
|
||||
[WMI_TAG_P2P_NOA_INFO] = {
|
||||
.min_len = sizeof(struct ath12k_wmi_p2p_noa_info) },
|
||||
[WMI_TAG_P2P_NOA_EVENT] = {
|
||||
.min_len = sizeof(struct wmi_p2p_noa_event) },
|
||||
};
|
||||
|
||||
static __le32 ath12k_wmi_tlv_hdr(u32 cmd, u32 len)
|
||||
|
@ -179,18 +188,9 @@ void ath12k_wmi_init_qcn9274(struct ath12k_base *ab,
|
|||
struct ath12k_wmi_resource_config_arg *config)
|
||||
{
|
||||
config->num_vdevs = ab->num_radios * TARGET_NUM_VDEVS;
|
||||
|
||||
if (ab->num_radios == 2) {
|
||||
config->num_peers = TARGET_NUM_PEERS(DBS);
|
||||
config->num_tids = TARGET_NUM_TIDS(DBS);
|
||||
} else if (ab->num_radios == 3) {
|
||||
config->num_peers = TARGET_NUM_PEERS(DBS_SBS);
|
||||
config->num_tids = TARGET_NUM_TIDS(DBS_SBS);
|
||||
} else {
|
||||
/* Control should not reach here */
|
||||
config->num_peers = TARGET_NUM_PEERS(SINGLE);
|
||||
config->num_tids = TARGET_NUM_TIDS(SINGLE);
|
||||
}
|
||||
config->num_peers = ab->num_radios *
|
||||
ath12k_core_get_max_peers_per_radio(ab);
|
||||
config->num_tids = ath12k_core_get_max_num_tids(ab);
|
||||
config->num_offload_peers = TARGET_NUM_OFFLD_PEERS;
|
||||
config->num_offload_reorder_buffs = TARGET_NUM_OFFLD_REORDER_BUFFS;
|
||||
config->num_peer_keys = TARGET_NUM_PEER_KEYS;
|
||||
|
@ -228,6 +228,9 @@ void ath12k_wmi_init_qcn9274(struct ath12k_base *ab,
|
|||
config->peer_map_unmap_version = 0x32;
|
||||
config->twt_ap_pdev_count = ab->num_radios;
|
||||
config->twt_ap_sta_count = 1000;
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT, ab->wmi_ab.svc_map))
|
||||
config->dp_peer_meta_data_ver = TARGET_RX_PEER_METADATA_VER_V1B;
|
||||
}
|
||||
|
||||
void ath12k_wmi_init_wcn7850(struct ath12k_base *ab,
|
||||
|
@ -359,8 +362,8 @@ static int ath12k_wmi_tlv_parse(struct ath12k_base *ar, const void **tb,
|
|||
}
|
||||
|
||||
static const void **
|
||||
ath12k_wmi_tlv_parse_alloc(struct ath12k_base *ab, const void *ptr,
|
||||
size_t len, gfp_t gfp)
|
||||
ath12k_wmi_tlv_parse_alloc(struct ath12k_base *ab,
|
||||
struct sk_buff *skb, gfp_t gfp)
|
||||
{
|
||||
const void **tb;
|
||||
int ret;
|
||||
|
@ -369,7 +372,7 @@ ath12k_wmi_tlv_parse_alloc(struct ath12k_base *ab, const void *ptr,
|
|||
if (!tb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = ath12k_wmi_tlv_parse(ab, tb, ptr, len);
|
||||
ret = ath12k_wmi_tlv_parse(ab, tb, skb->data, skb->len);
|
||||
if (ret) {
|
||||
kfree(tb);
|
||||
return ERR_PTR(ret);
|
||||
|
@ -493,13 +496,13 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
|
|||
|
||||
mac_caps = wmi_mac_phy_caps + phy_idx;
|
||||
|
||||
pdev->pdev_id = le32_to_cpu(mac_caps->pdev_id);
|
||||
pdev->pdev_id = ath12k_wmi_mac_phy_get_pdev_id(mac_caps);
|
||||
pdev_cap->supported_bands |= le32_to_cpu(mac_caps->supported_bands);
|
||||
pdev_cap->ampdu_density = le32_to_cpu(mac_caps->ampdu_density);
|
||||
|
||||
fw_pdev = &ab->fw_pdev[ab->fw_pdev_count];
|
||||
fw_pdev->supported_bands = le32_to_cpu(mac_caps->supported_bands);
|
||||
fw_pdev->pdev_id = le32_to_cpu(mac_caps->pdev_id);
|
||||
fw_pdev->pdev_id = ath12k_wmi_mac_phy_get_pdev_id(mac_caps);
|
||||
fw_pdev->phy_id = le32_to_cpu(mac_caps->phy_id);
|
||||
ab->fw_pdev_count++;
|
||||
|
||||
|
@ -727,6 +730,20 @@ static int ath12k_service_ready_event(struct ath12k_base *ab, struct sk_buff *sk
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u32 ath12k_wmi_mgmt_get_freq(struct ath12k *ar,
|
||||
struct ieee80211_tx_info *info)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
u32 freq = 0;
|
||||
|
||||
if (ab->hw_params->single_pdev_only &&
|
||||
ar->scan.is_roc &&
|
||||
(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN))
|
||||
freq = ar->scan.roc_freq;
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
struct sk_buff *ath12k_wmi_alloc_skb(struct ath12k_wmi_base *wmi_ab, u32 len)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
@ -752,6 +769,7 @@ int ath12k_wmi_mgmt_send(struct ath12k *ar, u32 vdev_id, u32 buf_id,
|
|||
{
|
||||
struct ath12k_wmi_pdev *wmi = ar->wmi;
|
||||
struct wmi_mgmt_send_cmd *cmd;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(frame);
|
||||
struct wmi_tlv *frame_tlv;
|
||||
struct sk_buff *skb;
|
||||
u32 buf_len;
|
||||
|
@ -770,7 +788,7 @@ int ath12k_wmi_mgmt_send(struct ath12k *ar, u32 vdev_id, u32 buf_id,
|
|||
sizeof(*cmd));
|
||||
cmd->vdev_id = cpu_to_le32(vdev_id);
|
||||
cmd->desc_id = cpu_to_le32(buf_id);
|
||||
cmd->chanfreq = 0;
|
||||
cmd->chanfreq = cpu_to_le32(ath12k_wmi_mgmt_get_freq(ar, info));
|
||||
cmd->paddr_lo = cpu_to_le32(lower_32_bits(ATH12K_SKB_CB(frame)->paddr));
|
||||
cmd->paddr_hi = cpu_to_le32(upper_32_bits(ATH12K_SKB_CB(frame)->paddr));
|
||||
cmd->frame_len = cpu_to_le32(frame->len);
|
||||
|
@ -826,6 +844,9 @@ int ath12k_wmi_vdev_create(struct ath12k *ar, u8 *macaddr,
|
|||
cmd->vdev_stats_id = cpu_to_le32(args->if_stats_id);
|
||||
ether_addr_copy(cmd->vdev_macaddr.addr, macaddr);
|
||||
|
||||
if (args->if_stats_id != ATH12K_INVAL_VDEV_STATS_ID)
|
||||
cmd->vdev_stats_id_valid = cpu_to_le32(BIT(0));
|
||||
|
||||
ptr = skb->data + sizeof(*cmd);
|
||||
len = WMI_NUM_SUPPORTED_BAND_MAX * sizeof(*txrx_streams);
|
||||
|
||||
|
@ -1024,6 +1045,7 @@ int ath12k_wmi_vdev_start(struct ath12k *ar, struct wmi_vdev_start_req_arg *arg,
|
|||
cmd->regdomain = cpu_to_le32(arg->regdomain);
|
||||
cmd->he_ops = cpu_to_le32(arg->he_ops);
|
||||
cmd->punct_bitmap = cpu_to_le32(arg->punct_bitmap);
|
||||
cmd->mbssid_flags = cpu_to_le32(arg->mbssid_flags);
|
||||
|
||||
if (!restart) {
|
||||
if (arg->ssid) {
|
||||
|
@ -1051,7 +1073,7 @@ int ath12k_wmi_vdev_start(struct ath12k *ar, struct wmi_vdev_start_req_arg *arg,
|
|||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, 0);
|
||||
|
||||
/* Note: This is a nested TLV containing:
|
||||
* [wmi_tlv][wmi_p2p_noa_descriptor][wmi_tlv]..
|
||||
* [wmi_tlv][ath12k_wmi_p2p_noa_descriptor][wmi_tlv]..
|
||||
*/
|
||||
|
||||
ptr += sizeof(*tlv);
|
||||
|
@ -1710,6 +1732,48 @@ int ath12k_wmi_send_bcn_offload_control_cmd(struct ath12k *ar,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_p2p_go_bcn_ie(struct ath12k *ar, u32 vdev_id,
|
||||
const u8 *p2p_ie)
|
||||
{
|
||||
struct ath12k_wmi_pdev *wmi = ar->wmi;
|
||||
struct wmi_p2p_go_set_beacon_ie_cmd *cmd;
|
||||
size_t p2p_ie_len, aligned_len;
|
||||
struct wmi_tlv *tlv;
|
||||
struct sk_buff *skb;
|
||||
void *ptr;
|
||||
int ret, len;
|
||||
|
||||
p2p_ie_len = p2p_ie[1] + 2;
|
||||
aligned_len = roundup(p2p_ie_len, sizeof(u32));
|
||||
|
||||
len = sizeof(*cmd) + TLV_HDR_SIZE + aligned_len;
|
||||
|
||||
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
ptr = skb->data;
|
||||
cmd = ptr;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_P2P_GO_SET_BEACON_IE,
|
||||
sizeof(*cmd));
|
||||
cmd->vdev_id = cpu_to_le32(vdev_id);
|
||||
cmd->ie_buf_len = cpu_to_le32(p2p_ie_len);
|
||||
|
||||
ptr += sizeof(*cmd);
|
||||
tlv = ptr;
|
||||
tlv->header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_ARRAY_BYTE,
|
||||
aligned_len);
|
||||
memcpy(tlv->value, p2p_ie, p2p_ie_len);
|
||||
|
||||
ret = ath12k_wmi_cmd_send(wmi, skb, WMI_P2P_GO_SET_BEACON_IE);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to send WMI_P2P_GO_SET_BEACON_IE\n");
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_bcn_tmpl(struct ath12k *ar, u32 vdev_id,
|
||||
struct ieee80211_mutable_offsets *offs,
|
||||
struct sk_buff *bcn)
|
||||
|
@ -2130,7 +2194,7 @@ void ath12k_wmi_start_scan_init(struct ath12k *ar,
|
|||
WMI_SCAN_EVENT_BSS_CHANNEL |
|
||||
WMI_SCAN_EVENT_FOREIGN_CHAN |
|
||||
WMI_SCAN_EVENT_DEQUEUED;
|
||||
arg->scan_flags |= WMI_SCAN_CHAN_STAT_EVENT;
|
||||
arg->scan_f_chan_stat_evnt = 1;
|
||||
arg->num_bssid = 1;
|
||||
|
||||
/* fill bssid_list[0] with 0xff, otherwise bssid and RA will be
|
||||
|
@ -3265,6 +3329,9 @@ ath12k_wmi_copy_resource_config(struct ath12k_wmi_resource_config_params *wmi_cf
|
|||
wmi_cfg->sched_params = cpu_to_le32(tg_cfg->sched_params);
|
||||
wmi_cfg->twt_ap_pdev_count = cpu_to_le32(tg_cfg->twt_ap_pdev_count);
|
||||
wmi_cfg->twt_ap_sta_count = cpu_to_le32(tg_cfg->twt_ap_sta_count);
|
||||
wmi_cfg->flags2 = le32_encode_bits(tg_cfg->dp_peer_meta_data_ver,
|
||||
WMI_RSRC_CFG_FLAGS2_RX_PEER_METADATA_VERSION);
|
||||
|
||||
wmi_cfg->host_service_flags = cpu_to_le32(tg_cfg->is_reg_cc_ext_event_supported <<
|
||||
WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT);
|
||||
}
|
||||
|
@ -4214,7 +4281,7 @@ ath12k_wmi_tlv_mac_phy_caps_ext_parse(struct ath12k_base *ab,
|
|||
for (i = 0; i < ab->fw_pdev_count; i++) {
|
||||
struct ath12k_fw_pdev *fw_pdev = &ab->fw_pdev[i];
|
||||
|
||||
if (fw_pdev->pdev_id == le32_to_cpu(caps->pdev_id) &&
|
||||
if (fw_pdev->pdev_id == ath12k_wmi_caps_ext_get_pdev_id(caps) &&
|
||||
fw_pdev->phy_id == le32_to_cpu(caps->phy_id)) {
|
||||
bands = fw_pdev->supported_bands;
|
||||
break;
|
||||
|
@ -4271,7 +4338,8 @@ static int ath12k_wmi_tlv_mac_phy_caps_ext(struct ath12k_base *ab, u16 tag,
|
|||
return 0;
|
||||
} else {
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
if (ab->pdevs[i].pdev_id == le32_to_cpu(caps->pdev_id))
|
||||
if (ab->pdevs[i].pdev_id ==
|
||||
ath12k_wmi_caps_ext_get_pdev_id(caps))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -4374,7 +4442,7 @@ static int ath12k_pull_vdev_start_resp_tlv(struct ath12k_base *ab, struct sk_buf
|
|||
const struct wmi_vdev_start_resp_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -4452,7 +4520,7 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
|
|||
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI, "processing regulatory ext channel list\n");
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -4738,7 +4806,7 @@ static int ath12k_pull_peer_del_resp_ev(struct ath12k_base *ab, struct sk_buff *
|
|||
const struct wmi_peer_delete_resp_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -4770,7 +4838,7 @@ static int ath12k_pull_vdev_del_resp_ev(struct ath12k_base *ab,
|
|||
const struct wmi_vdev_delete_resp_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -4790,15 +4858,15 @@ static int ath12k_pull_vdev_del_resp_ev(struct ath12k_base *ab,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath12k_pull_bcn_tx_status_ev(struct ath12k_base *ab, void *evt_buf,
|
||||
u32 len, u32 *vdev_id,
|
||||
u32 *tx_status)
|
||||
static int ath12k_pull_bcn_tx_status_ev(struct ath12k_base *ab,
|
||||
struct sk_buff *skb,
|
||||
u32 *vdev_id, u32 *tx_status)
|
||||
{
|
||||
const void **tb;
|
||||
const struct wmi_bcn_tx_status_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, evt_buf, len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -4826,7 +4894,7 @@ static int ath12k_pull_vdev_stopped_param_tlv(struct ath12k_base *ab, struct sk_
|
|||
const struct wmi_vdev_stopped_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -4948,7 +5016,7 @@ static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id,
|
|||
if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status)
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
ieee80211_tx_status_irqsafe(ar->hw, msdu);
|
||||
ieee80211_tx_status_irqsafe(ath12k_ar_to_hw(ar), msdu);
|
||||
|
||||
num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
|
||||
|
||||
|
@ -4970,7 +5038,7 @@ static int ath12k_pull_mgmt_tx_compl_param_tlv(struct ath12k_base *ab,
|
|||
const struct wmi_mgmt_tx_compl_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5006,6 +5074,10 @@ static void ath12k_wmi_event_scan_started(struct ath12k *ar)
|
|||
break;
|
||||
case ATH12K_SCAN_STARTING:
|
||||
ar->scan.state = ATH12K_SCAN_RUNNING;
|
||||
|
||||
if (ar->scan.is_roc)
|
||||
ieee80211_ready_on_channel(ath12k_ar_to_hw(ar));
|
||||
|
||||
complete(&ar->scan.started);
|
||||
break;
|
||||
}
|
||||
|
@ -5076,6 +5148,8 @@ static void ath12k_wmi_event_scan_bss_chan(struct ath12k *ar)
|
|||
|
||||
static void ath12k_wmi_event_scan_foreign_chan(struct ath12k *ar, u32 freq)
|
||||
{
|
||||
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
|
||||
|
||||
lockdep_assert_held(&ar->data_lock);
|
||||
|
||||
switch (ar->scan.state) {
|
||||
|
@ -5087,7 +5161,11 @@ static void ath12k_wmi_event_scan_foreign_chan(struct ath12k *ar, u32 freq)
|
|||
break;
|
||||
case ATH12K_SCAN_RUNNING:
|
||||
case ATH12K_SCAN_ABORTING:
|
||||
ar->scan_channel = ieee80211_get_channel(ar->hw->wiphy, freq);
|
||||
ar->scan_channel = ieee80211_get_channel(hw->wiphy, freq);
|
||||
|
||||
if (ar->scan.is_roc && ar->scan.roc_freq == freq)
|
||||
complete(&ar->scan.on_channel);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5141,7 +5219,7 @@ static int ath12k_pull_scan_ev(struct ath12k_base *ab, struct sk_buff *skb,
|
|||
const struct wmi_scan_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5174,7 +5252,7 @@ static int ath12k_pull_peer_sta_kickout_ev(struct ath12k_base *ab, struct sk_buf
|
|||
const struct wmi_peer_sta_kickout_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5201,7 +5279,7 @@ static int ath12k_pull_roam_ev(struct ath12k_base *ab, struct sk_buff *skb,
|
|||
const struct wmi_roam_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5226,13 +5304,14 @@ static int ath12k_pull_roam_ev(struct ath12k_base *ab, struct sk_buff *skb,
|
|||
static int freq_to_idx(struct ath12k *ar, int freq)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
|
||||
int band, ch, idx = 0;
|
||||
|
||||
for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
|
||||
if (!ar->mac.sbands[band].channels)
|
||||
continue;
|
||||
|
||||
sband = ar->hw->wiphy->bands[band];
|
||||
sband = hw->wiphy->bands[band];
|
||||
if (!sband)
|
||||
continue;
|
||||
|
||||
|
@ -5245,14 +5324,14 @@ exit:
|
|||
return idx;
|
||||
}
|
||||
|
||||
static int ath12k_pull_chan_info_ev(struct ath12k_base *ab, u8 *evt_buf,
|
||||
u32 len, struct wmi_chan_info_event *ch_info_ev)
|
||||
static int ath12k_pull_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,
|
||||
struct wmi_chan_info_event *ch_info_ev)
|
||||
{
|
||||
const void **tb;
|
||||
const struct wmi_chan_info_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, evt_buf, len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5291,7 +5370,7 @@ ath12k_pull_pdev_bss_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,
|
|||
const struct wmi_pdev_bss_chan_info_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5331,7 +5410,7 @@ ath12k_pull_vdev_install_key_compl_ev(struct ath12k_base *ab, struct sk_buff *sk
|
|||
const struct wmi_vdev_install_key_compl_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5362,7 +5441,7 @@ static int ath12k_pull_peer_assoc_conf_ev(struct ath12k_base *ab, struct sk_buff
|
|||
const struct wmi_peer_assoc_conf_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5384,13 +5463,13 @@ static int ath12k_pull_peer_assoc_conf_ev(struct ath12k_base *ab, struct sk_buff
|
|||
}
|
||||
|
||||
static int
|
||||
ath12k_pull_pdev_temp_ev(struct ath12k_base *ab, u8 *evt_buf,
|
||||
u32 len, const struct wmi_pdev_temperature_event *ev)
|
||||
ath12k_pull_pdev_temp_ev(struct ath12k_base *ab, struct sk_buff *skb,
|
||||
const struct wmi_pdev_temperature_event *ev)
|
||||
{
|
||||
const void **tb;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, evt_buf, len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -5725,8 +5804,7 @@ static void ath12k_bcn_tx_status_event(struct ath12k_base *ab, struct sk_buff *s
|
|||
{
|
||||
u32 vdev_id, tx_status;
|
||||
|
||||
if (ath12k_pull_bcn_tx_status_ev(ab, skb->data, skb->len,
|
||||
&vdev_id, &tx_status) != 0) {
|
||||
if (ath12k_pull_bcn_tx_status_ev(ab, skb, &vdev_id, &tx_status) != 0) {
|
||||
ath12k_warn(ab, "failed to extract bcn tx status");
|
||||
return;
|
||||
}
|
||||
|
@ -5864,7 +5942,7 @@ static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb)
|
|||
status->freq, status->band, status->signal,
|
||||
status->rate_idx);
|
||||
|
||||
ieee80211_rx_ni(ar->hw, skb);
|
||||
ieee80211_rx_ni(ath12k_ar_to_hw(ar), skb);
|
||||
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
|
@ -6037,7 +6115,7 @@ static void ath12k_peer_sta_kickout_event(struct ath12k_base *ab, struct sk_buff
|
|||
goto exit;
|
||||
}
|
||||
|
||||
sta = ieee80211_find_sta_by_ifaddr(ar->hw,
|
||||
sta = ieee80211_find_sta_by_ifaddr(ath12k_ar_to_hw(ar),
|
||||
arg.mac_addr, NULL);
|
||||
if (!sta) {
|
||||
ath12k_warn(ab, "Spurious quick kickout for STA %pM\n",
|
||||
|
@ -6110,7 +6188,7 @@ static void ath12k_chan_info_event(struct ath12k_base *ab, struct sk_buff *skb)
|
|||
/* HW channel counters frequency value in hertz */
|
||||
u32 cc_freq_hz = ab->cc_freq_hz;
|
||||
|
||||
if (ath12k_pull_chan_info_ev(ab, skb->data, skb->len, &ch_info_ev) != 0) {
|
||||
if (ath12k_pull_chan_info_ev(ab, skb, &ch_info_ev) != 0) {
|
||||
ath12k_warn(ab, "failed to extract chan info event");
|
||||
return;
|
||||
}
|
||||
|
@ -6395,7 +6473,7 @@ static void ath12k_pdev_ctl_failsafe_check_event(struct ath12k_base *ab,
|
|||
const struct wmi_pdev_ctl_failsafe_chk_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -6446,7 +6524,7 @@ ath12k_wmi_process_csa_switch_count_event(struct ath12k_base *ab,
|
|||
}
|
||||
|
||||
if (arvif->is_up && arvif->vif->bss_conf.csa_active)
|
||||
ieee80211_csa_finish(arvif->vif);
|
||||
ieee80211_csa_finish(arvif->vif, 0);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
@ -6460,7 +6538,7 @@ ath12k_wmi_pdev_csa_switch_count_status_event(struct ath12k_base *ab,
|
|||
const u32 *vdev_ids;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -6494,7 +6572,7 @@ ath12k_wmi_pdev_dfs_radar_detected_event(struct ath12k_base *ab, struct sk_buff
|
|||
struct ath12k *ar;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -6531,7 +6609,7 @@ ath12k_wmi_pdev_dfs_radar_detected_event(struct ath12k_base *ab, struct sk_buff
|
|||
if (ar->dfs_block_radar_events)
|
||||
ath12k_info(ab, "DFS Radar detected, but ignored as requested\n");
|
||||
else
|
||||
ieee80211_radar_detected(ar->hw);
|
||||
ieee80211_radar_detected(ath12k_ar_to_hw(ar));
|
||||
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
|
@ -6546,7 +6624,7 @@ ath12k_wmi_pdev_temperature_event(struct ath12k_base *ab,
|
|||
struct ath12k *ar;
|
||||
struct wmi_pdev_temperature_event ev = {0};
|
||||
|
||||
if (ath12k_pull_pdev_temp_ev(ab, skb->data, skb->len, &ev) != 0) {
|
||||
if (ath12k_pull_pdev_temp_ev(ab, skb, &ev) != 0) {
|
||||
ath12k_warn(ab, "failed to extract pdev temperature event");
|
||||
return;
|
||||
}
|
||||
|
@ -6573,7 +6651,7 @@ static void ath12k_fils_discovery_event(struct ath12k_base *ab,
|
|||
const struct wmi_fils_discovery_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab,
|
||||
|
@ -6603,7 +6681,7 @@ static void ath12k_probe_resp_tx_status_event(struct ath12k_base *ab,
|
|||
const struct wmi_probe_resp_tx_status_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab,
|
||||
|
@ -6628,6 +6706,56 @@ static void ath12k_probe_resp_tx_status_event(struct ath12k_base *ab,
|
|||
kfree(tb);
|
||||
}
|
||||
|
||||
static int ath12k_wmi_p2p_noa_event(struct ath12k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const void **tb;
|
||||
const struct wmi_p2p_noa_event *ev;
|
||||
const struct ath12k_wmi_p2p_noa_info *noa;
|
||||
struct ath12k *ar;
|
||||
int ret, vdev_id;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse P2P NoA TLV: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_P2P_NOA_EVENT];
|
||||
noa = tb[WMI_TAG_P2P_NOA_INFO];
|
||||
|
||||
if (!ev || !noa) {
|
||||
ret = -EPROTO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vdev_id = __le32_to_cpu(ev->vdev_id);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI,
|
||||
"wmi tlv p2p noa vdev_id %i descriptors %u\n",
|
||||
vdev_id, le32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_DESC_NUM));
|
||||
|
||||
rcu_read_lock();
|
||||
ar = ath12k_mac_get_ar_by_vdev_id(ab, vdev_id);
|
||||
if (!ar) {
|
||||
ath12k_warn(ab, "invalid vdev id %d in P2P NoA event\n",
|
||||
vdev_id);
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ath12k_p2p_noa_update_by_vdev_id(ar, vdev_id, noa);
|
||||
|
||||
ret = 0;
|
||||
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
out:
|
||||
kfree(tb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath12k_rfkill_state_change_event(struct ath12k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
|
@ -6635,7 +6763,7 @@ static void ath12k_rfkill_state_change_event(struct ath12k_base *ab,
|
|||
const void **tb;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
|
@ -6662,6 +6790,70 @@ static void ath12k_rfkill_state_change_event(struct ath12k_base *ab,
|
|||
kfree(tb);
|
||||
}
|
||||
|
||||
static void
|
||||
ath12k_wmi_diag_event(struct ath12k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
trace_ath12k_wmi_diag(ab, skb->data, skb->len);
|
||||
}
|
||||
|
||||
static void ath12k_wmi_twt_enable_event(struct ath12k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const void **tb;
|
||||
const struct wmi_twt_enable_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse wmi twt enable status event tlv: %d\n",
|
||||
ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_TWT_ENABLE_COMPLETE_EVENT];
|
||||
if (!ev) {
|
||||
ath12k_warn(ab, "failed to fetch twt enable wmi event\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_MAC, "wmi twt enable event pdev id %u status %u\n",
|
||||
le32_to_cpu(ev->pdev_id),
|
||||
le32_to_cpu(ev->status));
|
||||
|
||||
exit:
|
||||
kfree(tb);
|
||||
}
|
||||
|
||||
static void ath12k_wmi_twt_disable_event(struct ath12k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const void **tb;
|
||||
const struct wmi_twt_disable_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath12k_warn(ab, "failed to parse wmi twt disable status event tlv: %d\n",
|
||||
ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_TWT_DISABLE_COMPLETE_EVENT];
|
||||
if (!ev) {
|
||||
ath12k_warn(ab, "failed to fetch twt disable wmi event\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_MAC, "wmi twt disable event pdev id %d status %u\n",
|
||||
le32_to_cpu(ev->pdev_id),
|
||||
le32_to_cpu(ev->status));
|
||||
|
||||
exit:
|
||||
kfree(tb);
|
||||
}
|
||||
|
||||
static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_cmd_hdr *cmd_hdr;
|
||||
|
@ -6757,11 +6949,18 @@ static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)
|
|||
case WMI_RFKILL_STATE_CHANGE_EVENTID:
|
||||
ath12k_rfkill_state_change_event(ab, skb);
|
||||
break;
|
||||
case WMI_TWT_ENABLE_EVENTID:
|
||||
ath12k_wmi_twt_enable_event(ab, skb);
|
||||
break;
|
||||
case WMI_TWT_DISABLE_EVENTID:
|
||||
ath12k_wmi_twt_disable_event(ab, skb);
|
||||
break;
|
||||
case WMI_P2P_NOA_EVENTID:
|
||||
ath12k_wmi_p2p_noa_event(ab, skb);
|
||||
break;
|
||||
/* add Unsupported events here */
|
||||
case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID:
|
||||
case WMI_PEER_OPER_MODE_CHANGE_EVENTID:
|
||||
case WMI_TWT_ENABLE_EVENTID:
|
||||
case WMI_TWT_DISABLE_EVENTID:
|
||||
case WMI_PDEV_DMA_RING_CFG_RSP_EVENTID:
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI,
|
||||
"ignoring unsupported event 0x%x\n", id);
|
||||
|
@ -6772,6 +6971,9 @@ static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)
|
|||
case WMI_VDEV_DELETE_RESP_EVENTID:
|
||||
ath12k_vdev_delete_resp_event(ab, skb);
|
||||
break;
|
||||
case WMI_DIAG_EVENTID:
|
||||
ath12k_wmi_diag_event(ab, skb);
|
||||
break;
|
||||
/* TODO: Add remaining events */
|
||||
default:
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI, "Unknown eventid: 0x%x\n", id);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_WMI_H
|
||||
|
@ -168,10 +168,6 @@ struct wmi_tlv {
|
|||
#define WLAN_SCAN_MAX_HINT_BSSID 10
|
||||
#define MAX_RNR_BSS 5
|
||||
|
||||
#define WLAN_SCAN_PARAMS_MAX_SSID 16
|
||||
#define WLAN_SCAN_PARAMS_MAX_BSSID 4
|
||||
#define WLAN_SCAN_PARAMS_MAX_IE_LEN 256
|
||||
|
||||
#define WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG 1
|
||||
|
||||
#define WMI_BA_MODE_BUFFER_SIZE_256 3
|
||||
|
@ -2163,6 +2159,10 @@ enum wmi_tlv_service {
|
|||
|
||||
WMI_TLV_SERVICE_11BE = 289,
|
||||
|
||||
WMI_TLV_SERVICE_WMSK_COMPACTION_RX_TLVS = 361,
|
||||
|
||||
WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT = 365,
|
||||
|
||||
WMI_MAX_EXT2_SERVICE,
|
||||
};
|
||||
|
||||
|
@ -2350,6 +2350,7 @@ struct ath12k_wmi_resource_config_arg {
|
|||
u32 twt_ap_pdev_count;
|
||||
u32 twt_ap_sta_count;
|
||||
bool is_reg_cc_ext_event_supported;
|
||||
u8 dp_peer_meta_data_ver;
|
||||
};
|
||||
|
||||
struct ath12k_wmi_init_cmd_arg {
|
||||
|
@ -2402,6 +2403,7 @@ struct wmi_init_cmd {
|
|||
} __packed;
|
||||
|
||||
#define WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT 4
|
||||
#define WMI_RSRC_CFG_FLAGS2_RX_PEER_METADATA_VERSION GENMASK(5, 4)
|
||||
|
||||
struct ath12k_wmi_resource_config_params {
|
||||
__le32 tlv_header;
|
||||
|
@ -2542,9 +2544,17 @@ struct ath12k_wmi_hw_mode_cap_params {
|
|||
|
||||
#define WMI_MAX_HECAP_PHY_SIZE (3)
|
||||
|
||||
/* pdev_id is present in lower 16 bits of pdev_and_hw_link_ids in
|
||||
* ath12k_wmi_mac_phy_caps_params & ath12k_wmi_caps_ext_params.
|
||||
*
|
||||
* hw_link_id is present in higher 16 bits of pdev_and_hw_link_ids.
|
||||
*/
|
||||
#define WMI_CAPS_PARAMS_PDEV_ID GENMASK(15, 0)
|
||||
#define WMI_CAPS_PARAMS_HW_LINK_ID GENMASK(31, 16)
|
||||
|
||||
struct ath12k_wmi_mac_phy_caps_params {
|
||||
__le32 hw_mode_id;
|
||||
__le32 pdev_id;
|
||||
__le32 pdev_and_hw_link_ids;
|
||||
__le32 phy_id;
|
||||
__le32 supported_flags;
|
||||
__le32 supported_bands;
|
||||
|
@ -2636,13 +2646,7 @@ struct wmi_service_ready_ext2_event {
|
|||
|
||||
struct ath12k_wmi_caps_ext_params {
|
||||
__le32 hw_mode_id;
|
||||
union {
|
||||
struct {
|
||||
__le16 pdev_id;
|
||||
__le16 hw_link_id;
|
||||
} __packed ath12k_wmi_pdev_to_link_map;
|
||||
__le32 pdev_id;
|
||||
};
|
||||
__le32 pdev_and_hw_link_ids;
|
||||
__le32 phy_id;
|
||||
__le32 wireless_modes_ext;
|
||||
__le32 eht_cap_mac_info_2ghz[WMI_MAX_EHTCAP_MAC_SIZE];
|
||||
|
@ -2716,6 +2720,9 @@ struct wmi_vdev_create_cmd {
|
|||
struct ath12k_wmi_mac_addr_params vdev_macaddr;
|
||||
__le32 num_cfg_txrx_streams;
|
||||
__le32 pdev_id;
|
||||
__le32 mbssid_flags;
|
||||
__le32 mbssid_tx_vdev_id;
|
||||
__le32 vdev_stats_id_valid;
|
||||
__le32 vdev_stats_id;
|
||||
} __packed;
|
||||
|
||||
|
@ -2764,6 +2771,10 @@ struct ath12k_wmi_ssid_params {
|
|||
|
||||
#define ATH12K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ)
|
||||
|
||||
enum wmi_vdev_mbssid_flags {
|
||||
WMI_VDEV_MBSSID_FLAGS_NON_MBSSID_AP = BIT(0),
|
||||
};
|
||||
|
||||
struct wmi_vdev_start_request_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 vdev_id;
|
||||
|
@ -2782,7 +2793,7 @@ struct wmi_vdev_start_request_cmd {
|
|||
__le32 cac_duration_ms;
|
||||
__le32 regdomain;
|
||||
__le32 min_data_rate;
|
||||
__le32 mbssid_flags;
|
||||
__le32 mbssid_flags; /* uses enum wmi_vdev_mbssid_flags */
|
||||
__le32 mbssid_tx_vdev_id;
|
||||
__le32 eht_ops;
|
||||
__le32 punct_bitmap;
|
||||
|
@ -3146,7 +3157,7 @@ struct ath12k_wmi_element_info_arg {
|
|||
|
||||
#define WLAN_SCAN_PARAMS_MAX_SSID 16
|
||||
#define WLAN_SCAN_PARAMS_MAX_BSSID 4
|
||||
#define WLAN_SCAN_PARAMS_MAX_IE_LEN 256
|
||||
#define WLAN_SCAN_PARAMS_MAX_IE_LEN 512
|
||||
|
||||
/* Values lower than this may be refused by some firmware revisions with a scan
|
||||
* completion with a timedout reason.
|
||||
|
@ -3270,24 +3281,19 @@ struct ath12k_wmi_scan_req_arg {
|
|||
u32 vdev_id;
|
||||
u32 pdev_id;
|
||||
enum wmi_scan_priority scan_priority;
|
||||
union {
|
||||
struct {
|
||||
u32 scan_ev_started:1,
|
||||
scan_ev_completed:1,
|
||||
scan_ev_bss_chan:1,
|
||||
scan_ev_foreign_chan:1,
|
||||
scan_ev_dequeued:1,
|
||||
scan_ev_preempted:1,
|
||||
scan_ev_start_failed:1,
|
||||
scan_ev_restarted:1,
|
||||
scan_ev_foreign_chn_exit:1,
|
||||
scan_ev_invalid:1,
|
||||
scan_ev_gpio_timeout:1,
|
||||
scan_ev_suspended:1,
|
||||
scan_ev_resumed:1;
|
||||
};
|
||||
u32 scan_events;
|
||||
};
|
||||
u32 scan_ev_started:1,
|
||||
scan_ev_completed:1,
|
||||
scan_ev_bss_chan:1,
|
||||
scan_ev_foreign_chan:1,
|
||||
scan_ev_dequeued:1,
|
||||
scan_ev_preempted:1,
|
||||
scan_ev_start_failed:1,
|
||||
scan_ev_restarted:1,
|
||||
scan_ev_foreign_chn_exit:1,
|
||||
scan_ev_invalid:1,
|
||||
scan_ev_gpio_timeout:1,
|
||||
scan_ev_suspended:1,
|
||||
scan_ev_resumed:1;
|
||||
u32 dwell_time_active;
|
||||
u32 dwell_time_active_2g;
|
||||
u32 dwell_time_passive;
|
||||
|
@ -3300,36 +3306,31 @@ struct ath12k_wmi_scan_req_arg {
|
|||
u32 idle_time;
|
||||
u32 max_scan_time;
|
||||
u32 probe_delay;
|
||||
union {
|
||||
struct {
|
||||
u32 scan_f_passive:1,
|
||||
scan_f_bcast_probe:1,
|
||||
scan_f_cck_rates:1,
|
||||
scan_f_ofdm_rates:1,
|
||||
scan_f_chan_stat_evnt:1,
|
||||
scan_f_filter_prb_req:1,
|
||||
scan_f_bypass_dfs_chn:1,
|
||||
scan_f_continue_on_err:1,
|
||||
scan_f_offchan_mgmt_tx:1,
|
||||
scan_f_offchan_data_tx:1,
|
||||
scan_f_promisc_mode:1,
|
||||
scan_f_capture_phy_err:1,
|
||||
scan_f_strict_passive_pch:1,
|
||||
scan_f_half_rate:1,
|
||||
scan_f_quarter_rate:1,
|
||||
scan_f_force_active_dfs_chn:1,
|
||||
scan_f_add_tpc_ie_in_probe:1,
|
||||
scan_f_add_ds_ie_in_probe:1,
|
||||
scan_f_add_spoofed_mac_in_probe:1,
|
||||
scan_f_add_rand_seq_in_probe:1,
|
||||
scan_f_en_ie_whitelist_in_probe:1,
|
||||
scan_f_forced:1,
|
||||
scan_f_2ghz:1,
|
||||
scan_f_5ghz:1,
|
||||
scan_f_80mhz:1;
|
||||
};
|
||||
u32 scan_flags;
|
||||
};
|
||||
u32 scan_f_passive:1,
|
||||
scan_f_bcast_probe:1,
|
||||
scan_f_cck_rates:1,
|
||||
scan_f_ofdm_rates:1,
|
||||
scan_f_chan_stat_evnt:1,
|
||||
scan_f_filter_prb_req:1,
|
||||
scan_f_bypass_dfs_chn:1,
|
||||
scan_f_continue_on_err:1,
|
||||
scan_f_offchan_mgmt_tx:1,
|
||||
scan_f_offchan_data_tx:1,
|
||||
scan_f_promisc_mode:1,
|
||||
scan_f_capture_phy_err:1,
|
||||
scan_f_strict_passive_pch:1,
|
||||
scan_f_half_rate:1,
|
||||
scan_f_quarter_rate:1,
|
||||
scan_f_force_active_dfs_chn:1,
|
||||
scan_f_add_tpc_ie_in_probe:1,
|
||||
scan_f_add_ds_ie_in_probe:1,
|
||||
scan_f_add_spoofed_mac_in_probe:1,
|
||||
scan_f_add_rand_seq_in_probe:1,
|
||||
scan_f_en_ie_whitelist_in_probe:1,
|
||||
scan_f_forced:1,
|
||||
scan_f_2ghz:1,
|
||||
scan_f_5ghz:1,
|
||||
scan_f_80mhz:1;
|
||||
enum scan_dwelltime_adaptive_mode adaptive_dwell_time_mode;
|
||||
u32 burst_duration;
|
||||
u32 num_chan;
|
||||
|
@ -3489,6 +3490,37 @@ struct wmi_get_pdev_temperature_cmd {
|
|||
__le32 pdev_id;
|
||||
} __packed;
|
||||
|
||||
#define WMI_P2P_MAX_NOA_DESCRIPTORS 4
|
||||
|
||||
struct wmi_p2p_noa_event {
|
||||
__le32 vdev_id;
|
||||
} __packed;
|
||||
|
||||
struct ath12k_wmi_p2p_noa_descriptor {
|
||||
__le32 type_count; /* 255: continuous schedule, 0: reserved */
|
||||
__le32 duration; /* Absent period duration in micro seconds */
|
||||
__le32 interval; /* Absent period interval in micro seconds */
|
||||
__le32 start_time; /* 32 bit tsf time when in starts */
|
||||
} __packed;
|
||||
|
||||
#define WMI_P2P_NOA_INFO_CHANGED_FLAG BIT(0)
|
||||
#define WMI_P2P_NOA_INFO_INDEX GENMASK(15, 8)
|
||||
#define WMI_P2P_NOA_INFO_OPP_PS BIT(16)
|
||||
#define WMI_P2P_NOA_INFO_CTWIN_TU GENMASK(23, 17)
|
||||
#define WMI_P2P_NOA_INFO_DESC_NUM GENMASK(31, 24)
|
||||
|
||||
struct ath12k_wmi_p2p_noa_info {
|
||||
/* Bit 0 - Flag to indicate an update in NOA schedule
|
||||
* Bits 7-1 - Reserved
|
||||
* Bits 15-8 - Index (identifies the instance of NOA sub element)
|
||||
* Bit 16 - Opp PS state of the AP
|
||||
* Bits 23-17 - Ctwindow in TUs
|
||||
* Bits 31-24 - Number of NOA descriptors
|
||||
*/
|
||||
__le32 noa_attr;
|
||||
struct ath12k_wmi_p2p_noa_descriptor descriptors[WMI_P2P_MAX_NOA_DESCRIPTORS];
|
||||
} __packed;
|
||||
|
||||
#define WMI_BEACON_TX_BUFFER_SIZE 512
|
||||
|
||||
struct wmi_bcn_tmpl_cmd {
|
||||
|
@ -3503,6 +3535,12 @@ struct wmi_bcn_tmpl_cmd {
|
|||
__le32 esp_ie_offset;
|
||||
} __packed;
|
||||
|
||||
struct wmi_p2p_go_set_beacon_ie_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 vdev_id;
|
||||
__le32 ie_buf_len;
|
||||
} __packed;
|
||||
|
||||
struct wmi_vdev_install_key_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 vdev_id;
|
||||
|
@ -4797,6 +4835,16 @@ struct wmi_rfkill_state_change_event {
|
|||
__le32 radio_state;
|
||||
} __packed;
|
||||
|
||||
struct wmi_twt_enable_event {
|
||||
__le32 pdev_id;
|
||||
__le32 status;
|
||||
} __packed;
|
||||
|
||||
struct wmi_twt_disable_event {
|
||||
__le32 pdev_id;
|
||||
__le32 status;
|
||||
} __packed;
|
||||
|
||||
void ath12k_wmi_init_qcn9274(struct ath12k_base *ab,
|
||||
struct ath12k_wmi_resource_config_arg *config);
|
||||
void ath12k_wmi_init_wcn7850(struct ath12k_base *ab,
|
||||
|
@ -4806,6 +4854,8 @@ int ath12k_wmi_cmd_send(struct ath12k_wmi_pdev *wmi, struct sk_buff *skb,
|
|||
struct sk_buff *ath12k_wmi_alloc_skb(struct ath12k_wmi_base *wmi_sc, u32 len);
|
||||
int ath12k_wmi_mgmt_send(struct ath12k *ar, u32 vdev_id, u32 buf_id,
|
||||
struct sk_buff *frame);
|
||||
int ath12k_wmi_p2p_go_bcn_ie(struct ath12k *ar, u32 vdev_id,
|
||||
const u8 *p2p_ie);
|
||||
int ath12k_wmi_bcn_tmpl(struct ath12k *ar, u32 vdev_id,
|
||||
struct ieee80211_mutable_offsets *offs,
|
||||
struct sk_buff *bcn);
|
||||
|
@ -4917,4 +4967,30 @@ int ath12k_wmi_probe_resp_tmpl(struct ath12k *ar, u32 vdev_id,
|
|||
int ath12k_wmi_set_hw_mode(struct ath12k_base *ab,
|
||||
enum wmi_host_hw_mode_config_type mode);
|
||||
|
||||
static inline u32
|
||||
ath12k_wmi_caps_ext_get_pdev_id(const struct ath12k_wmi_caps_ext_params *param)
|
||||
{
|
||||
return le32_get_bits(param->pdev_and_hw_link_ids, WMI_CAPS_PARAMS_PDEV_ID);
|
||||
}
|
||||
|
||||
static inline u32
|
||||
ath12k_wmi_caps_ext_get_hw_link_id(const struct ath12k_wmi_caps_ext_params *param)
|
||||
{
|
||||
return le32_get_bits(param->pdev_and_hw_link_ids, WMI_CAPS_PARAMS_HW_LINK_ID);
|
||||
}
|
||||
|
||||
static inline u32
|
||||
ath12k_wmi_mac_phy_get_pdev_id(const struct ath12k_wmi_mac_phy_caps_params *param)
|
||||
{
|
||||
return le32_get_bits(param->pdev_and_hw_link_ids,
|
||||
WMI_CAPS_PARAMS_PDEV_ID);
|
||||
}
|
||||
|
||||
static inline u32
|
||||
ath12k_wmi_mac_phy_get_hw_link_id(const struct ath12k_wmi_mac_phy_caps_params *param)
|
||||
{
|
||||
return le32_get_bits(param->pdev_and_hw_link_ids,
|
||||
WMI_CAPS_PARAMS_HW_LINK_ID);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -779,6 +779,10 @@ static int ath5k_set_ringparam(struct ieee80211_hw *hw, u32 tx, u32 rx)
|
|||
|
||||
|
||||
const struct ieee80211_ops ath5k_hw_ops = {
|
||||
.add_chanctx = ieee80211_emulate_add_chanctx,
|
||||
.remove_chanctx = ieee80211_emulate_remove_chanctx,
|
||||
.change_chanctx = ieee80211_emulate_change_chanctx,
|
||||
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
|
||||
.tx = ath5k_tx,
|
||||
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = ath5k_start,
|
||||
|
|
|
@ -1119,7 +1119,7 @@ void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
|
|||
NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT);
|
||||
|
||||
wiphy_lock(vif->ar->wiphy);
|
||||
cfg80211_ch_switch_notify(vif->ndev, &chandef, 0, 0);
|
||||
cfg80211_ch_switch_notify(vif->ndev, &chandef, 0);
|
||||
wiphy_unlock(vif->ar->wiphy);
|
||||
}
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ath_ahb_remove(struct platform_device *pdev)
|
||||
static void ath_ahb_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ieee80211_hw *hw = platform_get_drvdata(pdev);
|
||||
|
||||
|
@ -155,13 +155,11 @@ static int ath_ahb_remove(struct platform_device *pdev)
|
|||
free_irq(sc->irq, sc);
|
||||
ieee80211_free_hw(sc->hw);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ath_ahb_driver = {
|
||||
.probe = ath_ahb_probe,
|
||||
.remove = ath_ahb_remove,
|
||||
.remove_new = ath_ahb_remove,
|
||||
.driver = {
|
||||
.name = "ath9k",
|
||||
},
|
||||
|
|
|
@ -643,7 +643,7 @@ static void ath_ant_try_scan(struct ath_ant_comb *antcomb,
|
|||
conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
|
||||
conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
|
||||
} else if (antcomb->rssi_sub >
|
||||
antcomb->rssi_lna1) {
|
||||
antcomb->rssi_lna2) {
|
||||
/* set to A-B */
|
||||
conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
|
||||
conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
|
||||
|
|
|
@ -851,8 +851,6 @@
|
|||
#define AR_PHY_TXGAIN_FORCED_TXBB1DBGAIN 0x0000000e
|
||||
#define AR_PHY_TXGAIN_FORCED_TXBB1DBGAIN_S 1
|
||||
|
||||
#define AR_PHY_POWER_TX_RATE1 0x9934
|
||||
#define AR_PHY_POWER_TX_RATE2 0x9938
|
||||
#define AR_PHY_POWER_TX_RATE_MAX 0x993c
|
||||
#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
|
||||
#define PHY_AGC_CLR 0x10000000
|
||||
|
@ -1041,13 +1039,6 @@
|
|||
|
||||
#define AR_PHY_TX_IQCAL_STATUS_B2_FAILED 0x00000001
|
||||
|
||||
/*
|
||||
* AGC 3 Register Map
|
||||
*/
|
||||
#define AR_AGC3_BASE 0xce00
|
||||
|
||||
#define AR_PHY_RSSI_3 (AR_AGC3_BASE + 0x180)
|
||||
|
||||
/* GLB Registers */
|
||||
#define AR_GLB_BASE 0x20000
|
||||
#define AR_GLB_GPIO_CONTROL (AR_GLB_BASE)
|
||||
|
|
|
@ -365,10 +365,10 @@ bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif)
|
|||
if (!vif || !vif->bss_conf.csa_active)
|
||||
return false;
|
||||
|
||||
if (!ieee80211_beacon_cntdwn_is_complete(vif))
|
||||
if (!ieee80211_beacon_cntdwn_is_complete(vif, 0))
|
||||
return false;
|
||||
|
||||
ieee80211_csa_finish(vif);
|
||||
ieee80211_csa_finish(vif, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -306,7 +306,6 @@ struct ath9k_htc_tx {
|
|||
DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM);
|
||||
struct timer_list cleanup_timer;
|
||||
spinlock_t tx_lock;
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
struct ath9k_htc_tx_ctl {
|
||||
|
@ -515,6 +514,7 @@ struct ath9k_htc_priv {
|
|||
unsigned long ps_usecount;
|
||||
bool ps_enabled;
|
||||
bool ps_idle;
|
||||
bool initialized;
|
||||
|
||||
#ifdef CONFIG_MAC80211_LEDS
|
||||
enum led_brightness brightness;
|
||||
|
|
|
@ -514,10 +514,10 @@ bool ath9k_htc_csa_is_finished(struct ath9k_htc_priv *priv)
|
|||
if (!vif || !vif->bss_conf.csa_active)
|
||||
return false;
|
||||
|
||||
if (!ieee80211_beacon_cntdwn_is_complete(vif))
|
||||
if (!ieee80211_beacon_cntdwn_is_complete(vif, 0))
|
||||
return false;
|
||||
|
||||
ieee80211_csa_finish(vif);
|
||||
ieee80211_csa_finish(vif, 0);
|
||||
|
||||
priv->csa_vif = NULL;
|
||||
return true;
|
||||
|
|
|
@ -966,6 +966,10 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
|
|||
|
||||
htc_handle->drv_priv = priv;
|
||||
|
||||
/* Allow ath9k_wmi_event_tasklet() to operate. */
|
||||
smp_wmb();
|
||||
priv->initialized = true;
|
||||
|
||||
return 0;
|
||||
|
||||
err_init:
|
||||
|
|
|
@ -1868,6 +1868,10 @@ static void ath9k_htc_channel_switch_beacon(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
struct ieee80211_ops ath9k_htc_ops = {
|
||||
.add_chanctx = ieee80211_emulate_add_chanctx,
|
||||
.remove_chanctx = ieee80211_emulate_remove_chanctx,
|
||||
.change_chanctx = ieee80211_emulate_change_chanctx,
|
||||
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
|
||||
.tx = ath9k_htc_tx,
|
||||
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.start = ath9k_htc_start,
|
||||
|
|
|
@ -815,10 +815,6 @@ int ath9k_tx_init(struct ath9k_htc_priv *priv)
|
|||
skb_queue_head_init(&priv->tx.data_vo_queue);
|
||||
skb_queue_head_init(&priv->tx.tx_failed);
|
||||
|
||||
/* Allow ath9k_wmi_event_tasklet(WMI_TXSTATUS_EVENTID) to operate. */
|
||||
smp_wmb();
|
||||
priv->tx.initialized = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -2786,6 +2786,10 @@ static int ath9k_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
}
|
||||
|
||||
struct ieee80211_ops ath9k_ops = {
|
||||
.add_chanctx = ieee80211_emulate_add_chanctx,
|
||||
.remove_chanctx = ieee80211_emulate_remove_chanctx,
|
||||
.change_chanctx = ieee80211_emulate_change_chanctx,
|
||||
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
|
||||
.tx = ath9k_tx,
|
||||
.start = ath9k_start,
|
||||
.stop = ath9k_stop,
|
||||
|
|
|
@ -17,10 +17,6 @@
|
|||
#ifndef REG_AIC_H
|
||||
#define REG_AIC_H
|
||||
|
||||
#define AR_SM_BASE 0xa200
|
||||
#define AR_SM1_BASE 0xb200
|
||||
#define AR_AGC_BASE 0x9e00
|
||||
|
||||
#define AR_PHY_AIC_CTRL_0_B0 (AR_SM_BASE + 0x4b0)
|
||||
#define AR_PHY_AIC_CTRL_1_B0 (AR_SM_BASE + 0x4b4)
|
||||
#define AR_PHY_AIC_CTRL_2_B0 (AR_SM_BASE + 0x4b8)
|
||||
|
|
|
@ -155,6 +155,12 @@ void ath9k_wmi_event_tasklet(struct tasklet_struct *t)
|
|||
}
|
||||
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
|
||||
|
||||
/* Check if ath9k_htc_probe_device() completed. */
|
||||
if (!data_race(priv->initialized)) {
|
||||
kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
hdr = (struct wmi_cmd_hdr *) skb->data;
|
||||
cmd_id = be16_to_cpu(hdr->command_id);
|
||||
wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
|
||||
|
@ -169,10 +175,6 @@ void ath9k_wmi_event_tasklet(struct tasklet_struct *t)
|
|||
&wmi->drv_priv->fatal_work);
|
||||
break;
|
||||
case WMI_TXSTATUS_EVENTID:
|
||||
/* Check if ath9k_tx_init() completed. */
|
||||
if (!data_race(priv->tx.initialized))
|
||||
break;
|
||||
|
||||
spin_lock_bh(&priv->tx.tx_lock);
|
||||
if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) {
|
||||
spin_unlock_bh(&priv->tx.tx_lock);
|
||||
|
|
|
@ -369,12 +369,11 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
|
|||
struct list_head bf_head;
|
||||
struct ath_tx_status ts;
|
||||
struct ath_frame_info *fi;
|
||||
int ret;
|
||||
|
||||
memset(&ts, 0, sizeof(ts));
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
|
||||
while ((ret = ath_tid_dequeue(tid, &skb)) == 0) {
|
||||
while (ath_tid_dequeue(tid, &skb) == 0) {
|
||||
fi = get_frame_info(skb);
|
||||
bf = fi->bf;
|
||||
|
||||
|
|
|
@ -1713,6 +1713,10 @@ static bool carl9170_tx_frames_pending(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
static const struct ieee80211_ops carl9170_ops = {
|
||||
.add_chanctx = ieee80211_emulate_add_chanctx,
|
||||
.remove_chanctx = ieee80211_emulate_remove_chanctx,
|
||||
.change_chanctx = ieee80211_emulate_change_chanctx,
|
||||
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
|
||||
.start = carl9170_op_start,
|
||||
.stop = carl9170_op_stop,
|
||||
.tx = carl9170_op_tx,
|
||||
|
|
|
@ -1259,6 +1259,10 @@ static void wcn36xx_ipv6_addr_change(struct ieee80211_hw *hw,
|
|||
#endif
|
||||
|
||||
static const struct ieee80211_ops wcn36xx_ops = {
|
||||
.add_chanctx = ieee80211_emulate_add_chanctx,
|
||||
.remove_chanctx = ieee80211_emulate_remove_chanctx,
|
||||
.change_chanctx = ieee80211_emulate_change_chanctx,
|
||||
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
|
||||
.start = wcn36xx_start,
|
||||
.stop = wcn36xx_stop,
|
||||
.add_interface = wcn36xx_add_interface,
|
||||
|
|
|
@ -2178,6 +2178,10 @@ static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
}
|
||||
|
||||
static const struct ieee80211_ops at76_ops = {
|
||||
.add_chanctx = ieee80211_emulate_add_chanctx,
|
||||
.remove_chanctx = ieee80211_emulate_remove_chanctx,
|
||||
.change_chanctx = ieee80211_emulate_change_chanctx,
|
||||
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
|
||||
.tx = at76_mac80211_tx,
|
||||
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.add_interface = at76_add_interface,
|
||||
|
|
|
@ -5170,6 +5170,10 @@ static int b43_op_get_survey(struct ieee80211_hw *hw, int idx,
|
|||
}
|
||||
|
||||
static const struct ieee80211_ops b43_hw_ops = {
|
||||
.add_chanctx = ieee80211_emulate_add_chanctx,
|
||||
.remove_chanctx = ieee80211_emulate_remove_chanctx,
|
||||
.change_chanctx = ieee80211_emulate_change_chanctx,
|
||||
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
|
||||
.tx = b43_op_tx,
|
||||
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.conf_tx = b43_op_conf_tx,
|
||||
|
|
|
@ -3531,6 +3531,10 @@ static int b43legacy_op_get_survey(struct ieee80211_hw *hw, int idx,
|
|||
}
|
||||
|
||||
static const struct ieee80211_ops b43legacy_hw_ops = {
|
||||
.add_chanctx = ieee80211_emulate_add_chanctx,
|
||||
.remove_chanctx = ieee80211_emulate_remove_chanctx,
|
||||
.change_chanctx = ieee80211_emulate_change_chanctx,
|
||||
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
|
||||
.tx = b43legacy_op_tx,
|
||||
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
.conf_tx = b43legacy_op_conf_tx,
|
||||
|
|
|
@ -7,21 +7,33 @@
|
|||
#include <core.h>
|
||||
#include <bus.h>
|
||||
#include <fwvid.h>
|
||||
#include <feature.h>
|
||||
|
||||
#include "vops.h"
|
||||
|
||||
static int brcmf_bca_attach(struct brcmf_pub *drvr)
|
||||
#define BRCMF_BCA_E_LAST 212
|
||||
|
||||
static void brcmf_bca_feat_attach(struct brcmf_if *ifp)
|
||||
{
|
||||
pr_err("%s: executing\n", __func__);
|
||||
/* SAE support not confirmed so disabling for now */
|
||||
ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_SAE);
|
||||
}
|
||||
|
||||
static int brcmf_bca_alloc_fweh_info(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct brcmf_fweh_info *fweh;
|
||||
|
||||
fweh = kzalloc(struct_size(fweh, evt_handler, BRCMF_BCA_E_LAST),
|
||||
GFP_KERNEL);
|
||||
if (!fweh)
|
||||
return -ENOMEM;
|
||||
|
||||
fweh->num_event_codes = BRCMF_BCA_E_LAST;
|
||||
drvr->fweh = fweh;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void brcmf_bca_detach(struct brcmf_pub *drvr)
|
||||
{
|
||||
pr_err("%s: executing\n", __func__);
|
||||
}
|
||||
|
||||
const struct brcmf_fwvid_ops brcmf_bca_ops = {
|
||||
.attach = brcmf_bca_attach,
|
||||
.detach = brcmf_bca_detach,
|
||||
.feat_attach = brcmf_bca_feat_attach,
|
||||
.alloc_fweh_info = brcmf_bca_alloc_fweh_info,
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue