mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
ath.git patches for v6.10
ath12k * debugfs support * dfs_simulate_radar debugfs file * disable Wireless Extensions * suspend and hibernation support * ACPI support * refactoring in preparation of multi-link support ath11k * support hibernation (required changes in qrtr and MHI subsystems) * ieee80211-freq-limit Device Tree property support ath10k * firmware-name Device Tree property support -----BEGIN PGP SIGNATURE----- iQFLBAABCgA1FiEEiBjanGPFTz4PRfLobhckVSbrbZsFAmYztxUXHHF1aWNfa3Zh bG9AcXVpY2luYy5jb20ACgkQbhckVSbrbZs0NQf/dYF+Pjy3eh9vabwZ05rUZwLF P/k7Q8o631Gl0LTkmGw6SseUFswAOH1uwaKpWQvjhzHE8Fy4ziMeQ+aruqtbfZ3i Q1BYsnCbQHZ+1HX0EJmB9KDz8+/G1JxOlwiux7EsujOuFixjomm08VEJ4QXGVSnj NnCg0zx/0njDqT/3KjJuoL4stAk0HDvIayiVGsQOwcQQJelLGudqTNmRPnKQkR5w yRUX+NaFlVHgbbhsnEyW3XeqKVFwgy64BtNRIVpJ0lF51aazT80DagNmw5CawznC uak1nFktAtX/AID3lWRjek3smIdlnUz39JojKW7iO60/wfZXXFbR8Xl2XEpp9g== =fF10 -----END PGP SIGNATURE----- Merge tag 'ath-next-20240502' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath ath.git patches for v6.10 ath12k * debugfs support * dfs_simulate_radar debugfs file * disable Wireless Extensions * suspend and hibernation support * ACPI support * refactoring in preparation of multi-link support ath11k * support hibernation (required changes in qrtr and MHI subsystems) * ieee80211-freq-limit Device Tree property support ath10k * firmware-name Device Tree property support
This commit is contained in:
commit
f1c26960b6
@ -73,6 +73,12 @@ properties:
|
||||
- sky85703-11
|
||||
- sky85803
|
||||
|
||||
firmware-name:
|
||||
maxItems: 1
|
||||
description:
|
||||
If present, a board or platform specific string used to lookup firmware
|
||||
files for the device.
|
||||
|
||||
wifi-firmware:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
@ -59,6 +59,8 @@ properties:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
ieee80211-freq-limit: true
|
||||
|
||||
wifi-firmware:
|
||||
type: object
|
||||
description: |
|
||||
@ -88,6 +90,7 @@ required:
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- $ref: ieee80211.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -80,6 +80,7 @@ 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,
|
||||
};
|
||||
|
||||
@ -90,7 +91,8 @@ enum dev_st_transition {
|
||||
dev_st_trans(MISSION_MODE, "MISSION MODE") \
|
||||
dev_st_trans(FP, "FLASH PROGRAMMER") \
|
||||
dev_st_trans(SYS_ERR, "SYS ERROR") \
|
||||
dev_st_trans_end(DISABLE, "DISABLE")
|
||||
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) ? \
|
||||
|
@ -468,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;
|
||||
@ -530,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);
|
||||
|
||||
@ -821,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;
|
||||
@ -1175,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;
|
||||
@ -1211,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);
|
||||
|
@ -1594,6 +1594,20 @@ static int ar5523_probe(struct usb_interface *intf,
|
||||
struct ar5523 *ar;
|
||||
int error = -ENOMEM;
|
||||
|
||||
static const u8 bulk_ep_addr[] = {
|
||||
AR5523_CMD_TX_PIPE | USB_DIR_OUT,
|
||||
AR5523_DATA_TX_PIPE | USB_DIR_OUT,
|
||||
AR5523_CMD_RX_PIPE | USB_DIR_IN,
|
||||
AR5523_DATA_RX_PIPE | USB_DIR_IN,
|
||||
0};
|
||||
|
||||
if (!usb_check_bulk_endpoints(intf, bulk_ep_addr)) {
|
||||
dev_err(&dev->dev,
|
||||
"Could not find all expected endpoints\n");
|
||||
error = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load firmware if the device requires it. This will return
|
||||
* -ENXIO on success and we'll get called back afer the usb
|
||||
|
@ -171,8 +171,10 @@ struct ath_common {
|
||||
unsigned int clockrate;
|
||||
|
||||
spinlock_t cc_lock;
|
||||
struct ath_cycle_counters cc_ani;
|
||||
struct ath_cycle_counters cc_survey;
|
||||
struct_group(cc,
|
||||
struct ath_cycle_counters cc_ani;
|
||||
struct ath_cycle_counters cc_survey;
|
||||
);
|
||||
|
||||
struct ath_regulatory regulatory;
|
||||
struct ath_regulatory reg_world_copy;
|
||||
|
@ -75,7 +75,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 2116,
|
||||
.fw = {
|
||||
.dir = QCA988X_HW_2_0_FW_DIR,
|
||||
.board = QCA988X_HW_2_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA988X_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA988X_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
@ -116,7 +115,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 2116,
|
||||
.fw = {
|
||||
.dir = QCA988X_HW_2_0_FW_DIR,
|
||||
.board = QCA988X_HW_2_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA988X_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA988X_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
@ -158,7 +156,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 2116,
|
||||
.fw = {
|
||||
.dir = QCA9887_HW_1_0_FW_DIR,
|
||||
.board = QCA9887_HW_1_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA9887_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9887_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
@ -199,7 +196,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 0,
|
||||
.fw = {
|
||||
.dir = QCA6174_HW_3_0_FW_DIR,
|
||||
.board = QCA6174_HW_3_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
@ -236,7 +232,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 8124,
|
||||
.fw = {
|
||||
.dir = QCA6174_HW_2_1_FW_DIR,
|
||||
.board = QCA6174_HW_2_1_BOARD_DATA_FILE,
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
@ -277,7 +272,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 8124,
|
||||
.fw = {
|
||||
.dir = QCA6174_HW_2_1_FW_DIR,
|
||||
.board = QCA6174_HW_2_1_BOARD_DATA_FILE,
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
@ -318,7 +312,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 8124,
|
||||
.fw = {
|
||||
.dir = QCA6174_HW_3_0_FW_DIR,
|
||||
.board = QCA6174_HW_3_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
@ -360,7 +353,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.fw = {
|
||||
/* uses same binaries as hw3.0 */
|
||||
.dir = QCA6174_HW_3_0_FW_DIR,
|
||||
.board = QCA6174_HW_3_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
@ -409,7 +401,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 12064,
|
||||
.fw = {
|
||||
.dir = QCA99X0_HW_2_0_FW_DIR,
|
||||
.board = QCA99X0_HW_2_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA99X0_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
@ -457,8 +448,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 12064,
|
||||
.fw = {
|
||||
.dir = QCA9984_HW_1_0_FW_DIR,
|
||||
.board = QCA9984_HW_1_0_BOARD_DATA_FILE,
|
||||
.eboard = QCA9984_HW_1_0_EBOARD_DATA_FILE,
|
||||
.board_size = QCA99X0_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
|
||||
.ext_board_size = QCA99X0_EXT_BOARD_DATA_SZ,
|
||||
@ -510,7 +499,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 12064,
|
||||
.fw = {
|
||||
.dir = QCA9888_HW_2_0_FW_DIR,
|
||||
.board = QCA9888_HW_2_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA99X0_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
@ -556,7 +544,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 8124,
|
||||
.fw = {
|
||||
.dir = QCA9377_HW_1_0_FW_DIR,
|
||||
.board = QCA9377_HW_1_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA9377_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
@ -597,7 +584,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 8124,
|
||||
.fw = {
|
||||
.dir = QCA9377_HW_1_0_FW_DIR,
|
||||
.board = QCA9377_HW_1_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA9377_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
@ -640,7 +626,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 8124,
|
||||
.fw = {
|
||||
.dir = QCA9377_HW_1_0_FW_DIR,
|
||||
.board = QCA9377_HW_1_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA9377_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
@ -680,7 +665,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 12064,
|
||||
.fw = {
|
||||
.dir = QCA4019_HW_1_0_FW_DIR,
|
||||
.board = QCA4019_HW_1_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA4019_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA4019_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
@ -720,6 +704,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.max_spatial_stream = 4,
|
||||
.fw = {
|
||||
.dir = WCN3990_HW_1_0_FW_DIR,
|
||||
.board_size = WCN3990_BOARD_DATA_SZ,
|
||||
.board_ext_size = WCN3990_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.sw_decrypt_mcast_mgmt = true,
|
||||
.rx_desc_ops = &wcn3990_rx_desc_ops,
|
||||
@ -942,11 +928,20 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar,
|
||||
if (dir == NULL)
|
||||
dir = ".";
|
||||
|
||||
if (ar->board_name) {
|
||||
snprintf(filename, sizeof(filename), "%s/%s/%s",
|
||||
dir, ar->board_name, file);
|
||||
ret = firmware_request_nowarn(&fw, filename, ar->dev);
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot fw request '%s': %d\n",
|
||||
filename, ret);
|
||||
if (!ret)
|
||||
return fw;
|
||||
}
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s/%s", dir, file);
|
||||
ret = firmware_request_nowarn(&fw, filename, ar->dev);
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot fw request '%s': %d\n",
|
||||
filename, ret);
|
||||
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
@ -1288,11 +1283,6 @@ static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)
|
||||
char boardname[100];
|
||||
|
||||
if (bd_ie_type == ATH10K_BD_IE_BOARD) {
|
||||
if (!ar->hw_params.fw.board) {
|
||||
ath10k_err(ar, "failed to find board file fw entry\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
scnprintf(boardname, sizeof(boardname), "board-%s-%s.bin",
|
||||
ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));
|
||||
|
||||
@ -1302,7 +1292,7 @@ static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)
|
||||
if (IS_ERR(ar->normal_mode_fw.board)) {
|
||||
fw = ath10k_fetch_fw_file(ar,
|
||||
ar->hw_params.fw.dir,
|
||||
ar->hw_params.fw.board);
|
||||
ATH10K_BOARD_DATA_FILE);
|
||||
ar->normal_mode_fw.board = fw;
|
||||
}
|
||||
|
||||
@ -1312,13 +1302,8 @@ static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)
|
||||
ar->normal_mode_fw.board_data = ar->normal_mode_fw.board->data;
|
||||
ar->normal_mode_fw.board_len = ar->normal_mode_fw.board->size;
|
||||
} else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) {
|
||||
if (!ar->hw_params.fw.eboard) {
|
||||
ath10k_err(ar, "failed to find eboard file fw entry\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,
|
||||
ar->hw_params.fw.eboard);
|
||||
ATH10K_EBOARD_DATA_FILE);
|
||||
ar->normal_mode_fw.ext_board = fw;
|
||||
if (IS_ERR(ar->normal_mode_fw.ext_board))
|
||||
return PTR_ERR(ar->normal_mode_fw.ext_board);
|
||||
|
@ -1081,6 +1081,8 @@ struct ath10k {
|
||||
*/
|
||||
const struct ath10k_fw_components *running_fw;
|
||||
|
||||
const char *board_name;
|
||||
|
||||
const struct firmware *pre_cal_file;
|
||||
const struct firmware *cal_file;
|
||||
|
||||
|
@ -439,7 +439,7 @@ ath10k_dbg_sta_write_peer_debug_trigger(struct file *file,
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return count;
|
||||
return ret ?: count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_peer_debug_trigger = {
|
||||
|
@ -39,14 +39,12 @@ enum ath10k_bus {
|
||||
#define QCA988X_HW_2_0_VERSION 0x4100016c
|
||||
#define QCA988X_HW_2_0_CHIP_ID_REV 0x2
|
||||
#define QCA988X_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA988X/hw2.0"
|
||||
#define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9887 1.0 definitions */
|
||||
#define QCA9887_HW_1_0_VERSION 0x4100016d
|
||||
#define QCA9887_HW_1_0_CHIP_ID_REV 0
|
||||
#define QCA9887_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9887/hw1.0"
|
||||
#define QCA9887_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA9887_HW_1_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA6174 target BMI version signatures */
|
||||
@ -85,11 +83,9 @@ enum qca9377_chip_id_rev {
|
||||
};
|
||||
|
||||
#define QCA6174_HW_2_1_FW_DIR ATH10K_FW_DIR "/QCA6174/hw2.1"
|
||||
#define QCA6174_HW_2_1_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA6174_HW_2_1_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
#define QCA6174_HW_3_0_FW_DIR ATH10K_FW_DIR "/QCA6174/hw3.0"
|
||||
#define QCA6174_HW_3_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA6174_HW_3_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA99X0 1.0 definitions (unsupported) */
|
||||
@ -99,7 +95,6 @@ enum qca9377_chip_id_rev {
|
||||
#define QCA99X0_HW_2_0_DEV_VERSION 0x01000000
|
||||
#define QCA99X0_HW_2_0_CHIP_ID_REV 0x1
|
||||
#define QCA99X0_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA99X0/hw2.0"
|
||||
#define QCA99X0_HW_2_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA99X0_HW_2_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9984 1.0 defines */
|
||||
@ -107,8 +102,6 @@ enum qca9377_chip_id_rev {
|
||||
#define QCA9984_HW_DEV_TYPE 0xa
|
||||
#define QCA9984_HW_1_0_CHIP_ID_REV 0x0
|
||||
#define QCA9984_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9984/hw1.0"
|
||||
#define QCA9984_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA9984_HW_1_0_EBOARD_DATA_FILE "eboard.bin"
|
||||
#define QCA9984_HW_1_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9888 2.0 defines */
|
||||
@ -116,18 +109,15 @@ enum qca9377_chip_id_rev {
|
||||
#define QCA9888_HW_DEV_TYPE 0xc
|
||||
#define QCA9888_HW_2_0_CHIP_ID_REV 0x0
|
||||
#define QCA9888_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA9888/hw2.0"
|
||||
#define QCA9888_HW_2_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA9888_HW_2_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9377 1.0 definitions */
|
||||
#define QCA9377_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9377/hw1.0"
|
||||
#define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA9377_HW_1_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA4019 1.0 definitions */
|
||||
#define QCA4019_HW_1_0_DEV_VERSION 0x01000000
|
||||
#define QCA4019_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA4019/hw1.0"
|
||||
#define QCA4019_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA4019_HW_1_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* WCN3990 1.0 definitions */
|
||||
@ -159,7 +149,9 @@ enum qca9377_chip_id_rev {
|
||||
#define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K"
|
||||
#define ATH10K_BOARD_MAGIC "QCA-ATH10K-BOARD"
|
||||
|
||||
#define ATH10K_BOARD_DATA_FILE "board.bin"
|
||||
#define ATH10K_BOARD_API2_FILE "board-2.bin"
|
||||
#define ATH10K_EBOARD_DATA_FILE "eboard.bin"
|
||||
|
||||
#define REG_DUMP_COUNT_QCA988X 60
|
||||
|
||||
@ -553,9 +545,7 @@ struct ath10k_hw_params {
|
||||
|
||||
struct ath10k_hw_params_fw {
|
||||
const char *dir;
|
||||
const char *board;
|
||||
size_t board_size;
|
||||
const char *eboard;
|
||||
size_t ext_board_size;
|
||||
size_t board_ext_size;
|
||||
} fw;
|
||||
|
@ -3826,28 +3826,28 @@ MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API2_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API3_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API4_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API5_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_BOARD_API2_FILE);
|
||||
|
||||
/* QCA9887 1.0 firmware files */
|
||||
MODULE_FIRMWARE(QCA9887_HW_1_0_FW_DIR "/" ATH10K_FW_API5_FILE);
|
||||
MODULE_FIRMWARE(QCA9887_HW_1_0_FW_DIR "/" QCA9887_HW_1_0_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(QCA9887_HW_1_0_FW_DIR "/" ATH10K_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(QCA9887_HW_1_0_FW_DIR "/" ATH10K_BOARD_API2_FILE);
|
||||
|
||||
/* QCA6174 2.1 firmware files */
|
||||
MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API4_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API5_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" QCA6174_HW_2_1_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_BOARD_API2_FILE);
|
||||
|
||||
/* QCA6174 3.1 firmware files */
|
||||
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API4_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API5_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API6_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_BOARD_API2_FILE);
|
||||
|
||||
/* QCA9377 1.0 firmware files */
|
||||
MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" ATH10K_FW_API6_FILE);
|
||||
MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" ATH10K_FW_API5_FILE);
|
||||
MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" QCA9377_HW_1_0_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" ATH10K_BOARD_DATA_FILE);
|
||||
|
@ -1338,6 +1338,9 @@ static void ath10k_snoc_quirks_init(struct ath10k *ar)
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct device *dev = &ar_snoc->dev->dev;
|
||||
|
||||
/* ignore errors, keep NULL if there is no property */
|
||||
of_property_read_string(dev->of_node, "firmware-name", &ar->board_name);
|
||||
|
||||
if (of_property_read_bool(dev->of_node, "qcom,snoc-host-cap-8bit-quirk"))
|
||||
set_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags);
|
||||
}
|
||||
|
@ -491,4 +491,7 @@ struct host_interest {
|
||||
#define QCA4019_BOARD_DATA_SZ 12064
|
||||
#define QCA4019_BOARD_EXT_DATA_SZ 0
|
||||
|
||||
#define WCN3990_BOARD_DATA_SZ 26328
|
||||
#define WCN3990_BOARD_EXT_DATA_SZ 0
|
||||
|
||||
#endif /* __TARGADDRS_H__ */
|
||||
|
@ -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);
|
||||
|
||||
@ -1261,7 +1261,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;
|
||||
|
@ -906,12 +906,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",
|
||||
@ -922,20 +916,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;
|
||||
@ -944,7 +967,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);
|
||||
@ -952,29 +975,46 @@ 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);
|
||||
|
||||
ath11k_hif_ce_irq_enable(ab);
|
||||
ath11k_hif_irq_enable(ab);
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -2072,6 +2112,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)
|
||||
@ -2141,7 +2183,7 @@ static void ath11k_core_reset(struct work_struct *work)
|
||||
ath11k_hif_irq_disable(ab);
|
||||
ath11k_hif_ce_irq_disable(ab);
|
||||
|
||||
ath11k_hif_power_down(ab);
|
||||
ath11k_hif_power_down(ab, false);
|
||||
ath11k_hif_power_up(ab);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n");
|
||||
@ -2214,7 +2256,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);
|
||||
@ -2267,6 +2309,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
|
||||
@ -1033,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;
|
||||
@ -1232,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);
|
||||
|
||||
|
@ -664,7 +664,7 @@ struct hal_srng_config {
|
||||
};
|
||||
|
||||
/**
|
||||
* enum hal_rx_buf_return_buf_manager
|
||||
* enum hal_rx_buf_return_buf_manager - manager for returned rx buffers
|
||||
*
|
||||
* @HAL_RX_BUF_RBM_WBM_IDLE_BUF_LIST: Buffer returned to WBM idle buffer list
|
||||
* @HAL_RX_BUF_RBM_WBM_IDLE_DESC_LIST: Descriptor returned to WBM idle
|
||||
|
@ -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)
|
||||
|
@ -10126,6 +10126,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
wiphy_read_of_freq_limits(ar->hw->wiphy);
|
||||
ath11k_mac_setup_ht_vht_cap(ar, cap, &ht_cap);
|
||||
ath11k_mac_setup_he_cap(ar, cap);
|
||||
|
||||
|
@ -453,9 +453,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
|
||||
|
@ -638,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);
|
||||
|
||||
@ -649,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);
|
||||
}
|
||||
@ -970,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;
|
||||
@ -998,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)
|
||||
@ -1035,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",
|
||||
|
@ -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;
|
||||
|
@ -8651,30 +8651,27 @@ exit:
|
||||
kfree(tb);
|
||||
}
|
||||
|
||||
static int ath11k_wmi_p2p_noa_event(struct ath11k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
static void ath11k_wmi_p2p_noa_event(struct ath11k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const void **tb;
|
||||
const struct wmi_p2p_noa_event *ev;
|
||||
const struct ath11k_wmi_p2p_noa_info *noa;
|
||||
struct ath11k *ar;
|
||||
int ret, vdev_id;
|
||||
int vdev_id;
|
||||
u8 noa_descriptors;
|
||||
|
||||
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);
|
||||
return ret;
|
||||
ath11k_warn(ab, "failed to parse tlv: %ld\n", PTR_ERR(tb));
|
||||
return;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_P2P_NOA_EVENT];
|
||||
noa = tb[WMI_TAG_P2P_NOA_INFO];
|
||||
|
||||
if (!ev || !noa) {
|
||||
ret = -EPROTO;
|
||||
if (!ev || !noa)
|
||||
goto out;
|
||||
}
|
||||
|
||||
vdev_id = ev->vdev_id;
|
||||
noa_descriptors = u32_get_bits(noa->noa_attr,
|
||||
@ -8683,7 +8680,6 @@ static int ath11k_wmi_p2p_noa_event(struct ath11k_base *ab,
|
||||
if (noa_descriptors > WMI_P2P_MAX_NOA_DESCRIPTORS) {
|
||||
ath11k_warn(ab, "invalid descriptor num %d in P2P NoA event\n",
|
||||
noa_descriptors);
|
||||
return -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -8696,7 +8692,6 @@ static int ath11k_wmi_p2p_noa_event(struct ath11k_base *ab,
|
||||
if (!ar) {
|
||||
ath11k_warn(ab, "invalid vdev id %d in P2P NoA event\n",
|
||||
vdev_id);
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
@ -8706,7 +8701,6 @@ unlock:
|
||||
rcu_read_unlock();
|
||||
out:
|
||||
kfree(tb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
|
@ -24,6 +24,15 @@ config ATH12K_DEBUG
|
||||
If unsure, say Y to make it easier to debug problems. But if
|
||||
you want optimal performance choose N.
|
||||
|
||||
config ATH12K_DEBUGFS
|
||||
bool "QTI ath12k debugfs support"
|
||||
depends on ATH12K && MAC80211_DEBUGFS
|
||||
help
|
||||
Enable ath12k debugfs support
|
||||
|
||||
If unsure, say Y to make it easier to debug problems. But if
|
||||
you want optimal performance choose N.
|
||||
|
||||
config ATH12K_TRACING
|
||||
bool "ath12k tracing support"
|
||||
depends on ATH12K && EVENT_TRACING
|
||||
|
@ -23,6 +23,8 @@ ath12k-y += core.o \
|
||||
fw.o \
|
||||
p2p.o
|
||||
|
||||
ath12k-$(CONFIG_ATH12K_DEBUGFS) += debugfs.o
|
||||
ath12k-$(CONFIG_ACPI) += acpi.o
|
||||
ath12k-$(CONFIG_ATH12K_TRACING) += trace.o
|
||||
|
||||
# for tracing framework to find trace.h
|
||||
|
394
drivers/net/wireless/ath/ath12k/acpi.c
Normal file
394
drivers/net/wireless/ath/ath12k/acpi.c
Normal file
@ -0,0 +1,394 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "acpi.h"
|
||||
#include "debug.h"
|
||||
|
||||
static int ath12k_acpi_dsm_get_data(struct ath12k_base *ab, int func)
|
||||
{
|
||||
union acpi_object *obj;
|
||||
acpi_handle root_handle;
|
||||
int ret;
|
||||
|
||||
root_handle = ACPI_HANDLE(ab->dev);
|
||||
if (!root_handle) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "invalid acpi handler\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
obj = acpi_evaluate_dsm(root_handle, ab->hw_params->acpi_guid, 0, func,
|
||||
NULL);
|
||||
|
||||
if (!obj) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "acpi_evaluate_dsm() failed\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (obj->type == ACPI_TYPE_INTEGER) {
|
||||
ab->acpi.func_bit = obj->integer.value;
|
||||
} else if (obj->type == ACPI_TYPE_BUFFER) {
|
||||
switch (func) {
|
||||
case ATH12K_ACPI_DSM_FUNC_TAS_CFG:
|
||||
if (obj->buffer.length != ATH12K_ACPI_DSM_TAS_CFG_SIZE) {
|
||||
ath12k_warn(ab, "invalid ACPI DSM TAS config size: %d\n",
|
||||
obj->buffer.length);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(&ab->acpi.tas_cfg, obj->buffer.pointer,
|
||||
obj->buffer.length);
|
||||
|
||||
break;
|
||||
case ATH12K_ACPI_DSM_FUNC_TAS_DATA:
|
||||
if (obj->buffer.length != ATH12K_ACPI_DSM_TAS_DATA_SIZE) {
|
||||
ath12k_warn(ab, "invalid ACPI DSM TAS data size: %d\n",
|
||||
obj->buffer.length);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(&ab->acpi.tas_sar_power_table, obj->buffer.pointer,
|
||||
obj->buffer.length);
|
||||
|
||||
break;
|
||||
case ATH12K_ACPI_DSM_FUNC_BIOS_SAR:
|
||||
if (obj->buffer.length != ATH12K_ACPI_DSM_BIOS_SAR_DATA_SIZE) {
|
||||
ath12k_warn(ab, "invalid ACPI BIOS SAR data size: %d\n",
|
||||
obj->buffer.length);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(&ab->acpi.bios_sar_data, obj->buffer.pointer,
|
||||
obj->buffer.length);
|
||||
|
||||
break;
|
||||
case ATH12K_ACPI_DSM_FUNC_GEO_OFFSET:
|
||||
if (obj->buffer.length != ATH12K_ACPI_DSM_GEO_OFFSET_DATA_SIZE) {
|
||||
ath12k_warn(ab, "invalid ACPI GEO OFFSET data size: %d\n",
|
||||
obj->buffer.length);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(&ab->acpi.geo_offset_data, obj->buffer.pointer,
|
||||
obj->buffer.length);
|
||||
|
||||
break;
|
||||
case ATH12K_ACPI_DSM_FUNC_INDEX_CCA:
|
||||
if (obj->buffer.length != ATH12K_ACPI_DSM_CCA_DATA_SIZE) {
|
||||
ath12k_warn(ab, "invalid ACPI DSM CCA data size: %d\n",
|
||||
obj->buffer.length);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(&ab->acpi.cca_data, obj->buffer.pointer,
|
||||
obj->buffer.length);
|
||||
|
||||
break;
|
||||
case ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE:
|
||||
if (obj->buffer.length != ATH12K_ACPI_DSM_BAND_EDGE_DATA_SIZE) {
|
||||
ath12k_warn(ab, "invalid ACPI DSM band edge data size: %d\n",
|
||||
obj->buffer.length);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(&ab->acpi.band_edge_power, obj->buffer.pointer,
|
||||
obj->buffer.length);
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ath12k_warn(ab, "ACPI DSM method returned an unsupported object type: %d\n",
|
||||
obj->type);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
ACPI_FREE(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath12k_acpi_set_power_limit(struct ath12k_base *ab)
|
||||
{
|
||||
const u8 *tas_sar_power_table = ab->acpi.tas_sar_power_table;
|
||||
int ret;
|
||||
|
||||
if (tas_sar_power_table[0] != ATH12K_ACPI_TAS_DATA_VERSION ||
|
||||
tas_sar_power_table[1] != ATH12K_ACPI_TAS_DATA_ENABLE) {
|
||||
ath12k_warn(ab, "latest ACPI TAS data is invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_DATA_TYPE,
|
||||
tas_sar_power_table,
|
||||
ATH12K_ACPI_DSM_TAS_DATA_SIZE);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to send ACPI TAS data table: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath12k_acpi_set_bios_sar_power(struct ath12k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ab->acpi.bios_sar_data[0] != ATH12K_ACPI_POWER_LIMIT_VERSION ||
|
||||
ab->acpi.bios_sar_data[1] != ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG) {
|
||||
ath12k_warn(ab, "invalid latest ACPI BIOS SAR data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = ath12k_wmi_set_bios_sar_cmd(ab, ab->acpi.bios_sar_data);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to set ACPI BIOS SAR table: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath12k_acpi_dsm_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
int ret;
|
||||
struct ath12k_base *ab = data;
|
||||
|
||||
if (event == ATH12K_ACPI_NOTIFY_EVENT) {
|
||||
ath12k_warn(ab, "unknown acpi notify %u\n", event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ab->acpi.acpi_tas_enable) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "acpi_tas_enable is false\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_DATA);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to update ACPI TAS data table: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = ath12k_acpi_set_power_limit(ab);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to set ACPI TAS power limit data: %d", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ab->acpi.acpi_bios_sar_enable)
|
||||
return;
|
||||
|
||||
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BIOS_SAR);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to update BIOS SAR: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = ath12k_acpi_set_bios_sar_power(ab);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to set BIOS SAR power limit: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int ath12k_acpi_set_bios_sar_params(struct ath12k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath12k_wmi_set_bios_sar_cmd(ab, ab->acpi.bios_sar_data);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to set ACPI BIOS SAR table: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath12k_wmi_set_bios_geo_cmd(ab, ab->acpi.geo_offset_data);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to set ACPI BIOS GEO table: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath12k_acpi_set_tas_params(struct ath12k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_CONFIG_TYPE,
|
||||
ab->acpi.tas_cfg,
|
||||
ATH12K_ACPI_DSM_TAS_CFG_SIZE);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to send ACPI TAS config table parameter: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_DATA_TYPE,
|
||||
ab->acpi.tas_sar_power_table,
|
||||
ATH12K_ACPI_DSM_TAS_DATA_SIZE);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to send ACPI TAS data table parameter: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath12k_acpi_start(struct ath12k_base *ab)
|
||||
{
|
||||
acpi_status status;
|
||||
u8 *buf;
|
||||
int ret;
|
||||
|
||||
if (!ab->hw_params->acpi_guid)
|
||||
/* not supported with this hardware */
|
||||
return 0;
|
||||
|
||||
ab->acpi.acpi_tas_enable = false;
|
||||
|
||||
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS);
|
||||
if (ret) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "failed to get ACPI DSM data: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_TAS_CFG)) {
|
||||
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_CFG);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to get ACPI TAS config table: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_TAS_DATA)) {
|
||||
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_DATA);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to get ACPI TAS data table: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_TAS_CFG) &&
|
||||
ab->acpi.tas_sar_power_table[0] == ATH12K_ACPI_TAS_DATA_VERSION &&
|
||||
ab->acpi.tas_sar_power_table[1] == ATH12K_ACPI_TAS_DATA_ENABLE)
|
||||
ab->acpi.acpi_tas_enable = true;
|
||||
}
|
||||
|
||||
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_BIOS_SAR)) {
|
||||
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BIOS_SAR);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to get ACPI bios sar data: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_GEO_OFFSET)) {
|
||||
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_GEO_OFFSET);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to get ACPI geo offset data: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_BIOS_SAR) &&
|
||||
ab->acpi.bios_sar_data[0] == ATH12K_ACPI_POWER_LIMIT_VERSION &&
|
||||
ab->acpi.bios_sar_data[1] == ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG &&
|
||||
!ab->acpi.acpi_tas_enable)
|
||||
ab->acpi.acpi_bios_sar_enable = true;
|
||||
}
|
||||
|
||||
if (ab->acpi.acpi_tas_enable) {
|
||||
ret = ath12k_acpi_set_tas_params(ab);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to send ACPI parameters: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (ab->acpi.acpi_bios_sar_enable) {
|
||||
ret = ath12k_acpi_set_bios_sar_params(ab);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_CCA)) {
|
||||
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_INDEX_CCA);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to get ACPI DSM CCA threshold configuration: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ab->acpi.cca_data[0] == ATH12K_ACPI_CCA_THR_VERSION &&
|
||||
ab->acpi.cca_data[ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET] ==
|
||||
ATH12K_ACPI_CCA_THR_ENABLE_FLAG) {
|
||||
buf = ab->acpi.cca_data + ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET;
|
||||
ret = ath12k_wmi_set_bios_cmd(ab,
|
||||
WMI_BIOS_PARAM_CCA_THRESHOLD_TYPE,
|
||||
buf,
|
||||
ATH12K_ACPI_CCA_THR_OFFSET_LEN);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to set ACPI DSM CCA threshold: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi,
|
||||
ATH12K_ACPI_FUNC_BIT_BAND_EDGE_CHAN_POWER)) {
|
||||
ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to get ACPI DSM band edge channel power: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ab->acpi.band_edge_power[0] == ATH12K_ACPI_BAND_EDGE_VERSION &&
|
||||
ab->acpi.band_edge_power[1] == ATH12K_ACPI_BAND_EDGE_ENABLE_FLAG) {
|
||||
ret = ath12k_wmi_set_bios_cmd(ab,
|
||||
WMI_BIOS_PARAM_TYPE_BANDEDGE,
|
||||
ab->acpi.band_edge_power,
|
||||
sizeof(ab->acpi.band_edge_power));
|
||||
if (ret) {
|
||||
ath12k_warn(ab,
|
||||
"failed to set ACPI DSM band edge channel power: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status = acpi_install_notify_handler(ACPI_HANDLE(ab->dev),
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
ath12k_acpi_dsm_notify, ab);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ath12k_warn(ab, "failed to install DSM notify callback: %d\n", status);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ab->acpi.started = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath12k_acpi_stop(struct ath12k_base *ab)
|
||||
{
|
||||
if (!ab->acpi.started)
|
||||
return;
|
||||
|
||||
acpi_remove_notify_handler(ACPI_HANDLE(ab->dev),
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
ath12k_acpi_dsm_notify);
|
||||
}
|
76
drivers/net/wireless/ath/ath12k/acpi.h
Normal file
76
drivers/net/wireless/ath/ath12k/acpi.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef ATH12K_ACPI_H
|
||||
#define ATH12K_ACPI_H
|
||||
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#define ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS 0
|
||||
#define ATH12K_ACPI_DSM_FUNC_BIOS_SAR 4
|
||||
#define ATH12K_ACPI_DSM_FUNC_GEO_OFFSET 5
|
||||
#define ATH12K_ACPI_DSM_FUNC_INDEX_CCA 6
|
||||
#define ATH12K_ACPI_DSM_FUNC_TAS_CFG 8
|
||||
#define ATH12K_ACPI_DSM_FUNC_TAS_DATA 9
|
||||
#define ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE 10
|
||||
|
||||
#define ATH12K_ACPI_FUNC_BIT_BIOS_SAR BIT(3)
|
||||
#define ATH12K_ACPI_FUNC_BIT_GEO_OFFSET BIT(4)
|
||||
#define ATH12K_ACPI_FUNC_BIT_CCA BIT(5)
|
||||
#define ATH12K_ACPI_FUNC_BIT_TAS_CFG BIT(7)
|
||||
#define ATH12K_ACPI_FUNC_BIT_TAS_DATA BIT(8)
|
||||
#define ATH12K_ACPI_FUNC_BIT_BAND_EDGE_CHAN_POWER BIT(9)
|
||||
|
||||
#define ATH12K_ACPI_NOTIFY_EVENT 0x86
|
||||
#define ATH12K_ACPI_FUNC_BIT_VALID(_acdata, _func) (((_acdata).func_bit) & (_func))
|
||||
|
||||
#define ATH12K_ACPI_TAS_DATA_VERSION 0x1
|
||||
#define ATH12K_ACPI_TAS_DATA_ENABLE 0x1
|
||||
#define ATH12K_ACPI_POWER_LIMIT_VERSION 0x1
|
||||
#define ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG 0x1
|
||||
#define ATH12K_ACPI_CCA_THR_VERSION 0x1
|
||||
#define ATH12K_ACPI_CCA_THR_ENABLE_FLAG 0x1
|
||||
#define ATH12K_ACPI_BAND_EDGE_VERSION 0x1
|
||||
#define ATH12K_ACPI_BAND_EDGE_ENABLE_FLAG 0x1
|
||||
|
||||
#define ATH12K_ACPI_GEO_OFFSET_DATA_OFFSET 1
|
||||
#define ATH12K_ACPI_DBS_BACKOFF_DATA_OFFSET 2
|
||||
#define ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET 5
|
||||
#define ATH12K_ACPI_BIOS_SAR_DBS_BACKOFF_LEN 10
|
||||
#define ATH12K_ACPI_POWER_LIMIT_DATA_OFFSET 12
|
||||
#define ATH12K_ACPI_BIOS_SAR_GEO_OFFSET_LEN 18
|
||||
#define ATH12K_ACPI_BIOS_SAR_TABLE_LEN 22
|
||||
#define ATH12K_ACPI_CCA_THR_OFFSET_LEN 36
|
||||
|
||||
#define ATH12K_ACPI_DSM_TAS_DATA_SIZE 69
|
||||
#define ATH12K_ACPI_DSM_BAND_EDGE_DATA_SIZE 100
|
||||
#define ATH12K_ACPI_DSM_TAS_CFG_SIZE 108
|
||||
|
||||
#define ATH12K_ACPI_DSM_GEO_OFFSET_DATA_SIZE (ATH12K_ACPI_GEO_OFFSET_DATA_OFFSET + \
|
||||
ATH12K_ACPI_BIOS_SAR_GEO_OFFSET_LEN)
|
||||
#define ATH12K_ACPI_DSM_BIOS_SAR_DATA_SIZE (ATH12K_ACPI_POWER_LIMIT_DATA_OFFSET + \
|
||||
ATH12K_ACPI_BIOS_SAR_TABLE_LEN)
|
||||
#define ATH12K_ACPI_DSM_CCA_DATA_SIZE (ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET + \
|
||||
ATH12K_ACPI_CCA_THR_OFFSET_LEN)
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
|
||||
int ath12k_acpi_start(struct ath12k_base *ab);
|
||||
void ath12k_acpi_stop(struct ath12k_base *ab);
|
||||
|
||||
#else
|
||||
|
||||
static inline int ath12k_acpi_start(struct ath12k_base *ab)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath12k_acpi_stop(struct ath12k_base *ab)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#endif /* ATH12K_ACPI_H */
|
@ -15,6 +15,7 @@
|
||||
#include "debug.h"
|
||||
#include "hif.h"
|
||||
#include "fw.h"
|
||||
#include "debugfs.h"
|
||||
|
||||
unsigned int ath12k_debug_mask;
|
||||
module_param_named(debug_mask, ath12k_debug_mask, uint, 0644);
|
||||
@ -43,67 +44,90 @@ static int ath12k_core_rfkill_config(struct ath12k_base *ab)
|
||||
|
||||
int ath12k_core_suspend(struct ath12k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
struct ath12k *ar;
|
||||
int ret, i;
|
||||
|
||||
if (!ab->hw_params->supports_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* TODO: there can frames in queues so for now add delay as a hack.
|
||||
* Need to implement to handle and remove this delay.
|
||||
rcu_read_lock();
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
ar = ath12k_mac_get_ar_by_pdev_id(ab, i);
|
||||
if (!ar)
|
||||
continue;
|
||||
ret = ath12k_mac_wait_tx_complete(ar);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to wait tx complete: %d\n", ret);
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
/* PM framework skips suspend_late/resume_early callbacks
|
||||
* if other devices report errors in their suspend callbacks.
|
||||
* However ath12k_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
|
||||
* ath12k_core_restart(), making ath12k_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 ath12k_core_resume_early().
|
||||
*/
|
||||
msleep(500);
|
||||
complete(&ab->restart_completed);
|
||||
|
||||
ret = ath12k_dp_rx_pktlog_stop(ab, true);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to stop dp rx (and timer) pktlog during suspend: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath12k_core_suspend);
|
||||
|
||||
ret = ath12k_dp_rx_pktlog_stop(ab, false);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to stop dp rx pktlog during suspend: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
int ath12k_core_suspend_late(struct ath12k_base *ab)
|
||||
{
|
||||
if (!ab->hw_params->supports_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ath12k_hif_irq_disable(ab);
|
||||
ath12k_hif_ce_irq_disable(ab);
|
||||
|
||||
ret = ath12k_hif_suspend(ab);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to suspend hif: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ath12k_hif_power_down(ab, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath12k_core_suspend_late);
|
||||
|
||||
int ath12k_core_resume(struct ath12k_base *ab)
|
||||
int ath12k_core_resume_early(struct ath12k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!ab->hw_params->supports_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = ath12k_hif_resume(ab);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to resume hif during resume: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
reinit_completion(&ab->restart_completed);
|
||||
ret = ath12k_hif_power_up(ab);
|
||||
if (ret)
|
||||
ath12k_warn(ab, "failed to power up hif during resume: %d\n", ret);
|
||||
|
||||
ath12k_hif_ce_irq_enable(ab);
|
||||
ath12k_hif_irq_enable(ab);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ath12k_core_resume_early);
|
||||
|
||||
ret = ath12k_dp_rx_pktlog_start(ab);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to start rx pktlog during resume: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
int ath12k_core_resume(struct ath12k_base *ab)
|
||||
{
|
||||
long time_left;
|
||||
|
||||
if (!ab->hw_params->supports_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
time_left = wait_for_completion_timeout(&ab->restart_completed,
|
||||
ATH12K_RESET_TIMEOUT_HZ);
|
||||
if (time_left == 0) {
|
||||
ath12k_warn(ab, "timeout while waiting for restart complete");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath12k_core_resume);
|
||||
|
||||
static int __ath12k_core_create_board_name(struct ath12k_base *ab, char *name,
|
||||
size_t name_len, bool with_variant,
|
||||
@ -542,6 +566,8 @@ static void ath12k_core_stop(struct ath12k_base *ab)
|
||||
if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags))
|
||||
ath12k_qmi_firmware_stop(ab);
|
||||
|
||||
ath12k_acpi_stop(ab);
|
||||
|
||||
ath12k_hif_stop(ab);
|
||||
ath12k_wmi_detach(ab);
|
||||
ath12k_dp_rx_pdev_reo_cleanup(ab);
|
||||
@ -628,6 +654,8 @@ static int ath12k_core_soc_create(struct ath12k_base *ab)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ath12k_debugfs_soc_create(ab);
|
||||
|
||||
ret = ath12k_hif_power_up(ab);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to power up :%d\n", ret);
|
||||
@ -637,6 +665,7 @@ static int ath12k_core_soc_create(struct ath12k_base *ab)
|
||||
return 0;
|
||||
|
||||
err_qmi_deinit:
|
||||
ath12k_debugfs_soc_destroy(ab);
|
||||
ath12k_qmi_deinit_service(ab);
|
||||
return ret;
|
||||
}
|
||||
@ -645,6 +674,7 @@ static void ath12k_core_soc_destroy(struct ath12k_base *ab)
|
||||
{
|
||||
ath12k_dp_free(ab);
|
||||
ath12k_reg_free(ab);
|
||||
ath12k_debugfs_soc_destroy(ab);
|
||||
ath12k_qmi_deinit_service(ab);
|
||||
}
|
||||
|
||||
@ -779,6 +809,11 @@ static int ath12k_core_start(struct ath12k_base *ab,
|
||||
goto err_reo_cleanup;
|
||||
}
|
||||
|
||||
ret = ath12k_acpi_start(ab);
|
||||
if (ret)
|
||||
/* ACPI is optional so continue in case of an error */
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "acpi failed: %d\n", ret);
|
||||
|
||||
return 0;
|
||||
|
||||
err_reo_cleanup:
|
||||
@ -874,9 +909,8 @@ static int ath12k_core_reconfigure_on_crash(struct ath12k_base *ab)
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ab->core_lock);
|
||||
ath12k_hif_irq_disable(ab);
|
||||
ath12k_dp_pdev_free(ab);
|
||||
ath12k_hif_stop(ab);
|
||||
ath12k_ce_cleanup_pipes(ab);
|
||||
ath12k_wmi_detach(ab);
|
||||
ath12k_dp_rx_pdev_reo_cleanup(ab);
|
||||
mutex_unlock(&ab->core_lock);
|
||||
@ -1052,9 +1086,6 @@ static void ath12k_core_restart(struct work_struct *work)
|
||||
struct ath12k_base *ab = container_of(work, struct ath12k_base, restart_work);
|
||||
int ret;
|
||||
|
||||
if (!ab->is_reset)
|
||||
ath12k_core_pre_reconfigure_recovery(ab);
|
||||
|
||||
ret = ath12k_core_reconfigure_on_crash(ab);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to reconfigure driver on crash recovery\n");
|
||||
@ -1064,8 +1095,7 @@ static void ath12k_core_restart(struct work_struct *work)
|
||||
if (ab->is_reset)
|
||||
complete_all(&ab->reconfigure_complete);
|
||||
|
||||
if (!ab->is_reset)
|
||||
ath12k_core_post_reconfigure_recovery(ab);
|
||||
complete(&ab->restart_completed);
|
||||
}
|
||||
|
||||
static void ath12k_core_reset(struct work_struct *work)
|
||||
@ -1131,8 +1161,10 @@ static void ath12k_core_reset(struct work_struct *work)
|
||||
time_left = wait_for_completion_timeout(&ab->recovery_start,
|
||||
ATH12K_RECOVER_START_TIMEOUT_HZ);
|
||||
|
||||
ath12k_hif_power_down(ab);
|
||||
ath12k_qmi_free_resource(ab);
|
||||
ath12k_hif_irq_disable(ab);
|
||||
ath12k_hif_ce_irq_disable(ab);
|
||||
|
||||
ath12k_hif_power_down(ab, false);
|
||||
ath12k_hif_power_up(ab);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset started\n");
|
||||
@ -1175,7 +1207,7 @@ void ath12k_core_deinit(struct ath12k_base *ab)
|
||||
|
||||
mutex_unlock(&ab->core_lock);
|
||||
|
||||
ath12k_hif_power_down(ab);
|
||||
ath12k_hif_power_down(ab, false);
|
||||
ath12k_mac_destroy(ab);
|
||||
ath12k_core_soc_destroy(ab);
|
||||
ath12k_fw_unmap(ab);
|
||||
@ -1223,11 +1255,12 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
|
||||
|
||||
timer_setup(&ab->rx_replenish_retry, ath12k_ce_rx_replenish_retry, 0);
|
||||
init_completion(&ab->htc_suspend);
|
||||
init_completion(&ab->restart_completed);
|
||||
|
||||
ab->dev = dev;
|
||||
ab->hif.bus = bus;
|
||||
ab->qmi.num_radios = U8_MAX;
|
||||
ab->slo_capable = true;
|
||||
ab->mlo_capable_flags = ATH12K_INTRA_DEVICE_MLO_SUPPORT;
|
||||
|
||||
return ab;
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "reg.h"
|
||||
#include "dbring.h"
|
||||
#include "fw.h"
|
||||
#include "acpi.h"
|
||||
|
||||
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
|
||||
|
||||
@ -46,6 +47,7 @@
|
||||
#define ATH12K_SMBIOS_BDF_EXT_MAGIC "BDF_"
|
||||
|
||||
#define ATH12K_INVALID_HW_MAC_ID 0xFF
|
||||
#define ATH12K_CONNECTION_LOSS_HZ (3 * HZ)
|
||||
#define ATH12K_RX_RATE_TABLE_NUM 320
|
||||
#define ATH12K_RX_RATE_TABLE_11AX_NUM 576
|
||||
|
||||
@ -214,6 +216,24 @@ enum ath12k_monitor_flags {
|
||||
ATH12K_FLAG_MONITOR_ENABLED,
|
||||
};
|
||||
|
||||
struct ath12k_tx_conf {
|
||||
bool changed;
|
||||
u16 ac;
|
||||
struct ieee80211_tx_queue_params tx_queue_params;
|
||||
};
|
||||
|
||||
struct ath12k_key_conf {
|
||||
bool changed;
|
||||
enum set_key_cmd cmd;
|
||||
struct ieee80211_key_conf *key;
|
||||
};
|
||||
|
||||
struct ath12k_vif_cache {
|
||||
struct ath12k_tx_conf tx_conf;
|
||||
struct ath12k_key_conf key_conf;
|
||||
u32 bss_conf_changed;
|
||||
};
|
||||
|
||||
struct ath12k_vif {
|
||||
u32 vdev_id;
|
||||
enum wmi_vdev_type vdev_type;
|
||||
@ -251,11 +271,13 @@ struct ath12k_vif {
|
||||
} ap;
|
||||
} u;
|
||||
|
||||
bool is_created;
|
||||
bool is_started;
|
||||
bool is_up;
|
||||
u32 aid;
|
||||
u8 bssid[ETH_ALEN];
|
||||
struct cfg80211_bitrate_mask bitrate_mask;
|
||||
struct delayed_work connection_loss_work;
|
||||
int num_legacy_stations;
|
||||
int rtscts_prot_mode;
|
||||
int txpower;
|
||||
@ -267,10 +289,12 @@ struct ath12k_vif {
|
||||
u8 vdev_stats_id;
|
||||
u32 punct_bitmap;
|
||||
bool ps;
|
||||
struct ath12k_vif_cache *cache;
|
||||
};
|
||||
|
||||
struct ath12k_vif_iter {
|
||||
u32 vdev_id;
|
||||
struct ath12k *ar;
|
||||
struct ath12k_vif *arvif;
|
||||
};
|
||||
|
||||
@ -453,6 +477,10 @@ struct ath12k_fw_stats {
|
||||
struct list_head bcn;
|
||||
};
|
||||
|
||||
struct ath12k_debug {
|
||||
struct dentry *debugfs_pdev;
|
||||
};
|
||||
|
||||
struct ath12k_per_peer_tx_stats {
|
||||
u32 succ_bytes;
|
||||
u32 retry_bytes;
|
||||
@ -592,16 +620,24 @@ struct ath12k {
|
||||
struct ath12k_per_peer_tx_stats cached_stats;
|
||||
u32 last_ppdu_id;
|
||||
u32 cached_ppdu_id;
|
||||
#ifdef CONFIG_ATH12K_DEBUGFS
|
||||
struct ath12k_debug debug;
|
||||
#endif
|
||||
|
||||
bool dfs_block_radar_events;
|
||||
bool monitor_conf_enabled;
|
||||
bool monitor_vdev_created;
|
||||
bool monitor_started;
|
||||
int monitor_vdev_id;
|
||||
|
||||
u32 freq_low;
|
||||
u32 freq_high;
|
||||
};
|
||||
|
||||
struct ath12k_hw {
|
||||
struct ieee80211_hw *hw;
|
||||
bool regd_updated;
|
||||
bool use_6ghz_regd;
|
||||
|
||||
u8 num_radio;
|
||||
struct ath12k radio[] __aligned(sizeof(void *));
|
||||
@ -688,6 +724,21 @@ struct ath12k_soc_dp_stats {
|
||||
struct ath12k_soc_dp_tx_err_stats tx_err;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ath12k_link_capable_flags - link capable flags
|
||||
*
|
||||
* Single/Multi link capability information
|
||||
*
|
||||
* @ATH12K_INTRA_DEVICE_MLO_SUPPORT: SLO/MLO form between the radio, where all
|
||||
* the links (radios) present within a device.
|
||||
* @ATH12K_INTER_DEVICE_MLO_SUPPORT: SLO/MLO form between the radio, where all
|
||||
* the links (radios) present across the devices.
|
||||
*/
|
||||
enum ath12k_link_capable_flags {
|
||||
ATH12K_INTRA_DEVICE_MLO_SUPPORT = BIT(0),
|
||||
ATH12K_INTER_DEVICE_MLO_SUPPORT = BIT(1),
|
||||
};
|
||||
|
||||
/* Master structure to hold the hw data which may be used in core module */
|
||||
struct ath12k_base {
|
||||
enum ath12k_hw_rev hw_rev;
|
||||
@ -782,6 +833,9 @@ struct ath12k_base {
|
||||
/* Current DFS Regulatory */
|
||||
enum ath12k_dfs_region dfs_region;
|
||||
struct ath12k_soc_dp_stats soc_stats;
|
||||
#ifdef CONFIG_ATH12K_DEBUGFS
|
||||
struct dentry *debugfs_soc;
|
||||
#endif
|
||||
|
||||
unsigned long dev_flags;
|
||||
struct completion driver_recovery;
|
||||
@ -843,10 +897,31 @@ struct ath12k_base {
|
||||
|
||||
const struct hal_rx_ops *hal_rx_ops;
|
||||
|
||||
/* slo_capable denotes if the single/multi link operation
|
||||
* is supported within the same chip (SoC).
|
||||
/* mlo_capable_flags denotes the single/multi link operation
|
||||
* capabilities of the Device.
|
||||
*
|
||||
* See enum ath12k_link_capable_flags
|
||||
*/
|
||||
bool slo_capable;
|
||||
u8 mlo_capable_flags;
|
||||
|
||||
struct completion restart_completed;
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
|
||||
struct {
|
||||
bool started;
|
||||
u32 func_bit;
|
||||
bool acpi_tas_enable;
|
||||
bool acpi_bios_sar_enable;
|
||||
u8 tas_cfg[ATH12K_ACPI_DSM_TAS_CFG_SIZE];
|
||||
u8 tas_sar_power_table[ATH12K_ACPI_DSM_TAS_DATA_SIZE];
|
||||
u8 bios_sar_data[ATH12K_ACPI_DSM_BIOS_SAR_DATA_SIZE];
|
||||
u8 geo_offset_data[ATH12K_ACPI_DSM_GEO_OFFSET_DATA_SIZE];
|
||||
u8 cca_data[ATH12K_ACPI_DSM_CCA_DATA_SIZE];
|
||||
u8 band_edge_power[ATH12K_ACPI_DSM_BAND_EDGE_DATA_SIZE];
|
||||
} acpi;
|
||||
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
/* must be last */
|
||||
u8 drv_priv[] __aligned(sizeof(void *));
|
||||
@ -874,8 +949,10 @@ 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);
|
||||
int ath12k_core_resume_early(struct ath12k_base *ab);
|
||||
int ath12k_core_resume(struct ath12k_base *ab);
|
||||
int ath12k_core_suspend(struct ath12k_base *ab);
|
||||
int ath12k_core_suspend_late(struct ath12k_base *ab);
|
||||
|
||||
const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab,
|
||||
const char *filename);
|
||||
@ -951,13 +1028,21 @@ 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)
|
||||
static inline struct ath12k *ath12k_ah_to_ar(struct ath12k_hw *ah, u8 hw_link_id)
|
||||
{
|
||||
return ah->radio;
|
||||
if (WARN(hw_link_id >= ah->num_radio,
|
||||
"bad hw link id %d, so switch to default link\n", hw_link_id))
|
||||
hw_link_id = 0;
|
||||
|
||||
return &ah->radio[hw_link_id];
|
||||
}
|
||||
|
||||
static inline struct ieee80211_hw *ath12k_ar_to_hw(struct ath12k *ar)
|
||||
{
|
||||
return ar->ah->hw;
|
||||
}
|
||||
|
||||
#define for_each_ar(ah, ar, index) \
|
||||
for ((index) = 0; ((index) < (ah)->num_radio && \
|
||||
((ar) = &(ah)->radio[(index)])); (index)++)
|
||||
#endif /* _CORE_H_ */
|
||||
|
90
drivers/net/wireless/ath/ath12k/debugfs.c
Normal file
90
drivers/net/wireless/ath/ath12k/debugfs.c
Normal file
@ -0,0 +1,90 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "debugfs.h"
|
||||
|
||||
static ssize_t ath12k_write_simulate_radar(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath12k *ar = file->private_data;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
ret = ath12k_wmi_simulate_radar(ar);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
ret = count;
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_simulate_radar = {
|
||||
.write = ath12k_write_simulate_radar,
|
||||
.open = simple_open
|
||||
};
|
||||
|
||||
void ath12k_debugfs_soc_create(struct ath12k_base *ab)
|
||||
{
|
||||
bool dput_needed;
|
||||
char soc_name[64] = { 0 };
|
||||
struct dentry *debugfs_ath12k;
|
||||
|
||||
debugfs_ath12k = debugfs_lookup("ath12k", NULL);
|
||||
if (debugfs_ath12k) {
|
||||
/* a dentry from lookup() needs dput() after we don't use it */
|
||||
dput_needed = true;
|
||||
} else {
|
||||
debugfs_ath12k = debugfs_create_dir("ath12k", NULL);
|
||||
if (IS_ERR_OR_NULL(debugfs_ath12k))
|
||||
return;
|
||||
dput_needed = false;
|
||||
}
|
||||
|
||||
scnprintf(soc_name, sizeof(soc_name), "%s-%s", ath12k_bus_str(ab->hif.bus),
|
||||
dev_name(ab->dev));
|
||||
|
||||
ab->debugfs_soc = debugfs_create_dir(soc_name, debugfs_ath12k);
|
||||
|
||||
if (dput_needed)
|
||||
dput(debugfs_ath12k);
|
||||
}
|
||||
|
||||
void ath12k_debugfs_soc_destroy(struct ath12k_base *ab)
|
||||
{
|
||||
debugfs_remove_recursive(ab->debugfs_soc);
|
||||
ab->debugfs_soc = NULL;
|
||||
/* We are not removing ath12k directory on purpose, even if it
|
||||
* would be empty. This simplifies the directory handling and it's
|
||||
* a minor cosmetic issue to leave an empty ath12k directory to
|
||||
* debugfs.
|
||||
*/
|
||||
}
|
||||
|
||||
void ath12k_debugfs_register(struct ath12k *ar)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
struct ieee80211_hw *hw = ar->ah->hw;
|
||||
char pdev_name[5];
|
||||
char buf[100] = {0};
|
||||
|
||||
scnprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
|
||||
|
||||
ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
|
||||
|
||||
/* Create a symlink under ieee80211/phy* */
|
||||
scnprintf(buf, sizeof(buf), "../../ath12k/%pd2", ar->debug.debugfs_pdev);
|
||||
debugfs_create_symlink("ath12k", hw->wiphy->debugfsdir, buf);
|
||||
|
||||
if (ar->mac.sbands[NL80211_BAND_5GHZ].channels) {
|
||||
debugfs_create_file("dfs_simulate_radar", 0200,
|
||||
ar->debug.debugfs_pdev, ar,
|
||||
&fops_simulate_radar);
|
||||
}
|
||||
}
|
30
drivers/net/wireless/ath/ath12k/debugfs.h
Normal file
30
drivers/net/wireless/ath/ath12k/debugfs.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _ATH12K_DEBUGFS_H_
|
||||
#define _ATH12K_DEBUGFS_H_
|
||||
|
||||
#ifdef CONFIG_ATH12K_DEBUGFS
|
||||
void ath12k_debugfs_soc_create(struct ath12k_base *ab);
|
||||
void ath12k_debugfs_soc_destroy(struct ath12k_base *ab);
|
||||
void ath12k_debugfs_register(struct ath12k *ar);
|
||||
|
||||
#else
|
||||
static inline void ath12k_debugfs_soc_create(struct ath12k_base *ab)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ath12k_debugfs_soc_destroy(struct ath12k_base *ab)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ath12k_debugfs_register(struct ath12k *ar)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ATH12K_DEBUGFS */
|
||||
|
||||
#endif /* _ATH12K_DEBUGFS_H_ */
|
@ -14,6 +14,11 @@
|
||||
#include "peer.h"
|
||||
#include "dp_mon.h"
|
||||
|
||||
enum ath12k_dp_desc_type {
|
||||
ATH12K_DP_TX_DESC,
|
||||
ATH12K_DP_RX_DESC,
|
||||
};
|
||||
|
||||
static void ath12k_dp_htt_htc_tx_complete(struct ath12k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@ -1150,7 +1155,9 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
|
||||
struct ath12k_rx_desc_info *desc_info;
|
||||
struct ath12k_tx_desc_info *tx_desc_info, *tmp1;
|
||||
struct ath12k_dp *dp = &ab->dp;
|
||||
struct ath12k_skb_cb *skb_cb;
|
||||
struct sk_buff *skb;
|
||||
struct ath12k *ar;
|
||||
int i, j;
|
||||
u32 pool_id, tx_spt_page;
|
||||
|
||||
@ -1201,6 +1208,11 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
|
||||
if (!skb)
|
||||
continue;
|
||||
|
||||
skb_cb = ATH12K_SKB_CB(skb);
|
||||
ar = skb_cb->ar;
|
||||
if (atomic_dec_and_test(&ar->dp.num_tx_pending))
|
||||
wake_up(&ar->dp.tx_empty_waitq);
|
||||
|
||||
dma_unmap_single(ab->dev, ATH12K_SKB_CB(skb)->paddr,
|
||||
skb->len, DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
@ -1344,12 +1356,16 @@ struct ath12k_rx_desc_info *ath12k_dp_get_rx_desc(struct ath12k_base *ab,
|
||||
u32 cookie)
|
||||
{
|
||||
struct ath12k_rx_desc_info **desc_addr_ptr;
|
||||
u16 ppt_idx, spt_idx;
|
||||
u16 start_ppt_idx, end_ppt_idx, ppt_idx, spt_idx;
|
||||
|
||||
ppt_idx = u32_get_bits(cookie, ATH12K_DP_CC_COOKIE_PPT);
|
||||
spt_idx = u32_get_bits(cookie, ATH12k_DP_CC_COOKIE_SPT);
|
||||
spt_idx = u32_get_bits(cookie, ATH12K_DP_CC_COOKIE_SPT);
|
||||
|
||||
if (ppt_idx > ATH12K_NUM_RX_SPT_PAGES ||
|
||||
start_ppt_idx = ATH12K_RX_SPT_PAGE_OFFSET;
|
||||
end_ppt_idx = start_ppt_idx + ATH12K_NUM_RX_SPT_PAGES;
|
||||
|
||||
if (ppt_idx < start_ppt_idx ||
|
||||
ppt_idx >= end_ppt_idx ||
|
||||
spt_idx > ATH12K_MAX_SPT_ENTRIES)
|
||||
return NULL;
|
||||
|
||||
@ -1362,13 +1378,17 @@ struct ath12k_tx_desc_info *ath12k_dp_get_tx_desc(struct ath12k_base *ab,
|
||||
u32 cookie)
|
||||
{
|
||||
struct ath12k_tx_desc_info **desc_addr_ptr;
|
||||
u16 ppt_idx, spt_idx;
|
||||
u16 start_ppt_idx, end_ppt_idx, ppt_idx, spt_idx;
|
||||
|
||||
ppt_idx = u32_get_bits(cookie, ATH12K_DP_CC_COOKIE_PPT);
|
||||
spt_idx = u32_get_bits(cookie, ATH12k_DP_CC_COOKIE_SPT);
|
||||
spt_idx = u32_get_bits(cookie, ATH12K_DP_CC_COOKIE_SPT);
|
||||
|
||||
if (ppt_idx < ATH12K_NUM_RX_SPT_PAGES ||
|
||||
ppt_idx > ab->dp.num_spt_pages ||
|
||||
start_ppt_idx = ATH12K_TX_SPT_PAGE_OFFSET;
|
||||
end_ppt_idx = start_ppt_idx +
|
||||
(ATH12K_TX_SPT_PAGES_PER_POOL * ATH12K_HW_MAX_QUEUES);
|
||||
|
||||
if (ppt_idx < start_ppt_idx ||
|
||||
ppt_idx >= end_ppt_idx ||
|
||||
spt_idx > ATH12K_MAX_SPT_ENTRIES)
|
||||
return NULL;
|
||||
|
||||
@ -1397,15 +1417,16 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ppt_idx = ATH12K_RX_SPT_PAGE_OFFSET + i;
|
||||
dp->spt_info->rxbaddr[i] = &rx_descs[0];
|
||||
|
||||
for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
|
||||
rx_descs[j].cookie = ath12k_dp_cc_cookie_gen(i, j);
|
||||
rx_descs[j].cookie = ath12k_dp_cc_cookie_gen(ppt_idx, j);
|
||||
rx_descs[j].magic = ATH12K_DP_RX_DESC_MAGIC;
|
||||
list_add_tail(&rx_descs[j].list, &dp->rx_desc_free_list);
|
||||
|
||||
/* Update descriptor VA in SPT */
|
||||
rx_desc_addr = ath12k_dp_cc_get_desc_addr_ptr(ab, i, j);
|
||||
rx_desc_addr = ath12k_dp_cc_get_desc_addr_ptr(ab, ppt_idx, j);
|
||||
*rx_desc_addr = &rx_descs[j];
|
||||
}
|
||||
}
|
||||
@ -1425,10 +1446,11 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
|
||||
}
|
||||
|
||||
tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL;
|
||||
ppt_idx = ATH12K_TX_SPT_PAGE_OFFSET + tx_spt_page;
|
||||
|
||||
dp->spt_info->txbaddr[tx_spt_page] = &tx_descs[0];
|
||||
|
||||
for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
|
||||
ppt_idx = ATH12K_NUM_RX_SPT_PAGES + tx_spt_page;
|
||||
tx_descs[j].desc_id = ath12k_dp_cc_cookie_gen(ppt_idx, j);
|
||||
tx_descs[j].pool_id = pool_id;
|
||||
list_add_tail(&tx_descs[j].list,
|
||||
@ -1445,11 +1467,41 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath12k_dp_cmem_init(struct ath12k_base *ab,
|
||||
struct ath12k_dp *dp,
|
||||
enum ath12k_dp_desc_type type)
|
||||
{
|
||||
u32 cmem_base;
|
||||
int i, start, end;
|
||||
|
||||
cmem_base = ab->qmi.dev_mem[ATH12K_QMI_DEVMEM_CMEM_INDEX].start;
|
||||
|
||||
switch (type) {
|
||||
case ATH12K_DP_TX_DESC:
|
||||
start = ATH12K_TX_SPT_PAGE_OFFSET;
|
||||
end = start + ATH12K_NUM_TX_SPT_PAGES;
|
||||
break;
|
||||
case ATH12K_DP_RX_DESC:
|
||||
start = ATH12K_RX_SPT_PAGE_OFFSET;
|
||||
end = start + ATH12K_NUM_RX_SPT_PAGES;
|
||||
break;
|
||||
default:
|
||||
ath12k_err(ab, "invalid descriptor type %d in cmem init\n", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Write to PPT in CMEM */
|
||||
for (i = start; i < end; i++)
|
||||
ath12k_hif_write32(ab, cmem_base + ATH12K_PPT_ADDR_OFFSET(i),
|
||||
dp->spt_info[i].paddr >> ATH12K_SPT_4K_ALIGN_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath12k_dp_cc_init(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_dp *dp = &ab->dp;
|
||||
int i, ret = 0;
|
||||
u32 cmem_base;
|
||||
|
||||
INIT_LIST_HEAD(&dp->rx_desc_free_list);
|
||||
spin_lock_init(&dp->rx_desc_lock);
|
||||
@ -1472,8 +1524,6 @@ static int ath12k_dp_cc_init(struct ath12k_base *ab)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmem_base = ab->qmi.dev_mem[ATH12K_QMI_DEVMEM_CMEM_INDEX].start;
|
||||
|
||||
for (i = 0; i < dp->num_spt_pages; i++) {
|
||||
dp->spt_info[i].vaddr = dma_alloc_coherent(ab->dev,
|
||||
ATH12K_PAGE_SIZE,
|
||||
@ -1490,10 +1540,18 @@ static int ath12k_dp_cc_init(struct ath12k_base *ab)
|
||||
ret = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write to PPT in CMEM */
|
||||
ath12k_hif_write32(ab, cmem_base + ATH12K_PPT_ADDR_OFFSET(i),
|
||||
dp->spt_info[i].paddr >> ATH12K_SPT_4K_ALIGN_OFFSET);
|
||||
ret = ath12k_dp_cmem_init(ab, dp, ATH12K_DP_TX_DESC);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "HW CC Tx cmem init failed %d", ret);
|
||||
goto free;
|
||||
}
|
||||
|
||||
ret = ath12k_dp_cmem_init(ab, dp, ATH12K_DP_RX_DESC);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "HW CC Rx cmem init failed %d", ret);
|
||||
goto free;
|
||||
}
|
||||
|
||||
ret = ath12k_dp_cc_desc_init(ab);
|
||||
|
@ -223,6 +223,9 @@ struct ath12k_pdev_dp {
|
||||
#define ATH12K_NUM_TX_SPT_PAGES (ATH12K_TX_SPT_PAGES_PER_POOL * ATH12K_HW_MAX_QUEUES)
|
||||
#define ATH12K_NUM_SPT_PAGES (ATH12K_NUM_RX_SPT_PAGES + ATH12K_NUM_TX_SPT_PAGES)
|
||||
|
||||
#define ATH12K_TX_SPT_PAGE_OFFSET 0
|
||||
#define ATH12K_RX_SPT_PAGE_OFFSET ATH12K_NUM_TX_SPT_PAGES
|
||||
|
||||
/* The SPT pages are divided for RX and TX, first block for RX
|
||||
* and remaining for TX
|
||||
*/
|
||||
@ -245,7 +248,7 @@ struct ath12k_pdev_dp {
|
||||
#define ATH12K_CC_SPT_MSB 8
|
||||
#define ATH12K_CC_PPT_MSB 19
|
||||
#define ATH12K_CC_PPT_SHIFT 9
|
||||
#define ATH12k_DP_CC_COOKIE_SPT GENMASK(8, 0)
|
||||
#define ATH12K_DP_CC_COOKIE_SPT GENMASK(8, 0)
|
||||
#define ATH12K_DP_CC_COOKIE_PPT GENMASK(19, 9)
|
||||
|
||||
#define DP_REO_QREF_NUM GENMASK(31, 16)
|
||||
|
@ -944,7 +944,7 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
|
||||
goto err_merge_fail;
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_DATA,
|
||||
"mpdu_buf %pK mpdu_buf->len %u",
|
||||
"mpdu_buf %p mpdu_buf->len %u",
|
||||
prev_buf, prev_buf->len);
|
||||
} else {
|
||||
ath12k_dbg(ab, ATH12K_DBG_DATA,
|
||||
@ -958,7 +958,7 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
|
||||
err_merge_fail:
|
||||
if (mpdu_buf && decap_format != DP_RX_DECAP_TYPE_RAW) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_DATA,
|
||||
"err_merge_fail mpdu_buf %pK", mpdu_buf);
|
||||
"err_merge_fail mpdu_buf %p", mpdu_buf);
|
||||
/* Free the head buffer */
|
||||
dev_kfree_skb_any(mpdu_buf);
|
||||
}
|
||||
@ -1092,7 +1092,7 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
|
||||
spin_unlock_bh(&ar->ab->base_lock);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
|
||||
"rx skb %pK len %u peer %pM %u %s %s%s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
|
||||
"rx skb %p len %u peer %pM %u %s %s%s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
|
||||
msdu,
|
||||
msdu->len,
|
||||
peer ? peer->addr : NULL,
|
||||
|
@ -239,26 +239,12 @@ static inline u8 ath12k_dp_rx_get_msdu_src_link(struct ath12k_base *ab,
|
||||
return ab->hal_rx_ops->rx_desc_get_msdu_src_link_id(desc);
|
||||
}
|
||||
|
||||
static int ath12k_dp_purge_mon_ring(struct ath12k_base *ab)
|
||||
static void ath12k_dp_clean_up_skb_list(struct sk_buff_head *skb_list)
|
||||
{
|
||||
int i, reaped = 0;
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(DP_MON_PURGE_TIMEOUT_MS);
|
||||
struct sk_buff *skb;
|
||||
|
||||
do {
|
||||
for (i = 0; i < ab->hw_params->num_rxmda_per_pdev; i++)
|
||||
reaped += ath12k_dp_mon_process_ring(ab, i, NULL,
|
||||
DP_MON_SERVICE_BUDGET,
|
||||
ATH12K_DP_RX_MONITOR_MODE);
|
||||
|
||||
/* nothing more to reap */
|
||||
if (reaped < DP_MON_SERVICE_BUDGET)
|
||||
return 0;
|
||||
|
||||
} while (time_before(jiffies, timeout));
|
||||
|
||||
ath12k_warn(ab, "dp mon ring purge timeout");
|
||||
|
||||
return -ETIMEDOUT;
|
||||
while ((skb = __skb_dequeue(skb_list)))
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
static size_t ath12k_dp_list_cut_nodes(struct list_head *list,
|
||||
@ -2459,7 +2445,7 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_DATA,
|
||||
"rx skb %pK len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s%s%s rate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
|
||||
"rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s%s%s rate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
|
||||
msdu,
|
||||
msdu->len,
|
||||
peer ? peer->addr : NULL,
|
||||
@ -3742,19 +3728,20 @@ 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;
|
||||
struct sk_buff_head msdu_list, scatter_msdu_list;
|
||||
struct ath12k_skb_rxcb *rxcb;
|
||||
void *rx_desc;
|
||||
u8 mac_id;
|
||||
int num_buffs_reaped = 0;
|
||||
struct ath12k_rx_desc_info *desc_info;
|
||||
int ret, pdev_id;
|
||||
struct hal_rx_desc *msdu_data;
|
||||
|
||||
__skb_queue_head_init(&msdu_list);
|
||||
__skb_queue_head_init(&scatter_msdu_list);
|
||||
|
||||
srng = &ab->hal.srng_list[dp->rx_rel_ring.ring_id];
|
||||
rx_ring = &dp->rx_refill_buf_ring;
|
||||
|
||||
spin_lock_bh(&srng->lock);
|
||||
|
||||
ath12k_hal_srng_access_begin(ab, srng);
|
||||
@ -3807,17 +3794,53 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
|
||||
continue;
|
||||
}
|
||||
|
||||
msdu_data = (struct hal_rx_desc *)msdu->data;
|
||||
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, msdu);
|
||||
|
||||
rxcb->is_first_msdu = err_info.first_msdu;
|
||||
rxcb->is_last_msdu = err_info.last_msdu;
|
||||
rxcb->is_continuation = err_info.continuation;
|
||||
rxcb->rx_desc = msdu_data;
|
||||
|
||||
if (err_info.continuation) {
|
||||
__skb_queue_tail(&scatter_msdu_list, msdu);
|
||||
continue;
|
||||
}
|
||||
|
||||
mac_id = ath12k_dp_rx_get_msdu_src_link(ab,
|
||||
msdu_data);
|
||||
if (mac_id >= MAX_RADIOS) {
|
||||
dev_kfree_skb_any(msdu);
|
||||
|
||||
/* In any case continuation bit is set
|
||||
* in the previous record, cleanup scatter_msdu_list
|
||||
*/
|
||||
ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!skb_queue_empty(&scatter_msdu_list)) {
|
||||
struct sk_buff *msdu;
|
||||
|
||||
skb_queue_walk(&scatter_msdu_list, msdu) {
|
||||
rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
rxcb->mac_id = mac_id;
|
||||
}
|
||||
|
||||
skb_queue_splice_tail_init(&scatter_msdu_list,
|
||||
&msdu_list);
|
||||
}
|
||||
|
||||
rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
rxcb->mac_id = mac_id;
|
||||
__skb_queue_tail(&msdu_list, msdu);
|
||||
}
|
||||
|
||||
/* In any case continuation bit is set in the
|
||||
* last record, cleanup scatter_msdu_list
|
||||
*/
|
||||
ath12k_dp_clean_up_skb_list(&scatter_msdu_list);
|
||||
|
||||
ath12k_hal_srng_access_end(ab, srng);
|
||||
|
||||
spin_unlock_bh(&srng->lock);
|
||||
@ -3830,8 +3853,9 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
|
||||
|
||||
rcu_read_lock();
|
||||
while ((msdu = __skb_dequeue(&msdu_list))) {
|
||||
mac_id = ath12k_dp_rx_get_msdu_src_link(ab,
|
||||
(struct hal_rx_desc *)msdu->data);
|
||||
rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
mac_id = rxcb->mac_id;
|
||||
|
||||
pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
|
||||
ar = ab->pdevs[pdev_id].ar;
|
||||
|
||||
@ -4264,29 +4288,3 @@ int ath12k_dp_rx_pdev_mon_attach(struct ath12k *ar)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath12k_dp_rx_pktlog_start(struct ath12k_base *ab)
|
||||
{
|
||||
/* start reap timer */
|
||||
mod_timer(&ab->mon_reap_timer,
|
||||
jiffies + msecs_to_jiffies(ATH12K_MON_TIMER_INTERVAL));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath12k_dp_rx_pktlog_stop(struct ath12k_base *ab, bool stop_timer)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (stop_timer)
|
||||
del_timer_sync(&ab->mon_reap_timer);
|
||||
|
||||
/* reap all the monitor related rings */
|
||||
ret = ath12k_dp_purge_mon_ring(ab);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to purge dp mon ring: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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_RX_H
|
||||
#define ATH12K_DP_RX_H
|
||||
@ -123,8 +123,6 @@ int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
|
||||
int ath12k_dp_rx_pdev_mon_attach(struct ath12k *ar);
|
||||
int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id);
|
||||
|
||||
int ath12k_dp_rx_pktlog_start(struct ath12k_base *ab);
|
||||
int ath12k_dp_rx_pktlog_stop(struct ath12k_base *ab, bool stop_timer);
|
||||
u8 ath12k_dp_rx_h_l3pad(struct ath12k_base *ab,
|
||||
struct hal_rx_desc *desc);
|
||||
struct ath12k_peer *
|
||||
|
@ -767,7 +767,7 @@ struct hal_srng_config {
|
||||
};
|
||||
|
||||
/**
|
||||
* enum hal_rx_buf_return_buf_manager
|
||||
* enum hal_rx_buf_return_buf_manager - manager for returned rx buffers
|
||||
*
|
||||
* @HAL_RX_BUF_RBM_WBM_IDLE_BUF_LIST: Buffer returned to WBM idle buffer list
|
||||
* @HAL_RX_BUF_RBM_WBM_CHIP0_IDLE_DESC_LIST: Descriptor returned to WBM idle
|
||||
|
@ -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_HIF_H
|
||||
@ -17,7 +17,7 @@ struct ath12k_hif_ops {
|
||||
int (*start)(struct ath12k_base *ab);
|
||||
void (*stop)(struct ath12k_base *ab);
|
||||
int (*power_up)(struct ath12k_base *ab);
|
||||
void (*power_down)(struct ath12k_base *ab);
|
||||
void (*power_down)(struct ath12k_base *ab, bool is_suspend);
|
||||
int (*suspend)(struct ath12k_base *ab);
|
||||
int (*resume)(struct ath12k_base *ab);
|
||||
int (*map_service_to_pipe)(struct ath12k_base *ab, u16 service_id,
|
||||
@ -133,12 +133,18 @@ static inline void ath12k_hif_write32(struct ath12k_base *ab, u32 address,
|
||||
|
||||
static inline int ath12k_hif_power_up(struct ath12k_base *ab)
|
||||
{
|
||||
if (!ab->hif.ops->power_up)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ab->hif.ops->power_up(ab);
|
||||
}
|
||||
|
||||
static inline void ath12k_hif_power_down(struct ath12k_base *ab)
|
||||
static inline void ath12k_hif_power_down(struct ath12k_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);
|
||||
}
|
||||
|
||||
#endif /* ATH12K_HIF_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-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/ctype.h>
|
||||
@ -358,7 +358,7 @@ void ath12k_htc_rx_completion_handler(struct ath12k_base *ab,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_HTC, "htc rx completion ep %d skb %pK\n",
|
||||
ath12k_dbg(ab, ATH12K_DBG_HTC, "htc rx completion ep %d skb %p\n",
|
||||
eid, skb);
|
||||
ep->ep_ops.ep_rx_complete(ab, skb);
|
||||
|
||||
|
@ -15,6 +15,10 @@
|
||||
#include "mhi.h"
|
||||
#include "dp_rx.h"
|
||||
|
||||
static const guid_t wcn7850_uuid = GUID_INIT(0xf634f534, 0x6147, 0x11ec,
|
||||
0x90, 0xd6, 0x02, 0x42,
|
||||
0xac, 0x12, 0x00, 0x03);
|
||||
|
||||
static u8 ath12k_hw_qcn9274_mac_from_pdev_id(int pdev_idx)
|
||||
{
|
||||
return pdev_idx;
|
||||
@ -920,6 +924,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
||||
.otp_board_id_register = QCN9274_QFPROM_RAW_RFA_PDET_ROW13_LSB,
|
||||
|
||||
.supports_sta_ps = false,
|
||||
|
||||
.acpi_guid = NULL,
|
||||
},
|
||||
{
|
||||
.name = "wcn7850 hw2.0",
|
||||
@ -964,7 +970,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
||||
|
||||
.idle_ps = true,
|
||||
.download_calib = false,
|
||||
.supports_suspend = false,
|
||||
.supports_suspend = true,
|
||||
.tcl_ring_retry = false,
|
||||
.reoq_lut_support = false,
|
||||
.supports_shadow_regs = true,
|
||||
@ -993,6 +999,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
||||
.otp_board_id_register = 0,
|
||||
|
||||
.supports_sta_ps = true,
|
||||
|
||||
.acpi_guid = &wcn7850_uuid,
|
||||
},
|
||||
{
|
||||
.name = "qcn9274 hw2.0",
|
||||
@ -1061,6 +1069,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
||||
.otp_board_id_register = QCN9274_QFPROM_RAW_RFA_PDET_ROW13_LSB,
|
||||
|
||||
.supports_sta_ps = false,
|
||||
|
||||
.acpi_guid = NULL,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define ATH12K_HW_H
|
||||
|
||||
#include <linux/mhi.h>
|
||||
#include <linux/uuid.h>
|
||||
|
||||
#include "wmi.h"
|
||||
#include "hal.h"
|
||||
@ -80,6 +81,7 @@
|
||||
#define TARGET_RX_PEER_METADATA_VER_V1A 2
|
||||
#define TARGET_RX_PEER_METADATA_VER_V1B 3
|
||||
|
||||
#define ATH12K_HW_DEFAULT_QUEUE 0
|
||||
#define ATH12K_HW_MAX_QUEUES 4
|
||||
#define ATH12K_QUEUE_LEN 4096
|
||||
|
||||
@ -211,6 +213,8 @@ struct ath12k_hw_params {
|
||||
u32 otp_board_id_register;
|
||||
|
||||
bool supports_sta_ps;
|
||||
|
||||
const guid_t *acpi_guid;
|
||||
};
|
||||
|
||||
struct ath12k_hw_ops {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -78,4 +78,8 @@ enum ath12k_supported_bw ath12k_mac_mac80211_bw_to_ath12k_bw(enum rate_info_bw b
|
||||
enum hal_encrypt_type ath12k_dp_tx_get_encrypt_type(u32 cipher);
|
||||
int ath12k_mac_rfkill_enable_radio(struct ath12k *ar, bool enable);
|
||||
int ath12k_mac_rfkill_config(struct ath12k *ar);
|
||||
int ath12k_mac_wait_tx_complete(struct ath12k *ar);
|
||||
void ath12k_mac_handle_beacon(struct ath12k *ar, struct sk_buff *skb);
|
||||
void ath12k_mac_handle_beacon_miss(struct ath12k *ar, u32 vdev_id);
|
||||
|
||||
#endif
|
||||
|
@ -18,34 +18,6 @@
|
||||
#define OTP_VALID_DUALMAC_BOARD_ID_MASK 0x1000
|
||||
|
||||
static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
|
||||
{
|
||||
.num = 0,
|
||||
.name = "LOOPBACK",
|
||||
.num_elements = 32,
|
||||
.event_ring = 1,
|
||||
.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 = 1,
|
||||
.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,
|
||||
},
|
||||
{
|
||||
.num = 20,
|
||||
.name = "IPCR",
|
||||
@ -111,34 +83,6 @@ const struct mhi_controller_config ath12k_mhi_config_qcn9274 = {
|
||||
};
|
||||
|
||||
static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {
|
||||
{
|
||||
.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,
|
||||
},
|
||||
{
|
||||
.num = 20,
|
||||
.name = "IPCR",
|
||||
@ -196,7 +140,7 @@ const struct mhi_controller_config ath12k_mhi_config_wcn7850 = {
|
||||
.max_channels = 128,
|
||||
.timeout_ms = 2000,
|
||||
.use_bounce_buf = false,
|
||||
.buf_len = 0,
|
||||
.buf_len = 8192,
|
||||
.num_channels = ARRAY_SIZE(ath12k_mhi_channels_wcn7850),
|
||||
.ch_cfg = ath12k_mhi_channels_wcn7850,
|
||||
.num_events = ARRAY_SIZE(ath12k_mhi_events_wcn7850),
|
||||
@ -385,7 +329,6 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci)
|
||||
"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);
|
||||
}
|
||||
@ -470,6 +413,8 @@ static char *ath12k_mhi_state_to_str(enum ath12k_mhi_state mhi_state)
|
||||
return "POWER_ON";
|
||||
case ATH12K_MHI_POWER_OFF:
|
||||
return "POWER_OFF";
|
||||
case ATH12K_MHI_POWER_OFF_KEEP_DEV:
|
||||
return "POWER_OFF_KEEP_DEV";
|
||||
case ATH12K_MHI_FORCE_POWER_OFF:
|
||||
return "FORCE_POWER_OFF";
|
||||
case ATH12K_MHI_SUSPEND:
|
||||
@ -501,6 +446,7 @@ static void ath12k_mhi_set_state_bit(struct ath12k_pci *ab_pci,
|
||||
set_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state);
|
||||
break;
|
||||
case ATH12K_MHI_POWER_OFF:
|
||||
case ATH12K_MHI_POWER_OFF_KEEP_DEV:
|
||||
case ATH12K_MHI_FORCE_POWER_OFF:
|
||||
clear_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state);
|
||||
clear_bit(ATH12K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state);
|
||||
@ -544,6 +490,7 @@ static int ath12k_mhi_check_state_bit(struct ath12k_pci *ab_pci,
|
||||
return 0;
|
||||
break;
|
||||
case ATH12K_MHI_POWER_OFF:
|
||||
case ATH12K_MHI_POWER_OFF_KEEP_DEV:
|
||||
case ATH12K_MHI_SUSPEND:
|
||||
if (test_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state) &&
|
||||
!test_bit(ATH12K_MHI_SUSPEND, &ab_pci->mhi_state))
|
||||
@ -594,12 +541,27 @@ static int ath12k_mhi_set_state(struct ath12k_pci *ab_pci,
|
||||
ret = 0;
|
||||
break;
|
||||
case ATH12K_MHI_POWER_ON:
|
||||
ret = mhi_async_power_up(ab_pci->mhi_ctrl);
|
||||
/* In case of resume, QRTR's resume_early() is called
|
||||
* right after ath12k' resume_early(). Since QRTR requires
|
||||
* MHI mission mode state when preparing IPCR channels
|
||||
* (see ee_mask of that channel), we need to use the 'sync'
|
||||
* version here to make sure MHI is in that state when we
|
||||
* return. Or QRTR might resume before that state comes,
|
||||
* and as a result it fails.
|
||||
*
|
||||
* The 'sync' version works for non-resume (normal power on)
|
||||
* case as well.
|
||||
*/
|
||||
ret = mhi_sync_power_up(ab_pci->mhi_ctrl);
|
||||
break;
|
||||
case ATH12K_MHI_POWER_OFF:
|
||||
mhi_power_down(ab_pci->mhi_ctrl, true);
|
||||
ret = 0;
|
||||
break;
|
||||
case ATH12K_MHI_POWER_OFF_KEEP_DEV:
|
||||
mhi_power_down_keep_dev(ab_pci->mhi_ctrl, true);
|
||||
ret = 0;
|
||||
break;
|
||||
case ATH12K_MHI_FORCE_POWER_OFF:
|
||||
mhi_power_down(ab_pci->mhi_ctrl, false);
|
||||
ret = 0;
|
||||
@ -653,9 +615,17 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ath12k_mhi_stop(struct ath12k_pci *ab_pci)
|
||||
void ath12k_mhi_stop(struct ath12k_pci *ab_pci, bool is_suspend)
|
||||
{
|
||||
ath12k_mhi_set_state(ab_pci, ATH12K_MHI_POWER_OFF);
|
||||
/* During suspend we need to use mhi_power_down_keep_dev()
|
||||
* workaround, otherwise ath12k_core_resume() will timeout
|
||||
* during resume.
|
||||
*/
|
||||
if (is_suspend)
|
||||
ath12k_mhi_set_state(ab_pci, ATH12K_MHI_POWER_OFF_KEEP_DEV);
|
||||
else
|
||||
ath12k_mhi_set_state(ab_pci, ATH12K_MHI_POWER_OFF);
|
||||
|
||||
ath12k_mhi_set_state(ab_pci, ATH12K_MHI_DEINIT);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2020-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.
|
||||
*/
|
||||
#ifndef _ATH12K_MHI_H
|
||||
#define _ATH12K_MHI_H
|
||||
@ -22,6 +22,7 @@ enum ath12k_mhi_state {
|
||||
ATH12K_MHI_DEINIT,
|
||||
ATH12K_MHI_POWER_ON,
|
||||
ATH12K_MHI_POWER_OFF,
|
||||
ATH12K_MHI_POWER_OFF_KEEP_DEV,
|
||||
ATH12K_MHI_FORCE_POWER_OFF,
|
||||
ATH12K_MHI_SUSPEND,
|
||||
ATH12K_MHI_RESUME,
|
||||
@ -34,7 +35,7 @@ extern const struct mhi_controller_config ath12k_mhi_config_qcn9274;
|
||||
extern const struct mhi_controller_config ath12k_mhi_config_wcn7850;
|
||||
|
||||
int ath12k_mhi_start(struct ath12k_pci *ar_pci);
|
||||
void ath12k_mhi_stop(struct ath12k_pci *ar_pci);
|
||||
void ath12k_mhi_stop(struct ath12k_pci *ar_pci, bool is_suspend);
|
||||
int ath12k_mhi_register(struct ath12k_pci *ar_pci);
|
||||
void ath12k_mhi_unregister(struct ath12k_pci *ar_pci);
|
||||
void ath12k_mhi_set_mhictrl_reset(struct ath12k_base *ab);
|
||||
|
@ -121,7 +121,7 @@ static void ath12k_p2p_noa_update_vdev_iter(void *data, u8 *mac,
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct ath12k_p2p_noa_arg *arg = data;
|
||||
|
||||
if (arvif->vdev_id != arg->vdev_id)
|
||||
if (arvif->ar != arg->ar || arvif->vdev_id != arg->vdev_id)
|
||||
return;
|
||||
|
||||
ath12k_p2p_noa_update(arvif, arg->noa);
|
||||
@ -132,6 +132,7 @@ void ath12k_p2p_noa_update_by_vdev_id(struct ath12k *ar, u32 vdev_id,
|
||||
{
|
||||
struct ath12k_p2p_noa_arg arg = {
|
||||
.vdev_id = vdev_id,
|
||||
.ar = ar,
|
||||
.noa = noa,
|
||||
};
|
||||
|
||||
|
@ -12,6 +12,7 @@ struct ath12k_wmi_p2p_noa_info;
|
||||
|
||||
struct ath12k_p2p_noa_arg {
|
||||
u32 vdev_id;
|
||||
struct ath12k *ar;
|
||||
const struct ath12k_wmi_p2p_noa_info *noa;
|
||||
};
|
||||
|
||||
|
@ -872,7 +872,7 @@ static int ath12k_pci_claim(struct ath12k_pci *ab_pci, struct pci_dev *pdev)
|
||||
goto release_region;
|
||||
}
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot pci_mem 0x%p\n", ab->mem);
|
||||
return 0;
|
||||
|
||||
release_region:
|
||||
@ -1271,7 +1271,7 @@ int ath12k_pci_power_up(struct ath12k_base *ab)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath12k_pci_power_down(struct ath12k_base *ab)
|
||||
void ath12k_pci_power_down(struct ath12k_base *ab, bool is_suspend)
|
||||
{
|
||||
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
||||
|
||||
@ -1280,7 +1280,7 @@ void ath12k_pci_power_down(struct ath12k_base *ab)
|
||||
|
||||
ath12k_pci_force_wake(ab_pci->ab);
|
||||
ath12k_pci_msi_disable(ab_pci);
|
||||
ath12k_mhi_stop(ab_pci);
|
||||
ath12k_mhi_stop(ab_pci, is_suspend);
|
||||
clear_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
|
||||
ath12k_pci_sw_reset(ab_pci->ab, false);
|
||||
}
|
||||
@ -1503,7 +1503,7 @@ static void ath12k_pci_remove(struct pci_dev *pdev)
|
||||
ath12k_pci_set_irq_affinity_hint(ab_pci, NULL);
|
||||
|
||||
if (test_bit(ATH12K_FLAG_QMI_FAIL, &ab->dev_flags)) {
|
||||
ath12k_pci_power_down(ab);
|
||||
ath12k_pci_power_down(ab, false);
|
||||
ath12k_qmi_deinit_service(ab);
|
||||
goto qmi_fail;
|
||||
}
|
||||
@ -1531,7 +1531,7 @@ static void ath12k_pci_shutdown(struct pci_dev *pdev)
|
||||
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
||||
|
||||
ath12k_pci_set_irq_affinity_hint(ab_pci, NULL);
|
||||
ath12k_pci_power_down(ab);
|
||||
ath12k_pci_power_down(ab, false);
|
||||
}
|
||||
|
||||
static __maybe_unused int ath12k_pci_pm_suspend(struct device *dev)
|
||||
@ -1558,9 +1558,36 @@ static __maybe_unused int ath12k_pci_pm_resume(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ath12k_pci_pm_ops,
|
||||
ath12k_pci_pm_suspend,
|
||||
ath12k_pci_pm_resume);
|
||||
static __maybe_unused int ath12k_pci_pm_suspend_late(struct device *dev)
|
||||
{
|
||||
struct ath12k_base *ab = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = ath12k_core_suspend_late(ab);
|
||||
if (ret)
|
||||
ath12k_warn(ab, "failed to late suspend core: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __maybe_unused int ath12k_pci_pm_resume_early(struct device *dev)
|
||||
{
|
||||
struct ath12k_base *ab = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = ath12k_core_resume_early(ab);
|
||||
if (ret)
|
||||
ath12k_warn(ab, "failed to early resume core: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops __maybe_unused ath12k_pci_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(ath12k_pci_pm_suspend,
|
||||
ath12k_pci_pm_resume)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(ath12k_pci_pm_suspend_late,
|
||||
ath12k_pci_pm_resume_early)
|
||||
};
|
||||
|
||||
static struct pci_driver ath12k_pci_driver = {
|
||||
.name = "ath12k_pci",
|
||||
|
@ -143,5 +143,5 @@ int ath12k_pci_hif_resume(struct ath12k_base *ab);
|
||||
void ath12k_pci_stop(struct ath12k_base *ab);
|
||||
int ath12k_pci_start(struct ath12k_base *ab);
|
||||
int ath12k_pci_power_up(struct ath12k_base *ab);
|
||||
void ath12k_pci_power_down(struct ath12k_base *ab);
|
||||
void ath12k_pci_power_down(struct ath12k_base *ab, bool is_suspend);
|
||||
#endif /* ATH12K_PCI_H */
|
||||
|
@ -582,6 +582,24 @@ static const struct qmi_elem_info qmi_wlanfw_phy_cap_resp_msg_v01_ei[] = {
|
||||
.offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01,
|
||||
board_id),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x13,
|
||||
.offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01,
|
||||
single_chip_mlo_support_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x13,
|
||||
.offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01,
|
||||
single_chip_mlo_support),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
@ -2005,7 +2023,15 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab,
|
||||
u8 hw_link_id = 0;
|
||||
int i;
|
||||
|
||||
if (!(ab->mlo_capable_flags & ATH12K_INTRA_DEVICE_MLO_SUPPORT)) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_QMI,
|
||||
"intra device MLO is disabled hence skip QMI MLO cap");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ab->qmi.num_radios || ab->qmi.num_radios == U8_MAX) {
|
||||
ab->mlo_capable_flags = 0;
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_QMI,
|
||||
"skip QMI MLO cap due to invalid num_radio %d\n",
|
||||
ab->qmi.num_radios);
|
||||
@ -2124,9 +2150,6 @@ static void ath12k_qmi_phy_cap_send(struct ath12k_base *ab)
|
||||
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)
|
||||
@ -2151,6 +2174,13 @@ static void ath12k_qmi_phy_cap_send(struct ath12k_base *ab)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (resp.single_chip_mlo_support_valid) {
|
||||
if (resp.single_chip_mlo_support)
|
||||
ab->mlo_capable_flags |= ATH12K_INTRA_DEVICE_MLO_SUPPORT;
|
||||
else
|
||||
ab->mlo_capable_flags &= ~ATH12K_INTRA_DEVICE_MLO_SUPPORT;
|
||||
}
|
||||
|
||||
if (!resp.num_phy_valid) {
|
||||
ret = -ENODATA;
|
||||
goto out;
|
||||
@ -2158,9 +2188,11 @@ static void ath12k_qmi_phy_cap_send(struct ath12k_base *ab)
|
||||
|
||||
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",
|
||||
ath12k_dbg(ab, ATH12K_DBG_QMI,
|
||||
"phy capability resp valid %d num_phy %d valid %d board_id %d valid %d single_chip_mlo_support %d\n",
|
||||
resp.num_phy_valid, resp.num_phy,
|
||||
resp.board_id_valid, resp.board_id);
|
||||
resp.board_id_valid, resp.board_id,
|
||||
resp.single_chip_mlo_support_valid, resp.single_chip_mlo_support);
|
||||
|
||||
return;
|
||||
|
||||
@ -2325,8 +2357,9 @@ static void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab)
|
||||
for (i = 0; i < ab->qmi.mem_seg_count; i++) {
|
||||
if (!ab->qmi.target_mem[i].v.addr)
|
||||
continue;
|
||||
|
||||
dma_free_coherent(ab->dev,
|
||||
ab->qmi.target_mem[i].size,
|
||||
ab->qmi.target_mem[i].prev_size,
|
||||
ab->qmi.target_mem[i].v.addr,
|
||||
ab->qmi.target_mem[i].paddr);
|
||||
ab->qmi.target_mem[i].v.addr = NULL;
|
||||
@ -2352,6 +2385,20 @@ static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab)
|
||||
case M3_DUMP_REGION_TYPE:
|
||||
case PAGEABLE_MEM_REGION_TYPE:
|
||||
case CALDB_MEM_REGION_TYPE:
|
||||
/* Firmware reloads in recovery/resume.
|
||||
* In such cases, no need to allocate memory for FW again.
|
||||
*/
|
||||
if (chunk->v.addr) {
|
||||
if (chunk->prev_type == chunk->type &&
|
||||
chunk->prev_size == chunk->size)
|
||||
goto this_chunk_done;
|
||||
|
||||
/* cannot reuse the existing chunk */
|
||||
dma_free_coherent(ab->dev, chunk->prev_size,
|
||||
chunk->v.addr, chunk->paddr);
|
||||
chunk->v.addr = NULL;
|
||||
}
|
||||
|
||||
chunk->v.addr = dma_alloc_coherent(ab->dev,
|
||||
chunk->size,
|
||||
&chunk->paddr,
|
||||
@ -2370,6 +2417,10 @@ static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab)
|
||||
chunk->type, chunk->size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
chunk->prev_type = chunk->type;
|
||||
chunk->prev_size = chunk->size;
|
||||
this_chunk_done:
|
||||
break;
|
||||
default:
|
||||
ath12k_warn(ab, "memory type %u not supported\n",
|
||||
@ -2666,6 +2717,19 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath12k_qmi_m3_free(struct ath12k_base *ab)
|
||||
{
|
||||
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
|
||||
|
||||
if (!m3_mem->vaddr)
|
||||
return;
|
||||
|
||||
dma_free_coherent(ab->dev, m3_mem->size,
|
||||
m3_mem->vaddr, m3_mem->paddr);
|
||||
m3_mem->vaddr = NULL;
|
||||
m3_mem->size = 0;
|
||||
}
|
||||
|
||||
static int ath12k_qmi_m3_load(struct ath12k_base *ab)
|
||||
{
|
||||
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
|
||||
@ -2675,10 +2739,6 @@ static int ath12k_qmi_m3_load(struct ath12k_base *ab)
|
||||
size_t m3_len;
|
||||
int ret;
|
||||
|
||||
if (m3_mem->vaddr)
|
||||
/* m3 firmware buffer is already available in the DMA buffer */
|
||||
return 0;
|
||||
|
||||
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;
|
||||
@ -2700,6 +2760,15 @@ static int ath12k_qmi_m3_load(struct ath12k_base *ab)
|
||||
m3_len = fw->size;
|
||||
}
|
||||
|
||||
/* In recovery/resume cases, M3 buffer is not freed, try to reuse that */
|
||||
if (m3_mem->vaddr) {
|
||||
if (m3_mem->size >= m3_len)
|
||||
goto skip_m3_alloc;
|
||||
|
||||
/* Old buffer is too small, free and reallocate */
|
||||
ath12k_qmi_m3_free(ab);
|
||||
}
|
||||
|
||||
m3_mem->vaddr = dma_alloc_coherent(ab->dev,
|
||||
m3_len, &m3_mem->paddr,
|
||||
GFP_KERNEL);
|
||||
@ -2710,6 +2779,7 @@ static int ath12k_qmi_m3_load(struct ath12k_base *ab)
|
||||
goto out;
|
||||
}
|
||||
|
||||
skip_m3_alloc:
|
||||
memcpy(m3_mem->vaddr, m3_data, m3_len);
|
||||
m3_mem->size = m3_len;
|
||||
|
||||
@ -2721,19 +2791,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath12k_qmi_m3_free(struct ath12k_base *ab)
|
||||
{
|
||||
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
|
||||
|
||||
if (!m3_mem->vaddr)
|
||||
return;
|
||||
|
||||
dma_free_coherent(ab->dev, m3_mem->size,
|
||||
m3_mem->vaddr, m3_mem->paddr);
|
||||
m3_mem->vaddr = NULL;
|
||||
m3_mem->size = 0;
|
||||
}
|
||||
|
||||
static int ath12k_qmi_wlanfw_m3_info_send(struct ath12k_base *ab)
|
||||
{
|
||||
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
|
||||
@ -3178,6 +3235,9 @@ static const struct qmi_msg_handler ath12k_qmi_msg_handlers[] = {
|
||||
.decoded_size = sizeof(struct qmi_wlanfw_fw_ready_ind_msg_v01),
|
||||
.fn = ath12k_qmi_msg_fw_ready_cb,
|
||||
},
|
||||
|
||||
/* end of list */
|
||||
{},
|
||||
};
|
||||
|
||||
static int ath12k_qmi_ops_new_server(struct qmi_handle *qmi_hdl,
|
||||
@ -3261,7 +3321,8 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work)
|
||||
case ATH12K_QMI_EVENT_FW_READY:
|
||||
clear_bit(ATH12K_FLAG_QMI_FAIL, &ab->dev_flags);
|
||||
if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) {
|
||||
ath12k_hal_dump_srng_stats(ab);
|
||||
if (ab->is_reset)
|
||||
ath12k_hal_dump_srng_stats(ab);
|
||||
queue_work(ab->workqueue, &ab->restart_work);
|
||||
break;
|
||||
}
|
||||
|
@ -96,6 +96,8 @@ struct ath12k_qmi_event_msg {
|
||||
struct target_mem_chunk {
|
||||
u32 size;
|
||||
u32 type;
|
||||
u32 prev_size;
|
||||
u32 prev_type;
|
||||
dma_addr_t paddr;
|
||||
union {
|
||||
void __iomem *ioaddr;
|
||||
@ -265,6 +267,8 @@ struct qmi_wlanfw_phy_cap_resp_msg_v01 {
|
||||
u8 num_phy;
|
||||
u8 board_id_valid;
|
||||
u32 board_id;
|
||||
u8 single_chip_mlo_support_valid;
|
||||
u8 single_chip_mlo_support;
|
||||
};
|
||||
|
||||
#define QMI_WLANFW_IND_REGISTER_REQ_MSG_V01_MAX_LEN 54
|
||||
|
@ -49,8 +49,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_hw *ah = ath12k_hw_to_ah(hw);
|
||||
struct ath12k *ar = ath12k_ah_to_ar(ah);
|
||||
int ret;
|
||||
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
|
||||
int ret, i;
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
|
||||
"Regulatory Notification received for %s\n", wiphy_name(wiphy));
|
||||
@ -85,10 +85,16 @@ ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
|
||||
memcpy(&arg.cc_info.alpha2, request->alpha2, 2);
|
||||
arg.cc_info.alpha2[2] = 0;
|
||||
|
||||
ret = ath12k_wmi_send_init_country_cmd(ar, &arg);
|
||||
if (ret)
|
||||
ath12k_warn(ar->ab,
|
||||
"INIT Country code set to fw failed : %d\n", ret);
|
||||
/* Allow fresh updates to wiphy regd */
|
||||
ah->regd_updated = false;
|
||||
|
||||
/* Send the reg change request to all the radios */
|
||||
for_each_ar(ah, ar, i) {
|
||||
ret = ath12k_wmi_send_init_country_cmd(ar, &arg);
|
||||
if (ret)
|
||||
ath12k_warn(ar->ab,
|
||||
"INIT Country code set to fw failed : %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
int ath12k_reg_update_chan_list(struct ath12k *ar)
|
||||
@ -202,10 +208,32 @@ int ath12k_regd_update(struct ath12k *ar, bool init)
|
||||
{
|
||||
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
|
||||
struct ieee80211_regdomain *regd, *regd_copy = NULL;
|
||||
struct ath12k_hw *ah = ar->ah;
|
||||
int ret, regd_len, pdev_id;
|
||||
struct ath12k_base *ab;
|
||||
int i;
|
||||
|
||||
ab = ar->ab;
|
||||
|
||||
/* If one of the radios within ah has already updated the regd for
|
||||
* the wiphy, then avoid setting regd again
|
||||
*/
|
||||
if (ah->regd_updated)
|
||||
return 0;
|
||||
|
||||
/* firmware provides reg rules which are similar for 2 GHz and 5 GHz
|
||||
* pdev but 6 GHz pdev has superset of all rules including rules for
|
||||
* all bands, we prefer 6 GHz pdev's rules to be used for setup of
|
||||
* the wiphy regd.
|
||||
* If 6 GHz pdev was part of the ath12k_hw, wait for the 6 GHz pdev,
|
||||
* else pick the first pdev which calls this function and use its
|
||||
* regd to update global hw regd.
|
||||
* The regd_updated flag set at the end will not allow any further
|
||||
* updates.
|
||||
*/
|
||||
if (ah->use_6ghz_regd && !ar->supports_6ghz)
|
||||
return 0;
|
||||
|
||||
pdev_id = ar->pdev_idx;
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
@ -258,10 +286,17 @@ int ath12k_regd_update(struct ath12k *ar, bool init)
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (ar->state == ATH12K_STATE_ON) {
|
||||
ret = ath12k_reg_update_chan_list(ar);
|
||||
if (ret)
|
||||
goto err;
|
||||
ah->regd_updated = true;
|
||||
/* Apply the new regd to all the radios, this is expected to be received only once
|
||||
* since we check for ah->regd_updated and allow here only once.
|
||||
*/
|
||||
for_each_ar(ah, ar, i) {
|
||||
if (ar->state == ATH12K_STATE_ON) {
|
||||
ab = ar->ab;
|
||||
ret = ath12k_reg_update_chan_list(ar);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -858,20 +858,20 @@ int ath12k_wmi_vdev_create(struct ath12k *ar, u8 *macaddr,
|
||||
len = sizeof(*txrx_streams);
|
||||
txrx_streams->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_TXRX_STREAMS,
|
||||
len);
|
||||
txrx_streams->band = WMI_TPC_CHAINMASK_CONFIG_BAND_2G;
|
||||
txrx_streams->band = cpu_to_le32(WMI_TPC_CHAINMASK_CONFIG_BAND_2G);
|
||||
txrx_streams->supported_tx_streams =
|
||||
args->chains[NL80211_BAND_2GHZ].tx;
|
||||
cpu_to_le32(args->chains[NL80211_BAND_2GHZ].tx);
|
||||
txrx_streams->supported_rx_streams =
|
||||
args->chains[NL80211_BAND_2GHZ].rx;
|
||||
cpu_to_le32(args->chains[NL80211_BAND_2GHZ].rx);
|
||||
|
||||
txrx_streams++;
|
||||
txrx_streams->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_TXRX_STREAMS,
|
||||
len);
|
||||
txrx_streams->band = WMI_TPC_CHAINMASK_CONFIG_BAND_5G;
|
||||
txrx_streams->band = cpu_to_le32(WMI_TPC_CHAINMASK_CONFIG_BAND_5G);
|
||||
txrx_streams->supported_tx_streams =
|
||||
args->chains[NL80211_BAND_5GHZ].tx;
|
||||
cpu_to_le32(args->chains[NL80211_BAND_5GHZ].tx);
|
||||
txrx_streams->supported_rx_streams =
|
||||
args->chains[NL80211_BAND_5GHZ].rx;
|
||||
cpu_to_le32(args->chains[NL80211_BAND_5GHZ].rx);
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
|
||||
"WMI vdev create: id %d type %d subtype %d macaddr %pM pdevid %d\n",
|
||||
@ -2723,6 +2723,149 @@ int ath12k_wmi_send_dfs_phyerr_offload_enable_cmd(struct ath12k *ar,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_set_bios_cmd(struct ath12k_base *ab, u32 param_id,
|
||||
const u8 *buf, size_t buf_len)
|
||||
{
|
||||
struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab;
|
||||
struct wmi_pdev_set_bios_interface_cmd *cmd;
|
||||
struct wmi_tlv *tlv;
|
||||
struct sk_buff *skb;
|
||||
u8 *ptr;
|
||||
u32 len, len_aligned;
|
||||
int ret;
|
||||
|
||||
len_aligned = roundup(buf_len, sizeof(u32));
|
||||
len = sizeof(*cmd) + TLV_HDR_SIZE + len_aligned;
|
||||
|
||||
skb = ath12k_wmi_alloc_skb(wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_pdev_set_bios_interface_cmd *)skb->data;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_BIOS_INTERFACE_CMD,
|
||||
sizeof(*cmd));
|
||||
cmd->pdev_id = cpu_to_le32(WMI_PDEV_ID_SOC);
|
||||
cmd->param_type_id = cpu_to_le32(param_id);
|
||||
cmd->length = cpu_to_le32(buf_len);
|
||||
|
||||
ptr = skb->data + sizeof(*cmd);
|
||||
tlv = (struct wmi_tlv *)ptr;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, len_aligned);
|
||||
ptr += TLV_HDR_SIZE;
|
||||
memcpy(ptr, buf, buf_len);
|
||||
|
||||
ret = ath12k_wmi_cmd_send(&wmi_ab->wmi[0],
|
||||
skb,
|
||||
WMI_PDEV_SET_BIOS_INTERFACE_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ab,
|
||||
"failed to send WMI_PDEV_SET_BIOS_INTERFACE_CMDID parameter id %d: %d\n",
|
||||
param_id, ret);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath12k_wmi_set_bios_sar_cmd(struct ath12k_base *ab, const u8 *psar_table)
|
||||
{
|
||||
struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab;
|
||||
struct wmi_pdev_set_bios_sar_table_cmd *cmd;
|
||||
struct wmi_tlv *tlv;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
u8 *buf_ptr;
|
||||
u32 len, sar_table_len_aligned, sar_dbs_backoff_len_aligned;
|
||||
const u8 *psar_value = psar_table + ATH12K_ACPI_POWER_LIMIT_DATA_OFFSET;
|
||||
const u8 *pdbs_value = psar_table + ATH12K_ACPI_DBS_BACKOFF_DATA_OFFSET;
|
||||
|
||||
sar_table_len_aligned = roundup(ATH12K_ACPI_BIOS_SAR_TABLE_LEN, sizeof(u32));
|
||||
sar_dbs_backoff_len_aligned = roundup(ATH12K_ACPI_BIOS_SAR_DBS_BACKOFF_LEN,
|
||||
sizeof(u32));
|
||||
len = sizeof(*cmd) + TLV_HDR_SIZE + sar_table_len_aligned +
|
||||
TLV_HDR_SIZE + sar_dbs_backoff_len_aligned;
|
||||
|
||||
skb = ath12k_wmi_alloc_skb(wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_pdev_set_bios_sar_table_cmd *)skb->data;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD,
|
||||
sizeof(*cmd));
|
||||
cmd->pdev_id = cpu_to_le32(WMI_PDEV_ID_SOC);
|
||||
cmd->sar_len = cpu_to_le32(ATH12K_ACPI_BIOS_SAR_TABLE_LEN);
|
||||
cmd->dbs_backoff_len = cpu_to_le32(ATH12K_ACPI_BIOS_SAR_DBS_BACKOFF_LEN);
|
||||
|
||||
buf_ptr = skb->data + sizeof(*cmd);
|
||||
tlv = (struct wmi_tlv *)buf_ptr;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE,
|
||||
sar_table_len_aligned);
|
||||
buf_ptr += TLV_HDR_SIZE;
|
||||
memcpy(buf_ptr, psar_value, ATH12K_ACPI_BIOS_SAR_TABLE_LEN);
|
||||
|
||||
buf_ptr += sar_table_len_aligned;
|
||||
tlv = (struct wmi_tlv *)buf_ptr;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE,
|
||||
sar_dbs_backoff_len_aligned);
|
||||
buf_ptr += TLV_HDR_SIZE;
|
||||
memcpy(buf_ptr, pdbs_value, ATH12K_ACPI_BIOS_SAR_DBS_BACKOFF_LEN);
|
||||
|
||||
ret = ath12k_wmi_cmd_send(&wmi_ab->wmi[0],
|
||||
skb,
|
||||
WMI_PDEV_SET_BIOS_SAR_TABLE_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ab,
|
||||
"failed to send WMI_PDEV_SET_BIOS_INTERFACE_CMDID %d\n",
|
||||
ret);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_set_bios_geo_cmd(struct ath12k_base *ab, const u8 *pgeo_table)
|
||||
{
|
||||
struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab;
|
||||
struct wmi_pdev_set_bios_geo_table_cmd *cmd;
|
||||
struct wmi_tlv *tlv;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
u8 *buf_ptr;
|
||||
u32 len, sar_geo_len_aligned;
|
||||
const u8 *pgeo_value = pgeo_table + ATH12K_ACPI_GEO_OFFSET_DATA_OFFSET;
|
||||
|
||||
sar_geo_len_aligned = roundup(ATH12K_ACPI_BIOS_SAR_GEO_OFFSET_LEN, sizeof(u32));
|
||||
len = sizeof(*cmd) + TLV_HDR_SIZE + sar_geo_len_aligned;
|
||||
|
||||
skb = ath12k_wmi_alloc_skb(wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_pdev_set_bios_geo_table_cmd *)skb->data;
|
||||
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD,
|
||||
sizeof(*cmd));
|
||||
cmd->pdev_id = cpu_to_le32(WMI_PDEV_ID_SOC);
|
||||
cmd->geo_len = cpu_to_le32(ATH12K_ACPI_BIOS_SAR_GEO_OFFSET_LEN);
|
||||
|
||||
buf_ptr = skb->data + sizeof(*cmd);
|
||||
tlv = (struct wmi_tlv *)buf_ptr;
|
||||
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, sar_geo_len_aligned);
|
||||
buf_ptr += TLV_HDR_SIZE;
|
||||
memcpy(buf_ptr, pgeo_value, ATH12K_ACPI_BIOS_SAR_GEO_OFFSET_LEN);
|
||||
|
||||
ret = ath12k_wmi_cmd_send(&wmi_ab->wmi[0],
|
||||
skb,
|
||||
WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID);
|
||||
if (ret) {
|
||||
ath12k_warn(ab,
|
||||
"failed to send WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID %d\n",
|
||||
ret);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_wmi_delba_send(struct ath12k *ar, u32 vdev_id, const u8 *mac,
|
||||
u32 tid, u32 initiator, u32 reason)
|
||||
{
|
||||
@ -3324,7 +3467,8 @@ ath12k_wmi_copy_resource_config(struct ath12k_wmi_resource_config_params *wmi_cf
|
||||
wmi_cfg->bpf_instruction_size = cpu_to_le32(tg_cfg->bpf_instruction_size);
|
||||
wmi_cfg->max_bssid_rx_filters = cpu_to_le32(tg_cfg->max_bssid_rx_filters);
|
||||
wmi_cfg->use_pdev_id = cpu_to_le32(tg_cfg->use_pdev_id);
|
||||
wmi_cfg->flag1 = cpu_to_le32(tg_cfg->atf_config);
|
||||
wmi_cfg->flag1 = cpu_to_le32(tg_cfg->atf_config |
|
||||
WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64);
|
||||
wmi_cfg->peer_map_unmap_version = cpu_to_le32(tg_cfg->peer_map_unmap_version);
|
||||
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);
|
||||
@ -4041,6 +4185,7 @@ static void ath12k_wmi_free_dbring_caps(struct ath12k_base *ab)
|
||||
{
|
||||
kfree(ab->db_caps);
|
||||
ab->db_caps = NULL;
|
||||
ab->num_db_cap = 0;
|
||||
}
|
||||
|
||||
static int ath12k_wmi_dma_ring_caps(struct ath12k_base *ab,
|
||||
@ -5927,13 +6072,11 @@ static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb)
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Pending handle beacon implementation
|
||||
*if (ieee80211_is_beacon(hdr->frame_control))
|
||||
* ath12k_mac_handle_beacon(ar, skb);
|
||||
*/
|
||||
if (ieee80211_is_beacon(hdr->frame_control))
|
||||
ath12k_mac_handle_beacon(ar, skb);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_MGMT,
|
||||
"event mgmt rx skb %pK len %d ftype %02x stype %02x\n",
|
||||
"event mgmt rx skb %p len %d ftype %02x stype %02x\n",
|
||||
skb, skb->len,
|
||||
fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE);
|
||||
|
||||
@ -6137,42 +6280,44 @@ static void ath12k_roam_event(struct ath12k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_roam_event roam_ev = {};
|
||||
struct ath12k *ar;
|
||||
u32 vdev_id;
|
||||
u8 roam_reason;
|
||||
|
||||
if (ath12k_pull_roam_ev(ab, skb, &roam_ev) != 0) {
|
||||
ath12k_warn(ab, "failed to extract roam event");
|
||||
return;
|
||||
}
|
||||
|
||||
vdev_id = le32_to_cpu(roam_ev.vdev_id);
|
||||
roam_reason = u32_get_bits(le32_to_cpu(roam_ev.reason),
|
||||
WMI_ROAM_REASON_MASK);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI,
|
||||
"wmi roam event vdev %u reason 0x%08x rssi %d\n",
|
||||
roam_ev.vdev_id, roam_ev.reason, roam_ev.rssi);
|
||||
"wmi roam event vdev %u reason %d rssi %d\n",
|
||||
vdev_id, roam_reason, roam_ev.rssi);
|
||||
|
||||
rcu_read_lock();
|
||||
ar = ath12k_mac_get_ar_by_vdev_id(ab, le32_to_cpu(roam_ev.vdev_id));
|
||||
ar = ath12k_mac_get_ar_by_vdev_id(ab, vdev_id);
|
||||
if (!ar) {
|
||||
ath12k_warn(ab, "invalid vdev id in roam ev %d",
|
||||
roam_ev.vdev_id);
|
||||
ath12k_warn(ab, "invalid vdev id in roam ev %d", vdev_id);
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(roam_ev.reason) >= WMI_ROAM_REASON_MAX)
|
||||
if (roam_reason >= WMI_ROAM_REASON_MAX)
|
||||
ath12k_warn(ab, "ignoring unknown roam event reason %d on vdev %i\n",
|
||||
roam_ev.reason, roam_ev.vdev_id);
|
||||
roam_reason, vdev_id);
|
||||
|
||||
switch (le32_to_cpu(roam_ev.reason)) {
|
||||
switch (roam_reason) {
|
||||
case WMI_ROAM_REASON_BEACON_MISS:
|
||||
/* TODO: Pending beacon miss and connection_loss_work
|
||||
* implementation
|
||||
* ath12k_mac_handle_beacon_miss(ar, vdev_id);
|
||||
*/
|
||||
ath12k_mac_handle_beacon_miss(ar, vdev_id);
|
||||
break;
|
||||
case WMI_ROAM_REASON_BETTER_AP:
|
||||
case WMI_ROAM_REASON_LOW_RSSI:
|
||||
case WMI_ROAM_REASON_SUITABLE_AP_FOUND:
|
||||
case WMI_ROAM_REASON_HO_FAILED:
|
||||
ath12k_warn(ab, "ignoring not implemented roam event reason %d on vdev %i\n",
|
||||
roam_ev.reason, roam_ev.vdev_id);
|
||||
roam_reason, vdev_id);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -353,6 +353,9 @@ enum wmi_tlv_cmd_id {
|
||||
WMI_PDEV_DMA_RING_CFG_REQ_CMDID,
|
||||
WMI_PDEV_HE_TB_ACTION_FRM_CMDID,
|
||||
WMI_PDEV_PKTLOG_FILTER_CMDID,
|
||||
WMI_PDEV_SET_BIOS_SAR_TABLE_CMDID = 0x4044,
|
||||
WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID = 0x4045,
|
||||
WMI_PDEV_SET_BIOS_INTERFACE_CMDID = 0x404A,
|
||||
WMI_VDEV_CREATE_CMDID = WMI_TLV_CMD(WMI_GRP_VDEV),
|
||||
WMI_VDEV_DELETE_CMDID,
|
||||
WMI_VDEV_START_REQUEST_CMDID,
|
||||
@ -1925,6 +1928,9 @@ enum wmi_tlv_tag {
|
||||
WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9,
|
||||
WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT,
|
||||
WMI_TAG_EHT_RATE_SET = 0x3C4,
|
||||
WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD = 0x3D8,
|
||||
WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD = 0x3D9,
|
||||
WMI_TAG_PDEV_SET_BIOS_INTERFACE_CMD = 0x3FB,
|
||||
WMI_TAG_MAX
|
||||
};
|
||||
|
||||
@ -2195,8 +2201,11 @@ enum wmi_peer_param {
|
||||
WMI_PEER_SET_MAX_TX_RATE = 17,
|
||||
WMI_PEER_SET_MIN_TX_RATE = 18,
|
||||
WMI_PEER_SET_DEFAULT_ROUTING = 19,
|
||||
WMI_PEER_CHWIDTH_PUNCTURE_20MHZ_BITMAP = 39,
|
||||
};
|
||||
|
||||
#define WMI_PEER_PUNCTURE_BITMAP GENMASK(23, 8)
|
||||
|
||||
enum wmi_slot_time {
|
||||
WMI_VDEV_SLOT_TIME_LONG = 1,
|
||||
WMI_VDEV_SLOT_TIME_SHORT = 2,
|
||||
@ -2400,6 +2409,7 @@ struct wmi_init_cmd {
|
||||
|
||||
#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)
|
||||
#define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5)
|
||||
|
||||
struct ath12k_wmi_resource_config_params {
|
||||
__le32 tlv_header;
|
||||
@ -2600,6 +2610,19 @@ struct ath12k_wmi_soc_hal_reg_caps_params {
|
||||
__le32 num_phy;
|
||||
} __packed;
|
||||
|
||||
enum wmi_channel_width {
|
||||
WMI_CHAN_WIDTH_20 = 0,
|
||||
WMI_CHAN_WIDTH_40 = 1,
|
||||
WMI_CHAN_WIDTH_80 = 2,
|
||||
WMI_CHAN_WIDTH_160 = 3,
|
||||
WMI_CHAN_WIDTH_80P80 = 4,
|
||||
WMI_CHAN_WIDTH_5 = 5,
|
||||
WMI_CHAN_WIDTH_10 = 6,
|
||||
WMI_CHAN_WIDTH_165 = 7,
|
||||
WMI_CHAN_WIDTH_160P160 = 8,
|
||||
WMI_CHAN_WIDTH_320 = 9,
|
||||
};
|
||||
|
||||
#define WMI_MAX_EHTCAP_MAC_SIZE 2
|
||||
#define WMI_MAX_EHTCAP_PHY_SIZE 3
|
||||
#define WMI_MAX_EHTCAP_RATE_SET 3
|
||||
@ -2724,9 +2747,9 @@ struct wmi_vdev_create_cmd {
|
||||
|
||||
struct ath12k_wmi_vdev_txrx_streams_params {
|
||||
__le32 tlv_header;
|
||||
u32 band;
|
||||
u32 supported_tx_streams;
|
||||
u32 supported_rx_streams;
|
||||
__le32 band;
|
||||
__le32 supported_tx_streams;
|
||||
__le32 supported_rx_streams;
|
||||
} __packed;
|
||||
|
||||
struct wmi_vdev_delete_cmd {
|
||||
@ -4182,6 +4205,9 @@ struct wmi_peer_sta_kickout_event {
|
||||
struct ath12k_wmi_mac_addr_params peer_macaddr;
|
||||
} __packed;
|
||||
|
||||
#define WMI_ROAM_REASON_MASK GENMASK(3, 0)
|
||||
#define WMI_ROAM_SUBNET_STATUS_MASK GENMASK(5, 4)
|
||||
|
||||
enum wmi_roam_reason {
|
||||
WMI_ROAM_REASON_BETTER_AP = 1,
|
||||
WMI_ROAM_REASON_BEACON_MISS = 2,
|
||||
@ -4774,6 +4800,37 @@ struct ath12k_wmi_base {
|
||||
struct ath12k_wmi_target_cap_arg *targ_cap;
|
||||
};
|
||||
|
||||
struct wmi_pdev_set_bios_interface_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 pdev_id;
|
||||
__le32 param_type_id;
|
||||
__le32 length;
|
||||
} __packed;
|
||||
|
||||
enum wmi_bios_param_type {
|
||||
WMI_BIOS_PARAM_CCA_THRESHOLD_TYPE = 0,
|
||||
WMI_BIOS_PARAM_TAS_CONFIG_TYPE = 1,
|
||||
WMI_BIOS_PARAM_TAS_DATA_TYPE = 2,
|
||||
|
||||
/* bandedge control power */
|
||||
WMI_BIOS_PARAM_TYPE_BANDEDGE = 3,
|
||||
|
||||
WMI_BIOS_PARAM_TYPE_MAX,
|
||||
};
|
||||
|
||||
struct wmi_pdev_set_bios_sar_table_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 pdev_id;
|
||||
__le32 sar_len;
|
||||
__le32 dbs_backoff_len;
|
||||
} __packed;
|
||||
|
||||
struct wmi_pdev_set_bios_geo_table_cmd {
|
||||
__le32 tlv_header;
|
||||
__le32 pdev_id;
|
||||
__le32 geo_len;
|
||||
} __packed;
|
||||
|
||||
#define ATH12K_FW_STATS_BUF_SIZE (1024 * 1024)
|
||||
|
||||
enum wmi_sys_cap_info_flags {
|
||||
@ -4932,6 +4989,10 @@ int ath12k_wmi_probe_resp_tmpl(struct ath12k *ar, u32 vdev_id,
|
||||
struct sk_buff *tmpl);
|
||||
int ath12k_wmi_set_hw_mode(struct ath12k_base *ab,
|
||||
enum wmi_host_hw_mode_config_type mode);
|
||||
int ath12k_wmi_set_bios_cmd(struct ath12k_base *ab, u32 param_id,
|
||||
const u8 *buf, size_t buf_len);
|
||||
int ath12k_wmi_set_bios_sar_cmd(struct ath12k_base *ab, const u8 *psar_table);
|
||||
int ath12k_wmi_set_bios_geo_cmd(struct ath12k_base *ab, const u8 *pgeo_table);
|
||||
|
||||
static inline u32
|
||||
ath12k_wmi_caps_ext_get_pdev_id(const struct ath12k_wmi_caps_ext_params *param)
|
||||
|
@ -1427,25 +1427,7 @@ static struct sdio_driver ath6kl_sdio_driver = {
|
||||
.remove = ath6kl_sdio_remove,
|
||||
.drv.pm = ATH6KL_SDIO_PM_OPS,
|
||||
};
|
||||
|
||||
static int __init ath6kl_sdio_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sdio_register_driver(&ath6kl_sdio_driver);
|
||||
if (ret)
|
||||
ath6kl_err("sdio driver registration failed: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit ath6kl_sdio_exit(void)
|
||||
{
|
||||
sdio_unregister_driver(&ath6kl_sdio_driver);
|
||||
}
|
||||
|
||||
module_init(ath6kl_sdio_init);
|
||||
module_exit(ath6kl_sdio_exit);
|
||||
module_sdio_driver(ath6kl_sdio_driver);
|
||||
|
||||
MODULE_AUTHOR("Atheros Communications, Inc.");
|
||||
MODULE_DESCRIPTION("Driver support for Atheros AR600x SDIO devices");
|
||||
|
@ -135,8 +135,7 @@ void ath9k_ps_wakeup(struct ath_softc *sc)
|
||||
if (power_mode != ATH9K_PM_AWAKE) {
|
||||
spin_lock(&common->cc_lock);
|
||||
ath_hw_cycle_counters_update(common);
|
||||
memset(&common->cc_survey, 0, sizeof(common->cc_survey));
|
||||
memset(&common->cc_ani, 0, sizeof(common->cc_ani));
|
||||
memset(&common->cc, 0, sizeof(common->cc));
|
||||
spin_unlock(&common->cc_lock);
|
||||
}
|
||||
|
||||
|
@ -280,7 +280,8 @@ static void carl9170_tx_release(struct kref *ref)
|
||||
* carl9170_tx_fill_rateinfo() has filled the rate information
|
||||
* before we get to this point.
|
||||
*/
|
||||
memset_after(&txinfo->status, 0, rates);
|
||||
memset(&txinfo->pad, 0, sizeof(txinfo->pad));
|
||||
memset(&txinfo->rate_driver_data, 0, sizeof(txinfo->rate_driver_data));
|
||||
|
||||
if (atomic_read(&ar->tx_total_queued))
|
||||
ar->tx_schedule = true;
|
||||
|
@ -1069,6 +1069,38 @@ static int carl9170_usb_probe(struct usb_interface *intf,
|
||||
ar->usb_ep_cmd_is_bulk = true;
|
||||
}
|
||||
|
||||
/* Verify that all expected endpoints are present */
|
||||
if (ar->usb_ep_cmd_is_bulk) {
|
||||
u8 bulk_ep_addr[] = {
|
||||
AR9170_USB_EP_RX | USB_DIR_IN,
|
||||
AR9170_USB_EP_TX | USB_DIR_OUT,
|
||||
AR9170_USB_EP_CMD | USB_DIR_OUT,
|
||||
0};
|
||||
u8 int_ep_addr[] = {
|
||||
AR9170_USB_EP_IRQ | USB_DIR_IN,
|
||||
0};
|
||||
if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
|
||||
!usb_check_int_endpoints(intf, int_ep_addr))
|
||||
err = -ENODEV;
|
||||
} else {
|
||||
u8 bulk_ep_addr[] = {
|
||||
AR9170_USB_EP_RX | USB_DIR_IN,
|
||||
AR9170_USB_EP_TX | USB_DIR_OUT,
|
||||
0};
|
||||
u8 int_ep_addr[] = {
|
||||
AR9170_USB_EP_IRQ | USB_DIR_IN,
|
||||
AR9170_USB_EP_CMD | USB_DIR_OUT,
|
||||
0};
|
||||
if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
|
||||
!usb_check_int_endpoints(intf, int_ep_addr))
|
||||
err = -ENODEV;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
carl9170_free(ar);
|
||||
return err;
|
||||
}
|
||||
|
||||
usb_set_intfdata(intf, ar);
|
||||
SET_IEEE80211_DEV(ar->hw, &intf->dev);
|
||||
|
||||
|
@ -892,10 +892,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
struct wireless_dev *wdev = request->wdev;
|
||||
struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
|
||||
struct {
|
||||
struct wmi_start_scan_cmd cmd;
|
||||
u16 chnl[4];
|
||||
} __packed cmd;
|
||||
DEFINE_FLEX(struct wmi_start_scan_cmd, cmd,
|
||||
channel_list, num_channels, 4);
|
||||
uint i, n;
|
||||
int rc;
|
||||
|
||||
@ -977,9 +975,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
||||
vif->scan_request = request;
|
||||
mod_timer(&vif->scan_timer, jiffies + WIL6210_SCAN_TO);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.cmd.scan_type = WMI_ACTIVE_SCAN;
|
||||
cmd.cmd.num_channels = 0;
|
||||
cmd->scan_type = WMI_ACTIVE_SCAN;
|
||||
cmd->num_channels = 0;
|
||||
n = min(request->n_channels, 4U);
|
||||
for (i = 0; i < n; i++) {
|
||||
int ch = request->channels[i]->hw_value;
|
||||
@ -991,7 +988,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
||||
continue;
|
||||
}
|
||||
/* 0-based channel indexes */
|
||||
cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1;
|
||||
cmd->num_channels++;
|
||||
cmd->channel_list[cmd->num_channels - 1].channel = ch - 1;
|
||||
wil_dbg_misc(wil, "Scan for ch %d : %d MHz\n", ch,
|
||||
request->channels[i]->center_freq);
|
||||
}
|
||||
@ -1007,16 +1005,15 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
||||
if (rc)
|
||||
goto out_restore;
|
||||
|
||||
if (wil->discovery_mode && cmd.cmd.scan_type == WMI_ACTIVE_SCAN) {
|
||||
cmd.cmd.discovery_mode = 1;
|
||||
if (wil->discovery_mode && cmd->scan_type == WMI_ACTIVE_SCAN) {
|
||||
cmd->discovery_mode = 1;
|
||||
wil_dbg_misc(wil, "active scan with discovery_mode=1\n");
|
||||
}
|
||||
|
||||
if (vif->mid == 0)
|
||||
wil->radio_wdev = wdev;
|
||||
rc = wmi_send(wil, WMI_START_SCAN_CMDID, vif->mid,
|
||||
&cmd, sizeof(cmd.cmd) +
|
||||
cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0]));
|
||||
cmd, struct_size(cmd, channel_list, cmd->num_channels));
|
||||
|
||||
out_restore:
|
||||
if (rc) {
|
||||
|
@ -4014,28 +4014,23 @@ int wmi_set_cqm_rssi_config(struct wil6210_priv *wil,
|
||||
struct net_device *ndev = wil->main_ndev;
|
||||
struct wil6210_vif *vif = ndev_to_vif(ndev);
|
||||
int rc;
|
||||
struct {
|
||||
struct wmi_set_link_monitor_cmd cmd;
|
||||
s8 rssi_thold;
|
||||
} __packed cmd = {
|
||||
.cmd = {
|
||||
.rssi_hyst = rssi_hyst,
|
||||
.rssi_thresholds_list_size = 1,
|
||||
},
|
||||
.rssi_thold = rssi_thold,
|
||||
};
|
||||
struct {
|
||||
struct wmi_cmd_hdr hdr;
|
||||
struct wmi_set_link_monitor_event evt;
|
||||
} __packed reply = {
|
||||
.evt = {.status = WMI_FW_STATUS_FAILURE},
|
||||
};
|
||||
DEFINE_FLEX(struct wmi_set_link_monitor_cmd, cmd,
|
||||
rssi_thresholds_list, rssi_thresholds_list_size, 1);
|
||||
|
||||
cmd->rssi_hyst = rssi_hyst;
|
||||
cmd->rssi_thresholds_list[0] = rssi_thold;
|
||||
|
||||
if (rssi_thold > S8_MAX || rssi_thold < S8_MIN || rssi_hyst > U8_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
rc = wmi_call(wil, WMI_SET_LINK_MONITOR_CMDID, vif->mid, &cmd,
|
||||
sizeof(cmd), WMI_SET_LINK_MONITOR_EVENTID,
|
||||
rc = wmi_call(wil, WMI_SET_LINK_MONITOR_CMDID, vif->mid, cmd,
|
||||
__struct_size(cmd), WMI_SET_LINK_MONITOR_EVENTID,
|
||||
&reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc) {
|
||||
wil_err(wil, "WMI_SET_LINK_MONITOR_CMDID failed, rc %d\n", rc);
|
||||
|
@ -474,7 +474,7 @@ struct wmi_start_scan_cmd {
|
||||
struct {
|
||||
u8 channel;
|
||||
u8 reserved;
|
||||
} channel_list[];
|
||||
} channel_list[] __counted_by(num_channels);
|
||||
} __packed;
|
||||
|
||||
#define WMI_MAX_PNO_SSID_NUM (16)
|
||||
@ -3320,7 +3320,7 @@ struct wmi_set_link_monitor_cmd {
|
||||
u8 rssi_hyst;
|
||||
u8 reserved[12];
|
||||
u8 rssi_thresholds_list_size;
|
||||
s8 rssi_thresholds_list[];
|
||||
s8 rssi_thresholds_list[] __counted_by(rssi_thresholds_list_size);
|
||||
} __packed;
|
||||
|
||||
/* wmi_link_monitor_event_type */
|
||||
|
@ -630,12 +630,28 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_sync_power_up(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
/**
|
||||
* mhi_power_down - Start MHI power down sequence
|
||||
* mhi_power_down - Power down the MHI device and also destroy the
|
||||
* 'struct device' for the channels associated with it.
|
||||
* See also mhi_power_down_keep_dev() which is a variant
|
||||
* of this API that keeps the 'struct device' for channels
|
||||
* (useful during suspend/hibernation).
|
||||
* @mhi_cntrl: MHI controller
|
||||
* @graceful: Link is still accessible, so do a graceful shutdown process
|
||||
*/
|
||||
void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful);
|
||||
|
||||
/**
|
||||
* mhi_power_down_keep_dev - Power down the MHI device but keep the 'struct
|
||||
* device' for the channels associated with it.
|
||||
* This is a variant of 'mhi_power_down()' and
|
||||
* useful in scenarios such as suspend/hibernation
|
||||
* where destroying of the 'struct device' is not
|
||||
* needed.
|
||||
* @mhi_cntrl: MHI controller
|
||||
* @graceful: Link is still accessible, so do a graceful shutdown process
|
||||
*/
|
||||
void mhi_power_down_keep_dev(struct mhi_controller *mhi_cntrl, bool graceful);
|
||||
|
||||
/**
|
||||
* mhi_unprepare_after_power_down - Free any allocated memory after power down
|
||||
* @mhi_cntrl: MHI controller
|
||||
|
@ -118,6 +118,51 @@ static const struct mhi_device_id qcom_mhi_qrtr_id_table[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(mhi, qcom_mhi_qrtr_id_table);
|
||||
|
||||
static int __maybe_unused qcom_mhi_qrtr_pm_suspend_late(struct device *dev)
|
||||
{
|
||||
struct mhi_device *mhi_dev = container_of(dev, struct mhi_device, dev);
|
||||
enum mhi_state state;
|
||||
|
||||
state = mhi_get_mhi_state(mhi_dev->mhi_cntrl);
|
||||
/*
|
||||
* If the device is in suspend state, then no need for the
|
||||
* client driver to unprepare the channels.
|
||||
*/
|
||||
if (state == MHI_STATE_M3)
|
||||
return 0;
|
||||
|
||||
mhi_unprepare_from_transfer(mhi_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused qcom_mhi_qrtr_pm_resume_early(struct device *dev)
|
||||
{
|
||||
struct mhi_device *mhi_dev = container_of(dev, struct mhi_device, dev);
|
||||
enum mhi_state state;
|
||||
int rc;
|
||||
|
||||
state = mhi_get_mhi_state(mhi_dev->mhi_cntrl);
|
||||
/*
|
||||
* If the device is in suspend state, we won't unprepare channels
|
||||
* in suspend callback, therefore no need to prepare channels when
|
||||
* resume.
|
||||
*/
|
||||
if (state == MHI_STATE_M3)
|
||||
return 0;
|
||||
|
||||
rc = mhi_prepare_for_transfer_autoqueue(mhi_dev);
|
||||
if (rc)
|
||||
dev_err(dev, "failed to prepare for autoqueue transfer %d\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops qcom_mhi_qrtr_pm_ops = {
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(qcom_mhi_qrtr_pm_suspend_late,
|
||||
qcom_mhi_qrtr_pm_resume_early)
|
||||
};
|
||||
|
||||
static struct mhi_driver qcom_mhi_qrtr_driver = {
|
||||
.probe = qcom_mhi_qrtr_probe,
|
||||
.remove = qcom_mhi_qrtr_remove,
|
||||
@ -126,6 +171,7 @@ static struct mhi_driver qcom_mhi_qrtr_driver = {
|
||||
.id_table = qcom_mhi_qrtr_id_table,
|
||||
.driver = {
|
||||
.name = "qcom_mhi_qrtr",
|
||||
.pm = &qcom_mhi_qrtr_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user