wireless-drivers patches for 4.7
Major changes: brcmfmac * add support for nl80211 BSS_SELECT feature mwifiex * add platform specific wakeup interrupt support 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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQEcBAABAgAGBQJXJztPAAoJEG4XJFUm622beSAIAKIw8zGcs7DWd/AGd9z8D7L5 DeO6fxhiu/05AU3d1jM7Rp/Z5hZ42s41PDjRN1lkZJaF4Squa7XOxuB35JlPd+o8 2S21lvaM6ABraSEcDdYL++rglXFL65gIesv/W4TuxqdJCmi9fL7ie7ccplQH17bi KyY3ePihHZPOR8aXMRbdEzTEjjPFaO/LlAghHPw5WKmVy7FkFKSyFR8muFEPnKEl DSBWmG6GqRQaHUuVl1QOmoEEqiv7h85D+YqwKiy/xEM4Yw5Rmt5n5pj02KA0i4y5 IRZs59I/8zdAgDgBd+liVeBw9Gp2xAV5R8afOTdzViBDrqCbDCwNq6OPG1GmkLw= =lyGT -----END PGP SIGNATURE----- Merge tag 'wireless-drivers-next-for-davem-2016-05-02' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next Kalle Valo says: ==================== wireless-drivers patches for 4.7 Major changes: brcmfmac * add support for nl80211 BSS_SELECT feature mwifiex * add platform specific wakeup interrupt support 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 ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ede00a5ceb
|
@ -0,0 +1,63 @@
|
|||
Marvell 8897/8997 (sd8897/sd8997) SDIO devices
|
||||
------
|
||||
|
||||
This node provides properties for controlling the marvell sdio wireless device.
|
||||
The node is expected to be specified as a child node to the SDIO controller that
|
||||
connects the device to the system.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be one of the following:
|
||||
* "marvell,sd8897"
|
||||
* "marvell,sd8997"
|
||||
|
||||
Optional properties:
|
||||
|
||||
- marvell,caldata* : A series of properties with marvell,caldata prefix,
|
||||
represent calibration data downloaded to the device during
|
||||
initialization. This is an array of unsigned 8-bit values.
|
||||
the properties should follow below property name and
|
||||
corresponding array length:
|
||||
"marvell,caldata-txpwrlimit-2g" (length = 566).
|
||||
"marvell,caldata-txpwrlimit-5g-sub0" (length = 502).
|
||||
"marvell,caldata-txpwrlimit-5g-sub1" (length = 688).
|
||||
"marvell,caldata-txpwrlimit-5g-sub2" (length = 750).
|
||||
"marvell,caldata-txpwrlimit-5g-sub3" (length = 502).
|
||||
- marvell,wakeup-pin : a wakeup pin number of wifi chip which will be configured
|
||||
to firmware. Firmware will wakeup the host using this pin
|
||||
during suspend/resume.
|
||||
- interrupt-parent: phandle of the parent interrupt controller
|
||||
- interrupts : interrupt pin number to the cpu. driver will request an irq based on
|
||||
this interrupt number. during system suspend, the irq will be enabled
|
||||
so that the wifi chip can wakeup host platform under certain condition.
|
||||
during system resume, the irq will be disabled to make sure
|
||||
unnecessary interrupt is not received.
|
||||
|
||||
Example:
|
||||
|
||||
Tx power limit calibration data is configured in below example.
|
||||
The calibration data is an array of unsigned values, the length
|
||||
can vary between hw versions.
|
||||
IRQ pin 38 is used as system wakeup source interrupt. wakeup pin 3 is configured
|
||||
so that firmware can wakeup host using this device side pin.
|
||||
|
||||
&mmc3 {
|
||||
status = "okay";
|
||||
vmmc-supply = <&wlan_en_reg>;
|
||||
bus-width = <4>;
|
||||
cap-power-off-card;
|
||||
keep-power-in-suspend;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
mwifiex: wifi@1 {
|
||||
compatible = "marvell,sd8897";
|
||||
reg = <1>;
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <38 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
marvell,caldata_00_txpwrlimit_2g_cfg_set = /bits/ 8 <
|
||||
0x01 0x00 0x06 0x00 0x08 0x02 0x89 0x01>;
|
||||
marvell,wakeup-pin = <3>;
|
||||
};
|
||||
};
|
|
@ -9490,7 +9490,7 @@ F: drivers/net/wireless/realtek/rtlwifi/rtl8192ce/
|
|||
RTL8XXXU WIRELESS DRIVER (rtl8xxxu)
|
||||
M: Jes Sorensen <Jes.Sorensen@redhat.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git rtl8723au-mac80211
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git rtl8xxxu-devel
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/realtek/rtl8xxxu/
|
||||
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -321,7 +321,8 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws,
|
|||
if (pktbuf->len == 0)
|
||||
return -ENODATA;
|
||||
|
||||
*ifp = tmp_if;
|
||||
if (ifp != NULL)
|
||||
*ifp = tmp_if;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -351,6 +352,12 @@ brcmf_proto_bcdc_add_tdls_peer(struct brcmf_pub *drvr, int ifidx,
|
|||
{
|
||||
}
|
||||
|
||||
static void brcmf_proto_bcdc_rxreorder(struct brcmf_if *ifp,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
brcmf_fws_rxreorder(ifp, skb);
|
||||
}
|
||||
|
||||
int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct brcmf_bcdc *bcdc;
|
||||
|
@ -372,6 +379,7 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
|
|||
drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode;
|
||||
drvr->proto->delete_peer = brcmf_proto_bcdc_delete_peer;
|
||||
drvr->proto->add_tdls_peer = brcmf_proto_bcdc_add_tdls_peer;
|
||||
drvr->proto->rxreorder = brcmf_proto_bcdc_rxreorder;
|
||||
drvr->proto->pd = bcdc;
|
||||
|
||||
drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
|
||||
|
|
|
@ -216,7 +216,9 @@ bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt,
|
|||
int prec);
|
||||
|
||||
/* Receive frame for delivery to OS. Callee disposes of rxp. */
|
||||
void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp);
|
||||
void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_event);
|
||||
/* Receive async event packet from firmware. Callee disposes of rxp. */
|
||||
void brcmf_rx_event(struct device *dev, struct sk_buff *rxp);
|
||||
|
||||
/* Indication from bus module regarding presence/insertion of dongle. */
|
||||
int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings);
|
||||
|
|
|
@ -250,6 +250,20 @@ struct parsed_vndr_ies {
|
|||
struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT];
|
||||
};
|
||||
|
||||
static u8 nl80211_band_to_fwil(enum nl80211_band band)
|
||||
{
|
||||
switch (band) {
|
||||
case NL80211_BAND_2GHZ:
|
||||
return WLC_BAND_2G;
|
||||
case NL80211_BAND_5GHZ:
|
||||
return WLC_BAND_5G;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
|
||||
struct cfg80211_chan_def *ch)
|
||||
{
|
||||
|
@ -1796,6 +1810,50 @@ enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp,
|
|||
return type;
|
||||
}
|
||||
|
||||
static void brcmf_set_join_pref(struct brcmf_if *ifp,
|
||||
struct cfg80211_bss_selection *bss_select)
|
||||
{
|
||||
struct brcmf_join_pref_params join_pref_params[2];
|
||||
enum nl80211_band band;
|
||||
int err, i = 0;
|
||||
|
||||
join_pref_params[i].len = 2;
|
||||
join_pref_params[i].rssi_gain = 0;
|
||||
|
||||
if (bss_select->behaviour != NL80211_BSS_SELECT_ATTR_BAND_PREF)
|
||||
brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_ASSOC_PREFER, WLC_BAND_AUTO);
|
||||
|
||||
switch (bss_select->behaviour) {
|
||||
case __NL80211_BSS_SELECT_ATTR_INVALID:
|
||||
brcmf_c_set_joinpref_default(ifp);
|
||||
return;
|
||||
case NL80211_BSS_SELECT_ATTR_BAND_PREF:
|
||||
join_pref_params[i].type = BRCMF_JOIN_PREF_BAND;
|
||||
band = bss_select->param.band_pref;
|
||||
join_pref_params[i].band = nl80211_band_to_fwil(band);
|
||||
i++;
|
||||
break;
|
||||
case NL80211_BSS_SELECT_ATTR_RSSI_ADJUST:
|
||||
join_pref_params[i].type = BRCMF_JOIN_PREF_RSSI_DELTA;
|
||||
band = bss_select->param.adjust.band;
|
||||
join_pref_params[i].band = nl80211_band_to_fwil(band);
|
||||
join_pref_params[i].rssi_gain = bss_select->param.adjust.delta;
|
||||
i++;
|
||||
break;
|
||||
case NL80211_BSS_SELECT_ATTR_RSSI:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
join_pref_params[i].type = BRCMF_JOIN_PREF_RSSI;
|
||||
join_pref_params[i].len = 2;
|
||||
join_pref_params[i].rssi_gain = 0;
|
||||
join_pref_params[i].band = 0;
|
||||
err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
|
||||
sizeof(join_pref_params));
|
||||
if (err)
|
||||
brcmf_err("Set join_pref error (%d)\n", err);
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
|
||||
struct cfg80211_connect_params *sme)
|
||||
|
@ -1952,6 +2010,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
|
|||
ext_join_params->scan_le.nprobes = cpu_to_le32(-1);
|
||||
}
|
||||
|
||||
brcmf_set_join_pref(ifp, &sme->bss_select);
|
||||
|
||||
err = brcmf_fil_bsscfg_data_set(ifp, "join", ext_join_params,
|
||||
join_params_size);
|
||||
kfree(ext_join_params);
|
||||
|
@ -3608,7 +3668,8 @@ static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg,
|
|||
if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
|
||||
wowl_config |= BRCMF_WOWL_UNASSOC;
|
||||
|
||||
brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear", strlen("clear"));
|
||||
brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear",
|
||||
sizeof(struct brcmf_wowl_wakeind_le));
|
||||
brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config);
|
||||
brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1);
|
||||
brcmf_bus_wowl_config(cfg->pub->bus_if, true);
|
||||
|
@ -6279,6 +6340,10 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
|
|||
wiphy->n_cipher_suites = ARRAY_SIZE(brcmf_cipher_suites);
|
||||
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
|
||||
wiphy->n_cipher_suites--;
|
||||
wiphy->bss_select_support = BIT(NL80211_BSS_SELECT_ATTR_RSSI) |
|
||||
BIT(NL80211_BSS_SELECT_ATTR_BAND_PREF) |
|
||||
BIT(NL80211_BSS_SELECT_ATTR_RSSI_ADJUST);
|
||||
|
||||
wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
|
||||
WIPHY_FLAG_OFFCHAN_TX |
|
||||
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
|
||||
|
|
|
@ -38,7 +38,7 @@ const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
|||
#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40
|
||||
#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
|
||||
|
||||
/* boost value for RSSI_DELTA in preferred join selection */
|
||||
/* default boost value for RSSI_DELTA in preferred join selection */
|
||||
#define BRCMF_JOIN_PREF_RSSI_BOOST 8
|
||||
|
||||
#define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */
|
||||
|
@ -83,11 +83,31 @@ MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging");
|
|||
static struct brcmfmac_platform_data *brcmfmac_pdata;
|
||||
struct brcmf_mp_global_t brcmf_mp_global;
|
||||
|
||||
void brcmf_c_set_joinpref_default(struct brcmf_if *ifp)
|
||||
{
|
||||
struct brcmf_join_pref_params join_pref_params[2];
|
||||
int err;
|
||||
|
||||
/* Setup join_pref to select target by RSSI (boost on 5GHz) */
|
||||
join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
|
||||
join_pref_params[0].len = 2;
|
||||
join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST;
|
||||
join_pref_params[0].band = WLC_BAND_5G;
|
||||
|
||||
join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI;
|
||||
join_pref_params[1].len = 2;
|
||||
join_pref_params[1].rssi_gain = 0;
|
||||
join_pref_params[1].band = 0;
|
||||
err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
|
||||
sizeof(join_pref_params));
|
||||
if (err)
|
||||
brcmf_err("Set join_pref error (%d)\n", err);
|
||||
}
|
||||
|
||||
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
||||
{
|
||||
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
|
||||
u8 buf[BRCMF_DCMD_SMLEN];
|
||||
struct brcmf_join_pref_params join_pref_params[2];
|
||||
struct brcmf_rev_info_le revinfo;
|
||||
struct brcmf_rev_info *ri;
|
||||
char *ptr;
|
||||
|
@ -154,19 +174,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Setup join_pref to select target by RSSI(with boost on 5GHz) */
|
||||
join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
|
||||
join_pref_params[0].len = 2;
|
||||
join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST;
|
||||
join_pref_params[0].band = WLC_BAND_5G;
|
||||
join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI;
|
||||
join_pref_params[1].len = 2;
|
||||
join_pref_params[1].rssi_gain = 0;
|
||||
join_pref_params[1].band = 0;
|
||||
err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
|
||||
sizeof(join_pref_params));
|
||||
if (err)
|
||||
brcmf_err("Set join_pref error (%d)\n", err);
|
||||
brcmf_c_set_joinpref_default(ifp);
|
||||
|
||||
/* Setup event_msgs, enable E_IF */
|
||||
err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
|
||||
|
|
|
@ -40,19 +40,6 @@
|
|||
|
||||
#define MAX_WAIT_FOR_8021X_TX msecs_to_jiffies(950)
|
||||
|
||||
/* AMPDU rx reordering definitions */
|
||||
#define BRCMF_RXREORDER_FLOWID_OFFSET 0
|
||||
#define BRCMF_RXREORDER_MAXIDX_OFFSET 2
|
||||
#define BRCMF_RXREORDER_FLAGS_OFFSET 4
|
||||
#define BRCMF_RXREORDER_CURIDX_OFFSET 6
|
||||
#define BRCMF_RXREORDER_EXPIDX_OFFSET 8
|
||||
|
||||
#define BRCMF_RXREORDER_DEL_FLOW 0x01
|
||||
#define BRCMF_RXREORDER_FLUSH_ALL 0x02
|
||||
#define BRCMF_RXREORDER_CURIDX_VALID 0x04
|
||||
#define BRCMF_RXREORDER_EXPIDX_VALID 0x08
|
||||
#define BRCMF_RXREORDER_NEW_HOLE 0x10
|
||||
|
||||
#define BRCMF_BSSIDX_INVALID -1
|
||||
|
||||
char *brcmf_ifname(struct brcmf_if *ifp)
|
||||
|
@ -313,15 +300,9 @@ void brcmf_txflowblock(struct device *dev, bool state)
|
|||
|
||||
void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
|
||||
{
|
||||
skb->dev = ifp->ndev;
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
|
||||
if (skb->pkt_type == PACKET_MULTICAST)
|
||||
ifp->stats.multicast++;
|
||||
|
||||
/* Process special event packets */
|
||||
brcmf_fweh_process_skb(ifp->drvr, skb);
|
||||
|
||||
if (!(ifp->ndev->flags & IFF_UP)) {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
return;
|
||||
|
@ -341,226 +322,60 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
|
|||
netif_rx_ni(skb);
|
||||
}
|
||||
|
||||
static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi,
|
||||
u8 start, u8 end,
|
||||
struct sk_buff_head *skb_list)
|
||||
static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb,
|
||||
struct brcmf_if **ifp)
|
||||
{
|
||||
/* initialize return list */
|
||||
__skb_queue_head_init(skb_list);
|
||||
int ret;
|
||||
|
||||
if (rfi->pend_pkts == 0) {
|
||||
brcmf_dbg(INFO, "no packets in reorder queue\n");
|
||||
return;
|
||||
/* process and remove protocol-specific header */
|
||||
ret = brcmf_proto_hdrpull(drvr, true, skb, ifp);
|
||||
|
||||
if (ret || !(*ifp) || !(*ifp)->ndev) {
|
||||
if (ret != -ENODATA && *ifp)
|
||||
(*ifp)->stats.rx_errors++;
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
do {
|
||||
if (rfi->pktslots[start]) {
|
||||
__skb_queue_tail(skb_list, rfi->pktslots[start]);
|
||||
rfi->pktslots[start] = NULL;
|
||||
}
|
||||
start++;
|
||||
if (start > rfi->max_idx)
|
||||
start = 0;
|
||||
} while (start != end);
|
||||
rfi->pend_pkts -= skb_queue_len(skb_list);
|
||||
skb->protocol = eth_type_trans(skb, (*ifp)->ndev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void brcmf_rxreorder_process_info(struct brcmf_if *ifp, u8 *reorder_data,
|
||||
struct sk_buff *pkt)
|
||||
{
|
||||
u8 flow_id, max_idx, cur_idx, exp_idx, end_idx;
|
||||
struct brcmf_ampdu_rx_reorder *rfi;
|
||||
struct sk_buff_head reorder_list;
|
||||
struct sk_buff *pnext;
|
||||
u8 flags;
|
||||
u32 buf_size;
|
||||
|
||||
flow_id = reorder_data[BRCMF_RXREORDER_FLOWID_OFFSET];
|
||||
flags = reorder_data[BRCMF_RXREORDER_FLAGS_OFFSET];
|
||||
|
||||
/* validate flags and flow id */
|
||||
if (flags == 0xFF) {
|
||||
brcmf_err("invalid flags...so ignore this packet\n");
|
||||
brcmf_netif_rx(ifp, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
rfi = ifp->drvr->reorder_flows[flow_id];
|
||||
if (flags & BRCMF_RXREORDER_DEL_FLOW) {
|
||||
brcmf_dbg(INFO, "flow-%d: delete\n",
|
||||
flow_id);
|
||||
|
||||
if (rfi == NULL) {
|
||||
brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
|
||||
flow_id);
|
||||
brcmf_netif_rx(ifp, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, rfi->exp_idx,
|
||||
&reorder_list);
|
||||
/* add the last packet */
|
||||
__skb_queue_tail(&reorder_list, pkt);
|
||||
kfree(rfi);
|
||||
ifp->drvr->reorder_flows[flow_id] = NULL;
|
||||
goto netif_rx;
|
||||
}
|
||||
/* from here on we need a flow reorder instance */
|
||||
if (rfi == NULL) {
|
||||
buf_size = sizeof(*rfi);
|
||||
max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
|
||||
|
||||
buf_size += (max_idx + 1) * sizeof(pkt);
|
||||
|
||||
/* allocate space for flow reorder info */
|
||||
brcmf_dbg(INFO, "flow-%d: start, maxidx %d\n",
|
||||
flow_id, max_idx);
|
||||
rfi = kzalloc(buf_size, GFP_ATOMIC);
|
||||
if (rfi == NULL) {
|
||||
brcmf_err("failed to alloc buffer\n");
|
||||
brcmf_netif_rx(ifp, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
ifp->drvr->reorder_flows[flow_id] = rfi;
|
||||
rfi->pktslots = (struct sk_buff **)(rfi+1);
|
||||
rfi->max_idx = max_idx;
|
||||
}
|
||||
if (flags & BRCMF_RXREORDER_NEW_HOLE) {
|
||||
if (rfi->pend_pkts) {
|
||||
brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx,
|
||||
rfi->exp_idx,
|
||||
&reorder_list);
|
||||
WARN_ON(rfi->pend_pkts);
|
||||
} else {
|
||||
__skb_queue_head_init(&reorder_list);
|
||||
}
|
||||
rfi->cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
|
||||
rfi->exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
|
||||
rfi->max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
|
||||
rfi->pktslots[rfi->cur_idx] = pkt;
|
||||
rfi->pend_pkts++;
|
||||
brcmf_dbg(DATA, "flow-%d: new hole %d (%d), pending %d\n",
|
||||
flow_id, rfi->cur_idx, rfi->exp_idx, rfi->pend_pkts);
|
||||
} else if (flags & BRCMF_RXREORDER_CURIDX_VALID) {
|
||||
cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
|
||||
exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
|
||||
|
||||
if ((exp_idx == rfi->exp_idx) && (cur_idx != rfi->exp_idx)) {
|
||||
/* still in the current hole */
|
||||
/* enqueue the current on the buffer chain */
|
||||
if (rfi->pktslots[cur_idx] != NULL) {
|
||||
brcmf_dbg(INFO, "HOLE: ERROR buffer pending..free it\n");
|
||||
brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
|
||||
rfi->pktslots[cur_idx] = NULL;
|
||||
}
|
||||
rfi->pktslots[cur_idx] = pkt;
|
||||
rfi->pend_pkts++;
|
||||
rfi->cur_idx = cur_idx;
|
||||
brcmf_dbg(DATA, "flow-%d: store pkt %d (%d), pending %d\n",
|
||||
flow_id, cur_idx, exp_idx, rfi->pend_pkts);
|
||||
|
||||
/* can return now as there is no reorder
|
||||
* list to process.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
if (rfi->exp_idx == cur_idx) {
|
||||
if (rfi->pktslots[cur_idx] != NULL) {
|
||||
brcmf_dbg(INFO, "error buffer pending..free it\n");
|
||||
brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
|
||||
rfi->pktslots[cur_idx] = NULL;
|
||||
}
|
||||
rfi->pktslots[cur_idx] = pkt;
|
||||
rfi->pend_pkts++;
|
||||
|
||||
/* got the expected one. flush from current to expected
|
||||
* and update expected
|
||||
*/
|
||||
brcmf_dbg(DATA, "flow-%d: expected %d (%d), pending %d\n",
|
||||
flow_id, cur_idx, exp_idx, rfi->pend_pkts);
|
||||
|
||||
rfi->cur_idx = cur_idx;
|
||||
rfi->exp_idx = exp_idx;
|
||||
|
||||
brcmf_rxreorder_get_skb_list(rfi, cur_idx, exp_idx,
|
||||
&reorder_list);
|
||||
brcmf_dbg(DATA, "flow-%d: freeing buffers %d, pending %d\n",
|
||||
flow_id, skb_queue_len(&reorder_list),
|
||||
rfi->pend_pkts);
|
||||
} else {
|
||||
u8 end_idx;
|
||||
|
||||
brcmf_dbg(DATA, "flow-%d (0x%x): both moved, old %d/%d, new %d/%d\n",
|
||||
flow_id, flags, rfi->cur_idx, rfi->exp_idx,
|
||||
cur_idx, exp_idx);
|
||||
if (flags & BRCMF_RXREORDER_FLUSH_ALL)
|
||||
end_idx = rfi->exp_idx;
|
||||
else
|
||||
end_idx = exp_idx;
|
||||
|
||||
/* flush pkts first */
|
||||
brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
|
||||
&reorder_list);
|
||||
|
||||
if (exp_idx == ((cur_idx + 1) % (rfi->max_idx + 1))) {
|
||||
__skb_queue_tail(&reorder_list, pkt);
|
||||
} else {
|
||||
rfi->pktslots[cur_idx] = pkt;
|
||||
rfi->pend_pkts++;
|
||||
}
|
||||
rfi->exp_idx = exp_idx;
|
||||
rfi->cur_idx = cur_idx;
|
||||
}
|
||||
} else {
|
||||
/* explicity window move updating the expected index */
|
||||
exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
|
||||
|
||||
brcmf_dbg(DATA, "flow-%d (0x%x): change expected: %d -> %d\n",
|
||||
flow_id, flags, rfi->exp_idx, exp_idx);
|
||||
if (flags & BRCMF_RXREORDER_FLUSH_ALL)
|
||||
end_idx = rfi->exp_idx;
|
||||
else
|
||||
end_idx = exp_idx;
|
||||
|
||||
brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
|
||||
&reorder_list);
|
||||
__skb_queue_tail(&reorder_list, pkt);
|
||||
/* set the new expected idx */
|
||||
rfi->exp_idx = exp_idx;
|
||||
}
|
||||
netif_rx:
|
||||
skb_queue_walk_safe(&reorder_list, pkt, pnext) {
|
||||
__skb_unlink(pkt, &reorder_list);
|
||||
brcmf_netif_rx(ifp, pkt);
|
||||
}
|
||||
}
|
||||
|
||||
void brcmf_rx_frame(struct device *dev, struct sk_buff *skb)
|
||||
void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
struct brcmf_skb_reorder_data *rd;
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
|
||||
|
||||
/* process and remove protocol-specific header */
|
||||
ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp);
|
||||
|
||||
if (ret || !ifp || !ifp->ndev) {
|
||||
if (ret != -ENODATA && ifp)
|
||||
ifp->stats.rx_errors++;
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
if (brcmf_rx_hdrpull(drvr, skb, &ifp))
|
||||
return;
|
||||
}
|
||||
|
||||
rd = (struct brcmf_skb_reorder_data *)skb->cb;
|
||||
if (rd->reorder)
|
||||
brcmf_rxreorder_process_info(ifp, rd->reorder, skb);
|
||||
else
|
||||
if (brcmf_proto_is_reorder_skb(skb)) {
|
||||
brcmf_proto_rxreorder(ifp, skb);
|
||||
} else {
|
||||
/* Process special event packets */
|
||||
if (handle_event)
|
||||
brcmf_fweh_process_skb(ifp->drvr, skb);
|
||||
|
||||
brcmf_netif_rx(ifp, skb);
|
||||
}
|
||||
}
|
||||
|
||||
void brcmf_rx_event(struct device *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
|
||||
brcmf_dbg(EVENT, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
|
||||
|
||||
if (brcmf_rx_hdrpull(drvr, skb, &ifp))
|
||||
return;
|
||||
|
||||
brcmf_fweh_process_skb(ifp->drvr, skb);
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
}
|
||||
|
||||
void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success)
|
||||
|
|
|
@ -208,10 +208,6 @@ struct brcmf_if {
|
|||
u8 ipv6addr_idx;
|
||||
};
|
||||
|
||||
struct brcmf_skb_reorder_data {
|
||||
u8 *reorder;
|
||||
};
|
||||
|
||||
int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
|
||||
|
||||
/* Return pointer to interface name */
|
||||
|
@ -227,6 +223,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp,
|
|||
void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
|
||||
void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
|
||||
void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
|
||||
void brcmf_c_set_joinpref_default(struct brcmf_if *ifp);
|
||||
int __init brcmf_core_init(void);
|
||||
void __exit brcmf_core_exit(void);
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#define BRCMF_FW_MAX_NVRAM_SIZE 64000
|
||||
#define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */
|
||||
#define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */
|
||||
#define BRCMF_FW_DEFAULT_BOARDREV "boardrev=0xff"
|
||||
|
||||
enum nvram_parser_state {
|
||||
IDLE,
|
||||
|
@ -51,6 +52,7 @@ enum nvram_parser_state {
|
|||
* @entry: start position of key,value entry.
|
||||
* @multi_dev_v1: detect pcie multi device v1 (compressed).
|
||||
* @multi_dev_v2: detect pcie multi device v2.
|
||||
* @boardrev_found: nvram contains boardrev information.
|
||||
*/
|
||||
struct nvram_parser {
|
||||
enum nvram_parser_state state;
|
||||
|
@ -63,6 +65,7 @@ struct nvram_parser {
|
|||
u32 entry;
|
||||
bool multi_dev_v1;
|
||||
bool multi_dev_v2;
|
||||
bool boardrev_found;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -125,6 +128,8 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
|
|||
nvp->multi_dev_v1 = true;
|
||||
if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0)
|
||||
nvp->multi_dev_v2 = true;
|
||||
if (strncmp(&nvp->data[nvp->entry], "boardrev", 8) == 0)
|
||||
nvp->boardrev_found = true;
|
||||
} else if (!is_nvram_char(c) || c == ' ') {
|
||||
brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
|
||||
nvp->line, nvp->column);
|
||||
|
@ -284,6 +289,8 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
|
|||
while (i < nvp->nvram_len) {
|
||||
if ((nvp->nvram[i] - '0' == id) && (nvp->nvram[i + 1] == ':')) {
|
||||
i += 2;
|
||||
if (strncmp(&nvp->nvram[i], "boardrev", 8) == 0)
|
||||
nvp->boardrev_found = true;
|
||||
while (nvp->nvram[i] != 0) {
|
||||
nvram[j] = nvp->nvram[i];
|
||||
i++;
|
||||
|
@ -335,6 +342,8 @@ static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr,
|
|||
while (i < nvp->nvram_len - len) {
|
||||
if (strncmp(&nvp->nvram[i], prefix, len) == 0) {
|
||||
i += len;
|
||||
if (strncmp(&nvp->nvram[i], "boardrev", 8) == 0)
|
||||
nvp->boardrev_found = true;
|
||||
while (nvp->nvram[i] != 0) {
|
||||
nvram[j] = nvp->nvram[i];
|
||||
i++;
|
||||
|
@ -356,6 +365,18 @@ fail:
|
|||
nvp->nvram_len = 0;
|
||||
}
|
||||
|
||||
static void brcmf_fw_add_defaults(struct nvram_parser *nvp)
|
||||
{
|
||||
if (nvp->boardrev_found)
|
||||
return;
|
||||
|
||||
memcpy(&nvp->nvram[nvp->nvram_len], &BRCMF_FW_DEFAULT_BOARDREV,
|
||||
strlen(BRCMF_FW_DEFAULT_BOARDREV));
|
||||
nvp->nvram_len += strlen(BRCMF_FW_DEFAULT_BOARDREV);
|
||||
nvp->nvram[nvp->nvram_len] = '\0';
|
||||
nvp->nvram_len++;
|
||||
}
|
||||
|
||||
/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
|
||||
* and ending in a NUL. Removes carriage returns, empty lines, comment lines,
|
||||
* and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
|
||||
|
@ -377,16 +398,21 @@ static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
|
|||
if (nvp.state == END)
|
||||
break;
|
||||
}
|
||||
if (nvp.multi_dev_v1)
|
||||
if (nvp.multi_dev_v1) {
|
||||
nvp.boardrev_found = false;
|
||||
brcmf_fw_strip_multi_v1(&nvp, domain_nr, bus_nr);
|
||||
else if (nvp.multi_dev_v2)
|
||||
} else if (nvp.multi_dev_v2) {
|
||||
nvp.boardrev_found = false;
|
||||
brcmf_fw_strip_multi_v2(&nvp, domain_nr, bus_nr);
|
||||
}
|
||||
|
||||
if (nvp.nvram_len == 0) {
|
||||
kfree(nvp.nvram);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
brcmf_fw_add_defaults(&nvp);
|
||||
|
||||
pad = nvp.nvram_len;
|
||||
*new_length = roundup(nvp.nvram_len + 1, 4);
|
||||
while (pad != *new_length) {
|
||||
|
|
|
@ -371,6 +371,7 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp)
|
|||
int i, err;
|
||||
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
|
||||
|
||||
memset(eventmask, 0, sizeof(eventmask));
|
||||
for (i = 0; i < BRCMF_E_LAST; i++) {
|
||||
if (ifp->drvr->fweh.evt_handler[i]) {
|
||||
brcmf_dbg(EVENT, "enable event %s\n",
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185
|
||||
#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187
|
||||
#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201
|
||||
#define BRCMF_C_SET_ASSOC_PREFER 205
|
||||
#define BRCMF_C_GET_VALID_CHANNELS 217
|
||||
#define BRCMF_C_GET_KEY_PRIMARY 235
|
||||
#define BRCMF_C_SET_KEY_PRIMARY 236
|
||||
|
|
|
@ -92,6 +92,19 @@ enum brcmf_fws_tlv_len {
|
|||
};
|
||||
#undef BRCMF_FWS_TLV_DEF
|
||||
|
||||
/* AMPDU rx reordering definitions */
|
||||
#define BRCMF_RXREORDER_FLOWID_OFFSET 0
|
||||
#define BRCMF_RXREORDER_MAXIDX_OFFSET 2
|
||||
#define BRCMF_RXREORDER_FLAGS_OFFSET 4
|
||||
#define BRCMF_RXREORDER_CURIDX_OFFSET 6
|
||||
#define BRCMF_RXREORDER_EXPIDX_OFFSET 8
|
||||
|
||||
#define BRCMF_RXREORDER_DEL_FLOW 0x01
|
||||
#define BRCMF_RXREORDER_FLUSH_ALL 0x02
|
||||
#define BRCMF_RXREORDER_CURIDX_VALID 0x04
|
||||
#define BRCMF_RXREORDER_EXPIDX_VALID 0x08
|
||||
#define BRCMF_RXREORDER_NEW_HOLE 0x10
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* brcmf_fws_tlv_names - array of tlv names.
|
||||
|
@ -1614,6 +1627,202 @@ static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi,
|
||||
u8 start, u8 end,
|
||||
struct sk_buff_head *skb_list)
|
||||
{
|
||||
/* initialize return list */
|
||||
__skb_queue_head_init(skb_list);
|
||||
|
||||
if (rfi->pend_pkts == 0) {
|
||||
brcmf_dbg(INFO, "no packets in reorder queue\n");
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
if (rfi->pktslots[start]) {
|
||||
__skb_queue_tail(skb_list, rfi->pktslots[start]);
|
||||
rfi->pktslots[start] = NULL;
|
||||
}
|
||||
start++;
|
||||
if (start > rfi->max_idx)
|
||||
start = 0;
|
||||
} while (start != end);
|
||||
rfi->pend_pkts -= skb_queue_len(skb_list);
|
||||
}
|
||||
|
||||
void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt)
|
||||
{
|
||||
u8 *reorder_data;
|
||||
u8 flow_id, max_idx, cur_idx, exp_idx, end_idx;
|
||||
struct brcmf_ampdu_rx_reorder *rfi;
|
||||
struct sk_buff_head reorder_list;
|
||||
struct sk_buff *pnext;
|
||||
u8 flags;
|
||||
u32 buf_size;
|
||||
|
||||
reorder_data = ((struct brcmf_skb_reorder_data *)pkt->cb)->reorder;
|
||||
flow_id = reorder_data[BRCMF_RXREORDER_FLOWID_OFFSET];
|
||||
flags = reorder_data[BRCMF_RXREORDER_FLAGS_OFFSET];
|
||||
|
||||
/* validate flags and flow id */
|
||||
if (flags == 0xFF) {
|
||||
brcmf_err("invalid flags...so ignore this packet\n");
|
||||
brcmf_netif_rx(ifp, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
rfi = ifp->drvr->reorder_flows[flow_id];
|
||||
if (flags & BRCMF_RXREORDER_DEL_FLOW) {
|
||||
brcmf_dbg(INFO, "flow-%d: delete\n",
|
||||
flow_id);
|
||||
|
||||
if (rfi == NULL) {
|
||||
brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
|
||||
flow_id);
|
||||
brcmf_netif_rx(ifp, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, rfi->exp_idx,
|
||||
&reorder_list);
|
||||
/* add the last packet */
|
||||
__skb_queue_tail(&reorder_list, pkt);
|
||||
kfree(rfi);
|
||||
ifp->drvr->reorder_flows[flow_id] = NULL;
|
||||
goto netif_rx;
|
||||
}
|
||||
/* from here on we need a flow reorder instance */
|
||||
if (rfi == NULL) {
|
||||
buf_size = sizeof(*rfi);
|
||||
max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
|
||||
|
||||
buf_size += (max_idx + 1) * sizeof(pkt);
|
||||
|
||||
/* allocate space for flow reorder info */
|
||||
brcmf_dbg(INFO, "flow-%d: start, maxidx %d\n",
|
||||
flow_id, max_idx);
|
||||
rfi = kzalloc(buf_size, GFP_ATOMIC);
|
||||
if (rfi == NULL) {
|
||||
brcmf_err("failed to alloc buffer\n");
|
||||
brcmf_netif_rx(ifp, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
ifp->drvr->reorder_flows[flow_id] = rfi;
|
||||
rfi->pktslots = (struct sk_buff **)(rfi + 1);
|
||||
rfi->max_idx = max_idx;
|
||||
}
|
||||
if (flags & BRCMF_RXREORDER_NEW_HOLE) {
|
||||
if (rfi->pend_pkts) {
|
||||
brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx,
|
||||
rfi->exp_idx,
|
||||
&reorder_list);
|
||||
WARN_ON(rfi->pend_pkts);
|
||||
} else {
|
||||
__skb_queue_head_init(&reorder_list);
|
||||
}
|
||||
rfi->cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
|
||||
rfi->exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
|
||||
rfi->max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
|
||||
rfi->pktslots[rfi->cur_idx] = pkt;
|
||||
rfi->pend_pkts++;
|
||||
brcmf_dbg(DATA, "flow-%d: new hole %d (%d), pending %d\n",
|
||||
flow_id, rfi->cur_idx, rfi->exp_idx, rfi->pend_pkts);
|
||||
} else if (flags & BRCMF_RXREORDER_CURIDX_VALID) {
|
||||
cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
|
||||
exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
|
||||
|
||||
if ((exp_idx == rfi->exp_idx) && (cur_idx != rfi->exp_idx)) {
|
||||
/* still in the current hole */
|
||||
/* enqueue the current on the buffer chain */
|
||||
if (rfi->pktslots[cur_idx] != NULL) {
|
||||
brcmf_dbg(INFO, "HOLE: ERROR buffer pending..free it\n");
|
||||
brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
|
||||
rfi->pktslots[cur_idx] = NULL;
|
||||
}
|
||||
rfi->pktslots[cur_idx] = pkt;
|
||||
rfi->pend_pkts++;
|
||||
rfi->cur_idx = cur_idx;
|
||||
brcmf_dbg(DATA, "flow-%d: store pkt %d (%d), pending %d\n",
|
||||
flow_id, cur_idx, exp_idx, rfi->pend_pkts);
|
||||
|
||||
/* can return now as there is no reorder
|
||||
* list to process.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
if (rfi->exp_idx == cur_idx) {
|
||||
if (rfi->pktslots[cur_idx] != NULL) {
|
||||
brcmf_dbg(INFO, "error buffer pending..free it\n");
|
||||
brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
|
||||
rfi->pktslots[cur_idx] = NULL;
|
||||
}
|
||||
rfi->pktslots[cur_idx] = pkt;
|
||||
rfi->pend_pkts++;
|
||||
|
||||
/* got the expected one. flush from current to expected
|
||||
* and update expected
|
||||
*/
|
||||
brcmf_dbg(DATA, "flow-%d: expected %d (%d), pending %d\n",
|
||||
flow_id, cur_idx, exp_idx, rfi->pend_pkts);
|
||||
|
||||
rfi->cur_idx = cur_idx;
|
||||
rfi->exp_idx = exp_idx;
|
||||
|
||||
brcmf_rxreorder_get_skb_list(rfi, cur_idx, exp_idx,
|
||||
&reorder_list);
|
||||
brcmf_dbg(DATA, "flow-%d: freeing buffers %d, pending %d\n",
|
||||
flow_id, skb_queue_len(&reorder_list),
|
||||
rfi->pend_pkts);
|
||||
} else {
|
||||
u8 end_idx;
|
||||
|
||||
brcmf_dbg(DATA, "flow-%d (0x%x): both moved, old %d/%d, new %d/%d\n",
|
||||
flow_id, flags, rfi->cur_idx, rfi->exp_idx,
|
||||
cur_idx, exp_idx);
|
||||
if (flags & BRCMF_RXREORDER_FLUSH_ALL)
|
||||
end_idx = rfi->exp_idx;
|
||||
else
|
||||
end_idx = exp_idx;
|
||||
|
||||
/* flush pkts first */
|
||||
brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
|
||||
&reorder_list);
|
||||
|
||||
if (exp_idx == ((cur_idx + 1) % (rfi->max_idx + 1))) {
|
||||
__skb_queue_tail(&reorder_list, pkt);
|
||||
} else {
|
||||
rfi->pktslots[cur_idx] = pkt;
|
||||
rfi->pend_pkts++;
|
||||
}
|
||||
rfi->exp_idx = exp_idx;
|
||||
rfi->cur_idx = cur_idx;
|
||||
}
|
||||
} else {
|
||||
/* explicity window move updating the expected index */
|
||||
exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
|
||||
|
||||
brcmf_dbg(DATA, "flow-%d (0x%x): change expected: %d -> %d\n",
|
||||
flow_id, flags, rfi->exp_idx, exp_idx);
|
||||
if (flags & BRCMF_RXREORDER_FLUSH_ALL)
|
||||
end_idx = rfi->exp_idx;
|
||||
else
|
||||
end_idx = exp_idx;
|
||||
|
||||
brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
|
||||
&reorder_list);
|
||||
__skb_queue_tail(&reorder_list, pkt);
|
||||
/* set the new expected idx */
|
||||
rfi->exp_idx = exp_idx;
|
||||
}
|
||||
netif_rx:
|
||||
skb_queue_walk_safe(&reorder_list, pkt, pnext) {
|
||||
__skb_unlink(pkt, &reorder_list);
|
||||
brcmf_netif_rx(ifp, pkt);
|
||||
}
|
||||
}
|
||||
|
||||
void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb)
|
||||
{
|
||||
struct brcmf_skb_reorder_data *rd;
|
||||
|
|
|
@ -29,5 +29,6 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp);
|
|||
void brcmf_fws_del_interface(struct brcmf_if *ifp);
|
||||
void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb);
|
||||
void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked);
|
||||
void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb);
|
||||
|
||||
#endif /* FWSIGNAL_H_ */
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
||||
#include <brcmu_utils.h>
|
||||
#include <brcmu_wifi.h>
|
||||
|
@ -526,6 +527,9 @@ static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void brcmf_msgbuf_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
brcmf_msgbuf_remove_flowring(struct brcmf_msgbuf *msgbuf, u16 flowid)
|
||||
|
@ -1075,28 +1079,13 @@ static void brcmf_msgbuf_rxbuf_event_post(struct brcmf_msgbuf *msgbuf)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
brcmf_msgbuf_rx_skb(struct brcmf_msgbuf *msgbuf, struct sk_buff *skb,
|
||||
u8 ifidx)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
ifp = brcmf_get_ifp(msgbuf->drvr, ifidx);
|
||||
if (!ifp || !ifp->ndev) {
|
||||
brcmf_err("Received pkt for invalid ifidx %d\n", ifidx);
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
return;
|
||||
}
|
||||
brcmf_netif_rx(ifp, skb);
|
||||
}
|
||||
|
||||
|
||||
static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf)
|
||||
{
|
||||
struct msgbuf_rx_event *event;
|
||||
u32 idx;
|
||||
u16 buflen;
|
||||
struct sk_buff *skb;
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
event = (struct msgbuf_rx_event *)buf;
|
||||
idx = le32_to_cpu(event->msg.request_id);
|
||||
|
@ -1116,7 +1105,19 @@ static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf)
|
|||
|
||||
skb_trim(skb, buflen);
|
||||
|
||||
brcmf_msgbuf_rx_skb(msgbuf, skb, event->msg.ifidx);
|
||||
ifp = brcmf_get_ifp(msgbuf->drvr, event->msg.ifidx);
|
||||
if (!ifp || !ifp->ndev) {
|
||||
brcmf_err("Received pkt for invalid ifidx %d\n",
|
||||
event->msg.ifidx);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
skb->protocol = eth_type_trans(skb, ifp->ndev);
|
||||
|
||||
brcmf_fweh_process_skb(ifp->drvr, skb);
|
||||
|
||||
exit:
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1128,6 +1129,7 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
|
|||
u16 data_offset;
|
||||
u16 buflen;
|
||||
u32 idx;
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
brcmf_msgbuf_update_rxbufpost_count(msgbuf, 1);
|
||||
|
||||
|
@ -1148,7 +1150,14 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
|
|||
|
||||
skb_trim(skb, buflen);
|
||||
|
||||
brcmf_msgbuf_rx_skb(msgbuf, skb, rx_complete->msg.ifidx);
|
||||
ifp = brcmf_get_ifp(msgbuf->drvr, rx_complete->msg.ifidx);
|
||||
if (!ifp || !ifp->ndev) {
|
||||
brcmf_err("Received pkt for invalid ifidx %d\n",
|
||||
rx_complete->msg.ifidx);
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
return;
|
||||
}
|
||||
brcmf_netif_rx(ifp, skb);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1460,6 +1469,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
|
|||
drvr->proto->configure_addr_mode = brcmf_msgbuf_configure_addr_mode;
|
||||
drvr->proto->delete_peer = brcmf_msgbuf_delete_peer;
|
||||
drvr->proto->add_tdls_peer = brcmf_msgbuf_add_tdls_peer;
|
||||
drvr->proto->rxreorder = brcmf_msgbuf_rxreorder;
|
||||
drvr->proto->pd = msgbuf;
|
||||
|
||||
init_waitqueue_head(&msgbuf->ioctl_resp_wait);
|
||||
|
|
|
@ -1266,7 +1266,7 @@ static void
|
|||
brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
struct brcmf_p2p_info *p2p = &cfg->p2p;
|
||||
struct brcmf_if *ifp = cfg->escan_info.ifp;
|
||||
struct brcmf_if *ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
|
||||
|
||||
if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) &&
|
||||
(test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status) ||
|
||||
|
|
|
@ -22,6 +22,9 @@ enum proto_addr_mode {
|
|||
ADDR_DIRECT
|
||||
};
|
||||
|
||||
struct brcmf_skb_reorder_data {
|
||||
u8 *reorder;
|
||||
};
|
||||
|
||||
struct brcmf_proto {
|
||||
int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws,
|
||||
|
@ -38,6 +41,7 @@ struct brcmf_proto {
|
|||
u8 peer[ETH_ALEN]);
|
||||
void (*add_tdls_peer)(struct brcmf_pub *drvr, int ifidx,
|
||||
u8 peer[ETH_ALEN]);
|
||||
void (*rxreorder)(struct brcmf_if *ifp, struct sk_buff *skb);
|
||||
void *pd;
|
||||
};
|
||||
|
||||
|
@ -91,6 +95,18 @@ brcmf_proto_add_tdls_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
|
|||
{
|
||||
drvr->proto->add_tdls_peer(drvr, ifidx, peer);
|
||||
}
|
||||
static inline bool brcmf_proto_is_reorder_skb(struct sk_buff *skb)
|
||||
{
|
||||
struct brcmf_skb_reorder_data *rd;
|
||||
|
||||
rd = (struct brcmf_skb_reorder_data *)skb->cb;
|
||||
return !!rd->reorder;
|
||||
}
|
||||
|
||||
static inline void
|
||||
brcmf_proto_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb)
|
||||
{
|
||||
ifp->drvr->proto->rxreorder(ifp, skb);
|
||||
}
|
||||
|
||||
#endif /* BRCMFMAC_PROTO_H */
|
||||
|
|
|
@ -1294,6 +1294,17 @@ static inline u8 brcmf_sdio_getdatoffset(u8 *swheader)
|
|||
return (u8)((hdrvalue & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT);
|
||||
}
|
||||
|
||||
static inline bool brcmf_sdio_fromevntchan(u8 *swheader)
|
||||
{
|
||||
u32 hdrvalue;
|
||||
u8 ret;
|
||||
|
||||
hdrvalue = *(u32 *)swheader;
|
||||
ret = (u8)((hdrvalue & SDPCM_CHANNEL_MASK) >> SDPCM_CHANNEL_SHIFT);
|
||||
|
||||
return (ret == SDPCM_EVENT_CHANNEL);
|
||||
}
|
||||
|
||||
static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header,
|
||||
struct brcmf_sdio_hdrinfo *rd,
|
||||
enum brcmf_sdio_frmtype type)
|
||||
|
@ -1641,7 +1652,11 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
|||
pfirst->len, pfirst->next,
|
||||
pfirst->prev);
|
||||
skb_unlink(pfirst, &bus->glom);
|
||||
brcmf_rx_frame(bus->sdiodev->dev, pfirst);
|
||||
if (brcmf_sdio_fromevntchan(pfirst->data))
|
||||
brcmf_rx_event(bus->sdiodev->dev, pfirst);
|
||||
else
|
||||
brcmf_rx_frame(bus->sdiodev->dev, pfirst,
|
||||
false);
|
||||
bus->sdcnt.rxglompkts++;
|
||||
}
|
||||
|
||||
|
@ -1967,18 +1982,19 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
__skb_trim(pkt, rd->len);
|
||||
skb_pull(pkt, rd->dat_offset);
|
||||
|
||||
if (pkt->len == 0)
|
||||
brcmu_pkt_buf_free_skb(pkt);
|
||||
else if (rd->channel == SDPCM_EVENT_CHANNEL)
|
||||
brcmf_rx_event(bus->sdiodev->dev, pkt);
|
||||
else
|
||||
brcmf_rx_frame(bus->sdiodev->dev, pkt,
|
||||
false);
|
||||
|
||||
/* prepare the descriptor for the next read */
|
||||
rd->len = rd->len_nxtfrm << 4;
|
||||
rd->len_nxtfrm = 0;
|
||||
/* treat all packet as event if we don't know */
|
||||
rd->channel = SDPCM_EVENT_CHANNEL;
|
||||
|
||||
if (pkt->len == 0) {
|
||||
brcmu_pkt_buf_free_skb(pkt);
|
||||
continue;
|
||||
}
|
||||
|
||||
brcmf_rx_frame(bus->sdiodev->dev, pkt);
|
||||
}
|
||||
|
||||
rxcount = maxframes - rxleft;
|
||||
|
|
|
@ -514,7 +514,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
|
|||
|
||||
if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
|
||||
skb_put(skb, urb->actual_length);
|
||||
brcmf_rx_frame(devinfo->dev, skb);
|
||||
brcmf_rx_frame(devinfo->dev, skb, true);
|
||||
brcmf_usb_rx_refill(devinfo, req);
|
||||
} else {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
|
|
|
@ -1280,7 +1280,10 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
|||
if (err)
|
||||
goto try_again;
|
||||
|
||||
api_ver = drv->fw.ucode_ver;
|
||||
if (fw_has_api(&drv->fw.ucode_capa, IWL_UCODE_TLV_API_NEW_VERSION))
|
||||
api_ver = drv->fw.ucode_ver;
|
||||
else
|
||||
api_ver = IWL_UCODE_API(drv->fw.ucode_ver);
|
||||
|
||||
/*
|
||||
* api_ver should match the api version forming part of the
|
||||
|
|
|
@ -251,6 +251,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t;
|
|||
* @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source.
|
||||
* @IWL_UCODE_TLV_API_WIDE_CMD_HDR: ucode supports wide command header
|
||||
* @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params
|
||||
* @IWL_UCODE_TLV_API_NEW_VERSION: new versioning format
|
||||
* @IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY: scan APIs use 8-level priority
|
||||
* instead of 3.
|
||||
* @IWL_UCODE_TLV_API_TX_POWER_CHAIN: TX power API has larger command size
|
||||
|
@ -263,6 +264,7 @@ enum iwl_ucode_tlv_api {
|
|||
IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = (__force iwl_ucode_tlv_api_t)9,
|
||||
IWL_UCODE_TLV_API_WIDE_CMD_HDR = (__force iwl_ucode_tlv_api_t)14,
|
||||
IWL_UCODE_TLV_API_LQ_SS_PARAMS = (__force iwl_ucode_tlv_api_t)18,
|
||||
IWL_UCODE_TLV_API_NEW_VERSION = (__force iwl_ucode_tlv_api_t)20,
|
||||
IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY = (__force iwl_ucode_tlv_api_t)24,
|
||||
IWL_UCODE_TLV_API_TX_POWER_CHAIN = (__force iwl_ucode_tlv_api_t)27,
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ktime.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -113,7 +114,7 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base)
|
|||
|
||||
#if VERBOSE > SHOW_ERROR_MESSAGES
|
||||
u32 counter = 0;
|
||||
struct timeval current_time;
|
||||
struct timespec64 current_ts64;
|
||||
DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n");
|
||||
#endif
|
||||
|
||||
|
@ -121,22 +122,22 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base)
|
|||
if (asleep) {
|
||||
/* device is in powersave, trigger the device for wakeup */
|
||||
#if VERBOSE > SHOW_ERROR_MESSAGES
|
||||
do_gettimeofday(¤t_time);
|
||||
DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n",
|
||||
current_time.tv_sec, (long)current_time.tv_usec);
|
||||
ktime_get_real_ts64(¤t_ts64);
|
||||
DEBUG(SHOW_TRACING, "%lld.%09ld Device wakeup triggered\n",
|
||||
(s64)current_ts64.tv_sec, current_ts64.tv_nsec);
|
||||
|
||||
DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
|
||||
current_time.tv_sec, (long)current_time.tv_usec,
|
||||
DEBUG(SHOW_TRACING, "%lld.%09ld Device register read %08x\n",
|
||||
(s64)current_ts64.tv_sec, current_ts64.tv_nsec,
|
||||
readl(device_base + ISL38XX_CTRL_STAT_REG));
|
||||
#endif
|
||||
|
||||
reg = readl(device_base + ISL38XX_INT_IDENT_REG);
|
||||
if (reg == 0xabadface) {
|
||||
#if VERBOSE > SHOW_ERROR_MESSAGES
|
||||
do_gettimeofday(¤t_time);
|
||||
ktime_get_real_ts64(¤t_ts64);
|
||||
DEBUG(SHOW_TRACING,
|
||||
"%08li.%08li Device register abadface\n",
|
||||
current_time.tv_sec, (long)current_time.tv_usec);
|
||||
"%lld.%09ld Device register abadface\n",
|
||||
(s64)current_ts64.tv_sec, current_ts64.tv_nsec);
|
||||
#endif
|
||||
/* read the Device Status Register until Sleepmode bit is set */
|
||||
while (reg = readl(device_base + ISL38XX_CTRL_STAT_REG),
|
||||
|
@ -149,13 +150,13 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base)
|
|||
|
||||
#if VERBOSE > SHOW_ERROR_MESSAGES
|
||||
DEBUG(SHOW_TRACING,
|
||||
"%08li.%08li Device register read %08x\n",
|
||||
current_time.tv_sec, (long)current_time.tv_usec,
|
||||
"%lld.%09ld Device register read %08x\n",
|
||||
(s64)current_ts64.tv_sec, current_ts64.tv_nsec,
|
||||
readl(device_base + ISL38XX_CTRL_STAT_REG));
|
||||
do_gettimeofday(¤t_time);
|
||||
ktime_get_real_ts64(¤t_ts64);
|
||||
DEBUG(SHOW_TRACING,
|
||||
"%08li.%08li Device asleep counter %i\n",
|
||||
current_time.tv_sec, (long)current_time.tv_usec,
|
||||
"%lld.%09ld Device asleep counter %i\n",
|
||||
(s64)current_ts64.tv_sec, current_ts64.tv_nsec,
|
||||
counter);
|
||||
#endif
|
||||
}
|
||||
|
@ -168,9 +169,9 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base)
|
|||
|
||||
/* perform another read on the Device Status Register */
|
||||
reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
|
||||
do_gettimeofday(¤t_time);
|
||||
DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
|
||||
current_time.tv_sec, (long)current_time.tv_usec, reg);
|
||||
ktime_get_real_ts64(¤t_ts64);
|
||||
DEBUG(SHOW_TRACING, "%lld.%00ld Device register read %08x\n",
|
||||
(s64)current_ts64.tv_sec, current_ts64.tv_nsec, reg);
|
||||
#endif
|
||||
} else {
|
||||
/* device is (still) awake */
|
||||
|
|
|
@ -3344,6 +3344,7 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy)
|
|||
struct mwifiex_ds_wakeup_reason wakeup_reason;
|
||||
struct cfg80211_wowlan_wakeup wakeup_report;
|
||||
int i;
|
||||
bool report_wakeup_reason = true;
|
||||
|
||||
for (i = 0; i < adapter->priv_num; i++) {
|
||||
priv = adapter->priv[i];
|
||||
|
@ -3354,6 +3355,9 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy)
|
|||
}
|
||||
}
|
||||
|
||||
if (!wiphy->wowlan_config)
|
||||
goto done;
|
||||
|
||||
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
|
||||
mwifiex_get_wakeup_reason(priv, HostCmd_ACT_GEN_GET, MWIFIEX_SYNC_CMD,
|
||||
&wakeup_reason);
|
||||
|
@ -3386,23 +3390,20 @@ static int mwifiex_cfg80211_resume(struct wiphy *wiphy)
|
|||
if (wiphy->wowlan_config->n_patterns)
|
||||
wakeup_report.pattern_idx = 1;
|
||||
break;
|
||||
case CONTROL_FRAME_MATCHED:
|
||||
break;
|
||||
case MANAGEMENT_FRAME_MATCHED:
|
||||
break;
|
||||
case GTK_REKEY_FAILURE:
|
||||
if (wiphy->wowlan_config->gtk_rekey_failure)
|
||||
wakeup_report.gtk_rekey_failure = true;
|
||||
break;
|
||||
default:
|
||||
report_wakeup_reason = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((wakeup_reason.hs_wakeup_reason > 0) &&
|
||||
(wakeup_reason.hs_wakeup_reason <= 7))
|
||||
if (report_wakeup_reason)
|
||||
cfg80211_report_wowlan_wakeup(&priv->wdev, &wakeup_report,
|
||||
GFP_KERNEL);
|
||||
|
||||
done:
|
||||
if (adapter->nd_info) {
|
||||
for (i = 0 ; i < adapter->nd_info->n_matches ; i++)
|
||||
kfree(adapter->nd_info->matches[i]);
|
||||
|
|
|
@ -104,6 +104,47 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns a command to the command free queue.
|
||||
*
|
||||
* The function also calls the completion callback if required, before
|
||||
* cleaning the command node and re-inserting it into the free queue.
|
||||
*/
|
||||
static void
|
||||
mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
|
||||
struct cmd_ctrl_node *cmd_node)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!cmd_node)
|
||||
return;
|
||||
|
||||
if (cmd_node->wait_q_enabled)
|
||||
mwifiex_complete_cmd(adapter, cmd_node);
|
||||
/* Clean the node */
|
||||
mwifiex_clean_cmd_node(adapter, cmd_node);
|
||||
|
||||
/* Insert node into cmd_free_q */
|
||||
spin_lock_irqsave(&adapter->cmd_free_q_lock, flags);
|
||||
list_add_tail(&cmd_node->list, &adapter->cmd_free_q);
|
||||
spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
|
||||
}
|
||||
|
||||
/* This function reuses a command node. */
|
||||
void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter,
|
||||
struct cmd_ctrl_node *cmd_node)
|
||||
{
|
||||
struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data;
|
||||
|
||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||
|
||||
atomic_dec(&adapter->cmd_pending);
|
||||
mwifiex_dbg(adapter, CMD,
|
||||
"cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n",
|
||||
le16_to_cpu(host_cmd->command),
|
||||
atomic_read(&adapter->cmd_pending));
|
||||
}
|
||||
|
||||
/*
|
||||
* This function sends a host command to the firmware.
|
||||
*
|
||||
|
@ -613,47 +654,6 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns a command to the command free queue.
|
||||
*
|
||||
* The function also calls the completion callback if required, before
|
||||
* cleaning the command node and re-inserting it into the free queue.
|
||||
*/
|
||||
void
|
||||
mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
|
||||
struct cmd_ctrl_node *cmd_node)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!cmd_node)
|
||||
return;
|
||||
|
||||
if (cmd_node->wait_q_enabled)
|
||||
mwifiex_complete_cmd(adapter, cmd_node);
|
||||
/* Clean the node */
|
||||
mwifiex_clean_cmd_node(adapter, cmd_node);
|
||||
|
||||
/* Insert node into cmd_free_q */
|
||||
spin_lock_irqsave(&adapter->cmd_free_q_lock, flags);
|
||||
list_add_tail(&cmd_node->list, &adapter->cmd_free_q);
|
||||
spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
|
||||
}
|
||||
|
||||
/* This function reuses a command node. */
|
||||
void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter,
|
||||
struct cmd_ctrl_node *cmd_node)
|
||||
{
|
||||
struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data;
|
||||
|
||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||
|
||||
atomic_dec(&adapter->cmd_pending);
|
||||
mwifiex_dbg(adapter, CMD,
|
||||
"cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n",
|
||||
le16_to_cpu(host_cmd->command),
|
||||
atomic_read(&adapter->cmd_pending));
|
||||
}
|
||||
|
||||
/*
|
||||
* This function queues a command to the command pending queue.
|
||||
*
|
||||
|
@ -991,6 +991,23 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
|
|||
adapter->if_ops.card_reset(adapter);
|
||||
}
|
||||
|
||||
void
|
||||
mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
struct cmd_ctrl_node *cmd_node = NULL, *tmp_node;
|
||||
unsigned long flags;
|
||||
|
||||
/* Cancel all pending scan command */
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
list_for_each_entry_safe(cmd_node, tmp_node,
|
||||
&adapter->scan_pending_q, list) {
|
||||
list_del(&cmd_node->list);
|
||||
cmd_node->wait_q_enabled = false;
|
||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||
}
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function cancels all the pending commands.
|
||||
*
|
||||
|
@ -1009,9 +1026,9 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
|
|||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||
/* Cancel current cmd */
|
||||
if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) {
|
||||
adapter->curr_cmd->wait_q_enabled = false;
|
||||
adapter->cmd_wait_q.status = -1;
|
||||
mwifiex_complete_cmd(adapter, adapter->curr_cmd);
|
||||
adapter->curr_cmd->wait_q_enabled = false;
|
||||
/* no recycle probably wait for response */
|
||||
}
|
||||
/* Cancel all pending command */
|
||||
|
@ -1029,16 +1046,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
|
|||
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||
|
||||
/* Cancel all pending scan command */
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
list_for_each_entry_safe(cmd_node, tmp_node,
|
||||
&adapter->scan_pending_q, list) {
|
||||
list_del(&cmd_node->list);
|
||||
|
||||
cmd_node->wait_q_enabled = false;
|
||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||
}
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
|
||||
mwifiex_cancel_pending_scan_cmd(adapter);
|
||||
|
||||
if (adapter->scan_processing) {
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||
|
@ -1070,9 +1078,8 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
|
|||
void
|
||||
mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL;
|
||||
struct cmd_ctrl_node *cmd_node = NULL;
|
||||
unsigned long cmd_flags;
|
||||
unsigned long scan_pending_q_flags;
|
||||
struct mwifiex_private *priv;
|
||||
int i;
|
||||
|
||||
|
@ -1094,17 +1101,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
|
|||
mwifiex_recycle_cmd_node(adapter, cmd_node);
|
||||
}
|
||||
|
||||
/* Cancel all pending scan command */
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock,
|
||||
scan_pending_q_flags);
|
||||
list_for_each_entry_safe(cmd_node, tmp_node,
|
||||
&adapter->scan_pending_q, list) {
|
||||
list_del(&cmd_node->list);
|
||||
cmd_node->wait_q_enabled = false;
|
||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||
}
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
||||
scan_pending_q_flags);
|
||||
mwifiex_cancel_pending_scan_cmd(adapter);
|
||||
|
||||
if (adapter->scan_processing) {
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
|
||||
|
|
|
@ -702,6 +702,13 @@ mwifiex_close(struct net_device *dev)
|
|||
priv->scan_aborting = true;
|
||||
}
|
||||
|
||||
if (priv->sched_scanning) {
|
||||
mwifiex_dbg(priv->adapter, INFO,
|
||||
"aborting bgscan on ndo_stop\n");
|
||||
mwifiex_stop_bg_scan(priv);
|
||||
cfg80211_sched_scan_stopped(priv->wdev.wiphy);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -753,13 +760,6 @@ int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb)
|
|||
|
||||
mwifiex_queue_main_work(priv->adapter);
|
||||
|
||||
if (priv->sched_scanning) {
|
||||
mwifiex_dbg(priv->adapter, INFO,
|
||||
"aborting bgscan on ndo_stop\n");
|
||||
mwifiex_stop_bg_scan(priv);
|
||||
cfg80211_sched_scan_stopped(priv->wdev.wiphy);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1434,7 +1434,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
|
|||
struct mwifiex_private *priv = NULL;
|
||||
int i;
|
||||
|
||||
if (down_interruptible(sem))
|
||||
if (down_trylock(sem))
|
||||
goto exit_sem_err;
|
||||
|
||||
if (!adapter)
|
||||
|
|
|
@ -37,6 +37,17 @@
|
|||
#include <linux/idr.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/devcoredump.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
||||
#include "decl.h"
|
||||
#include "ioctl.h"
|
||||
|
@ -100,8 +111,8 @@ enum {
|
|||
#define SCAN_BEACON_ENTRY_PAD 6
|
||||
|
||||
#define MWIFIEX_PASSIVE_SCAN_CHAN_TIME 110
|
||||
#define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 30
|
||||
#define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 30
|
||||
#define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 40
|
||||
#define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 40
|
||||
#define MWIFIEX_DEF_SCAN_CHAN_GAP_TIME 50
|
||||
|
||||
#define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI)))
|
||||
|
@ -1042,9 +1053,8 @@ int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter);
|
|||
int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter);
|
||||
void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter);
|
||||
void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter);
|
||||
void mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter);
|
||||
|
||||
void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
|
||||
struct cmd_ctrl_node *cmd_node);
|
||||
void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter,
|
||||
struct cmd_ctrl_node *cmd_node);
|
||||
|
||||
|
|
|
@ -2811,6 +2811,7 @@ static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter)
|
|||
static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter)
|
||||
{
|
||||
int revision_id = 0;
|
||||
int version;
|
||||
struct pcie_service_card *card = adapter->card;
|
||||
|
||||
switch (card->dev->device) {
|
||||
|
@ -2829,18 +2830,34 @@ static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter)
|
|||
strcpy(adapter->fw_name, PCIE8897_B0_FW_NAME);
|
||||
break;
|
||||
default:
|
||||
strcpy(adapter->fw_name, PCIE8897_DEFAULT_FW_NAME);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PCIE_DEVICE_ID_MARVELL_88W8997:
|
||||
mwifiex_read_reg(adapter, 0x0c48, &revision_id);
|
||||
mwifiex_read_reg(adapter, 0x0cd0, &version);
|
||||
version &= 0x7;
|
||||
switch (revision_id) {
|
||||
case PCIE8997_V2:
|
||||
strcpy(adapter->fw_name, PCIE8997_FW_NAME_V2);
|
||||
if (version == CHIP_VER_PCIEUSB)
|
||||
strcpy(adapter->fw_name,
|
||||
PCIEUSB8997_FW_NAME_V2);
|
||||
else
|
||||
strcpy(adapter->fw_name,
|
||||
PCIEUART8997_FW_NAME_V2);
|
||||
break;
|
||||
case PCIE8997_Z:
|
||||
strcpy(adapter->fw_name, PCIE8997_FW_NAME_Z);
|
||||
if (version == CHIP_VER_PCIEUSB)
|
||||
strcpy(adapter->fw_name,
|
||||
PCIEUSB8997_FW_NAME_Z);
|
||||
else
|
||||
strcpy(adapter->fw_name,
|
||||
PCIEUART8997_FW_NAME_Z);
|
||||
break;
|
||||
default:
|
||||
strcpy(adapter->fw_name, PCIE8997_DEFAULT_FW_NAME);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -30,10 +30,14 @@
|
|||
#include "main.h"
|
||||
|
||||
#define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin"
|
||||
#define PCIE8897_DEFAULT_FW_NAME "mrvl/pcie8897_uapsta.bin"
|
||||
#define PCIE8897_A0_FW_NAME "mrvl/pcie8897_uapsta_a0.bin"
|
||||
#define PCIE8897_B0_FW_NAME "mrvl/pcie8897_uapsta.bin"
|
||||
#define PCIE8997_FW_NAME_Z "mrvl/pcieusb8997_combo.bin"
|
||||
#define PCIE8997_FW_NAME_V2 "mrvl/pcieusb8997_combo_v2.bin"
|
||||
#define PCIE8997_DEFAULT_FW_NAME "mrvl/pcieuart8997_combo_v2.bin"
|
||||
#define PCIEUART8997_FW_NAME_Z "mrvl/pcieuart8997_combo.bin"
|
||||
#define PCIEUART8997_FW_NAME_V2 "mrvl/pcieuart8997_combo_v2.bin"
|
||||
#define PCIEUSB8997_FW_NAME_Z "mrvl/pcieusb8997_combo.bin"
|
||||
#define PCIEUSB8997_FW_NAME_V2 "mrvl/pcieusb8997_combo_v2.bin"
|
||||
|
||||
#define PCIE_VENDOR_ID_MARVELL (0x11ab)
|
||||
#define PCIE_VENDOR_ID_V2_MARVELL (0x1b4b)
|
||||
|
@ -45,6 +49,7 @@
|
|||
#define PCIE8897_B0 0x1200
|
||||
#define PCIE8997_Z 0x0
|
||||
#define PCIE8997_V2 0x471
|
||||
#define CHIP_VER_PCIEUSB 0x2
|
||||
|
||||
/* Constants for Buffer Descriptor (BD) rings */
|
||||
#define MWIFIEX_MAX_TXRX_BD 0x20
|
||||
|
|
|
@ -76,6 +76,39 @@ static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = {
|
|||
{ 0x00, 0x0f, 0xac, 0x04 }, /* AES */
|
||||
};
|
||||
|
||||
static void
|
||||
_dbg_security_flags(int log_level, const char *func, const char *desc,
|
||||
struct mwifiex_private *priv,
|
||||
struct mwifiex_bssdescriptor *bss_desc)
|
||||
{
|
||||
_mwifiex_dbg(priv->adapter, log_level,
|
||||
"info: %s: %s:\twpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\tEncMode=%#x privacy=%#x\n",
|
||||
func, desc,
|
||||
bss_desc->bcn_wpa_ie ?
|
||||
bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0,
|
||||
bss_desc->bcn_rsn_ie ?
|
||||
bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0,
|
||||
priv->sec_info.wep_enabled ? "e" : "d",
|
||||
priv->sec_info.wpa_enabled ? "e" : "d",
|
||||
priv->sec_info.wpa2_enabled ? "e" : "d",
|
||||
priv->sec_info.encryption_mode,
|
||||
bss_desc->privacy);
|
||||
}
|
||||
#define dbg_security_flags(mask, desc, priv, bss_desc) \
|
||||
_dbg_security_flags(MWIFIEX_DBG_##mask, desc, __func__, priv, bss_desc)
|
||||
|
||||
static bool
|
||||
has_ieee_hdr(struct ieee_types_generic *ie, u8 key)
|
||||
{
|
||||
return (ie && ie->ieee_hdr.element_id == key);
|
||||
}
|
||||
|
||||
static bool
|
||||
has_vendor_hdr(struct ieee_types_vendor_specific *ie, u8 key)
|
||||
{
|
||||
return (ie && ie->vend_hdr.element_id == key);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function parses a given IE for a given OUI.
|
||||
*
|
||||
|
@ -121,8 +154,7 @@ mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
|
|||
struct ie_body *iebody;
|
||||
u8 ret = MWIFIEX_OUI_NOT_PRESENT;
|
||||
|
||||
if (((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)).
|
||||
ieee_hdr.element_id == WLAN_EID_RSN))) {
|
||||
if (has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) {
|
||||
iebody = (struct ie_body *)
|
||||
(((u8 *) bss_desc->bcn_rsn_ie->data) +
|
||||
RSN_GTK_OUI_OFFSET);
|
||||
|
@ -148,9 +180,7 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
|
|||
struct ie_body *iebody;
|
||||
u8 ret = MWIFIEX_OUI_NOT_PRESENT;
|
||||
|
||||
if (((bss_desc->bcn_wpa_ie) &&
|
||||
((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id ==
|
||||
WLAN_EID_VENDOR_SPECIFIC))) {
|
||||
if (has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)) {
|
||||
iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data;
|
||||
oui = &mwifiex_wpa_oui[cipher][0];
|
||||
ret = mwifiex_search_oui_in_ie(iebody, oui);
|
||||
|
@ -180,11 +210,8 @@ mwifiex_is_bss_wapi(struct mwifiex_private *priv,
|
|||
struct mwifiex_bssdescriptor *bss_desc)
|
||||
{
|
||||
if (priv->sec_info.wapi_enabled &&
|
||||
(bss_desc->bcn_wapi_ie &&
|
||||
((*(bss_desc->bcn_wapi_ie)).ieee_hdr.element_id ==
|
||||
WLAN_EID_BSS_AC_ACCESS_DELAY))) {
|
||||
has_ieee_hdr(bss_desc->bcn_wapi_ie, WLAN_EID_BSS_AC_ACCESS_DELAY))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -197,12 +224,9 @@ mwifiex_is_bss_no_sec(struct mwifiex_private *priv,
|
|||
struct mwifiex_bssdescriptor *bss_desc)
|
||||
{
|
||||
if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
|
||||
!priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) ||
|
||||
((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id !=
|
||||
WLAN_EID_VENDOR_SPECIFIC)) &&
|
||||
((!bss_desc->bcn_rsn_ie) ||
|
||||
((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id !=
|
||||
WLAN_EID_RSN)) &&
|
||||
!priv->sec_info.wpa2_enabled &&
|
||||
!has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
|
||||
!has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
|
||||
!priv->sec_info.encryption_mode && !bss_desc->privacy) {
|
||||
return true;
|
||||
}
|
||||
|
@ -233,29 +257,14 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv,
|
|||
struct mwifiex_bssdescriptor *bss_desc)
|
||||
{
|
||||
if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled &&
|
||||
!priv->sec_info.wpa2_enabled && ((bss_desc->bcn_wpa_ie) &&
|
||||
((*(bss_desc->bcn_wpa_ie)).
|
||||
vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC))
|
||||
!priv->sec_info.wpa2_enabled &&
|
||||
has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)
|
||||
/*
|
||||
* Privacy bit may NOT be set in some APs like
|
||||
* LinkSys WRT54G && bss_desc->privacy
|
||||
*/
|
||||
) {
|
||||
mwifiex_dbg(priv->adapter, INFO,
|
||||
"info: %s: WPA:\t"
|
||||
"wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t"
|
||||
"EncMode=%#x privacy=%#x\n", __func__,
|
||||
(bss_desc->bcn_wpa_ie) ?
|
||||
(*bss_desc->bcn_wpa_ie).
|
||||
vend_hdr.element_id : 0,
|
||||
(bss_desc->bcn_rsn_ie) ?
|
||||
(*bss_desc->bcn_rsn_ie).
|
||||
ieee_hdr.element_id : 0,
|
||||
(priv->sec_info.wep_enabled) ? "e" : "d",
|
||||
(priv->sec_info.wpa_enabled) ? "e" : "d",
|
||||
(priv->sec_info.wpa2_enabled) ? "e" : "d",
|
||||
priv->sec_info.encryption_mode,
|
||||
bss_desc->privacy);
|
||||
dbg_security_flags(INFO, "WPA", priv, bss_desc);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -269,30 +278,14 @@ static bool
|
|||
mwifiex_is_bss_wpa2(struct mwifiex_private *priv,
|
||||
struct mwifiex_bssdescriptor *bss_desc)
|
||||
{
|
||||
if (!priv->sec_info.wep_enabled &&
|
||||
!priv->sec_info.wpa_enabled &&
|
||||
if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
|
||||
priv->sec_info.wpa2_enabled &&
|
||||
((bss_desc->bcn_rsn_ie) &&
|
||||
((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id == WLAN_EID_RSN))) {
|
||||
has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) {
|
||||
/*
|
||||
* Privacy bit may NOT be set in some APs like
|
||||
* LinkSys WRT54G && bss_desc->privacy
|
||||
*/
|
||||
mwifiex_dbg(priv->adapter, INFO,
|
||||
"info: %s: WPA2:\t"
|
||||
"wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t"
|
||||
"EncMode=%#x privacy=%#x\n", __func__,
|
||||
(bss_desc->bcn_wpa_ie) ?
|
||||
(*bss_desc->bcn_wpa_ie).
|
||||
vend_hdr.element_id : 0,
|
||||
(bss_desc->bcn_rsn_ie) ?
|
||||
(*bss_desc->bcn_rsn_ie).
|
||||
ieee_hdr.element_id : 0,
|
||||
(priv->sec_info.wep_enabled) ? "e" : "d",
|
||||
(priv->sec_info.wpa_enabled) ? "e" : "d",
|
||||
(priv->sec_info.wpa2_enabled) ? "e" : "d",
|
||||
priv->sec_info.encryption_mode,
|
||||
bss_desc->privacy);
|
||||
dbg_security_flags(INFO, "WAP2", priv, bss_desc);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -308,11 +301,8 @@ mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv,
|
|||
{
|
||||
if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
|
||||
!priv->sec_info.wpa2_enabled &&
|
||||
((!bss_desc->bcn_wpa_ie) ||
|
||||
((*(bss_desc->bcn_wpa_ie)).
|
||||
vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
|
||||
((!bss_desc->bcn_rsn_ie) ||
|
||||
((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
|
||||
!has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
|
||||
!has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
|
||||
!priv->sec_info.encryption_mode && bss_desc->privacy) {
|
||||
return true;
|
||||
}
|
||||
|
@ -329,25 +319,10 @@ mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
|
|||
{
|
||||
if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
|
||||
!priv->sec_info.wpa2_enabled &&
|
||||
((!bss_desc->bcn_wpa_ie) ||
|
||||
((*(bss_desc->bcn_wpa_ie)).
|
||||
vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
|
||||
((!bss_desc->bcn_rsn_ie) ||
|
||||
((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
|
||||
!has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
|
||||
!has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
|
||||
priv->sec_info.encryption_mode && bss_desc->privacy) {
|
||||
mwifiex_dbg(priv->adapter, INFO,
|
||||
"info: %s: dynamic\t"
|
||||
"WEP: wpa_ie=%#x wpa2_ie=%#x\t"
|
||||
"EncMode=%#x privacy=%#x\n",
|
||||
__func__,
|
||||
(bss_desc->bcn_wpa_ie) ?
|
||||
(*bss_desc->bcn_wpa_ie).
|
||||
vend_hdr.element_id : 0,
|
||||
(bss_desc->bcn_rsn_ie) ?
|
||||
(*bss_desc->bcn_rsn_ie).
|
||||
ieee_hdr.element_id : 0,
|
||||
priv->sec_info.encryption_mode,
|
||||
bss_desc->privacy);
|
||||
dbg_security_flags(INFO, "dynamic", priv, bss_desc);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -460,18 +435,7 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv,
|
|||
}
|
||||
|
||||
/* Security doesn't match */
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
"info: %s: failed: wpa_ie=%#x wpa2_ie=%#x WEP=%s\t"
|
||||
"WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n",
|
||||
__func__,
|
||||
(bss_desc->bcn_wpa_ie) ?
|
||||
(*bss_desc->bcn_wpa_ie).vend_hdr.element_id : 0,
|
||||
(bss_desc->bcn_rsn_ie) ?
|
||||
(*bss_desc->bcn_rsn_ie).ieee_hdr.element_id : 0,
|
||||
(priv->sec_info.wep_enabled) ? "e" : "d",
|
||||
(priv->sec_info.wpa_enabled) ? "e" : "d",
|
||||
(priv->sec_info.wpa2_enabled) ? "e" : "d",
|
||||
priv->sec_info.encryption_mode, bss_desc->privacy);
|
||||
dbg_security_flags(ERROR, "failed", priv, bss_desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -534,11 +498,13 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
|
|||
&= ~MWIFIEX_PASSIVE_SCAN;
|
||||
scan_chan_list[chan_idx].chan_number =
|
||||
(u32) ch->hw_value;
|
||||
|
||||
scan_chan_list[chan_idx].chan_scan_mode_bitmap
|
||||
|= MWIFIEX_DISABLE_CHAN_FILT;
|
||||
|
||||
if (filtered_scan) {
|
||||
scan_chan_list[chan_idx].max_scan_time =
|
||||
cpu_to_le16(adapter->specific_scan_time);
|
||||
scan_chan_list[chan_idx].chan_scan_mode_bitmap
|
||||
|= MWIFIEX_DISABLE_CHAN_FILT;
|
||||
}
|
||||
chan_idx++;
|
||||
}
|
||||
|
@ -655,8 +621,6 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
|
|||
int ret = 0;
|
||||
struct mwifiex_chan_scan_param_set *tmp_chan_list;
|
||||
struct mwifiex_chan_scan_param_set *start_chan;
|
||||
struct cmd_ctrl_node *cmd_node, *tmp_node;
|
||||
unsigned long flags;
|
||||
u32 tlv_idx, rates_size, cmd_no;
|
||||
u32 total_scan_time;
|
||||
u32 done_early;
|
||||
|
@ -813,16 +777,7 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
|
|||
sizeof(struct mwifiex_ie_types_header) + rates_size;
|
||||
|
||||
if (ret) {
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
list_for_each_entry_safe(cmd_node, tmp_node,
|
||||
&adapter->scan_pending_q,
|
||||
list) {
|
||||
list_del(&cmd_node->list);
|
||||
cmd_node->wait_q_enabled = false;
|
||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||
}
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
||||
flags);
|
||||
mwifiex_cancel_pending_scan_cmd(adapter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -912,14 +867,11 @@ mwifiex_config_scan(struct mwifiex_private *priv,
|
|||
/* Set the BSS type scan filter, use Adapter setting if
|
||||
unset */
|
||||
scan_cfg_out->bss_mode =
|
||||
(user_scan_in->bss_mode ? (u8) user_scan_in->
|
||||
bss_mode : (u8) adapter->scan_mode);
|
||||
(u8)(user_scan_in->bss_mode ?: adapter->scan_mode);
|
||||
|
||||
/* Set the number of probes to send, use Adapter setting
|
||||
if unset */
|
||||
num_probes =
|
||||
(user_scan_in->num_probes ? user_scan_in->
|
||||
num_probes : adapter->scan_probes);
|
||||
num_probes = user_scan_in->num_probes ?: adapter->scan_probes;
|
||||
|
||||
/*
|
||||
* Set the BSSID filter to the incoming configuration,
|
||||
|
@ -1094,28 +1046,24 @@ mwifiex_config_scan(struct mwifiex_private *priv,
|
|||
chan_idx++) {
|
||||
|
||||
channel = user_scan_in->chan_list[chan_idx].chan_number;
|
||||
(scan_chan_list + chan_idx)->chan_number = channel;
|
||||
scan_chan_list[chan_idx].chan_number = channel;
|
||||
|
||||
radio_type =
|
||||
user_scan_in->chan_list[chan_idx].radio_type;
|
||||
(scan_chan_list + chan_idx)->radio_type = radio_type;
|
||||
scan_chan_list[chan_idx].radio_type = radio_type;
|
||||
|
||||
scan_type = user_scan_in->chan_list[chan_idx].scan_type;
|
||||
|
||||
if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
|
||||
(scan_chan_list +
|
||||
chan_idx)->chan_scan_mode_bitmap
|
||||
scan_chan_list[chan_idx].chan_scan_mode_bitmap
|
||||
|= (MWIFIEX_PASSIVE_SCAN |
|
||||
MWIFIEX_HIDDEN_SSID_REPORT);
|
||||
else
|
||||
(scan_chan_list +
|
||||
chan_idx)->chan_scan_mode_bitmap
|
||||
scan_chan_list[chan_idx].chan_scan_mode_bitmap
|
||||
&= ~MWIFIEX_PASSIVE_SCAN;
|
||||
|
||||
if (*filtered_scan)
|
||||
(scan_chan_list +
|
||||
chan_idx)->chan_scan_mode_bitmap
|
||||
|= MWIFIEX_DISABLE_CHAN_FILT;
|
||||
scan_chan_list[chan_idx].chan_scan_mode_bitmap
|
||||
|= MWIFIEX_DISABLE_CHAN_FILT;
|
||||
|
||||
if (user_scan_in->chan_list[chan_idx].scan_time) {
|
||||
scan_dur = (u16) user_scan_in->
|
||||
|
@ -1129,9 +1077,9 @@ mwifiex_config_scan(struct mwifiex_private *priv,
|
|||
scan_dur = adapter->active_scan_time;
|
||||
}
|
||||
|
||||
(scan_chan_list + chan_idx)->min_scan_time =
|
||||
scan_chan_list[chan_idx].min_scan_time =
|
||||
cpu_to_le16(scan_dur);
|
||||
(scan_chan_list + chan_idx)->max_scan_time =
|
||||
scan_chan_list[chan_idx].max_scan_time =
|
||||
cpu_to_le16(scan_dur);
|
||||
}
|
||||
|
||||
|
@ -1991,12 +1939,13 @@ mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
|
|||
static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct cmd_ctrl_node *cmd_node, *tmp_node;
|
||||
struct cmd_ctrl_node *cmd_node;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
if (list_empty(&adapter->scan_pending_q)) {
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
adapter->scan_processing = false;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
|
@ -2018,13 +1967,10 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
|
|||
}
|
||||
} else if ((priv->scan_aborting && !priv->scan_request) ||
|
||||
priv->scan_block) {
|
||||
list_for_each_entry_safe(cmd_node, tmp_node,
|
||||
&adapter->scan_pending_q, list) {
|
||||
list_del(&cmd_node->list);
|
||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||
}
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
|
||||
|
||||
mwifiex_cancel_pending_scan_cmd(adapter);
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
adapter->scan_processing = false;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
|
|
|
@ -73,6 +73,66 @@ static struct memory_type_mapping mem_type_mapping_tbl[] = {
|
|||
{"EXTLAST", NULL, 0, 0xFE},
|
||||
};
|
||||
|
||||
static const struct of_device_id mwifiex_sdio_of_match_table[] = {
|
||||
{ .compatible = "marvell,sd8897" },
|
||||
{ .compatible = "marvell,sd8997" },
|
||||
{ }
|
||||
};
|
||||
|
||||
static irqreturn_t mwifiex_wake_irq_wifi(int irq, void *priv)
|
||||
{
|
||||
struct mwifiex_plt_wake_cfg *cfg = priv;
|
||||
|
||||
if (cfg->irq_wifi >= 0) {
|
||||
pr_info("%s: wake by wifi", __func__);
|
||||
cfg->wake_by_wifi = true;
|
||||
disable_irq_nosync(irq);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* This function parse device tree node using mmc subnode devicetree API.
|
||||
* The device node is saved in card->plt_of_node.
|
||||
* if the device tree node exist and include interrupts attributes, this
|
||||
* function will also request platform specific wakeup interrupt.
|
||||
*/
|
||||
static int mwifiex_sdio_probe_of(struct device *dev, struct sdio_mmc_card *card)
|
||||
{
|
||||
struct mwifiex_plt_wake_cfg *cfg;
|
||||
int ret;
|
||||
|
||||
if (!dev->of_node ||
|
||||
!of_match_node(mwifiex_sdio_of_match_table, dev->of_node)) {
|
||||
pr_err("sdio platform data not available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
card->plt_of_node = dev->of_node;
|
||||
card->plt_wake_cfg = devm_kzalloc(dev, sizeof(*card->plt_wake_cfg),
|
||||
GFP_KERNEL);
|
||||
cfg = card->plt_wake_cfg;
|
||||
if (cfg && card->plt_of_node) {
|
||||
cfg->irq_wifi = irq_of_parse_and_map(card->plt_of_node, 0);
|
||||
if (!cfg->irq_wifi) {
|
||||
dev_err(dev, "fail to parse irq_wifi from device tree");
|
||||
} else {
|
||||
ret = devm_request_irq(dev, cfg->irq_wifi,
|
||||
mwifiex_wake_irq_wifi,
|
||||
IRQF_TRIGGER_LOW,
|
||||
"wifi_wake", cfg);
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Failed to request irq_wifi %d (%d)\n",
|
||||
cfg->irq_wifi, ret);
|
||||
}
|
||||
disable_irq(cfg->irq_wifi);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SDIO probe.
|
||||
*
|
||||
|
@ -127,6 +187,9 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
/* device tree node parsing and platform specific configuration*/
|
||||
mwifiex_sdio_probe_of(&func->dev, card);
|
||||
|
||||
if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops,
|
||||
MWIFIEX_SDIO)) {
|
||||
pr_err("%s: add card failed\n", __func__);
|
||||
|
@ -183,6 +246,13 @@ static int mwifiex_sdio_resume(struct device *dev)
|
|||
mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
|
||||
MWIFIEX_SYNC_CMD);
|
||||
|
||||
/* Disable platform specific wakeup interrupt */
|
||||
if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
|
||||
disable_irq_wake(card->plt_wake_cfg->irq_wifi);
|
||||
if (!card->plt_wake_cfg->wake_by_wifi)
|
||||
disable_irq(card->plt_wake_cfg->irq_wifi);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -262,6 +332,13 @@ static int mwifiex_sdio_suspend(struct device *dev)
|
|||
|
||||
adapter = card->adapter;
|
||||
|
||||
/* Enable platform specific wakeup interrupt */
|
||||
if (card->plt_wake_cfg && card->plt_wake_cfg->irq_wifi >= 0) {
|
||||
card->plt_wake_cfg->wake_by_wifi = false;
|
||||
enable_irq(card->plt_wake_cfg->irq_wifi);
|
||||
enable_irq_wake(card->plt_wake_cfg->irq_wifi);
|
||||
}
|
||||
|
||||
/* Enable the Host Sleep */
|
||||
if (!mwifiex_enable_hs(adapter)) {
|
||||
mwifiex_dbg(adapter, ERROR,
|
||||
|
@ -1026,13 +1103,12 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
|
|||
offset += txlen;
|
||||
} while (true);
|
||||
|
||||
sdio_release_host(card->func);
|
||||
|
||||
mwifiex_dbg(adapter, MSG,
|
||||
"info: FW download over, size %d bytes\n", offset);
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
sdio_release_host(card->func);
|
||||
kfree(fwbuf);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -154,6 +154,11 @@
|
|||
a->mpa_rx.start_port = 0; \
|
||||
} while (0)
|
||||
|
||||
struct mwifiex_plt_wake_cfg {
|
||||
int irq_wifi;
|
||||
bool wake_by_wifi;
|
||||
};
|
||||
|
||||
/* data structure for SDIO MPA TX */
|
||||
struct mwifiex_sdio_mpa_tx {
|
||||
/* multiport tx aggregation buffer pointer */
|
||||
|
@ -237,6 +242,8 @@ struct mwifiex_sdio_card_reg {
|
|||
struct sdio_mmc_card {
|
||||
struct sdio_func *func;
|
||||
struct mwifiex_adapter *adapter;
|
||||
struct device_node *plt_of_node;
|
||||
struct mwifiex_plt_wake_cfg *plt_wake_cfg;
|
||||
|
||||
const char *firmware;
|
||||
const struct mwifiex_sdio_card_reg *reg;
|
||||
|
|
|
@ -2162,6 +2162,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
|
|||
enum state_11d_t state_11d;
|
||||
struct mwifiex_ds_11n_tx_cfg tx_cfg;
|
||||
u8 sdio_sp_rx_aggr_enable;
|
||||
int data;
|
||||
|
||||
if (first_sta) {
|
||||
if (priv->adapter->iface_type == MWIFIEX_PCIE) {
|
||||
|
@ -2182,9 +2183,16 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
|
|||
* The cal-data can be read from device tree and/or
|
||||
* a configuration file and downloaded to firmware.
|
||||
*/
|
||||
adapter->dt_node =
|
||||
of_find_node_by_name(NULL, "marvell_cfgdata");
|
||||
if (adapter->dt_node) {
|
||||
if (priv->adapter->iface_type == MWIFIEX_SDIO &&
|
||||
adapter->dev->of_node) {
|
||||
adapter->dt_node = adapter->dev->of_node;
|
||||
if (of_property_read_u32(adapter->dt_node,
|
||||
"marvell,wakeup-pin",
|
||||
&data) == 0) {
|
||||
pr_debug("Wakeup pin = 0x%x\n", data);
|
||||
adapter->hs_cfg.gpio = data;
|
||||
}
|
||||
|
||||
ret = mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node,
|
||||
"marvell,caldata");
|
||||
if (ret)
|
||||
|
|
|
@ -44,7 +44,6 @@ static void
|
|||
mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
|
||||
struct host_cmd_ds_command *resp)
|
||||
{
|
||||
struct cmd_ctrl_node *cmd_node = NULL, *tmp_node;
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
struct host_cmd_ds_802_11_ps_mode_enh *pm;
|
||||
unsigned long flags;
|
||||
|
@ -71,17 +70,7 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
|
|||
break;
|
||||
case HostCmd_CMD_802_11_SCAN:
|
||||
case HostCmd_CMD_802_11_SCAN_EXT:
|
||||
/* Cancel all pending scan command */
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
list_for_each_entry_safe(cmd_node, tmp_node,
|
||||
&adapter->scan_pending_q, list) {
|
||||
list_del(&cmd_node->list);
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
||||
flags);
|
||||
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
|
||||
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
|
||||
mwifiex_cancel_pending_scan_cmd(adapter);
|
||||
|
||||
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
|
||||
adapter->scan_processing = false;
|
||||
|
|
|
@ -146,6 +146,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
|
|||
size_t beacon_ie_len;
|
||||
struct mwifiex_bss_priv *bss_priv = (void *)bss->priv;
|
||||
const struct cfg80211_bss_ies *ies;
|
||||
int ret;
|
||||
|
||||
rcu_read_lock();
|
||||
ies = rcu_dereference(bss->ies);
|
||||
|
@ -189,7 +190,48 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
|
|||
if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_SPECTRUM_MGMT)
|
||||
bss_desc->sensed_11h = true;
|
||||
|
||||
return mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc);
|
||||
ret = mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Update HT40 capability based on current channel information */
|
||||
if (bss_desc->bcn_ht_oper && bss_desc->bcn_ht_cap) {
|
||||
u8 ht_param = bss_desc->bcn_ht_oper->ht_param;
|
||||
u8 radio = mwifiex_band_to_radio_type(bss_desc->bss_band);
|
||||
struct ieee80211_supported_band *sband =
|
||||
priv->wdev.wiphy->bands[radio];
|
||||
int freq = ieee80211_channel_to_frequency(bss_desc->channel,
|
||||
radio);
|
||||
struct ieee80211_channel *chan =
|
||||
ieee80211_get_channel(priv->adapter->wiphy, freq);
|
||||
|
||||
switch (ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
|
||||
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
|
||||
if (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) {
|
||||
sband->ht_cap.cap &=
|
||||
~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
|
||||
} else {
|
||||
sband->ht_cap.cap |=
|
||||
IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
|
||||
IEEE80211_HT_CAP_SGI_40;
|
||||
}
|
||||
break;
|
||||
case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
|
||||
if (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) {
|
||||
sband->ht_cap.cap &=
|
||||
~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
|
||||
} else {
|
||||
sband->ht_cap.cap |=
|
||||
IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
|
||||
IEEE80211_HT_CAP_SGI_40;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv)
|
||||
|
|
|
@ -297,6 +297,13 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
|
|||
goto done;
|
||||
|
||||
mwifiex_set_trans_start(priv->netdev);
|
||||
|
||||
if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
|
||||
atomic_dec_return(&adapter->pending_bridged_pkts);
|
||||
|
||||
if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
|
||||
goto done;
|
||||
|
||||
if (!status) {
|
||||
priv->stats.tx_packets++;
|
||||
priv->stats.tx_bytes += tx_info->pkt_len;
|
||||
|
@ -306,12 +313,6 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
|
|||
priv->stats.tx_errors++;
|
||||
}
|
||||
|
||||
if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
|
||||
atomic_dec_return(&adapter->pending_bridged_pkts);
|
||||
|
||||
if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
|
||||
goto done;
|
||||
|
||||
if (aggr)
|
||||
/* For skb_aggr, do not wake up tx queue */
|
||||
goto done;
|
||||
|
|
|
@ -102,6 +102,7 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
|
|||
int hdr_chop;
|
||||
struct ethhdr *p_ethhdr;
|
||||
struct mwifiex_sta_node *src_node;
|
||||
int index;
|
||||
|
||||
uap_rx_pd = (struct uap_rxpd *)(skb->data);
|
||||
rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
|
||||
|
@ -208,6 +209,9 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
|
|||
}
|
||||
|
||||
__net_timestamp(skb);
|
||||
|
||||
index = mwifiex_1d_to_wmm_queue[skb->priority];
|
||||
atomic_inc(&priv->wmm_tx_pending[index]);
|
||||
mwifiex_wmm_add_buf_txqueue(priv, skb);
|
||||
atomic_inc(&adapter->tx_pending);
|
||||
atomic_inc(&adapter->pending_bridged_pkts);
|
||||
|
|
|
@ -995,7 +995,8 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
|
|||
{
|
||||
int ret = 0;
|
||||
u8 *firmware = fw->fw_buf, *recv_buff;
|
||||
u32 retries = USB8XXX_FW_MAX_RETRY, dlen;
|
||||
u32 retries = USB8XXX_FW_MAX_RETRY + 1;
|
||||
u32 dlen;
|
||||
u32 fw_seqnum = 0, tlen = 0, dnld_cmd = 0;
|
||||
struct fw_data *fwdata;
|
||||
struct fw_sync_header sync_fw;
|
||||
|
@ -1017,8 +1018,10 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
|
|||
|
||||
/* Allocate memory for receive */
|
||||
recv_buff = kzalloc(FW_DNLD_RX_BUF_SIZE, GFP_KERNEL);
|
||||
if (!recv_buff)
|
||||
if (!recv_buff) {
|
||||
ret = -ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
do {
|
||||
/* Send pseudo data to check winner status first */
|
||||
|
@ -1041,7 +1044,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
|
|||
}
|
||||
|
||||
/* If the send/receive fails or CRC occurs then retry */
|
||||
while (retries--) {
|
||||
while (--retries) {
|
||||
u8 *buf = (u8 *)fwdata;
|
||||
u32 len = FW_DATA_XMIT_SIZE;
|
||||
|
||||
|
@ -1101,7 +1104,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
|
|||
continue;
|
||||
}
|
||||
|
||||
retries = USB8XXX_FW_MAX_RETRY;
|
||||
retries = USB8XXX_FW_MAX_RETRY + 1;
|
||||
break;
|
||||
}
|
||||
fw_seqnum++;
|
||||
|
|
|
@ -7492,6 +7492,10 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||
if (!rt2x00_is_usb(rt2x00dev))
|
||||
ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING);
|
||||
|
||||
/* Set MFP if HW crypto is disabled. */
|
||||
if (rt2800_hwcrypt_disabled(rt2x00dev))
|
||||
ieee80211_hw_set(rt2x00dev->hw, MFP_CAPABLE);
|
||||
|
||||
SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
|
||||
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
|
||||
rt2800_eeprom_addr(rt2x00dev,
|
||||
|
|
|
@ -1018,6 +1018,8 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev)
|
|||
dma_addr_t *mapping;
|
||||
entry = priv->rx_ring + priv->rx_ring_sz*i;
|
||||
if (!skb) {
|
||||
pci_free_consistent(priv->pdev, priv->rx_ring_sz * 32,
|
||||
priv->rx_ring, priv->rx_ring_dma);
|
||||
wiphy_err(dev->wiphy, "Cannot allocate RX skb\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -1028,6 +1030,8 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev)
|
|||
|
||||
if (pci_dma_mapping_error(priv->pdev, *mapping)) {
|
||||
kfree_skb(skb);
|
||||
pci_free_consistent(priv->pdev, priv->rx_ring_sz * 32,
|
||||
priv->rx_ring, priv->rx_ring_dma);
|
||||
wiphy_err(dev->wiphy, "Cannot map DMA for RX skb\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014 - 2015 Jes Sorensen <Jes.Sorensen@redhat.com>
|
||||
* Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -42,12 +42,18 @@
|
|||
#define REALTEK_USB_CMD_IDX 0x00
|
||||
|
||||
#define TX_TOTAL_PAGE_NUM 0xf8
|
||||
#define TX_TOTAL_PAGE_NUM_8192E 0xf3
|
||||
/* (HPQ + LPQ + NPQ + PUBQ) = TX_TOTAL_PAGE_NUM */
|
||||
#define TX_PAGE_NUM_PUBQ 0xe7
|
||||
#define TX_PAGE_NUM_HI_PQ 0x0c
|
||||
#define TX_PAGE_NUM_LO_PQ 0x02
|
||||
#define TX_PAGE_NUM_NORM_PQ 0x02
|
||||
|
||||
#define TX_PAGE_NUM_PUBQ_8192E 0xe7
|
||||
#define TX_PAGE_NUM_HI_PQ_8192E 0x08
|
||||
#define TX_PAGE_NUM_LO_PQ_8192E 0x0c
|
||||
#define TX_PAGE_NUM_NORM_PQ_8192E 0x00
|
||||
|
||||
#define RTL_FW_PAGE_SIZE 4096
|
||||
#define RTL8XXXU_FIRMWARE_POLL_MAX 1000
|
||||
|
||||
|
@ -95,7 +101,7 @@ enum rtl8xxxu_rx_type {
|
|||
RX_TYPE_ERROR = -1
|
||||
};
|
||||
|
||||
struct rtl8xxxu_rx_desc {
|
||||
struct rtl8xxxu_rxdesc16 {
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
u32 pktlen:14;
|
||||
u32 crc32:1;
|
||||
|
@ -231,7 +237,7 @@ struct rtl8xxxu_rx_desc {
|
|||
#endif
|
||||
};
|
||||
|
||||
struct rtl8723bu_rx_desc {
|
||||
struct rtl8xxxu_rxdesc24 {
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
u32 pktlen:14;
|
||||
u32 crc32:1;
|
||||
|
@ -623,6 +629,31 @@ struct rtl8xxxu_firmware_header {
|
|||
u8 data[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* 8723au/8192cu/8188ru required base power index offset tables.
|
||||
*/
|
||||
struct rtl8xxxu_power_base {
|
||||
u32 reg_0e00;
|
||||
u32 reg_0e04;
|
||||
u32 reg_0e08;
|
||||
u32 reg_086c;
|
||||
|
||||
u32 reg_0e10;
|
||||
u32 reg_0e14;
|
||||
u32 reg_0e18;
|
||||
u32 reg_0e1c;
|
||||
|
||||
u32 reg_0830;
|
||||
u32 reg_0834;
|
||||
u32 reg_0838;
|
||||
u32 reg_086c_2;
|
||||
|
||||
u32 reg_083c;
|
||||
u32 reg_0848;
|
||||
u32 reg_084c;
|
||||
u32 reg_0868;
|
||||
};
|
||||
|
||||
/*
|
||||
* The 8723au has 3 channel groups: 1-3, 4-9, and 10-14
|
||||
*/
|
||||
|
@ -787,55 +818,49 @@ struct rtl8192eu_efuse_tx_power {
|
|||
u8 cck_base[6];
|
||||
u8 ht40_base[5];
|
||||
struct rtl8723au_idx ht20_ofdm_1s_diff;
|
||||
struct rtl8723au_idx ht40_ht20_2s_diff;
|
||||
struct rtl8723au_idx ofdm_cck_2s_diff; /* not used */
|
||||
struct rtl8723au_idx ht40_ht20_3s_diff;
|
||||
struct rtl8723au_idx ofdm_cck_3s_diff; /* not used */
|
||||
struct rtl8723au_idx ht40_ht20_4s_diff;
|
||||
struct rtl8723au_idx ofdm_cck_4s_diff; /* not used */
|
||||
struct rtl8723bu_pwr_idx pwr_diff[3];
|
||||
u8 dummy5g[24]; /* max channel group (14) + power diff offset (10) */
|
||||
};
|
||||
|
||||
struct rtl8192eu_efuse {
|
||||
__le16 rtl_id;
|
||||
u8 res0[0x0e];
|
||||
struct rtl8192eu_efuse_tx_power tx_power_index_A; /* 0x10 */
|
||||
struct rtl8192eu_efuse_tx_power tx_power_index_B; /* 0x22 */
|
||||
struct rtl8192eu_efuse_tx_power tx_power_index_C; /* 0x34 */
|
||||
struct rtl8192eu_efuse_tx_power tx_power_index_D; /* 0x46 */
|
||||
u8 res1[0x60];
|
||||
struct rtl8192eu_efuse_tx_power tx_power_index_B; /* 0x3a */
|
||||
u8 res2[0x54];
|
||||
u8 channel_plan; /* 0xb8 */
|
||||
u8 xtal_k;
|
||||
u8 thermal_meter;
|
||||
u8 iqk_lck;
|
||||
u8 pa_type; /* 0xbc */
|
||||
u8 lna_type_2g; /* 0xbd */
|
||||
u8 res2[1];
|
||||
u8 res3[1];
|
||||
u8 lna_type_5g; /* 0xbf */
|
||||
u8 res13[1];
|
||||
u8 res4[1];
|
||||
u8 rf_board_option;
|
||||
u8 rf_feature_option;
|
||||
u8 rf_bt_setting;
|
||||
u8 eeprom_version;
|
||||
u8 eeprom_customer_id;
|
||||
u8 res3[3];
|
||||
u8 res5[3];
|
||||
u8 rf_antenna_option; /* 0xc9 */
|
||||
u8 res4[6];
|
||||
u8 res6[6];
|
||||
u8 vid; /* 0xd0 */
|
||||
u8 res5[1];
|
||||
u8 res7[1];
|
||||
u8 pid; /* 0xd2 */
|
||||
u8 res6[1];
|
||||
u8 res8[1];
|
||||
u8 usb_optional_function;
|
||||
u8 res7[2];
|
||||
u8 mac_addr[ETH_ALEN]; /* 0xd7 */
|
||||
u8 res8[2];
|
||||
u8 vendor_name[7];
|
||||
u8 res9[2];
|
||||
u8 device_name[0x0b]; /* 0xe8 */
|
||||
u8 mac_addr[ETH_ALEN]; /* 0xd7 */
|
||||
u8 res10[2];
|
||||
u8 vendor_name[7];
|
||||
u8 res11[2];
|
||||
u8 device_name[0x0b]; /* 0xe8 */
|
||||
u8 res12[2];
|
||||
u8 serial[0x0b]; /* 0xf5 */
|
||||
u8 res11[0x30];
|
||||
u8 res13[0x30];
|
||||
u8 unknown[0x0d]; /* 0x130 */
|
||||
u8 res12[0xc3];
|
||||
u8 res14[0xc3];
|
||||
};
|
||||
|
||||
struct rtl8xxxu_reg8val {
|
||||
|
@ -1201,6 +1226,7 @@ struct rtl8xxxu_priv {
|
|||
struct rtl8723au_idx ofdm_tx_power_diff[RTL8723B_TX_COUNT];
|
||||
struct rtl8723au_idx ht20_tx_power_diff[RTL8723B_TX_COUNT];
|
||||
struct rtl8723au_idx ht40_tx_power_diff[RTL8723B_TX_COUNT];
|
||||
struct rtl8xxxu_power_base *power_base;
|
||||
u32 chip_cut:4;
|
||||
u32 rom_rev:4;
|
||||
u32 is_multi_func:1;
|
||||
|
@ -1228,7 +1254,6 @@ struct rtl8xxxu_priv {
|
|||
u8 rf_paths;
|
||||
u8 rx_paths;
|
||||
u8 tx_paths;
|
||||
u32 rf_mode_ag[2];
|
||||
u32 rege94;
|
||||
u32 rege9c;
|
||||
u32 regeb4;
|
||||
|
@ -1262,6 +1287,7 @@ struct rtl8xxxu_priv {
|
|||
u32 bb_recovery_backup[RTL8XXXU_BB_REGS];
|
||||
enum rtl8xxxu_rtl_chip rtl_chip;
|
||||
u8 pi_enabled:1;
|
||||
u8 no_pape:1;
|
||||
u8 int_buf[USB_INTR_CONTENT_LENGTH];
|
||||
};
|
||||
|
||||
|
@ -1284,6 +1310,8 @@ struct rtl8xxxu_fileops {
|
|||
void (*power_off) (struct rtl8xxxu_priv *priv);
|
||||
void (*reset_8051) (struct rtl8xxxu_priv *priv);
|
||||
int (*llt_init) (struct rtl8xxxu_priv *priv, u8 last_tx_page);
|
||||
void (*init_phy_bb) (struct rtl8xxxu_priv *priv);
|
||||
int (*init_phy_rf) (struct rtl8xxxu_priv *priv);
|
||||
void (*phy_init_antenna_selection) (struct rtl8xxxu_priv *priv);
|
||||
void (*phy_iq_calibrate) (struct rtl8xxxu_priv *priv);
|
||||
void (*config_channel) (struct ieee80211_hw *hw);
|
||||
|
@ -1293,6 +1321,7 @@ struct rtl8xxxu_fileops {
|
|||
void (*init_statistics) (struct rtl8xxxu_priv *priv);
|
||||
void (*enable_rf) (struct rtl8xxxu_priv *priv);
|
||||
void (*disable_rf) (struct rtl8xxxu_priv *priv);
|
||||
void (*usb_quirks) (struct rtl8xxxu_priv *priv);
|
||||
void (*set_tx_power) (struct rtl8xxxu_priv *priv, int channel,
|
||||
bool ht40);
|
||||
void (*update_rate_mask) (struct rtl8xxxu_priv *priv,
|
||||
|
@ -1303,9 +1332,18 @@ struct rtl8xxxu_fileops {
|
|||
u16 mbox_ext_reg;
|
||||
char mbox_ext_width;
|
||||
char tx_desc_size;
|
||||
char rx_desc_size;
|
||||
char has_s0s1;
|
||||
u32 adda_1t_init;
|
||||
u32 adda_1t_path_on;
|
||||
u32 adda_2t_path_on_a;
|
||||
u32 adda_2t_path_on_b;
|
||||
u16 trxff_boundary;
|
||||
u8 pbp_rx;
|
||||
u8 pbp_tx;
|
||||
struct rtl8xxxu_reg8val *mactable;
|
||||
u8 total_page_num;
|
||||
u8 page_num_hi;
|
||||
u8 page_num_lo;
|
||||
u8 page_num_norm;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014 - 2015 Jes Sorensen <Jes.Sorensen@redhat.com>
|
||||
* Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -109,6 +109,9 @@
|
|||
#define AFE_XTAL_GATE_DIG BIT(17)
|
||||
#define AFE_XTAL_BT_GATE BIT(20)
|
||||
|
||||
/*
|
||||
* 0x0028 is also known as REG_AFE_CTRL2 on 8723bu/8192eu
|
||||
*/
|
||||
#define REG_AFE_PLL_CTRL 0x0028
|
||||
#define AFE_PLL_ENABLE BIT(0)
|
||||
#define AFE_PLL_320_ENABLE BIT(1)
|
||||
|
@ -192,6 +195,7 @@
|
|||
control */
|
||||
#define MULTI_GPS_FUNC_EN BIT(22) /* GPS function enable */
|
||||
|
||||
#define REG_AFE_CTRL4 0x0078 /* 8192eu/8723bu */
|
||||
#define REG_LDO_SW_CTRL 0x007c /* 8192eu */
|
||||
|
||||
#define REG_MCU_FW_DL 0x0080
|
||||
|
@ -383,7 +387,7 @@
|
|||
#define REG_RQPN 0x0200
|
||||
#define RQPN_HI_PQ_SHIFT 0
|
||||
#define RQPN_LO_PQ_SHIFT 8
|
||||
#define RQPN_NORM_PQ_SHIFT 16
|
||||
#define RQPN_PUB_PQ_SHIFT 16
|
||||
#define RQPN_LOAD BIT(31)
|
||||
|
||||
#define REG_FIFOPAGE 0x0204
|
||||
|
@ -512,6 +516,7 @@
|
|||
#define REG_PKT_VO_VI_LIFE_TIME 0x04c0
|
||||
#define REG_PKT_BE_BK_LIFE_TIME 0x04c2
|
||||
#define REG_STBC_SETTING 0x04c4
|
||||
#define REG_QUEUE_CTRL 0x04c6
|
||||
#define REG_HT_SINGLE_AMPDU_8723B 0x04c7
|
||||
#define REG_PROT_MODE_CTRL 0x04c8
|
||||
#define REG_MAX_AGGR_NUM 0x04ca
|
||||
|
@ -877,6 +882,10 @@
|
|||
#define CCK0_SIDEBAND BIT(4)
|
||||
|
||||
#define REG_CCK0_AFE_SETTING 0x0a04
|
||||
#define CCK0_AFE_RX_MASK 0x0f000000
|
||||
#define CCK0_AFE_RX_ANT_AB BIT(24)
|
||||
#define CCK0_AFE_RX_ANT_A 0
|
||||
#define CCK0_AFE_RX_ANT_B (BIT(24) | BIT(26))
|
||||
|
||||
#define REG_CONFIG_ANT_A 0x0b68
|
||||
#define REG_CONFIG_ANT_B 0x0b6c
|
||||
|
@ -1043,6 +1052,7 @@
|
|||
#define USB_HIMR_ROK BIT(0) /* Receive DMA OK Interrupt */
|
||||
|
||||
#define REG_USB_SPECIAL_OPTION 0xfe55
|
||||
#define REG_USB_HRPWM 0xfe58
|
||||
#define REG_USB_DMA_AGG_TO 0xfe5b
|
||||
#define REG_USB_AGG_TO 0xfe5c
|
||||
#define REG_USB_AGG_TH 0xfe5d
|
||||
|
@ -1128,6 +1138,7 @@
|
|||
#define RF6052_REG_T_METER_8723B 0x42
|
||||
#define RF6052_REG_UNKNOWN_43 0x43
|
||||
#define RF6052_REG_UNKNOWN_55 0x55
|
||||
#define RF6052_REG_UNKNOWN_56 0x56
|
||||
#define RF6052_REG_S0S1 0xb0
|
||||
#define RF6052_REG_UNKNOWN_DF 0xdf
|
||||
#define RF6052_REG_UNKNOWN_ED 0xed
|
||||
|
|
|
@ -959,7 +959,7 @@ static void _rtl8821ae_phy_store_txpower_by_rate_base(struct ieee80211_hw *hw)
|
|||
static void _phy_convert_txpower_dbm_to_relative_value(u32 *data, u8 start,
|
||||
u8 end, u8 base_val)
|
||||
{
|
||||
char i = 0;
|
||||
int i;
|
||||
u8 temp_value = 0;
|
||||
u32 temp_data = 0;
|
||||
|
||||
|
|
Loading…
Reference in New Issue