diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath10k')
35 files changed, 1230 insertions, 545 deletions
diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index ab8f77ae5e66..f0c615fa5614 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -728,20 +728,17 @@ static int ath10k_ahb_probe(struct platform_device *pdev) struct ath10k *ar; struct ath10k_ahb *ar_ahb; struct ath10k_pci *ar_pci; - const struct of_device_id *of_id; enum ath10k_hw_rev hw_rev; size_t size; int ret; struct ath10k_bus_params bus_params = {}; - of_id = of_match_device(ath10k_ahb_of_match, &pdev->dev); - if (!of_id) { - dev_err(&pdev->dev, "failed to find matching device tree id\n"); + hw_rev = (enum ath10k_hw_rev)of_device_get_match_data(&pdev->dev); + if (!hw_rev) { + dev_err(&pdev->dev, "OF data missing\n"); return -EINVAL; } - hw_rev = (enum ath10k_hw_rev)of_id->data; - size = sizeof(*ar_pci) + sizeof(*ar_ahb); ar = ath10k_core_create(size, &pdev->dev, ATH10K_BUS_AHB, hw_rev, &ath10k_ahb_hif_ops); diff --git a/drivers/net/wireless/ath/ath10k/bmi.c b/drivers/net/wireless/ath/ath10k/bmi.c index 4481ed375f55..af6546572df2 100644 --- a/drivers/net/wireless/ath/ath10k/bmi.c +++ b/drivers/net/wireless/ath/ath10k/bmi.c @@ -101,7 +101,7 @@ int ath10k_bmi_get_target_info_sdio(struct ath10k *ar, cmd.id = __cpu_to_le32(BMI_GET_TARGET_INFO); /* Step 1: Read 4 bytes of the target info and check if it is - * the special sentinal version word or the first word in the + * the special sentinel version word or the first word in the * version response. */ resplen = sizeof(u32); @@ -111,7 +111,7 @@ int ath10k_bmi_get_target_info_sdio(struct ath10k *ar, return ret; } - /* Some SDIO boards have a special sentinal byte before the real + /* Some SDIO boards have a special sentinel byte before the real * version response. */ if (__le32_to_cpu(tmp) == TARGET_VERSION_SENTINAL) { diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index c45c814fd122..59926227bd49 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -1323,7 +1323,7 @@ EXPORT_SYMBOL(ath10k_ce_per_engine_service); /* * Handler for per-engine interrupts on ALL active CEs. * This is used in cases where the system is sharing a - * single interrput for all CEs + * single interrupt for all CEs */ void ath10k_ce_per_engine_service_any(struct ath10k *ar) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 5935e0973d14..400f332a7ff0 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -12,6 +12,7 @@ #include <linux/dmi.h> #include <linux/ctype.h> #include <linux/pm_qos.h> +#include <linux/nvmem-consumer.h> #include <asm/byteorder.h> #include "core.h" @@ -32,9 +33,11 @@ EXPORT_SYMBOL(ath10k_debug_mask); static unsigned int ath10k_cryptmode_param; static bool uart_print; static bool skip_otp; -static bool rawmode; static bool fw_diag_log; +/* frame mode values are mapped as per enum ath10k_hw_txrx_mode */ +unsigned int ath10k_frame_mode = ATH10K_HW_TXRX_NATIVE_WIFI; + unsigned long ath10k_coredump_mask = BIT(ATH10K_FW_CRASH_DUMP_REGISTERS) | BIT(ATH10K_FW_CRASH_DUMP_CE_DATA); @@ -43,15 +46,16 @@ module_param_named(debug_mask, ath10k_debug_mask, uint, 0644); module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644); module_param(uart_print, bool, 0644); module_param(skip_otp, bool, 0644); -module_param(rawmode, bool, 0644); module_param(fw_diag_log, bool, 0644); +module_param_named(frame_mode, ath10k_frame_mode, uint, 0644); module_param_named(coredump_mask, ath10k_coredump_mask, ulong, 0444); MODULE_PARM_DESC(debug_mask, "Debugging mask"); MODULE_PARM_DESC(uart_print, "Uart target debugging"); MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode"); MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software"); -MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath"); +MODULE_PARM_DESC(frame_mode, + "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)"); MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file"); MODULE_PARM_DESC(fw_diag_log, "Diag based fw log debugging"); @@ -74,6 +78,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA988X_BOARD_DATA_SZ, .board_ext_size = QCA988X_BOARD_EXT_DATA_SZ, }, + .rx_desc_ops = &qca988x_rx_desc_ops, .hw_ops = &qca988x_ops, .decap_align_bytes = 4, .spectral_bin_discard = 0, @@ -89,8 +94,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .rri_on_ddr = false, .hw_filter_reset_required = true, .fw_diag_ce_download = false, + .credit_size_workaround = false, .tx_stats_over_pktlog = true, .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = QCA988X_HW_2_0_VERSION, @@ -109,6 +117,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA988X_BOARD_DATA_SZ, .board_ext_size = QCA988X_BOARD_EXT_DATA_SZ, }, + .rx_desc_ops = &qca988x_rx_desc_ops, .hw_ops = &qca988x_ops, .decap_align_bytes = 4, .spectral_bin_discard = 0, @@ -124,8 +133,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .rri_on_ddr = false, .hw_filter_reset_required = true, .fw_diag_ce_download = false, + .credit_size_workaround = false, .tx_stats_over_pktlog = true, .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = QCA9887_HW_1_0_VERSION, @@ -145,6 +157,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA9887_BOARD_DATA_SZ, .board_ext_size = QCA9887_BOARD_EXT_DATA_SZ, }, + .rx_desc_ops = &qca988x_rx_desc_ops, .hw_ops = &qca988x_ops, .decap_align_bytes = 4, .spectral_bin_discard = 0, @@ -160,8 +173,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .rri_on_ddr = false, .hw_filter_reset_required = true, .fw_diag_ce_download = false, + .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = QCA6174_HW_3_2_VERSION, @@ -180,6 +196,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, + .rx_desc_ops = &qca988x_rx_desc_ops, .hw_ops = &qca6174_sdio_ops, .hw_clk = qca6174_clk, .target_cpu_freq = 176000000, @@ -190,9 +207,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .num_wds_entries = 0x20, .uart_pin_workaround = true, .tx_stats_over_pktlog = false, + .credit_size_workaround = false, .bmi_large_size_download = true, .supports_peer_stats_info = true, .dynamic_sar_support = true, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = QCA6174_HW_2_1_VERSION, @@ -211,6 +231,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, + .rx_desc_ops = &qca988x_rx_desc_ops, .hw_ops = &qca988x_ops, .decap_align_bytes = 4, .spectral_bin_discard = 0, @@ -226,8 +247,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .rri_on_ddr = false, .hw_filter_reset_required = true, .fw_diag_ce_download = false, + .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = QCA6174_HW_2_1_VERSION, @@ -246,6 +270,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, + .rx_desc_ops = &qca988x_rx_desc_ops, .hw_ops = &qca988x_ops, .decap_align_bytes = 4, .spectral_bin_discard = 0, @@ -261,8 +286,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .rri_on_ddr = false, .hw_filter_reset_required = true, .fw_diag_ce_download = false, + .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = QCA6174_HW_3_0_VERSION, @@ -281,6 +309,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, + .rx_desc_ops = &qca988x_rx_desc_ops, .hw_ops = &qca988x_ops, .decap_align_bytes = 4, .spectral_bin_discard = 0, @@ -296,8 +325,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .rri_on_ddr = false, .hw_filter_reset_required = true, .fw_diag_ce_download = false, + .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = QCA6174_HW_3_2_VERSION, @@ -317,6 +349,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA6174_BOARD_DATA_SZ, .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, }, + .rx_desc_ops = &qca988x_rx_desc_ops, .hw_ops = &qca6174_ops, .hw_clk = qca6174_clk, .target_cpu_freq = 176000000, @@ -334,9 +367,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .rri_on_ddr = false, .hw_filter_reset_required = true, .fw_diag_ce_download = true, + .credit_size_workaround = false, .tx_stats_over_pktlog = false, .supports_peer_stats_info = true, .dynamic_sar_support = true, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = QCA99X0_HW_2_0_DEV_VERSION, @@ -361,6 +397,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, }, .sw_decrypt_mcast_mgmt = true, + .rx_desc_ops = &qca99x0_rx_desc_ops, .hw_ops = &qca99x0_ops, .decap_align_bytes = 1, .spectral_bin_discard = 4, @@ -376,8 +413,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .rri_on_ddr = false, .hw_filter_reset_required = true, .fw_diag_ce_download = false, + .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = QCA9984_HW_1_0_DEV_VERSION, @@ -405,6 +445,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .ext_board_size = QCA99X0_EXT_BOARD_DATA_SZ, }, .sw_decrypt_mcast_mgmt = true, + .rx_desc_ops = &qca99x0_rx_desc_ops, .hw_ops = &qca99x0_ops, .decap_align_bytes = 1, .spectral_bin_discard = 12, @@ -424,8 +465,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .rri_on_ddr = false, .hw_filter_reset_required = true, .fw_diag_ce_download = false, + .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = QCA9888_HW_2_0_DEV_VERSION, @@ -450,6 +494,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, }, .sw_decrypt_mcast_mgmt = true, + .rx_desc_ops = &qca99x0_rx_desc_ops, .hw_ops = &qca99x0_ops, .decap_align_bytes = 1, .spectral_bin_discard = 12, @@ -469,8 +514,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .rri_on_ddr = false, .hw_filter_reset_required = true, .fw_diag_ce_download = false, + .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = QCA9377_HW_1_0_DEV_VERSION, @@ -489,6 +537,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA9377_BOARD_DATA_SZ, .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, }, + .rx_desc_ops = &qca988x_rx_desc_ops, .hw_ops = &qca988x_ops, .decap_align_bytes = 4, .spectral_bin_discard = 0, @@ -504,8 +553,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .rri_on_ddr = false, .hw_filter_reset_required = true, .fw_diag_ce_download = false, + .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = QCA9377_HW_1_1_DEV_VERSION, @@ -524,6 +576,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA9377_BOARD_DATA_SZ, .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, }, + .rx_desc_ops = &qca988x_rx_desc_ops, .hw_ops = &qca6174_ops, .hw_clk = qca6174_clk, .target_cpu_freq = 176000000, @@ -541,8 +594,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .rri_on_ddr = false, .hw_filter_reset_required = true, .fw_diag_ce_download = true, + .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = QCA9377_HW_1_1_DEV_VERSION, @@ -561,6 +617,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_size = QCA9377_BOARD_DATA_SZ, .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, }, + .rx_desc_ops = &qca988x_rx_desc_ops, .hw_ops = &qca6174_ops, .hw_clk = qca6174_clk, .target_cpu_freq = 176000000, @@ -570,7 +627,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .ast_skid_limit = 0x10, .num_wds_entries = 0x20, .uart_pin_workaround = true, + .credit_size_workaround = true, .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = QCA4019_HW_1_0_DEV_VERSION, @@ -596,6 +656,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA4019_BOARD_EXT_DATA_SZ, }, .sw_decrypt_mcast_mgmt = true, + .rx_desc_ops = &qca99x0_rx_desc_ops, .hw_ops = &qca99x0_ops, .decap_align_bytes = 1, .spectral_bin_discard = 4, @@ -611,8 +672,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .rri_on_ddr = false, .hw_filter_reset_required = true, .fw_diag_ce_download = false, + .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, + .use_fw_tx_credits = true, }, { .id = WCN3990_HW_1_0_DEV_VERSION, @@ -627,6 +691,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dir = WCN3990_HW_1_0_FW_DIR, }, .sw_decrypt_mcast_mgmt = true, + .rx_desc_ops = &wcn3990_rx_desc_ops, .hw_ops = &wcn3990_ops, .decap_align_bytes = 1, .num_peers = TARGET_HL_TLV_NUM_PEERS, @@ -639,8 +704,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .rri_on_ddr = true, .hw_filter_reset_required = false, .fw_diag_ce_download = false, + .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = true, + .hw_restart_disconnect = true, + .use_fw_tx_credits = false, }, }; @@ -714,6 +782,7 @@ static void ath10k_send_suspend_complete(struct ath10k *ar) static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode) { + bool mtu_workaround = ar->hw_params.credit_size_workaround; int ret; u32 param = 0; @@ -731,7 +800,7 @@ static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode) param |= HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET; - if (mode == ATH10K_FIRMWARE_MODE_NORMAL) + if (mode == ATH10K_FIRMWARE_MODE_NORMAL && !mtu_workaround) param |= HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE; else param &= ~HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE; @@ -935,7 +1004,8 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) } if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT || - ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE) + ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE || + ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM) bmi_board_id_param = BMI_PARAM_GET_FLASH_BOARD_ID; else bmi_board_id_param = BMI_PARAM_GET_EEPROM_BOARD_ID; @@ -1182,6 +1252,7 @@ success: static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type) { const struct firmware *fw; + char boardname[100]; if (bd_ie_type == ATH10K_BD_IE_BOARD) { if (!ar->hw_params.fw.board) { @@ -1189,9 +1260,19 @@ static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type) return -EINVAL; } + scnprintf(boardname, sizeof(boardname), "board-%s-%s.bin", + ath10k_bus_str(ar->hif.bus), dev_name(ar->dev)); + ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, - ar->hw_params.fw.board); + boardname); + if (IS_ERR(ar->normal_mode_fw.board)) { + fw = ath10k_fetch_fw_file(ar, + ar->hw_params.fw.dir, + ar->hw_params.fw.board); + ar->normal_mode_fw.board = fw; + } + if (IS_ERR(ar->normal_mode_fw.board)) return PTR_ERR(ar->normal_mode_fw.board); @@ -1726,7 +1807,8 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) /* As of now pre-cal is valid for 10_4 variants */ if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT || - ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE) + ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE || + ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM) bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL; ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result); @@ -1853,6 +1935,39 @@ out_free: return ret; } +static int ath10k_download_cal_nvmem(struct ath10k *ar, const char *cell_name) +{ + struct nvmem_cell *cell; + void *buf; + size_t len; + int ret; + + cell = devm_nvmem_cell_get(ar->dev, cell_name); + if (IS_ERR(cell)) { + ret = PTR_ERR(cell); + return ret; + } + + buf = nvmem_cell_read(cell, &len); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + if (ar->hw_params.cal_data_len != len) { + kfree(buf); + ath10k_warn(ar, "invalid calibration data length in nvmem-cell '%s': %zu != %u\n", + cell_name, len, ar->hw_params.cal_data_len); + return -EMSGSIZE; + } + + ret = ath10k_download_board_data(ar, buf, len); + kfree(buf); + if (ret) + ath10k_warn(ar, "failed to download calibration data from nvmem-cell '%s': %d\n", + cell_name, ret); + + return ret; +} + int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, struct ath10k_fw_file *fw_file) { @@ -2087,6 +2202,18 @@ static int ath10k_core_pre_cal_download(struct ath10k *ar) { int ret; + ret = ath10k_download_cal_nvmem(ar, "pre-calibration"); + if (ret == 0) { + ar->cal_mode = ATH10K_PRE_CAL_MODE_NVMEM; + goto success; + } else if (ret == -EPROBE_DEFER) { + return ret; + } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "boot did not find a pre-calibration nvmem-cell, try file next: %d\n", + ret); + ret = ath10k_download_cal_file(ar, ar->pre_cal_file); if (ret == 0) { ar->cal_mode = ATH10K_PRE_CAL_MODE_FILE; @@ -2153,6 +2280,18 @@ static int ath10k_download_cal_data(struct ath10k *ar) "pre cal download procedure failed, try cal file: %d\n", ret); + ret = ath10k_download_cal_nvmem(ar, "calibration"); + if (ret == 0) { + ar->cal_mode = ATH10K_CAL_MODE_NVMEM; + goto done; + } else if (ret == -EPROBE_DEFER) { + return ret; + } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "boot did not find a calibration nvmem-cell, try file next: %d\n", + ret); + ret = ath10k_download_cal_file(ar, ar->cal_file); if (ret == 0) { ar->cal_mode = ATH10K_CAL_MODE_FILE; @@ -2349,6 +2488,7 @@ EXPORT_SYMBOL(ath10k_core_napi_sync_disable); static void ath10k_core_restart(struct work_struct *work) { struct ath10k *ar = container_of(work, struct ath10k, restart_work); + struct ath10k_vif *arvif; int ret; set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); @@ -2387,6 +2527,14 @@ static void ath10k_core_restart(struct work_struct *work) ar->state = ATH10K_STATE_RESTARTING; ath10k_halt(ar); ath10k_scan_finish(ar); + if (ar->hw_params.hw_restart_disconnect) { + list_for_each_entry(arvif, &ar->arvifs, list) { + if (arvif->is_up && + arvif->vdev_type == WMI_VDEV_TYPE_STA) + ieee80211_hw_restart_disconnect(arvif->vif); + } + } + ieee80211_restart_hw(ar->hw); break; case ATH10K_STATE_OFF: @@ -2470,7 +2618,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT; ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT; - if (rawmode) { + if (ath10k_frame_mode == ATH10K_HW_TXRX_RAW) { if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT, fw_file->fw_features)) { ath10k_err(ar, "rawmode = 1 requires support from firmware"); @@ -2948,7 +3096,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, * enabled always. * * We can still enable BTCOEX if firmware has the support - * eventhough btceox_support value is + * even though btceox_support value is * ATH10K_DT_BTCOEX_NOT_FOUND */ diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 5aeff2d9f6cf..f5de8ce8fb45 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -59,9 +59,6 @@ #define ATH10K_KEEPALIVE_MAX_IDLE 3895 #define ATH10K_KEEPALIVE_MAX_UNRESPONSIVE 3900 -/* NAPI poll budget */ -#define ATH10K_NAPI_BUDGET 64 - /* SMBIOS type containing Board Data File Name Extension */ #define ATH10K_SMBIOS_BDF_EXT_TYPE 0xF8 @@ -79,7 +76,7 @@ /* The magic used by QCA spec */ #define ATH10K_SMBIOS_BDF_EXT_MAGIC "BDF_" -/* Default Airtime weight multipler (Tuned for multiclient performance) */ +/* Default Airtime weight multiplier (Tuned for multiclient performance) */ #define ATH10K_AIRTIME_WEIGHT_MULTIPLIER 4 #define ATH10K_MAX_RETRY_COUNT 30 @@ -860,7 +857,7 @@ enum ath10k_dev_flags { /* Disable HW crypto engine */ ATH10K_FLAG_HW_CRYPTO_DISABLED, - /* Bluetooth coexistance enabled */ + /* Bluetooth coexistence enabled */ ATH10K_FLAG_BTCOEX, /* Per Station statistics service */ @@ -877,8 +874,10 @@ enum ath10k_cal_mode { ATH10K_CAL_MODE_FILE, ATH10K_CAL_MODE_OTP, ATH10K_CAL_MODE_DT, + ATH10K_CAL_MODE_NVMEM, ATH10K_PRE_CAL_MODE_FILE, ATH10K_PRE_CAL_MODE_DT, + ATH10K_PRE_CAL_MODE_NVMEM, ATH10K_CAL_MODE_EEPROM, }; @@ -898,10 +897,14 @@ static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode) return "otp"; case ATH10K_CAL_MODE_DT: return "dt"; + case ATH10K_CAL_MODE_NVMEM: + return "nvmem"; case ATH10K_PRE_CAL_MODE_FILE: return "pre-cal-file"; case ATH10K_PRE_CAL_MODE_DT: return "pre-cal-dt"; + case ATH10K_PRE_CAL_MODE_NVMEM: + return "pre-cal-nvmem"; case ATH10K_CAL_MODE_EEPROM: return "eeprom"; } @@ -1311,6 +1314,7 @@ static inline bool ath10k_peer_stats_enabled(struct ath10k *ar) return false; } +extern unsigned int ath10k_frame_mode; extern unsigned long ath10k_coredump_mask; void ath10k_core_napi_sync_disable(struct ath10k *ar); diff --git a/drivers/net/wireless/ath/ath10k/coredump.c b/drivers/net/wireless/ath/ath10k/coredump.c index 55e7e11d06d9..2d1634a890dd 100644 --- a/drivers/net/wireless/ath/ath10k/coredump.c +++ b/drivers/net/wireless/ath/ath10k/coredump.c @@ -531,7 +531,7 @@ static const struct ath10k_mem_section qca6174_hw30_sdio_register_sections[] = { {0x40000, 0x400A4}, - /* SI register is skiped here. + /* SI register is skipped here. * Because it will cause bus hang * * {0x50000, 0x50018}, @@ -1522,7 +1522,7 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar) mutex_lock(&ar->dump_mutex); dump_data = (struct ath10k_dump_file_data *)(buf); - strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP", + strscpy(dump_data->df_magic, "ATH10K-FW-DUMP", sizeof(dump_data->df_magic)); dump_data->len = cpu_to_le32(len); @@ -1543,11 +1543,11 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar) dump_data->vht_cap_info = cpu_to_le32(ar->vht_cap_info); dump_data->num_rf_chains = cpu_to_le32(ar->num_rf_chains); - strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version, + strscpy(dump_data->fw_ver, ar->hw->wiphy->fw_version, sizeof(dump_data->fw_ver)); dump_data->kernel_ver_code = 0; - strlcpy(dump_data->kernel_ver, init_utsname()->release, + strscpy(dump_data->kernel_ver, init_utsname()->release, sizeof(dump_data->kernel_ver)); dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec); diff --git a/drivers/net/wireless/ath/ath10k/coredump.h b/drivers/net/wireless/ath/ath10k/coredump.h index 240d70515088..437b9759f05d 100644 --- a/drivers/net/wireless/ath/ath10k/coredump.h +++ b/drivers/net/wireless/ath/ath10k/coredump.h @@ -125,7 +125,7 @@ enum ath10k_mem_region_type { * To minimize the size of the array, the list must obey the format: * '{start0,stop0},{start1,stop1},{start2,stop2}....' The values below must * also obey to 'start0 < stop0 < start1 < stop1 < start2 < ...', otherwise - * we may encouter error in the dump processing. + * we may encounter error in the dump processing. */ struct ath10k_mem_section { u32 start; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 39378e3f9b2b..c861e66ef6bc 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -1081,7 +1081,7 @@ exit: * struct available.. */ -/* This generally cooresponds to the debugfs fw_stats file */ +/* This generally corresponds to the debugfs fw_stats file */ static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = { "tx_pkts_nic", "tx_bytes_nic", diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index 367539f2c370..87a3365330ff 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c @@ -498,7 +498,7 @@ static char *get_num_ampdu_subfrm_str(enum ath10k_ampdu_subfrm_num i) { switch (i) { case ATH10K_AMPDU_SUBFRM_NUM_10: - return "upto 10"; + return "up to 10"; case ATH10K_AMPDU_SUBFRM_NUM_20: return "11-20"; case ATH10K_AMPDU_SUBFRM_NUM_30: diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index fab398046a3f..6d1784f74bea 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -947,13 +947,18 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) return -ECOMM; } - htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count); + if (ar->hw_params.use_fw_tx_credits) + htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count); + else + htc->total_transmit_credits = 1; + htc->target_credit_size = __le16_to_cpu(msg->ready.credit_size); ath10k_dbg(ar, ATH10K_DBG_HTC, - "Target ready! transmit resources: %d size:%d\n", + "Target ready! transmit resources: %d size:%d actual credits:%d\n", htc->total_transmit_credits, - htc->target_credit_size); + htc->target_credit_size, + msg->ready.credit_count); if ((htc->total_transmit_credits == 0) || (htc->target_credit_size == 0)) { diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index 127b4e4980ef..907e1e13871a 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c @@ -131,6 +131,159 @@ static const enum htt_t2h_msg_type htt_10_4_t2h_msg_types[] = { HTT_T2H_MSG_TYPE_PEER_STATS, }; +const struct ath10k_htt_rx_desc_ops qca988x_rx_desc_ops = { + .rx_desc_size = sizeof(struct htt_rx_desc_v1), + .rx_desc_msdu_payload_offset = offsetof(struct htt_rx_desc_v1, msdu_payload) +}; + +static int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v1 *rx_desc = container_of(rxd, + struct htt_rx_desc_v1, + base); + + return MS(__le32_to_cpu(rx_desc->msdu_end.qca99x0.info1), + RX_MSDU_END_INFO1_L3_HDR_PAD); +} + +static bool ath10k_qca99x0_rx_desc_msdu_limit_error(struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v1 *rx_desc = container_of(rxd, + struct htt_rx_desc_v1, + base); + + return !!(rx_desc->msdu_end.common.info0 & + __cpu_to_le32(RX_MSDU_END_INFO0_MSDU_LIMIT_ERR)); +} + +const struct ath10k_htt_rx_desc_ops qca99x0_rx_desc_ops = { + .rx_desc_size = sizeof(struct htt_rx_desc_v1), + .rx_desc_msdu_payload_offset = offsetof(struct htt_rx_desc_v1, msdu_payload), + + .rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes, + .rx_desc_get_msdu_limit_error = ath10k_qca99x0_rx_desc_msdu_limit_error, +}; + +static void ath10k_rx_desc_wcn3990_get_offsets(struct htt_rx_ring_rx_desc_offsets *off) +{ +#define desc_offset(x) (offsetof(struct htt_rx_desc_v2, x) / 4) + off->mac80211_hdr_offset = __cpu_to_le16(desc_offset(rx_hdr_status)); + off->msdu_payload_offset = __cpu_to_le16(desc_offset(msdu_payload)); + off->ppdu_start_offset = __cpu_to_le16(desc_offset(ppdu_start)); + off->ppdu_end_offset = __cpu_to_le16(desc_offset(ppdu_end)); + off->mpdu_start_offset = __cpu_to_le16(desc_offset(mpdu_start)); + off->mpdu_end_offset = __cpu_to_le16(desc_offset(mpdu_end)); + off->msdu_start_offset = __cpu_to_le16(desc_offset(msdu_start)); + off->msdu_end_offset = __cpu_to_le16(desc_offset(msdu_end)); + off->rx_attention_offset = __cpu_to_le16(desc_offset(attention)); + off->frag_info_offset = __cpu_to_le16(desc_offset(frag_info)); +#undef desc_offset +} + +static struct htt_rx_desc * +ath10k_rx_desc_wcn3990_from_raw_buffer(void *buff) +{ + return &((struct htt_rx_desc_v2 *)buff)->base; +} + +static struct rx_attention * +ath10k_rx_desc_wcn3990_get_attention(struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base); + + return &rx_desc->attention; +} + +static struct rx_frag_info_common * +ath10k_rx_desc_wcn3990_get_frag_info(struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base); + + return &rx_desc->frag_info.common; +} + +static struct rx_mpdu_start * +ath10k_rx_desc_wcn3990_get_mpdu_start(struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base); + + return &rx_desc->mpdu_start; +} + +static struct rx_mpdu_end * +ath10k_rx_desc_wcn3990_get_mpdu_end(struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base); + + return &rx_desc->mpdu_end; +} + +static struct rx_msdu_start_common * +ath10k_rx_desc_wcn3990_get_msdu_start(struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base); + + return &rx_desc->msdu_start.common; +} + +static struct rx_msdu_end_common * +ath10k_rx_desc_wcn3990_get_msdu_end(struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base); + + return &rx_desc->msdu_end.common; +} + +static struct rx_ppdu_start * +ath10k_rx_desc_wcn3990_get_ppdu_start(struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base); + + return &rx_desc->ppdu_start; +} + +static struct rx_ppdu_end_common * +ath10k_rx_desc_wcn3990_get_ppdu_end(struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base); + + return &rx_desc->ppdu_end.common; +} + +static u8 * +ath10k_rx_desc_wcn3990_get_rx_hdr_status(struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base); + + return rx_desc->rx_hdr_status; +} + +static u8 * +ath10k_rx_desc_wcn3990_get_msdu_payload(struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v2 *rx_desc = container_of(rxd, struct htt_rx_desc_v2, base); + + return rx_desc->msdu_payload; +} + +const struct ath10k_htt_rx_desc_ops wcn3990_rx_desc_ops = { + .rx_desc_size = sizeof(struct htt_rx_desc_v2), + .rx_desc_msdu_payload_offset = offsetof(struct htt_rx_desc_v2, msdu_payload), + + .rx_desc_from_raw_buffer = ath10k_rx_desc_wcn3990_from_raw_buffer, + .rx_desc_get_offsets = ath10k_rx_desc_wcn3990_get_offsets, + .rx_desc_get_attention = ath10k_rx_desc_wcn3990_get_attention, + .rx_desc_get_frag_info = ath10k_rx_desc_wcn3990_get_frag_info, + .rx_desc_get_mpdu_start = ath10k_rx_desc_wcn3990_get_mpdu_start, + .rx_desc_get_mpdu_end = ath10k_rx_desc_wcn3990_get_mpdu_end, + .rx_desc_get_msdu_start = ath10k_rx_desc_wcn3990_get_msdu_start, + .rx_desc_get_msdu_end = ath10k_rx_desc_wcn3990_get_msdu_end, + .rx_desc_get_ppdu_start = ath10k_rx_desc_wcn3990_get_ppdu_start, + .rx_desc_get_ppdu_end = ath10k_rx_desc_wcn3990_get_ppdu_end, + .rx_desc_get_rx_hdr_status = ath10k_rx_desc_wcn3990_get_rx_hdr_status, + .rx_desc_get_msdu_payload = ath10k_rx_desc_wcn3990_get_msdu_payload, +}; + int ath10k_htt_connect(struct ath10k_htt *htt) { struct ath10k_htc_svc_conn_req conn_req; diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index a6de08d3bf4a..f06cf39204e2 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -240,14 +240,7 @@ enum htt_rx_ring_flags { #define HTT_RX_RING_FILL_LEVEL (((HTT_RX_RING_SIZE) / 2) - 1) #define HTT_RX_RING_FILL_LEVEL_DUAL_MAC (HTT_RX_RING_SIZE - 1) -struct htt_rx_ring_setup_ring32 { - __le32 fw_idx_shadow_reg_paddr; - __le32 rx_ring_base_paddr; - __le16 rx_ring_len; /* in 4-byte words */ - __le16 rx_ring_bufsize; /* rx skb size - in bytes */ - __le16 flags; /* %HTT_RX_RING_FLAGS_ */ - __le16 fw_idx_init_val; - +struct htt_rx_ring_rx_desc_offsets { /* the following offsets are in 4-byte units */ __le16 mac80211_hdr_offset; __le16 msdu_payload_offset; @@ -261,6 +254,17 @@ struct htt_rx_ring_setup_ring32 { __le16 frag_info_offset; } __packed; +struct htt_rx_ring_setup_ring32 { + __le32 fw_idx_shadow_reg_paddr; + __le32 rx_ring_base_paddr; + __le16 rx_ring_len; /* in 4-byte words */ + __le16 rx_ring_bufsize; /* rx skb size - in bytes */ + __le16 flags; /* %HTT_RX_RING_FLAGS_ */ + __le16 fw_idx_init_val; + + struct htt_rx_ring_rx_desc_offsets offsets; +} __packed; + struct htt_rx_ring_setup_ring64 { __le64 fw_idx_shadow_reg_paddr; __le64 rx_ring_base_paddr; @@ -269,17 +273,7 @@ struct htt_rx_ring_setup_ring64 { __le16 flags; /* %HTT_RX_RING_FLAGS_ */ __le16 fw_idx_init_val; - /* the following offsets are in 4-byte units */ - __le16 mac80211_hdr_offset; - __le16 msdu_payload_offset; - __le16 ppdu_start_offset; - __le16 ppdu_end_offset; - __le16 mpdu_start_offset; - __le16 mpdu_end_offset; - __le16 msdu_start_offset; - __le16 msdu_end_offset; - __le16 rx_attention_offset; - __le16 frag_info_offset; + struct htt_rx_ring_rx_desc_offsets offsets; } __packed; struct htt_rx_ring_setup_hdr { @@ -1401,115 +1395,6 @@ enum htt_dbg_stats_status { }; /* - * target -> host statistics upload - * - * The following field definitions describe the format of the HTT target - * to host stats upload confirmation message. - * The message contains a cookie echoed from the HTT host->target stats - * upload request, which identifies which request the confirmation is - * for, and a series of tag-length-value stats information elements. - * The tag-length header for each stats info element also includes a - * status field, to indicate whether the request for the stat type in - * question was fully met, partially met, unable to be met, or invalid - * (if the stat type in question is disabled in the target). - * A special value of all 1's in this status field is used to indicate - * the end of the series of stats info elements. - * - * - * |31 16|15 8|7 5|4 0| - * |------------------------------------------------------------| - * | reserved | msg type | - * |------------------------------------------------------------| - * | cookie LSBs | - * |------------------------------------------------------------| - * | cookie MSBs | - * |------------------------------------------------------------| - * | stats entry length | reserved | S |stat type| - * |------------------------------------------------------------| - * | | - * | type-specific stats info | - * | | - * |------------------------------------------------------------| - * | stats entry length | reserved | S |stat type| - * |------------------------------------------------------------| - * | | - * | type-specific stats info | - * | | - * |------------------------------------------------------------| - * | n/a | reserved | 111 | n/a | - * |------------------------------------------------------------| - * Header fields: - * - MSG_TYPE - * Bits 7:0 - * Purpose: identifies this is a statistics upload confirmation message - * Value: 0x9 - * - COOKIE_LSBS - * Bits 31:0 - * Purpose: Provide a mechanism to match a target->host stats confirmation - * message with its preceding host->target stats request message. - * Value: LSBs of the opaque cookie specified by the host-side requestor - * - COOKIE_MSBS - * Bits 31:0 - * Purpose: Provide a mechanism to match a target->host stats confirmation - * message with its preceding host->target stats request message. - * Value: MSBs of the opaque cookie specified by the host-side requestor - * - * Stats Information Element tag-length header fields: - * - STAT_TYPE - * Bits 4:0 - * Purpose: identifies the type of statistics info held in the - * following information element - * Value: htt_dbg_stats_type - * - STATUS - * Bits 7:5 - * Purpose: indicate whether the requested stats are present - * Value: htt_dbg_stats_status, including a special value (0x7) to mark - * the completion of the stats entry series - * - LENGTH - * Bits 31:16 - * Purpose: indicate the stats information size - * Value: This field specifies the number of bytes of stats information - * that follows the element tag-length header. - * It is expected but not required that this length is a multiple of - * 4 bytes. Even if the length is not an integer multiple of 4, the - * subsequent stats entry header will begin on a 4-byte aligned - * boundary. - */ - -#define HTT_STATS_CONF_ITEM_INFO_STAT_TYPE_MASK 0x1F -#define HTT_STATS_CONF_ITEM_INFO_STAT_TYPE_LSB 0 -#define HTT_STATS_CONF_ITEM_INFO_STATUS_MASK 0xE0 -#define HTT_STATS_CONF_ITEM_INFO_STATUS_LSB 5 - -struct htt_stats_conf_item { - union { - u8 info; - struct { - u8 stat_type:5; /* %HTT_DBG_STATS_ */ - u8 status:3; /* %HTT_DBG_STATS_STATUS_ */ - } __packed; - } __packed; - u8 pad; - __le16 length; - u8 payload[]; /* roundup(length, 4) long */ -} __packed; - -struct htt_stats_conf { - u8 pad[3]; - __le32 cookie_lsb; - __le32 cookie_msb; - - /* each item has variable length! */ - struct htt_stats_conf_item items[]; -} __packed; - -static inline struct htt_stats_conf_item *htt_stats_conf_next_item( - const struct htt_stats_conf_item *item) -{ - return (void *)item + sizeof(*item) + roundup(item->length, 4); -} - -/* * host -> target FRAG DESCRIPTOR/MSDU_EXT DESC bank * * The following field definitions describe the format of the HTT host @@ -1828,7 +1713,6 @@ struct htt_resp { struct htt_rc_update rc_update; struct htt_rx_test rx_test; struct htt_pktlog_msg pktlog_msg; - struct htt_stats_conf stats_conf; struct htt_rx_pn_ind rx_pn_ind; struct htt_rx_offload_ind rx_offload_ind; struct htt_rx_in_ord_ind rx_in_ord_ind; @@ -2185,12 +2069,22 @@ static inline bool ath10k_htt_rx_proc_rx_frag_ind(struct ath10k_htt *htt, return htt->rx_ops->htt_rx_proc_rx_frag_ind(htt, rx, skb); } +/* the driver strongly assumes that the rx header status be 64 bytes long, + * so all possible rx_desc structures must respect this assumption. + */ #define RX_HTT_HDR_STATUS_LEN 64 -/* This structure layout is programmed via rx ring setup +/* The rx descriptor structure layout is programmed via rx ring setup * so that FW knows how to transfer the rx descriptor to the host. - * Buffers like this are placed on the rx ring. + * Unfortunately, though, QCA6174's firmware doesn't currently behave correctly + * when modifying the structure layout of the rx descriptor beyond what it expects + * (even if it correctly programmed during the rx ring setup). + * Therefore we must keep two different memory layouts, abstract the rx descriptor + * representation and use ath10k_rx_desc_ops + * for correctly accessing rx descriptor data. */ + +/* base struct used for abstracting the rx descritor representation */ struct htt_rx_desc { union { /* This field is filled on the host using the msdu buffer @@ -2199,6 +2093,13 @@ struct htt_rx_desc { struct fw_rx_desc_base fw_desc; u32 pad; } __packed; +} __packed; + +/* rx descriptor for wcn3990 and possibly extensible for newer cards + * Buffers like this are placed on the rx ring. + */ +struct htt_rx_desc_v2 { + struct htt_rx_desc base; struct { struct rx_attention attention; struct rx_frag_info frag_info; @@ -2213,6 +2114,240 @@ struct htt_rx_desc { u8 msdu_payload[]; }; +/* QCA6174, QCA988x, QCA99x0 dedicated rx descriptor to make sure their firmware + * works correctly. We keep a single rx descriptor for all these three + * families of cards because from tests it seems to be the most stable solution, + * e.g. having a rx descriptor only for QCA6174 seldom caused firmware crashes + * during some tests. + * Buffers like this are placed on the rx ring. + */ +struct htt_rx_desc_v1 { + struct htt_rx_desc base; + struct { + struct rx_attention attention; + struct rx_frag_info_v1 frag_info; + struct rx_mpdu_start mpdu_start; + struct rx_msdu_start_v1 msdu_start; + struct rx_msdu_end_v1 msdu_end; + struct rx_mpdu_end mpdu_end; + struct rx_ppdu_start ppdu_start; + struct rx_ppdu_end_v1 ppdu_end; + } __packed; + u8 rx_hdr_status[RX_HTT_HDR_STATUS_LEN]; + u8 msdu_payload[]; +}; + +/* rx_desc abstraction */ +struct ath10k_htt_rx_desc_ops { + /* These fields are mandatory, they must be specified in any instance */ + + /* sizeof() of the rx_desc structure used by this hw */ + size_t rx_desc_size; + + /* offset of msdu_payload inside the rx_desc structure used by this hw */ + size_t rx_desc_msdu_payload_offset; + + /* These fields are options. + * When a field is not provided the default implementation gets used + * (see the ath10k_rx_desc_* operations below for more info about the defaults) + */ + bool (*rx_desc_get_msdu_limit_error)(struct htt_rx_desc *rxd); + int (*rx_desc_get_l3_pad_bytes)(struct htt_rx_desc *rxd); + + /* Safely cast from a void* buffer containing an rx descriptor + * to the proper rx_desc structure + */ + struct htt_rx_desc *(*rx_desc_from_raw_buffer)(void *buff); + + void (*rx_desc_get_offsets)(struct htt_rx_ring_rx_desc_offsets *offs); + struct rx_attention *(*rx_desc_get_attention)(struct htt_rx_desc *rxd); + struct rx_frag_info_common *(*rx_desc_get_frag_info)(struct htt_rx_desc *rxd); + struct rx_mpdu_start *(*rx_desc_get_mpdu_start)(struct htt_rx_desc *rxd); + struct rx_mpdu_end *(*rx_desc_get_mpdu_end)(struct htt_rx_desc *rxd); + struct rx_msdu_start_common *(*rx_desc_get_msdu_start)(struct htt_rx_desc *rxd); + struct rx_msdu_end_common *(*rx_desc_get_msdu_end)(struct htt_rx_desc *rxd); + struct rx_ppdu_start *(*rx_desc_get_ppdu_start)(struct htt_rx_desc *rxd); + struct rx_ppdu_end_common *(*rx_desc_get_ppdu_end)(struct htt_rx_desc *rxd); + u8 *(*rx_desc_get_rx_hdr_status)(struct htt_rx_desc *rxd); + u8 *(*rx_desc_get_msdu_payload)(struct htt_rx_desc *rxd); +}; + +extern const struct ath10k_htt_rx_desc_ops qca988x_rx_desc_ops; +extern const struct ath10k_htt_rx_desc_ops qca99x0_rx_desc_ops; +extern const struct ath10k_htt_rx_desc_ops wcn3990_rx_desc_ops; + +static inline int +ath10k_htt_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd) +{ + if (hw->rx_desc_ops->rx_desc_get_l3_pad_bytes) + return hw->rx_desc_ops->rx_desc_get_l3_pad_bytes(rxd); + return 0; +} + +static inline bool +ath10k_htt_rx_desc_msdu_limit_error(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd) +{ + if (hw->rx_desc_ops->rx_desc_get_msdu_limit_error) + return hw->rx_desc_ops->rx_desc_get_msdu_limit_error(rxd); + return false; +} + +/* The default implementation of all these getters is using the old rx_desc, + * so that it is easier to define the ath10k_htt_rx_desc_ops instances. + * But probably, if new wireless cards must be supported, it would be better + * to switch the default implementation to the new rx_desc, since this would + * make the extension easier . + */ +static inline struct htt_rx_desc * +ath10k_htt_rx_desc_from_raw_buffer(struct ath10k_hw_params *hw, void *buff) +{ + if (hw->rx_desc_ops->rx_desc_from_raw_buffer) + return hw->rx_desc_ops->rx_desc_from_raw_buffer(buff); + return &((struct htt_rx_desc_v1 *)buff)->base; +} + +static inline void +ath10k_htt_rx_desc_get_offsets(struct ath10k_hw_params *hw, + struct htt_rx_ring_rx_desc_offsets *off) +{ + if (hw->rx_desc_ops->rx_desc_get_offsets) { + hw->rx_desc_ops->rx_desc_get_offsets(off); + } else { +#define desc_offset(x) (offsetof(struct htt_rx_desc_v1, x) / 4) + off->mac80211_hdr_offset = __cpu_to_le16(desc_offset(rx_hdr_status)); + off->msdu_payload_offset = __cpu_to_le16(desc_offset(msdu_payload)); + off->ppdu_start_offset = __cpu_to_le16(desc_offset(ppdu_start)); + off->ppdu_end_offset = __cpu_to_le16(desc_offset(ppdu_end)); + off->mpdu_start_offset = __cpu_to_le16(desc_offset(mpdu_start)); + off->mpdu_end_offset = __cpu_to_le16(desc_offset(mpdu_end)); + off->msdu_start_offset = __cpu_to_le16(desc_offset(msdu_start)); + off->msdu_end_offset = __cpu_to_le16(desc_offset(msdu_end)); + off->rx_attention_offset = __cpu_to_le16(desc_offset(attention)); + off->frag_info_offset = __cpu_to_le16(desc_offset(frag_info)); +#undef desc_offset + } +} + +static inline struct rx_attention * +ath10k_htt_rx_desc_get_attention(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v1 *rx_desc; + + if (hw->rx_desc_ops->rx_desc_get_attention) + return hw->rx_desc_ops->rx_desc_get_attention(rxd); + + rx_desc = container_of(rxd, struct htt_rx_desc_v1, base); + return &rx_desc->attention; +} + +static inline struct rx_frag_info_common * +ath10k_htt_rx_desc_get_frag_info(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v1 *rx_desc; + + if (hw->rx_desc_ops->rx_desc_get_frag_info) + return hw->rx_desc_ops->rx_desc_get_frag_info(rxd); + + rx_desc = container_of(rxd, struct htt_rx_desc_v1, base); + return &rx_desc->frag_info.common; +} + +static inline struct rx_mpdu_start * +ath10k_htt_rx_desc_get_mpdu_start(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v1 *rx_desc; + + if (hw->rx_desc_ops->rx_desc_get_mpdu_start) + return hw->rx_desc_ops->rx_desc_get_mpdu_start(rxd); + + rx_desc = container_of(rxd, struct htt_rx_desc_v1, base); + return &rx_desc->mpdu_start; +} + +static inline struct rx_mpdu_end * +ath10k_htt_rx_desc_get_mpdu_end(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v1 *rx_desc; + + if (hw->rx_desc_ops->rx_desc_get_mpdu_end) + return hw->rx_desc_ops->rx_desc_get_mpdu_end(rxd); + + rx_desc = container_of(rxd, struct htt_rx_desc_v1, base); + return &rx_desc->mpdu_end; +} + +static inline struct rx_msdu_start_common * +ath10k_htt_rx_desc_get_msdu_start(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v1 *rx_desc; + + if (hw->rx_desc_ops->rx_desc_get_msdu_start) + return hw->rx_desc_ops->rx_desc_get_msdu_start(rxd); + + rx_desc = container_of(rxd, struct htt_rx_desc_v1, base); + return &rx_desc->msdu_start.common; +} + +static inline struct rx_msdu_end_common * +ath10k_htt_rx_desc_get_msdu_end(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v1 *rx_desc; + + if (hw->rx_desc_ops->rx_desc_get_msdu_end) + return hw->rx_desc_ops->rx_desc_get_msdu_end(rxd); + + rx_desc = container_of(rxd, struct htt_rx_desc_v1, base); + return &rx_desc->msdu_end.common; +} + +static inline struct rx_ppdu_start * +ath10k_htt_rx_desc_get_ppdu_start(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v1 *rx_desc; + + if (hw->rx_desc_ops->rx_desc_get_ppdu_start) + return hw->rx_desc_ops->rx_desc_get_ppdu_start(rxd); + + rx_desc = container_of(rxd, struct htt_rx_desc_v1, base); + return &rx_desc->ppdu_start; +} + +static inline struct rx_ppdu_end_common * +ath10k_htt_rx_desc_get_ppdu_end(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v1 *rx_desc; + + if (hw->rx_desc_ops->rx_desc_get_ppdu_end) + return hw->rx_desc_ops->rx_desc_get_ppdu_end(rxd); + + rx_desc = container_of(rxd, struct htt_rx_desc_v1, base); + return &rx_desc->ppdu_end.common; +} + +static inline u8 * +ath10k_htt_rx_desc_get_rx_hdr_status(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v1 *rx_desc; + + if (hw->rx_desc_ops->rx_desc_get_rx_hdr_status) + return hw->rx_desc_ops->rx_desc_get_rx_hdr_status(rxd); + + rx_desc = container_of(rxd, struct htt_rx_desc_v1, base); + return rx_desc->rx_hdr_status; +} + +static inline u8 * +ath10k_htt_rx_desc_get_msdu_payload(struct ath10k_hw_params *hw, struct htt_rx_desc *rxd) +{ + struct htt_rx_desc_v1 *rx_desc; + + if (hw->rx_desc_ops->rx_desc_get_msdu_payload) + return hw->rx_desc_ops->rx_desc_get_msdu_payload(rxd); + + rx_desc = container_of(rxd, struct htt_rx_desc_v1, base); + return rx_desc->msdu_payload; +} + #define HTT_RX_DESC_HL_INFO_SEQ_NUM_MASK 0x00000fff #define HTT_RX_DESC_HL_INFO_SEQ_NUM_LSB 0 #define HTT_RX_DESC_HL_INFO_ENCRYPTED_MASK 0x00001000 @@ -2246,7 +2381,14 @@ struct htt_rx_chan_info { * rounded up to a cache line size. */ #define HTT_RX_BUF_SIZE 2048 -#define HTT_RX_MSDU_SIZE (HTT_RX_BUF_SIZE - (int)sizeof(struct htt_rx_desc)) + +/* The HTT_RX_MSDU_SIZE can't be statically computed anymore, + * because it depends on the underlying device rx_desc representation + */ +static inline int ath10k_htt_rx_msdu_size(struct ath10k_hw_params *hw) +{ + return HTT_RX_BUF_SIZE - (int)hw->rx_desc_ops->rx_desc_size; +} /* Refill a bunch of RX buffers for each refill round so that FW/HW can handle * aggregated traffic more nicely. diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index adbaeb67eedf..e76aab973320 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -21,7 +21,10 @@ #define HTT_RX_RING_REFILL_RESCHED_MS 5 -static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb); +/* shortcut to interpret a raw memory buffer as a rx descriptor */ +#define HTT_RX_BUF_TO_RX_DESC(hw, buf) ath10k_htt_rx_desc_from_raw_buffer(hw, buf) + +static int ath10k_htt_rx_get_csum_state(struct ath10k_hw_params *hw, struct sk_buff *skb); static struct sk_buff * ath10k_htt_rx_find_skb_paddr(struct ath10k *ar, u64 paddr) @@ -128,6 +131,7 @@ static void *ath10k_htt_get_vaddr_ring_64(struct ath10k_htt *htt) static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num) { + struct ath10k_hw_params *hw = &htt->ar->hw_params; struct htt_rx_desc *rx_desc; struct ath10k_skb_rxcb *rxcb; struct sk_buff *skb; @@ -163,8 +167,8 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num) skb->data); /* Clear rx_desc attention word before posting to Rx ring */ - rx_desc = (struct htt_rx_desc *)skb->data; - rx_desc->attention.flags = __cpu_to_le32(0); + rx_desc = HTT_RX_BUF_TO_RX_DESC(hw, skb->data); + ath10k_htt_rx_desc_get_attention(hw, rx_desc)->flags = __cpu_to_le32(0); paddr = dma_map_single(htt->ar->dev, skb->data, skb->len + skb_tailroom(skb), @@ -297,12 +301,16 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt) ath10k_htt_get_vaddr_ring(htt), htt->rx_ring.base_paddr); + ath10k_htt_config_paddrs_ring(htt, NULL); + dma_free_coherent(htt->ar->dev, sizeof(*htt->rx_ring.alloc_idx.vaddr), htt->rx_ring.alloc_idx.vaddr, htt->rx_ring.alloc_idx.paddr); + htt->rx_ring.alloc_idx.vaddr = NULL; kfree(htt->rx_ring.netbufs_ring); + htt->rx_ring.netbufs_ring = NULL; } static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt) @@ -343,9 +351,14 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, struct sk_buff_head *amsdu) { struct ath10k *ar = htt->ar; + struct ath10k_hw_params *hw = &ar->hw_params; int msdu_len, msdu_chaining = 0; struct sk_buff *msdu; struct htt_rx_desc *rx_desc; + struct rx_attention *rx_desc_attention; + struct rx_frag_info_common *rx_desc_frag_info_common; + struct rx_msdu_start_common *rx_desc_msdu_start_common; + struct rx_msdu_end_common *rx_desc_msdu_end_common; lockdep_assert_held(&htt->rx_ring.lock); @@ -360,13 +373,18 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, __skb_queue_tail(amsdu, msdu); - rx_desc = (struct htt_rx_desc *)msdu->data; + rx_desc = HTT_RX_BUF_TO_RX_DESC(hw, msdu->data); + rx_desc_attention = ath10k_htt_rx_desc_get_attention(hw, rx_desc); + rx_desc_msdu_start_common = ath10k_htt_rx_desc_get_msdu_start(hw, + rx_desc); + rx_desc_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rx_desc); + rx_desc_frag_info_common = ath10k_htt_rx_desc_get_frag_info(hw, rx_desc); /* FIXME: we must report msdu payload since this is what caller * expects now */ - skb_put(msdu, offsetof(struct htt_rx_desc, msdu_payload)); - skb_pull(msdu, offsetof(struct htt_rx_desc, msdu_payload)); + skb_put(msdu, hw->rx_desc_ops->rx_desc_msdu_payload_offset); + skb_pull(msdu, hw->rx_desc_ops->rx_desc_msdu_payload_offset); /* * Sanity check - confirm the HW is finished filling in the @@ -376,24 +394,24 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, * To prevent the case that we handle a stale Rx descriptor, * just assert for now until we have a way to recover. */ - if (!(__le32_to_cpu(rx_desc->attention.flags) + if (!(__le32_to_cpu(rx_desc_attention->flags) & RX_ATTENTION_FLAGS_MSDU_DONE)) { __skb_queue_purge(amsdu); return -EIO; } - msdu_len_invalid = !!(__le32_to_cpu(rx_desc->attention.flags) + msdu_len_invalid = !!(__le32_to_cpu(rx_desc_attention->flags) & (RX_ATTENTION_FLAGS_MPDU_LENGTH_ERR | RX_ATTENTION_FLAGS_MSDU_LENGTH_ERR)); - msdu_len = MS(__le32_to_cpu(rx_desc->msdu_start.common.info0), + msdu_len = MS(__le32_to_cpu(rx_desc_msdu_start_common->info0), RX_MSDU_START_INFO0_MSDU_LENGTH); - msdu_chained = rx_desc->frag_info.ring2_more_count; + msdu_chained = rx_desc_frag_info_common->ring2_more_count; if (msdu_len_invalid) msdu_len = 0; skb_trim(msdu, 0); - skb_put(msdu, min(msdu_len, HTT_RX_MSDU_SIZE)); + skb_put(msdu, min(msdu_len, ath10k_htt_rx_msdu_size(hw))); msdu_len -= msdu->len; /* Note: Chained buffers do not contain rx descriptor */ @@ -411,11 +429,12 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, msdu_chaining = 1; } - last_msdu = __le32_to_cpu(rx_desc->msdu_end.common.info0) & + last_msdu = __le32_to_cpu(rx_desc_msdu_end_common->info0) & RX_MSDU_END_INFO0_LAST_MSDU; - trace_ath10k_htt_rx_desc(ar, &rx_desc->attention, - sizeof(*rx_desc) - sizeof(u32)); + /* FIXME: why are we skipping the first part of the rx_desc? */ + trace_ath10k_htt_rx_desc(ar, (void *)rx_desc + sizeof(u32), + hw->rx_desc_ops->rx_desc_size - sizeof(u32)); if (last_msdu) break; @@ -480,6 +499,7 @@ static int ath10k_htt_rx_handle_amsdu_mon_32(struct ath10k_htt *htt, struct htt_rx_in_ord_msdu_desc **msdu_desc) { struct ath10k *ar = htt->ar; + struct ath10k_hw_params *hw = &ar->hw_params; u32 paddr; struct sk_buff *frag_buf; struct sk_buff *prev_frag_buf; @@ -488,12 +508,12 @@ static int ath10k_htt_rx_handle_amsdu_mon_32(struct ath10k_htt *htt, struct htt_rx_desc *rxd; int amsdu_len = __le16_to_cpu(ind_desc->msdu_len); - rxd = (void *)msdu->data; - trace_ath10k_htt_rx_desc(ar, rxd, sizeof(*rxd)); + rxd = HTT_RX_BUF_TO_RX_DESC(hw, msdu->data); + trace_ath10k_htt_rx_desc(ar, rxd, hw->rx_desc_ops->rx_desc_size); - skb_put(msdu, sizeof(struct htt_rx_desc)); - skb_pull(msdu, sizeof(struct htt_rx_desc)); - skb_put(msdu, min(amsdu_len, HTT_RX_MSDU_SIZE)); + skb_put(msdu, hw->rx_desc_ops->rx_desc_size); + skb_pull(msdu, hw->rx_desc_ops->rx_desc_size); + skb_put(msdu, min(amsdu_len, ath10k_htt_rx_msdu_size(hw))); amsdu_len -= msdu->len; last_frag = ind_desc->reserved; @@ -556,6 +576,7 @@ ath10k_htt_rx_handle_amsdu_mon_64(struct ath10k_htt *htt, struct htt_rx_in_ord_msdu_desc_ext **msdu_desc) { struct ath10k *ar = htt->ar; + struct ath10k_hw_params *hw = &ar->hw_params; u64 paddr; struct sk_buff *frag_buf; struct sk_buff *prev_frag_buf; @@ -564,12 +585,12 @@ ath10k_htt_rx_handle_amsdu_mon_64(struct ath10k_htt *htt, struct htt_rx_desc *rxd; int amsdu_len = __le16_to_cpu(ind_desc->msdu_len); - rxd = (void *)msdu->data; - trace_ath10k_htt_rx_desc(ar, rxd, sizeof(*rxd)); + rxd = HTT_RX_BUF_TO_RX_DESC(hw, msdu->data); + trace_ath10k_htt_rx_desc(ar, rxd, hw->rx_desc_ops->rx_desc_size); - skb_put(msdu, sizeof(struct htt_rx_desc)); - skb_pull(msdu, sizeof(struct htt_rx_desc)); - skb_put(msdu, min(amsdu_len, HTT_RX_MSDU_SIZE)); + skb_put(msdu, hw->rx_desc_ops->rx_desc_size); + skb_pull(msdu, hw->rx_desc_ops->rx_desc_size); + skb_put(msdu, min(amsdu_len, ath10k_htt_rx_msdu_size(hw))); amsdu_len -= msdu->len; last_frag = ind_desc->reserved; @@ -631,8 +652,10 @@ static int ath10k_htt_rx_pop_paddr32_list(struct ath10k_htt *htt, struct sk_buff_head *list) { struct ath10k *ar = htt->ar; + struct ath10k_hw_params *hw = &ar->hw_params; struct htt_rx_in_ord_msdu_desc *msdu_desc = ev->msdu_descs32; struct htt_rx_desc *rxd; + struct rx_attention *rxd_attention; struct sk_buff *msdu; int msdu_count, ret; bool is_offload; @@ -667,15 +690,16 @@ static int ath10k_htt_rx_pop_paddr32_list(struct ath10k_htt *htt, __skb_queue_tail(list, msdu); if (!is_offload) { - rxd = (void *)msdu->data; + rxd = HTT_RX_BUF_TO_RX_DESC(hw, msdu->data); + rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd); - trace_ath10k_htt_rx_desc(ar, rxd, sizeof(*rxd)); + trace_ath10k_htt_rx_desc(ar, rxd, hw->rx_desc_ops->rx_desc_size); - skb_put(msdu, sizeof(*rxd)); - skb_pull(msdu, sizeof(*rxd)); + skb_put(msdu, hw->rx_desc_ops->rx_desc_size); + skb_pull(msdu, hw->rx_desc_ops->rx_desc_size); skb_put(msdu, __le16_to_cpu(msdu_desc->msdu_len)); - if (!(__le32_to_cpu(rxd->attention.flags) & + if (!(__le32_to_cpu(rxd_attention->flags) & RX_ATTENTION_FLAGS_MSDU_DONE)) { ath10k_warn(htt->ar, "tried to pop an incomplete frame, oops!\n"); return -EIO; @@ -693,8 +717,10 @@ static int ath10k_htt_rx_pop_paddr64_list(struct ath10k_htt *htt, struct sk_buff_head *list) { struct ath10k *ar = htt->ar; + struct ath10k_hw_params *hw = &ar->hw_params; struct htt_rx_in_ord_msdu_desc_ext *msdu_desc = ev->msdu_descs64; struct htt_rx_desc *rxd; + struct rx_attention *rxd_attention; struct sk_buff *msdu; int msdu_count, ret; bool is_offload; @@ -728,15 +754,16 @@ static int ath10k_htt_rx_pop_paddr64_list(struct ath10k_htt *htt, __skb_queue_tail(list, msdu); if (!is_offload) { - rxd = (void *)msdu->data; + rxd = HTT_RX_BUF_TO_RX_DESC(hw, msdu->data); + rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd); - trace_ath10k_htt_rx_desc(ar, rxd, sizeof(*rxd)); + trace_ath10k_htt_rx_desc(ar, rxd, hw->rx_desc_ops->rx_desc_size); - skb_put(msdu, sizeof(*rxd)); - skb_pull(msdu, sizeof(*rxd)); + skb_put(msdu, hw->rx_desc_ops->rx_desc_size); + skb_pull(msdu, hw->rx_desc_ops->rx_desc_size); skb_put(msdu, __le16_to_cpu(msdu_desc->msdu_len)); - if (!(__le32_to_cpu(rxd->attention.flags) & + if (!(__le32_to_cpu(rxd_attention->flags) & RX_ATTENTION_FLAGS_MSDU_DONE)) { ath10k_warn(htt->ar, "tried to pop an incomplete frame, oops!\n"); return -EIO; @@ -823,8 +850,10 @@ err_dma_idx: ath10k_htt_get_rx_ring_size(htt), vaddr_ring, htt->rx_ring.base_paddr); + ath10k_htt_config_paddrs_ring(htt, NULL); err_dma_ring: kfree(htt->rx_ring.netbufs_ring); + htt->rx_ring.netbufs_ring = NULL; err_netbuf: return -ENOMEM; } @@ -944,16 +973,32 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, struct ieee80211_rx_status *status, struct htt_rx_desc *rxd) { + struct ath10k_hw_params *hw = &ar->hw_params; + struct rx_attention *rxd_attention; + struct rx_mpdu_start *rxd_mpdu_start; + struct rx_mpdu_end *rxd_mpdu_end; + struct rx_msdu_start_common *rxd_msdu_start_common; + struct rx_msdu_end_common *rxd_msdu_end_common; + struct rx_ppdu_start *rxd_ppdu_start; struct ieee80211_supported_band *sband; u8 cck, rate, bw, sgi, mcs, nss; + u8 *rxd_msdu_payload; u8 preamble = 0; u8 group_id; u32 info1, info2, info3; u32 stbc, nsts_su; - info1 = __le32_to_cpu(rxd->ppdu_start.info1); - info2 = __le32_to_cpu(rxd->ppdu_start.info2); - info3 = __le32_to_cpu(rxd->ppdu_start.info3); + rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd); + rxd_mpdu_start = ath10k_htt_rx_desc_get_mpdu_start(hw, rxd); + rxd_mpdu_end = ath10k_htt_rx_desc_get_mpdu_end(hw, rxd); + rxd_msdu_start_common = ath10k_htt_rx_desc_get_msdu_start(hw, rxd); + rxd_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rxd); + rxd_ppdu_start = ath10k_htt_rx_desc_get_ppdu_start(hw, rxd); + rxd_msdu_payload = ath10k_htt_rx_desc_get_msdu_payload(hw, rxd); + + info1 = __le32_to_cpu(rxd_ppdu_start->info1); + info2 = __le32_to_cpu(rxd_ppdu_start->info2); + info3 = __le32_to_cpu(rxd_ppdu_start->info3); preamble = MS(info1, RX_PPDU_START_INFO1_PREAMBLE_TYPE); @@ -1022,24 +1067,24 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, if (mcs > 0x09) { ath10k_warn(ar, "invalid MCS received %u\n", mcs); ath10k_warn(ar, "rxd %08x mpdu start %08x %08x msdu start %08x %08x ppdu start %08x %08x %08x %08x %08x\n", - __le32_to_cpu(rxd->attention.flags), - __le32_to_cpu(rxd->mpdu_start.info0), - __le32_to_cpu(rxd->mpdu_start.info1), - __le32_to_cpu(rxd->msdu_start.common.info0), - __le32_to_cpu(rxd->msdu_start.common.info1), - rxd->ppdu_start.info0, - __le32_to_cpu(rxd->ppdu_start.info1), - __le32_to_cpu(rxd->ppdu_start.info2), - __le32_to_cpu(rxd->ppdu_start.info3), - __le32_to_cpu(rxd->ppdu_start.info4)); + __le32_to_cpu(rxd_attention->flags), + __le32_to_cpu(rxd_mpdu_start->info0), + __le32_to_cpu(rxd_mpdu_start->info1), + __le32_to_cpu(rxd_msdu_start_common->info0), + __le32_to_cpu(rxd_msdu_start_common->info1), + rxd_ppdu_start->info0, + __le32_to_cpu(rxd_ppdu_start->info1), + __le32_to_cpu(rxd_ppdu_start->info2), + __le32_to_cpu(rxd_ppdu_start->info3), + __le32_to_cpu(rxd_ppdu_start->info4)); ath10k_warn(ar, "msdu end %08x mpdu end %08x\n", - __le32_to_cpu(rxd->msdu_end.common.info0), - __le32_to_cpu(rxd->mpdu_end.info0)); + __le32_to_cpu(rxd_msdu_end_common->info0), + __le32_to_cpu(rxd_mpdu_end->info0)); ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "rx desc msdu payload: ", - rxd->msdu_payload, 50); + rxd_msdu_payload, 50); } status->rate_idx = mcs; @@ -1059,6 +1104,10 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, static struct ieee80211_channel * ath10k_htt_rx_h_peer_channel(struct ath10k *ar, struct htt_rx_desc *rxd) { + struct ath10k_hw_params *hw = &ar->hw_params; + struct rx_attention *rxd_attention; + struct rx_msdu_end_common *rxd_msdu_end_common; + struct rx_mpdu_start *rxd_mpdu_start; struct ath10k_peer *peer; struct ath10k_vif *arvif; struct cfg80211_chan_def def; @@ -1069,15 +1118,19 @@ ath10k_htt_rx_h_peer_channel(struct ath10k *ar, struct htt_rx_desc *rxd) if (!rxd) return NULL; - if (rxd->attention.flags & + rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd); + rxd_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rxd); + rxd_mpdu_start = ath10k_htt_rx_desc_get_mpdu_start(hw, rxd); + + if (rxd_attention->flags & __cpu_to_le32(RX_ATTENTION_FLAGS_PEER_IDX_INVALID)) return NULL; - if (!(rxd->msdu_end.common.info0 & + if (!(rxd_msdu_end_common->info0 & __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU))) return NULL; - peer_id = MS(__le32_to_cpu(rxd->mpdu_start.info0), + peer_id = MS(__le32_to_cpu(rxd_mpdu_start->info0), RX_MPDU_START_INFO0_PEER_IDX); peer = ath10k_peer_find_by_id(ar, peer_id); @@ -1167,14 +1220,16 @@ static void ath10k_htt_rx_h_signal(struct ath10k *ar, struct ieee80211_rx_status *status, struct htt_rx_desc *rxd) { + struct ath10k_hw_params *hw = &ar->hw_params; + struct rx_ppdu_start *rxd_ppdu_start = ath10k_htt_rx_desc_get_ppdu_start(hw, rxd); int i; for (i = 0; i < IEEE80211_MAX_CHAINS ; i++) { status->chains &= ~BIT(i); - if (rxd->ppdu_start.rssi_chains[i].pri20_mhz != 0x80) { + if (rxd_ppdu_start->rssi_chains[i].pri20_mhz != 0x80) { status->chain_signal[i] = ATH10K_DEFAULT_NOISE_FLOOR + - rxd->ppdu_start.rssi_chains[i].pri20_mhz; + rxd_ppdu_start->rssi_chains[i].pri20_mhz; status->chains |= BIT(i); } @@ -1182,7 +1237,7 @@ static void ath10k_htt_rx_h_signal(struct ath10k *ar, /* FIXME: Get real NF */ status->signal = ATH10K_DEFAULT_NOISE_FLOOR + - rxd->ppdu_start.rssi_comb; + rxd_ppdu_start->rssi_comb; status->flag &= ~RX_FLAG_NO_SIGNAL_VAL; } @@ -1190,13 +1245,18 @@ static void ath10k_htt_rx_h_mactime(struct ath10k *ar, struct ieee80211_rx_status *status, struct htt_rx_desc *rxd) { + struct ath10k_hw_params *hw = &ar->hw_params; + struct rx_ppdu_end_common *rxd_ppdu_end_common; + + rxd_ppdu_end_common = ath10k_htt_rx_desc_get_ppdu_end(hw, rxd); + /* FIXME: TSF is known only at the end of PPDU, in the last MPDU. This * means all prior MSDUs in a PPDU are reported to mac80211 without the * TSF. Is it worth holding frames until end of PPDU is known? * * FIXME: Can we get/compute 64bit TSF? */ - status->mactime = __le32_to_cpu(rxd->ppdu_end.common.tsf_timestamp); + status->mactime = __le32_to_cpu(rxd_ppdu_end_common->tsf_timestamp); status->flag |= RX_FLAG_MACTIME_END; } @@ -1206,7 +1266,9 @@ static void ath10k_htt_rx_h_ppdu(struct ath10k *ar, u32 vdev_id) { struct sk_buff *first; + struct ath10k_hw_params *hw = &ar->hw_params; struct htt_rx_desc *rxd; + struct rx_attention *rxd_attention; bool is_first_ppdu; bool is_last_ppdu; @@ -1214,11 +1276,14 @@ static void ath10k_htt_rx_h_ppdu(struct ath10k *ar, return; first = skb_peek(amsdu); - rxd = (void *)first->data - sizeof(*rxd); + rxd = HTT_RX_BUF_TO_RX_DESC(hw, + (void *)first->data - hw->rx_desc_ops->rx_desc_size); - is_first_ppdu = !!(rxd->attention.flags & + rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd); + + is_first_ppdu = !!(rxd_attention->flags & __cpu_to_le32(RX_ATTENTION_FLAGS_FIRST_MPDU)); - is_last_ppdu = !!(rxd->attention.flags & + is_last_ppdu = !!(rxd_attention->flags & __cpu_to_le32(RX_ATTENTION_FLAGS_LAST_MPDU)); if (is_first_ppdu) { @@ -1357,7 +1422,9 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar, const u8 first_hdr[64]) { struct ieee80211_hdr *hdr; + struct ath10k_hw_params *hw = &ar->hw_params; struct htt_rx_desc *rxd; + struct rx_msdu_end_common *rxd_msdu_end_common; size_t hdr_len; size_t crypto_len; bool is_first; @@ -1366,10 +1433,13 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar, int bytes_aligned = ar->hw_params.decap_align_bytes; u8 *qos; - rxd = (void *)msdu->data - sizeof(*rxd); - is_first = !!(rxd->msdu_end.common.info0 & + rxd = HTT_RX_BUF_TO_RX_DESC(hw, + (void *)msdu->data - hw->rx_desc_ops->rx_desc_size); + + rxd_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rxd); + is_first = !!(rxd_msdu_end_common->info0 & __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU)); - is_last = !!(rxd->msdu_end.common.info0 & + is_last = !!(rxd_msdu_end_common->info0 & __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU)); /* Delivered decapped frame: @@ -1387,7 +1457,7 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar, * error packets. If limit exceeds, hw sends all remaining MSDUs as * a single last MSDU with this msdu limit error set. */ - msdu_limit_err = ath10k_rx_desc_msdu_limit_error(&ar->hw_params, rxd); + msdu_limit_err = ath10k_htt_rx_desc_msdu_limit_error(hw, rxd); /* If MSDU limit error happens, then don't warn on, the partial raw MSDU * without first MSDU is expected in that case, and handled later here. @@ -1479,6 +1549,7 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar, const u8 first_hdr[64], enum htt_rx_mpdu_encrypt_type enctype) { + struct ath10k_hw_params *hw = &ar->hw_params; struct ieee80211_hdr *hdr; struct htt_rx_desc *rxd; size_t hdr_len; @@ -1499,9 +1570,10 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar, */ /* pull decapped header and copy SA & DA */ - rxd = (void *)msdu->data - sizeof(*rxd); + rxd = HTT_RX_BUF_TO_RX_DESC(hw, (void *)msdu->data - + hw->rx_desc_ops->rx_desc_size); - l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd); + l3_pad_bytes = ath10k_htt_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd); skb_put(msdu, l3_pad_bytes); hdr = (struct ieee80211_hdr *)(msdu->data + l3_pad_bytes); @@ -1537,18 +1609,25 @@ static void *ath10k_htt_rx_h_find_rfc1042(struct ath10k *ar, enum htt_rx_mpdu_encrypt_type enctype) { struct ieee80211_hdr *hdr; + struct ath10k_hw_params *hw = &ar->hw_params; struct htt_rx_desc *rxd; + struct rx_msdu_end_common *rxd_msdu_end_common; + u8 *rxd_rx_hdr_status; size_t hdr_len, crypto_len; void *rfc1042; bool is_first, is_last, is_amsdu; int bytes_aligned = ar->hw_params.decap_align_bytes; - rxd = (void *)msdu->data - sizeof(*rxd); - hdr = (void *)rxd->rx_hdr_status; + rxd = HTT_RX_BUF_TO_RX_DESC(hw, + (void *)msdu->data - hw->rx_desc_ops->rx_desc_size); + + rxd_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rxd); + rxd_rx_hdr_status = ath10k_htt_rx_desc_get_rx_hdr_status(hw, rxd); + hdr = (void *)rxd_rx_hdr_status; - is_first = !!(rxd->msdu_end.common.info0 & + is_first = !!(rxd_msdu_end_common->info0 & __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU)); - is_last = !!(rxd->msdu_end.common.info0 & + is_last = !!(rxd_msdu_end_common->info0 & __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU)); is_amsdu = !(is_first && is_last); @@ -1574,6 +1653,7 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar, const u8 first_hdr[64], enum htt_rx_mpdu_encrypt_type enctype) { + struct ath10k_hw_params *hw = &ar->hw_params; struct ieee80211_hdr *hdr; struct ethhdr *eth; size_t hdr_len; @@ -1593,8 +1673,10 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar, if (WARN_ON_ONCE(!rfc1042)) return; - rxd = (void *)msdu->data - sizeof(*rxd); - l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd); + rxd = HTT_RX_BUF_TO_RX_DESC(hw, + (void *)msdu->data - hw->rx_desc_ops->rx_desc_size); + + l3_pad_bytes = ath10k_htt_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd); skb_put(msdu, l3_pad_bytes); skb_pull(msdu, l3_pad_bytes); @@ -1635,6 +1717,7 @@ static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar, const u8 first_hdr[64], enum htt_rx_mpdu_encrypt_type enctype) { + struct ath10k_hw_params *hw = &ar->hw_params; struct ieee80211_hdr *hdr; size_t hdr_len; int l3_pad_bytes; @@ -1647,8 +1730,10 @@ static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar, * [payload] */ - rxd = (void *)msdu->data - sizeof(*rxd); - l3_pad_bytes = ath10k_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd); + rxd = HTT_RX_BUF_TO_RX_DESC(hw, + (void *)msdu->data - hw->rx_desc_ops->rx_desc_size); + + l3_pad_bytes = ath10k_htt_rx_desc_get_l3_pad_bytes(&ar->hw_params, rxd); skb_put(msdu, l3_pad_bytes); skb_pull(msdu, sizeof(struct amsdu_subframe_hdr) + l3_pad_bytes); @@ -1673,7 +1758,9 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar, enum htt_rx_mpdu_encrypt_type enctype, bool is_decrypted) { + struct ath10k_hw_params *hw = &ar->hw_params; struct htt_rx_desc *rxd; + struct rx_msdu_start_common *rxd_msdu_start_common; enum rx_msdu_decap_format decap; /* First msdu's decapped header: @@ -1687,8 +1774,11 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar, * [rfc1042/llc] */ - rxd = (void *)msdu->data - sizeof(*rxd); - decap = MS(__le32_to_cpu(rxd->msdu_start.common.info1), + rxd = HTT_RX_BUF_TO_RX_DESC(hw, + (void *)msdu->data - hw->rx_desc_ops->rx_desc_size); + + rxd_msdu_start_common = ath10k_htt_rx_desc_get_msdu_start(hw, rxd); + decap = MS(__le32_to_cpu(rxd_msdu_start_common->info1), RX_MSDU_START_INFO1_DECAP_FORMAT); switch (decap) { @@ -1710,17 +1800,23 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar, } } -static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb) +static int ath10k_htt_rx_get_csum_state(struct ath10k_hw_params *hw, struct sk_buff *skb) { struct htt_rx_desc *rxd; + struct rx_attention *rxd_attention; + struct rx_msdu_start_common *rxd_msdu_start_common; u32 flags, info; bool is_ip4, is_ip6; bool is_tcp, is_udp; bool ip_csum_ok, tcpudp_csum_ok; - rxd = (void *)skb->data - sizeof(*rxd); - flags = __le32_to_cpu(rxd->attention.flags); - info = __le32_to_cpu(rxd->msdu_start.common.info1); + rxd = HTT_RX_BUF_TO_RX_DESC(hw, + (void *)skb->data - hw->rx_desc_ops->rx_desc_size); + + rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd); + rxd_msdu_start_common = ath10k_htt_rx_desc_get_msdu_start(hw, rxd); + flags = __le32_to_cpu(rxd_attention->flags); + info = __le32_to_cpu(rxd_msdu_start_common->info1); is_ip4 = !!(info & RX_MSDU_START_INFO1_IPV4_PROTO); is_ip6 = !!(info & RX_MSDU_START_INFO1_IPV6_PROTO); @@ -1741,9 +1837,10 @@ static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb) return CHECKSUM_UNNECESSARY; } -static void ath10k_htt_rx_h_csum_offload(struct sk_buff *msdu) +static void ath10k_htt_rx_h_csum_offload(struct ath10k_hw_params *hw, + struct sk_buff *msdu) { - msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu); + msdu->ip_summed = ath10k_htt_rx_get_csum_state(hw, msdu); } static u64 ath10k_htt_rx_h_get_pn(struct ath10k *ar, struct sk_buff *skb, @@ -1835,7 +1932,11 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, struct sk_buff *first; struct sk_buff *last; struct sk_buff *msdu, *temp; + struct ath10k_hw_params *hw = &ar->hw_params; struct htt_rx_desc *rxd; + struct rx_attention *rxd_attention; + struct rx_mpdu_start *rxd_mpdu_start; + struct ieee80211_hdr *hdr; enum htt_rx_mpdu_encrypt_type enctype; u8 first_hdr[64]; @@ -1853,18 +1954,22 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, return; first = skb_peek(amsdu); - rxd = (void *)first->data - sizeof(*rxd); + rxd = HTT_RX_BUF_TO_RX_DESC(hw, + (void *)first->data - hw->rx_desc_ops->rx_desc_size); - is_mgmt = !!(rxd->attention.flags & + rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd); + rxd_mpdu_start = ath10k_htt_rx_desc_get_mpdu_start(hw, rxd); + + is_mgmt = !!(rxd_attention->flags & __cpu_to_le32(RX_ATTENTION_FLAGS_MGMT_TYPE)); - enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), + enctype = MS(__le32_to_cpu(rxd_mpdu_start->info0), RX_MPDU_START_INFO0_ENCRYPT_TYPE); /* First MSDU's Rx descriptor in an A-MSDU contains full 802.11 * decapped header. It'll be used for undecapping of each MSDU. */ - hdr = (void *)rxd->rx_hdr_status; + hdr = (void *)ath10k_htt_rx_desc_get_rx_hdr_status(hw, rxd); memcpy(first_hdr, hdr, RX_HTT_HDR_STATUS_LEN); if (rx_hdr) @@ -1882,8 +1987,11 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, /* Some attention flags are valid only in the last MSDU. */ last = skb_peek_tail(amsdu); - rxd = (void *)last->data - sizeof(*rxd); - attention = __le32_to_cpu(rxd->attention.flags); + rxd = HTT_RX_BUF_TO_RX_DESC(hw, + (void *)last->data - hw->rx_desc_ops->rx_desc_size); + + rxd_attention = ath10k_htt_rx_desc_get_attention(hw, rxd); + attention = __le32_to_cpu(rxd_attention->flags); has_fcs_err = !!(attention & RX_ATTENTION_FLAGS_FCS_ERR); has_crypto_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR); @@ -1971,7 +2079,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, continue; } - ath10k_htt_rx_h_csum_offload(msdu); + ath10k_htt_rx_h_csum_offload(&ar->hw_params, msdu); if (frag && !fill_crypt_header && enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) @@ -2083,12 +2191,19 @@ static void ath10k_htt_rx_h_unchain(struct ath10k *ar, unsigned long *unchain_cnt) { struct sk_buff *first; + struct ath10k_hw_params *hw = &ar->hw_params; struct htt_rx_desc *rxd; + struct rx_msdu_start_common *rxd_msdu_start_common; + struct rx_frag_info_common *rxd_frag_info; enum rx_msdu_decap_format decap; first = skb_peek(amsdu); - rxd = (void *)first->data - sizeof(*rxd); - decap = MS(__le32_to_cpu(rxd->msdu_start.common.info1), + rxd = HTT_RX_BUF_TO_RX_DESC(hw, + (void *)first->data - hw->rx_desc_ops->rx_desc_size); + + rxd_msdu_start_common = ath10k_htt_rx_desc_get_msdu_start(hw, rxd); + rxd_frag_info = ath10k_htt_rx_desc_get_frag_info(hw, rxd); + decap = MS(__le32_to_cpu(rxd_msdu_start_common->info1), RX_MSDU_START_INFO1_DECAP_FORMAT); /* FIXME: Current unchaining logic can only handle simple case of raw @@ -2097,7 +2212,7 @@ static void ath10k_htt_rx_h_unchain(struct ath10k *ar, * try re-constructing such frames - it'll be pretty much garbage. */ if (decap != RX_MSDU_DECAP_RAW || - skb_queue_len(amsdu) != 1 + rxd->frag_info.ring2_more_count) { + skb_queue_len(amsdu) != 1 + rxd_frag_info->ring2_more_count) { *drop_cnt += skb_queue_len(amsdu); __skb_queue_purge(amsdu); return; @@ -2112,7 +2227,10 @@ static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar, u8 *subframe_hdr; struct sk_buff *first; bool is_first, is_last; + struct ath10k_hw_params *hw = &ar->hw_params; struct htt_rx_desc *rxd; + struct rx_msdu_end_common *rxd_msdu_end_common; + struct rx_mpdu_start *rxd_mpdu_start; struct ieee80211_hdr *hdr; size_t hdr_len, crypto_len; enum htt_rx_mpdu_encrypt_type enctype; @@ -2120,12 +2238,16 @@ static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar, first = skb_peek(amsdu); - rxd = (void *)first->data - sizeof(*rxd); - hdr = (void *)rxd->rx_hdr_status; + rxd = HTT_RX_BUF_TO_RX_DESC(hw, + (void *)first->data - hw->rx_desc_ops->rx_desc_size); - is_first = !!(rxd->msdu_end.common.info0 & + rxd_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rxd); + rxd_mpdu_start = ath10k_htt_rx_desc_get_mpdu_start(hw, rxd); + hdr = (void *)ath10k_htt_rx_desc_get_rx_hdr_status(hw, rxd); + + is_first = !!(rxd_msdu_end_common->info0 & __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU)); - is_last = !!(rxd->msdu_end.common.info0 & + is_last = !!(rxd_msdu_end_common->info0 & __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU)); /* Return in case of non-aggregated msdu */ @@ -2136,7 +2258,7 @@ static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar, if (!is_first) return false; - enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), + enctype = MS(__le32_to_cpu(rxd_mpdu_start->info0), RX_MPDU_START_INFO0_ENCRYPT_TYPE); hdr_len = ieee80211_hdrlen(hdr->frame_control); @@ -2380,7 +2502,7 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt, /* I have not yet seen any case where num_mpdu_ranges > 1. * qcacld does not seem handle that case either, so we introduce the - * same limitiation here as well. + * same limitation here as well. */ if (num_mpdu_ranges > 1) ath10k_warn(ar, @@ -3028,11 +3150,13 @@ static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp) spin_unlock_bh(&ar->data_lock); } -static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list, +static int ath10k_htt_rx_extract_amsdu(struct ath10k_hw_params *hw, + struct sk_buff_head *list, struct sk_buff_head *amsdu) { struct sk_buff *msdu; struct htt_rx_desc *rxd; + struct rx_msdu_end_common *rxd_msdu_end_common; if (skb_queue_empty(list)) return -ENOBUFS; @@ -3043,15 +3167,22 @@ static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list, while ((msdu = __skb_dequeue(list))) { __skb_queue_tail(amsdu, msdu); - rxd = (void *)msdu->data - sizeof(*rxd); - if (rxd->msdu_end.common.info0 & + rxd = HTT_RX_BUF_TO_RX_DESC(hw, + (void *)msdu->data - + hw->rx_desc_ops->rx_desc_size); + + rxd_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rxd); + if (rxd_msdu_end_common->info0 & __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU)) break; } msdu = skb_peek_tail(amsdu); - rxd = (void *)msdu->data - sizeof(*rxd); - if (!(rxd->msdu_end.common.info0 & + rxd = HTT_RX_BUF_TO_RX_DESC(hw, + (void *)msdu->data - hw->rx_desc_ops->rx_desc_size); + + rxd_msdu_end_common = ath10k_htt_rx_desc_get_msdu_end(hw, rxd); + if (!(rxd_msdu_end_common->info0 & __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU))) { skb_queue_splice_init(amsdu, list); return -EAGAIN; @@ -3194,7 +3325,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) while (!skb_queue_empty(&list)) { __skb_queue_head_init(&amsdu); - ret = ath10k_htt_rx_extract_amsdu(&list, &amsdu); + ret = ath10k_htt_rx_extract_amsdu(&ar->hw_params, &list, &amsdu); switch (ret) { case 0: /* Note: The in-order indication may report interleaved @@ -3438,7 +3569,7 @@ static void ath10k_htt_rx_tx_mode_switch_ind(struct ath10k *ar, threshold = MS(info1, HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD); ath10k_dbg(ar, ATH10K_DBG_HTT, - "htt rx tx mode switch ind info0 0x%04hx info1 0x%04x enable %d num records %zd mode %d threshold %u\n", + "htt rx tx mode switch ind info0 0x%04x info1 0x%04x enable %d num records %zd mode %d threshold %u\n", info0, info1, enable, num_records, mode, threshold); len += sizeof(resp->tx_mode_switch_ind.records[0]) * num_records; @@ -3715,7 +3846,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar, switch (txrate.flags) { case WMI_RATE_PREAMBLE_OFDM: if (arsta->arvif && arsta->arvif->vif) - conf = rcu_dereference(arsta->arvif->vif->chanctx_conf); + conf = rcu_dereference(arsta->arvif->vif->bss_conf.chanctx_conf); if (conf && conf->def.chan->band == NL80211_BAND_5GHZ) arsta->tx_info.status.rates[0].idx = rate_idx - 4; break; @@ -3759,6 +3890,10 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar, arsta->tx_info.status.rates[0].flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; break; + case RATE_INFO_BW_160: + arsta->tx_info.status.rates[0].flags |= + IEEE80211_TX_RC_160_MHZ_WIDTH; + break; } if (peer_stats->succ_pkts) { diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index d6b8bdcef416..bd603feb7953 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -147,6 +147,9 @@ void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) htt->num_pending_tx--; if (htt->num_pending_tx == htt->max_num_pending_tx - 1) ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); + + if (htt->num_pending_tx == 0) + wake_up(&htt->empty_tx_wq); } int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt) @@ -793,47 +796,26 @@ static int ath10k_htt_send_frag_desc_bank_cfg_64(struct ath10k_htt *htt) return 0; } -static void ath10k_htt_fill_rx_desc_offset_32(void *rx_ring) +static void ath10k_htt_fill_rx_desc_offset_32(struct ath10k_hw_params *hw, void *rx_ring) { struct htt_rx_ring_setup_ring32 *ring = (struct htt_rx_ring_setup_ring32 *)rx_ring; -#define desc_offset(x) (offsetof(struct htt_rx_desc, x) / 4) - ring->mac80211_hdr_offset = __cpu_to_le16(desc_offset(rx_hdr_status)); - ring->msdu_payload_offset = __cpu_to_le16(desc_offset(msdu_payload)); - ring->ppdu_start_offset = __cpu_to_le16(desc_offset(ppdu_start)); - ring->ppdu_end_offset = __cpu_to_le16(desc_offset(ppdu_end)); - ring->mpdu_start_offset = __cpu_to_le16(desc_offset(mpdu_start)); - ring->mpdu_end_offset = __cpu_to_le16(desc_offset(mpdu_end)); - ring->msdu_start_offset = __cpu_to_le16(desc_offset(msdu_start)); - ring->msdu_end_offset = __cpu_to_le16(desc_offset(msdu_end)); - ring->rx_attention_offset = __cpu_to_le16(desc_offset(attention)); - ring->frag_info_offset = __cpu_to_le16(desc_offset(frag_info)); -#undef desc_offset + ath10k_htt_rx_desc_get_offsets(hw, &ring->offsets); } -static void ath10k_htt_fill_rx_desc_offset_64(void *rx_ring) +static void ath10k_htt_fill_rx_desc_offset_64(struct ath10k_hw_params *hw, void *rx_ring) { struct htt_rx_ring_setup_ring64 *ring = (struct htt_rx_ring_setup_ring64 *)rx_ring; -#define desc_offset(x) (offsetof(struct htt_rx_desc, x) / 4) - ring->mac80211_hdr_offset = __cpu_to_le16(desc_offset(rx_hdr_status)); - ring->msdu_payload_offset = __cpu_to_le16(desc_offset(msdu_payload)); - ring->ppdu_start_offset = __cpu_to_le16(desc_offset(ppdu_start)); - ring->ppdu_end_offset = __cpu_to_le16(desc_offset(ppdu_end)); - ring->mpdu_start_offset = __cpu_to_le16(desc_offset(mpdu_start)); - ring->mpdu_end_offset = __cpu_to_le16(desc_offset(mpdu_end)); - ring->msdu_start_offset = __cpu_to_le16(desc_offset(msdu_start)); - ring->msdu_end_offset = __cpu_to_le16(desc_offset(msdu_end)); - ring->rx_attention_offset = __cpu_to_le16(desc_offset(attention)); - ring->frag_info_offset = __cpu_to_le16(desc_offset(frag_info)); -#undef desc_offset + ath10k_htt_rx_desc_get_offsets(hw, &ring->offsets); } static int ath10k_htt_send_rx_ring_cfg_32(struct ath10k_htt *htt) { struct ath10k *ar = htt->ar; + struct ath10k_hw_params *hw = &ar->hw_params; struct sk_buff *skb; struct htt_cmd *cmd; struct htt_rx_ring_setup_ring32 *ring; @@ -893,7 +875,7 @@ static int ath10k_htt_send_rx_ring_cfg_32(struct ath10k_htt *htt) ring->flags = __cpu_to_le16(flags); ring->fw_idx_init_val = __cpu_to_le16(fw_idx); - ath10k_htt_fill_rx_desc_offset_32(ring); + ath10k_htt_fill_rx_desc_offset_32(hw, ring); ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); if (ret) { dev_kfree_skb_any(skb); @@ -906,6 +888,7 @@ static int ath10k_htt_send_rx_ring_cfg_32(struct ath10k_htt *htt) static int ath10k_htt_send_rx_ring_cfg_64(struct ath10k_htt *htt) { struct ath10k *ar = htt->ar; + struct ath10k_hw_params *hw = &ar->hw_params; struct sk_buff *skb; struct htt_cmd *cmd; struct htt_rx_ring_setup_ring64 *ring; @@ -962,7 +945,7 @@ static int ath10k_htt_send_rx_ring_cfg_64(struct ath10k_htt *htt) ring->flags = __cpu_to_le16(flags); ring->fw_idx_init_val = __cpu_to_le16(fw_idx); - ath10k_htt_fill_rx_desc_offset_64(ring); + ath10k_htt_fill_rx_desc_offset_64(hw, ring); ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); if (ret) { dev_kfree_skb_any(skb); @@ -1129,7 +1112,7 @@ int ath10k_htt_tx_fetch_resp(struct ath10k *ar, int len = 0; int ret; - /* Response IDs are echo-ed back only for host driver convienence + /* Response IDs are echo-ed back only for host driver convenience * purposes. They aren't used for anything in the driver yet so use 0. */ @@ -1292,7 +1275,6 @@ static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txm struct ath10k *ar = htt->ar; int res, data_len; struct htt_cmd_hdr *cmd_hdr; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; struct htt_data_tx_desc *tx_desc; struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); struct sk_buff *tmp_skb; @@ -1303,11 +1285,15 @@ static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txm u16 flags1 = 0; u16 msdu_id = 0; - if ((ieee80211_is_action(hdr->frame_control) || - ieee80211_is_deauth(hdr->frame_control) || - ieee80211_is_disassoc(hdr->frame_control)) && - ieee80211_has_protected(hdr->frame_control)) { - skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + if (!is_eth) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; + + if ((ieee80211_is_action(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control) || + ieee80211_is_disassoc(hdr->frame_control)) && + ieee80211_has_protected(hdr->frame_control)) { + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + } } data_len = msdu->len; @@ -1404,7 +1390,6 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, { struct ath10k *ar = htt->ar; struct device *dev = ar->dev; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu); struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); struct ath10k_hif_sg_item sg_items[2]; @@ -1436,15 +1421,19 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, txbuf_paddr = htt->txbuf.paddr + (sizeof(struct ath10k_htt_txbuf_32) * msdu_id); - if ((ieee80211_is_action(hdr->frame_control) || - ieee80211_is_deauth(hdr->frame_control) || - ieee80211_is_disassoc(hdr->frame_control)) && - ieee80211_has_protected(hdr->frame_control)) { - skb_put(msdu, IEEE80211_CCMP_MIC_LEN); - } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) && - txmode == ATH10K_HW_TXRX_RAW && - ieee80211_has_protected(hdr->frame_control)) { - skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + if (!is_eth) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; + + if ((ieee80211_is_action(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control) || + ieee80211_is_disassoc(hdr->frame_control)) && + ieee80211_has_protected(hdr->frame_control)) { + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) && + txmode == ATH10K_HW_TXRX_RAW && + ieee80211_has_protected(hdr->frame_control)) { + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + } } skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len, @@ -1606,7 +1595,6 @@ static int ath10k_htt_tx_64(struct ath10k_htt *htt, { struct ath10k *ar = htt->ar; struct device *dev = ar->dev; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu); struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); struct ath10k_hif_sg_item sg_items[2]; @@ -1638,15 +1626,19 @@ static int ath10k_htt_tx_64(struct ath10k_htt *htt, txbuf_paddr = htt->txbuf.paddr + (sizeof(struct ath10k_htt_txbuf_64) * msdu_id); - if ((ieee80211_is_action(hdr->frame_control) || - ieee80211_is_deauth(hdr->frame_control) || - ieee80211_is_disassoc(hdr->frame_control)) && - ieee80211_has_protected(hdr->frame_control)) { - skb_put(msdu, IEEE80211_CCMP_MIC_LEN); - } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) && - txmode == ATH10K_HW_TXRX_RAW && - ieee80211_has_protected(hdr->frame_control)) { - skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + if (!is_eth) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; + + if ((ieee80211_is_action(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control) || + ieee80211_is_disassoc(hdr->frame_control)) && + ieee80211_has_protected(hdr->frame_control)) { + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) && + txmode == ATH10K_HW_TXRX_RAW && + ieee80211_has_protected(hdr->frame_control)) { + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + } } skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len, diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 57c58af64a57..6d32b43a4da6 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -11,6 +11,7 @@ #include "hif.h" #include "wmi-ops.h" #include "bmi.h" +#include "rx_desc.h" const struct ath10k_hw_regs qca988x_regs = { .rtc_soc_base_address = 0x00004000, @@ -83,7 +84,7 @@ const struct ath10k_hw_regs qca99x0_regs = { .ce5_base_address = 0x0004b400, .ce6_base_address = 0x0004b800, .ce7_base_address = 0x0004bc00, - /* Note: qca99x0 supports upto 12 Copy Engines. Other than address of + /* Note: qca99x0 supports up to 12 Copy Engines. Other than address of * CE0 and CE1 no other copy engine is directly referred in the code. * It is not really necessary to assign address for newly supported * CEs in this address table. @@ -119,7 +120,7 @@ const struct ath10k_hw_regs qca4019_regs = { .ce5_base_address = 0x0004b400, .ce6_base_address = 0x0004b800, .ce7_base_address = 0x0004bc00, - /* qca4019 supports upto 12 copy engines. Since base address + /* qca4019 supports up to 12 copy engines. Since base address * of ce8 to ce11 are not directly referred in the code, * no need have them in separate members in this table. * Copy Engine Address @@ -923,7 +924,7 @@ static void ath10k_hw_map_target_mem(struct ath10k *ar, u32 msb) ath10k_hif_write32(ar, address, msb); } -/* 1. Write to memory region of target, such as IRAM adn DRAM. +/* 1. Write to memory region of target, such as IRAM and DRAM. * 2. Target address( 0 ~ 00100000 & 0x00400000~0x00500000) * can be written directly. See ath10k_pci_targ_cpu_to_ce_addr() too. * 3. In order to access the region other than the above, @@ -1134,21 +1135,7 @@ const struct ath10k_hw_ops qca988x_ops = { .is_rssi_enable = ath10k_htt_tx_rssi_enable, }; -static int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(struct htt_rx_desc *rxd) -{ - return MS(__le32_to_cpu(rxd->msdu_end.qca99x0.info1), - RX_MSDU_END_INFO1_L3_HDR_PAD); -} - -static bool ath10k_qca99x0_rx_desc_msdu_limit_error(struct htt_rx_desc *rxd) -{ - return !!(rxd->msdu_end.common.info0 & - __cpu_to_le32(RX_MSDU_END_INFO0_MSDU_LIMIT_ERR)); -} - const struct ath10k_hw_ops qca99x0_ops = { - .rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes, - .rx_desc_get_msdu_limit_error = ath10k_qca99x0_rx_desc_msdu_limit_error, .is_rssi_enable = ath10k_htt_tx_rssi_enable, }; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 6b03c7787e36..1b99f3a39a11 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -510,6 +510,8 @@ struct ath10k_hw_clk_params { u32 outdiv; }; +struct htt_rx_desc_ops; + struct ath10k_hw_params { u32 id; u16 dev_id; @@ -562,6 +564,9 @@ struct ath10k_hw_params { */ bool sw_decrypt_mcast_mgmt; + /* Rx descriptor abstraction */ + const struct ath10k_htt_rx_desc_ops *rx_desc_ops; + const struct ath10k_hw_ops *hw_ops; /* Number of bytes used for alignment in rx_hdr_status of rx desc. */ @@ -618,6 +623,9 @@ struct ath10k_hw_params { */ bool uart_pin_workaround; + /* Workaround for the credit size calculation */ + bool credit_size_workaround; + /* tx stats support over pktlog */ bool tx_stats_over_pktlog; @@ -625,18 +633,20 @@ struct ath10k_hw_params { bool supports_peer_stats_info; bool dynamic_sar_support; + + bool hw_restart_disconnect; + + bool use_fw_tx_credits; }; -struct htt_rx_desc; struct htt_resp; struct htt_data_tx_completion_ext; +struct htt_rx_ring_rx_desc_offsets; /* Defines needed for Rx descriptor abstraction */ struct ath10k_hw_ops { - int (*rx_desc_get_l3_pad_bytes)(struct htt_rx_desc *rxd); void (*set_coverage_class)(struct ath10k *ar, s16 value); int (*enable_pll_clk)(struct ath10k *ar); - bool (*rx_desc_get_msdu_limit_error)(struct htt_rx_desc *rxd); int (*tx_data_rssi_pad_bytes)(struct htt_resp *htt); int (*is_rssi_enable)(struct htt_resp *resp); }; @@ -650,24 +660,6 @@ extern const struct ath10k_hw_ops wcn3990_ops; extern const struct ath10k_hw_clk_params qca6174_clk[]; static inline int -ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd) -{ - if (hw->hw_ops->rx_desc_get_l3_pad_bytes) - return hw->hw_ops->rx_desc_get_l3_pad_bytes(rxd); - return 0; -} - -static inline bool -ath10k_rx_desc_msdu_limit_error(struct ath10k_hw_params *hw, - struct htt_rx_desc *rxd) -{ - if (hw->hw_ops->rx_desc_get_msdu_limit_error) - return hw->hw_ops->rx_desc_get_msdu_limit_error(rxd); - return false; -} - -static inline int ath10k_tx_data_rssi_get_pad_bytes(struct ath10k_hw_params *hw, struct htt_resp *htt) { diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 1f73fbfee0c0..ec8d5b29bc72 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -659,7 +659,7 @@ int ath10k_mac_vif_chan(struct ieee80211_vif *vif, struct ieee80211_chanctx_conf *conf; rcu_read_lock(); - conf = rcu_dereference(vif->chanctx_conf); + conf = rcu_dereference(vif->bss_conf.chanctx_conf); if (!conf) { rcu_read_unlock(); return -ENOENT; @@ -864,11 +864,36 @@ static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr) return 0; } +static void ath10k_peer_map_cleanup(struct ath10k *ar, struct ath10k_peer *peer) +{ + int peer_id, i; + + lockdep_assert_held(&ar->conf_mutex); + + for_each_set_bit(peer_id, peer->peer_ids, + ATH10K_MAX_NUM_PEER_IDS) { + ar->peer_map[peer_id] = NULL; + } + + /* Double check that peer is properly un-referenced from + * the peer_map + */ + for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) { + if (ar->peer_map[i] == peer) { + ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n", + peer->addr, peer, i); + ar->peer_map[i] = NULL; + } + } + + list_del(&peer->list); + kfree(peer); + ar->num_peers--; +} + static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id) { struct ath10k_peer *peer, *tmp; - int peer_id; - int i; lockdep_assert_held(&ar->conf_mutex); @@ -880,25 +905,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id) ath10k_warn(ar, "removing stale peer %pM from vdev_id %d\n", peer->addr, vdev_id); - for_each_set_bit(peer_id, peer->peer_ids, - ATH10K_MAX_NUM_PEER_IDS) { - ar->peer_map[peer_id] = NULL; - } - - /* Double check that peer is properly un-referenced from - * the peer_map - */ - for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) { - if (ar->peer_map[i] == peer) { - ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n", - peer->addr, peer, i); - ar->peer_map[i] = NULL; - } - } - - list_del(&peer->list); - kfree(peer); - ar->num_peers--; + ath10k_peer_map_cleanup(ar, peer); } spin_unlock_bh(&ar->data_lock); } @@ -1509,8 +1516,8 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, arg.channel.chan_radar = !!(chandef->chan->flags & IEEE80211_CHAN_RADAR); } else if (arvif->vdev_type == WMI_VDEV_TYPE_IBSS) { - arg.ssid = arvif->vif->bss_conf.ssid; - arg.ssid_len = arvif->vif->bss_conf.ssid_len; + arg.ssid = arvif->vif->cfg.ssid; + arg.ssid_len = arvif->vif->cfg.ssid_len; } ath10k_dbg(ar, ATH10K_DBG_MAC, @@ -1630,7 +1637,7 @@ static int ath10k_mac_setup_bcn_tmpl(struct ath10k_vif *arvif) arvif->vdev_type != WMI_VDEV_TYPE_IBSS) return 0; - bcn = ieee80211_beacon_get_template(hw, vif, &offs); + bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0); if (!bcn) { ath10k_warn(ar, "failed to get beacon template from mac80211\n"); return -EPERM; @@ -1823,8 +1830,7 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif, } static void ath10k_control_ibss(struct ath10k_vif *arvif, - struct ieee80211_bss_conf *info, - const u8 self_peer[ETH_ALEN]) + struct ieee80211_vif *vif) { struct ath10k *ar = arvif->ar; u32 vdev_param; @@ -1832,7 +1838,7 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif, lockdep_assert_held(&arvif->ar->conf_mutex); - if (!info->ibss_joined) { + if (!vif->cfg.ibss_joined) { if (is_zero_ether_addr(arvif->bssid)) return; @@ -2028,7 +2034,7 @@ static void ath10k_mac_vif_ap_csa_count_down(struct ath10k_vif *arvif) if (arvif->vdev_type != WMI_VDEV_TYPE_AP) return; - if (!vif->csa_active) + if (!vif->bss_conf.csa_active) return; if (!arvif->is_up) @@ -2163,7 +2169,7 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar, lockdep_assert_held(&ar->conf_mutex); if (vif->type == NL80211_IFTYPE_STATION) - aid = vif->bss_conf.aid; + aid = vif->cfg.aid; else aid = sta->aid; @@ -2193,7 +2199,8 @@ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar, return; bss = cfg80211_get_bss(ar->hw->wiphy, def.chan, info->bssid, - info->ssid_len ? info->ssid : NULL, info->ssid_len, + vif->cfg.ssid_len ? vif->cfg.ssid : NULL, + vif->cfg.ssid_len, IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY); if (bss) { const struct cfg80211_bss_ies *ies; @@ -2251,7 +2258,7 @@ static void ath10k_peer_assoc_h_rates(struct ath10k *ar, band = def.chan->band; sband = ar->hw->wiphy->bands[band]; - ratemask = sta->supp_rates[band]; + ratemask = sta->deflink.supp_rates[band]; ratemask &= arvif->bitrate_mask.control[band].legacy; rates = sband->bitrates; @@ -2296,7 +2303,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar, struct ieee80211_sta *sta, struct wmi_peer_assoc_complete_arg *arg) { - const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; + const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap; struct ath10k_vif *arvif = (void *)vif->drv_priv; struct cfg80211_chan_def def; enum nl80211_band band; @@ -2335,7 +2342,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar, if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING) arg->peer_flags |= ar->wmi.peer_flags->ldbc; - if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) { + if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) { arg->peer_flags |= ar->wmi.peer_flags->bw40; arg->peer_rate_caps |= WMI_RC_CW40_FLAG; } @@ -2388,7 +2395,8 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar, arg->peer_ht_rates.rates[i] = i; } else { arg->peer_ht_rates.num_rates = n; - arg->peer_num_spatial_streams = min(sta->rx_nss, max_nss); + arg->peer_num_spatial_streams = min(sta->deflink.rx_nss, + max_nss); } ath10k_dbg(ar, ATH10K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n", @@ -2545,7 +2553,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, struct ieee80211_sta *sta, struct wmi_peer_assoc_complete_arg *arg) { - const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; + const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap; struct ath10k_vif *arvif = (void *)vif->drv_priv; struct ath10k_hw_params *hw = &ar->hw_params; struct cfg80211_chan_def def; @@ -2587,10 +2595,10 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, (1U << (IEEE80211_HT_MAX_AMPDU_FACTOR + ampdu_factor)) - 1); - if (sta->bandwidth == IEEE80211_STA_RX_BW_80) + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80) arg->peer_flags |= ar->wmi.peer_flags->bw80; - if (sta->bandwidth == IEEE80211_STA_RX_BW_160) + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) arg->peer_flags |= ar->wmi.peer_flags->bw160; /* Calculate peer NSS capability from VHT capabilities if STA @@ -2604,7 +2612,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, vht_mcs_mask[i]) max_nss = i + 1; } - arg->peer_num_spatial_streams = min(sta->rx_nss, max_nss); + arg->peer_num_spatial_streams = min(sta->deflink.rx_nss, max_nss); arg->peer_vht_rates.rx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.rx_highest); arg->peer_vht_rates.rx_mcs_set = @@ -2684,15 +2692,17 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar, static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta) { - return sta->supp_rates[NL80211_BAND_2GHZ] >> + return sta->deflink.supp_rates[NL80211_BAND_2GHZ] >> ATH10K_MAC_FIRST_OFDM_RATE_IDX; } static enum wmi_phy_mode ath10k_mac_get_phymode_vht(struct ath10k *ar, struct ieee80211_sta *sta) { - if (sta->bandwidth == IEEE80211_STA_RX_BW_160) { - switch (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { + struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap; + + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) { + switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: return MODE_11AC_VHT160; case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: @@ -2703,13 +2713,13 @@ static enum wmi_phy_mode ath10k_mac_get_phymode_vht(struct ath10k *ar, } } - if (sta->bandwidth == IEEE80211_STA_RX_BW_80) + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80) return MODE_11AC_VHT80; - if (sta->bandwidth == IEEE80211_STA_RX_BW_40) + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) return MODE_11AC_VHT40; - if (sta->bandwidth == IEEE80211_STA_RX_BW_20) + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) return MODE_11AC_VHT20; return MODE_UNKNOWN; @@ -2736,15 +2746,15 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, switch (band) { case NL80211_BAND_2GHZ: - if (sta->vht_cap.vht_supported && + if (sta->deflink.vht_cap.vht_supported && !ath10k_peer_assoc_h_vht_masked(vht_mcs_mask)) { - if (sta->bandwidth == IEEE80211_STA_RX_BW_40) + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) phymode = MODE_11AC_VHT40; else phymode = MODE_11AC_VHT20; - } else if (sta->ht_cap.ht_supported && + } else if (sta->deflink.ht_cap.ht_supported && !ath10k_peer_assoc_h_ht_masked(ht_mcs_mask)) { - if (sta->bandwidth == IEEE80211_STA_RX_BW_40) + if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40) phymode = MODE_11NG_HT40; else phymode = MODE_11NG_HT20; @@ -2759,12 +2769,12 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, /* * Check VHT first. */ - if (sta->vht_cap.vht_supported && + if (sta->deflink.vht_cap.vht_supported && !ath10k_peer_assoc_h_vht_masked(vht_mcs_mask)) { phymode = ath10k_mac_get_phymode_vht(ar, sta); - } else if (sta->ht_cap.ht_supported && + } else if (sta->deflink.ht_cap.ht_supported && !ath10k_peer_assoc_h_ht_masked(ht_mcs_mask)) { - if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) + if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) phymode = MODE_11NA_HT40; else phymode = MODE_11NA_HT20; @@ -3079,8 +3089,8 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, /* ap_sta must be accessed only within rcu section which must be left * before calling ath10k_setup_peer_smps() which might sleep. */ - ht_cap = ap_sta->ht_cap; - vht_cap = ap_sta->vht_cap; + ht_cap = ap_sta->deflink.ht_cap; + vht_cap = ap_sta->deflink.vht_cap; ret = ath10k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg); if (ret) { @@ -3115,11 +3125,11 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d up (associated) bssid %pM aid %d\n", - arvif->vdev_id, bss_conf->bssid, bss_conf->aid); + arvif->vdev_id, bss_conf->bssid, vif->cfg.aid); WARN_ON(arvif->is_up); - arvif->aid = bss_conf->aid; + arvif->aid = vif->cfg.aid; ether_addr_copy(arvif->bssid, bss_conf->bssid); ret = ath10k_wmi_pdev_set_param(ar, @@ -3278,7 +3288,7 @@ static int ath10k_station_assoc(struct ath10k *ar, */ if (!reassoc) { ret = ath10k_setup_peer_smps(ar, arvif, sta->addr, - &sta->ht_cap); + &sta->deflink.ht_cap); if (ret) { ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n", arvif->vdev_id, ret); @@ -3710,6 +3720,9 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar, const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); __le16 fc = hdr->frame_control; + if (IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) + return ATH10K_HW_TXRX_ETHERNET; + if (!vif || vif->type == NL80211_IFTYPE_MONITOR) return ATH10K_HW_TXRX_RAW; @@ -3870,6 +3883,12 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar, bool noack = false; cb->flags = 0; + + if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { + cb->flags |= ATH10K_SKB_F_QOS; /* Assume data frames are QoS */ + goto finish_cb_fill; + } + if (!ath10k_tx_h_use_hwcrypto(vif, skb)) cb->flags |= ATH10K_SKB_F_NO_HWCRYPT; @@ -3908,6 +3927,7 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar, cb->flags |= ATH10K_SKB_F_RAW_TX; } +finish_cb_fill: cb->vif = vif; cb->txq = txq; cb->airtime_est = airtime; @@ -4031,7 +4051,11 @@ static int ath10k_mac_tx(struct ath10k *ar, ath10k_tx_h_seq_no(vif, skb); break; case ATH10K_HW_TXRX_ETHERNET: - ath10k_tx_h_8023(skb); + /* Convert 802.11->802.3 header only if the frame was earlier + * encapsulated to 802.11 by mac80211. Otherwise pass it as is. + */ + if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) + ath10k_tx_h_8023(skb); break; case ATH10K_HW_TXRX_RAW: if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags) && @@ -4118,11 +4142,10 @@ void ath10k_offchan_tx_work(struct work_struct *work) peer = ath10k_peer_find(ar, vdev_id, peer_addr); spin_unlock_bh(&ar->data_lock); - if (peer) + if (peer) { ath10k_warn(ar, "peer %pM on vdev %d already present\n", peer_addr, vdev_id); - - if (!peer) { + } else { ret = ath10k_peer_create(ar, NULL, NULL, vdev_id, peer_addr, WMI_PEER_TYPE_DEFAULT); @@ -4643,12 +4666,10 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif = info->control.vif; struct ieee80211_sta *sta = control->sta; struct ieee80211_txq *txq = NULL; - struct ieee80211_hdr *hdr = (void *)skb->data; enum ath10k_hw_txrx_mode txmode; enum ath10k_mac_tx_path txpath; bool is_htt; bool is_mgmt; - bool is_presp; int ret; u16 airtime; @@ -4662,8 +4683,14 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw, is_mgmt = (txpath == ATH10K_MAC_TX_HTT_MGMT); if (is_htt) { + bool is_presp = false; + spin_lock_bh(&ar->htt.tx_lock); - is_presp = ieee80211_is_probe_resp(hdr->frame_control); + if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) { + struct ieee80211_hdr *hdr = (void *)skb->data; + + is_presp = ieee80211_is_probe_resp(hdr->frame_control); + } ret = ath10k_htt_tx_inc_pending(htt); if (ret) { @@ -5339,13 +5366,29 @@ err: static void ath10k_stop(struct ieee80211_hw *hw) { struct ath10k *ar = hw->priv; + u32 opt; ath10k_drain_tx(ar); mutex_lock(&ar->conf_mutex); if (ar->state != ATH10K_STATE_OFF) { - if (!ar->hw_rfkill_on) - ath10k_halt(ar); + if (!ar->hw_rfkill_on) { + /* If the current driver state is RESTARTING but not yet + * fully RESTARTED because of incoming suspend event, + * then ath10k_halt() is already called via + * ath10k_core_restart() and should not be called here. + */ + if (ar->state != ATH10K_STATE_RESTARTING) { + ath10k_halt(ar); + } else { + /* Suspending here, because when in RESTARTING + * state, ath10k_core_stop() skips + * ath10k_wait_for_suspend(). + */ + opt = WMI_PDEV_SUSPEND_AND_DISABLE_INTR; + ath10k_wait_for_suspend(ar, opt); + } + } ar->state = ATH10K_STATE_OFF; } mutex_unlock(&ar->conf_mutex); @@ -5447,6 +5490,30 @@ static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif) ar->wmi.vdev_param->txbf, value); } +static void ath10k_update_vif_offload(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ath10k_vif *arvif = (void *)vif->drv_priv; + struct ath10k *ar = hw->priv; + u32 vdev_param; + int ret; + + if (ath10k_frame_mode != ATH10K_HW_TXRX_ETHERNET || + ar->wmi.vdev_param->tx_encap_type == WMI_VDEV_PARAM_UNSUPPORTED || + (vif->type != NL80211_IFTYPE_STATION && + vif->type != NL80211_IFTYPE_AP)) + vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; + + vdev_param = ar->wmi.vdev_param->tx_encap_type; + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, + ATH10K_HW_TXRX_NATIVE_WIFI); + /* 10.X firmware does not support this VDEV parameter. Do not warn */ + if (ret && ret != -EOPNOTSUPP) { + ath10k_warn(ar, "failed to set vdev %i TX encapsulation: %d\n", + arvif->vdev_id, ret); + } +} + /* * TODO: * Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE, @@ -5656,15 +5723,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, arvif->def_wep_key_idx = -1; - vdev_param = ar->wmi.vdev_param->tx_encap_type; - ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, - ATH10K_HW_TXRX_NATIVE_WIFI); - /* 10.X firmware does not support this VDEV parameter. Do not warn */ - if (ret && ret != -EOPNOTSUPP) { - ath10k_warn(ar, "failed to set vdev %i TX encapsulation: %d\n", - arvif->vdev_id, ret); - goto err_vdev_delete; - } + ath10k_update_vif_offload(hw, vif); /* Configuring number of spatial stream for monitor interface is causing * target assert in qca9888 and qca6174. @@ -6016,7 +6075,7 @@ static void ath10k_recalculate_mgmt_rate(struct ath10k *ar, static void ath10k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, - u32 changed) + u64 changed) { struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = (void *)vif->drv_priv; @@ -6030,7 +6089,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); if (changed & BSS_CHANGED_IBSS) - ath10k_control_ibss(arvif, info, vif->addr); + ath10k_control_ibss(arvif, vif); if (changed & BSS_CHANGED_BEACON_INT) { arvif->beacon_interval = info->beacon_int; @@ -6095,9 +6154,10 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_SSID && vif->type == NL80211_IFTYPE_AP) { - arvif->u.ap.ssid_len = info->ssid_len; - if (info->ssid_len) - memcpy(arvif->u.ap.ssid, info->ssid, info->ssid_len); + arvif->u.ap.ssid_len = vif->cfg.ssid_len; + if (vif->cfg.ssid_len) + memcpy(arvif->u.ap.ssid, vif->cfg.ssid, + vif->cfg.ssid_len); arvif->u.ap.hidden_ssid = info->hidden_ssid; } @@ -6174,7 +6234,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_ASSOC) { - if (info->assoc) { + if (vif->cfg.assoc) { /* Workaround: Make sure monitor vdev is not running * when associating to prevent some firmware revisions * (e.g. 10.1 and 10.2) from crashing. @@ -6199,7 +6259,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_PS) { - arvif->ps = vif->bss_conf.ps; + arvif->ps = vif->cfg.ps; ret = ath10k_config_ps(ar); if (ret) @@ -6380,13 +6440,14 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw, scan_timeout = min_t(u32, arg.max_rest_time * (arg.n_channels - 1) + (req->duration + ATH10K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) * - arg.n_channels, arg.max_scan_time + 200); - + arg.n_channels, arg.max_scan_time); } else { - /* Add a 200ms margin to account for event/command processing */ - scan_timeout = arg.max_scan_time + 200; + scan_timeout = arg.max_scan_time; } + /* Add a 200ms margin to account for event/command processing */ + scan_timeout += 200; + ret = ath10k_start_scan(ar, &arg); if (ret) { ath10k_warn(ar, "failed to start hw scan: %d\n", ret); @@ -6786,10 +6847,10 @@ static int ath10k_sta_set_txpwr(struct ieee80211_hw *hw, int ret = 0; s16 txpwr; - if (sta->txpwr.type == NL80211_TX_POWER_AUTOMATIC) { + if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) { txpwr = 0; } else { - txpwr = sta->txpwr.power; + txpwr = sta->deflink.txpwr.power; if (!txpwr) return -EINVAL; } @@ -6909,26 +6970,29 @@ static int ath10k_mac_validate_rate_mask(struct ath10k *ar, struct ieee80211_sta *sta, u32 rate_ctrl_flag, u8 nss) { - if (nss > sta->rx_nss) { + struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap; + struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap; + + if (nss > sta->deflink.rx_nss) { ath10k_warn(ar, "Invalid nss field, configured %u limit %u\n", - nss, sta->rx_nss); + nss, sta->deflink.rx_nss); return -EINVAL; } if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_VHT) { - if (!sta->vht_cap.vht_supported) { + if (!vht_cap->vht_supported) { ath10k_warn(ar, "Invalid VHT rate for sta %pM\n", sta->addr); return -EINVAL; } } else if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_HT) { - if (!sta->ht_cap.ht_supported || sta->vht_cap.vht_supported) { + if (!ht_cap->ht_supported || vht_cap->vht_supported) { ath10k_warn(ar, "Invalid HT rate for sta %pM\n", sta->addr); return -EINVAL; } } else { - if (sta->ht_cap.ht_supported || sta->vht_cap.vht_supported) + if (ht_cap->ht_supported || vht_cap->vht_supported) return -EINVAL; } @@ -7564,10 +7628,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, /* Clean up the peer object as well since we * must have failed to do this above. */ - list_del(&peer->list); - ar->peer_map[i] = NULL; - kfree(peer); - ar->num_peers--; + ath10k_peer_map_cleanup(ar, peer); } } spin_unlock_bh(&ar->data_lock); @@ -7757,7 +7818,8 @@ exit: } static int ath10k_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 ac, + struct ieee80211_vif *vif, + unsigned int link_id, u16 ac, const struct ieee80211_tx_queue_params *params) { struct ath10k *ar = hw->priv; @@ -8035,7 +8097,7 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, /* TODO: Implement this function properly * For now it is needed to reply to Probe Requests in IBSS mode. - * Propably we need this information from FW. + * Probably we need this information from FW. */ static int ath10k_tx_last_beacon(struct ieee80211_hw *hw) { @@ -8271,7 +8333,7 @@ static bool ath10k_mac_set_vht_bitrate_mask_fixup(struct ath10k *ar, u8 rate = arvif->vht_pfr; /* skip non vht and multiple rate peers */ - if (!sta->vht_cap.vht_supported || arvif->vht_num_rates != 1) + if (!sta->deflink.vht_cap.vht_supported || arvif->vht_num_rates != 1) return false; err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, @@ -8312,7 +8374,7 @@ static void ath10k_mac_clr_bitrate_mask_iter(void *data, int err; /* clear vht peers only */ - if (arsta->arvif != arvif || !sta->vht_cap.vht_supported) + if (arsta->arvif != arvif || !sta->deflink.vht_cap.vht_supported) return; err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, @@ -8456,13 +8518,14 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, ath10k_dbg(ar, ATH10K_DBG_STA, "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n", - sta->addr, changed, sta->bandwidth, sta->rx_nss, - sta->smps_mode); + sta->addr, changed, sta->deflink.bandwidth, + sta->deflink.rx_nss, + sta->deflink.smps_mode); if (changed & IEEE80211_RC_BW_CHANGED) { bw = WMI_PEER_CHWIDTH_20MHZ; - switch (sta->bandwidth) { + switch (sta->deflink.bandwidth) { case IEEE80211_STA_RX_BW_20: bw = WMI_PEER_CHWIDTH_20MHZ; break; @@ -8477,7 +8540,7 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, break; default: ath10k_warn(ar, "Invalid bandwidth %d in rc update for %pM\n", - sta->bandwidth, sta->addr); + sta->deflink.bandwidth, sta->addr); bw = WMI_PEER_CHWIDTH_20MHZ; break; } @@ -8486,12 +8549,12 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, } if (changed & IEEE80211_RC_NSS_CHANGED) - arsta->nss = sta->rx_nss; + arsta->nss = sta->deflink.rx_nss; if (changed & IEEE80211_RC_SMPS_CHANGED) { smps = WMI_PEER_SMPS_PS_NONE; - switch (sta->smps_mode) { + switch (sta->deflink.smps_mode) { case IEEE80211_SMPS_AUTOMATIC: case IEEE80211_SMPS_OFF: smps = WMI_PEER_SMPS_PS_NONE; @@ -8504,7 +8567,7 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, break; case IEEE80211_SMPS_NUM_MODES: ath10k_warn(ar, "Invalid smps %d in sta rc update for %pM\n", - sta->smps_mode, sta->addr); + sta->deflink.smps_mode, sta->addr); smps = WMI_PEER_SMPS_PS_NONE; break; } @@ -8775,7 +8838,7 @@ ath10k_mac_change_chanctx_cnt_iter(void *data, u8 *mac, { struct ath10k_mac_change_chanctx_arg *arg = data; - if (rcu_access_pointer(vif->chanctx_conf) != arg->ctx) + if (rcu_access_pointer(vif->bss_conf.chanctx_conf) != arg->ctx) return; arg->n_vifs++; @@ -8788,7 +8851,7 @@ ath10k_mac_change_chanctx_fill_iter(void *data, u8 *mac, struct ath10k_mac_change_chanctx_arg *arg = data; struct ieee80211_chanctx_conf *ctx; - ctx = rcu_access_pointer(vif->chanctx_conf); + ctx = rcu_access_pointer(vif->bss_conf.chanctx_conf); if (ctx != arg->ctx) return; @@ -8861,6 +8924,7 @@ unlock: static int ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx) { struct ath10k *ar = hw->priv; @@ -8940,6 +9004,7 @@ err: static void ath10k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx) { struct ath10k *ar = hw->priv; @@ -9352,6 +9417,7 @@ static const struct ieee80211_ops ath10k_ops = { .stop = ath10k_stop, .config = ath10k_config, .add_interface = ath10k_add_interface, + .update_vif_offload = ath10k_update_vif_offload, .remove_interface = ath10k_remove_interface, .configure_filter = ath10k_configure_filter, .bss_info_changed = ath10k_bss_info_changed, @@ -9620,7 +9686,7 @@ static const struct ieee80211_iface_limit ath10k_tlv_if_limit_ibss[] = { }, }; -/* FIXME: This is not thouroughly tested. These combinations may over- or +/* FIXME: This is not thoroughly tested. These combinations may over- or * underestimate hw/fw capabilities. */ static struct ieee80211_iface_combination ath10k_tlv_if_comb[] = { @@ -9860,7 +9926,7 @@ int ath10k_mac_register(struct ath10k *ar) WLAN_CIPHER_SUITE_BIP_GMAC_128, WLAN_CIPHER_SUITE_BIP_GMAC_256, - /* Only QCA99x0 and QCA4019 varients support GCMP-128, GCMP-256 + /* Only QCA99x0 and QCA4019 variants support GCMP-128, GCMP-256 * and CCMP-256 in hardware. */ WLAN_CIPHER_SUITE_GCMP, @@ -10021,6 +10087,12 @@ int ath10k_mac_register(struct ath10k *ar) if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map)) ieee80211_hw_set(ar->hw, SUPPORTS_TDLS_BUFFER_STA); + if (ath10k_frame_mode == ATH10K_HW_TXRX_ETHERNET) { + if (ar->wmi.vdev_param->tx_encap_type != + WMI_VDEV_PARAM_UNSUPPORTED) + ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD); + } + ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; ar->hw->wiphy->max_remain_on_channel_duration = 5000; @@ -10206,7 +10278,8 @@ int ath10k_mac_register(struct ath10k *ar) ar->hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN); } - if (!ath_is_world_regd(&ar->ath_common.regulatory)) { + if (!ath_is_world_regd(&ar->ath_common.reg_world_copy) && + !ath_is_world_regd(&ar->ath_common.regulatory)) { ret = regulatory_hint(ar->hw->wiphy, ar->ath_common.regulatory.alpha2); if (ret) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 4d4e2f91e15c..e56c6a6b1379 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1244,7 +1244,7 @@ static void ath10k_pci_process_htt_rx_cb(struct ath10k_ce_pipe *ce_state, unsigned int nbytes, max_nbytes, nentries; int orig_len; - /* No need to aquire ce_lock for CE5, since this is the only place CE5 + /* No need to acquire ce_lock for CE5, since this is the only place CE5 * is processed other than init and deinit. Before releasing CE5 * buffers, interrupts are disabled. Thus CE5 access is serialized. */ @@ -3215,8 +3215,7 @@ static void ath10k_pci_free_irq(struct ath10k *ar) void ath10k_pci_init_napi(struct ath10k *ar) { - netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_pci_napi_poll, - ATH10K_NAPI_BUDGET); + netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_pci_napi_poll); } static int ath10k_pci_init_irq(struct ath10k *ar) diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index cf64898b9447..480cd97ab739 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -81,7 +81,7 @@ struct ath10k_pci_pipe { /* Handle of underlying Copy Engine */ struct ath10k_ce_pipe *ce_hdl; - /* Our pipe number; facilitiates use of pipe_info ptrs. */ + /* Our pipe number; facilitates use of pipe_info ptrs. */ u8 pipe_num; /* Convenience back pointer to hif_ce_state. */ diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c index 80fcb917fe4e..66cb7a1e628a 100644 --- a/drivers/net/wireless/ath/ath10k/qmi.c +++ b/drivers/net/wireless/ath/ath10k/qmi.c @@ -590,12 +590,12 @@ static int ath10k_qmi_cap_send_sync_msg(struct ath10k_qmi *qmi) if (resp->fw_version_info_valid) { qmi->fw_version = resp->fw_version_info.fw_version; - strlcpy(qmi->fw_build_timestamp, resp->fw_version_info.fw_build_timestamp, + strscpy(qmi->fw_build_timestamp, resp->fw_version_info.fw_build_timestamp, sizeof(qmi->fw_build_timestamp)); } if (resp->fw_build_id_valid) - strlcpy(qmi->fw_build_id, resp->fw_build_id, + strscpy(qmi->fw_build_id, resp->fw_build_id, MAX_BUILD_ID_LEN + 1); if (!test_bit(ATH10K_SNOC_FLAG_REGISTERED, &ar_snoc->flags)) { @@ -792,7 +792,7 @@ static void ath10k_qmi_event_server_arrive(struct ath10k_qmi *qmi) return; /* - * HACK: sleep for a while inbetween receiving the msa info response + * HACK: sleep for a while between receiving the msa info response * and the XPU update to prevent SDM845 from crashing due to a security * violation, when running MPSS.AT.4.0.c2-01184-SDM845_GEN_PACK-1. */ diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h index 705b6295e466..777e53aa69dc 100644 --- a/drivers/net/wireless/ath/ath10k/rx_desc.h +++ b/drivers/net/wireless/ath/ath10k/rx_desc.h @@ -196,17 +196,31 @@ struct rx_attention { * descriptor. */ -struct rx_frag_info { +struct rx_frag_info_common { u8 ring0_more_count; u8 ring1_more_count; u8 ring2_more_count; u8 ring3_more_count; +} __packed; + +struct rx_frag_info_wcn3990 { u8 ring4_more_count; u8 ring5_more_count; u8 ring6_more_count; u8 ring7_more_count; } __packed; +struct rx_frag_info { + struct rx_frag_info_common common; + union { + struct rx_frag_info_wcn3990 wcn3990; + } __packed; +} __packed; + +struct rx_frag_info_v1 { + struct rx_frag_info_common common; +} __packed; + /* * ring0_more_count * Indicates the number of more buffers associated with RX DMA @@ -434,7 +448,7 @@ struct rx_mpdu_end { * - 4 bytes for WEP * - 8 bytes for TKIP, AES * [padding to 4 bytes] - * c) A-MSDU subframe header (14 bytes) if appliable + * c) A-MSDU subframe header (14 bytes) if applicable * d) LLC/SNAP (RFC1042, 8 bytes) * * In case of A-MSDU only first frame in sequence contains (a) and (b). @@ -474,11 +488,17 @@ struct rx_msdu_start_wcn3990 { struct rx_msdu_start { struct rx_msdu_start_common common; union { - struct rx_msdu_start_qca99x0 qca99x0; struct rx_msdu_start_wcn3990 wcn3990; } __packed; } __packed; +struct rx_msdu_start_v1 { + struct rx_msdu_start_common common; + union { + struct rx_msdu_start_qca99x0 qca99x0; + } __packed; +} __packed; + /* * msdu_length * MSDU length in bytes after decapsulation. This field is @@ -612,11 +632,17 @@ struct rx_msdu_end_wcn3990 { struct rx_msdu_end { struct rx_msdu_end_common common; union { - struct rx_msdu_end_qca99x0 qca99x0; struct rx_msdu_end_wcn3990 wcn3990; } __packed; } __packed; +struct rx_msdu_end_v1 { + struct rx_msdu_end_common common; + union { + struct rx_msdu_end_qca99x0 qca99x0; + } __packed; +} __packed; + /* *ip_hdr_chksum * This can include the IP header checksum or the pseudo header @@ -1136,11 +1162,17 @@ struct rx_ppdu_end_wcn3990 { struct rx_ppdu_end { struct rx_ppdu_end_common common; union { + struct rx_ppdu_end_wcn3990 wcn3990; + } __packed; +} __packed; + +struct rx_ppdu_end_v1 { + struct rx_ppdu_end_common common; + union { struct rx_ppdu_end_qca988x qca988x; struct rx_ppdu_end_qca6174 qca6174; struct rx_ppdu_end_qca99x0 qca99x0; struct rx_ppdu_end_qca9984 qca9984; - struct rx_ppdu_end_wcn3990 wcn3990; } __packed; } __packed; diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c index 63e1c2d783c5..79e09c7a82b3 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c @@ -1057,7 +1057,7 @@ static int ath10k_sdio_mbox_proc_pending_irqs(struct ath10k *ar, out: /* An optimization to bypass reading the IRQ status registers - * unecessarily which can re-wake the target, if upper layers + * unnecessarily which can re-wake the target, if upper layers * determine that we are in a low-throughput mode, we can rely on * taking another interrupt rather than re-checking the status * registers which can re-wake the target. @@ -1633,7 +1633,7 @@ static void ath10k_sdio_hif_power_down(struct ath10k *ar) return; } - ret = mmc_hw_reset(ar_sdio->func->card->host); + ret = mmc_hw_reset(ar_sdio->func->card); if (ret) ath10k_warn(ar, "unable to reset sdio: %d\n", ret); @@ -2531,8 +2531,7 @@ static int ath10k_sdio_probe(struct sdio_func *func, return -ENOMEM; } - netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_sdio_napi_poll, - ATH10K_NAPI_BUDGET); + netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_sdio_napi_poll); ath10k_dbg(ar, ATH10K_DBG_BOOT, "sdio new func %d vendor 0x%x device 0x%x block 0x%x/0x%x\n", diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 9513ab696fff..cfcb759a87de 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -1242,20 +1242,18 @@ static int ath10k_snoc_napi_poll(struct napi_struct *ctx, int budget) static void ath10k_snoc_init_napi(struct ath10k *ar) { - netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_snoc_napi_poll, - ATH10K_NAPI_BUDGET); + netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_snoc_napi_poll); } static int ath10k_snoc_request_irq(struct ath10k *ar) { struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); - int irqflags = IRQF_TRIGGER_RISING; int ret, id; for (id = 0; id < CE_COUNT_MAX; id++) { ret = request_irq(ar_snoc->ce_irqs[id].irq_line, - ath10k_snoc_per_engine_handler, - irqflags, ce_name[id], ar); + ath10k_snoc_per_engine_handler, 0, + ce_name[id], ar); if (ret) { ath10k_err(ar, "failed to register IRQ handler for CE %d: %d\n", @@ -1306,13 +1304,10 @@ static int ath10k_snoc_resource_init(struct ath10k *ar) } for (i = 0; i < CE_COUNT; i++) { - res = platform_get_resource(ar_snoc->dev, IORESOURCE_IRQ, i); - if (!res) { - ath10k_err(ar, "failed to get IRQ%d\n", i); - ret = -ENODEV; - goto out; - } - ar_snoc->ce_irqs[i].irq_line = res->start; + ret = platform_get_irq(ar_snoc->dev, i); + if (ret < 0) + return ret; + ar_snoc->ce_irqs[i].irq_line = ret; } ret = device_property_read_u32(&pdev->dev, "qcom,xo-cal-data", @@ -1323,10 +1318,8 @@ static int ath10k_snoc_resource_init(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_SNOC, "xo cal data %x\n", ar_snoc->xo_cal_data); } - ret = 0; -out: - return ret; + return 0; } static void ath10k_snoc_quirks_init(struct ath10k *ar) @@ -1556,11 +1549,11 @@ static int ath10k_setup_msa_resources(struct ath10k *ar, u32 msa_size) node = of_parse_phandle(dev->of_node, "memory-region", 0); if (node) { ret = of_address_to_resource(node, 0, &r); + of_node_put(node); if (ret) { dev_err(dev, "failed to resolve msa fixed region\n"); return ret; } - of_node_put(node); ar->msa.paddr = r.start; ar->msa.mem_size = resource_size(&r); diff --git a/drivers/net/wireless/ath/ath10k/swap.h b/drivers/net/wireless/ath/ath10k/swap.h index 25e0ad36ddb1..b4733b5ded34 100644 --- a/drivers/net/wireless/ath/ath10k/swap.h +++ b/drivers/net/wireless/ath/ath10k/swap.h @@ -17,7 +17,7 @@ struct ath10k_fw_file; struct ath10k_swap_code_seg_tlv { __le32 address; __le32 length; - u8 data[0]; + u8 data[]; } __packed; struct ath10k_swap_code_seg_tail { diff --git a/drivers/net/wireless/ath/ath10k/thermal.c b/drivers/net/wireless/ath/ath10k/thermal.c index 36c9a1364253..cefd97323dfe 100644 --- a/drivers/net/wireless/ath/ath10k/thermal.c +++ b/drivers/net/wireless/ath/ath10k/thermal.c @@ -98,7 +98,7 @@ static ssize_t ath10k_thermal_show_temp(struct device *dev, temperature = ar->thermal.temperature; spin_unlock_bh(&ar->data_lock); - /* display in millidegree celcius */ + /* display in millidegree celsius */ ret = snprintf(buf, PAGE_SIZE, "%d\n", temperature * 1000); out: mutex_unlock(&ar->conf_mutex); diff --git a/drivers/net/wireless/ath/ath10k/thermal.h b/drivers/net/wireless/ath/ath10k/thermal.h index 5fdb020f4da3..1f4de9fbf2b3 100644 --- a/drivers/net/wireless/ath/ath10k/thermal.h +++ b/drivers/net/wireless/ath/ath10k/thermal.h @@ -19,7 +19,7 @@ struct ath10k_thermal { /* protected by conf_mutex */ u32 throttle_state; u32 quiet_period; - /* temperature value in Celcius degree + /* temperature value in Celsius degree * protected by data_lock */ int temperature; diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h index 4714c86bb501..64e7a767d963 100644 --- a/drivers/net/wireless/ath/ath10k/trace.h +++ b/drivers/net/wireless/ath/ath10k/trace.h @@ -52,15 +52,12 @@ DECLARE_EVENT_CLASS(ath10k_log_event, TP_STRUCT__entry( __string(device, dev_name(ar->dev)) __string(driver, dev_driver_string(ar->dev)) - __dynamic_array(char, msg, ATH10K_MSG_MAX) + __vstring(msg, vaf->fmt, vaf->va) ), TP_fast_assign( __assign_str(device, dev_name(ar->dev)); __assign_str(driver, dev_driver_string(ar->dev)); - WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), - ATH10K_MSG_MAX, - vaf->fmt, - *vaf->va) >= ATH10K_MSG_MAX); + __assign_vstr(msg, vaf->fmt, vaf->va); ), TP_printk( "%s %s %s", @@ -92,16 +89,13 @@ TRACE_EVENT(ath10k_log_dbg, __string(device, dev_name(ar->dev)) __string(driver, dev_driver_string(ar->dev)) __field(unsigned int, level) - __dynamic_array(char, msg, ATH10K_MSG_MAX) + __vstring(msg, vaf->fmt, vaf->va) ), TP_fast_assign( __assign_str(device, dev_name(ar->dev)); __assign_str(driver, dev_driver_string(ar->dev)); __entry->level = level; - WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), - ATH10K_MSG_MAX, - vaf->fmt, - *vaf->va) >= ATH10K_MSG_MAX); + __assign_vstr(msg, vaf->fmt, vaf->va); ), TP_printk( "%s %s %s", diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 7c9ea0c073d8..da3bc35e41aa 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -43,6 +43,7 @@ out: int ath10k_txrx_tx_unref(struct ath10k_htt *htt, const struct htt_tx_done *tx_done) { + struct ieee80211_tx_status status; struct ath10k *ar = htt->ar; struct device *dev = ar->dev; struct ieee80211_tx_info *info; @@ -82,8 +83,6 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, flags = skb_cb->flags; ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); ath10k_htt_tx_dec_pending(htt); - if (htt->num_pending_tx == 0) - wake_up(&htt->empty_tx_wq); spin_unlock_bh(&htt->tx_lock); rcu_read_lock(); @@ -127,10 +126,22 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, tx_done->ack_rssi != ATH10K_INVALID_RSSI) { info->status.ack_signal = ATH10K_DEFAULT_NOISE_FLOOR + tx_done->ack_rssi; - info->status.is_valid_ack_signal = true; + info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; } - ieee80211_tx_status(htt->ar->hw, msdu); + memset(&status, 0, sizeof(status)); + status.skb = msdu; + status.info = info; + + rcu_read_lock(); + + if (txq) + status.sta = txq->sta; + + ieee80211_tx_status_ext(htt->ar->hw, &status); + + rcu_read_unlock(); + /* we do not own the msdu anymore */ return 0; diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c index 3d98f19c6ec8..b0067af685b1 100644 --- a/drivers/net/wireless/ath/ath10k/usb.c +++ b/drivers/net/wireless/ath/ath10k/usb.c @@ -345,6 +345,12 @@ static void ath10k_usb_rx_complete(struct ath10k *ar, struct sk_buff *skb) ep->ep_ops.ep_rx_complete(ar, skb); /* The RX complete handler now owns the skb... */ + if (test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags)) { + local_bh_disable(); + napi_schedule(&ar->napi); + local_bh_enable(); + } + return; out_free_skb: @@ -387,6 +393,7 @@ static int ath10k_usb_hif_start(struct ath10k *ar) int i; struct ath10k_usb *ar_usb = ath10k_usb_priv(ar); + ath10k_core_napi_enable(ar); ath10k_usb_start_recv_pipes(ar); /* set the TX resource avail threshold for each TX pipe */ @@ -462,6 +469,7 @@ err: static void ath10k_usb_hif_stop(struct ath10k *ar) { ath10k_usb_flush_all(ar); + ath10k_core_napi_sync_disable(ar); } static u16 ath10k_usb_hif_get_free_queue_number(struct ath10k *ar, u8 pipe_id) @@ -966,6 +974,20 @@ err: return ret; } +static int ath10k_usb_napi_poll(struct napi_struct *ctx, int budget) +{ + struct ath10k *ar = container_of(ctx, struct ath10k, napi); + int done; + + done = ath10k_htt_rx_hl_indication(ar, budget); + ath10k_dbg(ar, ATH10K_DBG_USB, "napi poll: done: %d, budget:%d\n", done, budget); + + if (done < budget) + napi_complete_done(ctx, done); + + return done; +} + /* ath10k usb driver registered functions */ static int ath10k_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) @@ -992,6 +1014,8 @@ static int ath10k_usb_probe(struct usb_interface *interface, return -ENOMEM; } + netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_usb_napi_poll); + usb_get_dev(dev); vendor_id = le16_to_cpu(dev->descriptor.idVendor); product_id = le16_to_cpu(dev->descriptor.idProduct); @@ -1013,6 +1037,7 @@ static int ath10k_usb_probe(struct usb_interface *interface, bus_params.dev_type = ATH10K_DEV_TYPE_HL; /* TODO: don't know yet how to get chip_id with USB */ bus_params.chip_id = 0; + bus_params.hl_msdu_ids = true; ret = ath10k_core_register(ar, &bus_params); if (ret) { ath10k_warn(ar, "failed to register driver core: %d\n", ret); @@ -1044,6 +1069,7 @@ static void ath10k_usb_remove(struct usb_interface *interface) return; ath10k_core_unregister(ar_usb->ar); + netif_napi_del(&ar_usb->ar->napi); ath10k_usb_destroy(ar_usb->ar); usb_put_dev(interface_to_usbdev(interface)); ath10k_core_destroy(ar_usb->ar); diff --git a/drivers/net/wireless/ath/ath10k/usb.h b/drivers/net/wireless/ath/ath10k/usb.h index 34d683e8fc18..48e066ba8162 100644 --- a/drivers/net/wireless/ath/ath10k/usb.h +++ b/drivers/net/wireless/ath/ath10k/usb.h @@ -26,7 +26,7 @@ #define ATH10K_USB_EP_ADDR_APP_DATA_MP_OUT 0x03 #define ATH10K_USB_EP_ADDR_APP_DATA_HP_OUT 0x04 -/* diagnostic command defnitions */ +/* diagnostic command definitions */ #define ATH10K_USB_CONTROL_REQ_SEND_BMI_CMD 1 #define ATH10K_USB_CONTROL_REQ_RECV_BMI_RESP 2 #define ATH10K_USB_CONTROL_REQ_DIAG_CMD 3 diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 7efbe03fbca8..876410a47d1d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -205,7 +205,7 @@ static int ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k *ar, } arvif = ath10k_get_arvif(ar, vdev_id); - if (arvif && arvif->is_up && arvif->vif->csa_active) + if (arvif && arvif->is_up && arvif->vif->bss_conf.csa_active) ieee80211_queue_work(ar->hw, &arvif->ap_csa_work); kfree(tb); diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index b39c9b78b32b..dbb48d70f2e9 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -1813,7 +1813,7 @@ struct wmi_tlv_pdev_get_temp_cmd { struct wmi_tlv_pdev_temperature_event { __le32 tlv_hdr; - /* temperature value in Celcius degree */ + /* temperature value in Celsius degree */ __le32 temperature; __le32 pdev_id; } __packed; @@ -2548,7 +2548,7 @@ struct nlo_channel_prediction_cfg { /* Preconfigured stationary threshold. * Lesser value means more conservative. Bigger value means more aggressive. - * Maximum is 100 and mininum is 0. + * Maximum is 100 and minimum is 0. */ __le32 stationary_threshold; diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 7c1c2658cb5f..980d4124fa28 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2427,7 +2427,7 @@ wmi_process_mgmt_tx_comp(struct ath10k *ar, struct mgmt_tx_compl_params *param) info->flags |= IEEE80211_TX_STAT_ACK; info->status.ack_signal = ATH10K_DEFAULT_NOISE_FLOOR + param->ack_rssi; - info->status.is_valid_ack_signal = true; + info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; } ieee80211_tx_status_irqsafe(ar->hw, msdu); @@ -3555,7 +3555,7 @@ static void ath10k_wmi_update_tim(struct ath10k *ar, __le32 t; u32 v, tim_len; - /* When FW reports 0 in tim_len, ensure atleast first byte + /* When FW reports 0 in tim_len, ensure at least first byte * in tim_bitmap is considered for pvm calculation. */ tim_len = tim_info->tim_len ? __le32_to_cpu(tim_info->tim_len) : 1; @@ -3882,13 +3882,13 @@ void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) * Once CSA counter is completed stop sending beacons until * actual channel switch is done */ - if (arvif->vif->csa_active && + if (arvif->vif->bss_conf.csa_active && ieee80211_beacon_cntdwn_is_complete(arvif->vif)) { ieee80211_csa_finish(arvif->vif); continue; } - bcn = ieee80211_beacon_get(ar->hw, arvif->vif); + bcn = ieee80211_beacon_get(ar->hw, arvif->vif, 0); if (!bcn) { ath10k_warn(ar, "could not get mac80211 beacon\n"); continue; diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 01bfd09a9d88..6de3cc4640a0 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -3170,7 +3170,7 @@ struct wmi_start_scan_common { /* dwell time in msec on passive channels */ __le32 dwell_time_passive; /* - * min time in msec on the BSS channel,only valid if atleast one + * min time in msec on the BSS channel,only valid if at least one * VDEV is active */ __le32 min_rest_time; @@ -3196,7 +3196,7 @@ struct wmi_start_scan_common { * and bssid_list */ __le32 repeat_probe_time; - /* time in msec between 2 consequetive probe requests with in a set. */ + /* time in msec between 2 consecutive probe requests with in a set. */ __le32 probe_spacing_time; /* * data inactivity time in msec on bss channel that will be used by @@ -3478,7 +3478,9 @@ struct wmi_phyerr_event { __le32 num_phyerrs; __le32 tsf_l32; __le32 tsf_u32; - struct wmi_phyerr phyerrs[]; + + /* array of struct wmi_phyerr */ + u8 phyerrs[]; } __packed; struct wmi_10_4_phyerr_event { @@ -4395,7 +4397,7 @@ struct wmi_pdev_stats_tx { /* wal pdev continuous xretry */ __le32 pdev_cont_xretry; - /* wal pdev continous xretry */ + /* wal pdev continuous xretry */ __le32 pdev_tx_timeout; /* wal pdev resets */ @@ -5238,7 +5240,7 @@ enum wmi_vdev_param { * scheduler. */ WMI_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, - /* enable/dsiable WDS for this VDEV */ + /* enable/disable WDS for this VDEV */ WMI_VDEV_PARAM_WDS, /* ATIM Window */ WMI_VDEV_PARAM_ATIM_WINDOW, @@ -5370,7 +5372,7 @@ enum wmi_10x_vdev_param { * scheduler. */ WMI_10X_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, - /* enable/dsiable WDS for this VDEV */ + /* enable/disable WDS for this VDEV */ WMI_10X_VDEV_PARAM_WDS, /* ATIM Window */ WMI_10X_VDEV_PARAM_ATIM_WINDOW, @@ -5902,7 +5904,7 @@ enum wmi_sta_ps_param_tx_wake_threshold { enum wmi_sta_ps_param_pspoll_count { WMI_STA_PS_PSPOLL_COUNT_NO_MAX = 0, /* - * Values greater than 0 indicate the maximum numer of PS-Poll frames + * Values greater than 0 indicate the maximum number of PS-Poll frames * FW will send before waking up. */ @@ -6945,7 +6947,7 @@ struct wmi_echo_ev_arg { }; struct wmi_pdev_temperature_event { - /* temperature value in Celcius degree */ + /* temperature value in Celsius degree */ __le32 temperature; } __packed; diff --git a/drivers/net/wireless/ath/ath10k/wow.c b/drivers/net/wireless/ath/ath10k/wow.c index 7d65c115669f..20b9aa8ddf7d 100644 --- a/drivers/net/wireless/ath/ath10k/wow.c +++ b/drivers/net/wireless/ath/ath10k/wow.c @@ -337,14 +337,15 @@ static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif, if (patterns[i].mask[j / 8] & BIT(j % 8)) bitmask[j] = 0xff; old_pattern.mask = bitmask; - new_pattern = old_pattern; if (ar->wmi.rx_decap_mode == ATH10K_HW_TXRX_NATIVE_WIFI) { - if (patterns[i].pkt_offset < ETH_HLEN) + if (patterns[i].pkt_offset < ETH_HLEN) { ath10k_wow_convert_8023_to_80211(&new_pattern, &old_pattern); - else + } else { + new_pattern = old_pattern; new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN; + } } if (WARN_ON(new_pattern.pattern_len > WOW_MAX_PATTERN_SIZE)) |