mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-21 20:13:58 +08:00
Merge ath-next from ath.git
ath.git patches for 4.7. Major changes: ath10k * implement set_tsf() for 10.2.4 branch * remove rare MSI range support * remove deprecated firmware API 1 support ath9k * add module parameter to invert LED polarity wcn36xx * fixes to get the driver properly working on Dragonboard 410c
This commit is contained in:
commit
efd7cef310
@ -1050,11 +1050,11 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
|
||||
*
|
||||
* For the lack of a better place do the check here.
|
||||
*/
|
||||
BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC >
|
||||
BUILD_BUG_ON(2 * TARGET_NUM_MSDU_DESC >
|
||||
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
|
||||
BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
|
||||
BUILD_BUG_ON(2 * TARGET_10X_NUM_MSDU_DESC >
|
||||
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
|
||||
BUILD_BUG_ON(2*TARGET_TLV_NUM_MSDU_DESC >
|
||||
BUILD_BUG_ON(2 * TARGET_TLV_NUM_MSDU_DESC >
|
||||
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
|
||||
|
||||
ce_state->ar = ar;
|
||||
|
@ -408,7 +408,7 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
|
||||
|
||||
/* Ring arithmetic (modulus number of entries in ring, which is a pwr of 2). */
|
||||
#define CE_RING_DELTA(nentries_mask, fromidx, toidx) \
|
||||
(((int)(toidx)-(int)(fromidx)) & (nentries_mask))
|
||||
(((int)(toidx) - (int)(fromidx)) & (nentries_mask))
|
||||
|
||||
#define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask))
|
||||
#define CE_RING_IDX_ADD(nentries_mask, idx, num) \
|
||||
|
@ -63,8 +63,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 2116,
|
||||
.fw = {
|
||||
.dir = QCA988X_HW_2_0_FW_DIR,
|
||||
.fw = QCA988X_HW_2_0_FW_FILE,
|
||||
.otp = QCA988X_HW_2_0_OTP_FILE,
|
||||
.board = QCA988X_HW_2_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA988X_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA988X_BOARD_EXT_DATA_SZ,
|
||||
@ -82,8 +80,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 8124,
|
||||
.fw = {
|
||||
.dir = QCA6174_HW_2_1_FW_DIR,
|
||||
.fw = QCA6174_HW_2_1_FW_FILE,
|
||||
.otp = QCA6174_HW_2_1_OTP_FILE,
|
||||
.board = QCA6174_HW_2_1_BOARD_DATA_FILE,
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
@ -102,8 +98,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 8124,
|
||||
.fw = {
|
||||
.dir = QCA6174_HW_2_1_FW_DIR,
|
||||
.fw = QCA6174_HW_2_1_FW_FILE,
|
||||
.otp = QCA6174_HW_2_1_OTP_FILE,
|
||||
.board = QCA6174_HW_2_1_BOARD_DATA_FILE,
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
@ -122,8 +116,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 8124,
|
||||
.fw = {
|
||||
.dir = QCA6174_HW_3_0_FW_DIR,
|
||||
.fw = QCA6174_HW_3_0_FW_FILE,
|
||||
.otp = QCA6174_HW_3_0_OTP_FILE,
|
||||
.board = QCA6174_HW_3_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
@ -143,8 +135,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.fw = {
|
||||
/* uses same binaries as hw3.0 */
|
||||
.dir = QCA6174_HW_3_0_FW_DIR,
|
||||
.fw = QCA6174_HW_3_0_FW_FILE,
|
||||
.otp = QCA6174_HW_3_0_OTP_FILE,
|
||||
.board = QCA6174_HW_3_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
@ -167,8 +157,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 12064,
|
||||
.fw = {
|
||||
.dir = QCA99X0_HW_2_0_FW_DIR,
|
||||
.fw = QCA99X0_HW_2_0_FW_FILE,
|
||||
.otp = QCA99X0_HW_2_0_OTP_FILE,
|
||||
.board = QCA99X0_HW_2_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA99X0_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
|
||||
@ -186,8 +174,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 8124,
|
||||
.fw = {
|
||||
.dir = QCA9377_HW_1_0_FW_DIR,
|
||||
.fw = QCA9377_HW_1_0_FW_FILE,
|
||||
.otp = QCA9377_HW_1_0_OTP_FILE,
|
||||
.board = QCA9377_HW_1_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA9377_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
|
||||
@ -205,8 +191,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 8124,
|
||||
.fw = {
|
||||
.dir = QCA9377_HW_1_0_FW_DIR,
|
||||
.fw = QCA9377_HW_1_0_FW_FILE,
|
||||
.otp = QCA9377_HW_1_0_OTP_FILE,
|
||||
.board = QCA9377_HW_1_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA9377_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
|
||||
@ -229,8 +213,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.cal_data_len = 12064,
|
||||
.fw = {
|
||||
.dir = QCA4019_HW_1_0_FW_DIR,
|
||||
.fw = QCA4019_HW_1_0_FW_FILE,
|
||||
.otp = QCA4019_HW_1_0_OTP_FILE,
|
||||
.board = QCA4019_HW_1_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA4019_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA4019_BOARD_EXT_DATA_SZ,
|
||||
@ -279,7 +261,7 @@ void ath10k_core_get_fw_features_str(struct ath10k *ar,
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ATH10K_FW_FEATURE_COUNT; i++) {
|
||||
if (test_bit(i, ar->fw_features)) {
|
||||
if (test_bit(i, ar->normal_mode_fw.fw_file.fw_features)) {
|
||||
if (len > 0)
|
||||
len += scnprintf(buf + len, buf_len - len, ",");
|
||||
|
||||
@ -556,7 +538,8 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
|
||||
|
||||
address = ar->hw_params.patch_load_addr;
|
||||
|
||||
if (!ar->otp_data || !ar->otp_len) {
|
||||
if (!ar->normal_mode_fw.fw_file.otp_data ||
|
||||
!ar->normal_mode_fw.fw_file.otp_len) {
|
||||
ath10k_warn(ar,
|
||||
"failed to retrieve board id because of invalid otp\n");
|
||||
return -ENODATA;
|
||||
@ -564,9 +547,11 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"boot upload otp to 0x%x len %zd for board id\n",
|
||||
address, ar->otp_len);
|
||||
address, ar->normal_mode_fw.fw_file.otp_len);
|
||||
|
||||
ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len);
|
||||
ret = ath10k_bmi_fast_download(ar, address,
|
||||
ar->normal_mode_fw.fw_file.otp_data,
|
||||
ar->normal_mode_fw.fw_file.otp_len);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "could not write otp for board id check: %d\n",
|
||||
ret);
|
||||
@ -604,7 +589,9 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
|
||||
u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param;
|
||||
int ret;
|
||||
|
||||
ret = ath10k_download_board_data(ar, ar->board_data, ar->board_len);
|
||||
ret = ath10k_download_board_data(ar,
|
||||
ar->running_fw->board_data,
|
||||
ar->running_fw->board_len);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to download board data: %d\n", ret);
|
||||
return ret;
|
||||
@ -612,16 +599,20 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
|
||||
|
||||
/* OTP is optional */
|
||||
|
||||
if (!ar->otp_data || !ar->otp_len) {
|
||||
if (!ar->running_fw->fw_file.otp_data ||
|
||||
!ar->running_fw->fw_file.otp_len) {
|
||||
ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %p otp_len %zd)!\n",
|
||||
ar->otp_data, ar->otp_len);
|
||||
ar->running_fw->fw_file.otp_data,
|
||||
ar->running_fw->fw_file.otp_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n",
|
||||
address, ar->otp_len);
|
||||
address, ar->running_fw->fw_file.otp_len);
|
||||
|
||||
ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len);
|
||||
ret = ath10k_bmi_fast_download(ar, address,
|
||||
ar->running_fw->fw_file.otp_data,
|
||||
ar->running_fw->fw_file.otp_len);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "could not write otp (%d)\n", ret);
|
||||
return ret;
|
||||
@ -636,7 +627,7 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
|
||||
|
||||
if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT,
|
||||
ar->fw_features)) &&
|
||||
ar->running_fw->fw_file.fw_features)) &&
|
||||
result != 0) {
|
||||
ath10k_err(ar, "otp calibration failed: %d", result);
|
||||
return -EINVAL;
|
||||
@ -645,46 +636,32 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
static int ath10k_download_fw(struct ath10k *ar)
|
||||
{
|
||||
u32 address, data_len;
|
||||
const char *mode_name;
|
||||
const void *data;
|
||||
int ret;
|
||||
|
||||
address = ar->hw_params.patch_load_addr;
|
||||
|
||||
switch (mode) {
|
||||
case ATH10K_FIRMWARE_MODE_NORMAL:
|
||||
data = ar->firmware_data;
|
||||
data_len = ar->firmware_len;
|
||||
mode_name = "normal";
|
||||
ret = ath10k_swap_code_seg_configure(ar,
|
||||
ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to configure fw code swap: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case ATH10K_FIRMWARE_MODE_UTF:
|
||||
data = ar->testmode.utf_firmware_data;
|
||||
data_len = ar->testmode.utf_firmware_len;
|
||||
mode_name = "utf";
|
||||
break;
|
||||
default:
|
||||
ath10k_err(ar, "unknown firmware mode: %d\n", mode);
|
||||
return -EINVAL;
|
||||
data = ar->running_fw->fw_file.firmware_data;
|
||||
data_len = ar->running_fw->fw_file.firmware_len;
|
||||
|
||||
ret = ath10k_swap_code_seg_configure(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to configure fw code swap: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"boot uploading firmware image %p len %d mode %s\n",
|
||||
data, data_len, mode_name);
|
||||
"boot uploading firmware image %p len %d\n",
|
||||
data, data_len);
|
||||
|
||||
ret = ath10k_bmi_fast_download(ar, address, data, data_len);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to download %s firmware: %d\n",
|
||||
mode_name, ret);
|
||||
ath10k_err(ar, "failed to download firmware: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -693,34 +670,30 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
|
||||
static void ath10k_core_free_board_files(struct ath10k *ar)
|
||||
{
|
||||
if (!IS_ERR(ar->board))
|
||||
release_firmware(ar->board);
|
||||
if (!IS_ERR(ar->normal_mode_fw.board))
|
||||
release_firmware(ar->normal_mode_fw.board);
|
||||
|
||||
ar->board = NULL;
|
||||
ar->board_data = NULL;
|
||||
ar->board_len = 0;
|
||||
ar->normal_mode_fw.board = NULL;
|
||||
ar->normal_mode_fw.board_data = NULL;
|
||||
ar->normal_mode_fw.board_len = 0;
|
||||
}
|
||||
|
||||
static void ath10k_core_free_firmware_files(struct ath10k *ar)
|
||||
{
|
||||
if (!IS_ERR(ar->otp))
|
||||
release_firmware(ar->otp);
|
||||
|
||||
if (!IS_ERR(ar->firmware))
|
||||
release_firmware(ar->firmware);
|
||||
if (!IS_ERR(ar->normal_mode_fw.fw_file.firmware))
|
||||
release_firmware(ar->normal_mode_fw.fw_file.firmware);
|
||||
|
||||
if (!IS_ERR(ar->cal_file))
|
||||
release_firmware(ar->cal_file);
|
||||
|
||||
ath10k_swap_code_seg_release(ar);
|
||||
|
||||
ar->otp = NULL;
|
||||
ar->otp_data = NULL;
|
||||
ar->otp_len = 0;
|
||||
ar->normal_mode_fw.fw_file.otp_data = NULL;
|
||||
ar->normal_mode_fw.fw_file.otp_len = 0;
|
||||
|
||||
ar->firmware = NULL;
|
||||
ar->firmware_data = NULL;
|
||||
ar->firmware_len = 0;
|
||||
ar->normal_mode_fw.fw_file.firmware = NULL;
|
||||
ar->normal_mode_fw.fw_file.firmware_data = NULL;
|
||||
ar->normal_mode_fw.fw_file.firmware_len = 0;
|
||||
|
||||
ar->cal_file = NULL;
|
||||
}
|
||||
@ -759,14 +732,14 @@ static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ar->board = ath10k_fetch_fw_file(ar,
|
||||
ar->hw_params.fw.dir,
|
||||
ar->hw_params.fw.board);
|
||||
if (IS_ERR(ar->board))
|
||||
return PTR_ERR(ar->board);
|
||||
ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
|
||||
ar->hw_params.fw.dir,
|
||||
ar->hw_params.fw.board);
|
||||
if (IS_ERR(ar->normal_mode_fw.board))
|
||||
return PTR_ERR(ar->normal_mode_fw.board);
|
||||
|
||||
ar->board_data = ar->board->data;
|
||||
ar->board_len = ar->board->size;
|
||||
ar->normal_mode_fw.board_data = ar->normal_mode_fw.board->data;
|
||||
ar->normal_mode_fw.board_len = ar->normal_mode_fw.board->size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -826,8 +799,8 @@ static int ath10k_core_parse_bd_ie_board(struct ath10k *ar,
|
||||
"boot found board data for '%s'",
|
||||
boardname);
|
||||
|
||||
ar->board_data = board_ie_data;
|
||||
ar->board_len = board_ie_len;
|
||||
ar->normal_mode_fw.board_data = board_ie_data;
|
||||
ar->normal_mode_fw.board_len = board_ie_len;
|
||||
|
||||
ret = 0;
|
||||
goto out;
|
||||
@ -860,12 +833,14 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
|
||||
const u8 *data;
|
||||
int ret, ie_id;
|
||||
|
||||
ar->board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, filename);
|
||||
if (IS_ERR(ar->board))
|
||||
return PTR_ERR(ar->board);
|
||||
ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
|
||||
ar->hw_params.fw.dir,
|
||||
filename);
|
||||
if (IS_ERR(ar->normal_mode_fw.board))
|
||||
return PTR_ERR(ar->normal_mode_fw.board);
|
||||
|
||||
data = ar->board->data;
|
||||
len = ar->board->size;
|
||||
data = ar->normal_mode_fw.board->data;
|
||||
len = ar->normal_mode_fw.board->size;
|
||||
|
||||
/* magic has extra null byte padded */
|
||||
magic_len = strlen(ATH10K_BOARD_MAGIC) + 1;
|
||||
@ -932,7 +907,7 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
|
||||
}
|
||||
|
||||
out:
|
||||
if (!ar->board_data || !ar->board_len) {
|
||||
if (!ar->normal_mode_fw.board_data || !ar->normal_mode_fw.board_len) {
|
||||
ath10k_err(ar,
|
||||
"failed to fetch board data for %s from %s/%s\n",
|
||||
boardname, ar->hw_params.fw.dir, filename);
|
||||
@ -1000,51 +975,8 @@ success:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (ar->hw_params.fw.fw == NULL) {
|
||||
ath10k_err(ar, "firmware file not defined\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ar->firmware = ath10k_fetch_fw_file(ar,
|
||||
ar->hw_params.fw.dir,
|
||||
ar->hw_params.fw.fw);
|
||||
if (IS_ERR(ar->firmware)) {
|
||||
ret = PTR_ERR(ar->firmware);
|
||||
ath10k_err(ar, "could not fetch firmware (%d)\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ar->firmware_data = ar->firmware->data;
|
||||
ar->firmware_len = ar->firmware->size;
|
||||
|
||||
/* OTP may be undefined. If so, don't fetch it at all */
|
||||
if (ar->hw_params.fw.otp == NULL)
|
||||
return 0;
|
||||
|
||||
ar->otp = ath10k_fetch_fw_file(ar,
|
||||
ar->hw_params.fw.dir,
|
||||
ar->hw_params.fw.otp);
|
||||
if (IS_ERR(ar->otp)) {
|
||||
ret = PTR_ERR(ar->otp);
|
||||
ath10k_err(ar, "could not fetch otp (%d)\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ar->otp_data = ar->otp->data;
|
||||
ar->otp_len = ar->otp->size;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
ath10k_core_free_firmware_files(ar);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
|
||||
int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
|
||||
struct ath10k_fw_file *fw_file)
|
||||
{
|
||||
size_t magic_len, len, ie_len;
|
||||
int ie_id, i, index, bit, ret;
|
||||
@ -1053,15 +985,17 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
|
||||
__le32 *timestamp, *version;
|
||||
|
||||
/* first fetch the firmware file (firmware-*.bin) */
|
||||
ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name);
|
||||
if (IS_ERR(ar->firmware)) {
|
||||
fw_file->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,
|
||||
name);
|
||||
if (IS_ERR(fw_file->firmware)) {
|
||||
ath10k_err(ar, "could not fetch firmware file '%s/%s': %ld\n",
|
||||
ar->hw_params.fw.dir, name, PTR_ERR(ar->firmware));
|
||||
return PTR_ERR(ar->firmware);
|
||||
ar->hw_params.fw.dir, name,
|
||||
PTR_ERR(fw_file->firmware));
|
||||
return PTR_ERR(fw_file->firmware);
|
||||
}
|
||||
|
||||
data = ar->firmware->data;
|
||||
len = ar->firmware->size;
|
||||
data = fw_file->firmware->data;
|
||||
len = fw_file->firmware->size;
|
||||
|
||||
/* magic also includes the null byte, check that as well */
|
||||
magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;
|
||||
@ -1104,15 +1038,15 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
|
||||
|
||||
switch (ie_id) {
|
||||
case ATH10K_FW_IE_FW_VERSION:
|
||||
if (ie_len > sizeof(ar->hw->wiphy->fw_version) - 1)
|
||||
if (ie_len > sizeof(fw_file->fw_version) - 1)
|
||||
break;
|
||||
|
||||
memcpy(ar->hw->wiphy->fw_version, data, ie_len);
|
||||
ar->hw->wiphy->fw_version[ie_len] = '\0';
|
||||
memcpy(fw_file->fw_version, data, ie_len);
|
||||
fw_file->fw_version[ie_len] = '\0';
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"found fw version %s\n",
|
||||
ar->hw->wiphy->fw_version);
|
||||
fw_file->fw_version);
|
||||
break;
|
||||
case ATH10K_FW_IE_TIMESTAMP:
|
||||
if (ie_len != sizeof(u32))
|
||||
@ -1139,21 +1073,21 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"Enabling feature bit: %i\n",
|
||||
i);
|
||||
__set_bit(i, ar->fw_features);
|
||||
__set_bit(i, fw_file->fw_features);
|
||||
}
|
||||
}
|
||||
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_BOOT, "features", "",
|
||||
ar->fw_features,
|
||||
sizeof(ar->fw_features));
|
||||
ar->running_fw->fw_file.fw_features,
|
||||
sizeof(fw_file->fw_features));
|
||||
break;
|
||||
case ATH10K_FW_IE_FW_IMAGE:
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"found fw image ie (%zd B)\n",
|
||||
ie_len);
|
||||
|
||||
ar->firmware_data = data;
|
||||
ar->firmware_len = ie_len;
|
||||
fw_file->firmware_data = data;
|
||||
fw_file->firmware_len = ie_len;
|
||||
|
||||
break;
|
||||
case ATH10K_FW_IE_OTP_IMAGE:
|
||||
@ -1161,8 +1095,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
|
||||
"found otp image ie (%zd B)\n",
|
||||
ie_len);
|
||||
|
||||
ar->otp_data = data;
|
||||
ar->otp_len = ie_len;
|
||||
fw_file->otp_data = data;
|
||||
fw_file->otp_len = ie_len;
|
||||
|
||||
break;
|
||||
case ATH10K_FW_IE_WMI_OP_VERSION:
|
||||
@ -1171,10 +1105,10 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
|
||||
|
||||
version = (__le32 *)data;
|
||||
|
||||
ar->wmi.op_version = le32_to_cpup(version);
|
||||
fw_file->wmi_op_version = le32_to_cpup(version);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie wmi op version %d\n",
|
||||
ar->wmi.op_version);
|
||||
fw_file->wmi_op_version);
|
||||
break;
|
||||
case ATH10K_FW_IE_HTT_OP_VERSION:
|
||||
if (ie_len != sizeof(u32))
|
||||
@ -1182,17 +1116,17 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
|
||||
|
||||
version = (__le32 *)data;
|
||||
|
||||
ar->htt.op_version = le32_to_cpup(version);
|
||||
fw_file->htt_op_version = le32_to_cpup(version);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie htt op version %d\n",
|
||||
ar->htt.op_version);
|
||||
fw_file->htt_op_version);
|
||||
break;
|
||||
case ATH10K_FW_IE_FW_CODE_SWAP_IMAGE:
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"found fw code swap image ie (%zd B)\n",
|
||||
ie_len);
|
||||
ar->swap.firmware_codeswap_data = data;
|
||||
ar->swap.firmware_codeswap_len = ie_len;
|
||||
fw_file->codeswap_data = data;
|
||||
fw_file->codeswap_len = ie_len;
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "Unknown FW IE: %u\n",
|
||||
@ -1207,7 +1141,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
|
||||
data += ie_len;
|
||||
}
|
||||
|
||||
if (!ar->firmware_data || !ar->firmware_len) {
|
||||
if (!fw_file->firmware_data ||
|
||||
!fw_file->firmware_len) {
|
||||
ath10k_warn(ar, "No ATH10K_FW_IE_FW_IMAGE found from '%s/%s', skipping\n",
|
||||
ar->hw_params.fw.dir, name);
|
||||
ret = -ENOMEDIUM;
|
||||
@ -1231,35 +1166,32 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
|
||||
ar->fw_api = 5;
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
|
||||
|
||||
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API5_FILE);
|
||||
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API5_FILE,
|
||||
&ar->normal_mode_fw.fw_file);
|
||||
if (ret == 0)
|
||||
goto success;
|
||||
|
||||
ar->fw_api = 4;
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
|
||||
|
||||
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API4_FILE);
|
||||
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API4_FILE,
|
||||
&ar->normal_mode_fw.fw_file);
|
||||
if (ret == 0)
|
||||
goto success;
|
||||
|
||||
ar->fw_api = 3;
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
|
||||
|
||||
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE);
|
||||
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE,
|
||||
&ar->normal_mode_fw.fw_file);
|
||||
if (ret == 0)
|
||||
goto success;
|
||||
|
||||
ar->fw_api = 2;
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
|
||||
|
||||
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE);
|
||||
if (ret == 0)
|
||||
goto success;
|
||||
|
||||
ar->fw_api = 1;
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
|
||||
|
||||
ret = ath10k_core_fetch_firmware_api_1(ar);
|
||||
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE,
|
||||
&ar->normal_mode_fw.fw_file);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -1497,15 +1429,17 @@ static void ath10k_core_restart(struct work_struct *work)
|
||||
|
||||
static int ath10k_core_init_firmware_features(struct ath10k *ar)
|
||||
{
|
||||
if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features) &&
|
||||
!test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
|
||||
struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file;
|
||||
|
||||
if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, fw_file->fw_features) &&
|
||||
!test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) {
|
||||
ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ar->wmi.op_version >= ATH10K_FW_WMI_OP_VERSION_MAX) {
|
||||
if (fw_file->wmi_op_version >= ATH10K_FW_WMI_OP_VERSION_MAX) {
|
||||
ath10k_err(ar, "unsupported WMI OP version (max %d): %d\n",
|
||||
ATH10K_FW_WMI_OP_VERSION_MAX, ar->wmi.op_version);
|
||||
ATH10K_FW_WMI_OP_VERSION_MAX, fw_file->wmi_op_version);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1517,7 +1451,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
|
||||
break;
|
||||
case ATH10K_CRYPT_MODE_SW:
|
||||
if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,
|
||||
ar->fw_features)) {
|
||||
fw_file->fw_features)) {
|
||||
ath10k_err(ar, "cryptmode > 0 requires raw mode support from firmware");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1536,7 +1470,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
|
||||
|
||||
if (rawmode) {
|
||||
if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,
|
||||
ar->fw_features)) {
|
||||
fw_file->fw_features)) {
|
||||
ath10k_err(ar, "rawmode = 1 requires support from firmware");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1561,19 +1495,19 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
|
||||
/* Backwards compatibility for firmwares without
|
||||
* ATH10K_FW_IE_WMI_OP_VERSION.
|
||||
*/
|
||||
if (ar->wmi.op_version == ATH10K_FW_WMI_OP_VERSION_UNSET) {
|
||||
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
|
||||
if (fw_file->wmi_op_version == ATH10K_FW_WMI_OP_VERSION_UNSET) {
|
||||
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) {
|
||||
if (test_bit(ATH10K_FW_FEATURE_WMI_10_2,
|
||||
ar->fw_features))
|
||||
ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_2;
|
||||
fw_file->fw_features))
|
||||
fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_2;
|
||||
else
|
||||
ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
|
||||
fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
|
||||
} else {
|
||||
ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_MAIN;
|
||||
fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_MAIN;
|
||||
}
|
||||
}
|
||||
|
||||
switch (ar->wmi.op_version) {
|
||||
switch (fw_file->wmi_op_version) {
|
||||
case ATH10K_FW_WMI_OP_VERSION_MAIN:
|
||||
ar->max_num_peers = TARGET_NUM_PEERS;
|
||||
ar->max_num_stations = TARGET_NUM_STATIONS;
|
||||
@ -1620,7 +1554,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
|
||||
ar->max_spatial_stream = ar->hw_params.max_spatial_stream;
|
||||
|
||||
if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
|
||||
ar->fw_features))
|
||||
fw_file->fw_features))
|
||||
ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC_PFC;
|
||||
else
|
||||
ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC;
|
||||
@ -1634,18 +1568,18 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
|
||||
/* Backwards compatibility for firmwares without
|
||||
* ATH10K_FW_IE_HTT_OP_VERSION.
|
||||
*/
|
||||
if (ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_UNSET) {
|
||||
switch (ar->wmi.op_version) {
|
||||
if (fw_file->htt_op_version == ATH10K_FW_HTT_OP_VERSION_UNSET) {
|
||||
switch (fw_file->wmi_op_version) {
|
||||
case ATH10K_FW_WMI_OP_VERSION_MAIN:
|
||||
ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_MAIN;
|
||||
fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_MAIN;
|
||||
break;
|
||||
case ATH10K_FW_WMI_OP_VERSION_10_1:
|
||||
case ATH10K_FW_WMI_OP_VERSION_10_2:
|
||||
case ATH10K_FW_WMI_OP_VERSION_10_2_4:
|
||||
ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_10_1;
|
||||
fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_10_1;
|
||||
break;
|
||||
case ATH10K_FW_WMI_OP_VERSION_TLV:
|
||||
ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_TLV;
|
||||
fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_TLV;
|
||||
break;
|
||||
case ATH10K_FW_WMI_OP_VERSION_10_4:
|
||||
case ATH10K_FW_WMI_OP_VERSION_UNSET:
|
||||
@ -1658,7 +1592,8 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
const struct ath10k_fw_components *fw)
|
||||
{
|
||||
int status;
|
||||
u32 val;
|
||||
@ -1667,6 +1602,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
|
||||
clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
|
||||
|
||||
ar->running_fw = fw;
|
||||
|
||||
ath10k_bmi_start(ar);
|
||||
|
||||
if (ath10k_init_configure_target(ar)) {
|
||||
@ -1685,7 +1622,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
* to set the clock source once the target is initialized.
|
||||
*/
|
||||
if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT,
|
||||
ar->fw_features)) {
|
||||
ar->running_fw->fw_file.fw_features)) {
|
||||
status = ath10k_bmi_write32(ar, hi_skip_clock_init, 1);
|
||||
if (status) {
|
||||
ath10k_err(ar, "could not write to skip_clock_init: %d\n",
|
||||
@ -1694,7 +1631,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
}
|
||||
}
|
||||
|
||||
status = ath10k_download_fw(ar, mode);
|
||||
status = ath10k_download_fw(ar);
|
||||
if (status)
|
||||
goto err;
|
||||
|
||||
@ -1787,8 +1724,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
if (ath10k_peer_stats_enabled(ar))
|
||||
val = WMI_10_4_PEER_STATS;
|
||||
|
||||
status = ath10k_wmi_ext_resource_config(ar,
|
||||
WMI_HOST_PLATFORM_HIGH_PERF, val);
|
||||
status = ath10k_mac_ext_resource_config(ar, val);
|
||||
if (status) {
|
||||
ath10k_err(ar,
|
||||
"failed to send ext resource cfg command : %d\n",
|
||||
@ -1931,6 +1867,11 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
|
||||
goto err_power_down;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(sizeof(ar->hw->wiphy->fw_version) !=
|
||||
sizeof(ar->normal_mode_fw.fw_file.fw_version));
|
||||
memcpy(ar->hw->wiphy->fw_version, ar->normal_mode_fw.fw_file.fw_version,
|
||||
sizeof(ar->hw->wiphy->fw_version));
|
||||
|
||||
ath10k_debug_print_hwfw_info(ar);
|
||||
|
||||
ret = ath10k_core_pre_cal_download(ar);
|
||||
@ -1973,7 +1914,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
|
||||
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL,
|
||||
&ar->normal_mode_fw);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "could not init core (%d)\n", ret);
|
||||
goto err_unlock;
|
||||
|
@ -44,8 +44,8 @@
|
||||
|
||||
#define ATH10K_SCAN_ID 0
|
||||
#define WMI_READY_TIMEOUT (5 * HZ)
|
||||
#define ATH10K_FLUSH_TIMEOUT_HZ (5*HZ)
|
||||
#define ATH10K_CONNECTION_LOSS_HZ (3*HZ)
|
||||
#define ATH10K_FLUSH_TIMEOUT_HZ (5 * HZ)
|
||||
#define ATH10K_CONNECTION_LOSS_HZ (3 * HZ)
|
||||
#define ATH10K_NUM_CHANS 39
|
||||
|
||||
/* Antenna noise floor */
|
||||
@ -139,7 +139,6 @@ struct ath10k_mem_chunk {
|
||||
};
|
||||
|
||||
struct ath10k_wmi {
|
||||
enum ath10k_fw_wmi_op_version op_version;
|
||||
enum ath10k_htc_ep_id eid;
|
||||
struct completion service_ready;
|
||||
struct completion unified_ready;
|
||||
@ -334,7 +333,7 @@ struct ath10k_sta {
|
||||
#endif
|
||||
};
|
||||
|
||||
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ)
|
||||
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ)
|
||||
|
||||
enum ath10k_beacon_state {
|
||||
ATH10K_BEACON_SCHEDULED = 0,
|
||||
@ -627,6 +626,34 @@ enum ath10k_tx_pause_reason {
|
||||
ATH10K_TX_PAUSE_MAX,
|
||||
};
|
||||
|
||||
struct ath10k_fw_file {
|
||||
const struct firmware *firmware;
|
||||
|
||||
char fw_version[ETHTOOL_FWVERS_LEN];
|
||||
|
||||
DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT);
|
||||
|
||||
enum ath10k_fw_wmi_op_version wmi_op_version;
|
||||
enum ath10k_fw_htt_op_version htt_op_version;
|
||||
|
||||
const void *firmware_data;
|
||||
size_t firmware_len;
|
||||
|
||||
const void *otp_data;
|
||||
size_t otp_len;
|
||||
|
||||
const void *codeswap_data;
|
||||
size_t codeswap_len;
|
||||
};
|
||||
|
||||
struct ath10k_fw_components {
|
||||
const struct firmware *board;
|
||||
const void *board_data;
|
||||
size_t board_len;
|
||||
|
||||
struct ath10k_fw_file fw_file;
|
||||
};
|
||||
|
||||
struct ath10k {
|
||||
struct ath_common ath_common;
|
||||
struct ieee80211_hw *hw;
|
||||
@ -652,8 +679,6 @@ struct ath10k {
|
||||
/* protected by conf_mutex */
|
||||
bool ani_enabled;
|
||||
|
||||
DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT);
|
||||
|
||||
bool p2p;
|
||||
|
||||
struct {
|
||||
@ -708,32 +733,24 @@ struct ath10k {
|
||||
|
||||
struct ath10k_hw_params_fw {
|
||||
const char *dir;
|
||||
const char *fw;
|
||||
const char *otp;
|
||||
const char *board;
|
||||
size_t board_size;
|
||||
size_t board_ext_size;
|
||||
} fw;
|
||||
} hw_params;
|
||||
|
||||
const struct firmware *board;
|
||||
const void *board_data;
|
||||
size_t board_len;
|
||||
/* contains the firmware images used with ATH10K_FIRMWARE_MODE_NORMAL */
|
||||
struct ath10k_fw_components normal_mode_fw;
|
||||
|
||||
const struct firmware *otp;
|
||||
const void *otp_data;
|
||||
size_t otp_len;
|
||||
|
||||
const struct firmware *firmware;
|
||||
const void *firmware_data;
|
||||
size_t firmware_len;
|
||||
/* READ-ONLY images of the running firmware, which can be either
|
||||
* normal or UTF. Do not modify, release etc!
|
||||
*/
|
||||
const struct ath10k_fw_components *running_fw;
|
||||
|
||||
const struct firmware *pre_cal_file;
|
||||
const struct firmware *cal_file;
|
||||
|
||||
struct {
|
||||
const void *firmware_codeswap_data;
|
||||
size_t firmware_codeswap_len;
|
||||
struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info;
|
||||
} swap;
|
||||
|
||||
@ -879,13 +896,8 @@ struct ath10k {
|
||||
|
||||
struct {
|
||||
/* protected by conf_mutex */
|
||||
const struct firmware *utf;
|
||||
char utf_version[32];
|
||||
const void *utf_firmware_data;
|
||||
size_t utf_firmware_len;
|
||||
DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);
|
||||
enum ath10k_fw_wmi_op_version orig_wmi_op_version;
|
||||
enum ath10k_fw_wmi_op_version op_version;
|
||||
struct ath10k_fw_components utf_mode_fw;
|
||||
|
||||
/* protected by data_lock */
|
||||
bool utf_monitor;
|
||||
} testmode;
|
||||
@ -921,8 +933,11 @@ void ath10k_core_destroy(struct ath10k *ar);
|
||||
void ath10k_core_get_fw_features_str(struct ath10k *ar,
|
||||
char *buf,
|
||||
size_t max_len);
|
||||
int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
|
||||
struct ath10k_fw_file *fw_file);
|
||||
|
||||
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode);
|
||||
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
const struct ath10k_fw_components *fw_components);
|
||||
int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
|
||||
void ath10k_core_stop(struct ath10k *ar);
|
||||
int ath10k_core_register(struct ath10k *ar, u32 chip_id);
|
||||
|
@ -126,6 +126,7 @@ EXPORT_SYMBOL(ath10k_info);
|
||||
|
||||
void ath10k_debug_print_hwfw_info(struct ath10k *ar)
|
||||
{
|
||||
const struct firmware *firmware;
|
||||
char fw_features[128] = {};
|
||||
u32 crc = 0;
|
||||
|
||||
@ -144,8 +145,9 @@ void ath10k_debug_print_hwfw_info(struct ath10k *ar)
|
||||
config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
|
||||
config_enabled(CONFIG_NL80211_TESTMODE));
|
||||
|
||||
if (ar->firmware)
|
||||
crc = crc32_le(0, ar->firmware->data, ar->firmware->size);
|
||||
firmware = ar->normal_mode_fw.fw_file.firmware;
|
||||
if (firmware)
|
||||
crc = crc32_le(0, firmware->data, firmware->size);
|
||||
|
||||
ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n",
|
||||
ar->hw->wiphy->fw_version,
|
||||
@ -167,7 +169,8 @@ void ath10k_debug_print_board_info(struct ath10k *ar)
|
||||
ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x",
|
||||
ar->bd_api,
|
||||
boardinfo,
|
||||
crc32_le(0, ar->board->data, ar->board->size));
|
||||
crc32_le(0, ar->normal_mode_fw.board->data,
|
||||
ar->normal_mode_fw.board->size));
|
||||
}
|
||||
|
||||
void ath10k_debug_print_boot_info(struct ath10k *ar)
|
||||
@ -175,8 +178,8 @@ void ath10k_debug_print_boot_info(struct ath10k *ar)
|
||||
ath10k_info(ar, "htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d\n",
|
||||
ar->htt.target_version_major,
|
||||
ar->htt.target_version_minor,
|
||||
ar->wmi.op_version,
|
||||
ar->htt.op_version,
|
||||
ar->normal_mode_fw.fw_file.wmi_op_version,
|
||||
ar->normal_mode_fw.fw_file.htt_op_version,
|
||||
ath10k_cal_mode_str(ar->cal_mode),
|
||||
ar->max_num_stations,
|
||||
test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
|
||||
@ -2122,7 +2125,7 @@ static ssize_t ath10k_write_btcoex(struct file *file,
|
||||
struct ath10k *ar = file->private_data;
|
||||
char buf[32];
|
||||
size_t buf_size;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
bool val;
|
||||
|
||||
buf_size = min(count, (sizeof(buf) - 1));
|
||||
@ -2142,8 +2145,10 @@ static ssize_t ath10k_write_btcoex(struct file *file,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val))
|
||||
if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val)) {
|
||||
ret = count;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (val)
|
||||
set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
|
||||
@ -2189,7 +2194,7 @@ static ssize_t ath10k_write_peer_stats(struct file *file,
|
||||
struct ath10k *ar = file->private_data;
|
||||
char buf[32];
|
||||
size_t buf_size;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
bool val;
|
||||
|
||||
buf_size = min(count, (sizeof(buf) - 1));
|
||||
@ -2209,8 +2214,10 @@ static ssize_t ath10k_write_peer_stats(struct file *file,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val))
|
||||
if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val)) {
|
||||
ret = count;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (val)
|
||||
set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
|
||||
@ -2266,23 +2273,28 @@ static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"firmware-N.bin\t\t%08x\n",
|
||||
crc32_le(0, ar->firmware->data, ar->firmware->size));
|
||||
crc32_le(0, ar->normal_mode_fw.fw_file.firmware->data,
|
||||
ar->normal_mode_fw.fw_file.firmware->size));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"athwlan\t\t\t%08x\n",
|
||||
crc32_le(0, ar->firmware_data, ar->firmware_len));
|
||||
crc32_le(0, ar->normal_mode_fw.fw_file.firmware_data,
|
||||
ar->normal_mode_fw.fw_file.firmware_len));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"otp\t\t\t%08x\n",
|
||||
crc32_le(0, ar->otp_data, ar->otp_len));
|
||||
crc32_le(0, ar->normal_mode_fw.fw_file.otp_data,
|
||||
ar->normal_mode_fw.fw_file.otp_len));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"codeswap\t\t%08x\n",
|
||||
crc32_le(0, ar->swap.firmware_codeswap_data,
|
||||
ar->swap.firmware_codeswap_len));
|
||||
crc32_le(0, ar->normal_mode_fw.fw_file.codeswap_data,
|
||||
ar->normal_mode_fw.fw_file.codeswap_len));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"board-N.bin\t\t%08x\n",
|
||||
crc32_le(0, ar->board->data, ar->board->size));
|
||||
crc32_le(0, ar->normal_mode_fw.board->data,
|
||||
ar->normal_mode_fw.board->size));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"board\t\t\t%08x\n",
|
||||
crc32_le(0, ar->board_data, ar->board_len));
|
||||
crc32_le(0, ar->normal_mode_fw.board_data,
|
||||
ar->normal_mode_fw.board_len));
|
||||
|
||||
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
|
||||
|
@ -57,7 +57,7 @@ enum ath10k_dbg_aggr_mode {
|
||||
};
|
||||
|
||||
/* FIXME: How to calculate the buffer size sanely? */
|
||||
#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
|
||||
#define ATH10K_FW_STATS_BUF_SIZE (1024 * 1024)
|
||||
|
||||
extern unsigned int ath10k_debug_mask;
|
||||
|
||||
|
@ -297,10 +297,10 @@ struct ath10k_htc_svc_conn_resp {
|
||||
#define ATH10K_NUM_CONTROL_TX_BUFFERS 2
|
||||
#define ATH10K_HTC_MAX_LEN 4096
|
||||
#define ATH10K_HTC_MAX_CTRL_MSG_LEN 256
|
||||
#define ATH10K_HTC_WAIT_TIMEOUT_HZ (1*HZ)
|
||||
#define ATH10K_HTC_WAIT_TIMEOUT_HZ (1 * HZ)
|
||||
#define ATH10K_HTC_CONTROL_BUFFER_SIZE (ATH10K_HTC_MAX_CTRL_MSG_LEN + \
|
||||
sizeof(struct ath10k_htc_hdr))
|
||||
#define ATH10K_HTC_CONN_SVC_TIMEOUT_HZ (1*HZ)
|
||||
#define ATH10K_HTC_CONN_SVC_TIMEOUT_HZ (1 * HZ)
|
||||
|
||||
struct ath10k_htc_ep {
|
||||
struct ath10k_htc *htc;
|
||||
|
@ -183,7 +183,7 @@ int ath10k_htt_init(struct ath10k *ar)
|
||||
8 + /* llc snap */
|
||||
2; /* ip4 dscp or ip6 priority */
|
||||
|
||||
switch (ar->htt.op_version) {
|
||||
switch (ar->running_fw->fw_file.htt_op_version) {
|
||||
case ATH10K_FW_HTT_OP_VERSION_10_4:
|
||||
ar->htt.t2h_msg_types = htt_10_4_t2h_msg_types;
|
||||
ar->htt.t2h_msg_types_max = HTT_10_4_T2H_NUM_MSGS;
|
||||
@ -208,7 +208,7 @@ int ath10k_htt_init(struct ath10k *ar)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define HTT_TARGET_VERSION_TIMEOUT_HZ (3*HZ)
|
||||
#define HTT_TARGET_VERSION_TIMEOUT_HZ (3 * HZ)
|
||||
|
||||
static int ath10k_htt_verify_version(struct ath10k_htt *htt)
|
||||
{
|
||||
|
@ -1475,10 +1475,10 @@ union htt_rx_pn_t {
|
||||
u32 pn24;
|
||||
|
||||
/* TKIP or CCMP: 48-bit PN */
|
||||
u_int64_t pn48;
|
||||
u64 pn48;
|
||||
|
||||
/* WAPI: 128-bit PN */
|
||||
u_int64_t pn128[2];
|
||||
u64 pn128[2];
|
||||
};
|
||||
|
||||
struct htt_cmd {
|
||||
@ -1562,7 +1562,6 @@ struct ath10k_htt {
|
||||
u8 target_version_major;
|
||||
u8 target_version_minor;
|
||||
struct completion target_version_received;
|
||||
enum ath10k_fw_htt_op_version op_version;
|
||||
u8 max_num_amsdu;
|
||||
u8 max_num_ampdu;
|
||||
|
||||
|
@ -966,7 +966,7 @@ static int ath10k_htt_rx_nwifi_hdrlen(struct ath10k *ar,
|
||||
int len = ieee80211_hdrlen(hdr->frame_control);
|
||||
|
||||
if (!test_bit(ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING,
|
||||
ar->fw_features))
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
len = round_up(len, 4);
|
||||
|
||||
return len;
|
||||
|
@ -267,7 +267,8 @@ static void ath10k_htt_tx_free_txq(struct ath10k_htt *htt)
|
||||
struct ath10k *ar = htt->ar;
|
||||
size_t size;
|
||||
|
||||
if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features))
|
||||
if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
return;
|
||||
|
||||
size = sizeof(*htt->tx_q_state.vaddr);
|
||||
@ -282,7 +283,8 @@ static int ath10k_htt_tx_alloc_txq(struct ath10k_htt *htt)
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features))
|
||||
if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
return 0;
|
||||
|
||||
htt->tx_q_state.num_peers = HTT_TX_Q_STATE_NUM_PEERS;
|
||||
@ -513,7 +515,8 @@ int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt)
|
||||
info |= SM(htt->tx_q_state.type,
|
||||
HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE);
|
||||
|
||||
if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features))
|
||||
if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
info |= HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_VALID;
|
||||
|
||||
cfg = &cmd->frag_desc_bank_cfg;
|
||||
|
@ -35,8 +35,6 @@
|
||||
#define QCA988X_HW_2_0_VERSION 0x4100016c
|
||||
#define QCA988X_HW_2_0_CHIP_ID_REV 0x2
|
||||
#define QCA988X_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA988X/hw2.0"
|
||||
#define QCA988X_HW_2_0_FW_FILE "firmware.bin"
|
||||
#define QCA988X_HW_2_0_OTP_FILE "otp.bin"
|
||||
#define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
@ -76,14 +74,10 @@ enum qca9377_chip_id_rev {
|
||||
};
|
||||
|
||||
#define QCA6174_HW_2_1_FW_DIR "ath10k/QCA6174/hw2.1"
|
||||
#define QCA6174_HW_2_1_FW_FILE "firmware.bin"
|
||||
#define QCA6174_HW_2_1_OTP_FILE "otp.bin"
|
||||
#define QCA6174_HW_2_1_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA6174_HW_2_1_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
#define QCA6174_HW_3_0_FW_DIR "ath10k/QCA6174/hw3.0"
|
||||
#define QCA6174_HW_3_0_FW_FILE "firmware.bin"
|
||||
#define QCA6174_HW_3_0_OTP_FILE "otp.bin"
|
||||
#define QCA6174_HW_3_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA6174_HW_3_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
@ -94,23 +88,17 @@ enum qca9377_chip_id_rev {
|
||||
#define QCA99X0_HW_2_0_DEV_VERSION 0x01000000
|
||||
#define QCA99X0_HW_2_0_CHIP_ID_REV 0x1
|
||||
#define QCA99X0_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA99X0/hw2.0"
|
||||
#define QCA99X0_HW_2_0_FW_FILE "firmware.bin"
|
||||
#define QCA99X0_HW_2_0_OTP_FILE "otp.bin"
|
||||
#define QCA99X0_HW_2_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA99X0_HW_2_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9377 1.0 definitions */
|
||||
#define QCA9377_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9377/hw1.0"
|
||||
#define QCA9377_HW_1_0_FW_FILE "firmware.bin"
|
||||
#define QCA9377_HW_1_0_OTP_FILE "otp.bin"
|
||||
#define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA9377_HW_1_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA4019 1.0 definitions */
|
||||
#define QCA4019_HW_1_0_DEV_VERSION 0x01000000
|
||||
#define QCA4019_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA4019/hw1.0"
|
||||
#define QCA4019_HW_1_0_FW_FILE "firmware.bin"
|
||||
#define QCA4019_HW_1_0_OTP_FILE "otp.bin"
|
||||
#define QCA4019_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA4019_HW_1_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
|
@ -157,6 +157,26 @@ ath10k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ath10k_mac_ext_resource_config(struct ath10k *ar, u32 val)
|
||||
{
|
||||
enum wmi_host_platform_type platform_type;
|
||||
int ret;
|
||||
|
||||
if (test_bit(WMI_SERVICE_TX_MODE_DYNAMIC, ar->wmi.svc_map))
|
||||
platform_type = WMI_HOST_PLATFORM_LOW_PERF;
|
||||
else
|
||||
platform_type = WMI_HOST_PLATFORM_HIGH_PERF;
|
||||
|
||||
ret = ath10k_wmi_ext_resource_config(ar, platform_type, val);
|
||||
|
||||
if (ret && ret != -EOPNOTSUPP) {
|
||||
ath10k_warn(ar, "failed to configure ext resource: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********/
|
||||
/* Crypto */
|
||||
/**********/
|
||||
@ -449,10 +469,10 @@ static int ath10k_mac_vif_update_wep_key(struct ath10k_vif *arvif,
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
list_for_each_entry(peer, &ar->peers, list) {
|
||||
if (!memcmp(peer->addr, arvif->vif->addr, ETH_ALEN))
|
||||
if (ether_addr_equal(peer->addr, arvif->vif->addr))
|
||||
continue;
|
||||
|
||||
if (!memcmp(peer->addr, arvif->bssid, ETH_ALEN))
|
||||
if (ether_addr_equal(peer->addr, arvif->bssid))
|
||||
continue;
|
||||
|
||||
if (peer->keys[key->keyidx] == key)
|
||||
@ -1752,7 +1772,7 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
|
||||
|
||||
if (enable_ps && ath10k_mac_num_vifs_started(ar) > 1 &&
|
||||
!test_bit(ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT,
|
||||
ar->fw_features)) {
|
||||
ar->running_fw->fw_file.fw_features)) {
|
||||
ath10k_warn(ar, "refusing to enable ps on vdev %i: not supported by fw\n",
|
||||
arvif->vdev_id);
|
||||
enable_ps = false;
|
||||
@ -2040,7 +2060,8 @@ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
|
||||
}
|
||||
|
||||
if (sta->mfp &&
|
||||
test_bit(ATH10K_FW_FEATURE_MFP_SUPPORT, ar->fw_features)) {
|
||||
test_bit(ATH10K_FW_FEATURE_MFP_SUPPORT,
|
||||
ar->running_fw->fw_file.fw_features)) {
|
||||
arg->peer_flags |= ar->wmi.peer_flags->pmf;
|
||||
}
|
||||
}
|
||||
@ -3187,7 +3208,8 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
|
||||
*/
|
||||
if (ar->htt.target_version_major < 3 &&
|
||||
(ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)) &&
|
||||
!test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, ar->fw_features))
|
||||
!test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
return ATH10K_HW_TXRX_MGMT;
|
||||
|
||||
/* Workaround:
|
||||
@ -3337,7 +3359,7 @@ bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar)
|
||||
*/
|
||||
return (ar->htt.target_version_major >= 3 &&
|
||||
ar->htt.target_version_minor >= 4 &&
|
||||
ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_TLV);
|
||||
ar->running_fw->fw_file.htt_op_version == ATH10K_FW_HTT_OP_VERSION_TLV);
|
||||
}
|
||||
|
||||
static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb)
|
||||
@ -3374,7 +3396,7 @@ ath10k_mac_tx_h_get_txpath(struct ath10k *ar,
|
||||
return ATH10K_MAC_TX_HTT;
|
||||
case ATH10K_HW_TXRX_MGMT:
|
||||
if (test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
|
||||
ar->fw_features))
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
return ATH10K_MAC_TX_WMI_MGMT;
|
||||
else if (ar->htt.target_version_major >= 3)
|
||||
return ATH10K_MAC_TX_HTT;
|
||||
@ -3846,7 +3868,7 @@ static int ath10k_scan_stop(struct ath10k *ar)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_timeout(&ar->scan.completed, 3*HZ);
|
||||
ret = wait_for_completion_timeout(&ar->scan.completed, 3 * HZ);
|
||||
if (ret == 0) {
|
||||
ath10k_warn(ar, "failed to receive scan abortion completion: timed out\n");
|
||||
ret = -ETIMEDOUT;
|
||||
@ -3926,7 +3948,7 @@ static int ath10k_start_scan(struct ath10k *ar,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = wait_for_completion_timeout(&ar->scan.started, 1*HZ);
|
||||
ret = wait_for_completion_timeout(&ar->scan.started, 1 * HZ);
|
||||
if (ret == 0) {
|
||||
ret = ath10k_scan_stop(ar);
|
||||
if (ret)
|
||||
@ -4356,7 +4378,8 @@ static int ath10k_start(struct ieee80211_hw *hw)
|
||||
goto err_off;
|
||||
}
|
||||
|
||||
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
|
||||
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL,
|
||||
&ar->normal_mode_fw);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "Could not init core: %d\n", ret);
|
||||
goto err_power_down;
|
||||
@ -4414,7 +4437,7 @@ static int ath10k_start(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA,
|
||||
ar->fw_features)) {
|
||||
ar->running_fw->fw_file.fw_features)) {
|
||||
ret = ath10k_wmi_pdev_enable_adaptive_cca(ar, 1,
|
||||
WMI_CCA_DETECT_LEVEL_AUTO,
|
||||
WMI_CCA_DETECT_MARGIN_AUTO);
|
||||
@ -6168,7 +6191,7 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define ATH10K_ROC_TIMEOUT_HZ (2*HZ)
|
||||
#define ATH10K_ROC_TIMEOUT_HZ (2 * HZ)
|
||||
|
||||
static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
@ -6232,7 +6255,7 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_timeout(&ar->scan.on_channel, 3*HZ);
|
||||
ret = wait_for_completion_timeout(&ar->scan.on_channel, 3 * HZ);
|
||||
if (ret == 0) {
|
||||
ath10k_warn(ar, "failed to switch to channel for roc scan\n");
|
||||
|
||||
@ -6796,6 +6819,32 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
u64 tsf)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
|
||||
u32 tsf_offset, vdev_param = ar->wmi.vdev_param->set_tsf;
|
||||
int ret;
|
||||
|
||||
/* Workaround:
|
||||
*
|
||||
* Given tsf argument is entire TSF value, but firmware accepts
|
||||
* only TSF offset to current TSF.
|
||||
*
|
||||
* get_tsf function is used to get offset value, however since
|
||||
* ath10k_get_tsf is not implemented properly, it will return 0 always.
|
||||
* Luckily all the caller functions to set_tsf, as of now, also rely on
|
||||
* get_tsf function to get entire tsf value such get_tsf() + tsf_delta,
|
||||
* final tsf offset value to firmware will be arithmetically correct.
|
||||
*/
|
||||
tsf_offset = tsf - ath10k_get_tsf(hw, vif);
|
||||
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
|
||||
vdev_param, tsf_offset);
|
||||
if (ret && ret != -EOPNOTSUPP)
|
||||
ath10k_warn(ar, "failed to set tsf offset: %d\n", ret);
|
||||
}
|
||||
|
||||
static int ath10k_ampdu_action(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_ampdu_params *params)
|
||||
@ -6867,7 +6916,13 @@ ath10k_mac_update_rx_channel(struct ath10k *ar,
|
||||
def = &vifs[0].new_ctx->def;
|
||||
|
||||
ar->rx_channel = def->chan;
|
||||
} else if (ctx && ath10k_mac_num_chanctxs(ar) == 0) {
|
||||
} else if ((ctx && ath10k_mac_num_chanctxs(ar) == 0) ||
|
||||
(ctx && (ar->state == ATH10K_STATE_RESTARTED))) {
|
||||
/* During driver restart due to firmware assert, since mac80211
|
||||
* already has valid channel context for given radio, channel
|
||||
* context iteration return num_chanctx > 0. So fix rx_channel
|
||||
* when restart is in progress.
|
||||
*/
|
||||
ar->rx_channel = ctx->def.chan;
|
||||
} else {
|
||||
ar->rx_channel = NULL;
|
||||
@ -7252,6 +7307,7 @@ static const struct ieee80211_ops ath10k_ops = {
|
||||
.set_bitrate_mask = ath10k_mac_op_set_bitrate_mask,
|
||||
.sta_rc_update = ath10k_sta_rc_update,
|
||||
.get_tsf = ath10k_get_tsf,
|
||||
.set_tsf = ath10k_set_tsf,
|
||||
.ampdu_action = ath10k_ampdu_action,
|
||||
.get_et_sset_count = ath10k_debug_get_et_sset_count,
|
||||
.get_et_stats = ath10k_debug_get_et_stats,
|
||||
@ -7640,7 +7696,7 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
ar->hw->wiphy->available_antennas_rx = ar->cfg_rx_chainmask;
|
||||
ar->hw->wiphy->available_antennas_tx = ar->cfg_tx_chainmask;
|
||||
|
||||
if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features))
|
||||
if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->normal_mode_fw.fw_file.fw_features))
|
||||
ar->hw->wiphy->interface_modes |=
|
||||
BIT(NL80211_IFTYPE_P2P_DEVICE) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
@ -7730,7 +7786,7 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
*/
|
||||
ar->hw->offchannel_tx_hw_queue = IEEE80211_MAX_QUEUES - 1;
|
||||
|
||||
switch (ar->wmi.op_version) {
|
||||
switch (ar->running_fw->fw_file.wmi_op_version) {
|
||||
case ATH10K_FW_WMI_OP_VERSION_MAIN:
|
||||
ar->hw->wiphy->iface_combinations = ath10k_if_comb;
|
||||
ar->hw->wiphy->n_iface_combinations =
|
||||
|
@ -81,6 +81,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
|
||||
struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar,
|
||||
u16 peer_id,
|
||||
u8 tid);
|
||||
int ath10k_mac_ext_resource_config(struct ath10k *ar, u32 val);
|
||||
|
||||
static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
|
||||
{
|
||||
|
@ -33,12 +33,6 @@
|
||||
#include "ce.h"
|
||||
#include "pci.h"
|
||||
|
||||
enum ath10k_pci_irq_mode {
|
||||
ATH10K_PCI_IRQ_AUTO = 0,
|
||||
ATH10K_PCI_IRQ_LEGACY = 1,
|
||||
ATH10K_PCI_IRQ_MSI = 2,
|
||||
};
|
||||
|
||||
enum ath10k_pci_reset_mode {
|
||||
ATH10K_PCI_RESET_AUTO = 0,
|
||||
ATH10K_PCI_RESET_WARM_ONLY = 1,
|
||||
@ -745,10 +739,7 @@ static inline const char *ath10k_pci_get_irq_method(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
||||
if (ar_pci->num_msi_intrs > 1)
|
||||
return "msi-x";
|
||||
|
||||
if (ar_pci->num_msi_intrs == 1)
|
||||
if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_MSI)
|
||||
return "msi";
|
||||
|
||||
return "legacy";
|
||||
@ -1502,13 +1493,8 @@ void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe,
|
||||
void ath10k_pci_kill_tasklet(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
int i;
|
||||
|
||||
tasklet_kill(&ar_pci->intr_tq);
|
||||
tasklet_kill(&ar_pci->msi_fw_err);
|
||||
|
||||
for (i = 0; i < CE_COUNT; i++)
|
||||
tasklet_kill(&ar_pci->pipe_info[i].intr);
|
||||
|
||||
del_timer_sync(&ar_pci->rx_post_retry);
|
||||
}
|
||||
@ -1624,10 +1610,8 @@ static void ath10k_pci_irq_disable(struct ath10k *ar)
|
||||
static void ath10k_pci_irq_sync(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
|
||||
synchronize_irq(ar_pci->pdev->irq + i);
|
||||
synchronize_irq(ar_pci->pdev->irq);
|
||||
}
|
||||
|
||||
static void ath10k_pci_irq_enable(struct ath10k *ar)
|
||||
@ -2596,65 +2580,6 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static void ath10k_pci_ce_tasklet(unsigned long ptr)
|
||||
{
|
||||
struct ath10k_pci_pipe *pipe = (struct ath10k_pci_pipe *)ptr;
|
||||
struct ath10k_pci *ar_pci = pipe->ar_pci;
|
||||
|
||||
ath10k_ce_per_engine_service(ar_pci->ar, pipe->pipe_num);
|
||||
}
|
||||
|
||||
static void ath10k_msi_err_tasklet(unsigned long data)
|
||||
{
|
||||
struct ath10k *ar = (struct ath10k *)data;
|
||||
|
||||
if (!ath10k_pci_has_fw_crashed(ar)) {
|
||||
ath10k_warn(ar, "received unsolicited fw crash interrupt\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ath10k_pci_irq_disable(ar);
|
||||
ath10k_pci_fw_crashed_clear(ar);
|
||||
ath10k_pci_fw_crashed_dump(ar);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for a per-engine interrupt on a PARTICULAR CE.
|
||||
* This is used in cases where each CE has a private MSI interrupt.
|
||||
*/
|
||||
static irqreturn_t ath10k_pci_per_engine_handler(int irq, void *arg)
|
||||
{
|
||||
struct ath10k *ar = arg;
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
int ce_id = irq - ar_pci->pdev->irq - MSI_ASSIGN_CE_INITIAL;
|
||||
|
||||
if (ce_id < 0 || ce_id >= ARRAY_SIZE(ar_pci->pipe_info)) {
|
||||
ath10k_warn(ar, "unexpected/invalid irq %d ce_id %d\n", irq,
|
||||
ce_id);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: We are able to derive ce_id from irq because we
|
||||
* use a one-to-one mapping for CE's 0..5.
|
||||
* CE's 6 & 7 do not use interrupts at all.
|
||||
*
|
||||
* This mapping must be kept in sync with the mapping
|
||||
* used by firmware.
|
||||
*/
|
||||
tasklet_schedule(&ar_pci->pipe_info[ce_id].intr);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t ath10k_pci_msi_fw_handler(int irq, void *arg)
|
||||
{
|
||||
struct ath10k *ar = arg;
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
||||
tasklet_schedule(&ar_pci->msi_fw_err);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Top-level interrupt handler for all PCI interrupts from a Target.
|
||||
* When a block of MSI interrupts is allocated, this top-level handler
|
||||
@ -2672,7 +2597,7 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg)
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
if (ar_pci->num_msi_intrs == 0) {
|
||||
if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY) {
|
||||
if (!ath10k_pci_irq_pending(ar))
|
||||
return IRQ_NONE;
|
||||
|
||||
@ -2699,43 +2624,10 @@ static void ath10k_pci_tasklet(unsigned long data)
|
||||
ath10k_ce_per_engine_service_any(ar);
|
||||
|
||||
/* Re-enable legacy irq that was disabled in the irq handler */
|
||||
if (ar_pci->num_msi_intrs == 0)
|
||||
if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY)
|
||||
ath10k_pci_enable_legacy_irq(ar);
|
||||
}
|
||||
|
||||
static int ath10k_pci_request_irq_msix(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
int ret, i;
|
||||
|
||||
ret = request_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW,
|
||||
ath10k_pci_msi_fw_handler,
|
||||
IRQF_SHARED, "ath10k_pci", ar);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to request MSI-X fw irq %d: %d\n",
|
||||
ar_pci->pdev->irq + MSI_ASSIGN_FW, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = MSI_ASSIGN_CE_INITIAL; i <= MSI_ASSIGN_CE_MAX; i++) {
|
||||
ret = request_irq(ar_pci->pdev->irq + i,
|
||||
ath10k_pci_per_engine_handler,
|
||||
IRQF_SHARED, "ath10k_pci", ar);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to request MSI-X ce irq %d: %d\n",
|
||||
ar_pci->pdev->irq + i, ret);
|
||||
|
||||
for (i--; i >= MSI_ASSIGN_CE_INITIAL; i--)
|
||||
free_irq(ar_pci->pdev->irq + i, ar);
|
||||
|
||||
free_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW, ar);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_pci_request_irq_msi(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
@ -2774,41 +2666,28 @@ static int ath10k_pci_request_irq(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
||||
switch (ar_pci->num_msi_intrs) {
|
||||
case 0:
|
||||
switch (ar_pci->oper_irq_mode) {
|
||||
case ATH10K_PCI_IRQ_LEGACY:
|
||||
return ath10k_pci_request_irq_legacy(ar);
|
||||
case 1:
|
||||
case ATH10K_PCI_IRQ_MSI:
|
||||
return ath10k_pci_request_irq_msi(ar);
|
||||
default:
|
||||
return ath10k_pci_request_irq_msix(ar);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath10k_pci_free_irq(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
int i;
|
||||
|
||||
/* There's at least one interrupt irregardless whether its legacy INTR
|
||||
* or MSI or MSI-X */
|
||||
for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
|
||||
free_irq(ar_pci->pdev->irq + i, ar);
|
||||
free_irq(ar_pci->pdev->irq, ar);
|
||||
}
|
||||
|
||||
void ath10k_pci_init_irq_tasklets(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
int i;
|
||||
|
||||
tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long)ar);
|
||||
tasklet_init(&ar_pci->msi_fw_err, ath10k_msi_err_tasklet,
|
||||
(unsigned long)ar);
|
||||
|
||||
for (i = 0; i < CE_COUNT; i++) {
|
||||
ar_pci->pipe_info[i].ar_pci = ar_pci;
|
||||
tasklet_init(&ar_pci->pipe_info[i].intr, ath10k_pci_ce_tasklet,
|
||||
(unsigned long)&ar_pci->pipe_info[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int ath10k_pci_init_irq(struct ath10k *ar)
|
||||
@ -2822,20 +2701,9 @@ static int ath10k_pci_init_irq(struct ath10k *ar)
|
||||
ath10k_info(ar, "limiting irq mode to: %d\n",
|
||||
ath10k_pci_irq_mode);
|
||||
|
||||
/* Try MSI-X */
|
||||
if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO) {
|
||||
ar_pci->num_msi_intrs = MSI_ASSIGN_CE_MAX + 1;
|
||||
ret = pci_enable_msi_range(ar_pci->pdev, ar_pci->num_msi_intrs,
|
||||
ar_pci->num_msi_intrs);
|
||||
if (ret > 0)
|
||||
return 0;
|
||||
|
||||
/* fall-through */
|
||||
}
|
||||
|
||||
/* Try MSI */
|
||||
if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_LEGACY) {
|
||||
ar_pci->num_msi_intrs = 1;
|
||||
ar_pci->oper_irq_mode = ATH10K_PCI_IRQ_MSI;
|
||||
ret = pci_enable_msi(ar_pci->pdev);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
@ -2851,7 +2719,7 @@ static int ath10k_pci_init_irq(struct ath10k *ar)
|
||||
* This write might get lost if target has NOT written BAR.
|
||||
* For now, fix the race by repeating the write in below
|
||||
* synchronization checking. */
|
||||
ar_pci->num_msi_intrs = 0;
|
||||
ar_pci->oper_irq_mode = ATH10K_PCI_IRQ_LEGACY;
|
||||
|
||||
ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS,
|
||||
PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL);
|
||||
@ -2869,8 +2737,8 @@ static int ath10k_pci_deinit_irq(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
||||
switch (ar_pci->num_msi_intrs) {
|
||||
case 0:
|
||||
switch (ar_pci->oper_irq_mode) {
|
||||
case ATH10K_PCI_IRQ_LEGACY:
|
||||
ath10k_pci_deinit_irq_legacy(ar);
|
||||
break;
|
||||
default:
|
||||
@ -2908,7 +2776,7 @@ int ath10k_pci_wait_for_target_init(struct ath10k *ar)
|
||||
if (val & FW_IND_INITIALIZED)
|
||||
break;
|
||||
|
||||
if (ar_pci->num_msi_intrs == 0)
|
||||
if (ar_pci->oper_irq_mode == ATH10K_PCI_IRQ_LEGACY)
|
||||
/* Fix potential race by repeating CORE_BASE writes */
|
||||
ath10k_pci_enable_legacy_irq(ar);
|
||||
|
||||
@ -3186,8 +3054,8 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
goto err_sleep;
|
||||
}
|
||||
|
||||
ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n",
|
||||
ath10k_pci_get_irq_method(ar), ar_pci->num_msi_intrs,
|
||||
ath10k_info(ar, "pci irq %s oper_irq_mode %d irq_mode %d reset_mode %d\n",
|
||||
ath10k_pci_get_irq_method(ar), ar_pci->oper_irq_mode,
|
||||
ath10k_pci_irq_mode, ath10k_pci_reset_mode);
|
||||
|
||||
ret = ath10k_pci_request_irq(ar);
|
||||
@ -3305,7 +3173,6 @@ MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
/* QCA988x 2.0 firmware files */
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API2_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API3_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API4_FILE);
|
||||
|
@ -148,9 +148,6 @@ struct ath10k_pci_pipe {
|
||||
|
||||
/* protects compl_free and num_send_allowed */
|
||||
spinlock_t pipe_lock;
|
||||
|
||||
struct ath10k_pci *ar_pci;
|
||||
struct tasklet_struct intr;
|
||||
};
|
||||
|
||||
struct ath10k_pci_supp_chip {
|
||||
@ -164,6 +161,12 @@ struct ath10k_bus_ops {
|
||||
int (*get_num_banks)(struct ath10k *ar);
|
||||
};
|
||||
|
||||
enum ath10k_pci_irq_mode {
|
||||
ATH10K_PCI_IRQ_AUTO = 0,
|
||||
ATH10K_PCI_IRQ_LEGACY = 1,
|
||||
ATH10K_PCI_IRQ_MSI = 2,
|
||||
};
|
||||
|
||||
struct ath10k_pci {
|
||||
struct pci_dev *pdev;
|
||||
struct device *dev;
|
||||
@ -171,14 +174,10 @@ struct ath10k_pci {
|
||||
void __iomem *mem;
|
||||
size_t mem_len;
|
||||
|
||||
/*
|
||||
* Number of MSI interrupts granted, 0 --> using legacy PCI line
|
||||
* interrupts.
|
||||
*/
|
||||
int num_msi_intrs;
|
||||
/* Operating interrupt mode */
|
||||
enum ath10k_pci_irq_mode oper_irq_mode;
|
||||
|
||||
struct tasklet_struct intr_tq;
|
||||
struct tasklet_struct msi_fw_err;
|
||||
|
||||
struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX];
|
||||
|
||||
|
@ -134,27 +134,17 @@ ath10k_swap_code_seg_alloc(struct ath10k *ar, size_t swap_bin_len)
|
||||
return seg_info;
|
||||
}
|
||||
|
||||
int ath10k_swap_code_seg_configure(struct ath10k *ar,
|
||||
enum ath10k_swap_code_seg_bin_type type)
|
||||
int ath10k_swap_code_seg_configure(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
struct ath10k_swap_code_seg_info *seg_info = NULL;
|
||||
|
||||
switch (type) {
|
||||
case ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW:
|
||||
if (!ar->swap.firmware_swap_code_seg_info)
|
||||
return 0;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot found firmware code swap binary\n");
|
||||
seg_info = ar->swap.firmware_swap_code_seg_info;
|
||||
break;
|
||||
default:
|
||||
case ATH10K_SWAP_CODE_SEG_BIN_TYPE_OTP:
|
||||
case ATH10K_SWAP_CODE_SEG_BIN_TYPE_UTF:
|
||||
ath10k_warn(ar, "ignoring unknown code swap binary type %d\n",
|
||||
type);
|
||||
if (!ar->swap.firmware_swap_code_seg_info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot found firmware code swap binary\n");
|
||||
|
||||
seg_info = ar->swap.firmware_swap_code_seg_info;
|
||||
|
||||
ret = ath10k_bmi_write_memory(ar, seg_info->target_addr,
|
||||
&seg_info->seg_hw_info,
|
||||
@ -171,8 +161,13 @@ int ath10k_swap_code_seg_configure(struct ath10k *ar,
|
||||
void ath10k_swap_code_seg_release(struct ath10k *ar)
|
||||
{
|
||||
ath10k_swap_code_seg_free(ar, ar->swap.firmware_swap_code_seg_info);
|
||||
ar->swap.firmware_codeswap_data = NULL;
|
||||
ar->swap.firmware_codeswap_len = 0;
|
||||
|
||||
/* FIXME: these two assignments look to bein wrong place! Shouldn't
|
||||
* they be in ath10k_core_free_firmware_files() like the rest?
|
||||
*/
|
||||
ar->normal_mode_fw.fw_file.codeswap_data = NULL;
|
||||
ar->normal_mode_fw.fw_file.codeswap_len = 0;
|
||||
|
||||
ar->swap.firmware_swap_code_seg_info = NULL;
|
||||
}
|
||||
|
||||
@ -180,20 +175,23 @@ int ath10k_swap_code_seg_init(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
struct ath10k_swap_code_seg_info *seg_info;
|
||||
const void *codeswap_data;
|
||||
size_t codeswap_len;
|
||||
|
||||
if (!ar->swap.firmware_codeswap_len || !ar->swap.firmware_codeswap_data)
|
||||
codeswap_data = ar->normal_mode_fw.fw_file.codeswap_data;
|
||||
codeswap_len = ar->normal_mode_fw.fw_file.codeswap_len;
|
||||
|
||||
if (!codeswap_len || !codeswap_data)
|
||||
return 0;
|
||||
|
||||
seg_info = ath10k_swap_code_seg_alloc(ar,
|
||||
ar->swap.firmware_codeswap_len);
|
||||
seg_info = ath10k_swap_code_seg_alloc(ar, codeswap_len);
|
||||
if (!seg_info) {
|
||||
ath10k_err(ar, "failed to allocate fw code swap segment\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = ath10k_swap_code_seg_fill(ar, seg_info,
|
||||
ar->swap.firmware_codeswap_data,
|
||||
ar->swap.firmware_codeswap_len);
|
||||
codeswap_data, codeswap_len);
|
||||
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to initialize fw code swap segment: %d\n",
|
||||
|
@ -39,12 +39,6 @@ union ath10k_swap_code_seg_item {
|
||||
struct ath10k_swap_code_seg_tail tail;
|
||||
} __packed;
|
||||
|
||||
enum ath10k_swap_code_seg_bin_type {
|
||||
ATH10K_SWAP_CODE_SEG_BIN_TYPE_OTP,
|
||||
ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW,
|
||||
ATH10K_SWAP_CODE_SEG_BIN_TYPE_UTF,
|
||||
};
|
||||
|
||||
struct ath10k_swap_code_seg_hw_info {
|
||||
/* Swap binary image size */
|
||||
__le32 swap_size;
|
||||
@ -64,8 +58,7 @@ struct ath10k_swap_code_seg_info {
|
||||
dma_addr_t paddr[ATH10K_SWAP_CODE_SEG_NUM_SUPPORTED];
|
||||
};
|
||||
|
||||
int ath10k_swap_code_seg_configure(struct ath10k *ar,
|
||||
enum ath10k_swap_code_seg_bin_type type);
|
||||
int ath10k_swap_code_seg_configure(struct ath10k *ar);
|
||||
void ath10k_swap_code_seg_release(struct ath10k *ar);
|
||||
int ath10k_swap_code_seg_init(struct ath10k *ar);
|
||||
|
||||
|
@ -438,7 +438,7 @@ Fw Mode/SubMode Mask
|
||||
((HOST_INTEREST->hi_pwr_save_flags & HI_PWR_SAVE_LPL_ENABLED))
|
||||
#define HI_DEV_LPL_TYPE_GET(_devix) \
|
||||
(HOST_INTEREST->hi_pwr_save_flags & ((HI_PWR_SAVE_LPL_DEV_MASK) << \
|
||||
(HI_PWR_SAVE_LPL_DEV0_LSB + (_devix)*2)))
|
||||
(HI_PWR_SAVE_LPL_DEV0_LSB + (_devix) * 2)))
|
||||
|
||||
#define HOST_INTEREST_SMPS_IS_ALLOWED() \
|
||||
((HOST_INTEREST->hi_smps_options & HI_SMPS_ALLOW_MASK))
|
||||
|
@ -139,127 +139,8 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
|
||||
return cfg80211_testmode_reply(skb);
|
||||
}
|
||||
|
||||
static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar)
|
||||
{
|
||||
size_t len, magic_len, ie_len;
|
||||
struct ath10k_fw_ie *hdr;
|
||||
char filename[100];
|
||||
__le32 *version;
|
||||
const u8 *data;
|
||||
int ie_id, ret;
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s/%s",
|
||||
ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE);
|
||||
|
||||
/* load utf firmware image */
|
||||
ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
|
||||
filename, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
data = ar->testmode.utf->data;
|
||||
len = ar->testmode.utf->size;
|
||||
|
||||
/* FIXME: call release_firmware() in error cases */
|
||||
|
||||
/* magic also includes the null byte, check that as well */
|
||||
magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;
|
||||
|
||||
if (len < magic_len) {
|
||||
ath10k_err(ar, "utf firmware file is too small to contain magic\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) {
|
||||
ath10k_err(ar, "invalid firmware magic\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* jump over the padding */
|
||||
magic_len = ALIGN(magic_len, 4);
|
||||
|
||||
len -= magic_len;
|
||||
data += magic_len;
|
||||
|
||||
/* loop elements */
|
||||
while (len > sizeof(struct ath10k_fw_ie)) {
|
||||
hdr = (struct ath10k_fw_ie *)data;
|
||||
|
||||
ie_id = le32_to_cpu(hdr->id);
|
||||
ie_len = le32_to_cpu(hdr->len);
|
||||
|
||||
len -= sizeof(*hdr);
|
||||
data += sizeof(*hdr);
|
||||
|
||||
if (len < ie_len) {
|
||||
ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n",
|
||||
ie_id, len, ie_len);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (ie_id) {
|
||||
case ATH10K_FW_IE_FW_VERSION:
|
||||
if (ie_len > sizeof(ar->testmode.utf_version) - 1)
|
||||
break;
|
||||
|
||||
memcpy(ar->testmode.utf_version, data, ie_len);
|
||||
ar->testmode.utf_version[ie_len] = '\0';
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
|
||||
"testmode found fw utf version %s\n",
|
||||
ar->testmode.utf_version);
|
||||
break;
|
||||
case ATH10K_FW_IE_TIMESTAMP:
|
||||
/* ignore timestamp, but don't warn about it either */
|
||||
break;
|
||||
case ATH10K_FW_IE_FW_IMAGE:
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
|
||||
"testmode found fw image ie (%zd B)\n",
|
||||
ie_len);
|
||||
|
||||
ar->testmode.utf_firmware_data = data;
|
||||
ar->testmode.utf_firmware_len = ie_len;
|
||||
break;
|
||||
case ATH10K_FW_IE_WMI_OP_VERSION:
|
||||
if (ie_len != sizeof(u32))
|
||||
break;
|
||||
version = (__le32 *)data;
|
||||
ar->testmode.op_version = le32_to_cpup(version);
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw ie wmi op version %d\n",
|
||||
ar->testmode.op_version);
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "Unknown testmode FW IE: %u\n",
|
||||
le32_to_cpu(hdr->id));
|
||||
break;
|
||||
}
|
||||
/* jump over the padding */
|
||||
ie_len = ALIGN(ie_len, 4);
|
||||
|
||||
len -= ie_len;
|
||||
data += ie_len;
|
||||
}
|
||||
|
||||
if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) {
|
||||
ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
release_firmware(ar->testmode.utf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar)
|
||||
static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar,
|
||||
struct ath10k_fw_file *fw_file)
|
||||
{
|
||||
char filename[100];
|
||||
int ret;
|
||||
@ -268,7 +149,7 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar)
|
||||
ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
|
||||
|
||||
/* load utf firmware image */
|
||||
ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
|
||||
ret = request_firmware(&fw_file->firmware, filename, ar->dev);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
|
||||
filename, ret);
|
||||
@ -281,24 +162,27 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar)
|
||||
* correct WMI interface.
|
||||
*/
|
||||
|
||||
ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
|
||||
ar->testmode.utf_firmware_data = ar->testmode.utf->data;
|
||||
ar->testmode.utf_firmware_len = ar->testmode.utf->size;
|
||||
fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
|
||||
fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_10_1;
|
||||
fw_file->firmware_data = fw_file->firmware->data;
|
||||
fw_file->firmware_len = fw_file->firmware->size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_tm_fetch_firmware(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_fw_components *utf_mode_fw;
|
||||
int ret;
|
||||
|
||||
ret = ath10k_tm_fetch_utf_firmware_api_2(ar);
|
||||
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_UTF_API2_FILE,
|
||||
&ar->testmode.utf_mode_fw.fw_file);
|
||||
if (ret == 0) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2");
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ath10k_tm_fetch_utf_firmware_api_1(ar);
|
||||
ret = ath10k_tm_fetch_utf_firmware_api_1(ar, &ar->testmode.utf_mode_fw.fw_file);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret);
|
||||
return ret;
|
||||
@ -306,6 +190,21 @@ static int ath10k_tm_fetch_firmware(struct ath10k *ar)
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1");
|
||||
|
||||
out:
|
||||
utf_mode_fw = &ar->testmode.utf_mode_fw;
|
||||
|
||||
/* Use the same board data file as the normal firmware uses (but
|
||||
* it's still "owned" by normal_mode_fw so we shouldn't free it.
|
||||
*/
|
||||
utf_mode_fw->board_data = ar->normal_mode_fw.board_data;
|
||||
utf_mode_fw->board_len = ar->normal_mode_fw.board_len;
|
||||
|
||||
if (!utf_mode_fw->fw_file.otp_data) {
|
||||
ath10k_info(ar, "utf.bin didn't contain otp binary, taking it from the normal mode firmware");
|
||||
utf_mode_fw->fw_file.otp_data = ar->normal_mode_fw.fw_file.otp_data;
|
||||
utf_mode_fw->fw_file.otp_len = ar->normal_mode_fw.fw_file.otp_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -329,7 +228,7 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (WARN_ON(ar->testmode.utf != NULL)) {
|
||||
if (WARN_ON(ar->testmode.utf_mode_fw.fw_file.firmware != NULL)) {
|
||||
/* utf image is already downloaded, it shouldn't be */
|
||||
ret = -EEXIST;
|
||||
goto err;
|
||||
@ -344,27 +243,19 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->testmode.utf_monitor = true;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
BUILD_BUG_ON(sizeof(ar->fw_features) !=
|
||||
sizeof(ar->testmode.orig_fw_features));
|
||||
|
||||
memcpy(ar->testmode.orig_fw_features, ar->fw_features,
|
||||
sizeof(ar->fw_features));
|
||||
ar->testmode.orig_wmi_op_version = ar->wmi.op_version;
|
||||
memset(ar->fw_features, 0, sizeof(ar->fw_features));
|
||||
|
||||
ar->wmi.op_version = ar->testmode.op_version;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n",
|
||||
ar->wmi.op_version);
|
||||
ar->testmode.utf_mode_fw.fw_file.wmi_op_version);
|
||||
|
||||
ret = ath10k_hif_power_up(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret);
|
||||
ar->state = ATH10K_STATE_OFF;
|
||||
goto err_fw_features;
|
||||
goto err_release_utf_mode_fw;
|
||||
}
|
||||
|
||||
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF);
|
||||
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF,
|
||||
&ar->testmode.utf_mode_fw);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to start core (testmode): %d\n", ret);
|
||||
ar->state = ATH10K_STATE_OFF;
|
||||
@ -373,8 +264,8 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
||||
|
||||
ar->state = ATH10K_STATE_UTF;
|
||||
|
||||
if (strlen(ar->testmode.utf_version) > 0)
|
||||
ver = ar->testmode.utf_version;
|
||||
if (strlen(ar->testmode.utf_mode_fw.fw_file.fw_version) > 0)
|
||||
ver = ar->testmode.utf_mode_fw.fw_file.fw_version;
|
||||
else
|
||||
ver = "API 1";
|
||||
|
||||
@ -387,14 +278,9 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
||||
err_power_down:
|
||||
ath10k_hif_power_down(ar);
|
||||
|
||||
err_fw_features:
|
||||
/* return the original firmware features */
|
||||
memcpy(ar->fw_features, ar->testmode.orig_fw_features,
|
||||
sizeof(ar->fw_features));
|
||||
ar->wmi.op_version = ar->testmode.orig_wmi_op_version;
|
||||
|
||||
release_firmware(ar->testmode.utf);
|
||||
ar->testmode.utf = NULL;
|
||||
err_release_utf_mode_fw:
|
||||
release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware);
|
||||
ar->testmode.utf_mode_fw.fw_file.firmware = NULL;
|
||||
|
||||
err:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
@ -415,13 +301,8 @@ static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar)
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
/* return the original firmware features */
|
||||
memcpy(ar->fw_features, ar->testmode.orig_fw_features,
|
||||
sizeof(ar->fw_features));
|
||||
ar->wmi.op_version = ar->testmode.orig_wmi_op_version;
|
||||
|
||||
release_firmware(ar->testmode.utf);
|
||||
ar->testmode.utf = NULL;
|
||||
release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware);
|
||||
ar->testmode.utf_mode_fw.fw_file.firmware = NULL;
|
||||
|
||||
ar->state = ATH10K_STATE_OFF;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
#define ATH10K_QUIET_PERIOD_MIN 25
|
||||
#define ATH10K_QUIET_START_OFFSET 10
|
||||
#define ATH10K_HWMON_NAME_LEN 15
|
||||
#define ATH10K_THERMAL_SYNC_TIMEOUT_HZ (5*HZ)
|
||||
#define ATH10K_THERMAL_SYNC_TIMEOUT_HZ (5 * HZ)
|
||||
#define ATH10K_THERMAL_THROTTLE_MAX 100
|
||||
|
||||
struct ath10k_thermal {
|
||||
|
@ -130,7 +130,7 @@ struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
|
||||
list_for_each_entry(peer, &ar->peers, list) {
|
||||
if (peer->vdev_id != vdev_id)
|
||||
continue;
|
||||
if (memcmp(peer->addr, addr, ETH_ALEN))
|
||||
if (!ether_addr_equal(peer->addr, addr))
|
||||
continue;
|
||||
|
||||
return peer;
|
||||
@ -166,7 +166,7 @@ static int ath10k_wait_for_peer_common(struct ath10k *ar, int vdev_id,
|
||||
|
||||
(mapped == expect_mapped ||
|
||||
test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags));
|
||||
}), 3*HZ);
|
||||
}), 3 * HZ);
|
||||
|
||||
if (time_left == 0)
|
||||
return -ETIMEDOUT;
|
||||
@ -190,6 +190,13 @@ void ath10k_peer_map_event(struct ath10k_htt *htt,
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct ath10k_peer *peer;
|
||||
|
||||
if (ev->peer_id >= ATH10K_MAX_NUM_PEER_IDS) {
|
||||
ath10k_warn(ar,
|
||||
"received htt peer map event with idx out of bounds: %hu\n",
|
||||
ev->peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
peer = ath10k_peer_find(ar, ev->vdev_id, ev->addr);
|
||||
if (!peer) {
|
||||
@ -218,6 +225,13 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt,
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct ath10k_peer *peer;
|
||||
|
||||
if (ev->peer_id >= ATH10K_MAX_NUM_PEER_IDS) {
|
||||
ath10k_warn(ar,
|
||||
"received htt peer unmap event with idx out of bounds: %hu\n",
|
||||
ev->peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
peer = ath10k_peer_find_by_id(ar, ev->peer_id);
|
||||
if (!peer) {
|
||||
|
@ -3409,6 +3409,7 @@ static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
|
||||
.meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.set_tsf = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
};
|
||||
|
||||
static const struct wmi_ops wmi_tlv_ops = {
|
||||
|
@ -968,8 +968,8 @@ enum wmi_tlv_service {
|
||||
|
||||
#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \
|
||||
((svc_id) < (len) && \
|
||||
__le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
|
||||
BIT((svc_id)%(sizeof(u32))))
|
||||
__le32_to_cpu((wmi_svc_bmap)[(svc_id) / (sizeof(u32))]) & \
|
||||
BIT((svc_id) % (sizeof(u32))))
|
||||
|
||||
#define SVCMAP(x, y, len) \
|
||||
do { \
|
||||
|
@ -781,6 +781,7 @@ static struct wmi_vdev_param_map wmi_vdev_param_map = {
|
||||
.meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.set_tsf = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
};
|
||||
|
||||
/* 10.X WMI VDEV param map */
|
||||
@ -856,6 +857,7 @@ static struct wmi_vdev_param_map wmi_10x_vdev_param_map = {
|
||||
.meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.set_tsf = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
};
|
||||
|
||||
static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = {
|
||||
@ -930,6 +932,7 @@ static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = {
|
||||
.meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.set_tsf = WMI_10X_VDEV_PARAM_TSF_INCREMENT,
|
||||
};
|
||||
|
||||
static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = {
|
||||
@ -1005,6 +1008,7 @@ static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = {
|
||||
.meru_vc = WMI_10_4_VDEV_PARAM_MERU_VC,
|
||||
.rx_decap_type = WMI_10_4_VDEV_PARAM_RX_DECAP_TYPE,
|
||||
.bw_nss_ratemask = WMI_10_4_VDEV_PARAM_BW_NSS_RATEMASK,
|
||||
.set_tsf = WMI_10_4_VDEV_PARAM_TSF_INCREMENT,
|
||||
};
|
||||
|
||||
static struct wmi_pdev_param_map wmi_pdev_param_map = {
|
||||
@ -1804,7 +1808,7 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
|
||||
ret = -ESHUTDOWN;
|
||||
|
||||
(ret != -EAGAIN);
|
||||
}), 3*HZ);
|
||||
}), 3 * HZ);
|
||||
|
||||
if (ret)
|
||||
dev_kfree_skb_any(skb);
|
||||
@ -2145,7 +2149,8 @@ static int ath10k_wmi_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb,
|
||||
u32 msdu_len;
|
||||
u32 len;
|
||||
|
||||
if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) {
|
||||
if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX,
|
||||
ar->running_fw->fw_file.fw_features)) {
|
||||
ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data;
|
||||
ev_hdr = &ev_v2->hdr.v1;
|
||||
pull_len = sizeof(*ev_v2);
|
||||
@ -4600,10 +4605,6 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
|
||||
arg.service_map, arg.service_map_len);
|
||||
|
||||
/* only manually set fw features when not using FW IE format */
|
||||
if (ar->fw_api == 1 && ar->fw_version_build > 636)
|
||||
set_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features);
|
||||
|
||||
if (ar->num_rf_chains > ar->max_spatial_stream) {
|
||||
ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n",
|
||||
ar->num_rf_chains, ar->max_spatial_stream);
|
||||
@ -4634,7 +4635,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
|
||||
|
||||
if (test_bit(WMI_SERVICE_PEER_CACHING, ar->wmi.svc_map)) {
|
||||
if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
|
||||
ar->fw_features))
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
ar->num_active_peers = TARGET_10_4_QCACHE_ACTIVE_PEERS_PFC +
|
||||
ar->max_num_vdevs;
|
||||
else
|
||||
@ -5823,9 +5824,8 @@ ath10k_wmi_put_start_scan_tlvs(struct wmi_start_scan_tlvs *tlvs,
|
||||
bssids->num_bssid = __cpu_to_le32(arg->n_bssids);
|
||||
|
||||
for (i = 0; i < arg->n_bssids; i++)
|
||||
memcpy(&bssids->bssid_list[i],
|
||||
arg->bssids[i].bssid,
|
||||
ETH_ALEN);
|
||||
ether_addr_copy(bssids->bssid_list[i].addr,
|
||||
arg->bssids[i].bssid);
|
||||
|
||||
ptr += sizeof(*bssids);
|
||||
ptr += sizeof(struct wmi_mac_addr) * arg->n_bssids;
|
||||
@ -7865,7 +7865,7 @@ static const struct wmi_ops wmi_10_4_ops = {
|
||||
|
||||
int ath10k_wmi_attach(struct ath10k *ar)
|
||||
{
|
||||
switch (ar->wmi.op_version) {
|
||||
switch (ar->running_fw->fw_file.wmi_op_version) {
|
||||
case ATH10K_FW_WMI_OP_VERSION_10_4:
|
||||
ar->wmi.ops = &wmi_10_4_ops;
|
||||
ar->wmi.cmd = &wmi_10_4_cmd_map;
|
||||
@ -7907,7 +7907,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
||||
case ATH10K_FW_WMI_OP_VERSION_UNSET:
|
||||
case ATH10K_FW_WMI_OP_VERSION_MAX:
|
||||
ath10k_err(ar, "unsupported WMI op version: %d\n",
|
||||
ar->wmi.op_version);
|
||||
ar->running_fw->fw_file.wmi_op_version);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -180,6 +180,9 @@ enum wmi_service {
|
||||
WMI_SERVICE_MESH_NON_11S,
|
||||
WMI_SERVICE_PEER_STATS,
|
||||
WMI_SERVICE_RESTRT_CHNL_SUPPORT,
|
||||
WMI_SERVICE_TX_MODE_PUSH_ONLY,
|
||||
WMI_SERVICE_TX_MODE_PUSH_PULL,
|
||||
WMI_SERVICE_TX_MODE_DYNAMIC,
|
||||
|
||||
/* keep last */
|
||||
WMI_SERVICE_MAX,
|
||||
@ -302,6 +305,9 @@ enum wmi_10_4_service {
|
||||
WMI_10_4_SERVICE_RESTRT_CHNL_SUPPORT,
|
||||
WMI_10_4_SERVICE_PEER_STATS,
|
||||
WMI_10_4_SERVICE_MESH_11S,
|
||||
WMI_10_4_SERVICE_TX_MODE_PUSH_ONLY,
|
||||
WMI_10_4_SERVICE_TX_MODE_PUSH_PULL,
|
||||
WMI_10_4_SERVICE_TX_MODE_DYNAMIC,
|
||||
};
|
||||
|
||||
static inline char *wmi_service_name(int service_id)
|
||||
@ -396,6 +402,9 @@ static inline char *wmi_service_name(int service_id)
|
||||
SVCSTR(WMI_SERVICE_MESH_NON_11S);
|
||||
SVCSTR(WMI_SERVICE_PEER_STATS);
|
||||
SVCSTR(WMI_SERVICE_RESTRT_CHNL_SUPPORT);
|
||||
SVCSTR(WMI_SERVICE_TX_MODE_PUSH_ONLY);
|
||||
SVCSTR(WMI_SERVICE_TX_MODE_PUSH_PULL);
|
||||
SVCSTR(WMI_SERVICE_TX_MODE_DYNAMIC);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@ -405,8 +414,8 @@ static inline char *wmi_service_name(int service_id)
|
||||
|
||||
#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \
|
||||
((svc_id) < (len) && \
|
||||
__le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
|
||||
BIT((svc_id)%(sizeof(u32))))
|
||||
__le32_to_cpu((wmi_svc_bmap)[(svc_id) / (sizeof(u32))]) & \
|
||||
BIT((svc_id) % (sizeof(u32))))
|
||||
|
||||
#define SVCMAP(x, y, len) \
|
||||
do { \
|
||||
@ -643,6 +652,12 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
|
||||
WMI_SERVICE_PEER_STATS, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_MESH_11S,
|
||||
WMI_SERVICE_MESH_11S, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_TX_MODE_PUSH_ONLY,
|
||||
WMI_SERVICE_TX_MODE_PUSH_ONLY, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_TX_MODE_PUSH_PULL,
|
||||
WMI_SERVICE_TX_MODE_PUSH_PULL, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_TX_MODE_DYNAMIC,
|
||||
WMI_SERVICE_TX_MODE_DYNAMIC, len);
|
||||
}
|
||||
|
||||
#undef SVCMAP
|
||||
@ -1309,7 +1324,7 @@ enum wmi_10x_event_id {
|
||||
WMI_10X_PDEV_TPC_CONFIG_EVENTID,
|
||||
|
||||
WMI_10X_GPIO_INPUT_EVENTID,
|
||||
WMI_10X_PDEV_UTF_EVENTID = WMI_10X_END_EVENTID-1,
|
||||
WMI_10X_PDEV_UTF_EVENTID = WMI_10X_END_EVENTID - 1,
|
||||
};
|
||||
|
||||
enum wmi_10_2_cmd_id {
|
||||
@ -2042,8 +2057,8 @@ struct wmi_10x_service_ready_event {
|
||||
struct wlan_host_mem_req mem_reqs[0];
|
||||
} __packed;
|
||||
|
||||
#define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ)
|
||||
#define WMI_UNIFIED_READY_TIMEOUT_HZ (5*HZ)
|
||||
#define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ)
|
||||
#define WMI_UNIFIED_READY_TIMEOUT_HZ (5 * HZ)
|
||||
|
||||
struct wmi_ready_event {
|
||||
__le32 sw_version;
|
||||
@ -2661,9 +2676,14 @@ struct wmi_resource_config_10_4 {
|
||||
*/
|
||||
__le32 iphdr_pad_config;
|
||||
|
||||
/* qwrap configuration
|
||||
/* qwrap configuration (bits 15-0)
|
||||
* 1 - This is qwrap configuration
|
||||
* 0 - This is not qwrap
|
||||
*
|
||||
* Bits 31-16 is alloc_frag_desc_for_data_pkt (1 enables, 0 disables)
|
||||
* In order to get ack-RSSI reporting and to specify the tx-rate for
|
||||
* individual frames, this option must be enabled. This uses an extra
|
||||
* 4 bytes per tx-msdu descriptor, so don't enable it unless you need it.
|
||||
*/
|
||||
__le32 qwrap_config;
|
||||
} __packed;
|
||||
@ -4384,14 +4404,14 @@ enum wmi_vdev_subtype_10_4 {
|
||||
/*
|
||||
* Indicates that AP VDEV uses hidden ssid. only valid for
|
||||
* AP/GO */
|
||||
#define WMI_VDEV_START_HIDDEN_SSID (1<<0)
|
||||
#define WMI_VDEV_START_HIDDEN_SSID (1 << 0)
|
||||
/*
|
||||
* Indicates if robust management frame/management frame
|
||||
* protection is enabled. For GO/AP vdevs, it indicates that
|
||||
* it may support station/client associations with RMF enabled.
|
||||
* For STA/client vdevs, it indicates that sta will
|
||||
* associate with AP with RMF enabled. */
|
||||
#define WMI_VDEV_START_PMF_ENABLED (1<<1)
|
||||
#define WMI_VDEV_START_PMF_ENABLED (1 << 1)
|
||||
|
||||
struct wmi_p2p_noa_descriptor {
|
||||
__le32 type_count; /* 255: continuous schedule, 0: reserved */
|
||||
@ -4630,6 +4650,7 @@ struct wmi_vdev_param_map {
|
||||
u32 meru_vc;
|
||||
u32 rx_decap_type;
|
||||
u32 bw_nss_ratemask;
|
||||
u32 set_tsf;
|
||||
};
|
||||
|
||||
#define WMI_VDEV_PARAM_UNSUPPORTED 0
|
||||
@ -4886,6 +4907,7 @@ enum wmi_10x_vdev_param {
|
||||
WMI_10X_VDEV_PARAM_RTS_FIXED_RATE,
|
||||
WMI_10X_VDEV_PARAM_VHT_SGIMASK,
|
||||
WMI_10X_VDEV_PARAM_VHT80_RATEMASK,
|
||||
WMI_10X_VDEV_PARAM_TSF_INCREMENT,
|
||||
};
|
||||
|
||||
enum wmi_10_4_vdev_param {
|
||||
@ -4955,6 +4977,12 @@ enum wmi_10_4_vdev_param {
|
||||
WMI_10_4_VDEV_PARAM_MERU_VC,
|
||||
WMI_10_4_VDEV_PARAM_RX_DECAP_TYPE,
|
||||
WMI_10_4_VDEV_PARAM_BW_NSS_RATEMASK,
|
||||
WMI_10_4_VDEV_PARAM_SENSOR_AP,
|
||||
WMI_10_4_VDEV_PARAM_BEACON_RATE,
|
||||
WMI_10_4_VDEV_PARAM_DTIM_ENABLE_CTS,
|
||||
WMI_10_4_VDEV_PARAM_STA_KICKOUT,
|
||||
WMI_10_4_VDEV_PARAM_CAPABILITIES,
|
||||
WMI_10_4_VDEV_PARAM_TSF_INCREMENT,
|
||||
};
|
||||
|
||||
#define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0)
|
||||
@ -5329,7 +5357,7 @@ enum wmi_sta_ps_param_pspoll_count {
|
||||
#define WMI_UAPSD_AC_TYPE_TRIG 1
|
||||
|
||||
#define WMI_UAPSD_AC_BIT_MASK(ac, type) \
|
||||
((type == WMI_UAPSD_AC_TYPE_DELI) ? (1<<(ac<<1)) : (1<<((ac<<1)+1)))
|
||||
((type == WMI_UAPSD_AC_TYPE_DELI) ? (1 << (ac << 1)) : (1 << ((ac << 1) + 1)))
|
||||
|
||||
enum wmi_sta_ps_param_uapsd {
|
||||
WMI_STA_PS_UAPSD_AC0_DELIVERY_EN = (1 << 0),
|
||||
@ -5744,7 +5772,7 @@ struct wmi_rate_set {
|
||||
* the rates are filled from least significant byte to most
|
||||
* significant byte.
|
||||
*/
|
||||
__le32 rates[(MAX_SUPPORTED_RATES/4)+1];
|
||||
__le32 rates[(MAX_SUPPORTED_RATES / 4) + 1];
|
||||
} __packed;
|
||||
|
||||
struct wmi_rate_set_arg {
|
||||
|
@ -233,7 +233,7 @@ int ath10k_wow_op_suspend(struct ieee80211_hw *hw,
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
|
||||
ar->fw_features))) {
|
||||
ar->running_fw->fw_file.fw_features))) {
|
||||
ret = 1;
|
||||
goto exit;
|
||||
}
|
||||
@ -285,7 +285,7 @@ int ath10k_wow_op_resume(struct ieee80211_hw *hw)
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
|
||||
ar->fw_features))) {
|
||||
ar->running_fw->fw_file.fw_features))) {
|
||||
ret = 1;
|
||||
goto exit;
|
||||
}
|
||||
@ -325,7 +325,8 @@ exit:
|
||||
|
||||
int ath10k_wow_init(struct ath10k *ar)
|
||||
{
|
||||
if (!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, ar->fw_features))
|
||||
if (!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
return 0;
|
||||
|
||||
if (WARN_ON(!test_bit(WMI_SERVICE_WOW, ar->wmi.svc_map)))
|
||||
|
@ -246,7 +246,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_conf *conf = &common->hw->conf;
|
||||
bool fastcc;
|
||||
struct ieee80211_channel *channel = hw->conf.chandef.chan;
|
||||
struct ath9k_hw_cal_data *caldata = NULL;
|
||||
struct ath9k_hw_cal_data *caldata;
|
||||
enum htc_phymode mode;
|
||||
__be16 htc_mode;
|
||||
u8 cmd_rsp;
|
||||
@ -274,10 +274,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
|
||||
priv->ah->curchan->channel,
|
||||
channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf),
|
||||
fastcc);
|
||||
|
||||
if (!fastcc)
|
||||
caldata = &priv->caldata;
|
||||
|
||||
caldata = fastcc ? NULL : &priv->caldata;
|
||||
ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);
|
||||
if (ret) {
|
||||
ath_err(common,
|
||||
|
@ -2914,8 +2914,7 @@ void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
{
|
||||
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
|
||||
struct ieee80211_channel *channel;
|
||||
int chan_pwr, new_pwr, max_gain;
|
||||
int ant_gain, ant_reduction = 0;
|
||||
int chan_pwr, new_pwr;
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
@ -2923,15 +2922,10 @@ void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
channel = chan->chan;
|
||||
chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
|
||||
new_pwr = min_t(int, chan_pwr, reg->power_limit);
|
||||
max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
|
||||
|
||||
ant_gain = get_antenna_gain(ah, chan);
|
||||
if (ant_gain > max_gain)
|
||||
ant_reduction = ant_gain - max_gain;
|
||||
|
||||
ah->eep_ops->set_txpower(ah, chan,
|
||||
ath9k_regd_get_ctl(reg, chan),
|
||||
ant_reduction, new_pwr, test);
|
||||
get_antenna_gain(ah, chan), new_pwr, test);
|
||||
}
|
||||
|
||||
void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
|
||||
|
@ -49,6 +49,10 @@ int ath9k_led_blink;
|
||||
module_param_named(blink, ath9k_led_blink, int, 0444);
|
||||
MODULE_PARM_DESC(blink, "Enable LED blink on activity");
|
||||
|
||||
static int ath9k_led_active_high = -1;
|
||||
module_param_named(led_active_high, ath9k_led_active_high, int, 0444);
|
||||
MODULE_PARM_DESC(led_active_high, "Invert LED polarity");
|
||||
|
||||
static int ath9k_btcoex_enable;
|
||||
module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
|
||||
MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
|
||||
@ -477,7 +481,7 @@ static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob,
|
||||
static int ath9k_eeprom_request(struct ath_softc *sc, const char *name)
|
||||
{
|
||||
struct ath9k_eeprom_ctx ec;
|
||||
struct ath_hw *ah = ah = sc->sc_ah;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
int err;
|
||||
|
||||
/* try to load the EEPROM content asynchronously */
|
||||
@ -600,6 +604,9 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ath9k_led_active_high != -1)
|
||||
ah->config.led_active_high = ath9k_led_active_high == 1;
|
||||
|
||||
/*
|
||||
* Enable WLAN/BT RX Antenna diversity only when:
|
||||
*
|
||||
|
@ -28,6 +28,16 @@ static const struct pci_device_id ath_pci_id_table[] = {
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
|
||||
|
||||
#ifdef CONFIG_ATH9K_PCOEM
|
||||
/* Mini PCI AR9220 MB92 cards: Compex WLM200NX, Wistron DNMA-92 */
|
||||
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
|
||||
0x0029,
|
||||
PCI_VENDOR_ID_ATHEROS,
|
||||
0x2096),
|
||||
.driver_data = ATH9K_PCI_LED_ACT_HI },
|
||||
#endif
|
||||
|
||||
{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
|
||||
|
||||
#ifdef CONFIG_ATH9K_PCOEM
|
||||
|
@ -33,9 +33,7 @@ static ssize_t read_file_bool_bmps(struct file *file, char __user *user_buf,
|
||||
char buf[3];
|
||||
|
||||
list_for_each_entry(vif_priv, &wcn->vif_list, list) {
|
||||
vif = container_of((void *)vif_priv,
|
||||
struct ieee80211_vif,
|
||||
drv_priv);
|
||||
vif = wcn36xx_priv_to_vif(vif_priv);
|
||||
if (NL80211_IFTYPE_STATION == vif->type) {
|
||||
if (vif_priv->pw_state == WCN36XX_BMPS)
|
||||
buf[0] = '1';
|
||||
@ -70,9 +68,7 @@ static ssize_t write_file_bool_bmps(struct file *file,
|
||||
case 'Y':
|
||||
case '1':
|
||||
list_for_each_entry(vif_priv, &wcn->vif_list, list) {
|
||||
vif = container_of((void *)vif_priv,
|
||||
struct ieee80211_vif,
|
||||
drv_priv);
|
||||
vif = wcn36xx_priv_to_vif(vif_priv);
|
||||
if (NL80211_IFTYPE_STATION == vif->type) {
|
||||
wcn36xx_enable_keep_alive_null_packet(wcn, vif);
|
||||
wcn36xx_pmc_enter_bmps_state(wcn, vif);
|
||||
@ -83,9 +79,7 @@ static ssize_t write_file_bool_bmps(struct file *file,
|
||||
case 'N':
|
||||
case '0':
|
||||
list_for_each_entry(vif_priv, &wcn->vif_list, list) {
|
||||
vif = container_of((void *)vif_priv,
|
||||
struct ieee80211_vif,
|
||||
drv_priv);
|
||||
vif = wcn36xx_priv_to_vif(vif_priv);
|
||||
if (NL80211_IFTYPE_STATION == vif->type)
|
||||
wcn36xx_pmc_exit_bmps_state(wcn, vif);
|
||||
}
|
||||
|
@ -48,12 +48,15 @@
|
||||
|
||||
#define WCN36XX_HAL_IPV4_ADDR_LEN 4
|
||||
|
||||
#define WALN_HAL_STA_INVALID_IDX 0xFF
|
||||
#define WCN36XX_HAL_STA_INVALID_IDX 0xFF
|
||||
#define WCN36XX_HAL_BSS_INVALID_IDX 0xFF
|
||||
|
||||
/* Default Beacon template size */
|
||||
#define BEACON_TEMPLATE_SIZE 0x180
|
||||
|
||||
/* Minimum PVM size that the FW expects. See comment in smd.c for details. */
|
||||
#define TIM_MIN_PVM_SIZE 6
|
||||
|
||||
/* Param Change Bitmap sent to HAL */
|
||||
#define PARAM_BCN_INTERVAL_CHANGED (1 << 0)
|
||||
#define PARAM_SHORT_PREAMBLE_CHANGED (1 << 1)
|
||||
@ -2884,11 +2887,14 @@ struct update_beacon_rsp_msg {
|
||||
struct wcn36xx_hal_send_beacon_req_msg {
|
||||
struct wcn36xx_hal_msg_header header;
|
||||
|
||||
/* length of the template + 6. Only qcom knows why */
|
||||
u32 beacon_length6;
|
||||
|
||||
/* length of the template. */
|
||||
u32 beacon_length;
|
||||
|
||||
/* Beacon data. */
|
||||
u8 beacon[BEACON_TEMPLATE_SIZE];
|
||||
u8 beacon[BEACON_TEMPLATE_SIZE - sizeof(u32)];
|
||||
|
||||
u8 bssid[ETH_ALEN];
|
||||
|
||||
@ -4261,9 +4267,9 @@ struct wcn36xx_hal_rcv_flt_mc_addr_list_type {
|
||||
u8 data_offset;
|
||||
|
||||
u32 mc_addr_count;
|
||||
u8 mc_addr[ETH_ALEN][WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS];
|
||||
u8 mc_addr[WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS][ETH_ALEN];
|
||||
u8 bss_index;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct wcn36xx_hal_set_pkt_filter_rsp_msg {
|
||||
struct wcn36xx_hal_msg_header header;
|
||||
@ -4317,7 +4323,7 @@ struct wcn36xx_hal_rcv_flt_pkt_clear_rsp_msg {
|
||||
struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg {
|
||||
struct wcn36xx_hal_msg_header header;
|
||||
struct wcn36xx_hal_rcv_flt_mc_addr_list_type mc_addr_list;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_rsp_msg {
|
||||
struct wcn36xx_hal_msg_header header;
|
||||
@ -4383,6 +4389,45 @@ enum place_holder_in_cap_bitmap {
|
||||
RTT = 20,
|
||||
RATECTRL = 21,
|
||||
WOW = 22,
|
||||
WLAN_ROAM_SCAN_OFFLOAD = 23,
|
||||
SPECULATIVE_PS_POLL = 24,
|
||||
SCAN_SCH = 25,
|
||||
IBSS_HEARTBEAT_OFFLOAD = 26,
|
||||
WLAN_SCAN_OFFLOAD = 27,
|
||||
WLAN_PERIODIC_TX_PTRN = 28,
|
||||
ADVANCE_TDLS = 29,
|
||||
BATCH_SCAN = 30,
|
||||
FW_IN_TX_PATH = 31,
|
||||
EXTENDED_NSOFFLOAD_SLOT = 32,
|
||||
CH_SWITCH_V1 = 33,
|
||||
HT40_OBSS_SCAN = 34,
|
||||
UPDATE_CHANNEL_LIST = 35,
|
||||
WLAN_MCADDR_FLT = 36,
|
||||
WLAN_CH144 = 37,
|
||||
NAN = 38,
|
||||
TDLS_SCAN_COEXISTENCE = 39,
|
||||
LINK_LAYER_STATS_MEAS = 40,
|
||||
MU_MIMO = 41,
|
||||
EXTENDED_SCAN = 42,
|
||||
DYNAMIC_WMM_PS = 43,
|
||||
MAC_SPOOFED_SCAN = 44,
|
||||
BMU_ERROR_GENERIC_RECOVERY = 45,
|
||||
DISA = 46,
|
||||
FW_STATS = 47,
|
||||
WPS_PRBRSP_TMPL = 48,
|
||||
BCN_IE_FLT_DELTA = 49,
|
||||
TDLS_OFF_CHANNEL = 51,
|
||||
RTT3 = 52,
|
||||
MGMT_FRAME_LOGGING = 53,
|
||||
ENHANCED_TXBD_COMPLETION = 54,
|
||||
LOGGING_ENHANCEMENT = 55,
|
||||
EXT_SCAN_ENHANCED = 56,
|
||||
MEMORY_DUMP_SUPPORTED = 57,
|
||||
PER_PKT_STATS_SUPPORTED = 58,
|
||||
EXT_LL_STAT = 60,
|
||||
WIFI_CONFIG = 61,
|
||||
ANTENNA_DIVERSITY_SELECTION = 62,
|
||||
|
||||
MAX_FEATURE_SUPPORTED = 128,
|
||||
};
|
||||
|
||||
|
@ -201,7 +201,45 @@ static const char * const wcn36xx_caps_names[] = {
|
||||
"BCN_FILTER", /* 19 */
|
||||
"RTT", /* 20 */
|
||||
"RATECTRL", /* 21 */
|
||||
"WOW" /* 22 */
|
||||
"WOW", /* 22 */
|
||||
"WLAN_ROAM_SCAN_OFFLOAD", /* 23 */
|
||||
"SPECULATIVE_PS_POLL", /* 24 */
|
||||
"SCAN_SCH", /* 25 */
|
||||
"IBSS_HEARTBEAT_OFFLOAD", /* 26 */
|
||||
"WLAN_SCAN_OFFLOAD", /* 27 */
|
||||
"WLAN_PERIODIC_TX_PTRN", /* 28 */
|
||||
"ADVANCE_TDLS", /* 29 */
|
||||
"BATCH_SCAN", /* 30 */
|
||||
"FW_IN_TX_PATH", /* 31 */
|
||||
"EXTENDED_NSOFFLOAD_SLOT", /* 32 */
|
||||
"CH_SWITCH_V1", /* 33 */
|
||||
"HT40_OBSS_SCAN", /* 34 */
|
||||
"UPDATE_CHANNEL_LIST", /* 35 */
|
||||
"WLAN_MCADDR_FLT", /* 36 */
|
||||
"WLAN_CH144", /* 37 */
|
||||
"NAN", /* 38 */
|
||||
"TDLS_SCAN_COEXISTENCE", /* 39 */
|
||||
"LINK_LAYER_STATS_MEAS", /* 40 */
|
||||
"MU_MIMO", /* 41 */
|
||||
"EXTENDED_SCAN", /* 42 */
|
||||
"DYNAMIC_WMM_PS", /* 43 */
|
||||
"MAC_SPOOFED_SCAN", /* 44 */
|
||||
"BMU_ERROR_GENERIC_RECOVERY", /* 45 */
|
||||
"DISA", /* 46 */
|
||||
"FW_STATS", /* 47 */
|
||||
"WPS_PRBRSP_TMPL", /* 48 */
|
||||
"BCN_IE_FLT_DELTA", /* 49 */
|
||||
"TDLS_OFF_CHANNEL", /* 51 */
|
||||
"RTT3", /* 52 */
|
||||
"MGMT_FRAME_LOGGING", /* 53 */
|
||||
"ENHANCED_TXBD_COMPLETION", /* 54 */
|
||||
"LOGGING_ENHANCEMENT", /* 55 */
|
||||
"EXT_SCAN_ENHANCED", /* 56 */
|
||||
"MEMORY_DUMP_SUPPORTED", /* 57 */
|
||||
"PER_PKT_STATS_SUPPORTED", /* 58 */
|
||||
"EXT_LL_STAT", /* 60 */
|
||||
"WIFI_CONFIG", /* 61 */
|
||||
"ANTENNA_DIVERSITY_SELECTION", /* 62 */
|
||||
};
|
||||
|
||||
static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x)
|
||||
@ -287,6 +325,7 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
wcn36xx_detect_chip_version(wcn);
|
||||
wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_ENABLE_MC_ADDR_LIST, 1);
|
||||
|
||||
/* DMA channel initialization */
|
||||
ret = wcn36xx_dxe_init(wcn);
|
||||
@ -346,9 +385,7 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n",
|
||||
ch);
|
||||
list_for_each_entry(tmp, &wcn->vif_list, list) {
|
||||
vif = container_of((void *)tmp,
|
||||
struct ieee80211_vif,
|
||||
drv_priv);
|
||||
vif = wcn36xx_priv_to_vif(tmp);
|
||||
wcn36xx_smd_switch_channel(wcn, vif, ch);
|
||||
}
|
||||
}
|
||||
@ -356,15 +393,57 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define WCN36XX_SUPPORTED_FILTERS (0)
|
||||
|
||||
static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed,
|
||||
unsigned int *total, u64 multicast)
|
||||
{
|
||||
struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp;
|
||||
struct wcn36xx *wcn = hw->priv;
|
||||
struct wcn36xx_vif *tmp;
|
||||
struct ieee80211_vif *vif = NULL;
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
|
||||
|
||||
*total &= WCN36XX_SUPPORTED_FILTERS;
|
||||
*total &= FIF_ALLMULTI;
|
||||
|
||||
fp = (void *)(unsigned long)multicast;
|
||||
list_for_each_entry(tmp, &wcn->vif_list, list) {
|
||||
vif = wcn36xx_priv_to_vif(tmp);
|
||||
|
||||
/* FW handles MC filtering only when connected as STA */
|
||||
if (*total & FIF_ALLMULTI)
|
||||
wcn36xx_smd_set_mc_list(wcn, vif, NULL);
|
||||
else if (NL80211_IFTYPE_STATION == vif->type && tmp->sta_assoc)
|
||||
wcn36xx_smd_set_mc_list(wcn, vif, fp);
|
||||
}
|
||||
kfree(fp);
|
||||
}
|
||||
|
||||
static u64 wcn36xx_prepare_multicast(struct ieee80211_hw *hw,
|
||||
struct netdev_hw_addr_list *mc_list)
|
||||
{
|
||||
struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp;
|
||||
struct netdev_hw_addr *ha;
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac prepare multicast list\n");
|
||||
fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
|
||||
if (!fp) {
|
||||
wcn36xx_err("Out of memory setting filters.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fp->mc_addr_count = 0;
|
||||
/* update multicast filtering parameters */
|
||||
if (netdev_hw_addr_list_count(mc_list) <=
|
||||
WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS) {
|
||||
netdev_hw_addr_list_for_each(ha, mc_list) {
|
||||
memcpy(fp->mc_addr[fp->mc_addr_count],
|
||||
ha->addr, ETH_ALEN);
|
||||
fp->mc_addr_count++;
|
||||
}
|
||||
}
|
||||
|
||||
return (u64)(unsigned long)fp;
|
||||
}
|
||||
|
||||
static void wcn36xx_tx(struct ieee80211_hw *hw,
|
||||
@ -375,7 +454,7 @@ static void wcn36xx_tx(struct ieee80211_hw *hw,
|
||||
struct wcn36xx_sta *sta_priv = NULL;
|
||||
|
||||
if (control->sta)
|
||||
sta_priv = (struct wcn36xx_sta *)control->sta->drv_priv;
|
||||
sta_priv = wcn36xx_sta_to_priv(control->sta);
|
||||
|
||||
if (wcn36xx_start_tx(wcn, sta_priv, skb))
|
||||
ieee80211_free_txskb(wcn->hw, skb);
|
||||
@ -387,8 +466,8 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_key_conf *key_conf)
|
||||
{
|
||||
struct wcn36xx *wcn = hw->priv;
|
||||
struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_sta *sta_priv = vif_priv->sta;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
|
||||
int ret = 0;
|
||||
u8 key[WLAN_MAX_KEY_LEN];
|
||||
|
||||
@ -473,6 +552,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
break;
|
||||
case DISABLE_KEY:
|
||||
if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) {
|
||||
vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
|
||||
wcn36xx_smd_remove_bsskey(wcn,
|
||||
vif_priv->encrypt_type,
|
||||
key_conf->keyidx);
|
||||
@ -520,7 +600,7 @@ static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
|
||||
{
|
||||
int i, size;
|
||||
u16 *rates_table;
|
||||
struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
|
||||
struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
|
||||
u32 rates = sta->supp_rates[band];
|
||||
|
||||
memset(&sta_priv->supported_rates, 0,
|
||||
@ -590,7 +670,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb = NULL;
|
||||
u16 tim_off, tim_len;
|
||||
enum wcn36xx_hal_link_state link_state;
|
||||
struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
|
||||
vif, changed);
|
||||
@ -620,7 +700,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||
|
||||
if (!is_zero_ether_addr(bss_conf->bssid)) {
|
||||
vif_priv->is_joining = true;
|
||||
vif_priv->bss_index = 0xff;
|
||||
vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
|
||||
wcn36xx_smd_join(wcn, bss_conf->bssid,
|
||||
vif->addr, WCN36XX_HW_CHANNEL(wcn));
|
||||
wcn36xx_smd_config_bss(wcn, vif, NULL,
|
||||
@ -628,6 +708,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||
} else {
|
||||
vif_priv->is_joining = false;
|
||||
wcn36xx_smd_delete_bss(wcn, vif);
|
||||
vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -655,6 +736,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||
vif->addr,
|
||||
bss_conf->aid);
|
||||
|
||||
vif_priv->sta_assoc = true;
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(vif, bss_conf->bssid);
|
||||
if (!sta) {
|
||||
@ -663,7 +745,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||
rcu_read_unlock();
|
||||
goto out;
|
||||
}
|
||||
sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
|
||||
sta_priv = wcn36xx_sta_to_priv(sta);
|
||||
|
||||
wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
|
||||
|
||||
@ -686,6 +768,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||
bss_conf->bssid,
|
||||
vif->addr,
|
||||
bss_conf->aid);
|
||||
vif_priv->sta_assoc = false;
|
||||
wcn36xx_smd_set_link_st(wcn,
|
||||
bss_conf->bssid,
|
||||
vif->addr,
|
||||
@ -713,7 +796,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||
|
||||
if (bss_conf->enable_beacon) {
|
||||
vif_priv->dtim_period = bss_conf->dtim_period;
|
||||
vif_priv->bss_index = 0xff;
|
||||
vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
|
||||
wcn36xx_smd_config_bss(wcn, vif, NULL,
|
||||
vif->addr, false);
|
||||
skb = ieee80211_beacon_get_tim(hw, vif, &tim_off,
|
||||
@ -734,9 +817,9 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||
wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
|
||||
link_state);
|
||||
} else {
|
||||
wcn36xx_smd_delete_bss(wcn, vif);
|
||||
wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
|
||||
WCN36XX_HAL_LINK_IDLE_STATE);
|
||||
wcn36xx_smd_delete_bss(wcn, vif);
|
||||
}
|
||||
}
|
||||
out:
|
||||
@ -757,7 +840,7 @@ static void wcn36xx_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct wcn36xx *wcn = hw->priv;
|
||||
struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif);
|
||||
|
||||
list_del(&vif_priv->list);
|
||||
@ -768,7 +851,7 @@ static int wcn36xx_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct wcn36xx *wcn = hw->priv;
|
||||
struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n",
|
||||
vif, vif->type);
|
||||
@ -792,13 +875,12 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct wcn36xx *wcn = hw->priv;
|
||||
struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n",
|
||||
vif, sta->addr);
|
||||
|
||||
spin_lock_init(&sta_priv->ampdu_lock);
|
||||
vif_priv->sta = sta_priv;
|
||||
sta_priv->vif = vif_priv;
|
||||
/*
|
||||
* For STA mode HW will be configured on BSS_CHANGED_ASSOC because
|
||||
@ -817,14 +899,12 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct wcn36xx *wcn = hw->priv;
|
||||
struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
|
||||
struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n",
|
||||
vif, sta->addr, sta_priv->sta_index);
|
||||
|
||||
wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
|
||||
vif_priv->sta = NULL;
|
||||
sta_priv->vif = NULL;
|
||||
return 0;
|
||||
}
|
||||
@ -860,7 +940,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
|
||||
struct ieee80211_ampdu_params *params)
|
||||
{
|
||||
struct wcn36xx *wcn = hw->priv;
|
||||
struct wcn36xx_sta *sta_priv = NULL;
|
||||
struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(params->sta);
|
||||
struct ieee80211_sta *sta = params->sta;
|
||||
enum ieee80211_ampdu_mlme_action action = params->action;
|
||||
u16 tid = params->tid;
|
||||
@ -869,8 +949,6 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
|
||||
action, tid);
|
||||
|
||||
sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
|
||||
|
||||
switch (action) {
|
||||
case IEEE80211_AMPDU_RX_START:
|
||||
sta_priv->tid = tid;
|
||||
@ -923,6 +1001,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
|
||||
.resume = wcn36xx_resume,
|
||||
#endif
|
||||
.config = wcn36xx_config,
|
||||
.prepare_multicast = wcn36xx_prepare_multicast,
|
||||
.configure_filter = wcn36xx_configure_filter,
|
||||
.tx = wcn36xx_tx,
|
||||
.set_key = wcn36xx_set_key,
|
||||
|
@ -22,7 +22,7 @@ int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
int ret = 0;
|
||||
struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
/* TODO: Make sure the TX chain clean */
|
||||
ret = wcn36xx_smd_enter_bmps(wcn, vif);
|
||||
if (!ret) {
|
||||
@ -42,7 +42,7 @@ int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn,
|
||||
int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
|
||||
if (WCN36XX_BMPS != vif_priv->pw_state) {
|
||||
wcn36xx_err("Not in BMPS mode, no need to exit from BMPS mode!\n");
|
||||
|
@ -191,16 +191,16 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
|
||||
struct ieee80211_sta *sta,
|
||||
struct wcn36xx_hal_config_sta_params *sta_params)
|
||||
{
|
||||
struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_sta *priv_sta = NULL;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
struct wcn36xx_sta *sta_priv = NULL;
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC ||
|
||||
vif->type == NL80211_IFTYPE_AP ||
|
||||
vif->type == NL80211_IFTYPE_MESH_POINT) {
|
||||
sta_params->type = 1;
|
||||
sta_params->sta_index = 0xFF;
|
||||
sta_params->sta_index = WCN36XX_HAL_STA_INVALID_IDX;
|
||||
} else {
|
||||
sta_params->type = 0;
|
||||
sta_params->sta_index = 1;
|
||||
sta_params->sta_index = vif_priv->self_sta_index;
|
||||
}
|
||||
|
||||
sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
|
||||
@ -215,7 +215,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
|
||||
else
|
||||
memcpy(&sta_params->bssid, vif->addr, ETH_ALEN);
|
||||
|
||||
sta_params->encrypt_type = priv_vif->encrypt_type;
|
||||
sta_params->encrypt_type = vif_priv->encrypt_type;
|
||||
sta_params->short_preamble_supported = true;
|
||||
|
||||
sta_params->rifs_mode = 0;
|
||||
@ -224,21 +224,21 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
|
||||
sta_params->uapsd = 0;
|
||||
sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC;
|
||||
sta_params->max_ampdu_duration = 0;
|
||||
sta_params->bssid_index = priv_vif->bss_index;
|
||||
sta_params->bssid_index = vif_priv->bss_index;
|
||||
sta_params->p2p = 0;
|
||||
|
||||
if (sta) {
|
||||
priv_sta = (struct wcn36xx_sta *)sta->drv_priv;
|
||||
sta_priv = wcn36xx_sta_to_priv(sta);
|
||||
if (NL80211_IFTYPE_STATION == vif->type)
|
||||
memcpy(&sta_params->bssid, sta->addr, ETH_ALEN);
|
||||
else
|
||||
memcpy(&sta_params->mac, sta->addr, ETH_ALEN);
|
||||
sta_params->wmm_enabled = sta->wme;
|
||||
sta_params->max_sp_len = sta->max_sp;
|
||||
sta_params->aid = priv_sta->aid;
|
||||
sta_params->aid = sta_priv->aid;
|
||||
wcn36xx_smd_set_sta_ht_params(sta, sta_params);
|
||||
memcpy(&sta_params->supported_rates, &priv_sta->supported_rates,
|
||||
sizeof(priv_sta->supported_rates));
|
||||
memcpy(&sta_params->supported_rates, &sta_priv->supported_rates,
|
||||
sizeof(sta_priv->supported_rates));
|
||||
} else {
|
||||
wcn36xx_set_default_rates(&sta_params->supported_rates);
|
||||
wcn36xx_smd_set_sta_default_ht_params(sta_params);
|
||||
@ -271,6 +271,16 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void init_hal_msg(struct wcn36xx_hal_msg_header *hdr,
|
||||
enum wcn36xx_hal_host_msg_type msg_type,
|
||||
size_t msg_size)
|
||||
{
|
||||
memset(hdr, 0, msg_size + sizeof(*hdr));
|
||||
hdr->msg_type = msg_type;
|
||||
hdr->msg_version = WCN36XX_HAL_MSG_VERSION0;
|
||||
hdr->len = msg_size + sizeof(*hdr);
|
||||
}
|
||||
|
||||
#define INIT_HAL_MSG(msg_body, type) \
|
||||
do { \
|
||||
memset(&msg_body, 0, sizeof(msg_body)); \
|
||||
@ -302,22 +312,6 @@ static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcn36xx_smd_rsp_status_check_v2(struct wcn36xx *wcn, void *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct wcn36xx_fw_msg_status_rsp_v2 *rsp;
|
||||
|
||||
if (len < sizeof(struct wcn36xx_hal_msg_header) + sizeof(*rsp))
|
||||
return wcn36xx_smd_rsp_status_check(buf, len);
|
||||
|
||||
rsp = buf + sizeof(struct wcn36xx_hal_msg_header);
|
||||
|
||||
if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
|
||||
return rsp->status;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
|
||||
{
|
||||
struct nv_data *nv_d;
|
||||
@ -726,7 +720,7 @@ static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
|
||||
size_t len)
|
||||
{
|
||||
struct wcn36xx_hal_add_sta_self_rsp_msg *rsp;
|
||||
struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
|
||||
if (len < sizeof(*rsp))
|
||||
return -EINVAL;
|
||||
@ -743,8 +737,8 @@ static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
|
||||
"hal add sta self status %d self_sta_index %d dpu_index %d\n",
|
||||
rsp->status, rsp->self_sta_index, rsp->dpu_index);
|
||||
|
||||
priv_vif->self_sta_index = rsp->self_sta_index;
|
||||
priv_vif->self_dpu_desc_index = rsp->dpu_index;
|
||||
vif_priv->self_sta_index = rsp->self_sta_index;
|
||||
vif_priv->self_dpu_desc_index = rsp->dpu_index;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -949,17 +943,32 @@ static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn,
|
||||
memcpy(&v1->mac, orig->mac, ETH_ALEN);
|
||||
v1->aid = orig->aid;
|
||||
v1->type = orig->type;
|
||||
v1->short_preamble_supported = orig->short_preamble_supported;
|
||||
v1->listen_interval = orig->listen_interval;
|
||||
v1->wmm_enabled = orig->wmm_enabled;
|
||||
v1->ht_capable = orig->ht_capable;
|
||||
|
||||
v1->tx_channel_width_set = orig->tx_channel_width_set;
|
||||
v1->rifs_mode = orig->rifs_mode;
|
||||
v1->lsig_txop_protection = orig->lsig_txop_protection;
|
||||
v1->max_ampdu_size = orig->max_ampdu_size;
|
||||
v1->max_ampdu_density = orig->max_ampdu_density;
|
||||
v1->sgi_40mhz = orig->sgi_40mhz;
|
||||
v1->sgi_20Mhz = orig->sgi_20Mhz;
|
||||
|
||||
v1->rmf = orig->rmf;
|
||||
v1->encrypt_type = orig->encrypt_type;
|
||||
v1->action = orig->action;
|
||||
v1->uapsd = orig->uapsd;
|
||||
v1->max_sp_len = orig->max_sp_len;
|
||||
v1->green_field_capable = orig->green_field_capable;
|
||||
v1->mimo_ps = orig->mimo_ps;
|
||||
v1->delayed_ba_support = orig->delayed_ba_support;
|
||||
v1->max_ampdu_duration = orig->max_ampdu_duration;
|
||||
v1->dsss_cck_mode_40mhz = orig->dsss_cck_mode_40mhz;
|
||||
memcpy(&v1->supported_rates, &orig->supported_rates,
|
||||
sizeof(orig->supported_rates));
|
||||
v1->sta_index = orig->sta_index;
|
||||
v1->bssid_index = orig->bssid_index;
|
||||
v1->p2p = orig->p2p;
|
||||
}
|
||||
|
||||
static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
|
||||
@ -969,7 +978,7 @@ static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
|
||||
{
|
||||
struct wcn36xx_hal_config_sta_rsp_msg *rsp;
|
||||
struct config_sta_rsp_params *params;
|
||||
struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
|
||||
struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
|
||||
|
||||
if (len < sizeof(*rsp))
|
||||
return -EINVAL;
|
||||
@ -1170,12 +1179,13 @@ static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
|
||||
|
||||
static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
void *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct wcn36xx_hal_config_bss_rsp_msg *rsp;
|
||||
struct wcn36xx_hal_config_bss_rsp_params *params;
|
||||
struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
|
||||
if (len < sizeof(*rsp))
|
||||
return -EINVAL;
|
||||
@ -1198,14 +1208,15 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
|
||||
params->bss_bcast_sta_idx, params->mac,
|
||||
params->tx_mgmt_power, params->ucast_dpu_signature);
|
||||
|
||||
priv_vif->bss_index = params->bss_index;
|
||||
vif_priv->bss_index = params->bss_index;
|
||||
|
||||
if (priv_vif->sta) {
|
||||
priv_vif->sta->bss_sta_index = params->bss_sta_index;
|
||||
priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index;
|
||||
if (sta) {
|
||||
struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
|
||||
sta_priv->bss_sta_index = params->bss_sta_index;
|
||||
sta_priv->bss_dpu_desc_index = params->dpu_desc_index;
|
||||
}
|
||||
|
||||
priv_vif->self_ucast_dpu_sign = params->ucast_dpu_signature;
|
||||
vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1217,7 +1228,7 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
|
||||
struct wcn36xx_hal_config_bss_req_msg msg;
|
||||
struct wcn36xx_hal_config_bss_params *bss;
|
||||
struct wcn36xx_hal_config_sta_params *sta_params;
|
||||
struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
@ -1329,6 +1340,7 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
|
||||
}
|
||||
ret = wcn36xx_smd_config_bss_rsp(wcn,
|
||||
vif,
|
||||
sta,
|
||||
wcn->hal_buf,
|
||||
wcn->hal_rsp_len);
|
||||
if (ret) {
|
||||
@ -1343,13 +1355,13 @@ out:
|
||||
int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct wcn36xx_hal_delete_bss_req_msg msg_body;
|
||||
struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ);
|
||||
|
||||
msg_body.bss_index = priv_vif->bss_index;
|
||||
msg_body.bss_index = vif_priv->bss_index;
|
||||
|
||||
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
|
||||
|
||||
@ -1375,26 +1387,47 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
|
||||
u16 p2p_off)
|
||||
{
|
||||
struct wcn36xx_hal_send_beacon_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret = 0, pad, pvm_len;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
|
||||
|
||||
/* TODO need to find out why this is needed? */
|
||||
msg_body.beacon_length = skb_beacon->len + 6;
|
||||
pvm_len = skb_beacon->data[tim_off + 1] - 3;
|
||||
pad = TIM_MIN_PVM_SIZE - pvm_len;
|
||||
|
||||
if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) {
|
||||
memcpy(&msg_body.beacon, &skb_beacon->len, sizeof(u32));
|
||||
memcpy(&(msg_body.beacon[4]), skb_beacon->data,
|
||||
skb_beacon->len);
|
||||
} else {
|
||||
/* Padding is irrelevant to mesh mode since tim_off is always 0. */
|
||||
if (vif->type == NL80211_IFTYPE_MESH_POINT)
|
||||
pad = 0;
|
||||
|
||||
msg_body.beacon_length = skb_beacon->len + pad;
|
||||
/* TODO need to find out why + 6 is needed */
|
||||
msg_body.beacon_length6 = msg_body.beacon_length + 6;
|
||||
|
||||
if (msg_body.beacon_length > BEACON_TEMPLATE_SIZE) {
|
||||
wcn36xx_err("Beacon is to big: beacon size=%d\n",
|
||||
msg_body.beacon_length);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len);
|
||||
memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
|
||||
|
||||
if (pad > 0) {
|
||||
/*
|
||||
* The wcn36xx FW has a fixed size for the PVM in the TIM. If
|
||||
* given the beacon template from mac80211 with a PVM shorter
|
||||
* than the FW expectes it will overwrite the data after the
|
||||
* TIM.
|
||||
*/
|
||||
wcn36xx_dbg(WCN36XX_DBG_HAL, "Pad TIM PVM. %d bytes at %d\n",
|
||||
pad, pvm_len);
|
||||
memmove(&msg_body.beacon[tim_off + 5 + pvm_len + pad],
|
||||
&msg_body.beacon[tim_off + 5 + pvm_len],
|
||||
skb_beacon->len - (tim_off + 5 + pvm_len));
|
||||
memset(&msg_body.beacon[tim_off + 5 + pvm_len], 0, pad);
|
||||
msg_body.beacon[tim_off + 1] += pad;
|
||||
}
|
||||
|
||||
/* TODO need to find out why this is needed? */
|
||||
if (vif->type == NL80211_IFTYPE_MESH_POINT)
|
||||
/* mesh beacon don't need this, so push further down */
|
||||
@ -1598,8 +1631,7 @@ int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
|
||||
wcn36xx_err("Sending hal_remove_bsskey failed\n");
|
||||
goto out;
|
||||
}
|
||||
ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf,
|
||||
wcn->hal_rsp_len);
|
||||
ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
|
||||
if (ret) {
|
||||
wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
|
||||
goto out;
|
||||
@ -1612,7 +1644,7 @@ out:
|
||||
int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct wcn36xx_hal_enter_bmps_req_msg msg_body;
|
||||
struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
@ -1641,8 +1673,8 @@ out:
|
||||
|
||||
int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct wcn36xx_hal_enter_bmps_req_msg msg_body;
|
||||
struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_hal_exit_bmps_req_msg msg_body;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
@ -1703,7 +1735,7 @@ int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
|
||||
int packet_type)
|
||||
{
|
||||
struct wcn36xx_hal_keep_alive_req_msg msg_body;
|
||||
struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
@ -1944,6 +1976,17 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len)
|
||||
{
|
||||
struct wcn36xx_hal_trigger_ba_rsp_msg *rsp;
|
||||
|
||||
if (len < sizeof(*rsp))
|
||||
return -EINVAL;
|
||||
|
||||
rsp = (struct wcn36xx_hal_trigger_ba_rsp_msg *) buf;
|
||||
return rsp->status;
|
||||
}
|
||||
|
||||
int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
|
||||
{
|
||||
struct wcn36xx_hal_trigger_ba_req_msg msg_body;
|
||||
@ -1968,8 +2011,7 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
|
||||
wcn36xx_err("Sending hal_trigger_ba failed\n");
|
||||
goto out;
|
||||
}
|
||||
ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf,
|
||||
wcn->hal_rsp_len);
|
||||
ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len);
|
||||
if (ret) {
|
||||
wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
|
||||
goto out;
|
||||
@ -2006,9 +2048,7 @@ static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
|
||||
list_for_each_entry(tmp, &wcn->vif_list, list) {
|
||||
wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
|
||||
tmp->bss_index);
|
||||
vif = container_of((void *)tmp,
|
||||
struct ieee80211_vif,
|
||||
drv_priv);
|
||||
vif = wcn36xx_priv_to_vif(tmp);
|
||||
ieee80211_connection_loss(vif);
|
||||
}
|
||||
return 0;
|
||||
@ -2023,9 +2063,7 @@ static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
|
||||
if (tmp->bss_index == rsp->bss_index) {
|
||||
wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
|
||||
rsp->bss_index);
|
||||
vif = container_of((void *)tmp,
|
||||
struct ieee80211_vif,
|
||||
drv_priv);
|
||||
vif = wcn36xx_priv_to_vif(tmp);
|
||||
ieee80211_connection_loss(vif);
|
||||
return 0;
|
||||
}
|
||||
@ -2041,25 +2079,24 @@ static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
|
||||
{
|
||||
struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
|
||||
struct wcn36xx_vif *tmp;
|
||||
struct ieee80211_sta *sta = NULL;
|
||||
struct ieee80211_sta *sta;
|
||||
|
||||
if (len != sizeof(*rsp)) {
|
||||
wcn36xx_warn("Corrupted delete sta indication\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_HAL, "delete station indication %pM index %d\n",
|
||||
rsp->addr2, rsp->sta_id);
|
||||
|
||||
list_for_each_entry(tmp, &wcn->vif_list, list) {
|
||||
if (sta && (tmp->sta->sta_index == rsp->sta_id)) {
|
||||
sta = container_of((void *)tmp->sta,
|
||||
struct ieee80211_sta,
|
||||
drv_priv);
|
||||
wcn36xx_dbg(WCN36XX_DBG_HAL,
|
||||
"delete station indication %pM index %d\n",
|
||||
rsp->addr2,
|
||||
rsp->sta_id);
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(wcn36xx_priv_to_vif(tmp), rsp->addr2);
|
||||
if (sta)
|
||||
ieee80211_report_low_ack(sta, 0);
|
||||
rcu_read_unlock();
|
||||
if (sta)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
wcn36xx_warn("STA with addr %pM and index %d not found\n",
|
||||
@ -2100,6 +2137,46 @@ out:
|
||||
mutex_unlock(&wcn->hal_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
|
||||
struct ieee80211_vif *vif,
|
||||
struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp)
|
||||
{
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *msg_body = NULL;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
|
||||
msg_body = (struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *)
|
||||
wcn->hal_buf;
|
||||
init_hal_msg(&msg_body->header, WCN36XX_HAL_8023_MULTICAST_LIST_REQ,
|
||||
sizeof(msg_body->mc_addr_list));
|
||||
|
||||
/* An empty list means all mc traffic will be received */
|
||||
if (fp)
|
||||
memcpy(&msg_body->mc_addr_list, fp,
|
||||
sizeof(msg_body->mc_addr_list));
|
||||
else
|
||||
msg_body->mc_addr_list.mc_addr_count = 0;
|
||||
|
||||
msg_body->mc_addr_list.bss_index = vif_priv->bss_index;
|
||||
|
||||
ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
|
||||
if (ret) {
|
||||
wcn36xx_err("Sending HAL_8023_MULTICAST_LIST failed\n");
|
||||
goto out;
|
||||
}
|
||||
ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
|
||||
if (ret) {
|
||||
wcn36xx_err("HAL_8023_MULTICAST_LIST rsp failed err=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&wcn->hal_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
|
||||
{
|
||||
struct wcn36xx_hal_msg_header *msg_header = buf;
|
||||
@ -2141,6 +2218,7 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
|
||||
case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP:
|
||||
case WCN36XX_HAL_CH_SWITCH_RSP:
|
||||
case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
|
||||
case WCN36XX_HAL_8023_MULTICAST_LIST_RSP:
|
||||
memcpy(wcn->hal_buf, buf, len);
|
||||
wcn->hal_rsp_len = len;
|
||||
complete(&wcn->hal_rsp_compl);
|
||||
|
@ -44,15 +44,6 @@ struct wcn36xx_fw_msg_status_rsp {
|
||||
u32 status;
|
||||
} __packed;
|
||||
|
||||
/* wcn3620 returns this for tigger_ba */
|
||||
|
||||
struct wcn36xx_fw_msg_status_rsp_v2 {
|
||||
u8 bss_id[6];
|
||||
u32 status __packed;
|
||||
u16 count_following_candidates __packed;
|
||||
/* candidate list follows */
|
||||
};
|
||||
|
||||
struct wcn36xx_hal_ind_msg {
|
||||
struct list_head list;
|
||||
u8 *msg;
|
||||
@ -136,4 +127,7 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index);
|
||||
int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index);
|
||||
|
||||
int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value);
|
||||
int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
|
||||
struct ieee80211_vif *vif,
|
||||
struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp);
|
||||
#endif /* _SMD_H_ */
|
||||
|
@ -102,9 +102,7 @@ static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn,
|
||||
struct wcn36xx_vif *vif_priv = NULL;
|
||||
struct ieee80211_vif *vif = NULL;
|
||||
list_for_each_entry(vif_priv, &wcn->vif_list, list) {
|
||||
vif = container_of((void *)vif_priv,
|
||||
struct ieee80211_vif,
|
||||
drv_priv);
|
||||
vif = wcn36xx_priv_to_vif(vif_priv);
|
||||
if (memcmp(vif->addr, addr, ETH_ALEN) == 0)
|
||||
return vif_priv;
|
||||
}
|
||||
@ -167,9 +165,7 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
|
||||
*/
|
||||
if (sta_priv) {
|
||||
__vif_priv = sta_priv->vif;
|
||||
vif = container_of((void *)__vif_priv,
|
||||
struct ieee80211_vif,
|
||||
drv_priv);
|
||||
vif = wcn36xx_priv_to_vif(__vif_priv);
|
||||
|
||||
bd->dpu_sign = sta_priv->ucast_dpu_sign;
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
|
@ -125,10 +125,10 @@ struct wcn36xx_platform_ctrl_ops {
|
||||
*/
|
||||
struct wcn36xx_vif {
|
||||
struct list_head list;
|
||||
struct wcn36xx_sta *sta;
|
||||
u8 dtim_period;
|
||||
enum ani_ed_type encrypt_type;
|
||||
bool is_joining;
|
||||
bool sta_assoc;
|
||||
struct wcn36xx_hal_mac_ssid ssid;
|
||||
|
||||
/* Power management */
|
||||
@ -263,4 +263,22 @@ struct ieee80211_sta *wcn36xx_priv_to_sta(struct wcn36xx_sta *sta_priv)
|
||||
return container_of((void *)sta_priv, struct ieee80211_sta, drv_priv);
|
||||
}
|
||||
|
||||
static inline
|
||||
struct wcn36xx_vif *wcn36xx_vif_to_priv(struct ieee80211_vif *vif)
|
||||
{
|
||||
return (struct wcn36xx_vif *) vif->drv_priv;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct ieee80211_vif *wcn36xx_priv_to_vif(struct wcn36xx_vif *vif_priv)
|
||||
{
|
||||
return container_of((void *) vif_priv, struct ieee80211_vif, drv_priv);
|
||||
}
|
||||
|
||||
static inline
|
||||
struct wcn36xx_sta *wcn36xx_sta_to_priv(struct ieee80211_sta *sta)
|
||||
{
|
||||
return (struct wcn36xx_sta *)sta->drv_priv;
|
||||
}
|
||||
|
||||
#endif /* _WCN36XX_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user