From 1019f9efcb9fa0cea4b361604b438fef3ea3e394 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 30 Sep 2019 14:45:54 +0200 Subject: [PATCH 01/96] iwlwifi: mvm: update powersave correctly for D3 This fixes a long-standing bug - we haven't been able to check the firmware image that was loaded for D3/not-D3 since the introduction of the unified image... Fix this by keeping a status flag for D3 instead of checking for the firmware image that's loaded. This reduces occurrences of checks for IWL_UCODE_WOWLAN to just the code that actually loads the image or deals with it in other ways. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 6 +++++ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 ++ .../net/wireless/intel/iwlwifi/mvm/power.c | 27 +++++++++---------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 43ebb2149b63..8878409d2f07 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -989,6 +989,8 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, mutex_lock(&mvm->mutex); + set_bit(IWL_MVM_STATUS_IN_D3, &mvm->status); + vif = iwl_mvm_get_bss_vif(mvm); if (IS_ERR_OR_NULL(vif)) { ret = 1; @@ -1083,6 +1085,8 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, ieee80211_restart_hw(mvm->hw); } } + + clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status); } out_noreset: mutex_unlock(&mvm->mutex); @@ -1929,6 +1933,8 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) mutex_lock(&mvm->mutex); + clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status); + /* get the BSS vif pointer again */ vif = iwl_mvm_get_bss_vif(mvm); if (IS_ERR_OR_NULL(vif)) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 3ec8de00f3aa..3571b71fc51e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1160,6 +1160,7 @@ struct iwl_mvm { * @IWL_MVM_STATUS_ROC_AUX_RUNNING: AUX remain-on-channel is running * @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running * @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA + * @IWL_MVM_STATUS_IN_D3: in D3 (or at least about to go into it) */ enum iwl_mvm_status { IWL_MVM_STATUS_HW_RFKILL, @@ -1170,6 +1171,7 @@ enum iwl_mvm_status { IWL_MVM_STATUS_ROC_AUX_RUNNING, IWL_MVM_STATUS_FIRMWARE_RUNNING, IWL_MVM_STATUS_NEED_FLUSH_P2P, + IWL_MVM_STATUS_IN_D3, }; /* Keep track of completed init configuration */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index 25d7faea1c62..c146303ec73b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -198,7 +198,7 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm, if (!mvmvif->queue_params[ac].uapsd) continue; - if (mvm->fwrt.cur_fw_img != IWL_UCODE_WOWLAN) + if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) cmd->flags |= cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK); @@ -233,15 +233,15 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm, cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK); cmd->snooze_interval = cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL); cmd->snooze_window = - (mvm->fwrt.cur_fw_img == IWL_UCODE_WOWLAN) ? + test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ? cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) : cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW); } cmd->uapsd_max_sp = mvm->hw->uapsd_max_sp_len; - if (mvm->fwrt.cur_fw_img == IWL_UCODE_WOWLAN || cmd->flags & - cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { + if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) || + cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { cmd->rx_data_timeout_uapsd = cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); cmd->tx_data_timeout_uapsd = @@ -354,8 +354,7 @@ static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif) static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct iwl_mac_power_cmd *cmd, - bool host_awake) + struct iwl_mac_power_cmd *cmd) { int dtimper = vif->bss_conf.dtim_period ?: 1; int skip; @@ -370,7 +369,7 @@ static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm, if (dtimper >= 10) return; - if (host_awake) { + if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) { if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_LP) return; skip = 2; @@ -390,8 +389,7 @@ static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm, static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct iwl_mac_power_cmd *cmd, - bool host_awake) + struct iwl_mac_power_cmd *cmd) { int dtimper, bi; int keep_alive; @@ -437,9 +435,9 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD; } - iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, host_awake); + iwl_mvm_power_config_skip_dtim(mvm, vif, cmd); - if (!host_awake) { + if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) { cmd->rx_data_timeout = cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); cmd->tx_data_timeout = @@ -512,8 +510,7 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm, { struct iwl_mac_power_cmd cmd = {}; - iwl_mvm_power_build_cmd(mvm, vif, &cmd, - mvm->fwrt.cur_fw_img != IWL_UCODE_WOWLAN); + iwl_mvm_power_build_cmd(mvm, vif, &cmd); iwl_mvm_power_log(mvm, &cmd); #ifdef CONFIG_IWLWIFI_DEBUGFS memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd)); @@ -536,7 +533,7 @@ int iwl_mvm_power_update_device(struct iwl_mvm *mvm) cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK); #ifdef CONFIG_IWLWIFI_DEBUGFS - if ((mvm->fwrt.cur_fw_img == IWL_UCODE_WOWLAN) ? + if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ? mvm->disable_power_off_d3 : mvm->disable_power_off) cmd.flags &= cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK); @@ -943,7 +940,7 @@ static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm, if (!mvmvif->bf_data.bf_enabled) return 0; - if (mvm->fwrt.cur_fw_img == IWL_UCODE_WOWLAN) + if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3); mvmvif->bf_data.ba_enabled = !(!mvmvif->pm_enabled || From efaaa97c0e7f14c48ee406a37ba25ff3915c6e50 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 1 Oct 2019 14:42:28 +0300 Subject: [PATCH 02/96] iwlwifi: dbg_ini: don't skip a TX FIFO when dumping Before we start looping over the internal TX FIFOs increase the fifo number, but that's incorrect and causes a FIFO to be skipped. This is probably due to a copy and paste from the previous loop. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index ed90dd104366..c8bc6b9b53a4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1230,13 +1230,15 @@ static bool iwl_ini_txf_iter(struct iwl_fw_runtime *fwrt, iter->lmac = 0; } - if (!iter->internal_txf) + if (!iter->internal_txf) { for (iter->fifo++; iter->fifo < txf_num; iter->fifo++) { iter->fifo_size = cfg->lmac[iter->lmac].txfifo_size[iter->fifo]; if (iter->fifo_size && (lmac_bitmap & BIT(iter->fifo))) return true; } + iter->fifo--; + } iter->internal_txf = 1; From 5b5b9d35e05a01afacda745a0877105d33f7a768 Mon Sep 17 00:00:00 2001 From: Tova Mussai Date: Thu, 3 Oct 2019 20:17:07 +0300 Subject: [PATCH 03/96] iwlwifi: scan: remove support for fw scan api v11 The fw already support scan api v12, v11 is not needed anymore. Signed-off-by: Tova Mussai Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/scan.h | 41 ---------------- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 47 ------------------- 2 files changed, 88 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h index 408798f351c6..1b2b5fa56e19 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h @@ -921,21 +921,6 @@ struct iwl_scan_probe_params_v4 { #define SCAN_MAX_NUM_CHANS_V3 67 -/** - * struct iwl_scan_channel_params_v3 - * @flags: channel flags &enum iwl_scan_channel_flags - * @count: num of channels in scan request - * @reserved: for future use and alignment - * @channel_config: array of explicit channel configurations - * for 2.4Ghz and 5.2Ghz bands - */ -struct iwl_scan_channel_params_v3 { - u8 flags; - u8 count; - __le16 reserved; - struct iwl_scan_channel_cfg_umac channel_config[SCAN_MAX_NUM_CHANS_V3]; -} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_3 */ - /** * struct iwl_scan_channel_params_v4 * @flags: channel flags &enum iwl_scan_channel_flags @@ -1010,20 +995,6 @@ struct iwl_scan_periodic_parms_v1 { __le16 reserved; } __packed; /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */ -/** - * struct iwl_scan_req_params_v11 - * @general_params: &struct iwl_scan_general_params_v10 - * @channel_params: &struct iwl_scan_channel_params_v3 - * @periodic_params: &struct iwl_scan_periodic_parms_v1 - * @probe_params: &struct iwl_scan_probe_params_v3 - */ -struct iwl_scan_req_params_v11 { - struct iwl_scan_general_params_v10 general_params; - struct iwl_scan_channel_params_v3 channel_params; - struct iwl_scan_periodic_parms_v1 periodic_params; - struct iwl_scan_probe_params_v3 probe_params; -} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_11 */ - /** * struct iwl_scan_req_params_v12 * @general_params: &struct iwl_scan_general_params_v10 @@ -1052,18 +1023,6 @@ struct iwl_scan_req_params_v13 { struct iwl_scan_probe_params_v4 probe_params; } __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_13 */ -/** - * struct iwl_scan_req_umac_v11 - * @uid: scan id, &enum iwl_umac_scan_uid_offsets - * @ooc_priority: out of channel priority - &enum iwl_scan_priority - * @scan_params: scan parameters - */ -struct iwl_scan_req_umac_v11 { - __le32 uid; - __le32 ooc_priority; - struct iwl_scan_req_params_v11 scan_params; -} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_11 */ - /** * struct iwl_scan_req_umac_v12 * @uid: scan id, &enum iwl_umac_scan_uid_offsets diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index a046ac9fa852..c0c89d460700 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -1906,20 +1906,6 @@ iwl_mvm_scan_umac_fill_probe_p_v4(struct iwl_mvm_scan_params *params, iwl_scan_build_ssids(params, pp->direct_scan, bitmap_ssid); } -static void -iwl_mvm_scan_umac_fill_ch_p_v3(struct iwl_mvm *mvm, - struct iwl_mvm_scan_params *params, - struct ieee80211_vif *vif, - struct iwl_scan_channel_params_v3 *cp) -{ - cp->flags = iwl_mvm_scan_umac_chan_flags_v2(mvm, params, vif); - cp->count = params->n_channels; - - iwl_mvm_umac_scan_cfg_channels(mvm, params->channels, - params->n_channels, 0, - cp->channel_config); -} - static void iwl_mvm_scan_umac_fill_ch_p_v4(struct iwl_mvm *mvm, struct iwl_mvm_scan_params *params, @@ -1937,37 +1923,6 @@ iwl_mvm_scan_umac_fill_ch_p_v4(struct iwl_mvm *mvm, vif->type); } -static int iwl_mvm_scan_umac_v11(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct iwl_mvm_scan_params *params, int type, - int uid) -{ - struct iwl_scan_req_umac_v11 *cmd = mvm->scan_cmd; - struct iwl_scan_req_params_v11 *scan_p = &cmd->scan_params; - int ret; - u16 gen_flags; - - mvm->scan_uid_status[uid] = type; - - cmd->ooc_priority = cpu_to_le32(iwl_mvm_scan_umac_ooc_priority(params)); - cmd->uid = cpu_to_le32(uid); - - gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type); - iwl_mvm_scan_umac_fill_general_p_v10(mvm, params, vif, - &scan_p->general_params, - gen_flags); - - ret = iwl_mvm_fill_scan_sched_params(params, - scan_p->periodic_params.schedule, - &scan_p->periodic_params.delay); - if (ret) - return ret; - - iwl_mvm_scan_umac_fill_probe_p_v3(params, &scan_p->probe_params); - iwl_mvm_scan_umac_fill_ch_p_v3(mvm, params, vif, - &scan_p->channel_params); - - return 0; -} static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_mvm_scan_params *params, int type, @@ -2152,7 +2107,6 @@ static const struct iwl_scan_umac_handler iwl_scan_umac_handlers[] = { /* set the newest version first to shorten the list traverse time */ IWL_SCAN_UMAC_HANDLER(13), IWL_SCAN_UMAC_HANDLER(12), - IWL_SCAN_UMAC_HANDLER(11), }; static int iwl_mvm_build_scan_cmd(struct iwl_mvm *mvm, @@ -2511,7 +2465,6 @@ static int iwl_scan_req_umac_get_size(u8 scan_ver) switch (scan_ver) { IWL_SCAN_REQ_UMAC_HANDLE_SIZE(13); IWL_SCAN_REQ_UMAC_HANDLE_SIZE(12); - IWL_SCAN_REQ_UMAC_HANDLE_SIZE(11); } return 0; From b59ec4cac5160370d908c60934e799bc6da7d784 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Wed, 2 Oct 2019 12:20:32 +0300 Subject: [PATCH 04/96] iwlwifi: mvm: add support for location range request version 8 The new API requires the driver to set the frame format (legacy, HT, VHT etc.) to be used for the measurement. The new API also supports 11az and secured measurement, but these are not supported by the driver for now. Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho --- .../wireless/intel/iwlwifi/fw/api/location.h | 104 +++++++- .../intel/iwlwifi/mvm/ftm-initiator.c | 245 ++++++++++++++---- 2 files changed, 293 insertions(+), 56 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h index 7a0fe5adefa5..a51fda4c9588 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h @@ -403,7 +403,7 @@ enum iwl_initiator_ap_flags { }; /** - * struct iwl_tof_range_req_ap_entry - AP configuration parameters + * struct iwl_tof_range_req_ap_entry_v3 - AP configuration parameters * @initiator_ap_flags: see &enum iwl_initiator_ap_flags. * @channel_num: AP Channel number * @bandwidth: AP bandwidth. One of iwl_tof_bandwidth. @@ -420,7 +420,7 @@ enum iwl_initiator_ap_flags { * @reserved: For alignment and future use * @tsf_delta: not in use */ -struct iwl_tof_range_req_ap_entry { +struct iwl_tof_range_req_ap_entry_v3 { __le32 initiator_ap_flags; u8 channel_num; u8 bandwidth; @@ -434,6 +434,72 @@ struct iwl_tof_range_req_ap_entry { __le32 tsf_delta; } __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_3 */ +/** + * enum iwl_location_frame_format - location frame formats + * @IWL_LOCATION_FRAME_FORMAT_LEGACY: legacy + * @IWL_LOCATION_FRAME_FORMAT_HT: HT + * @IWL_LOCATION_FRAME_FORMAT_VHT: VHT + * @IWL_LOCATION_FRAME_FORMAT_HE: HE + */ +enum iwl_location_frame_format { + IWL_LOCATION_FRAME_FORMAT_LEGACY, + IWL_LOCATION_FRAME_FORMAT_HT, + IWL_LOCATION_FRAME_FORMAT_VHT, + IWL_LOCATION_FRAME_FORMAT_HE, +}; + +/** + * enum iwl_location_bw - location bandwidth selection + * @IWL_LOCATION_BW_20MHZ: 20MHz + * @IWL_LOCATION_BW_40MHZ: 40MHz + * @IWL_LOCATION_BW_80MHZ: 80MHz + */ +enum iwl_location_bw { + IWL_LOCATION_BW_20MHZ, + IWL_LOCATION_BW_40MHZ, + IWL_LOCATION_BW_80MHZ, +}; + +#define HLTK_11AZ_LEN 32 +#define TK_11AZ_LEN 32 + +#define LOCATION_BW_POS 4 + +/** + * struct iwl_tof_range_req_ap_entry - AP configuration parameters + * @initiator_ap_flags: see &enum iwl_initiator_ap_flags. + * @channel_num: AP Channel number + * @format_bw: bits 0 - 3: &enum iwl_location_frame_format. + * bits 4 - 7: &enum iwl_location_bw. + * @ctrl_ch_position: Coding of the control channel position relative to the + * center frequency, see iwl_mvm_get_ctrl_pos(). + * @ftmr_max_retries: Max number of retries to send the FTMR in case of no + * reply from the AP. + * @bssid: AP's BSSID + * @burst_period: Recommended value to be sent to the AP. Measurement + * periodicity In units of 100ms. ignored if num_of_bursts_exp = 0 + * @samples_per_burst: the number of FTMs pairs in single Burst (1-31); + * @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of + * the number of measurement iterations (min 2^0 = 1, max 2^14) + * @reserved: For alignment and future use + * @hltk: HLTK to be used for secured 11az measurement + * @tk: TK to be used for secured 11az measurement + */ +struct iwl_tof_range_req_ap_entry { + __le32 initiator_ap_flags; + u8 channel_num; + u8 format_bw; + u8 ctrl_ch_position; + u8 ftmr_max_retries; + u8 bssid[ETH_ALEN]; + __le16 burst_period; + u8 samples_per_burst; + u8 num_of_bursts; + __le16 reserved; + u8 hltk[HLTK_11AZ_LEN]; + u8 tk[TK_11AZ_LEN]; +} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_4 */ + /** * enum iwl_tof_response_mode * @IWL_MVM_TOF_RESPONSE_ASAP: report each AP measurement separately as soon as @@ -535,6 +601,38 @@ struct iwl_tof_range_req_cmd_v5 { } __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */ +/** + * struct iwl_tof_range_req_cmd_v7 - start measurement cmd + * @initiator_flags: see flags @ iwl_tof_initiator_flags + * @request_id: A Token incremented per request. The same Token will be + * sent back in the range response + * @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS) + * @range_req_bssid: ranging request BSSID + * @macaddr_mask: Bits set to 0 shall be copied from the MAC address template. + * Bits set to 1 shall be randomized by the UMAC + * @macaddr_template: MAC address template to use for non-randomized bits + * @req_timeout_ms: Requested timeout of the response in units of milliseconds. + * This is the session time for completing the measurement. + * @tsf_mac_id: report the measurement start time for each ap in terms of the + * TSF of this mac id. 0xff to disable TSF reporting. + * @common_calib: The common calib value to inject to this measurement calc + * @specific_calib: The specific calib value to inject to this measurement calc + * @ap: per-AP request data, see &struct iwl_tof_range_req_ap_entry_v2. + */ +struct iwl_tof_range_req_cmd_v7 { + __le32 initiator_flags; + u8 request_id; + u8 num_of_ap; + u8 range_req_bssid[ETH_ALEN]; + u8 macaddr_mask[ETH_ALEN]; + u8 macaddr_template[ETH_ALEN]; + __le32 req_timeout_ms; + __le32 tsf_mac_id; + __le16 common_calib; + __le16 specific_calib; + struct iwl_tof_range_req_ap_entry_v3 ap[IWL_MVM_TOF_MAX_APS]; +} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_7 */ + /** * struct iwl_tof_range_req_cmd - start measurement cmd * @initiator_flags: see flags @ iwl_tof_initiator_flags @@ -565,7 +663,7 @@ struct iwl_tof_range_req_cmd { __le16 common_calib; __le16 specific_calib; struct iwl_tof_range_req_ap_entry ap[IWL_MVM_TOF_MAX_APS]; -} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_7 */ +} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_8 */ /* * enum iwl_tof_range_request_status - status of the sent request diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c index 9f4b117db9d7..f783d6d53b6f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c @@ -208,10 +208,11 @@ static void iwl_mvm_ftm_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cmd->tsf_mac_id = cpu_to_le32(0xff); } -static int iwl_mvm_ftm_target_chandef(struct iwl_mvm *mvm, - struct cfg80211_pmsr_request_peer *peer, - u8 *channel, u8 *bandwidth, - u8 *ctrl_ch_position) +static int +iwl_mvm_ftm_target_chandef_v1(struct iwl_mvm *mvm, + struct cfg80211_pmsr_request_peer *peer, + u8 *channel, u8 *bandwidth, + u8 *ctrl_ch_position) { u32 freq = peer->chandef.chan->center_freq; @@ -242,6 +243,45 @@ static int iwl_mvm_ftm_target_chandef(struct iwl_mvm *mvm, return 0; } +static int +iwl_mvm_ftm_target_chandef_v2(struct iwl_mvm *mvm, + struct cfg80211_pmsr_request_peer *peer, + u8 *channel, u8 *format_bw, + u8 *ctrl_ch_position) +{ + u32 freq = peer->chandef.chan->center_freq; + + *channel = ieee80211_frequency_to_channel(freq); + + switch (peer->chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + *format_bw = IWL_LOCATION_FRAME_FORMAT_LEGACY; + *format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS; + break; + case NL80211_CHAN_WIDTH_20: + *format_bw = IWL_LOCATION_FRAME_FORMAT_HT; + *format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS; + break; + case NL80211_CHAN_WIDTH_40: + *format_bw = IWL_LOCATION_FRAME_FORMAT_HT; + *format_bw |= IWL_LOCATION_BW_40MHZ << LOCATION_BW_POS; + break; + case NL80211_CHAN_WIDTH_80: + *format_bw = IWL_LOCATION_FRAME_FORMAT_VHT; + *format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS; + break; + default: + IWL_ERR(mvm, "Unsupported BW in FTM request (%d)\n", + peer->chandef.width); + return -EINVAL; + } + + *ctrl_ch_position = (peer->chandef.width > NL80211_CHAN_WIDTH_20) ? + iwl_mvm_get_ctrl_pos(&peer->chandef) : 0; + + return 0; +} + static int iwl_mvm_ftm_put_target_v2(struct iwl_mvm *mvm, struct cfg80211_pmsr_request_peer *peer, @@ -249,9 +289,9 @@ iwl_mvm_ftm_put_target_v2(struct iwl_mvm *mvm, { int ret; - ret = iwl_mvm_ftm_target_chandef(mvm, peer, &target->channel_num, - &target->bandwidth, - &target->ctrl_ch_position); + ret = iwl_mvm_ftm_target_chandef_v1(mvm, peer, &target->channel_num, + &target->bandwidth, + &target->ctrl_ch_position); if (ret) return ret; @@ -278,18 +318,11 @@ iwl_mvm_ftm_put_target_v2(struct iwl_mvm *mvm, #define FTM_PUT_FLAG(flag) (target->initiator_ap_flags |= \ cpu_to_le32(IWL_INITIATOR_AP_FLAGS_##flag)) -static int iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, - struct cfg80211_pmsr_request_peer *peer, - struct iwl_tof_range_req_ap_entry *target) +static void +iwl_mvm_ftm_put_target_common(struct iwl_mvm *mvm, + struct cfg80211_pmsr_request_peer *peer, + struct iwl_tof_range_req_ap_entry *target) { - int ret; - - ret = iwl_mvm_ftm_target_chandef(mvm, peer, &target->channel_num, - &target->bandwidth, - &target->ctrl_ch_position); - if (ret) - return ret; - memcpy(target->bssid, peer->addr, ETH_ALEN); target->burst_period = cpu_to_le16(peer->ftm.burst_period); @@ -314,24 +347,149 @@ static int iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, FTM_PUT_FLAG(ALGO_LR); else if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_FFT) FTM_PUT_FLAG(ALGO_FFT); +} + +static int +iwl_mvm_ftm_put_target_v3(struct iwl_mvm *mvm, + struct cfg80211_pmsr_request_peer *peer, + struct iwl_tof_range_req_ap_entry_v3 *target) +{ + int ret; + + ret = iwl_mvm_ftm_target_chandef_v1(mvm, peer, &target->channel_num, + &target->bandwidth, + &target->ctrl_ch_position); + if (ret) + return ret; + + /* + * Versions 3 and 4 has some common fields, so + * iwl_mvm_ftm_put_target_common() can be used for version 7 too. + */ + iwl_mvm_ftm_put_target_common(mvm, peer, (void *)target); return 0; } +static int iwl_mvm_ftm_put_target_v4(struct iwl_mvm *mvm, + struct cfg80211_pmsr_request_peer *peer, + struct iwl_tof_range_req_ap_entry *target) +{ + int ret; + + ret = iwl_mvm_ftm_target_chandef_v2(mvm, peer, &target->channel_num, + &target->format_bw, + &target->ctrl_ch_position); + if (ret) + return ret; + + iwl_mvm_ftm_put_target_common(mvm, peer, target); + + return 0; +} + +static int iwl_mvm_ftm_send_cmd(struct iwl_mvm *mvm, struct iwl_host_cmd *hcmd) +{ + u32 status; + int err = iwl_mvm_send_cmd_status(mvm, hcmd, &status); + + if (!err && status) { + IWL_ERR(mvm, "FTM range request command failure, status: %u\n", + status); + err = iwl_ftm_range_request_status_to_err(status); + } + + return err; +} + +static int iwl_mvm_ftm_start_v5(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *req) +{ + struct iwl_tof_range_req_cmd_v5 cmd_v5; + struct iwl_host_cmd hcmd = { + .id = iwl_cmd_id(TOF_RANGE_REQ_CMD, LOCATION_GROUP, 0), + .dataflags[0] = IWL_HCMD_DFL_DUP, + .data[0] = &cmd_v5, + .len[0] = sizeof(cmd_v5), + }; + u8 i; + int err; + + iwl_mvm_ftm_cmd_v5(mvm, vif, &cmd_v5, req); + + for (i = 0; i < cmd_v5.num_of_ap; i++) { + struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; + + err = iwl_mvm_ftm_put_target_v2(mvm, peer, &cmd_v5.ap[i]); + if (err) + return err; + } + + return iwl_mvm_ftm_send_cmd(mvm, &hcmd); +} + +static int iwl_mvm_ftm_start_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *req) +{ + struct iwl_tof_range_req_cmd_v7 cmd_v7; + struct iwl_host_cmd hcmd = { + .id = iwl_cmd_id(TOF_RANGE_REQ_CMD, LOCATION_GROUP, 0), + .dataflags[0] = IWL_HCMD_DFL_DUP, + .data[0] = &cmd_v7, + .len[0] = sizeof(cmd_v7), + }; + u8 i; + int err; + + /* + * Versions 7 and 8 has the same structure except from the responders + * list, so iwl_mvm_ftm_cmd() can be used for version 7 too. + */ + iwl_mvm_ftm_cmd(mvm, vif, (void *)&cmd_v7, req); + + for (i = 0; i < cmd_v7.num_of_ap; i++) { + struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; + + err = iwl_mvm_ftm_put_target_v3(mvm, peer, &cmd_v7.ap[i]); + if (err) + return err; + } + + return iwl_mvm_ftm_send_cmd(mvm, &hcmd); +} + +static int iwl_mvm_ftm_start_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *req) +{ + struct iwl_tof_range_req_cmd cmd; + struct iwl_host_cmd hcmd = { + .id = iwl_cmd_id(TOF_RANGE_REQ_CMD, LOCATION_GROUP, 0), + .dataflags[0] = IWL_HCMD_DFL_DUP, + .data[0] = &cmd, + .len[0] = sizeof(cmd), + }; + u8 i; + int err; + + iwl_mvm_ftm_cmd(mvm, vif, &cmd, req); + + for (i = 0; i < cmd.num_of_ap; i++) { + struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; + + err = iwl_mvm_ftm_put_target_v4(mvm, peer, &cmd.ap[i]); + if (err) + return err; + } + + return iwl_mvm_ftm_send_cmd(mvm, &hcmd); +} + int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct cfg80211_pmsr_request *req) { - struct iwl_tof_range_req_cmd_v5 cmd_v5; - struct iwl_tof_range_req_cmd cmd; bool new_api = fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ); - u8 num_of_ap; - struct iwl_host_cmd hcmd = { - .id = iwl_cmd_id(TOF_RANGE_REQ_CMD, LOCATION_GROUP, 0), - .dataflags[0] = IWL_HCMD_DFL_DUP, - }; - u32 status = 0; - int err, i; + int err; lockdep_assert_held(&mvm->mutex); @@ -339,35 +497,16 @@ int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return -EBUSY; if (new_api) { - iwl_mvm_ftm_cmd(mvm, vif, &cmd, req); - hcmd.data[0] = &cmd; - hcmd.len[0] = sizeof(cmd); - num_of_ap = cmd.num_of_ap; - } else { - iwl_mvm_ftm_cmd_v5(mvm, vif, &cmd_v5, req); - hcmd.data[0] = &cmd_v5; - hcmd.len[0] = sizeof(cmd_v5); - num_of_ap = cmd_v5.num_of_ap; - } + u8 cmd_ver = iwl_mvm_lookup_cmd_ver(mvm->fw, LOCATION_GROUP, + TOF_RANGE_REQ_CMD); - for (i = 0; i < num_of_ap; i++) { - struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; - - if (new_api) - err = iwl_mvm_ftm_put_target(mvm, peer, &cmd.ap[i]); + if (cmd_ver == 8) + err = iwl_mvm_ftm_start_v8(mvm, vif, req); else - err = iwl_mvm_ftm_put_target_v2(mvm, peer, - &cmd_v5.ap[i]); + err = iwl_mvm_ftm_start_v7(mvm, vif, req); - if (err) - return err; - } - - err = iwl_mvm_send_cmd_status(mvm, &hcmd, &status); - if (!err && status) { - IWL_ERR(mvm, "FTM range request command failure, status: %u\n", - status); - err = iwl_ftm_range_request_status_to_err(status); + } else { + err = iwl_mvm_ftm_start_v5(mvm, vif, req); } if (!err) { From b1a6db1320e94bc8e924918fc236b5df97c1cca7 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Wed, 2 Oct 2019 13:44:27 +0300 Subject: [PATCH 05/96] iwlwifi: mvm: add support for responder config command version 7 The new API requires the driver to config the supported frame format (legacy, HT, VHT etc.). Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho --- .../wireless/intel/iwlwifi/fw/api/location.h | 40 +++++++- .../intel/iwlwifi/mvm/ftm-responder.c | 95 +++++++++++++++---- 2 files changed, 113 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h index a51fda4c9588..a0d6802c2715 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h @@ -240,7 +240,7 @@ enum iwl_tof_responder_cfg_flags { }; /** - * struct iwl_tof_responder_config_cmd - ToF AP mode (for debug) + * struct iwl_tof_responder_config_cmd_v6 - ToF AP mode (for debug) * @cmd_valid_fields: &iwl_tof_responder_cmd_valid_field * @responder_cfg_flags: &iwl_tof_responder_cfg_flags * @bandwidth: current AP Bandwidth: &enum iwl_tof_bandwidth @@ -258,7 +258,7 @@ enum iwl_tof_responder_cfg_flags { * @bssid: Current AP BSSID * @reserved2: reserved */ -struct iwl_tof_responder_config_cmd { +struct iwl_tof_responder_config_cmd_v6 { __le32 cmd_valid_fields; __le32 responder_cfg_flags; u8 bandwidth; @@ -274,6 +274,42 @@ struct iwl_tof_responder_config_cmd { __le16 reserved2; } __packed; /* TOF_RESPONDER_CONFIG_CMD_API_S_VER_6 */ +/** + * struct iwl_tof_responder_config_cmd - ToF AP mode (for debug) + * @cmd_valid_fields: &iwl_tof_responder_cmd_valid_field + * @responder_cfg_flags: &iwl_tof_responder_cfg_flags + * @format_bw: bits 0 - 3: &enum iwl_location_frame_format. + * bits 4 - 7: &enum iwl_location_bw. + * @rate: current AP rate + * @channel_num: current AP Channel + * @ctrl_ch_position: coding of the control channel position relative to + * the center frequency, see iwl_mvm_get_ctrl_pos() + * @sta_id: index of the AP STA when in AP mode + * @reserved1: reserved + * @toa_offset: Artificial addition [pSec] for the ToA - to be used for debug + * purposes, simulating station movement by adding various values + * to this field + * @common_calib: XVT: common calibration value + * @specific_calib: XVT: specific calibration value + * @bssid: Current AP BSSID + * @reserved2: reserved + */ +struct iwl_tof_responder_config_cmd { + __le32 cmd_valid_fields; + __le32 responder_cfg_flags; + u8 format_bw; + u8 rate; + u8 channel_num; + u8 ctrl_ch_position; + u8 sta_id; + u8 reserved1; + __le16 toa_offset; + __le16 common_calib; + __le16 specific_calib; + u8 bssid[ETH_ALEN]; + __le16 reserved2; +} __packed; /* TOF_RESPONDER_CONFIG_CMD_API_S_VER_6 */ + #define IWL_LCI_CIVIC_IE_MAX_SIZE 400 /** diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c index 1513b8b4062f..834564198409 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * * 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 @@ -27,7 +27,7 @@ * BSD LICENSE * * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -62,12 +62,72 @@ #include "mvm.h" #include "constants.h" +static int iwl_mvm_ftm_responder_set_bw_v1(struct cfg80211_chan_def *chandef, + u8 *bw, u8 *ctrl_ch_position) +{ + switch (chandef->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + *bw = IWL_TOF_BW_20_LEGACY; + break; + case NL80211_CHAN_WIDTH_20: + *bw = IWL_TOF_BW_20_HT; + break; + case NL80211_CHAN_WIDTH_40: + *bw = IWL_TOF_BW_40; + *ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef); + break; + case NL80211_CHAN_WIDTH_80: + *bw = IWL_TOF_BW_80; + *ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef); + break; + default: + return -ENOTSUPP; + } + + return 0; +} + +static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef, + u8 *format_bw, + u8 *ctrl_ch_position) +{ + switch (chandef->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + *format_bw = IWL_LOCATION_FRAME_FORMAT_LEGACY; + *format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS; + break; + case NL80211_CHAN_WIDTH_20: + *format_bw = IWL_LOCATION_FRAME_FORMAT_HT; + *format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS; + break; + case NL80211_CHAN_WIDTH_40: + *format_bw = IWL_LOCATION_FRAME_FORMAT_HT; + *format_bw |= IWL_LOCATION_BW_40MHZ << LOCATION_BW_POS; + *ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef); + break; + case NL80211_CHAN_WIDTH_80: + *format_bw = IWL_LOCATION_FRAME_FORMAT_VHT; + *format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS; + *ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef); + break; + default: + return -ENOTSUPP; + } + + return 0; +} + static int iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct cfg80211_chan_def *chandef) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + /* + * The command structure is the same for versions 6 and 7, (only the + * field interpretation is different), so the same struct can be use + * for all cases. + */ struct iwl_tof_responder_config_cmd cmd = { .channel_num = chandef->chan->hw_value, .cmd_valid_fields = @@ -76,27 +136,22 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm, IWL_TOF_RESPONDER_CMD_VALID_STA_ID), .sta_id = mvmvif->bcast_sta.sta_id, }; + u8 cmd_ver = iwl_mvm_lookup_cmd_ver(mvm->fw, LOCATION_GROUP, + TOF_RESPONDER_CONFIG_CMD); + int err; lockdep_assert_held(&mvm->mutex); - switch (chandef->width) { - case NL80211_CHAN_WIDTH_20_NOHT: - cmd.bandwidth = IWL_TOF_BW_20_LEGACY; - break; - case NL80211_CHAN_WIDTH_20: - cmd.bandwidth = IWL_TOF_BW_20_HT; - break; - case NL80211_CHAN_WIDTH_40: - cmd.bandwidth = IWL_TOF_BW_40; - cmd.ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef); - break; - case NL80211_CHAN_WIDTH_80: - cmd.bandwidth = IWL_TOF_BW_80; - cmd.ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef); - break; - default: - WARN_ON(1); - return -EINVAL; + if (cmd_ver == 7) + err = iwl_mvm_ftm_responder_set_bw_v2(chandef, &cmd.format_bw, + &cmd.ctrl_ch_position); + else + err = iwl_mvm_ftm_responder_set_bw_v1(chandef, &cmd.format_bw, + &cmd.ctrl_ch_position); + + if (err) { + IWL_ERR(mvm, "Failed to set responder bandwidth\n"); + return err; } memcpy(cmd.bssid, vif->addr, ETH_ALEN); From c042f0c77f3df39ac4d530f5720ed64ff2f38375 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Sep 2019 10:36:02 +0200 Subject: [PATCH 06/96] iwlwifi: allocate more receive buffers for HE devices For HE-capable devices, we need to allocate more receive buffers as there could be 256 frames aggregated into a single A-MPDU, and then they might contain A-MSDUs as well. Until 22000 family, the devices are able to put multiple frames into a single RB and the default RB size is 4k, but starting from AX210 family this is no longer true. On the other hand, those newer devices only use 2k receive buffers (by default). Modify the code and configuration to allocate an appropriate number of RBs depending on the device capabilities: * 4096 for AX210 HE devices, which use 2k buffers by default, * 2048 for 22000 family devices which use 4k buffers by default, * 512 for existing 9000 family devices, which doesn't really change anything since that's the default before this patch, * 512 also for AX210/22000 family devices that don't do HE. Theoretically, for devices lower than AX210, we wouldn't have to allocate that many RBs if the RB size was manually increased, but to support that the code got more complex, and it didn't really seem necessary as that's a use case for monitor mode only, where hopefully the wasted memory isn't really much of a concern. Note that AX210 devices actually support bigger than 12-bit VID, which is required here as we want to allocate 4096 buffers plus some for quick recycling, so adjust the code for that as well. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/cfg/22000.c | 55 +++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/cfg/9000.c | 1 + .../net/wireless/intel/iwlwifi/iwl-config.h | 3 + .../wireless/intel/iwlwifi/iwl-context-info.h | 20 +++---- drivers/net/wireless/intel/iwlwifi/iwl-fh.h | 5 +- .../intel/iwlwifi/pcie/ctxt-info-gen3.c | 2 +- .../wireless/intel/iwlwifi/pcie/ctxt-info.c | 11 ++-- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 13 +++++ .../wireless/intel/iwlwifi/pcie/internal.h | 5 +- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 34 ++++++++---- 10 files changed, 116 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 56dc335a788c..bd687e745dc9 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -236,10 +236,22 @@ static const struct iwl_ht_params iwl_22000_ht_params = { }, \ } +/* + * If the device doesn't support HE, no need to have that many buffers. + * 22000 devices can split multiple frames into a single RB, so fewer are + * needed; AX210 cannot (but use smaller RBs by default) - these sizes + * were picked according to 8 MSDUs inside 256 A-MSDUs in an A-MPDU, with + * additional overhead to account for processing time. + */ +#define IWL_NUM_RBDS_NON_HE 512 +#define IWL_NUM_RBDS_22000_HE 2048 +#define IWL_NUM_RBDS_AX210_HE 4096 + const struct iwl_cfg iwl22000_2ac_cfg_hr = { .name = "Intel(R) Dual Band Wireless AC 22000", .fw_name_pre = IWL_22000_HR_FW_PRE, IWL_DEVICE_22500, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb = { @@ -247,12 +259,14 @@ const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb = { .fw_name_pre = IWL_22000_HR_CDB_FW_PRE, IWL_DEVICE_22500, .cdb = true, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl22000_2ac_cfg_jf = { .name = "Intel(R) Dual Band Wireless AC 22000", .fw_name_pre = IWL_22000_JF_FW_PRE, IWL_DEVICE_22500, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl_ax101_cfg_qu_hr = { @@ -266,6 +280,7 @@ const struct iwl_cfg iwl_ax101_cfg_qu_hr = { */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, .tx_with_siso_diversity = true, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg iwl_ax201_cfg_qu_hr = { @@ -278,6 +293,7 @@ const struct iwl_cfg iwl_ax201_cfg_qu_hr = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg iwl_ax101_cfg_qu_c0_hr_b0 = { @@ -290,6 +306,7 @@ const struct iwl_cfg iwl_ax101_cfg_qu_c0_hr_b0 = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg iwl_ax201_cfg_qu_c0_hr_b0 = { @@ -302,6 +319,7 @@ const struct iwl_cfg iwl_ax201_cfg_qu_c0_hr_b0 = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg iwl_ax101_cfg_quz_hr = { @@ -314,6 +332,7 @@ const struct iwl_cfg iwl_ax101_cfg_quz_hr = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg iwl_ax201_cfg_quz_hr = { @@ -326,6 +345,7 @@ const struct iwl_cfg iwl_ax201_cfg_quz_hr = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg iwl_ax1650s_cfg_quz_hr = { @@ -338,6 +358,7 @@ const struct iwl_cfg iwl_ax1650s_cfg_quz_hr = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg iwl_ax1650i_cfg_quz_hr = { @@ -350,6 +371,7 @@ const struct iwl_cfg iwl_ax1650i_cfg_quz_hr = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg iwl_ax200_cfg_cc = { @@ -363,6 +385,7 @@ const struct iwl_cfg iwl_ax200_cfg_cc = { */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, .trans.bisr_workaround = 1, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg killer1650x_2ax_cfg = { @@ -376,6 +399,7 @@ const struct iwl_cfg killer1650x_2ax_cfg = { */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, .trans.bisr_workaround = 1, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg killer1650w_2ax_cfg = { @@ -389,6 +413,7 @@ const struct iwl_cfg killer1650w_2ax_cfg = { */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, .trans.bisr_workaround = 1, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; /* @@ -400,48 +425,56 @@ const struct iwl_cfg iwl9461_2ac_cfg_qu_b0_jf_b0 = { .name = "Intel(R) Wireless-AC 9461", .fw_name_pre = IWL_QU_B_JF_B_FW_PRE, IWL_DEVICE_22500, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl9462_2ac_cfg_qu_b0_jf_b0 = { .name = "Intel(R) Wireless-AC 9462", .fw_name_pre = IWL_QU_B_JF_B_FW_PRE, IWL_DEVICE_22500, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl9560_2ac_cfg_qu_b0_jf_b0 = { .name = "Intel(R) Wireless-AC 9560", .fw_name_pre = IWL_QU_B_JF_B_FW_PRE, IWL_DEVICE_22500, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl9560_2ac_160_cfg_qu_b0_jf_b0 = { .name = "Intel(R) Wireless-AC 9560 160MHz", .fw_name_pre = IWL_QU_B_JF_B_FW_PRE, IWL_DEVICE_22500, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl9461_2ac_cfg_qu_c0_jf_b0 = { .name = "Intel(R) Wireless-AC 9461", .fw_name_pre = IWL_QU_C_JF_B_FW_PRE, IWL_DEVICE_22500, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl9462_2ac_cfg_qu_c0_jf_b0 = { .name = "Intel(R) Wireless-AC 9462", .fw_name_pre = IWL_QU_C_JF_B_FW_PRE, IWL_DEVICE_22500, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl9560_2ac_cfg_qu_c0_jf_b0 = { .name = "Intel(R) Wireless-AC 9560", .fw_name_pre = IWL_QU_C_JF_B_FW_PRE, IWL_DEVICE_22500, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl9560_2ac_160_cfg_qu_c0_jf_b0 = { .name = "Intel(R) Wireless-AC 9560 160MHz", .fw_name_pre = IWL_QU_C_JF_B_FW_PRE, IWL_DEVICE_22500, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl9560_2ac_cfg_qnj_jf_b0 = { @@ -454,6 +487,7 @@ const struct iwl_cfg iwl9560_2ac_cfg_qnj_jf_b0 = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl9560_2ac_cfg_quz_a0_jf_b0_soc = { @@ -468,6 +502,7 @@ const struct iwl_cfg iwl9560_2ac_cfg_quz_a0_jf_b0_soc = { .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, .integrated = true, .soc_latency = 5000, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc = { @@ -482,6 +517,7 @@ const struct iwl_cfg iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc = { .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, .integrated = true, .soc_latency = 5000, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl9461_2ac_cfg_quz_a0_jf_b0_soc = { @@ -496,6 +532,7 @@ const struct iwl_cfg iwl9461_2ac_cfg_quz_a0_jf_b0_soc = { .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, .integrated = true, .soc_latency = 5000, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl9462_2ac_cfg_quz_a0_jf_b0_soc = { @@ -510,6 +547,7 @@ const struct iwl_cfg iwl9462_2ac_cfg_quz_a0_jf_b0_soc = { .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, .integrated = true, .soc_latency = 5000, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl9560_killer_s_2ac_cfg_quz_a0_jf_b0_soc = { @@ -524,6 +562,7 @@ const struct iwl_cfg iwl9560_killer_s_2ac_cfg_quz_a0_jf_b0_soc = { .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, .integrated = true, .soc_latency = 5000, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwl9560_killer_i_2ac_cfg_quz_a0_jf_b0_soc = { @@ -538,18 +577,21 @@ const struct iwl_cfg iwl9560_killer_i_2ac_cfg_quz_a0_jf_b0_soc = { .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, .integrated = true, .soc_latency = 5000, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg killer1550i_2ac_cfg_qu_b0_jf_b0 = { .name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)", .fw_name_pre = IWL_QU_B_JF_B_FW_PRE, IWL_DEVICE_22500, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg killer1550s_2ac_cfg_qu_b0_jf_b0 = { .name = "Killer (R) Wireless-AC 1550s Wireless Network Adapter (9560NGW)", .fw_name_pre = IWL_QU_B_JF_B_FW_PRE, IWL_DEVICE_22500, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = { @@ -562,6 +604,7 @@ const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = { @@ -574,6 +617,7 @@ const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0 = { @@ -586,6 +630,7 @@ const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0 = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = { @@ -598,6 +643,7 @@ const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg iwl22000_2ax_cfg_jf = { @@ -610,6 +656,7 @@ const struct iwl_cfg iwl22000_2ax_cfg_jf = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0_f0 = { @@ -622,6 +669,7 @@ const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0_f0 = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0 = { @@ -634,6 +682,7 @@ const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0 = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0 = { @@ -646,18 +695,21 @@ const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0 = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .num_rbds = IWL_NUM_RBDS_22000_HE, }; const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0 = { .name = "Intel(R) Wireless-AC 9560 160MHz", .fw_name_pre = IWL_22000_SO_A_JF_B_FW_PRE, IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = { .name = "Intel(R) Wi-Fi 7 AX210 160MHz", .fw_name_pre = IWL_22000_SO_A_HR_B_FW_PRE, IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, }; const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = { @@ -665,6 +717,7 @@ const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = { .fw_name_pre = IWL_22000_SO_A_GF_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, }; const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = { @@ -672,12 +725,14 @@ const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = { .fw_name_pre = IWL_22000_TY_A_GF_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, }; const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = { .name = "Intel(R) Wi-Fi 7 AX411 160MHz", .fw_name_pre = IWL_22000_SO_A_GF4_A_FW_PRE, IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, }; MODULE_FIRMWARE(IWL_22000_HR_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index e9155b9b5ee4..ac05c1a6ec6b 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -138,6 +138,7 @@ static const struct iwl_tt_params iwl9000_tt_params = { .thermal_params = &iwl9000_tt_params, \ .apmg_not_supported = true, \ .trans.mq_rx_supported = true, \ + .num_rbds = 512, \ .vht_mu_mimo_supported = true, \ .mac_addr_from_csr = true, \ .trans.rf_id = true, \ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 317eac066082..f8a93324d7c0 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -431,6 +431,8 @@ struct iwl_fw_mon_regs { * @uhb_supported: ultra high band channels supported * @min_256_ba_txq_size: minimum number of slots required in a TX queue which * supports 256 BA aggregation + * @num_rbds: number of receive buffer descriptors to use + * (only used for multi-queue capable devices) * * We enable the driver to be backward compatible wrt. hardware features. * API differences in uCode shouldn't be handled here but through TLVs @@ -485,6 +487,7 @@ struct iwl_cfg { u8 max_vht_ampdu_exponent; u8 ucode_api_max; u8 ucode_api_min; + u16 num_rbds; u32 min_umac_error_event_table; u32 extra_phy_cfg_flags; u32 d3_debug_data_base_addr; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h index 5ed07e37e3ee..eeaa8cbdddce 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * 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 @@ -20,7 +20,7 @@ * BSD LICENSE * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -64,12 +64,12 @@ * the init done for driver command that configures several system modes * @IWL_CTXT_INFO_EARLY_DEBUG: enable early debug * @IWL_CTXT_INFO_ENABLE_CDMP: enable core dump - * @IWL_CTXT_INFO_RB_CB_SIZE_POS: position of the RBD Cyclic Buffer Size + * @IWL_CTXT_INFO_RB_CB_SIZE: mask of the RBD Cyclic Buffer Size * exponent, the actual size is 2**value, valid sizes are 8-2048. * The value is four bits long. Maximum valid exponent is 12 * @IWL_CTXT_INFO_TFD_FORMAT_LONG: use long TFD Format (the * default is short format - not supported by the driver) - * @IWL_CTXT_INFO_RB_SIZE_POS: RB size position + * @IWL_CTXT_INFO_RB_SIZE: RB size mask * (values are IWL_CTXT_INFO_RB_SIZE_*K) * @IWL_CTXT_INFO_RB_SIZE_1K: Value for 1K RB size * @IWL_CTXT_INFO_RB_SIZE_2K: Value for 2K RB size @@ -83,12 +83,12 @@ * @IWL_CTXT_INFO_RB_SIZE_32K: Value for 32K RB size */ enum iwl_context_info_flags { - IWL_CTXT_INFO_AUTO_FUNC_INIT = BIT(0), - IWL_CTXT_INFO_EARLY_DEBUG = BIT(1), - IWL_CTXT_INFO_ENABLE_CDMP = BIT(2), - IWL_CTXT_INFO_RB_CB_SIZE_POS = 4, - IWL_CTXT_INFO_TFD_FORMAT_LONG = BIT(8), - IWL_CTXT_INFO_RB_SIZE_POS = 9, + IWL_CTXT_INFO_AUTO_FUNC_INIT = 0x0001, + IWL_CTXT_INFO_EARLY_DEBUG = 0x0002, + IWL_CTXT_INFO_ENABLE_CDMP = 0x0004, + IWL_CTXT_INFO_RB_CB_SIZE = 0x00f0, + IWL_CTXT_INFO_TFD_FORMAT_LONG = 0x0100, + IWL_CTXT_INFO_RB_SIZE = 0x1e00, IWL_CTXT_INFO_RB_SIZE_1K = 0x1, IWL_CTXT_INFO_RB_SIZE_2K = 0x2, IWL_CTXT_INFO_RB_SIZE_4K = 0x4, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h index 8836f85afe85..bf673ce5f183 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h @@ -611,10 +611,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans, */ #define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN (0x00000002) -#define MQ_RX_TABLE_SIZE 512 -#define MQ_RX_TABLE_MASK (MQ_RX_TABLE_SIZE - 1) -#define MQ_RX_NUM_RBDS (MQ_RX_TABLE_SIZE - 1) -#define RX_POOL_SIZE (MQ_RX_NUM_RBDS + \ +#define RX_POOL_SIZE(rbds) ((rbds) - 1 + \ IWL_MAX_RX_HW_QUEUES * \ (RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC)) /* cb size is the exponent */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index a4e09a5b1816..01f248ba8fec 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -206,7 +206,7 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, ctxt_info_gen3->mtr_size = cpu_to_le16(TFD_QUEUE_CB_SIZE(cmdq_size)); ctxt_info_gen3->mcr_size = - cpu_to_le16(RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE)); + cpu_to_le16(RX_QUEUE_CB_SIZE(trans->cfg->num_rbds)); trans_pcie->ctxt_info_gen3 = ctxt_info_gen3; trans_pcie->prph_info = prph_info; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c index d38cefbb779e..c34451e7e7ef 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c @@ -193,11 +193,12 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans, rb_size = IWL_CTXT_INFO_RB_SIZE_4K; } - BUILD_BUG_ON(RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE) > 0xF); - control_flags = IWL_CTXT_INFO_TFD_FORMAT_LONG | - (RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE) << - IWL_CTXT_INFO_RB_CB_SIZE_POS) | - (rb_size << IWL_CTXT_INFO_RB_SIZE_POS); + WARN_ON(RX_QUEUE_CB_SIZE(trans->cfg->num_rbds) > 12); + control_flags = IWL_CTXT_INFO_TFD_FORMAT_LONG; + control_flags |= + u32_encode_bits(RX_QUEUE_CB_SIZE(trans->cfg->num_rbds), + IWL_CTXT_INFO_RB_CB_SIZE); + control_flags |= u32_encode_bits(rb_size, IWL_CTXT_INFO_RB_SIZE); ctxt_info->control.control_flags = cpu_to_le32(control_flags); /* initialize RX default queue */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 040cec17d3ad..cdf112d6c0f9 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -995,6 +995,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); const struct iwl_cfg *cfg_7265d __maybe_unused = NULL; struct iwl_trans *iwl_trans; + struct iwl_trans_pcie *trans_pcie; unsigned long flags; int ret; @@ -1002,6 +1003,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (IS_ERR(iwl_trans)) return PTR_ERR(iwl_trans); + trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans); + /* the trans_cfg should never change, so set it now */ iwl_trans->trans_cfg = &cfg->trans; @@ -1129,6 +1132,16 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* now set the real cfg we decided to use */ iwl_trans->cfg = cfg; + if (cfg->trans.mq_rx_supported) { + if (WARN_ON(!cfg->num_rbds)) { + ret = -EINVAL; + goto out_free_trans; + } + trans_pcie->num_rx_bufs = cfg->num_rbds; + } else { + trans_pcie->num_rx_bufs = RX_QUEUE_SIZE; + } + if (iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_8000 && iwl_trans_grab_nic_access(iwl_trans, &flags)) { u32 hw_step; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index a091690f6c79..c45df9a48559 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -513,8 +513,8 @@ struct cont_rec { */ struct iwl_trans_pcie { struct iwl_rxq *rxq; - struct iwl_rx_mem_buffer rx_pool[RX_POOL_SIZE]; - struct iwl_rx_mem_buffer *global_table[RX_POOL_SIZE]; + struct iwl_rx_mem_buffer *rx_pool; + struct iwl_rx_mem_buffer **global_table; struct iwl_rb_allocator rba; union { struct iwl_context_info *ctxt_info; @@ -573,6 +573,7 @@ struct iwl_trans_pcie { u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; u8 max_tbs; u16 tfd_size; + u16 num_rx_bufs; enum iwl_amsdu_size rx_buf_size; bool bc_table_dword; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 452da44a21e0..f03d3cfb50da 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -510,7 +510,7 @@ void iwl_pcie_free_rbs_pool(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int i; - for (i = 0; i < RX_POOL_SIZE; i++) { + for (i = 0; i < RX_POOL_SIZE(trans_pcie->num_rx_bufs); i++) { if (!trans_pcie->rx_pool[i].page) continue; dma_unmap_page(trans->dev, trans_pcie->rx_pool[i].page_dma, @@ -738,7 +738,7 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans, spin_lock_init(&rxq->lock); if (trans->trans_cfg->mq_rx_supported) - rxq->queue_size = MQ_RX_TABLE_SIZE; + rxq->queue_size = trans->cfg->num_rbds; else rxq->queue_size = RX_QUEUE_SIZE; @@ -807,8 +807,18 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans) trans_pcie->rxq = kcalloc(trans->num_rx_queues, sizeof(struct iwl_rxq), GFP_KERNEL); - if (!trans_pcie->rxq) - return -ENOMEM; + trans_pcie->rx_pool = kcalloc(RX_POOL_SIZE(trans_pcie->num_rx_bufs), + sizeof(trans_pcie->rx_pool[0]), + GFP_KERNEL); + trans_pcie->global_table = + kcalloc(RX_POOL_SIZE(trans_pcie->num_rx_bufs), + sizeof(trans_pcie->global_table[0]), + GFP_KERNEL); + if (!trans_pcie->rxq || !trans_pcie->rx_pool || + !trans_pcie->global_table) { + ret = -ENOMEM; + goto err; + } spin_lock_init(&rba->lock); @@ -845,6 +855,8 @@ err: trans_pcie->base_rb_stts = NULL; trans_pcie->base_rb_stts_dma = 0; } + kfree(trans_pcie->rx_pool); + kfree(trans_pcie->global_table); kfree(trans_pcie->rxq); return ret; @@ -1081,12 +1093,11 @@ static int _iwl_pcie_rx_init(struct iwl_trans *trans) /* move the pool to the default queue and allocator ownerships */ queue_size = trans->trans_cfg->mq_rx_supported ? - MQ_RX_NUM_RBDS : RX_QUEUE_SIZE; + trans_pcie->num_rx_bufs - 1 : RX_QUEUE_SIZE; allocator_pool_size = trans->num_rx_queues * (RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC); num_alloc = queue_size + allocator_pool_size; - BUILD_BUG_ON(ARRAY_SIZE(trans_pcie->global_table) != - ARRAY_SIZE(trans_pcie->rx_pool)); + for (i = 0; i < num_alloc; i++) { struct iwl_rx_mem_buffer *rxb = &trans_pcie->rx_pool[i]; @@ -1177,6 +1188,8 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) if (rxq->napi.poll) netif_napi_del(&rxq->napi); } + kfree(trans_pcie->rx_pool); + kfree(trans_pcie->global_table); kfree(trans_pcie->rxq); } @@ -1390,13 +1403,12 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans, return rxb; } - /* used_bd is a 32/16 bit but only 12 are used to retrieve the vid */ if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) - vid = le16_to_cpu(rxq->cd[i].rbid) & 0x0FFF; + vid = le16_to_cpu(rxq->cd[i].rbid); else - vid = le32_to_cpu(rxq->bd_32[i]) & 0x0FFF; + vid = le32_to_cpu(rxq->bd_32[i]) & 0x0FFF; /* 12-bit VID */ - if (!vid || vid > ARRAY_SIZE(trans_pcie->global_table)) + if (!vid || vid > RX_POOL_SIZE(trans_pcie->num_rx_bufs)) goto out_err; rxb = trans_pcie->global_table[vid - 1]; From 80084e3591390367f56161a48b6818b3a3fd64df Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 2 Oct 2019 11:33:46 +0200 Subject: [PATCH 07/96] iwlwifi: pcie: map only used part of RX buffers We don't need to map *everything* of the RX buffers, we won't use that much, map only the part we're going to use. This save some IOMMU space (if applicable and it can deal with that) and also prepares a bit for mapping partial pages for 2K buffers later. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 18 ++++++++++++++++++ .../net/wireless/intel/iwlwifi/pcie/internal.h | 2 ++ drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 13 ++++++------- .../net/wireless/intel/iwlwifi/pcie/trans.c | 4 +++- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 8cadad7364ac..872cda2be0f6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -358,6 +358,24 @@ iwl_trans_get_rb_size_order(enum iwl_amsdu_size rb_size) } } +static inline int +iwl_trans_get_rb_size(enum iwl_amsdu_size rb_size) +{ + switch (rb_size) { + case IWL_AMSDU_2K: + return 2 * 1024; + case IWL_AMSDU_4K: + return 4 * 1024; + case IWL_AMSDU_8K: + return 8 * 1024; + case IWL_AMSDU_12K: + return 12 * 1024; + default: + WARN_ON(1); + return 0; + } +} + struct iwl_hcmd_names { u8 cmd_id; const char *const cmd_name; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index c45df9a48559..c7d094cf1e4e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -491,6 +491,7 @@ struct cont_rec { * @sw_csum_tx: if true, then the transport will compute the csum of the TXed * frame. * @rx_page_order: page order for receive buffer size + * @rx_buf_bytes: RX buffer (RB) size in bytes * @reg_lock: protect hw register access * @mutex: to protect stop_device / start_fw / start_hw * @cmd_in_flight: true when we have a host command in flight @@ -581,6 +582,7 @@ struct iwl_trans_pcie { bool sw_csum_tx; bool pcie_dbg_dumped_once; u32 rx_page_order; + u32 rx_buf_bytes; /*protect hw register */ spinlock_t reg_lock; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index f03d3cfb50da..20f93386fc4d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -485,7 +485,7 @@ void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority, /* Get physical address of the RB */ rxb->page_dma = dma_map_page(trans->dev, page, 0, - PAGE_SIZE << trans_pcie->rx_page_order, + trans_pcie->rx_buf_bytes, DMA_FROM_DEVICE); if (dma_mapping_error(trans->dev, rxb->page_dma)) { rxb->page = NULL; @@ -514,8 +514,7 @@ void iwl_pcie_free_rbs_pool(struct iwl_trans *trans) if (!trans_pcie->rx_pool[i].page) continue; dma_unmap_page(trans->dev, trans_pcie->rx_pool[i].page_dma, - PAGE_SIZE << trans_pcie->rx_page_order, - DMA_FROM_DEVICE); + trans_pcie->rx_buf_bytes, DMA_FROM_DEVICE); __free_pages(trans_pcie->rx_pool[i].page, trans_pcie->rx_page_order); trans_pcie->rx_pool[i].page = NULL; @@ -575,8 +574,8 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) /* Get physical address of the RB */ rxb->page_dma = dma_map_page(trans->dev, page, 0, - PAGE_SIZE << trans_pcie->rx_page_order, - DMA_FROM_DEVICE); + trans_pcie->rx_buf_bytes, + DMA_FROM_DEVICE); if (dma_mapping_error(trans->dev, rxb->page_dma)) { rxb->page = NULL; __free_pages(page, trans_pcie->rx_page_order); @@ -1248,7 +1247,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_txq *txq = trans_pcie->txq[trans_pcie->cmd_queue]; bool page_stolen = false; - int max_len = PAGE_SIZE << trans_pcie->rx_page_order; + int max_len = trans_pcie->rx_buf_bytes; u32 offset = 0; if (WARN_ON(!rxb)) @@ -1369,7 +1368,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, if (rxb->page != NULL) { rxb->page_dma = dma_map_page(trans->dev, rxb->page, 0, - PAGE_SIZE << trans_pcie->rx_page_order, + trans_pcie->rx_buf_bytes, DMA_FROM_DEVICE); if (dma_mapping_error(trans->dev, rxb->page_dma)) { /* diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index af9bc6b64542..d7617eb52c02 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1915,6 +1915,8 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, trans_pcie->rx_buf_size = trans_cfg->rx_buf_size; trans_pcie->rx_page_order = iwl_trans_get_rb_size_order(trans_pcie->rx_buf_size); + trans_pcie->rx_buf_bytes = + iwl_trans_get_rb_size(trans_pcie->rx_buf_size); trans_pcie->bc_table_dword = trans_cfg->bc_table_dword; trans_pcie->scd_set_active = trans_cfg->scd_set_active; @@ -2933,7 +2935,7 @@ static u32 iwl_trans_pcie_dump_rbs(struct iwl_trans *trans, int allocated_rb_nums) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - int max_len = PAGE_SIZE << trans_pcie->rx_page_order; + int max_len = trans_pcie->rx_buf_bytes; /* Dump RBs is supported only for pre-9000 devices (1 queue) */ struct iwl_rxq *rxq = &trans_pcie->rxq[0]; u32 i, r, j, rb_len = 0; From cfdc20efebdc1dc918338818b10f1d95b58b2ca5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 2 Oct 2019 12:11:54 +0200 Subject: [PATCH 08/96] iwlwifi: pcie: use partial pages if applicable If we have only 2k RBs like on the latest (AX210) hardware, then even on x86 where PAGE_SIZE is 4k we currently waste half of the memory. If this is the case, return partial pages from the allocator and track the offset in each RBD (to be able to find the data in them and remap them later.) This might also address other platforms with larger PAGE_SIZE by putting more RBs into a single large page. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- .../wireless/intel/iwlwifi/pcie/internal.h | 14 +++++ drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 59 +++++++++++++++---- .../net/wireless/intel/iwlwifi/pcie/trans.c | 10 +++- 3 files changed, 70 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index c7d094cf1e4e..2ac730859eac 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -106,6 +106,8 @@ struct iwl_host_cmd; * @page: driver's pointer to the rxb page * @invalid: rxb is in driver ownership - not owned by HW * @vid: index of this rxb in the global table + * @offset: indicates which offset of the page (in bytes) + * this buffer uses (if multiple RBs fit into one page) */ struct iwl_rx_mem_buffer { dma_addr_t page_dma; @@ -113,6 +115,7 @@ struct iwl_rx_mem_buffer { u16 vid; bool invalid; struct list_head list; + u32 offset; }; /** @@ -511,6 +514,11 @@ struct cont_rec { * @in_rescan: true if we have triggered a device rescan * @base_rb_stts: base virtual address of receive buffer status for all queues * @base_rb_stts_dma: base physical address of receive buffer status + * @supported_dma_mask: DMA mask to validate the actual address against, + * will be DMA_BIT_MASK(11) or DMA_BIT_MASK(12) depending on the device + * @alloc_page_lock: spinlock for the page allocator + * @alloc_page: allocated page to still use parts of + * @alloc_page_used: how much of the allocated page was already used (bytes) */ struct iwl_trans_pcie { struct iwl_rxq *rxq; @@ -583,6 +591,12 @@ struct iwl_trans_pcie { bool pcie_dbg_dumped_once; u32 rx_page_order; u32 rx_buf_bytes; + u32 supported_dma_mask; + + /* allocator lock for the two values below */ + spinlock_t alloc_page_lock; + struct page *alloc_page; + u32 alloc_page_used; /*protect hw register */ spinlock_t reg_lock; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 20f93386fc4d..498a14ebac47 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -298,6 +298,7 @@ static void iwl_pcie_restock_bd(struct iwl_trans *trans, static void iwl_pcie_rxmq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rx_mem_buffer *rxb; /* @@ -318,8 +319,8 @@ static void iwl_pcie_rxmq_restock(struct iwl_trans *trans, list); list_del(&rxb->list); rxb->invalid = false; - /* 12 first bits are expected to be empty */ - WARN_ON(rxb->page_dma & DMA_BIT_MASK(12)); + /* some low bits are expected to be unset (depending on hw) */ + WARN_ON(rxb->page_dma & trans_pcie->supported_dma_mask); /* Point to Rx buffer via next RBD in circular buffer */ iwl_pcie_restock_bd(trans, rxq, rxb); rxq->write = (rxq->write + 1) & (rxq->queue_size - 1); @@ -412,15 +413,34 @@ void iwl_pcie_rxq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq) * */ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans, - gfp_t priority) + u32 *offset, gfp_t priority) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + unsigned int rbsize = iwl_trans_get_rb_size(trans_pcie->rx_buf_size); + unsigned int allocsize = PAGE_SIZE << trans_pcie->rx_page_order; struct page *page; gfp_t gfp_mask = priority; if (trans_pcie->rx_page_order > 0) gfp_mask |= __GFP_COMP; + if (trans_pcie->alloc_page) { + spin_lock_bh(&trans_pcie->alloc_page_lock); + /* recheck */ + if (trans_pcie->alloc_page) { + *offset = trans_pcie->alloc_page_used; + page = trans_pcie->alloc_page; + trans_pcie->alloc_page_used += rbsize; + if (trans_pcie->alloc_page_used >= allocsize) + trans_pcie->alloc_page = NULL; + else + get_page(page); + spin_unlock_bh(&trans_pcie->alloc_page_lock); + return page; + } + spin_unlock_bh(&trans_pcie->alloc_page_lock); + } + /* Alloc a new receive buffer */ page = alloc_pages(gfp_mask, trans_pcie->rx_page_order); if (!page) { @@ -436,6 +456,18 @@ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans, "Failed to alloc_pages\n"); return NULL; } + + if (2 * rbsize <= allocsize) { + spin_lock_bh(&trans_pcie->alloc_page_lock); + if (!trans_pcie->alloc_page) { + get_page(page); + trans_pcie->alloc_page = page; + trans_pcie->alloc_page_used = rbsize; + } + spin_unlock_bh(&trans_pcie->alloc_page_lock); + } + + *offset = 0; return page; } @@ -456,6 +488,8 @@ void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority, struct page *page; while (1) { + unsigned int offset; + spin_lock(&rxq->lock); if (list_empty(&rxq->rx_used)) { spin_unlock(&rxq->lock); @@ -463,8 +497,7 @@ void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority, } spin_unlock(&rxq->lock); - /* Alloc a new receive buffer */ - page = iwl_pcie_rx_alloc_page(trans, priority); + page = iwl_pcie_rx_alloc_page(trans, &offset, priority); if (!page) return; @@ -482,9 +515,10 @@ void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority, BUG_ON(rxb->page); rxb->page = page; + rxb->offset = offset; /* Get physical address of the RB */ rxb->page_dma = - dma_map_page(trans->dev, page, 0, + dma_map_page(trans->dev, page, rxb->offset, trans_pcie->rx_buf_bytes, DMA_FROM_DEVICE); if (dma_mapping_error(trans->dev, rxb->page_dma)) { @@ -567,13 +601,15 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) BUG_ON(rxb->page); /* Alloc a new receive buffer */ - page = iwl_pcie_rx_alloc_page(trans, gfp_mask); + page = iwl_pcie_rx_alloc_page(trans, &rxb->offset, + gfp_mask); if (!page) continue; rxb->page = page; /* Get physical address of the RB */ - rxb->page_dma = dma_map_page(trans->dev, page, 0, + rxb->page_dma = dma_map_page(trans->dev, page, + rxb->offset, trans_pcie->rx_buf_bytes, DMA_FROM_DEVICE); if (dma_mapping_error(trans->dev, rxb->page_dma)) { @@ -1190,6 +1226,9 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) kfree(trans_pcie->rx_pool); kfree(trans_pcie->global_table); kfree(trans_pcie->rxq); + + if (trans_pcie->alloc_page) + __free_pages(trans_pcie->alloc_page, trans_pcie->rx_page_order); } static void iwl_pcie_rx_move_to_allocator(struct iwl_rxq *rxq, @@ -1261,7 +1300,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, bool reclaim; int index, cmd_index, len; struct iwl_rx_cmd_buffer rxcb = { - ._offset = offset, + ._offset = rxb->offset + offset, ._rx_page_order = trans_pcie->rx_page_order, ._page = rxb->page, ._page_stolen = false, @@ -1367,7 +1406,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, * rx_free list for reuse later. */ if (rxb->page != NULL) { rxb->page_dma = - dma_map_page(trans->dev, rxb->page, 0, + dma_map_page(trans->dev, rxb->page, rxb->offset, trans_pcie->rx_buf_bytes, DMA_FROM_DEVICE); if (dma_mapping_error(trans->dev, rxb->page_dma)) { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index d7617eb52c02..cb4915451792 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1917,6 +1917,9 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, iwl_trans_get_rb_size_order(trans_pcie->rx_buf_size); trans_pcie->rx_buf_bytes = iwl_trans_get_rb_size(trans_pcie->rx_buf_size); + trans_pcie->supported_dma_mask = DMA_BIT_MASK(12); + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) + trans_pcie->supported_dma_mask = DMA_BIT_MASK(11); trans_pcie->bc_table_dword = trans_cfg->bc_table_dword; trans_pcie->scd_set_active = trans_cfg->scd_set_active; @@ -2961,9 +2964,9 @@ static u32 iwl_trans_pcie_dump_rbs(struct iwl_trans *trans, rb->index = cpu_to_le32(i); memcpy(rb->data, page_address(rxb->page), max_len); /* remap the page for the free benefit */ - rxb->page_dma = dma_map_page(trans->dev, rxb->page, 0, - max_len, - DMA_FROM_DEVICE); + rxb->page_dma = dma_map_page(trans->dev, rxb->page, + rxb->offset, max_len, + DMA_FROM_DEVICE); *data = iwl_fw_error_next_data(*data); } @@ -3454,6 +3457,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, trans_pcie->opmode_down = true; spin_lock_init(&trans_pcie->irq_lock); spin_lock_init(&trans_pcie->reg_lock); + spin_lock_init(&trans_pcie->alloc_page_lock); mutex_init(&trans_pcie->mutex); init_waitqueue_head(&trans_pcie->ucode_write_waitq); From 0e00270863daaf803b32c0ff64b73dabdefd612a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 8 Oct 2019 16:03:15 +0200 Subject: [PATCH 09/96] iwlwifi: pcie: validate queue ID before array deref/bit ops Validate that the queue ID is in range before trying to use it as an index or for test_bit() - the previous bug showed that this has in fact happened, and it was lucky that we caught it there, had the bit been set then we'd have actually used the value despite being far out of range. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 8ca0250de99e..c3683cddc301 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -587,6 +587,10 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb, int idx; void *tfd; + if (WARN_ONCE(txq_id >= IWL_MAX_TVQM_QUEUES, + "queue %d out of range", txq_id)) + return -EINVAL; + if (WARN_ONCE(!test_bit(txq_id, trans_pcie->queue_used), "TX on unused queue %d\n", txq_id)) return -EINVAL; @@ -1101,9 +1105,15 @@ void iwl_pcie_gen2_txq_free_memory(struct iwl_trans *trans, static void iwl_pcie_gen2_txq_free(struct iwl_trans *trans, int txq_id) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_txq *txq = trans_pcie->txq[txq_id]; + struct iwl_txq *txq; int i; + if (WARN_ONCE(txq_id >= IWL_MAX_TVQM_QUEUES, + "queue %d out of range", txq_id)) + return; + + txq = trans_pcie->txq[txq_id]; + if (WARN_ON(!txq)) return; @@ -1258,6 +1268,10 @@ void iwl_trans_pcie_dyn_txq_free(struct iwl_trans *trans, int queue) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + if (WARN(queue >= IWL_MAX_TVQM_QUEUES, + "queue %d out of range", queue)) + return; + /* * Upon HW Rfkill - we stop the device, and then stop the queues * in the op_mode. Just for the sake of the simplicity of the op_mode, From b81b7bd02eda86ae3cb40eb594f5ccd6ca790d8b Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Thu, 10 Oct 2019 10:13:49 +0300 Subject: [PATCH 10/96] iwlwifi: remove some outdated iwl22000 configurations A few configuration structures were either not referenced anymore or assigned to devices IDs that were not in use anymore. Remove them. Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/cfg/22000.c | 22 ------------------- .../net/wireless/intel/iwlwifi/iwl-config.h | 3 --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 6 ----- 3 files changed, 31 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index bd687e745dc9..1d3dc7cf4d63 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -247,28 +247,6 @@ static const struct iwl_ht_params iwl_22000_ht_params = { #define IWL_NUM_RBDS_22000_HE 2048 #define IWL_NUM_RBDS_AX210_HE 4096 -const struct iwl_cfg iwl22000_2ac_cfg_hr = { - .name = "Intel(R) Dual Band Wireless AC 22000", - .fw_name_pre = IWL_22000_HR_FW_PRE, - IWL_DEVICE_22500, - .num_rbds = IWL_NUM_RBDS_NON_HE, -}; - -const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb = { - .name = "Intel(R) Dual Band Wireless AC 22000", - .fw_name_pre = IWL_22000_HR_CDB_FW_PRE, - IWL_DEVICE_22500, - .cdb = true, - .num_rbds = IWL_NUM_RBDS_NON_HE, -}; - -const struct iwl_cfg iwl22000_2ac_cfg_jf = { - .name = "Intel(R) Dual Band Wireless AC 22000", - .fw_name_pre = IWL_22000_JF_FW_PRE, - IWL_DEVICE_22500, - .num_rbds = IWL_NUM_RBDS_NON_HE, -}; - const struct iwl_cfg iwl_ax101_cfg_qu_hr = { .name = "Intel(R) Wi-Fi 6 AX101", .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index f8a93324d7c0..31a6f286f7f7 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -598,9 +598,6 @@ extern const struct iwl_cfg iwl9560_2ac_cfg_shared_clk; extern const struct iwl_cfg iwl9560_2ac_160_cfg_shared_clk; extern const struct iwl_cfg iwl9560_killer_2ac_cfg_shared_clk; extern const struct iwl_cfg iwl9560_killer_s_2ac_cfg_shared_clk; -extern const struct iwl_cfg iwl22000_2ac_cfg_hr; -extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb; -extern const struct iwl_cfg iwl22000_2ac_cfg_jf; extern const struct iwl_cfg iwl_ax101_cfg_qu_hr; extern const struct iwl_cfg iwl_ax101_cfg_qu_c0_hr_b0; extern const struct iwl_cfg iwl_ax101_cfg_quz_hr; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index cdf112d6c0f9..bac3d3fa0dec 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -910,7 +910,6 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2720, 0x0074, iwl_ax201_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0078, iwl_ax201_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x2720, 0x007C, iwl_ax201_cfg_qu_hr)}, - {IWL_PCI_DEVICE(0x2720, 0x0090, iwl22000_2ac_cfg_hr_cdb)}, {IWL_PCI_DEVICE(0x2720, 0x0244, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0310, iwl_ax201_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0A10, iwl_ax201_cfg_qu_hr)}, @@ -1083,11 +1082,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) else if ((hw_status & UMAG_GEN_HW_IS_FPGA) && CSR_HW_RF_STEP(iwl_trans->hw_rf_id) == SILICON_A_STEP) { cfg = &iwl22000_2ax_cfg_qnj_hr_a0_f0; - } else { - /* - * a step no FPGA - */ - cfg = &iwl22000_2ac_cfg_hr; } } From 6dece0e99faa2aef6c21406dcd95e53d1a6f99d5 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Thu, 10 Oct 2019 11:59:30 +0300 Subject: [PATCH 11/96] iwlwifi: remove CSR registers abstraction We needed this abstraction for some CSR registers for IWL_DEVICE_22560, but that has been removed, so we don't need the abstraction anymore. Remove it. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/1000.c | 6 +-- drivers/net/wireless/intel/iwlwifi/cfg/2000.c | 12 ++--- .../net/wireless/intel/iwlwifi/cfg/22000.c | 2 - drivers/net/wireless/intel/iwlwifi/cfg/5000.c | 7 +-- drivers/net/wireless/intel/iwlwifi/cfg/6000.c | 19 +++---- drivers/net/wireless/intel/iwlwifi/cfg/7000.c | 3 +- drivers/net/wireless/intel/iwlwifi/cfg/8000.c | 3 +- drivers/net/wireless/intel/iwlwifi/cfg/9000.c | 1 - .../net/wireless/intel/iwlwifi/iwl-config.h | 50 ------------------- drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 27 +++++++++- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 37 ++------------ .../wireless/intel/iwlwifi/iwl-nvm-parse.c | 14 ++---- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 6 --- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 2 +- .../wireless/intel/iwlwifi/pcie/trans-gen2.c | 5 +- .../net/wireless/intel/iwlwifi/pcie/trans.c | 37 ++++++-------- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 12 ++--- 17 files changed, 74 insertions(+), 169 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c index b92255b91b72..8a4579bb10d3 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c @@ -77,8 +77,7 @@ static const struct iwl_eeprom_params iwl1000_eeprom_params = { .trans.base_params = &iwl1000_base_params, \ .eeprom_params = &iwl1000_eeprom_params, \ .led_mode = IWL_LED_BLINK, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .trans.csr = &iwl_csr_v1 + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K const struct iwl_cfg iwl1000_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 1000 BGN", @@ -104,8 +103,7 @@ const struct iwl_cfg iwl1000_bg_cfg = { .eeprom_params = &iwl1000_eeprom_params, \ .led_mode = IWL_LED_RF_STATE, \ .rx_with_siso_diversity = true, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .trans.csr = &iwl_csr_v1 + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K const struct iwl_cfg iwl100_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 100 BGN", diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c index 2b1ae0cecc83..7140a5f3ea8b 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c @@ -103,8 +103,7 @@ static const struct iwl_eeprom_params iwl20x0_eeprom_params = { .trans.base_params = &iwl2000_base_params, \ .eeprom_params = &iwl20x0_eeprom_params, \ .led_mode = IWL_LED_RF_STATE, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .trans.csr = &iwl_csr_v1 + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K const struct iwl_cfg iwl2000_2bgn_cfg = { @@ -131,8 +130,7 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = { .trans.base_params = &iwl2030_base_params, \ .eeprom_params = &iwl20x0_eeprom_params, \ .led_mode = IWL_LED_RF_STATE, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .trans.csr = &iwl_csr_v1 + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K const struct iwl_cfg iwl2030_2bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 2230 BGN", @@ -153,8 +151,7 @@ const struct iwl_cfg iwl2030_2bgn_cfg = { .eeprom_params = &iwl20x0_eeprom_params, \ .led_mode = IWL_LED_RF_STATE, \ .rx_with_siso_diversity = true, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .trans.csr = &iwl_csr_v1 + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K const struct iwl_cfg iwl105_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 105 BGN", @@ -181,8 +178,7 @@ const struct iwl_cfg iwl105_bgn_d_cfg = { .eeprom_params = &iwl20x0_eeprom_params, \ .led_mode = IWL_LED_RF_STATE, \ .rx_with_siso_diversity = true, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .trans.csr = &iwl_csr_v1 + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K const struct iwl_cfg iwl135_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 135 BGN", diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 1d3dc7cf4d63..837c06891f5e 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -199,7 +199,6 @@ static const struct iwl_ht_params iwl_22000_ht_params = { IWL_DEVICE_22000_COMMON, \ .trans.device_family = IWL_DEVICE_FAMILY_22000, \ .trans.base_params = &iwl_22000_base_params, \ - .trans.csr = &iwl_csr_v1, \ .gp2_reg_addr = 0xa02c68, \ .mon_dram_regs = { \ .write_ptr = { \ @@ -217,7 +216,6 @@ static const struct iwl_ht_params iwl_22000_ht_params = { .trans.umac_prph_offset = 0x300000, \ .trans.device_family = IWL_DEVICE_FAMILY_AX210, \ .trans.base_params = &iwl_ax210_base_params, \ - .trans.csr = &iwl_csr_v1, \ .min_txq_size = 128, \ .gp2_reg_addr = 0xd02c68, \ .min_256_ba_txq_size = 512, \ diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c index aab4495c6085..3591336dc644 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c @@ -75,8 +75,7 @@ static const struct iwl_eeprom_params iwl5000_eeprom_params = { .trans.base_params = &iwl5000_base_params, \ .eeprom_params = &iwl5000_eeprom_params, \ .led_mode = IWL_LED_BLINK, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .trans.csr = &iwl_csr_v1 + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K const struct iwl_cfg iwl5300_agn_cfg = { .name = "Intel(R) Ultimate N WiFi Link 5300 AGN", @@ -125,7 +124,6 @@ const struct iwl_cfg iwl5350_agn_cfg = { .ht_params = &iwl5000_ht_params, .led_mode = IWL_LED_BLINK, .internal_wimax_coex = true, - .trans.csr = &iwl_csr_v1, }; #define IWL_DEVICE_5150 \ @@ -141,8 +139,7 @@ const struct iwl_cfg iwl5350_agn_cfg = { .eeprom_params = &iwl5000_eeprom_params, \ .led_mode = IWL_LED_BLINK, \ .internal_wimax_coex = true, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .trans.csr = &iwl_csr_v1 + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K const struct iwl_cfg iwl5150_agn_cfg = { .name = "Intel(R) WiMAX/WiFi Link 5150 AGN", diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c index 39ea81903dbe..b4a8a6804c39 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c @@ -124,8 +124,7 @@ static const struct iwl_eeprom_params iwl6000_eeprom_params = { .trans.base_params = &iwl6000_g2_base_params, \ .eeprom_params = &iwl6000_eeprom_params, \ .led_mode = IWL_LED_RF_STATE, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .trans.csr = &iwl_csr_v1 + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K const struct iwl_cfg iwl6005_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6205 AGN", @@ -179,8 +178,7 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = { .trans.base_params = &iwl6000_g2_base_params, \ .eeprom_params = &iwl6000_eeprom_params, \ .led_mode = IWL_LED_RF_STATE, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .trans.csr = &iwl_csr_v1 + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K const struct iwl_cfg iwl6030_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6230 AGN", @@ -216,8 +214,7 @@ const struct iwl_cfg iwl6030_2bg_cfg = { .trans.base_params = &iwl6000_g2_base_params, \ .eeprom_params = &iwl6000_eeprom_params, \ .led_mode = IWL_LED_RF_STATE, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .trans.csr = &iwl_csr_v1 + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K const struct iwl_cfg iwl6035_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN", @@ -272,8 +269,7 @@ const struct iwl_cfg iwl130_bg_cfg = { .trans.base_params = &iwl6000_base_params, \ .eeprom_params = &iwl6000_eeprom_params, \ .led_mode = IWL_LED_BLINK, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .trans.csr = &iwl_csr_v1 + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K const struct iwl_cfg iwl6000i_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6200 AGN", @@ -306,8 +302,7 @@ const struct iwl_cfg iwl6000i_2bg_cfg = { .eeprom_params = &iwl6000_eeprom_params, \ .led_mode = IWL_LED_BLINK, \ .internal_wimax_coex = true, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .trans.csr = &iwl_csr_v1 + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K const struct iwl_cfg iwl6050_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN", @@ -333,8 +328,7 @@ const struct iwl_cfg iwl6050_2abg_cfg = { .eeprom_params = &iwl6000_eeprom_params, \ .led_mode = IWL_LED_BLINK, \ .internal_wimax_coex = true, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .trans.csr = &iwl_csr_v1 + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K const struct iwl_cfg iwl6150_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN", @@ -361,7 +355,6 @@ const struct iwl_cfg iwl6000_3agn_cfg = { .eeprom_params = &iwl6000_eeprom_params, .ht_params = &iwl6000_ht_params, .led_mode = IWL_LED_BLINK, - .trans.csr = &iwl_csr_v1, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c index deb520aeb3f8..b72993e07fc2 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c @@ -154,8 +154,7 @@ static const struct iwl_ht_params iwl7000_ht_params = { .nvm_hw_section_num = 0, \ .non_shared_ant = ANT_A, \ .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ - .dccm_offset = IWL7000_DCCM_OFFSET, \ - .trans.csr = &iwl_csr_v1 + .dccm_offset = IWL7000_DCCM_OFFSET #define IWL_DEVICE_7000 \ IWL_DEVICE_7000_COMMON, \ diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c index b3cc477140c0..280d84fa5cb1 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c @@ -151,8 +151,7 @@ static const struct iwl_tt_params iwl8000_tt_params = { .apmg_not_supported = true, \ .nvm_type = IWL_NVM_EXT, \ .dbgc_supported = true, \ - .min_umac_error_event_table = 0x800000, \ - .trans.csr = &iwl_csr_v1 + .min_umac_error_event_table = 0x800000 #define IWL_DEVICE_8000 \ IWL_DEVICE_8000_COMMON, \ diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index ac05c1a6ec6b..79390f880efb 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -145,7 +145,6 @@ static const struct iwl_tt_params iwl9000_tt_params = { .nvm_type = IWL_NVM_EXT, \ .dbgc_supported = true, \ .min_umac_error_event_table = 0x800000, \ - .trans.csr = &iwl_csr_v1, \ .d3_debug_data_base_addr = 0x401000, \ .d3_debug_data_length = 92 * 1024, \ .ht_params = &iwl9000_ht_params, \ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 31a6f286f7f7..bb91c36c9d8b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -284,52 +284,6 @@ struct iwl_pwr_tx_backoff { u32 backoff; }; -/** - * struct iwl_csr_params - * - * @flag_sw_reset: reset the device - * @flag_mac_clock_ready: - * Indicates MAC (ucode processor, etc.) is powered up and can run. - * Internal resources are accessible. - * NOTE: This does not indicate that the processor is actually running. - * NOTE: This does not indicate that device has completed - * init or post-power-down restore of internal SRAM memory. - * Use CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that - * SRAM is restored and uCode is in normal operation mode. - * This note is relevant only for pre 5xxx devices. - * NOTE: After device reset, this bit remains "0" until host sets - * INIT_DONE - * @flag_init_done: Host sets this to put device into fully operational - * D0 power mode. Host resets this after SW_RESET to put device into - * low power mode. - * @flag_mac_access_req: Host sets this to request and maintain MAC wakeup, - * to allow host access to device-internal resources. Host must wait for - * mac_clock_ready (and !GOING_TO_SLEEP) before accessing non-CSR device - * registers. - * @flag_val_mac_access_en: mac access is enabled - * @flag_master_dis: disable master - * @flag_stop_master: stop master - * @addr_sw_reset: address for resetting the device - * @mac_addr0_otp: first part of MAC address from OTP - * @mac_addr1_otp: second part of MAC address from OTP - * @mac_addr0_strap: first part of MAC address from strap - * @mac_addr1_strap: second part of MAC address from strap - */ -struct iwl_csr_params { - u8 flag_sw_reset; - u8 flag_mac_clock_ready; - u8 flag_init_done; - u8 flag_mac_access_req; - u8 flag_val_mac_access_en; - u8 flag_master_dis; - u8 flag_stop_master; - u8 addr_sw_reset; - u32 mac_addr0_otp; - u32 mac_addr1_otp; - u32 mac_addr0_strap; - u32 mac_addr1_strap; -}; - /** * struct iwl_cfg_trans - information needed to start the trans * @@ -348,7 +302,6 @@ struct iwl_csr_params { */ struct iwl_cfg_trans_params { const struct iwl_base_params *base_params; - const struct iwl_csr_params *csr; enum iwl_device_family device_family; u32 umac_prph_offset; u32 rf_id:1, @@ -499,9 +452,6 @@ struct iwl_cfg { const struct iwl_fw_mon_regs mon_smem_regs; }; -extern const struct iwl_csr_params iwl_csr_v1; -extern const struct iwl_csr_params iwl_csr_v2; - /* * This list declares the config structures for all devices. */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index 92d9898ab7c2..2c150778d144 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -256,6 +256,7 @@ /* RESET */ #define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001) #define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002) +#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080) #define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100) #define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200) #define CSR_RESET_LINK_PWR_MGMT_DISABLED (0x80000000) @@ -278,11 +279,35 @@ * 4: GOING_TO_SLEEP * Indicates MAC is entering a power-saving sleep power-down. * Not a good time to access device-internal resources. + * 3: MAC_ACCESS_REQ + * Host sets this to request and maintain MAC wakeup, to allow host + * access to device-internal resources. Host must wait for + * MAC_CLOCK_READY (and !GOING_TO_SLEEP) before accessing non-CSR + * device registers. + * 2: INIT_DONE + * Host sets this to put device into fully operational D0 power mode. + * Host resets this after SW_RESET to put device into low power mode. + * 0: MAC_CLOCK_READY + * Indicates MAC (ucode processor, etc.) is powered up and can run. + * Internal resources are accessible. + * NOTE: This does not indicate that the processor is actually running. + * NOTE: This does not indicate that device has completed + * init or post-power-down restore of internal SRAM memory. + * Use CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that + * SRAM is restored and uCode is in normal operation mode. + * Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and + * do not need to save/restore it. + * NOTE: After device reset, this bit remains "0" until host sets + * INIT_DONE */ +#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001) #define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) -#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010) +#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008) +#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010) #define CSR_GP_CNTRL_REG_FLAG_XTAL_ON (0x00000400) +#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001) + #define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000) #define CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN (0x04000000) #define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index 1b7414bf7bef..2139f0b8f2bb 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -70,36 +70,6 @@ #include "iwl-prph.h" #include "iwl-fh.h" -const struct iwl_csr_params iwl_csr_v1 = { - .flag_mac_clock_ready = 0, - .flag_val_mac_access_en = 0, - .flag_init_done = 2, - .flag_mac_access_req = 3, - .flag_sw_reset = 7, - .flag_master_dis = 8, - .flag_stop_master = 9, - .addr_sw_reset = CSR_BASE + 0x020, - .mac_addr0_otp = 0x380, - .mac_addr1_otp = 0x384, - .mac_addr0_strap = 0x388, - .mac_addr1_strap = 0x38C -}; - -const struct iwl_csr_params iwl_csr_v2 = { - .flag_init_done = 6, - .flag_mac_clock_ready = 20, - .flag_val_mac_access_en = 20, - .flag_mac_access_req = 21, - .flag_master_dis = 28, - .flag_stop_master = 29, - .flag_sw_reset = 31, - .addr_sw_reset = CSR_BASE + 0x024, - .mac_addr0_otp = 0x30, - .mac_addr1_otp = 0x34, - .mac_addr0_strap = 0x38, - .mac_addr1_strap = 0x3C -}; - void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) { trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val); @@ -506,8 +476,7 @@ int iwl_finish_nic_init(struct iwl_trans *trans, * Set "initialization complete" bit to move adapter from * D0U* --> D0A* (powered-up active) state. */ - iwl_set_bit(trans, CSR_GP_CNTRL, - BIT(cfg_trans->csr->flag_init_done)); + iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); if (cfg_trans->device_family == IWL_DEVICE_FAMILY_8000) udelay(2); @@ -518,8 +487,8 @@ int iwl_finish_nic_init(struct iwl_trans *trans, * and accesses to uCode SRAM. */ err = iwl_poll_bit(trans, CSR_GP_CNTRL, - BIT(cfg_trans->csr->flag_mac_clock_ready), - BIT(cfg_trans->csr->flag_mac_clock_ready), + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (err < 0) IWL_DEBUG_INFO(trans, "Failed to wake NIC\n"); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 1e240a2a8329..4e706c684b1d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -801,12 +801,8 @@ static void iwl_flip_hw_address(__le32 mac_addr0, __le32 mac_addr1, u8 *dest) static void iwl_set_hw_address_from_csr(struct iwl_trans *trans, struct iwl_nvm_data *data) { - __le32 mac_addr0 = - cpu_to_le32(iwl_read32(trans, - trans->trans_cfg->csr->mac_addr0_strap)); - __le32 mac_addr1 = - cpu_to_le32(iwl_read32(trans, - trans->trans_cfg->csr->mac_addr1_strap)); + __le32 mac_addr0 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR0_STRAP)); + __le32 mac_addr1 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR1_STRAP)); iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr); /* @@ -816,10 +812,8 @@ static void iwl_set_hw_address_from_csr(struct iwl_trans *trans, if (is_valid_ether_addr(data->hw_addr)) return; - mac_addr0 = cpu_to_le32(iwl_read32(trans, - trans->trans_cfg->csr->mac_addr0_otp)); - mac_addr1 = cpu_to_le32(iwl_read32(trans, - trans->trans_cfg->csr->mac_addr1_otp)); + mac_addr0 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR0_OTP)); + mac_addr1 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR1_OTP)); iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr); } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index bac3d3fa0dec..79c24c696c8f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1007,12 +1007,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* the trans_cfg should never change, so set it now */ iwl_trans->trans_cfg = &cfg->trans; - if (WARN_ONCE(!iwl_trans->trans_cfg->csr, - "CSR addresses aren't configured\n")) { - ret = -EINVAL; - goto out_free_trans; - } - #if IS_ENABLED(CONFIG_IWLMVM) /* * special-case 7265D, it has the same PCI IDs. diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 498a14ebac47..12fec6d59eb9 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -240,7 +240,7 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, IWL_DEBUG_INFO(trans, "Rx queue requesting wakeup, GP1 = 0x%x\n", reg); iwl_set_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_mac_access_req)); + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); rxq->need_update = true; return; } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index 0252716c0b24..c1bb7150489a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -157,8 +157,7 @@ static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave) * Clear "initialization complete" bit to move adapter from * D0A* (powered-up Active) --> D0U* (Uninitialized) state. */ - iwl_clear_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_init_done)); + iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); } void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans) @@ -200,7 +199,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans) /* Make sure (redundant) we've released our request to stay awake */ iwl_clear_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_mac_access_req)); + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* Stop the device, and put it in low power state */ iwl_pcie_gen2_apm_stop(trans, false); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index cb4915451792..3db1313f9270 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -183,8 +183,7 @@ out: static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans) { /* Reset entire device - do controller reset (results in SHRD_HW_RST) */ - iwl_set_bit(trans, trans->trans_cfg->csr->addr_sw_reset, - BIT(trans->trans_cfg->csr->flag_sw_reset)); + iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); usleep_range(5000, 6000); } @@ -487,8 +486,7 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) * Clear "initialization complete" bit to move adapter from * D0A* (powered-up Active) --> D0U* (Uninitialized) state. */ - iwl_clear_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_init_done)); + iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* Activates XTAL resources monitor */ __iwl_trans_pcie_set_bit(trans, CSR_MONITOR_CFG_REG, @@ -510,12 +508,11 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans) int ret; /* stop device's busmaster DMA activity */ - iwl_set_bit(trans, trans->trans_cfg->csr->addr_sw_reset, - BIT(trans->trans_cfg->csr->flag_stop_master)); + iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); - ret = iwl_poll_bit(trans, trans->trans_cfg->csr->addr_sw_reset, - BIT(trans->trans_cfg->csr->flag_master_dis), - BIT(trans->trans_cfg->csr->flag_master_dis), 100); + ret = iwl_poll_bit(trans, CSR_RESET, + CSR_RESET_REG_FLAG_MASTER_DISABLED, + CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); if (ret < 0) IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n"); @@ -564,8 +561,7 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave) * Clear "initialization complete" bit to move adapter from * D0A* (powered-up Active) --> D0U* (Uninitialized) state. */ - iwl_clear_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_init_done)); + iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); } static int iwl_pcie_nic_init(struct iwl_trans *trans) @@ -1270,7 +1266,7 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans) /* Make sure (redundant) we've released our request to stay awake */ iwl_clear_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_mac_access_req)); + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* Stop the device, and put it in low power state */ iwl_pcie_apm_stop(trans, false); @@ -1494,9 +1490,8 @@ void iwl_pcie_d3_complete_suspend(struct iwl_trans *trans, iwl_pcie_synchronize_irqs(trans); iwl_clear_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_mac_access_req)); - iwl_clear_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_init_done)); + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); if (reset) { /* @@ -1561,7 +1556,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, } iwl_set_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_mac_access_req)); + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); ret = iwl_finish_nic_init(trans, trans->trans_cfg); if (ret) @@ -1583,7 +1578,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, if (!reset) { iwl_clear_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_mac_access_req)); + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); } else { iwl_trans_pcie_tx_reset(trans); @@ -2029,7 +2024,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, /* this bit wakes up the NIC */ __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_mac_access_req)); + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_8000) udelay(2); @@ -2054,8 +2049,8 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, * and do not save/restore SRAM when power cycling. */ ret = iwl_poll_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_val_mac_access_en), - (BIT(trans->trans_cfg->csr->flag_mac_clock_ready) | + CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, + (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); if (unlikely(ret < 0)) { u32 cntrl = iwl_read32(trans, CSR_GP_CNTRL); @@ -2137,7 +2132,7 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans, goto out; __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_mac_access_req)); + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* * Above we read the CSR_GP_CNTRL register, which will flush * any previous writes, but we need the write that clears the diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index f21f16ab2a97..9ac03122653c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -306,7 +306,7 @@ static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, IWL_DEBUG_INFO(trans, "Tx queue %d requesting wakeup, GP1 = 0x%x\n", txq_id, reg); iwl_set_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_mac_access_req)); + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); txq->need_update = true; return; } @@ -646,7 +646,7 @@ static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans) trans_pcie->cmd_hold_nic_awake = false; __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_mac_access_req)); + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); } /* @@ -1255,16 +1255,16 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans, if (trans->trans_cfg->base_params->apmg_wake_up_wa && !trans_pcie->cmd_hold_nic_awake) { __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_mac_access_req)); + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); ret = iwl_poll_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_val_mac_access_en), - (BIT(trans->trans_cfg->csr->flag_mac_clock_ready) | + CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, + (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); if (ret < 0) { __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, - BIT(trans->trans_cfg->csr->flag_mac_access_req)); + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); IWL_ERR(trans, "Failed to wake NIC for hcmd\n"); return -EIO; } From 3e8bac0cf131353ddf69f35c89b650c4f5a34a2f Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Sun, 27 Oct 2019 14:01:43 +0200 Subject: [PATCH 12/96] iwlwifi: mvm: Update BEACON_TEMPLATE_CMD firmware API The new API version adds support for FILS discovery frames. It adds a new flag and a field for short SSID configuration. The new API is backward compatible, so we can just switch to it. Signed-off-by: Andrei Otcheretianski Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/tx.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h index f89a9e16a8c0..f1d1fe96fecc 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h @@ -813,6 +813,7 @@ enum iwl_mac_beacon_flags { IWL_MAC_BEACON_ANT_A = BIT(9), IWL_MAC_BEACON_ANT_B = BIT(10), IWL_MAC_BEACON_ANT_C = BIT(11), + IWL_MAC_BEACON_FILS = BIT(12), }; /** @@ -820,6 +821,7 @@ enum iwl_mac_beacon_flags { * @byte_cnt: byte count of the beacon frame. * @flags: least significant byte for rate code. The most significant byte * is &enum iwl_mac_beacon_flags. + * @short_ssid: Short SSID * @reserved: reserved * @template_id: currently equal to the mac context id of the coresponding mac. * @tim_idx: the offset of the tim IE in the beacon @@ -831,14 +833,15 @@ enum iwl_mac_beacon_flags { struct iwl_mac_beacon_cmd { __le16 byte_cnt; __le16 flags; - __le64 reserved; + __le32 short_ssid; + __le32 reserved; __le32 template_id; __le32 tim_idx; __le32 tim_size; __le32 ecsa_offset; __le32 csa_offset; struct ieee80211_hdr frame[0]; -} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_9 */ +} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_10 */ struct iwl_beacon_notif { struct iwl_mvm_tx_resp beacon_notify_hdr; From 10137f07571287aaa602f492d11db062f2dd3a29 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Mon, 28 Oct 2019 11:18:05 +0200 Subject: [PATCH 13/96] iwlwifi: yoyo: don't allow changing the domain via debugfs We don't want to allow changing the domain via debugfs so that we can apply the domain to all TLV types more easily (doing some at runtime is difficult due to buffer allocations etc.). Change the fw_dbg_domain debugfs file to be read-only and remove the write function. Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/debugfs.c | 29 ++----------------- .../net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 3 +- .../net/wireless/intel/iwlwifi/iwl-dbg-tlv.h | 1 - 3 files changed, 4 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c index ca3b1a461dea..89f74116569d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c @@ -320,31 +320,6 @@ out: FWRT_DEBUGFS_WRITE_FILE_OPS(send_hcmd, 512); -static ssize_t iwl_dbgfs_fw_dbg_domain_write(struct iwl_fw_runtime *fwrt, - char *buf, size_t count) -{ - u32 new_domain; - int ret; - - if (!iwl_trans_fw_running(fwrt->trans)) - return -EIO; - - ret = kstrtou32(buf, 0, &new_domain); - if (ret) - return ret; - - if (new_domain != fwrt->trans->dbg.domains_bitmap) { - ret = iwl_dbg_tlv_gen_active_trigs(fwrt, new_domain); - if (ret) - return ret; - - iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_PERIODIC, - NULL); - } - - return count; -} - static ssize_t iwl_dbgfs_fw_dbg_domain_read(struct iwl_fw_runtime *fwrt, size_t size, char *buf) { @@ -352,7 +327,7 @@ static ssize_t iwl_dbgfs_fw_dbg_domain_read(struct iwl_fw_runtime *fwrt, fwrt->trans->dbg.domains_bitmap); } -FWRT_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_domain, 20); +FWRT_DEBUGFS_READ_FILE_OPS(fw_dbg_domain, 20); void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, struct dentry *dbgfs_dir) @@ -360,5 +335,5 @@ void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, INIT_DELAYED_WORK(&fwrt->timestamp.wk, iwl_fw_timestamp_marker_wk); FWRT_DEBUGFS_ADD_FILE(timestamp_marker, dbgfs_dir, 0200); FWRT_DEBUGFS_ADD_FILE(send_hcmd, dbgfs_dir, 0200); - FWRT_DEBUGFS_ADD_FILE(fw_dbg_domain, dbgfs_dir, 0600); + FWRT_DEBUGFS_ADD_FILE(fw_dbg_domain, dbgfs_dir, 0400); } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index f266647dc08c..79c8c8057c2d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -913,7 +913,8 @@ iwl_dbg_tlv_gen_active_trig_list(struct iwl_fw_runtime *fwrt, } } -int iwl_dbg_tlv_gen_active_trigs(struct iwl_fw_runtime *fwrt, u32 new_domain) +static int iwl_dbg_tlv_gen_active_trigs(struct iwl_fw_runtime *fwrt, + u32 new_domain) { int i; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h index f18946872569..1360676b3b21 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h @@ -105,7 +105,6 @@ void iwl_dbg_tlv_init(struct iwl_trans *trans); void iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt, enum iwl_fw_ini_time_point tp_id, union iwl_dbg_tlv_tp_data *tp_data); -int iwl_dbg_tlv_gen_active_trigs(struct iwl_fw_runtime *fwrt, u32 new_domain); void iwl_dbg_tlv_del_timers(struct iwl_trans *trans); #endif /* __iwl_dbg_tlv_h__*/ From 058c411d19b21b8e5581cdeddae2392d5f421daa Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Mon, 28 Oct 2019 12:39:10 +0200 Subject: [PATCH 14/96] iwlwifi: yoyo: remove unnecessary active triggers status flag Now that we can't change the domain at runtime anymore, we don't have to protect the active trigger status. Remove it. Additionally, we don't need to flush the dumps at this point anymore, since this only runs during initialization and there shouldn't be any dumps running. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 3 --- drivers/net/wireless/intel/iwlwifi/fw/runtime.h | 11 ----------- drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 14 +------------- 3 files changed, 1 insertion(+), 27 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index c8bc6b9b53a4..09daf0f1f6f8 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -2353,9 +2353,6 @@ int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, u32 occur, delay; unsigned long idx; - if (test_bit(STATUS_GEN_ACTIVE_TRIGS, &fwrt->status)) - return -EBUSY; - if (!iwl_fw_ini_trigger_on(fwrt, trig)) { IWL_WARN(fwrt, "WRT: Trigger %d is not active, aborting dump\n", tp_id); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index c24575ff0e54..1b4bca717e79 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -129,14 +129,6 @@ struct iwl_txf_iter_data { u8 internal_txf; }; -/** - * enum iwl_fw_runtime_status - fw runtime status flags - * @STATUS_GEN_ACTIVE_TRIGS: generating active trigger list - */ -enum iwl_fw_runtime_status { - STATUS_GEN_ACTIVE_TRIGS, -}; - /** * struct iwl_fw_runtime - runtime data for firmware * @fw: firmware image @@ -150,7 +142,6 @@ enum iwl_fw_runtime_status { * @smem_cfg: saved firmware SMEM configuration * @cur_fw_img: current firmware image, must be maintained by * the driver by calling &iwl_fw_set_current_image() - * @status: &enum iwl_fw_runtime_status * @dump: debug dump data */ struct iwl_fw_runtime { @@ -171,8 +162,6 @@ struct iwl_fw_runtime { /* memory configuration */ struct iwl_fwrt_shared_mem_cfg smem_cfg; - unsigned long status; - /* debug */ struct { const struct iwl_fw_dump_desc *desc; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 79c8c8057c2d..4acb24f8fc11 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -891,15 +891,10 @@ static void iwl_dbg_tlv_gen_active_trig_list(struct iwl_fw_runtime *fwrt, struct iwl_dbg_tlv_time_point_data *tp) { - struct iwl_dbg_tlv_node *node, *tmp; + struct iwl_dbg_tlv_node *node; struct list_head *trig_list = &tp->trig_list; struct list_head *active_trig_list = &tp->active_trig_list; - list_for_each_entry_safe(node, tmp, active_trig_list, list) { - list_del(&node->list); - kfree(node); - } - list_for_each_entry(node, trig_list, list) { struct iwl_ucode_tlv *tlv = &node->tlv; struct iwl_fw_ini_trigger_tlv *trig = (void *)tlv->data; @@ -918,11 +913,6 @@ static int iwl_dbg_tlv_gen_active_trigs(struct iwl_fw_runtime *fwrt, { int i; - if (test_and_set_bit(STATUS_GEN_ACTIVE_TRIGS, &fwrt->status)) - return -EBUSY; - - iwl_fw_flush_dumps(fwrt); - fwrt->trans->dbg.domains_bitmap = new_domain; IWL_DEBUG_FW(fwrt, @@ -936,8 +926,6 @@ static int iwl_dbg_tlv_gen_active_trigs(struct iwl_fw_runtime *fwrt, iwl_dbg_tlv_gen_active_trig_list(fwrt, tp); } - clear_bit(STATUS_GEN_ACTIVE_TRIGS, &fwrt->status); - return 0; } From 5cbc310810090cf5a295835113d3b9e5dbbe587f Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Mon, 28 Oct 2019 12:57:00 +0200 Subject: [PATCH 15/96] iwlwifi: yoyo: remove the iwl_dbg_tlv_gen_active_trigs() function We only call this function from a single place and it's very very small and self-contained anyway, so remove the function and move the code into the caller. Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 34 +++++++------------ 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 4acb24f8fc11..31a0e885faf6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -908,27 +908,6 @@ iwl_dbg_tlv_gen_active_trig_list(struct iwl_fw_runtime *fwrt, } } -static int iwl_dbg_tlv_gen_active_trigs(struct iwl_fw_runtime *fwrt, - u32 new_domain) -{ - int i; - - fwrt->trans->dbg.domains_bitmap = new_domain; - - IWL_DEBUG_FW(fwrt, - "WRT: Generating active triggers list, domain 0x%x\n", - fwrt->trans->dbg.domains_bitmap); - - for (i = 0; i < ARRAY_SIZE(fwrt->trans->dbg.time_point); i++) { - struct iwl_dbg_tlv_time_point_data *tp = - &fwrt->trans->dbg.time_point[i]; - - iwl_dbg_tlv_gen_active_trig_list(fwrt, tp); - } - - return 0; -} - static bool iwl_dbg_tlv_check_fw_pkt(struct iwl_fw_runtime *fwrt, struct iwl_fwrt_dump_data *dump_data, union iwl_dbg_tlv_tp_data *tp_data, @@ -1002,7 +981,18 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt) enum iwl_fw_ini_buffer_location *ini_dest = &fwrt->trans->dbg.ini_dest; int ret, i; - iwl_dbg_tlv_gen_active_trigs(fwrt, IWL_FW_DBG_DOMAIN); + fwrt->trans->dbg.domains_bitmap = IWL_FW_DBG_DOMAIN; + + IWL_DEBUG_FW(fwrt, + "WRT: Generating active triggers list, domain 0x%x\n", + fwrt->trans->dbg.domains_bitmap); + + for (i = 0; i < ARRAY_SIZE(fwrt->trans->dbg.time_point); i++) { + struct iwl_dbg_tlv_time_point_data *tp = + &fwrt->trans->dbg.time_point[i]; + + iwl_dbg_tlv_gen_active_trig_list(fwrt, tp); + } *ini_dest = IWL_FW_INI_LOCATION_INVALID; for (i = 0; i < IWL_FW_INI_ALLOCATION_NUM; i++) { From e6ec237d3068dd023f5a20fd6c11527e57961019 Mon Sep 17 00:00:00 2001 From: Oren Givon Date: Tue, 22 Oct 2019 14:14:24 +0300 Subject: [PATCH 16/96] iwlwifi: add new iwlax411 struct for type SoSnj Add new struct for SoSnj and add uhb support for ax411 structs. Signed-off-by: Oren Givon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 10 ++++++++++ drivers/net/wireless/intel/iwlwifi/iwl-config.h | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 837c06891f5e..a22a830019c0 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -92,6 +92,7 @@ #define IWL_22000_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0-" #define IWL_22000_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0-" #define IWL_22000_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0-" +#define IWL_22000_SOSNJ_A_GF4_A_FW_PRE "iwlwifi-SoSnj-a0-gf4-a0-" #define IWL_22000_HR_MODULE_FIRMWARE(api) \ IWL_22000_HR_FW_PRE __stringify(api) ".ucode" @@ -707,6 +708,15 @@ const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = { const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = { .name = "Intel(R) Wi-Fi 7 AX411 160MHz", .fw_name_pre = IWL_22000_SO_A_GF4_A_FW_PRE, + .uhb_supported = true, + IWL_DEVICE_AX210, + .num_rbds = IWL_NUM_RBDS_AX210_HE, +}; + +const struct iwl_cfg iwlax411_2ax_cfg_sosnj_gf4_a0 = { + .name = "Intel(R) Wi-Fi 7 AX411 160MHz", + .fw_name_pre = IWL_22000_SOSNJ_A_GF4_A_FW_PRE, + .uhb_supported = true, IWL_DEVICE_AX210, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index bb91c36c9d8b..bbeb5fc3caad 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -586,6 +586,7 @@ extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0; extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0; extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0; extern const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0; +extern const struct iwl_cfg iwlax411_2ax_cfg_sosnj_gf4_a0; #endif /* CPTCFG_IWLMVM || CPTCFG_IWLFMAC */ #endif /* __IWL_CONFIG_H__ */ From e701da0c2320148a378ed1d191b6c4f7e8e82c4c Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Wed, 30 Oct 2019 09:40:12 +0200 Subject: [PATCH 17/96] iwlwifi: yoyo: check for the domain on all TLV types during init Now that we don't have dynamically changing domains anymore, we can simply skip all the TLVs with domains that are not enabled. To do so, remove the checks from the functions that handle the TLVs when a timepoint is reached to the top allocation function. Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/runtime.h | 2 +- .../net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 22 ++++++++----------- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 2 ++ .../net/wireless/intel/iwlwifi/iwl-trans.h | 2 ++ 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 1b4bca717e79..f8c6ed823bc5 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -69,7 +69,7 @@ #include "iwl-eeprom-parse.h" #include "fw/acpi.h" -#define IWL_FW_DBG_DOMAIN IWL_FW_INI_DOMAIN_ALWAYS_ON +#define IWL_FW_DBG_DOMAIN IWL_TRANS_FW_DBG_DOMAIN(fwrt->trans) struct iwl_fw_runtime_ops { int (*dump_start)(void *ctx); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 31a0e885faf6..eaf64ca3a134 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -290,10 +290,19 @@ void iwl_dbg_tlv_alloc(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv, struct iwl_fw_ini_header *hdr = (void *)&tlv->data[0]; u32 type = le32_to_cpu(tlv->type); u32 tlv_idx = type - IWL_UCODE_TLV_DEBUG_BASE; + u32 domain = le32_to_cpu(hdr->domain); enum iwl_ini_cfg_state *cfg_state = ext ? &trans->dbg.external_ini_cfg : &trans->dbg.internal_ini_cfg; int ret; + if (domain != IWL_FW_INI_DOMAIN_ALWAYS_ON && + !(domain & trans->dbg.domains_bitmap)) { + IWL_DEBUG_FW(trans, + "WRT: Skipping TLV with disabled domain 0x%0x (0x%0x)\n", + domain, trans->dbg.domains_bitmap); + return; + } + if (tlv_idx >= ARRAY_SIZE(dbg_tlv_alloc) || !dbg_tlv_alloc[tlv_idx]) { IWL_ERR(trans, "WRT: Unsupported TLV type 0x%x\n", type); goto out_err; @@ -660,7 +669,6 @@ static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt, list_for_each_entry(node, hcmd_list, list) { struct iwl_fw_ini_hcmd_tlv *hcmd = (void *)node->tlv.data; struct iwl_fw_ini_hcmd *hcmd_data = &hcmd->hcmd; - u32 domain = le32_to_cpu(hcmd->hdr.domain); u16 hcmd_len = le32_to_cpu(node->tlv.length) - sizeof(*hcmd); struct iwl_host_cmd cmd = { .id = WIDE_ID(hcmd_data->group, hcmd_data->id), @@ -668,10 +676,6 @@ static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt, .data = { hcmd_data->data, }, }; - if (domain != IWL_FW_INI_DOMAIN_ALWAYS_ON && - !(domain & fwrt->trans->dbg.domains_bitmap)) - continue; - iwl_trans_send_cmd(fwrt->trans, &cmd); } } @@ -897,12 +901,6 @@ iwl_dbg_tlv_gen_active_trig_list(struct iwl_fw_runtime *fwrt, list_for_each_entry(node, trig_list, list) { struct iwl_ucode_tlv *tlv = &node->tlv; - struct iwl_fw_ini_trigger_tlv *trig = (void *)tlv->data; - u32 domain = le32_to_cpu(trig->hdr.domain); - - if (domain != IWL_FW_INI_DOMAIN_ALWAYS_ON && - !(domain & fwrt->trans->dbg.domains_bitmap)) - continue; iwl_dbg_tlv_add_active_trigger(fwrt, active_trig_list, tlv); } @@ -981,8 +979,6 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt) enum iwl_fw_ini_buffer_location *ini_dest = &fwrt->trans->dbg.ini_dest; int ret, i; - fwrt->trans->dbg.domains_bitmap = IWL_FW_DBG_DOMAIN; - IWL_DEBUG_FW(fwrt, "WRT: Generating active triggers list, domain 0x%x\n", fwrt->trans->dbg.domains_bitmap); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 4096ccf58b07..c6cb5e1a1bd9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1647,6 +1647,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans) drv->trans->dbgfs_dir = debugfs_create_dir("trans", drv->dbgfs_drv); #endif + drv->trans->dbg.domains_bitmap = IWL_TRANS_FW_DBG_DOMAIN(drv->trans); + ret = iwl_request_firmware(drv, true); if (ret) { IWL_ERR(trans, "Couldn't request the fw\n"); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 872cda2be0f6..58bee4442e20 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -112,6 +112,8 @@ * 6) Eventually, the free function will be called. */ +#define IWL_TRANS_FW_DBG_DOMAIN(trans) IWL_FW_INI_DOMAIN_ALWAYS_ON + #define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */ #define FH_RSCSR_FRAME_INVALID 0x55550000 #define FH_RSCSR_FRAME_ALIGN 0x40 From 55b514b479ff8a6e2473e7ef2349d49380c5fa61 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 Oct 2019 10:28:32 +0100 Subject: [PATCH 18/96] iwlwifi: incorporate firmware filename into version We have many different firmware images with the same version, and it's sometimes cumbersome to figure out which image was really used, especially as the marketing strings that we do print out can be the same for (slightly) different hardware using different firmware images. Incorporate the firmware filename into the fw_version so it's printed out all the time. Unfortunately, this will make the string be longer than the 32 characters for ethtool, but we almost never really use ethtool, so strip the "iwlwifi-" prefix (if not overridden), and the remaining data that may then be stripped at the end is not usually useful anyway. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/img.h | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 24 +++++++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h index 994880a83652..90ca5f929cf9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h @@ -251,7 +251,7 @@ struct iwl_fw_dbg { struct iwl_fw { u32 ucode_ver; - char fw_version[ETHTOOL_FWVERS_LEN]; + char fw_version[64]; /* ucode images */ struct fw_img img[IWL_UCODE_TYPE_MAX]; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index c6cb5e1a1bd9..773de0b724be 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -493,6 +493,16 @@ static void iwl_set_ucode_capabilities(struct iwl_drv *drv, const u8 *data, } } +static const char *iwl_reduced_fw_name(struct iwl_drv *drv) +{ + const char *name = drv->firmware_name; + + if (strncmp(name, "iwlwifi-", 8) == 0) + name += 8; + + return name; +} + static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv, const struct firmware *ucode_raw, struct iwl_firmware_pieces *pieces) @@ -551,12 +561,12 @@ static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv, snprintf(drv->fw.fw_version, sizeof(drv->fw.fw_version), - "%u.%u.%u.%u%s", + "%u.%u.%u.%u%s %s", IWL_UCODE_MAJOR(drv->fw.ucode_ver), IWL_UCODE_MINOR(drv->fw.ucode_ver), IWL_UCODE_API(drv->fw.ucode_ver), IWL_UCODE_SERIAL(drv->fw.ucode_ver), - buildstr); + buildstr, iwl_reduced_fw_name(drv)); /* Verify size of file vs. image size info in file's header */ @@ -636,12 +646,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, snprintf(drv->fw.fw_version, sizeof(drv->fw.fw_version), - "%u.%u.%u.%u%s", + "%u.%u.%u.%u%s %s", IWL_UCODE_MAJOR(drv->fw.ucode_ver), IWL_UCODE_MINOR(drv->fw.ucode_ver), IWL_UCODE_API(drv->fw.ucode_ver), IWL_UCODE_SERIAL(drv->fw.ucode_ver), - buildstr); + buildstr, iwl_reduced_fw_name(drv)); data = ucode->data; @@ -895,11 +905,13 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, if (major >= 35) snprintf(drv->fw.fw_version, sizeof(drv->fw.fw_version), - "%u.%08x.%u", major, minor, local_comp); + "%u.%08x.%u %s", major, minor, + local_comp, iwl_reduced_fw_name(drv)); else snprintf(drv->fw.fw_version, sizeof(drv->fw.fw_version), - "%u.%u.%u", major, minor, local_comp); + "%u.%u.%u %s", major, minor, + local_comp, iwl_reduced_fw_name(drv)); break; } case IWL_UCODE_TLV_FW_DBG_DEST: { From 20f5aef55838241e797ba685235d91a3449e9f91 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 29 Oct 2019 15:45:40 +0100 Subject: [PATCH 19/96] iwlwifi: mvm: print out extended secboot status before dump Print out the secure boot status, extended by the PCs of LMACs and the UMAC. This needs to be before dumping, as dumping will corrupt the PC (if the NMI is handled), so move that down. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-prph.h | 3 +++ drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 27 ++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index 14c8ba23f3b9..c21d99418af9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -430,6 +430,9 @@ enum aux_misc_master1_en { #define UMAG_SB_CPU_1_STATUS 0xA038C0 #define UMAG_SB_CPU_2_STATUS 0xA038C4 #define UMAG_GEN_HW_STATUS 0xA038C8 +#define UREG_UMAC_CURRENT_PC 0xa05c18 +#define UREG_LMAC1_CURRENT_PC 0xa05c1c +#define UREG_LMAC2_CURRENT_PC 0xa05c20 /* For UMAG_GEN_HW_STATUS reg check */ enum { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index dd685f7eb410..67d414e5db19 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -353,22 +353,35 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, if (ret) { struct iwl_trans *trans = mvm->trans; - if (ret == -ETIMEDOUT) - iwl_fw_dbg_error_collect(&mvm->fwrt, - FW_DBG_TRIGGER_ALIVE_TIMEOUT); - - if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) + if (trans->trans_cfg->device_family >= + IWL_DEVICE_FAMILY_22000) { IWL_ERR(mvm, "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS), iwl_read_umac_prph(trans, UMAG_SB_CPU_2_STATUS)); - else if (trans->trans_cfg->device_family >= - IWL_DEVICE_FAMILY_8000) + IWL_ERR(mvm, "UMAC PC: 0x%x\n", + iwl_read_umac_prph(trans, + UREG_UMAC_CURRENT_PC)); + IWL_ERR(mvm, "LMAC PC: 0x%x\n", + iwl_read_umac_prph(trans, + UREG_LMAC1_CURRENT_PC)); + if (iwl_mvm_is_cdb_supported(mvm)) + IWL_ERR(mvm, "LMAC2 PC: 0x%x\n", + iwl_read_umac_prph(trans, + UREG_LMAC2_CURRENT_PC)); + } else if (trans->trans_cfg->device_family >= + IWL_DEVICE_FAMILY_8000) { IWL_ERR(mvm, "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", iwl_read_prph(trans, SB_CPU_1_STATUS), iwl_read_prph(trans, SB_CPU_2_STATUS)); + } + + if (ret == -ETIMEDOUT) + iwl_fw_dbg_error_collect(&mvm->fwrt, + FW_DBG_TRIGGER_ALIVE_TIMEOUT); + iwl_fw_set_current_image(&mvm->fwrt, old_type); return ret; } From 87f3073c16326dc6916e277df8961abb6ff17a5f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 Oct 2019 11:04:43 +0100 Subject: [PATCH 20/96] iwlwifi: prph: remove some unused register definitions There are some unused register definitions, remove them. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-prph.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index c21d99418af9..1136d9784f9d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -411,13 +411,6 @@ enum { HW_STEP_LOCATION_BITS = 24, }; -#define AUX_MISC_MASTER1_EN 0xA20818 -enum aux_misc_master1_en { - AUX_MISC_MASTER1_EN_SBE_MSK = 0x1, -}; - -#define AUX_MISC_MASTER1_SMPHR_STATUS 0xA20800 -#define RSA_ENABLE 0xA24B08 #define PREG_AUX_BUS_WPROT_0 0xA04CC0 /* device family 9000 WPROT register */ From b3bd6416fc77b5056d2dda7a4d5814ec81af7ecd Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Thu, 10 Oct 2019 15:57:35 +0300 Subject: [PATCH 21/96] iwlwifi: assume the driver_data is a trans_cfg, but allow full cfg With the new concept of separating the trans-specific (trans_cfg) data from the rest of the cfg, we will start mapping only the trans_cfg part to the PCI device ID/subsystem device ID. So we can assume that the data passed to the probe function contains the trans_cfg, but since the full cfg still contains the trans_cfg at the beginning, we can allow a full cfg to be passed as well. This makes it easier to convert the existing tables one by one. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 90 +++++++++++-------- 1 file changed, 55 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 79c24c696c8f..5eb528d2111f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -991,21 +991,32 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); + const struct iwl_cfg_trans_params *trans = + (struct iwl_cfg_trans_params *)(ent->driver_data); const struct iwl_cfg *cfg_7265d __maybe_unused = NULL; struct iwl_trans *iwl_trans; struct iwl_trans_pcie *trans_pcie; unsigned long flags; int ret; + /* + * This is needed for backwards compatibility with the old + * tables, so we don't need to change all the config structs + * at the same time. The cfg is used to compare with the old + * full cfg structs. + */ + const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); - iwl_trans = iwl_trans_pcie_alloc(pdev, ent, &cfg->trans); + /* make sure trans is the first element in iwl_cfg */ + BUILD_BUG_ON(offsetof(struct iwl_cfg, trans)); + + iwl_trans = iwl_trans_pcie_alloc(pdev, ent, trans); if (IS_ERR(iwl_trans)) return PTR_ERR(iwl_trans); trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans); /* the trans_cfg should never change, so set it now */ - iwl_trans->trans_cfg = &cfg->trans; + iwl_trans->trans_cfg = trans; #if IS_ENABLED(CONFIG_IWLMVM) /* @@ -1023,22 +1034,22 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) cfg_7265d = &iwl7265d_n_cfg; if (cfg_7265d && (iwl_trans->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D) - cfg = cfg_7265d; + iwl_trans->cfg = cfg_7265d; iwl_trans->hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID); if (cfg == &iwlax210_2ax_cfg_so_hr_a0) { if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_TY) { - cfg = &iwlax210_2ax_cfg_ty_gf_a0; + iwl_trans->cfg = &iwlax210_2ax_cfg_ty_gf_a0; } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) { - cfg = &iwlax210_2ax_cfg_so_jf_a0; + iwl_trans->cfg = &iwlax210_2ax_cfg_so_jf_a0; } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) { - cfg = &iwlax211_2ax_cfg_so_gf_a0; + iwl_trans->cfg = &iwlax211_2ax_cfg_so_gf_a0; } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF4)) { - cfg = &iwlax411_2ax_cfg_so_gf4_a0; + iwl_trans->cfg = &iwlax411_2ax_cfg_so_gf4_a0; } } else if (cfg == &iwl_ax101_cfg_qu_hr) { if ((CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == @@ -1046,13 +1057,17 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) || (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR1))) { - cfg = &iwl22000_2ax_cfg_qnj_hr_b0; + iwl_trans->cfg = &iwl22000_2ax_cfg_qnj_hr_b0; + } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == + CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) && + iwl_trans->hw_rev == CSR_HW_REV_TYPE_QUZ) { + iwl_trans->cfg = &iwl_ax101_cfg_quz_hr; } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) { - cfg = &iwl_ax101_cfg_qu_hr; + iwl_trans->cfg = &iwl_ax101_cfg_qu_hr; } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) { - cfg = &iwl22000_2ax_cfg_jf; + iwl_trans->cfg = &iwl22000_2ax_cfg_jf; } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HRCDB)) { IWL_ERR(iwl_trans, "RF ID HRCDB is not supported\n"); @@ -1069,14 +1084,11 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw_status = iwl_read_prph(iwl_trans, UMAG_GEN_HW_STATUS); if (CSR_HW_RF_STEP(iwl_trans->hw_rf_id) == SILICON_B_STEP) - /* - * b step fw is the same for physical card and fpga - */ - cfg = &iwl22000_2ax_cfg_qnj_hr_b0; + iwl_trans->cfg = &iwl22000_2ax_cfg_qnj_hr_b0; else if ((hw_status & UMAG_GEN_HW_IS_FPGA) && - CSR_HW_RF_STEP(iwl_trans->hw_rf_id) == SILICON_A_STEP) { - cfg = &iwl22000_2ax_cfg_qnj_hr_a0_f0; - } + CSR_HW_RF_STEP(iwl_trans->hw_rf_id) == + SILICON_A_STEP) + iwl_trans->cfg = &iwl22000_2ax_cfg_qnj_hr_a0_f0; } /* @@ -1087,45 +1099,53 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QU_C0) { if (cfg == &iwl_ax101_cfg_qu_hr) - cfg = &iwl_ax101_cfg_qu_c0_hr_b0; + iwl_trans->cfg = &iwl_ax101_cfg_qu_c0_hr_b0; else if (cfg == &iwl_ax201_cfg_qu_hr) - cfg = &iwl_ax201_cfg_qu_c0_hr_b0; + iwl_trans->cfg = &iwl_ax201_cfg_qu_c0_hr_b0; else if (cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0) - cfg = &iwl9461_2ac_cfg_qu_c0_jf_b0; + iwl_trans->cfg = &iwl9461_2ac_cfg_qu_c0_jf_b0; else if (cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0) - cfg = &iwl9462_2ac_cfg_qu_c0_jf_b0; + iwl_trans->cfg = &iwl9462_2ac_cfg_qu_c0_jf_b0; else if (cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0) - cfg = &iwl9560_2ac_cfg_qu_c0_jf_b0; + iwl_trans->cfg = &iwl9560_2ac_cfg_qu_c0_jf_b0; else if (cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0) - cfg = &iwl9560_2ac_160_cfg_qu_c0_jf_b0; + iwl_trans->cfg = &iwl9560_2ac_160_cfg_qu_c0_jf_b0; + else if (cfg == &killer1650s_2ax_cfg_qu_b0_hr_b0) + iwl_trans->cfg = &killer1650s_2ax_cfg_qu_c0_hr_b0; + else if (cfg == &killer1650i_2ax_cfg_qu_b0_hr_b0) + iwl_trans->cfg = &killer1650i_2ax_cfg_qu_c0_hr_b0; } /* same thing for QuZ... */ if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QUZ) { - if (iwl_trans->cfg == &iwl_ax101_cfg_qu_hr) + if (cfg == &iwl_ax101_cfg_qu_hr) iwl_trans->cfg = &iwl_ax101_cfg_quz_hr; - else if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr) + else if (cfg == &iwl_ax201_cfg_qu_hr) iwl_trans->cfg = &iwl_ax201_cfg_quz_hr; - else if (iwl_trans->cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0) + else if (cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0) iwl_trans->cfg = &iwl9461_2ac_cfg_quz_a0_jf_b0_soc; - else if (iwl_trans->cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0) + else if (cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0) iwl_trans->cfg = &iwl9462_2ac_cfg_quz_a0_jf_b0_soc; - else if (iwl_trans->cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0) + else if (cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0) iwl_trans->cfg = &iwl9560_2ac_cfg_quz_a0_jf_b0_soc; - else if (iwl_trans->cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0) + else if (cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0) iwl_trans->cfg = &iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc; } #endif - /* now set the real cfg we decided to use */ - iwl_trans->cfg = cfg; + /* + * If we didn't set the cfg yet, assume the trans is actually + * a full cfg from the old tables. + */ + if (!iwl_trans->cfg) + iwl_trans->cfg = cfg; - if (cfg->trans.mq_rx_supported) { - if (WARN_ON(!cfg->num_rbds)) { + if (iwl_trans->trans_cfg->mq_rx_supported) { + if (WARN_ON(!iwl_trans->cfg->num_rbds)) { ret = -EINVAL; goto out_free_trans; } - trans_pcie->num_rx_bufs = cfg->num_rbds; + trans_pcie->num_rx_bufs = iwl_trans->cfg->num_rbds; } else { trans_pcie->num_rx_bufs = RX_QUEUE_SIZE; } From 2a612a60ab440e6480c77b73403dfee061f74e4b Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Thu, 10 Oct 2019 16:30:11 +0300 Subject: [PATCH 22/96] iwlwifi: implement a new device configuration table Add a new device table that contains information that can be checked at runtime in order to decide which configuration to use. This allows us to map the full cfg independently from the tran-specific configuration. This is the first step in creating the new table. Subsequent patches will add the possibility of checking different values at runtime in order to make the decision. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/9000.c | 6 +++ .../net/wireless/intel/iwlwifi/iwl-config.h | 10 +++++ drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 42 +++++++++++++++---- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 79390f880efb..e7b95842bb60 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -171,6 +171,12 @@ static const struct iwl_tt_params iwl9000_tt_params = { }, \ } +const struct iwl_cfg_trans_params iwl9000_trans_cfg = { + .device_family = IWL_DEVICE_FAMILY_9000, + .base_params = &iwl9000_base_params, + .mq_rx_supported = true, + .rf_id = true, +}; const struct iwl_cfg iwl9160_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 9160", diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index bbeb5fc3caad..0af1a5184d82 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -452,9 +452,19 @@ struct iwl_cfg { const struct iwl_fw_mon_regs mon_smem_regs; }; +#define IWL_CFG_ANY (~0) + +struct iwl_dev_info { + u16 device; + u16 subdevice; + const struct iwl_cfg *cfg; +}; + /* * This list declares the config structures for all devices. */ +extern const struct iwl_cfg_trans_params iwl9000_trans_cfg; + #if IS_ENABLED(CONFIG_IWLDVM) extern const struct iwl_cfg iwl5300_agn_cfg; extern const struct iwl_cfg iwl5100_agn_cfg; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 5eb528d2111f..c2cb6283bc5a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -565,14 +565,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x06F0, 0x40A4, iwl9462_2ac_cfg_quz_a0_jf_b0_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x4234, iwl9560_2ac_cfg_quz_a0_jf_b0_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x42A4, iwl9462_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x0010, iwl9260_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0014, iwl9260_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0018, iwl9260_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x001C, iwl9260_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0030, iwl9560_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0034, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0038, iwl9560_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x003C, iwl9560_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0060, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -601,7 +595,6 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2526, 0x4010, iwl9260_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x4018, iwl9260_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x401C, iwl9260_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x4030, iwl9560_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x4034, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x4234, iwl9560_2ac_cfg_soc)}, @@ -613,6 +606,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2526, 0xA014, iwl9260_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0xE010, iwl9260_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0xE014, iwl9260_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2526, PCI_ANY_ID, iwl9000_trans_cfg)}, + {IWL_PCI_DEVICE(0x271B, 0x0010, iwl9160_2ac_cfg)}, {IWL_PCI_DEVICE(0x271B, 0x0014, iwl9160_2ac_cfg)}, {IWL_PCI_DEVICE(0x271B, 0x0210, iwl9160_2ac_cfg)}, @@ -986,6 +981,22 @@ static const struct pci_device_id iwl_hw_card_ids[] = { }; MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); +#define IWL_DEV_INFO(_device, _subdevice, _cfg) \ + {.device = (_device), .subdevice = (_subdevice), .cfg = &(_cfg)} + +static const struct iwl_dev_info iwl_dev_info_table[] = { +#if IS_ENABLED(CONFIG_IWLMVM) + IWL_DEV_INFO(0x2526, 0x0010, iwl9260_2ac_160_cfg), + IWL_DEV_INFO(0x2526, 0x0014, iwl9260_2ac_160_cfg), + IWL_DEV_INFO(0x2526, 0x0018, iwl9260_2ac_160_cfg), + IWL_DEV_INFO(0x2526, 0x001C, iwl9260_2ac_160_cfg), + IWL_DEV_INFO(0x2526, 0x0030, iwl9560_2ac_160_cfg), + IWL_DEV_INFO(0x2526, 0x0038, iwl9560_2ac_160_cfg), + IWL_DEV_INFO(0x2526, 0x003C, iwl9560_2ac_160_cfg), + IWL_DEV_INFO(0x2526, 0x4030, iwl9560_2ac_160_cfg), +#endif /* CONFIG_IWLMVM */ +}; + /* PCI registers */ #define PCI_CFG_RETRY_TIMEOUT 0x041 @@ -997,7 +1008,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct iwl_trans *iwl_trans; struct iwl_trans_pcie *trans_pcie; unsigned long flags; - int ret; + int i, ret; /* * This is needed for backwards compatibility with the old * tables, so we don't need to change all the config structs @@ -1018,6 +1029,18 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* the trans_cfg should never change, so set it now */ iwl_trans->trans_cfg = trans; + for (i = 0; i < ARRAY_SIZE(iwl_dev_info_table); i++) { + const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i]; + + if ((dev_info->device == IWL_CFG_ANY || + dev_info->device == pdev->device) && + (dev_info->subdevice == IWL_CFG_ANY || + dev_info->subdevice == pdev->subsystem_device)) { + iwl_trans->cfg = dev_info->cfg; + goto found; + } + } + #if IS_ENABLED(CONFIG_IWLMVM) /* * special-case 7265D, it has the same PCI IDs. @@ -1140,6 +1163,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (!iwl_trans->cfg) iwl_trans->cfg = cfg; +found: if (iwl_trans->trans_cfg->mq_rx_supported) { if (WARN_ON(!iwl_trans->cfg->num_rbds)) { ret = -EINVAL; From 0b295a1eb81f37dc7d4f4f2ee9ef375fb36ab5d8 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Thu, 10 Oct 2019 18:29:26 +0300 Subject: [PATCH 23/96] iwlwifi: add device name to device_info We have a lot of mostly duplicated data structures that are repeated only because the device name string is different. To avoid this, move the string from the cfg to the trans structure and add it independently from the rest of the configuration to the PCI mapping tables. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/9000.c | 4 +- drivers/net/wireless/intel/iwlwifi/dvm/main.c | 4 +- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 2 +- .../net/wireless/intel/iwlwifi/iwl-config.h | 3 ++ .../net/wireless/intel/iwlwifi/iwl-trans.h | 2 + .../net/wireless/intel/iwlwifi/mvm/debugfs.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/nvm.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 44 ++++++++++--------- 9 files changed, 38 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index e7b95842bb60..379ea788e424 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -190,8 +190,10 @@ const struct iwl_cfg iwl9260_2ac_cfg = { IWL_DEVICE_9000, }; +const char iwl9260_160_name[] = "Intel(R) Wireless-AC 9260 160MHz"; +const char iwl9560_160_name[] = "Intel(R) Wireless-AC 9560 160MHz"; + const struct iwl_cfg iwl9260_2ac_160_cfg = { - .name = "Intel(R) Wireless-AC 9260 160MHz", .fw_name_pre = IWL9260_FW_PRE, IWL_DEVICE_9000, }; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index 4f2789bb3b5b..598ee7315558 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c @@ -1255,7 +1255,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, ************************/ hw = iwl_alloc_all(); if (!hw) { - pr_err("%s: Cannot allocate network device\n", cfg->name); + pr_err("%s: Cannot allocate network device\n", trans->name); goto out; } @@ -1390,7 +1390,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, * 2. Read REV register ***********************/ IWL_INFO(priv, "Detected %s, REV=0x%X\n", - priv->cfg->name, priv->trans->hw_rev); + priv->trans->name, priv->trans->hw_rev); if (iwl_trans_start_hw(priv->trans)) goto out_free_hw; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 09daf0f1f6f8..89d796821023 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -929,7 +929,7 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt, cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev)); memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable, sizeof(dump_info->fw_human_readable)); - strncpy(dump_info->dev_human_readable, fwrt->trans->cfg->name, + strncpy(dump_info->dev_human_readable, fwrt->trans->name, sizeof(dump_info->dev_human_readable) - 1); strncpy(dump_info->bus_human_readable, fwrt->dev->bus->name, sizeof(dump_info->bus_human_readable) - 1); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 0af1a5184d82..be6a2bf9ce74 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -458,12 +458,15 @@ struct iwl_dev_info { u16 device; u16 subdevice; const struct iwl_cfg *cfg; + const char *name; }; /* * This list declares the config structures for all devices. */ extern const struct iwl_cfg_trans_params iwl9000_trans_cfg; +extern const char iwl9260_160_name[]; +extern const char iwl9560_160_name[]; #if IS_ENABLED(CONFIG_IWLDVM) extern const struct iwl_cfg iwl5300_agn_cfg; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 58bee4442e20..ab547be4994b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -859,6 +859,8 @@ struct iwl_trans { enum iwl_plat_pm_mode system_pm_mode; + const char *name; + /* pointer to trans specific struct */ /*Ensure that this pointer will always be aligned to sizeof pointer */ char trans_specific[0] __aligned(sizeof(void *)); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index aa659162a7c2..190cf15b825c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -752,7 +752,7 @@ static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf, pos += scnprintf(pos, endpos - pos, "FW: %s\n", mvm->fwrt.fw->human_readable); pos += scnprintf(pos, endpos - pos, "Device: %s\n", - mvm->fwrt.trans->cfg->name); + mvm->fwrt.trans->name); pos += scnprintf(pos, endpos - pos, "Bus: %s\n", mvm->fwrt.dev->bus->name); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c index 945c1ea5cda8..c46c00706cd5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c @@ -178,7 +178,7 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, } else { IWL_DEBUG_EEPROM(mvm->trans->dev, "NVM access command failed with status %d (device: %s)\n", - ret, mvm->cfg->name); + ret, mvm->trans->name); ret = -ENODATA; } goto exit; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 1b07a8e8f069..dfe02440d474 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -830,7 +830,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, } IWL_INFO(mvm, "Detected %s, REV=0x%X\n", - mvm->cfg->name, mvm->trans->hw_rev); + mvm->trans->name, mvm->trans->hw_rev); if (iwlwifi_mod_params.nvm_file) mvm->nvm_file_name = iwlwifi_mod_params.nvm_file; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index c2cb6283bc5a..9d8ffbecf5be 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -592,20 +592,10 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2526, 0x1610, iwl9270_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x2030, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x2034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x4010, iwl9260_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x4018, iwl9260_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x401C, iwl9260_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x4034, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x42A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x6010, iwl9260_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x6014, iwl9260_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x8014, iwl9260_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x8010, iwl9260_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0xA014, iwl9260_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0xE010, iwl9260_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0xE014, iwl9260_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, PCI_ANY_ID, iwl9000_trans_cfg)}, {IWL_PCI_DEVICE(0x271B, 0x0010, iwl9160_2ac_cfg)}, @@ -981,19 +971,28 @@ static const struct pci_device_id iwl_hw_card_ids[] = { }; MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); -#define IWL_DEV_INFO(_device, _subdevice, _cfg) \ - {.device = (_device), .subdevice = (_subdevice), .cfg = &(_cfg)} +#define IWL_DEV_INFO(_device, _subdevice, _cfg, _name) \ + { .device = (_device), .subdevice = (_subdevice), .cfg = &(_cfg), \ + .name = _name } static const struct iwl_dev_info iwl_dev_info_table[] = { #if IS_ENABLED(CONFIG_IWLMVM) - IWL_DEV_INFO(0x2526, 0x0010, iwl9260_2ac_160_cfg), - IWL_DEV_INFO(0x2526, 0x0014, iwl9260_2ac_160_cfg), - IWL_DEV_INFO(0x2526, 0x0018, iwl9260_2ac_160_cfg), - IWL_DEV_INFO(0x2526, 0x001C, iwl9260_2ac_160_cfg), - IWL_DEV_INFO(0x2526, 0x0030, iwl9560_2ac_160_cfg), - IWL_DEV_INFO(0x2526, 0x0038, iwl9560_2ac_160_cfg), - IWL_DEV_INFO(0x2526, 0x003C, iwl9560_2ac_160_cfg), - IWL_DEV_INFO(0x2526, 0x4030, iwl9560_2ac_160_cfg), + IWL_DEV_INFO(0x2526, 0x0010, iwl9260_2ac_160_cfg, iwl9260_160_name), + IWL_DEV_INFO(0x2526, 0x0014, iwl9260_2ac_160_cfg, iwl9260_160_name), + IWL_DEV_INFO(0x2526, 0x0018, iwl9260_2ac_160_cfg, iwl9260_160_name), + IWL_DEV_INFO(0x2526, 0x001C, iwl9260_2ac_160_cfg, iwl9260_160_name), + IWL_DEV_INFO(0x2526, 0x6010, iwl9260_2ac_160_cfg, iwl9260_160_name), + IWL_DEV_INFO(0x2526, 0x6014, iwl9260_2ac_160_cfg, iwl9260_160_name), + IWL_DEV_INFO(0x2526, 0x8014, iwl9260_2ac_160_cfg, iwl9260_160_name), + IWL_DEV_INFO(0x2526, 0x8010, iwl9260_2ac_160_cfg, iwl9260_160_name), + IWL_DEV_INFO(0x2526, 0xA014, iwl9260_2ac_160_cfg, iwl9260_160_name), + IWL_DEV_INFO(0x2526, 0xE010, iwl9260_2ac_160_cfg, iwl9260_160_name), + IWL_DEV_INFO(0x2526, 0xE014, iwl9260_2ac_160_cfg, iwl9260_160_name), + + IWL_DEV_INFO(0x2526, 0x0030, iwl9560_2ac_160_cfg, iwl9560_160_name), + IWL_DEV_INFO(0x2526, 0x0038, iwl9560_2ac_160_cfg, iwl9560_160_name), + IWL_DEV_INFO(0x2526, 0x003C, iwl9560_2ac_160_cfg, iwl9560_160_name), + IWL_DEV_INFO(0x2526, 0x4030, iwl9560_2ac_160_cfg, iwl9560_160_name), #endif /* CONFIG_IWLMVM */ }; @@ -1037,6 +1036,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (dev_info->subdevice == IWL_CFG_ANY || dev_info->subdevice == pdev->subsystem_device)) { iwl_trans->cfg = dev_info->cfg; + iwl_trans->name = dev_info->name; goto found; } } @@ -1164,6 +1164,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_trans->cfg = cfg; found: + /* if we don't have a name yet, copy name from the old cfg */ + if (!iwl_trans->name) + iwl_trans->name = iwl_trans->cfg->name; + if (iwl_trans->trans_cfg->mq_rx_supported) { if (WARN_ON(!iwl_trans->cfg->num_rbds)) { ret = -EINVAL; From d27c768f3b617a5a94844e58b18f773d2e40f41c Mon Sep 17 00:00:00 2001 From: zhengbin Date: Tue, 24 Dec 2019 22:16:03 +0800 Subject: [PATCH 24/96] ath9k: use true,false for bool variable Fixes coccicheck warning: drivers/net/wireless/ath/ath9k/ar9003_aic.c:409:2-12: WARNING: Assignment of 0/1 to bool variable Reported-by: Hulk Robot Signed-off-by: zhengbin Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_aic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_aic.c b/drivers/net/wireless/ath/ath9k/ar9003_aic.c index 547cd46da260..d0f1e8bcc846 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_aic.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_aic.c @@ -406,7 +406,7 @@ static bool ar9003_aic_cal_post_process(struct ath_hw *ah) sram.com_att_6db = ar9003_aic_find_index(1, fixed_com_att_db); - sram.valid = 1; + sram.valid = true; sram.rot_dir_att_db = min(max(rot_dir_path_att_db, From f89ee9927a49d805ae355c6d88a22e11a7ec083a Mon Sep 17 00:00:00 2001 From: zhengbin Date: Tue, 24 Dec 2019 22:16:05 +0800 Subject: [PATCH 25/96] wil6210: use true,false for bool variable Fixes coccicheck warning: drivers/net/wireless/ath/wil6210/main.c:765:1-14: WARNING: Assignment of 0/1 to bool variable drivers/net/wireless/ath/wil6210/txrx.c:1143:1-19: WARNING: Assignment of 0/1 to bool variable drivers/net/wireless/ath/wil6210/wmi.c:1516:4-23: WARNING: Assignment of 0/1 to bool variable drivers/net/wireless/ath/wil6210/wmi.c:1523:4-23: WARNING: Assignment of 0/1 to bool variable drivers/net/wireless/ath/wil6210/wmi.c:1538:4-30: WARNING: Assignment of 0/1 to bool variable drivers/net/wireless/ath/wil6210/wmi.c:1545:4-30: WARNING: Assignment of 0/1 to bool variable Reported-by: Hulk Robot Signed-off-by: zhengbin Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/main.c | 2 +- drivers/net/wireless/ath/wil6210/txrx.c | 2 +- drivers/net/wireless/ath/wil6210/wmi.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 6d39547e20fd..3ba5b2550a8c 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -762,7 +762,7 @@ int wil_priv_init(struct wil6210_priv *wil) */ wil->rx_buff_id_count = WIL_RX_BUFF_ARR_SIZE_DEFAULT; - wil->amsdu_en = 1; + wil->amsdu_en = true; return 0; diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 17118d643d7e..bc8c15fb609d 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -1140,7 +1140,7 @@ static int wil_tx_desc_map(union wil_tx_desc *desc, dma_addr_t pa, void wil_tx_data_init(struct wil_ring_tx_data *txdata) { spin_lock_bh(&txdata->lock); - txdata->dot1x_open = 0; + txdata->dot1x_open = false; txdata->enabled = 0; txdata->idle = 0; txdata->last_idle = 0; diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index dcba0a4c47b4..23e1ed6a9d6d 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1513,14 +1513,14 @@ static void wmi_link_stats_parse(struct wil6210_vif *vif, u64 tsf, if (vif->fw_stats_ready) { /* clean old statistics */ vif->fw_stats_tsf = 0; - vif->fw_stats_ready = 0; + vif->fw_stats_ready = false; } wil_link_stats_store_basic(vif, payload + hdr_size); if (!has_next) { vif->fw_stats_tsf = tsf; - vif->fw_stats_ready = 1; + vif->fw_stats_ready = true; } break; @@ -1535,14 +1535,14 @@ static void wmi_link_stats_parse(struct wil6210_vif *vif, u64 tsf, if (wil->fw_stats_global.ready) { /* clean old statistics */ wil->fw_stats_global.tsf = 0; - wil->fw_stats_global.ready = 0; + wil->fw_stats_global.ready = false; } wil_link_stats_store_global(vif, payload + hdr_size); if (!has_next) { wil->fw_stats_global.tsf = tsf; - wil->fw_stats_global.ready = 1; + wil->fw_stats_global.ready = true; } break; From d239380196c4e27a26fa4bea73d2bf994c14ec2d Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 19 Dec 2019 13:15:38 +0000 Subject: [PATCH 26/96] ath10k: pci: Only dump ATH10K_MEM_REGION_TYPE_IOREG when safe ath10k_pci_dump_memory_reg() will try to access memory of type ATH10K_MEM_REGION_TYPE_IOREG however, if a hardware restart is in progress this can crash a system. Individual ioread32() time has been observed to jump from 15-20 ticks to > 80k ticks followed by a secure-watchdog bite and a system reset. Work around this corner case by only issuing the read transaction when the driver state is ATH10K_STATE_ON. Tested-on: QCA9988 PCI 10.4-3.9.0.2-00044 Fixes: 219cc084c6706 ("ath10k: add memory dump support QCA9984") Signed-off-by: Bryan O'Donoghue Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index bb44f5a0941b..4822a65f6f3c 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1604,11 +1604,22 @@ static int ath10k_pci_dump_memory_reg(struct ath10k *ar, { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); u32 i; + int ret; + + mutex_lock(&ar->conf_mutex); + if (ar->state != ATH10K_STATE_ON) { + ath10k_warn(ar, "Skipping pci_dump_memory_reg invalid state\n"); + ret = -EIO; + goto done; + } for (i = 0; i < region->len; i += 4) *(u32 *)(buf + i) = ioread32(ar_pci->mem + region->start + i); - return region->len; + ret = region->len; +done: + mutex_unlock(&ar->conf_mutex); + return ret; } /* if an error happened returns < 0, otherwise the length */ @@ -1704,7 +1715,11 @@ static void ath10k_pci_dump_memory(struct ath10k *ar, count = ath10k_pci_dump_memory_sram(ar, current_region, buf); break; case ATH10K_MEM_REGION_TYPE_IOREG: - count = ath10k_pci_dump_memory_reg(ar, current_region, buf); + ret = ath10k_pci_dump_memory_reg(ar, current_region, buf); + if (ret < 0) + break; + + count = ret; break; default: ret = ath10k_pci_dump_memory_generic(ar, current_region, buf); From 63ec5cbc31f7c37870b7fbd33d9f1a50ba320221 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 19 Dec 2019 13:15:39 +0000 Subject: [PATCH 27/96] ath10k: pci: Fix comment on ath10k_pci_dump_memory_sram The description of ath10k_pci_dump_memory_sram() is inaccurate, an error can never be returned, it is always the length. Update the comment to reflect. Fixes: 219cc084c6706 ("ath10k: add memory dump support QCA9984") Signed-off-by: Bryan O'Donoghue Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 4822a65f6f3c..ded7a220a4aa 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1578,7 +1578,7 @@ static int ath10k_pci_set_ram_config(struct ath10k *ar, u32 config) return 0; } -/* if an error happened returns < 0, otherwise the length */ +/* Always returns the length */ static int ath10k_pci_dump_memory_sram(struct ath10k *ar, const struct ath10k_mem_region *region, u8 *buf) From 57a3b60ddbfa87e8707c453c69915a3c5d2c9e50 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Sun, 22 Dec 2019 21:48:54 -0800 Subject: [PATCH 28/96] ath10k: Add optional qdss clk The WiFi firmware found on sm8150 requires that the QDSS clock is ticking in order to operate, so add an optional clock to the binding to allow this to be specified in the sm8150 dts and add the clock to the list of clocks in the driver. Signed-off-by: Bjorn Andersson Acked-by: Rob Herring Signed-off-by: Kalle Valo --- Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt | 2 +- drivers/net/wireless/ath/ath10k/snoc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt index 017128394a3e..3fc2cce4626b 100644 --- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt @@ -50,7 +50,7 @@ Optional properties: entry in clock-names. - clock-names: Should contain the clock names "wifi_wcss_cmd", "wifi_wcss_ref", "wifi_wcss_rtc" for "qcom,ipq4019-wifi" compatible target and - "cxo_ref_clk_pin" for "qcom,wcn3990-wifi" + "cxo_ref_clk_pin" and optionally "qdss" for "qcom,wcn3990-wifi" compatible target. - qcom,msi_addr: MSI interrupt address. - qcom,msi_base: Base value to add before writing MSI data into diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 7e85c4916e7f..aeb4cca92c35 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -46,7 +46,7 @@ static const char * const ath10k_regulators[] = { }; static const char * const ath10k_clocks[] = { - "cxo_ref_clk_pin", + "cxo_ref_clk_pin", "qdss", }; static void ath10k_snoc_htc_tx_cb(struct ath10k_ce_pipe *ce_state); From 0f7ab288ade970b7754d89b594e872ea40af8f66 Mon Sep 17 00:00:00 2001 From: zhengbin Date: Tue, 24 Dec 2019 22:16:04 +0800 Subject: [PATCH 29/96] ath10k: use true,false for bool variable Fixes coccicheck warning: drivers/net/wireless/ath/ath10k/htt_rx.c:2143:2-31: WARNING: Assignment of 0/1 to bool variable Reported-by: Hulk Robot Signed-off-by: zhengbin Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 7fb15180c685..38a5814cf345 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2140,7 +2140,7 @@ static bool ath10k_htt_rx_pn_check_replay_hl(struct ath10k *ar, if (last_pn_valid) pn_invalid = ath10k_htt_rx_pn_cmp48(&new_pn, last_pn); else - peer->tids_last_pn_valid[tid] = 1; + peer->tids_last_pn_valid[tid] = true; if (!pn_invalid) last_pn->pn48 = new_pn.pn48; From 218f646d235a84d716c603100a6aa5447bc3c9a2 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Tue, 31 Dec 2019 17:27:06 +0800 Subject: [PATCH 30/96] ath10k: drop RX skb with invalid length for sdio When simulate random transfer fail for sdio write and read, it crash sometimes. Test steps: 1. Add config and update kernel: CONFIG_FAIL_MMC_REQUEST=y CONFIG_FAULT_INJECTION=y CONFIG_FAULT_INJECTION_DEBUG_FS=y 2. run simulate fail: cd /sys/kernel/debug/mmc1/fail_mmc_request echo 10 > probability echo 10 > times # repeat until hitting issues 3. it crash, the act len of ath10k_htc_hdr is higher than allocate len, it cause panic: [ 99.723482] skbuff: skb_over_panic: text:00000000caa0f780 len:57013 put:57013 head:000000004116f24a data:0000000019ecb4dc tail:0xdef5 end:0x640 dev: [ 99.737697] ------------[ cut here ]------------ [ 99.742327] kernel BUG at /mnt/host/source/src/third_party/kernel/v4.19/net/core/skbuff.c:104! [ 99.750937] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP [ 99.831154] Process kworker/0:2 (pid: 151, stack limit = 0x00000000728010bf) [ 99.838200] CPU: 0 PID: 151 Comm: kworker/0:2 Tainted: G W 4.19.85 #48 [ 99.846022] Hardware name: MediaTek krane sku0 board (DT) [ 99.851429] Workqueue: events sdio_irq_work [ 99.855614] pstate: 60000005 (nZCv daif -PAN -UAO) [ 99.860402] pc : skb_panic+0x64/0x68 [ 99.863974] lr : skb_panic+0x64/0x68 [ 99.867542] sp : ffffff8008833a90 [ 99.870850] x29: ffffff8008833ac0 x28: ffffffe52e337370 [ 99.876159] x27: ffffffe52e328a90 x26: 000000000000e0d0 [ 99.881469] x25: ffffffe52e336b60 x24: 000000000000deb5 [ 99.886779] x23: ffffffe52e340680 x22: ffffffe4efd47e00 [ 99.892088] x21: 000000000000deb5 x20: ffffffa516d85b4c [ 99.897397] x19: ffffffa526928037 x18: 0000000000000000 [ 99.902706] x17: 000000000000003c x16: ffffffa5265b6c80 [ 99.908015] x15: 0000000000000006 x14: 3a76656420303436 [ 99.913325] x13: 0000000000029bf0 x12: 0000000000000000 [ 99.918634] x11: 0000000000000000 x10: 0000000000000000 [ 99.923943] x9 : a3b907e4b2783000 x8 : a3b907e4b2783000 [ 99.929253] x7 : 0000000000000000 x6 : ffffffa526f66d76 [ 99.934563] x5 : 0000000000000000 x4 : 0000000000000000 [ 99.939872] x3 : 000000000002a5ab x2 : ffffffe53feed918 [ 99.945182] x1 : ffffffe53fee4a08 x0 : 000000000000008e [ 99.950491] Call trace: [ 99.952937] skb_panic+0x64/0x68 [ 99.956165] skb_put+0x7c/0x84 [ 99.959224] ath10k_sdio_irq_handler+0x740/0xbb8 [ath10k_sdio] [ 99.965055] process_sdio_pending_irqs+0x58/0x1a4 [ 99.969758] sdio_run_irqs+0x34/0x60 [ 99.973329] sdio_irq_work+0x1c/0x28 [ 99.974930] cros-ec-spi spi2.0: SPI transfer timed out [ 99.976904] process_one_work+0x210/0x410 [ 99.976911] worker_thread+0x234/0x3dc [ 99.976923] kthread+0x120/0x130 [ 99.982090] cros-ec-spi spi2.0: spi transfer failed: -110 [ 99.986054] ret_from_fork+0x10/0x18 [ 99.986063] Code: aa1403e2 2a1503e4 a90023e9 97e37d1a (d4210000) [ 99.986068] ---[ end trace cb6d948c5a0fd6c7 ]--- [ 100.017250] Kernel panic - not syncing: Fatal exception [ 100.018879] cros-ec-spi spi2.0: Command xfer error (err:-110) [ 100.023659] SMP: stopping secondary CPUs [ 100.023703] Kernel Offset: 0x251dc00000 from 0xffffff8008000000 [ 100.023707] CPU features: 0x0,2188200c [ 100.023709] Memory Limit: none The simulate fail of sdio is not a real sdio transter fail, it only set an error status in mmc_should_fail_request after the transfer end, actually the transfer is success, then sdio_io_rw_ext_helper will return error status and stop transfer the left data. For example, the really RX len is 286 bytes, then it will split to 2 blocks in sdio_io_rw_ext_helper, one is 256 bytes, left is 30 bytes, if the first 256 bytes get an error status by mmc_should_fail_request,then the left 30 bytes will not read in this RX operation. Then when the next RX arrive, the left 30 bytes will be considered as the header of the read, the top 8 bytes will be considered as ath10k_htc_hdr, but actually the 8 bytes is not the ath10k_htc_hdr, so the act_len from this ath10k_htc_hdr is not correct, if it is a big value, such as 57013, it will trigger skb_panic. Drop the skb with invalid length will be reasonable. This patch only effect sdio chips. Tested with QCA6174 SDIO with firmware WLAN.RMH.4.4.1-00029. Signed-off-by: Wen Gong Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/sdio.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c index 6fdf71b8b676..e5316b911e1d 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c @@ -642,16 +642,23 @@ static int ath10k_sdio_mbox_rx_fetch(struct ath10k *ar) ret = ath10k_sdio_readsb(ar, ar_sdio->mbox_info.htc_addr, skb->data, pkt->alloc_len); - - if (ret) { - ar_sdio->n_rx_pkts = 0; - ath10k_sdio_mbox_free_rx_pkt(pkt); - return ret; - } + if (ret) + goto err; htc_hdr = (struct ath10k_htc_hdr *)skb->data; pkt->act_len = le16_to_cpu(htc_hdr->len) + sizeof(*htc_hdr); + + if (pkt->act_len > pkt->alloc_len) { + ret = -EINVAL; + goto err; + } + skb_put(skb, pkt->act_len); + return 0; + +err: + ar_sdio->n_rx_pkts = 0; + ath10k_sdio_mbox_free_rx_pkt(pkt); return ret; } @@ -687,6 +694,11 @@ static int ath10k_sdio_mbox_rx_fetch_bundle(struct ath10k *ar) htc_hdr = (struct ath10k_htc_hdr *)(ar_sdio->vsg_buffer + pkt_offset); pkt->act_len = le16_to_cpu(htc_hdr->len) + sizeof(*htc_hdr); + if (pkt->act_len > pkt->alloc_len ) { + ret = -EINVAL; + goto err; + } + skb_put_data(pkt->skb, htc_hdr, pkt->act_len); pkt_offset += pkt->alloc_len; } From a1769bb68a850508a492e3674ab1e5e479b11254 Mon Sep 17 00:00:00 2001 From: Zhi Chen Date: Tue, 14 Jan 2020 12:35:21 +0800 Subject: [PATCH 31/96] Revert "ath10k: fix DMA related firmware crashes on multiple devices" This reverts commit 76d164f582150fd0259ec0fcbc485470bcd8033e. PCIe hung issue was observed on multiple platforms. The issue was reproduced when DUT was configured as AP and associated with 50+ STAs. For QCA9984/QCA9888, the DMA_BURST_SIZE register controls the AXI burst size of the RD/WR access to the HOST MEM. 0 - No split , RAW read/write transfer size from MAC is put out on bus as burst length 1 - Split at 256 byte boundary 2,3 - Reserved With PCIe protocol analyzer, we can see DMA Read crossing 4KB boundary when issue happened. It broke PCIe spec and caused PCIe stuck. So revert the default value from 0 to 1. Tested: IPQ8064 + QCA9984 with firmware 10.4-3.10-00047 QCS404 + QCA9984 with firmware 10.4-3.9.0.2--00044 Synaptics AS370 + QCA9888 with firmware 10.4-3.9.0.2--00040 Signed-off-by: Zhi Chen Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/hw.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 21b7a2a873b0..775fd62fb92d 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -816,7 +816,7 @@ ath10k_is_rssi_enable(struct ath10k_hw_params *hw, #define TARGET_10_4_TX_DBG_LOG_SIZE 1024 #define TARGET_10_4_NUM_WDS_ENTRIES 32 -#define TARGET_10_4_DMA_BURST_SIZE 0 +#define TARGET_10_4_DMA_BURST_SIZE 1 #define TARGET_10_4_MAC_AGGR_DELIM 0 #define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1 #define TARGET_10_4_VOW_CONFIG 0 From 6ca71a10aee8d5613446a180f85aa5efbb370b10 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Fri, 3 Jan 2020 19:14:13 +0530 Subject: [PATCH 32/96] dt: bindings: add dt entry flag to skip SCM call for msa region Add boolean context flag to disable SCM call for statically mapped msa region. Signed-off-by: Govind Singh Acked-by: Rob Herring Signed-off-by: Kalle Valo --- .../devicetree/bindings/net/wireless/qcom,ath10k.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt index 3fc2cce4626b..616c87746d6f 100644 --- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt @@ -88,6 +88,9 @@ Optional properties: of the host capability QMI request - qcom,xo-cal-data: xo cal offset to be configured in xo trim register. +- qcom,msa-fixed-perm: Boolean context flag to disable SCM call for statically + mapped msa region. + Example (to supply PCI based wifi block details): In this example, the node is defined as child node of the PCI controller. @@ -185,4 +188,5 @@ wifi@18000000 { vdd-3.3-ch0-supply = <&vreg_l25a_3p3>; memory-region = <&wifi_msa_mem>; iommus = <&apps_smmu 0x0040 0x1>; + qcom,msa-fixed-perm; }; From ab000ea6a3939972b6eaca78046c4cd7d3aeee22 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Fri, 3 Jan 2020 19:14:14 +0530 Subject: [PATCH 33/96] ath10k: Don't call SCM interface for statically mapped msa region For some targets ex: QCS404, SCM permissions for MSA region is statically configured in TrustZone fw. Add SCM call disable option for such targets to avoid duplicate permissions. Testing: Tested on WCN3990 HW Tested FW: WLAN.HL.3.1-01040-QCAHLSWMTPLZ-1 Signed-off-by: Govind Singh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/qmi.c | 9 +++++++++ drivers/net/wireless/ath/ath10k/qmi.h | 1 + 2 files changed, 10 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c index 7b524b614f22..85dce43c5439 100644 --- a/drivers/net/wireless/ath/ath10k/qmi.c +++ b/drivers/net/wireless/ath/ath10k/qmi.c @@ -84,6 +84,9 @@ static int ath10k_qmi_setup_msa_permissions(struct ath10k_qmi *qmi) int ret; int i; + if (qmi->msa_fixed_perm) + return 0; + for (i = 0; i < qmi->nr_mem_region; i++) { ret = ath10k_qmi_map_msa_permission(qmi, &qmi->mem_region[i]); if (ret) @@ -102,6 +105,9 @@ static void ath10k_qmi_remove_msa_permission(struct ath10k_qmi *qmi) { int i; + if (qmi->msa_fixed_perm) + return; + for (i = 0; i < qmi->nr_mem_region; i++) ath10k_qmi_unmap_msa_permission(qmi, &qmi->mem_region[i]); } @@ -1035,6 +1041,9 @@ static int ath10k_qmi_setup_msa_resources(struct ath10k_qmi *qmi, u32 msa_size) qmi->msa_mem_size = msa_size; } + if (of_property_read_bool(dev->of_node, "qcom,msa-fixed-perm")) + qmi->msa_fixed_perm = true; + ath10k_dbg(ar, ATH10K_DBG_QMI, "msa pa: %pad , msa va: 0x%p\n", &qmi->msa_pa, qmi->msa_va); diff --git a/drivers/net/wireless/ath/ath10k/qmi.h b/drivers/net/wireless/ath/ath10k/qmi.h index 40aafb875ed0..dc257375f161 100644 --- a/drivers/net/wireless/ath/ath10k/qmi.h +++ b/drivers/net/wireless/ath/ath10k/qmi.h @@ -104,6 +104,7 @@ struct ath10k_qmi { bool fw_ready; char fw_build_timestamp[MAX_TIMESTAMP_LEN + 1]; struct ath10k_qmi_cal_data cal_data[MAX_NUM_CAL_V01]; + bool msa_fixed_perm; }; int ath10k_qmi_wlan_enable(struct ath10k *ar, From a45ceea5015d5be4bab4f6ce59cffcbeceba7e6c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 7 Jan 2020 22:50:04 +0100 Subject: [PATCH 34/96] ath11k: fix debugfs build failure When CONFIG_ATH11K_DEBUGFS is disabled, but CONFIG_MAC80211_DEBUGFS is turned on, the driver fails to build: drivers/net/wireless/ath/ath11k/debugfs_sta.c: In function 'ath11k_dbg_sta_open_htt_peer_stats': drivers/net/wireless/ath/ath11k/debugfs_sta.c:416:4: error: 'struct ath11k' has no member named 'debug' ar->debug.htt_stats.stats_req = stats_req; ^~ It appears that just using the former symbol is sufficient here, adding a Kconfig dependency takes care of the corner cases. Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") Signed-off-by: Arnd Bergmann Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath11k/Kconfig | 2 +- drivers/net/wireless/ath/ath11k/Makefile | 3 +-- drivers/net/wireless/ath/ath11k/debug.h | 22 ++++++++++------------ drivers/net/wireless/ath/ath11k/mac.c | 2 +- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/Kconfig b/drivers/net/wireless/ath/ath11k/Kconfig index cfab4fb86aef..c88e16d4022b 100644 --- a/drivers/net/wireless/ath/ath11k/Kconfig +++ b/drivers/net/wireless/ath/ath11k/Kconfig @@ -22,7 +22,7 @@ config ATH11K_DEBUG config ATH11K_DEBUGFS bool "QCA ath11k debugfs support" - depends on ATH11K && DEBUG_FS + depends on ATH11K && DEBUG_FS && MAC80211_DEBUGFS ---help--- Enable ath11k debugfs support diff --git a/drivers/net/wireless/ath/ath11k/Makefile b/drivers/net/wireless/ath/ath11k/Makefile index a91d75c1cfeb..2761d07d938e 100644 --- a/drivers/net/wireless/ath/ath11k/Makefile +++ b/drivers/net/wireless/ath/ath11k/Makefile @@ -17,8 +17,7 @@ ath11k-y += core.o \ ce.o \ peer.o -ath11k-$(CONFIG_ATH11K_DEBUGFS) += debug_htt_stats.o -ath11k-$(CONFIG_MAC80211_DEBUGFS) += debugfs_sta.o +ath11k-$(CONFIG_ATH11K_DEBUGFS) += debug_htt_stats.o debugfs_sta.o ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o ath11k-$(CONFIG_ATH11K_TRACING) += trace.o diff --git a/drivers/net/wireless/ath/ath11k/debug.h b/drivers/net/wireless/ath/ath11k/debug.h index a317a7bdb9a2..8e8d5588b541 100644 --- a/drivers/net/wireless/ath/ath11k/debug.h +++ b/drivers/net/wireless/ath/ath11k/debug.h @@ -172,6 +172,16 @@ static inline int ath11k_debug_is_extd_rx_stats_enabled(struct ath11k *ar) { return ar->debug.extd_rx_stats; } + +void ath11k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct dentry *dir); +void +ath11k_accumulate_per_peer_tx_stats(struct ath11k_sta *arsta, + struct ath11k_per_peer_tx_stats *peer_stats, + u8 legacy_rate_idx); +void ath11k_update_per_peer_stats_from_txcompl(struct ath11k *ar, + struct sk_buff *msdu, + struct hal_tx_status *ts); #else static inline int ath11k_debug_soc_create(struct ath11k_base *ab) { @@ -243,19 +253,7 @@ static inline bool ath11k_debug_is_pktlog_peer_valid(struct ath11k *ar, u8 *addr { return false; } -#endif /* CONFIG_ATH11K_DEBUGFS */ -#ifdef CONFIG_MAC80211_DEBUGFS -void ath11k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, struct dentry *dir); -void -ath11k_accumulate_per_peer_tx_stats(struct ath11k_sta *arsta, - struct ath11k_per_peer_tx_stats *peer_stats, - u8 legacy_rate_idx); -void ath11k_update_per_peer_stats_from_txcompl(struct ath11k *ar, - struct sk_buff *msdu, - struct hal_tx_status *ts); -#else /* !CONFIG_MAC80211_DEBUGFS */ static inline void ath11k_accumulate_per_peer_tx_stats(struct ath11k_sta *arsta, struct ath11k_per_peer_tx_stats *peer_stats, diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 556eef9881a7..0ed3e4d19f7a 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -5468,7 +5468,7 @@ static const struct ieee80211_ops ath11k_ops = { .flush = ath11k_mac_op_flush, .sta_statistics = ath11k_mac_op_sta_statistics, CFG80211_TESTMODE_CMD(ath11k_tm_cmd) -#ifdef CONFIG_MAC80211_DEBUGFS +#ifdef CONFIG_ATH11K_DEBUGFS .sta_add_debugfs = ath11k_sta_add_debugfs, #endif }; From 1e93a78113b4eaf009b3c994595db44356544b05 Mon Sep 17 00:00:00 2001 From: Anilkumar Kolli Date: Tue, 17 Dec 2019 17:21:40 +0100 Subject: [PATCH 35/96] ath11k: enable HE tlvs in ppdu stats for pktlog lite This patch enables HE tlvs in ppdu stats for pktlog lite mode. Signed-off-by: John Crispin Signed-off-by: Anilkumar Kolli Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath11k/debug.c | 15 +++++++++++++++ drivers/net/wireless/ath/ath11k/dp.h | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/debug.c b/drivers/net/wireless/ath/ath11k/debug.c index f48daf17f2d2..8d485171b0b3 100644 --- a/drivers/net/wireless/ath/ath11k/debug.c +++ b/drivers/net/wireless/ath/ath11k/debug.c @@ -931,7 +931,22 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file, HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER | HTT_RX_FILTER_TLV_FLAGS_ATTENTION; } else if (mode == ATH11K_PKTLOG_MODE_LITE) { + ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar, + HTT_PPDU_STATS_TAG_PKTLOG); + if (ret) { + ath11k_err(ar->ab, "failed to enable pktlog lite: %d\n", ret); + goto out; + } + rx_filter = HTT_RX_FILTER_TLV_LITE_MODE; + } else { + ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar, + HTT_PPDU_STATS_TAG_DEFAULT); + if (ret) { + ath11k_err(ar->ab, "failed to send htt ppdu stats req: %d\n", + ret); + goto out; + } } tlv_filter.rx_filter = rx_filter; diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h index 2f0980f2c762..6ef5be4201b2 100644 --- a/drivers/net/wireless/ath/ath11k/dp.h +++ b/drivers/net/wireless/ath/ath11k/dp.h @@ -507,6 +507,14 @@ enum htt_ppdu_stats_tag_type { | BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_FLUSH) \ | BIT(HTT_PPDU_STATS_TAG_USR_COMMON_ARRAY)) +#define HTT_PPDU_STATS_TAG_PKTLOG (BIT(HTT_PPDU_STATS_TAG_USR_MPDU_ENQ_BITMAP_64) | \ + BIT(HTT_PPDU_STATS_TAG_USR_MPDU_ENQ_BITMAP_256) | \ + BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_BA_BITMAP_64) | \ + BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_BA_BITMAP_256) | \ + BIT(HTT_PPDU_STATS_TAG_INFO) | \ + BIT(HTT_PPDU_STATS_TAG_TX_MGMTCTRL_PAYLOAD) | \ + HTT_PPDU_STATS_TAG_DEFAULT) + /* HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG Message * * details: From 5815719dd2714a369448159a562f6fdf75ffe87b Mon Sep 17 00:00:00 2001 From: Bhagavathi Perumal S Date: Tue, 17 Dec 2019 17:49:17 +0100 Subject: [PATCH 36/96] ath11k: set TxBf parameters after vdev start The channel info parameters are required by the firmware to process TxBf parameters. Currently TxBf is passed prior to the channel info. This patch moves TxBf setup after the channel setup. Signed-off-by: John Crispin Signed-off-by: Bhagavathi Perumal S Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath11k/mac.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 0ed3e4d19f7a..f9ab02e84d13 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -4212,12 +4212,6 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, arvif->vdev_id, ret); } - ret = ath11k_mac_set_txbf_conf(arvif); - if (ret) { - ath11k_warn(ar->ab, "failed to set txbf conf for vdev %d: %d\n", - arvif->vdev_id, ret); - } - ath11k_dp_vdev_tx_attach(ar, arvif); mutex_unlock(&ar->conf_mutex); @@ -4567,6 +4561,11 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif, arg.channel.freq, arg.vdev_id); } + ret = ath11k_mac_set_txbf_conf(arvif); + if (ret) + ath11k_warn(ab, "failed to set txbf conf for vdev %d: %d\n", + arvif->vdev_id, ret); + return 0; } From eefca584140b42551e642277515ca26be0ca5ef3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 21 Dec 2019 00:40:46 +0000 Subject: [PATCH 37/96] ath11k: ensure ts.flags is initialized before bit-wise or'ing in values Currently the structure ts is not inititalized and ts.flags contains garbage values from the stack. This is being passed into function ath11k_dp_tx_status_parse that bit-wise or'ing in settings into the ts.flags field. To avoid flags (and other fields) from containing garbage, initialize the structure to zero before use. Addresses-Coverity: ("Uninitialized scalar variable)" Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath11k/dp_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index 918305dda106..04ad1a20e459 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -461,7 +461,7 @@ void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id) int hal_ring_id = dp->tx_ring[ring_id].tcl_comp_ring.ring_id; struct hal_srng *status_ring = &ab->hal.srng_list[hal_ring_id]; struct sk_buff *msdu; - struct hal_tx_status ts; + struct hal_tx_status ts = { 0 }; struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; u32 *desc; u32 msdu_id; From 875603b3de9fb5dc11acf80b6df45709adec68b2 Mon Sep 17 00:00:00 2001 From: Bhagavathi Perumal S Date: Thu, 9 Jan 2020 17:18:50 +0530 Subject: [PATCH 38/96] ath11k: Add missing pdev rx rate stats This adds missing rx rate info stats like pilot evm, per chain rssi, per user ul ppdu and mpdu counts and ul ofdma rate info etc. And add null checks for memory alloc failures. Signed-off-by: Bhagavathi Perumal S Signed-off-by: Kalle Valo --- .../net/wireless/ath/ath11k/debug_htt_stats.c | 205 +++++++++++++++--- .../net/wireless/ath/ath11k/debug_htt_stats.h | 42 ++++ 2 files changed, 214 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/debug_htt_stats.c b/drivers/net/wireless/ath/ath11k/debug_htt_stats.c index 090fffa5e53c..9939e909628f 100644 --- a/drivers/net/wireless/ath/ath11k/debug_htt_stats.c +++ b/drivers/net/wireless/ath/ath11k/debug_htt_stats.c @@ -776,11 +776,14 @@ static inline void htt_print_tx_peer_rate_stats_tlv(const void *tag_buf, u32 len = stats_req->buf_len; u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE; char str_buf[HTT_MAX_STRING_LEN] = {0}; - char *tx_gi[HTT_TX_PEER_STATS_NUM_GI_COUNTERS]; + char *tx_gi[HTT_TX_PEER_STATS_NUM_GI_COUNTERS] = {NULL}; u8 j; - for (j = 0; j < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; j++) + for (j = 0; j < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; j++) { tx_gi[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); + if (!tx_gi[j]) + goto fail; + } len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_PEER_RATE_STATS_TLV:"); len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_ldpc = %u", @@ -841,15 +844,16 @@ static inline void htt_print_tx_peer_rate_stats_tlv(const void *tag_buf, HTT_TX_PDEV_STATS_NUM_DCM_COUNTERS); len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_dcm = %s\n", str_buf); - for (j = 0; j < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; j++) - kfree(tx_gi[j]); - if (len >= buf_len) buf[buf_len - 1] = 0; else buf[len] = 0; stats_req->buf_len = len; + +fail: + for (j = 0; j < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; j++) + kfree(tx_gi[j]); } static inline void htt_print_rx_peer_rate_stats_tlv(const void *tag_buf, @@ -860,15 +864,21 @@ static inline void htt_print_rx_peer_rate_stats_tlv(const void *tag_buf, u32 len = stats_req->buf_len; u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE; u8 j; - char *rssi_chain[HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS]; - char *rx_gi[HTT_RX_PEER_STATS_NUM_GI_COUNTERS]; + char *rssi_chain[HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS] = {NULL}; + char *rx_gi[HTT_RX_PEER_STATS_NUM_GI_COUNTERS] = {NULL}; char str_buf[HTT_MAX_STRING_LEN] = {0}; - for (j = 0; j < HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS; j++) + for (j = 0; j < HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS; j++) { rssi_chain[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); + if (!rssi_chain[j]) + goto fail; + } - for (j = 0; j < HTT_RX_PEER_STATS_NUM_GI_COUNTERS; j++) + for (j = 0; j < HTT_RX_PEER_STATS_NUM_GI_COUNTERS; j++) { rx_gi[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); + if (!rx_gi[j]) + goto fail; + } len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_RX_PEER_RATE_STATS_TLV:"); len += HTT_DBG_OUT(buf + len, buf_len - len, "nsts = %u", @@ -928,18 +938,19 @@ static inline void htt_print_rx_peer_rate_stats_tlv(const void *tag_buf, HTT_RX_PDEV_STATS_NUM_PREAMBLE_TYPES); len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_pream = %s\n", str_buf); - for (j = 0; j < HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS; j++) - kfree(rssi_chain[j]); - - for (j = 0; j < HTT_RX_PEER_STATS_NUM_GI_COUNTERS; j++) - kfree(rx_gi[j]); - if (len >= buf_len) buf[buf_len - 1] = 0; else buf[len] = 0; stats_req->buf_len = len; + +fail: + for (j = 0; j < HTT_RX_PEER_STATS_NUM_SPATIAL_STREAMS; j++) + kfree(rssi_chain[j]); + + for (j = 0; j < HTT_RX_PEER_STATS_NUM_GI_COUNTERS; j++) + kfree(rx_gi[j]); } static inline void @@ -2832,10 +2843,13 @@ static inline void htt_print_tx_pdev_rate_stats_tlv(const void *tag_buf, u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE; u8 j; char str_buf[HTT_MAX_STRING_LEN] = {0}; - char *tx_gi[HTT_TX_PEER_STATS_NUM_GI_COUNTERS]; + char *tx_gi[HTT_TX_PEER_STATS_NUM_GI_COUNTERS] = {NULL}; - for (j = 0; j < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; j++) + for (j = 0; j < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; j++) { tx_gi[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); + if (!tx_gi[j]) + goto fail; + } len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_TX_PDEV_RATE_STATS_TLV:"); len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", @@ -2988,15 +3002,15 @@ static inline void htt_print_tx_pdev_rate_stats_tlv(const void *tag_buf, HTT_TX_PDEV_STATS_NUM_DCM_COUNTERS); len += HTT_DBG_OUT(buf + len, buf_len - len, "tx_dcm = %s\n", str_buf); - for (j = 0; j < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; j++) - kfree(tx_gi[j]); - if (len >= buf_len) buf[buf_len - 1] = 0; else buf[len] = 0; stats_req->buf_len = len; +fail: + for (j = 0; j < HTT_TX_PEER_STATS_NUM_GI_COUNTERS; j++) + kfree(tx_gi[j]); } static inline void htt_print_rx_pdev_rate_stats_tlv(const void *tag_buf, @@ -3006,16 +3020,30 @@ static inline void htt_print_rx_pdev_rate_stats_tlv(const void *tag_buf, u8 *buf = stats_req->buf; u32 len = stats_req->buf_len; u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE; - u8 j; - char *rssi_chain[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS]; - char *rx_gi[HTT_RX_PDEV_STATS_NUM_GI_COUNTERS]; + u8 i, j; + u16 index = 0; + char *rssi_chain[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS] = {NULL}; + char *rx_gi[HTT_RX_PDEV_STATS_NUM_GI_COUNTERS] = {NULL}; char str_buf[HTT_MAX_STRING_LEN] = {0}; + char *rx_pilot_evm_db[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS] = {NULL}; - for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) + for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { rssi_chain[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); + if (!rssi_chain[j]) + goto fail; + } - for (j = 0; j < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; j++) + for (j = 0; j < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; j++) { rx_gi[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); + if (!rx_gi[j]) + goto fail; + } + + for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { + rx_pilot_evm_db[j] = kmalloc(HTT_MAX_STRING_LEN, GFP_ATOMIC); + if (!rx_pilot_evm_db[j]) + goto fail; + } len += HTT_DBG_OUT(buf + len, buf_len - len, "HTT_RX_PDEV_RATE_STATS_TLV:"); len += HTT_DBG_OUT(buf + len, buf_len - len, "mac_id = %u", @@ -3059,6 +3087,32 @@ static inline void htt_print_rx_pdev_rate_stats_tlv(const void *tag_buf, ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_bw, HTT_RX_PDEV_STATS_NUM_BW_COUNTERS); len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_bw = %s ", str_buf); + len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_evm_nss_count = %u", + htt_stats_buf->nss_count); + + len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_evm_pilot_count = %u", + htt_stats_buf->pilot_count); + + for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { + index = 0; + + for (i = 0; i < HTT_RX_PDEV_STATS_RXEVM_MAX_PILOTS_PER_NSS; i++) + index += snprintf(&rx_pilot_evm_db[j][index], + HTT_MAX_STRING_LEN - index, + " %u:%d,", + i, + htt_stats_buf->rx_pilot_evm_db[j][i]); + len += HTT_DBG_OUT(buf + len, buf_len - len, "pilot_evm_dB[%u] = %s ", + j, rx_pilot_evm_db[j]); + } + + index = 0; + memset(str_buf, 0x0, HTT_MAX_STRING_LEN); + for (i = 0; i < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; i++) + index += snprintf(&str_buf[index], + HTT_MAX_STRING_LEN - index, + " %u:%d,", i, htt_stats_buf->rx_pilot_evm_db_mean[i]); + len += HTT_DBG_OUT(buf + len, buf_len - len, "pilot_evm_dB_mean = %s ", str_buf); for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { ARRAY_TO_STRING(rssi_chain[j], htt_stats_buf->rssi_chain[j], @@ -3079,12 +3133,6 @@ static inline void htt_print_rx_pdev_rate_stats_tlv(const void *tag_buf, HTT_RX_PDEV_STATS_NUM_PREAMBLE_TYPES); len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_pream = %s", str_buf); - for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) - kfree(rssi_chain[j]); - - for (j = 0; j < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; j++) - kfree(rx_gi[j]); - len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_11ax_su_ext = %u", htt_stats_buf->rx_11ax_su_ext); len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_11ac_mumimo = %u", @@ -3110,8 +3158,89 @@ static inline void htt_print_rx_pdev_rate_stats_tlv(const void *tag_buf, len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_active_dur_us_low = %u", htt_stats_buf->rx_active_dur_us_low); - len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_active_dur_us_high = %u\n", - htt_stats_buf->rx_active_dur_us_high); + len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_active_dur_us_high = %u", + htt_stats_buf->rx_active_dur_us_high); + len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_11ax_ul_ofdma = %u", + htt_stats_buf->rx_11ax_ul_ofdma); + + memset(str_buf, 0x0, HTT_MAX_STRING_LEN); + ARRAY_TO_STRING(str_buf, htt_stats_buf->ul_ofdma_rx_mcs, + HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS); + len += HTT_DBG_OUT(buf + len, buf_len - len, "ul_ofdma_rx_mcs = %s ", str_buf); + + for (j = 0; j < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; j++) { + ARRAY_TO_STRING(rx_gi[j], htt_stats_buf->ul_ofdma_rx_gi[j], + HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS); + len += HTT_DBG_OUT(buf + len, buf_len - len, "ul_ofdma_rx_gi[%u] = %s ", + j, rx_gi[j]); + } + + memset(str_buf, 0x0, HTT_MAX_STRING_LEN); + ARRAY_TO_STRING(str_buf, htt_stats_buf->ul_ofdma_rx_nss, + HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS); + len += HTT_DBG_OUT(buf + len, buf_len - len, "ul_ofdma_rx_nss = %s ", str_buf); + + memset(str_buf, 0x0, HTT_MAX_STRING_LEN); + ARRAY_TO_STRING(str_buf, htt_stats_buf->ul_ofdma_rx_bw, + HTT_RX_PDEV_STATS_NUM_BW_COUNTERS); + len += HTT_DBG_OUT(buf + len, buf_len - len, "ul_ofdma_rx_bw = %s ", str_buf); + + len += HTT_DBG_OUT(buf + len, buf_len - len, "ul_ofdma_rx_stbc = %u", + htt_stats_buf->ul_ofdma_rx_stbc); + len += HTT_DBG_OUT(buf + len, buf_len - len, "ul_ofdma_rx_ldpc = %u", + htt_stats_buf->ul_ofdma_rx_ldpc); + + memset(str_buf, 0x0, HTT_MAX_STRING_LEN); + ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_ulofdma_non_data_ppdu, + HTT_RX_PDEV_MAX_OFDMA_NUM_USER); + len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_ulofdma_non_data_ppdu = %s ", + str_buf); + + memset(str_buf, 0x0, HTT_MAX_STRING_LEN); + ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_ulofdma_data_ppdu, + HTT_RX_PDEV_MAX_OFDMA_NUM_USER); + len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_ulofdma_data_ppdu = %s ", + str_buf); + + memset(str_buf, 0x0, HTT_MAX_STRING_LEN); + ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_ulofdma_mpdu_ok, + HTT_RX_PDEV_MAX_OFDMA_NUM_USER); + len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_ulofdma_mpdu_ok = %s ", str_buf); + + memset(str_buf, 0x0, HTT_MAX_STRING_LEN); + ARRAY_TO_STRING(str_buf, htt_stats_buf->rx_ulofdma_mpdu_fail, + HTT_RX_PDEV_MAX_OFDMA_NUM_USER); + len += HTT_DBG_OUT(buf + len, buf_len - len, "rx_ulofdma_mpdu_fail = %s", + str_buf); + + for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { + index = 0; + memset(str_buf, 0x0, HTT_MAX_STRING_LEN); + for (i = 0; i < HTT_RX_PDEV_MAX_OFDMA_NUM_USER; i++) + index += snprintf(&str_buf[index], + HTT_MAX_STRING_LEN - index, + " %u:%d,", + i, htt_stats_buf->rx_ul_fd_rssi[j][i]); + len += HTT_DBG_OUT(buf + len, buf_len - len, + "rx_ul_fd_rssi: nss[%u] = %s", j, str_buf); + } + + len += HTT_DBG_OUT(buf + len, buf_len - len, "per_chain_rssi_pkt_type = %#x", + htt_stats_buf->per_chain_rssi_pkt_type); + + for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) { + index = 0; + memset(str_buf, 0x0, HTT_MAX_STRING_LEN); + for (i = 0; i < HTT_RX_PDEV_STATS_NUM_BW_COUNTERS; i++) + index += snprintf(&str_buf[index], + HTT_MAX_STRING_LEN - index, + " %u:%d,", + i, + htt_stats_buf->rx_per_chain_rssi_in_dbm[j][i]); + len += HTT_DBG_OUT(buf + len, buf_len - len, + "rx_per_chain_rssi_in_dbm[%u] = %s ", j, str_buf); + } + len += HTT_DBG_OUT(buf + len, buf_len - len, "\n"); if (len >= buf_len) buf[buf_len - 1] = 0; @@ -3119,6 +3248,16 @@ static inline void htt_print_rx_pdev_rate_stats_tlv(const void *tag_buf, buf[len] = 0; stats_req->buf_len = len; + +fail: + for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) + kfree(rssi_chain[j]); + + for (j = 0; j < HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS; j++) + kfree(rx_pilot_evm_db[j]); + + for (i = 0; i < HTT_RX_PDEV_STATS_NUM_GI_COUNTERS; i++) + kfree(rx_gi[i]); } static inline void htt_print_rx_soc_fw_stats_tlv(const void *tag_buf, diff --git a/drivers/net/wireless/ath/ath11k/debug_htt_stats.h b/drivers/net/wireless/ath/ath11k/debug_htt_stats.h index 618f1946bf49..4bdb62dd7b8d 100644 --- a/drivers/net/wireless/ath/ath11k/debug_htt_stats.h +++ b/drivers/net/wireless/ath/ath11k/debug_htt_stats.h @@ -1231,6 +1231,8 @@ struct htt_tx_pdev_rate_stats_tlv { #define HTT_RX_PDEV_STATS_NUM_BW_COUNTERS 4 #define HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS 8 #define HTT_RX_PDEV_STATS_NUM_PREAMBLE_TYPES HTT_STATS_PREAM_COUNT +#define HTT_RX_PDEV_MAX_OFDMA_NUM_USER 8 +#define HTT_RX_PDEV_STATS_RXEVM_MAX_PILOTS_PER_NSS 16 struct htt_rx_pdev_rate_stats_tlv { u32 mac_id__word; @@ -1269,6 +1271,46 @@ struct htt_rx_pdev_rate_stats_tlv { u32 rx_legacy_ofdm_rate[HTT_RX_PDEV_STATS_NUM_LEGACY_OFDM_STATS]; u32 rx_active_dur_us_low; u32 rx_active_dur_us_high; + + u32 rx_11ax_ul_ofdma; + + u32 ul_ofdma_rx_mcs[HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS]; + u32 ul_ofdma_rx_gi[HTT_TX_PDEV_STATS_NUM_GI_COUNTERS] + [HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS]; + u32 ul_ofdma_rx_nss[HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS]; + u32 ul_ofdma_rx_bw[HTT_TX_PDEV_STATS_NUM_BW_COUNTERS]; + u32 ul_ofdma_rx_stbc; + u32 ul_ofdma_rx_ldpc; + + /* record the stats for each user index */ + u32 rx_ulofdma_non_data_ppdu[HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; /* ppdu level */ + u32 rx_ulofdma_data_ppdu[HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; /* ppdu level */ + u32 rx_ulofdma_mpdu_ok[HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; /* mpdu level */ + u32 rx_ulofdma_mpdu_fail[HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; /* mpdu level */ + + u32 nss_count; + u32 pilot_count; + /* RxEVM stats in dB */ + s32 rx_pilot_evm_db[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS] + [HTT_RX_PDEV_STATS_RXEVM_MAX_PILOTS_PER_NSS]; + /* rx_pilot_evm_db_mean: + * EVM mean across pilots, computed as + * mean(10*log10(rx_pilot_evm_linear)) = mean(rx_pilot_evm_db) + */ + s32 rx_pilot_evm_db_mean[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS]; + s8 rx_ul_fd_rssi[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS] + [HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; /* dBm units */ + /* per_chain_rssi_pkt_type: + * This field shows what type of rx frame the per-chain RSSI was computed + * on, by recording the frame type and sub-type as bit-fields within this + * field: + * BIT [3 : 0] :- IEEE80211_FC0_TYPE + * BIT [7 : 4] :- IEEE80211_FC0_SUBTYPE + * BIT [31 : 8] :- Reserved + */ + u32 per_chain_rssi_pkt_type; + s8 rx_per_chain_rssi_in_dbm[HTT_RX_PDEV_STATS_NUM_SPATIAL_STREAMS] + [HTT_RX_PDEV_STATS_NUM_BW_COUNTERS]; }; /* == RX PDEV/SOC STATS == */ From 3b4516838eaabacc56770f12407d5f791c88838a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 11 Jan 2020 09:08:24 +0000 Subject: [PATCH 39/96] ath11k: avoid null pointer dereference when pointer band is null In the unlikely event that cap->supported_bands has neither WMI_HOST_WLAN_2G_CAP set or WMI_HOST_WLAN_5G_CAP set then pointer band is null and a null dereference occurs when assigning band->n_iftype_data. Move the assignment to the if blocks to avoid this. Cleans up static analysis warnings. Addresses-Coverity: ("Explicit null dereference") Fixes: 9f056ed8ee01 ("ath11k: add HE support") Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath11k/mac.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index f9ab02e84d13..6640662f5ede 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -3520,8 +3520,8 @@ static int ath11k_mac_copy_he_cap(struct ath11k *ar, static void ath11k_mac_setup_he_cap(struct ath11k *ar, struct ath11k_pdev_cap *cap) { - struct ieee80211_supported_band *band = NULL; - int count = 0; + struct ieee80211_supported_band *band; + int count; if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) { count = ath11k_mac_copy_he_cap(ar, cap, @@ -3529,6 +3529,7 @@ static void ath11k_mac_setup_he_cap(struct ath11k *ar, NL80211_BAND_2GHZ); band = &ar->mac.sbands[NL80211_BAND_2GHZ]; band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ]; + band->n_iftype_data = count; } if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) { @@ -3537,9 +3538,8 @@ static void ath11k_mac_setup_he_cap(struct ath11k *ar, NL80211_BAND_5GHZ); band = &ar->mac.sbands[NL80211_BAND_5GHZ]; band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ]; + band->n_iftype_data = count; } - - band->n_iftype_data = count; } static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant) From 93634c61056e34522e824d56ff77ee2332ed7f8a Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 17 Dec 2019 21:20:57 +0100 Subject: [PATCH 40/96] ath11k: make sure to also report the RX bandwidth inside radiotap Add IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN to the list of known fields. Not doing so will result in wireshark not calculating the bitrate correctly. Signed-off-by: John Crispin Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath11k/dp_rx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 3a3dc7680622..b08da839b7d9 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -2067,7 +2067,8 @@ static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *nap struct sk_buff *msdu) { static const struct ieee80211_radiotap_he known = { - .data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN), + .data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN | + IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN), .data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN), }; struct ieee80211_rx_status *status; From 7195c8747e8757daaf48d862e1314f8bcfdb3207 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 15 Jan 2020 20:46:52 +0300 Subject: [PATCH 41/96] ath11k: fix up some error paths There are two error paths where "ret" wasn't set. Also one error path we set the error code to -EINVAL but we should just preserve the error code from ath11k_hal_srng_get_entrysize(). That function only returns -EINVAL so this doesn't change anything. I removed the "ret = 0;" initializers so that hopefully GCC will be able to detect these sorts of bugs in the future. Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") Signed-off-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath11k/dp_tx.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index 04ad1a20e459..6d7d33761caf 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -630,7 +630,7 @@ int ath11k_dp_tx_htt_srng_setup(struct ath11k_base *ab, u32 ring_id, dma_addr_t hp_addr, tp_addr; enum htt_srng_ring_type htt_ring_type; enum htt_srng_ring_id htt_ring_id; - int ret = 0; + int ret; skb = ath11k_htc_alloc_skb(ab, len); if (!skb) @@ -642,9 +642,10 @@ int ath11k_dp_tx_htt_srng_setup(struct ath11k_base *ab, u32 ring_id, hp_addr = ath11k_hal_srng_get_hp_addr(ab, srng); tp_addr = ath11k_hal_srng_get_tp_addr(ab, srng); - if (ath11k_dp_tx_get_ring_id_type(ab, mac_id, ring_id, - ring_type, &htt_ring_type, - &htt_ring_id)) + ret = ath11k_dp_tx_get_ring_id_type(ab, mac_id, ring_id, + ring_type, &htt_ring_type, + &htt_ring_id); + if (ret) goto err_free; skb_put(skb, len); @@ -669,10 +670,8 @@ int ath11k_dp_tx_htt_srng_setup(struct ath11k_base *ab, u32 ring_id, HAL_ADDR_MSB_REG_SHIFT; ret = ath11k_hal_srng_get_entrysize(ring_type); - if (ret < 0) { - ret = -EINVAL; + if (ret < 0) goto err_free; - } ring_entry_sz = ret; @@ -817,7 +816,7 @@ int ath11k_dp_tx_htt_rx_filter_setup(struct ath11k_base *ab, u32 ring_id, int len = sizeof(*cmd); enum htt_srng_ring_type htt_ring_type; enum htt_srng_ring_id htt_ring_id; - int ret = 0; + int ret; skb = ath11k_htc_alloc_skb(ab, len); if (!skb) @@ -826,9 +825,10 @@ int ath11k_dp_tx_htt_rx_filter_setup(struct ath11k_base *ab, u32 ring_id, memset(¶ms, 0, sizeof(params)); ath11k_hal_srng_get_params(ab, srng, ¶ms); - if (ath11k_dp_tx_get_ring_id_type(ab, mac_id, ring_id, - ring_type, &htt_ring_type, - &htt_ring_id)) + ret = ath11k_dp_tx_get_ring_id_type(ab, mac_id, ring_id, + ring_type, &htt_ring_type, + &htt_ring_id); + if (ret) goto err_free; skb_put(skb, len); From 70e5b8f445fd27fde0c5583460e82539a7242424 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 6 Dec 2019 11:45:35 -0800 Subject: [PATCH 42/96] mwifiex: drop most magic numbers from mwifiex_process_tdls_action_frame() Before commit 1e58252e334d ("mwifiex: Fix heap overflow in mmwifiex_process_tdls_action_frame()"), mwifiex_process_tdls_action_frame() already had too many magic numbers. But this commit just added a ton more, in the name of checking for buffer overflows. That seems like a really bad idea. Let's make these magic numbers a little less magic, by (a) factoring out 'pos[1]' as 'ie_len' (b) using 'sizeof' on the appropriate source or destination fields where possible, instead of bare numbers (c) dropping redundant checks, per below. Regarding redundant checks: the beginning of the loop has this: if (pos + 2 + pos[1] > end) break; but then individual 'case's include stuff like this: if (pos > end - 3) return; if (pos[1] != 1) return; Note that the second 'return' (validating the length, pos[1]) combined with the above condition (ensuring 'pos + 2 + length' doesn't exceed 'end'), makes the first 'return' (whose 'if' can be reworded as 'pos > end - pos[1] - 2') redundant. Rather than unwind the magic numbers there, just drop those conditions. Fixes: 1e58252e334d ("mwifiex: Fix heap overflow in mmwifiex_process_tdls_action_frame()") Signed-off-by: Brian Norris Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/tdls.c | 75 ++++++++------------- 1 file changed, 28 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c index 7caf1d26124a..f8f282ce39bd 100644 --- a/drivers/net/wireless/marvell/mwifiex/tdls.c +++ b/drivers/net/wireless/marvell/mwifiex/tdls.c @@ -894,7 +894,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, u8 *peer, *pos, *end; u8 i, action, basic; u16 cap = 0; - int ie_len = 0; + int ies_len = 0; if (len < (sizeof(struct ethhdr) + 3)) return; @@ -916,7 +916,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, pos = buf + sizeof(struct ethhdr) + 4; /* payload 1+ category 1 + action 1 + dialog 1 */ cap = get_unaligned_le16(pos); - ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN; + ies_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN; pos += 2; break; @@ -926,7 +926,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/ pos = buf + sizeof(struct ethhdr) + 6; cap = get_unaligned_le16(pos); - ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN; + ies_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN; pos += 2; break; @@ -934,7 +934,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN)) return; pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN; - ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN; + ies_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN; break; default: mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS frame type.\n"); @@ -947,33 +947,33 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, sta_ptr->tdls_cap.capab = cpu_to_le16(cap); - for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) { - if (pos + 2 + pos[1] > end) + for (end = pos + ies_len; pos + 1 < end; pos += 2 + pos[1]) { + u8 ie_len = pos[1]; + + if (pos + 2 + ie_len > end) break; switch (*pos) { case WLAN_EID_SUPP_RATES: - if (pos[1] > 32) + if (ie_len > sizeof(sta_ptr->tdls_cap.rates)) return; - sta_ptr->tdls_cap.rates_len = pos[1]; - for (i = 0; i < pos[1]; i++) + sta_ptr->tdls_cap.rates_len = ie_len; + for (i = 0; i < ie_len; i++) sta_ptr->tdls_cap.rates[i] = pos[i + 2]; break; case WLAN_EID_EXT_SUPP_RATES: - if (pos[1] > 32) + if (ie_len > sizeof(sta_ptr->tdls_cap.rates)) return; basic = sta_ptr->tdls_cap.rates_len; - if (pos[1] > 32 - basic) + if (ie_len > sizeof(sta_ptr->tdls_cap.rates) - basic) return; - for (i = 0; i < pos[1]; i++) + for (i = 0; i < ie_len; i++) sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2]; - sta_ptr->tdls_cap.rates_len += pos[1]; + sta_ptr->tdls_cap.rates_len += ie_len; break; case WLAN_EID_HT_CAPABILITY: - if (pos > end - sizeof(struct ieee80211_ht_cap) - 2) - return; - if (pos[1] != sizeof(struct ieee80211_ht_cap)) + if (ie_len != sizeof(struct ieee80211_ht_cap)) return; /* copy the ie's value into ht_capb*/ memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos + 2, @@ -981,59 +981,45 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, sta_ptr->is_11n_enabled = 1; break; case WLAN_EID_HT_OPERATION: - if (pos > end - - sizeof(struct ieee80211_ht_operation) - 2) - return; - if (pos[1] != sizeof(struct ieee80211_ht_operation)) + if (ie_len != sizeof(struct ieee80211_ht_operation)) return; /* copy the ie's value into ht_oper*/ memcpy(&sta_ptr->tdls_cap.ht_oper, pos + 2, sizeof(struct ieee80211_ht_operation)); break; case WLAN_EID_BSS_COEX_2040: - if (pos > end - 3) - return; - if (pos[1] != 1) + if (ie_len != sizeof(pos[2])) return; sta_ptr->tdls_cap.coex_2040 = pos[2]; break; case WLAN_EID_EXT_CAPABILITY: - if (pos > end - sizeof(struct ieee_types_header)) + if (ie_len < sizeof(struct ieee_types_header)) return; - if (pos[1] < sizeof(struct ieee_types_header)) - return; - if (pos[1] > 8) + if (ie_len > 8) return; memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos, sizeof(struct ieee_types_header) + - min_t(u8, pos[1], 8)); + min_t(u8, ie_len, 8)); break; case WLAN_EID_RSN: - if (pos > end - sizeof(struct ieee_types_header)) + if (ie_len < sizeof(struct ieee_types_header)) return; - if (pos[1] < sizeof(struct ieee_types_header)) - return; - if (pos[1] > IEEE_MAX_IE_SIZE - + if (ie_len > IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_header)) return; memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos, sizeof(struct ieee_types_header) + - min_t(u8, pos[1], IEEE_MAX_IE_SIZE - + min_t(u8, ie_len, IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_header))); break; case WLAN_EID_QOS_CAPA: - if (pos > end - 3) - return; - if (pos[1] != 1) + if (ie_len != sizeof(pos[2])) return; sta_ptr->tdls_cap.qos_info = pos[2]; break; case WLAN_EID_VHT_OPERATION: if (priv->adapter->is_hw_11ac_capable) { - if (pos > end - - sizeof(struct ieee80211_vht_operation) - 2) - return; - if (pos[1] != + if (ie_len != sizeof(struct ieee80211_vht_operation)) return; /* copy the ie's value into vhtoper*/ @@ -1043,10 +1029,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, break; case WLAN_EID_VHT_CAPABILITY: if (priv->adapter->is_hw_11ac_capable) { - if (pos > end - - sizeof(struct ieee80211_vht_cap) - 2) - return; - if (pos[1] != sizeof(struct ieee80211_vht_cap)) + if (ie_len != sizeof(struct ieee80211_vht_cap)) return; /* copy the ie's value into vhtcap*/ memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos + 2, @@ -1056,9 +1039,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, break; case WLAN_EID_AID: if (priv->adapter->is_hw_11ac_capable) { - if (pos > end - 4) - return; - if (pos[1] != 2) + if (ie_len != sizeof(u16)) return; sta_ptr->tdls_cap.aid = get_unaligned_le16((pos + 2)); From d04bf42891a7ea43d15384262ae6ddd8e0461642 Mon Sep 17 00:00:00 2001 From: Ganapathi Bhat Date: Mon, 13 Jan 2020 10:42:46 +0000 Subject: [PATCH 43/96] MAINTAINERS: update for mwifiex driver maintainers Remove Nishant Sarmukadam from Maintainer list, as he is no longer working in NXP. Signed-off-by: Ganapathi Bhat Signed-off-by: Kalle Valo --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 2549f10eb0b1..c2979c6893c5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9960,7 +9960,6 @@ F: drivers/net/ethernet/marvell/mvneta.* MARVELL MWIFIEX WIRELESS DRIVER M: Amitkumar Karwar -M: Nishant Sarmukadam M: Ganapathi Bhat M: Xinming Hu L: linux-wireless@vger.kernel.org From 6ba8b3b6bd772f575f7736c8fd893c6981fcce16 Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Tue, 21 Jan 2020 12:42:28 +0530 Subject: [PATCH 44/96] ath10k: Correct the DMA direction for management tx buffers The management packets, send to firmware via WMI, are mapped using the direction DMA_TO_DEVICE. Currently in case of wmi cleanup, these buffers are being unmapped using an incorrect DMA direction. This can cause unwanted behavior when the host driver is handling a restart of the wlan firmware. We might see a trace like below [] __dma_inv_area+0x28/0x58 [] ath10k_wmi_mgmt_tx_clean_up_pending+0x60/0xb0 [ath10k_core] [] idr_for_each+0x78/0xe4 [] ath10k_wmi_detach+0x4c/0x7c [ath10k_core] [] ath10k_core_stop+0x58/0x68 [ath10k_core] [] ath10k_halt+0xec/0x13c [ath10k_core] [] ath10k_core_restart+0x11c/0x1a8 [ath10k_core] [] process_one_work+0x16c/0x31c Fix the incorrect DMA direction during the wmi management tx buffer cleanup. Tested HW: WCN3990 Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1 Fixes: dc405152bb6 ("ath10k: handle mgmt tx completion event") Signed-off-by: Rakesh Pillai Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 13f7531d945d..61885d4d662c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -9490,7 +9490,7 @@ static int ath10k_wmi_mgmt_tx_clean_up_pending(int msdu_id, void *ptr, msdu = pkt_addr->vaddr; dma_unmap_single(ar->dev, pkt_addr->paddr, - msdu->len, DMA_FROM_DEVICE); + msdu->len, DMA_TO_DEVICE); ieee80211_free_txskb(ar->hw, msdu); return 0; From 79a4b788451dd5afd4ef62d5ff9bcde219ce5286 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 23 Jan 2020 15:24:56 -0800 Subject: [PATCH 45/96] ath10k: Add newlines to printk messages Some printks in here don't have newlines at the end, meaning the log will be sort of hard to read. Add newlines. Signed-off-by: Stephen Boyd Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/snoc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index aeb4cca92c35..2189a0d01f5a 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -582,7 +582,7 @@ static void ath10k_snoc_process_rx_cb(struct ath10k_ce_pipe *ce_state, max_nbytes, DMA_FROM_DEVICE); if (unlikely(max_nbytes < nbytes)) { - ath10k_warn(ar, "rxed more than expected (nbytes %d, max %d)", + ath10k_warn(ar, "rxed more than expected (nbytes %d, max %d)\n", nbytes, max_nbytes); dev_kfree_skb_any(skb); continue; @@ -1201,7 +1201,7 @@ static int ath10k_snoc_request_irq(struct ath10k *ar) irqflags, ce_name[id], ar); if (ret) { ath10k_err(ar, - "failed to register IRQ handler for CE %d: %d", + "failed to register IRQ handler for CE %d: %d\n", id, ret); goto err_irq; } @@ -1485,7 +1485,7 @@ static int ath10k_snoc_probe(struct platform_device *pdev) ret = dma_set_mask_and_coherent(dev, drv_data->dma_mask); if (ret) { - dev_err(dev, "failed to set dma mask: %d", ret); + dev_err(dev, "failed to set dma mask: %d\n", ret); return ret; } From fa43e99dd4b76201eb323ee3918c68132e8abba9 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 23 Jan 2020 15:29:44 -0800 Subject: [PATCH 46/96] ath10k: Use device_get_match_data() to simplify code Use device_get_match_data() here to simplify the code a bit. Signed-off-by: Stephen Boyd Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/snoc.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 2189a0d01f5a..21081b4a27d7 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -1466,7 +1466,6 @@ MODULE_DEVICE_TABLE(of, ath10k_snoc_dt_match); static int ath10k_snoc_probe(struct platform_device *pdev) { const struct ath10k_snoc_drv_priv *drv_data; - const struct of_device_id *of_id; struct ath10k_snoc *ar_snoc; struct device *dev; struct ath10k *ar; @@ -1474,15 +1473,13 @@ static int ath10k_snoc_probe(struct platform_device *pdev) int ret; u32 i; - of_id = of_match_device(ath10k_snoc_dt_match, &pdev->dev); - if (!of_id) { - dev_err(&pdev->dev, "failed to find matching device tree id\n"); + dev = &pdev->dev; + drv_data = device_get_match_data(dev); + if (!drv_data) { + dev_err(dev, "failed to find matching device tree id\n"); return -EINVAL; } - drv_data = of_id->data; - dev = &pdev->dev; - ret = dma_set_mask_and_coherent(dev, drv_data->dma_mask); if (ret) { dev_err(dev, "failed to set dma mask: %d\n", ret); From 5b362498a79631f283578b64bf6f4d15ed4cc19a Mon Sep 17 00:00:00 2001 From: Mert Dirik Date: Thu, 16 Jan 2020 14:11:25 +0300 Subject: [PATCH 47/96] ar5523: Add USB ID of SMCWUSBT-G2 wireless adapter Add the required USB ID for running SMCWUSBT-G2 wireless adapter (SMC "EZ Connect g"). This device uses ar5523 chipset and requires firmware to be loaded. Even though pid of the device is 4507, this patch adds it as 4506 so that AR5523_DEVICE_UG macro can set the AR5523_FLAG_PRE_FIRMWARE flag for pid 4507. Signed-off-by: Mert Dirik Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ar5523/ar5523.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c index da2d179430ca..4c57e79e5779 100644 --- a/drivers/net/wireless/ath/ar5523/ar5523.c +++ b/drivers/net/wireless/ath/ar5523/ar5523.c @@ -1770,6 +1770,8 @@ static const struct usb_device_id ar5523_id_table[] = { AR5523_DEVICE_UX(0x0846, 0x4300), /* Netgear / WG111U */ AR5523_DEVICE_UG(0x0846, 0x4250), /* Netgear / WG111T */ AR5523_DEVICE_UG(0x0846, 0x5f00), /* Netgear / WPN111 */ + AR5523_DEVICE_UG(0x083a, 0x4506), /* SMC / EZ Connect + SMCWUSBT-G2 */ AR5523_DEVICE_UG(0x157e, 0x3006), /* Umedia / AR5523_1 */ AR5523_DEVICE_UX(0x157e, 0x3205), /* Umedia / AR5523_2 */ AR5523_DEVICE_UG(0x157e, 0x3006), /* Umedia / TEW444UBEU */ From d92e8fa8ce882107e3f5be1244ff77ea1a74e63e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 23 Jan 2020 00:18:01 +0000 Subject: [PATCH 48/96] ar5523: fix spelling mistake "to" -> "too" There is a spelling mistake in a ar5523_err message. Fix it. Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ar5523/ar5523.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c index 4c57e79e5779..49cc4b7ed516 100644 --- a/drivers/net/wireless/ath/ar5523/ar5523.c +++ b/drivers/net/wireless/ath/ar5523/ar5523.c @@ -74,7 +74,7 @@ static void ar5523_read_reply(struct ar5523 *ar, struct ar5523_cmd_hdr *hdr, if (cmd->odata) { if (cmd->olen < olen) { - ar5523_err(ar, "olen to small %d < %d\n", + ar5523_err(ar, "olen too small %d < %d\n", cmd->olen, olen); cmd->olen = 0; cmd->res = -EOVERFLOW; From d7809bd9eae67b4252cbc4672431610227cbb729 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 23 Jan 2020 00:51:17 +0000 Subject: [PATCH 49/96] wcn36xx: fix spelling mistake "to" -> "too" There is a spelling mistake in a wcn36xx_err message. Fix it. Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/smd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 523550f94a3f..77269ac7f352 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -1620,7 +1620,7 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, 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", + wcn36xx_err("Beacon is too big: beacon size=%d\n", msg_body.beacon_length); ret = -ENOMEM; goto out; From cf33a7728bf27e6f8c5e9190410db85c11103699 Mon Sep 17 00:00:00 2001 From: Maital Hahn Date: Thu, 16 Jan 2020 08:33:53 -0600 Subject: [PATCH 50/96] wlcore: mesh: Add support for RX Broadcast Key In order to support authentication of equals peers, need to save RX Broadcast key per peer (on top of 1 TX broadcast key and unicast key per peer). Signed-off-by: Maital Hahn Acked-by: Guy Mishol Signed-off-by: Hari Nagalla Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wlcore/cmd.c | 6 ++++-- drivers/net/wireless/ti/wlcore/cmd.h | 2 +- drivers/net/wireless/ti/wlcore/main.c | 23 +++++++++++++++-------- drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 + 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 2a48fc6ad56c..6ef8fc9ae627 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -1429,7 +1429,7 @@ out: int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, - u16 tx_seq_16) + u16 tx_seq_16, bool is_pairwise) { struct wl1271_cmd_set_keys *cmd; int ret = 0; @@ -1444,8 +1444,10 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, lid_type = WEP_DEFAULT_LID_TYPE; else lid_type = BROADCAST_LID_TYPE; - } else { + } else if (is_pairwise) { lid_type = UNICAST_LID_TYPE; + } else { + lid_type = BROADCAST_LID_TYPE; } wl1271_debug(DEBUG_CRYPT, "ap key action: %d id: %d lid: %d type: %d" diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index 084375ba4abf..bfad7b5a1ac6 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h @@ -65,7 +65,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, - u16 tx_seq_16); + u16 tx_seq_16, bool is_pairwise); int wl12xx_cmd_set_peer_state(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id, diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index e994995d79ab..ed049c9f7e29 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -3273,7 +3273,7 @@ out: static int wl1271_record_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 id, u8 key_type, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, - u16 tx_seq_16) + u16 tx_seq_16, bool is_pairwise) { struct wl1271_ap_key *ap_key; int i; @@ -3311,6 +3311,7 @@ static int wl1271_record_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, ap_key->hlid = hlid; ap_key->tx_seq_32 = tx_seq_32; ap_key->tx_seq_16 = tx_seq_16; + ap_key->is_pairwise = is_pairwise; wlvif->ap.recorded_keys[i] = ap_key; return 0; @@ -3346,7 +3347,7 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl, struct wl12xx_vif *wlvif) key->id, key->key_type, key->key_size, key->key, hlid, key->tx_seq_32, - key->tx_seq_16); + key->tx_seq_16, key->is_pairwise); if (ret < 0) goto out; @@ -3369,7 +3370,8 @@ out: static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, u32 tx_seq_32, - u16 tx_seq_16, struct ieee80211_sta *sta) + u16 tx_seq_16, struct ieee80211_sta *sta, + bool is_pairwise) { int ret; bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); @@ -3396,12 +3398,12 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, ret = wl1271_record_ap_key(wl, wlvif, id, key_type, key_size, key, hlid, tx_seq_32, - tx_seq_16); + tx_seq_16, is_pairwise); } else { ret = wl1271_cmd_set_ap_key(wl, wlvif, action, id, key_type, key_size, key, hlid, tx_seq_32, - tx_seq_16); + tx_seq_16, is_pairwise); } if (ret < 0) @@ -3501,6 +3503,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, u16 tx_seq_16 = 0; u8 key_type; u8 hlid; + bool is_pairwise; wl1271_debug(DEBUG_MAC80211, "mac80211 set key"); @@ -3550,12 +3553,14 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, return -EOPNOTSUPP; } + is_pairwise = key_conf->flags & IEEE80211_KEY_FLAG_PAIRWISE; + switch (cmd) { case SET_KEY: ret = wl1271_set_key(wl, wlvif, KEY_ADD_OR_REPLACE, key_conf->keyidx, key_type, key_conf->keylen, key_conf->key, - tx_seq_32, tx_seq_16, sta); + tx_seq_32, tx_seq_16, sta, is_pairwise); if (ret < 0) { wl1271_error("Could not add or replace key"); return ret; @@ -3581,7 +3586,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, ret = wl1271_set_key(wl, wlvif, KEY_REMOVE, key_conf->keyidx, key_type, key_conf->keylen, key_conf->key, - 0, 0, sta); + 0, 0, sta, is_pairwise); if (ret < 0) { wl1271_error("Could not remove key"); return ret; @@ -6223,6 +6228,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) ieee80211_hw_set(wl->hw, SUPPORT_FAST_XMIT); ieee80211_hw_set(wl->hw, CHANCTX_STA_CSA); + ieee80211_hw_set(wl->hw, SUPPORTS_PER_STA_GTK); ieee80211_hw_set(wl->hw, QUEUE_CONTROL); ieee80211_hw_set(wl->hw, TX_AMPDU_SETUP_IN_HW); ieee80211_hw_set(wl->hw, AMPDU_AGGREGATION); @@ -6267,7 +6273,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | - WIPHY_FLAG_HAS_CHANNEL_SWITCH; + WIPHY_FLAG_HAS_CHANNEL_SWITCH | ++ WIPHY_FLAG_IBSS_RSN; wl->hw->wiphy->features |= NL80211_FEATURE_AP_SCAN; diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index 6fab60b0e367..eefae3f867b9 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h @@ -212,6 +212,7 @@ struct wl1271_ap_key { u8 hlid; u32 tx_seq_32; u16 tx_seq_16; + bool is_pairwise; }; enum wl12xx_flags { From b61156fba74f659d0bc2de8f2dbf5bad9f4b8faf Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Tue, 17 Dec 2019 18:15:46 -0700 Subject: [PATCH 51/96] hostap: Adjust indentation in prism2_hostapd_add_sta Clang warns: ../drivers/net/wireless/intersil/hostap/hostap_ap.c:2511:3: warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation] if (sta->tx_supp_rates & WLAN_RATE_5M5) ^ ../drivers/net/wireless/intersil/hostap/hostap_ap.c:2509:2: note: previous statement is here if (sta->tx_supp_rates & WLAN_RATE_2M) ^ 1 warning generated. This warning occurs because there is a space before the tab on this line. Remove it so that the indentation is consistent with the Linux kernel coding style and clang no longer warns. Fixes: ff1d2767d5a4 ("Add HostAP wireless driver.") Link: https://github.com/ClangBuiltLinux/linux/issues/813 Signed-off-by: Nathan Chancellor Reviewed-by: Nick Desaulniers Signed-off-by: Kalle Valo --- drivers/net/wireless/intersil/hostap/hostap_ap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intersil/hostap/hostap_ap.c b/drivers/net/wireless/intersil/hostap/hostap_ap.c index 0094b1d2b577..3ec46f48cfde 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_ap.c +++ b/drivers/net/wireless/intersil/hostap/hostap_ap.c @@ -2508,7 +2508,7 @@ static int prism2_hostapd_add_sta(struct ap_data *ap, sta->supported_rates[0] = 2; if (sta->tx_supp_rates & WLAN_RATE_2M) sta->supported_rates[1] = 4; - if (sta->tx_supp_rates & WLAN_RATE_5M5) + if (sta->tx_supp_rates & WLAN_RATE_5M5) sta->supported_rates[2] = 11; if (sta->tx_supp_rates & WLAN_RATE_11M) sta->supported_rates[3] = 22; From 25cab7e71da32d46651f5fc9373eef9b79938629 Mon Sep 17 00:00:00 2001 From: Chin-Yen Lee Date: Thu, 19 Dec 2019 16:58:10 +0800 Subject: [PATCH 52/96] rtw88: pci: reset ring index when release skbs in tx ring When skbs queued for each TX ring are relased in PCI stop flow, the ring index should be reset at the same time. Signed-off-by: Chin-Yen Lee Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index a58e8276a41a..068f1bec88e6 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -506,6 +506,7 @@ static void rtw_pci_dma_release(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci) struct rtw_pci_tx_ring *tx_ring; u8 queue; + rtw_pci_reset_trx_ring(rtwdev); for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++) { tx_ring = &rtwpci->tx_rings[queue]; rtw_pci_free_tx_ring_skbs(rtwdev, tx_ring); From fd30e891e0bc68735b52d480d078959e5fb30e70 Mon Sep 17 00:00:00 2001 From: Chin-Yen Lee Date: Thu, 19 Dec 2019 16:58:11 +0800 Subject: [PATCH 53/96] rtw88: pci: reset dma when reset pci trx ring When PCI trx rings are reset, the DMA engine should also be reset. Otherswise, the rx_tag of rx flow is not synchronous to hw. Remove DMA reset when rtw_pci_start() as we added it in rtw_pci_setup(). Signed-off-by: Chin-Yen Lee Signed-off-by: Yan-Hsuan Chuang Reviewed-by: Chris Chiu Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/pci.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 068f1bec88e6..c394df494c95 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -486,13 +486,6 @@ static void rtw_pci_disable_interrupt(struct rtw_dev *rtwdev, rtwpci->irq_enabled = false; } -static int rtw_pci_setup(struct rtw_dev *rtwdev) -{ - rtw_pci_reset_trx_ring(rtwdev); - - return 0; -} - static void rtw_pci_dma_reset(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci) { /* reset dma and rx tag */ @@ -501,6 +494,16 @@ static void rtw_pci_dma_reset(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci) rtwpci->rx_tag = 0; } +static int rtw_pci_setup(struct rtw_dev *rtwdev) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + + rtw_pci_reset_trx_ring(rtwdev); + rtw_pci_dma_reset(rtwdev, rtwpci); + + return 0; +} + static void rtw_pci_dma_release(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci) { struct rtw_pci_tx_ring *tx_ring; @@ -518,8 +521,6 @@ static int rtw_pci_start(struct rtw_dev *rtwdev) struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; unsigned long flags; - rtw_pci_dma_reset(rtwdev, rtwpci); - spin_lock_irqsave(&rtwpci->irq_lock, flags); rtw_pci_enable_interrupt(rtwdev, rtwpci); spin_unlock_irqrestore(&rtwpci->irq_lock, flags); From 786221048e8f74bafb87b4ba8b613cd5bc0ea159 Mon Sep 17 00:00:00 2001 From: Yan-Hsuan Chuang Date: Thu, 19 Dec 2019 16:58:12 +0800 Subject: [PATCH 54/96] rtw88: add interface config for 8822c Some devices need to configure interface/HCI related reigsters in power on flow. Add interface_cfg for HCI for the settings. The driver only supports RTL8822BE/RTL8822CE now, and since RTL8822BE does not need to configure PCIE, the configuration is only added for RTL8822CE. Without it, some of the RTL8822CE device can crash and disconnected to host in suspend/wowlan mode. Signed-off-by: Tzu-En Huang Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/hci.h | 6 ++++++ drivers/net/wireless/realtek/rtw88/mac.c | 2 ++ drivers/net/wireless/realtek/rtw88/pci.c | 17 +++++++++++++++++ drivers/net/wireless/realtek/rtw88/reg.h | 2 ++ 4 files changed, 27 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/hci.h b/drivers/net/wireless/realtek/rtw88/hci.h index 3d91aea942c3..85a81a578fd5 100644 --- a/drivers/net/wireless/realtek/rtw88/hci.h +++ b/drivers/net/wireless/realtek/rtw88/hci.h @@ -15,6 +15,7 @@ struct rtw_hci_ops { void (*stop)(struct rtw_dev *rtwdev); void (*deep_ps)(struct rtw_dev *rtwdev, bool enter); void (*link_ps)(struct rtw_dev *rtwdev, bool enter); + void (*interface_cfg)(struct rtw_dev *rtwdev); int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size); int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size); @@ -59,6 +60,11 @@ static inline void rtw_hci_link_ps(struct rtw_dev *rtwdev, bool enter) rtwdev->hci.ops->link_ps(rtwdev, enter); } +static inline void rtw_hci_interface_cfg(struct rtw_dev *rtwdev) +{ + rtwdev->hci.ops->interface_cfg(rtwdev); +} + static inline int rtw_hci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size) { diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index 507970387b2a..03a82de053ea 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -1034,5 +1034,7 @@ int rtw_mac_init(struct rtw_dev *rtwdev) if (ret) return ret; + rtw_hci_interface_cfg(rtwdev); + return 0; } diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index c394df494c95..a60d9b107006 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -6,6 +6,7 @@ #include #include "main.h" #include "pci.h" +#include "reg.h" #include "tx.h" #include "rx.h" #include "fw.h" @@ -1224,6 +1225,21 @@ static void rtw_pci_link_cfg(struct rtw_dev *rtwdev) rtwpci->link_ctrl = link_ctrl; } +static void rtw_pci_interface_cfg(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + switch (chip->id) { + case RTW_CHIP_TYPE_8822C: + if (rtwdev->hal.cut_version >= RTW_CHIP_VER_CUT_D) + rtw_write32_mask(rtwdev, REG_HCI_MIX_CFG, + BIT_PCIE_EMAC_PDN_AUX_TO_FAST_CLK, 1); + break; + default: + break; + } +} + static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev) { struct rtw_chip_info *chip = rtwdev->chip; @@ -1332,6 +1348,7 @@ static struct rtw_hci_ops rtw_pci_ops = { .stop = rtw_pci_stop, .deep_ps = rtw_pci_deep_ps, .link_ps = rtw_pci_link_ps, + .interface_cfg = rtw_pci_interface_cfg, .read8 = rtw_pci_read8, .read16 = rtw_pci_read16, diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h index 7e817bc997eb..cd6b14c379ba 100644 --- a/drivers/net/wireless/realtek/rtw88/reg.h +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -194,6 +194,8 @@ #define REG_H2C_INFO 0x0254 #define REG_INT_MIG 0x0304 +#define REG_HCI_MIX_CFG 0x03FC +#define BIT_PCIE_EMAC_PDN_AUX_TO_FAST_CLK BIT(26) #define REG_FWHW_TXQ_CTRL 0x0420 #define BIT_EN_BCNQ_DL BIT(22) From c8e5695eae9959fc5774c0f490f2450be8bad3de Mon Sep 17 00:00:00 2001 From: Chin-Yen Lee Date: Thu, 19 Dec 2019 16:58:13 +0800 Subject: [PATCH 55/96] rtw88: load wowlan firmware if wowlan is supported Driver used to download normal firmware only, but some devices support wowlan and require to download wowlan firmware when system suspends. So modify rtw_load_firmware() and its callback to allow driver to download both normal and wowlan firmware. Signed-off-by: Chin-Yen Lee Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/main.c | 72 +++++++++++++++++++---- drivers/net/wireless/realtek/rtw88/main.h | 10 ++++ 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index ae61415e1665..54e8a0cef14b 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -793,6 +793,26 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) rtw_fw_send_ra_info(rtwdev, si); } +static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_fw_state *fw; + + fw = &rtwdev->fw; + wait_for_completion(&fw->completion); + if (!fw->firmware) + return -EINVAL; + + if (chip->wow_fw_name) { + fw = &rtwdev->wow_fw; + wait_for_completion(&fw->completion); + if (!fw->firmware) + return -EINVAL; + } + + return 0; +} + static int rtw_power_on(struct rtw_dev *rtwdev) { struct rtw_chip_info *chip = rtwdev->chip; @@ -813,11 +833,10 @@ static int rtw_power_on(struct rtw_dev *rtwdev) goto err; } - wait_for_completion(&fw->completion); - if (!fw->firmware) { - ret = -EINVAL; - rtw_err(rtwdev, "failed to load firmware\n"); - goto err; + ret = rtw_wait_firmware_completion(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to wait firmware completion\n"); + goto err_off; } ret = rtw_download_firmware(rtwdev, fw); @@ -1020,8 +1039,8 @@ static void rtw_unset_supported_band(struct ieee80211_hw *hw, static void rtw_load_firmware_cb(const struct firmware *firmware, void *context) { - struct rtw_dev *rtwdev = context; - struct rtw_fw_state *fw = &rtwdev->fw; + struct rtw_fw_state *fw = context; + struct rtw_dev *rtwdev = fw->rtwdev; const struct rtw_fw_hdr *fw_hdr; if (!firmware || !firmware->data) { @@ -1043,17 +1062,35 @@ static void rtw_load_firmware_cb(const struct firmware *firmware, void *context) fw->version, fw->sub_version, fw->sub_index, fw->h2c_version); } -static int rtw_load_firmware(struct rtw_dev *rtwdev, const char *fw_name) +static int rtw_load_firmware(struct rtw_dev *rtwdev, enum rtw_fw_type type) { - struct rtw_fw_state *fw = &rtwdev->fw; + const char *fw_name; + struct rtw_fw_state *fw; int ret; + switch (type) { + case RTW_WOWLAN_FW: + fw = &rtwdev->wow_fw; + fw_name = rtwdev->chip->wow_fw_name; + break; + + case RTW_NORMAL_FW: + fw = &rtwdev->fw; + fw_name = rtwdev->chip->fw_name; + break; + + default: + rtw_warn(rtwdev, "unsupported firmware type\n"); + return -ENOENT; + } + + fw->rtwdev = rtwdev; init_completion(&fw->completion); ret = request_firmware_nowait(THIS_MODULE, true, fw_name, rtwdev->dev, - GFP_KERNEL, rtwdev, rtw_load_firmware_cb); + GFP_KERNEL, fw, rtw_load_firmware_cb); if (ret) { - rtw_err(rtwdev, "async firmware request failed\n"); + rtw_err(rtwdev, "failed to async firmware request\n"); return ret; } @@ -1372,12 +1409,19 @@ int rtw_core_init(struct rtw_dev *rtwdev) BIT_HTC_LOC_CTRL | BIT_APP_PHYSTS | BIT_AB | BIT_AM | BIT_APM; - ret = rtw_load_firmware(rtwdev, rtwdev->chip->fw_name); + ret = rtw_load_firmware(rtwdev, RTW_NORMAL_FW); if (ret) { rtw_warn(rtwdev, "no firmware loaded\n"); return ret; } + if (chip->wow_fw_name) { + ret = rtw_load_firmware(rtwdev, RTW_WOWLAN_FW); + if (ret) { + rtw_warn(rtwdev, "no wow firmware loaded\n"); + return ret; + } + } return 0; } EXPORT_SYMBOL(rtw_core_init); @@ -1385,12 +1429,16 @@ EXPORT_SYMBOL(rtw_core_init); void rtw_core_deinit(struct rtw_dev *rtwdev) { struct rtw_fw_state *fw = &rtwdev->fw; + struct rtw_fw_state *wow_fw = &rtwdev->wow_fw; struct rtw_rsvd_page *rsvd_pkt, *tmp; unsigned long flags; if (fw->firmware) release_firmware(fw->firmware); + if (wow_fw->firmware) + release_firmware(wow_fw->firmware); + tasklet_kill(&rtwdev->tx_tasklet); spin_lock_irqsave(&rtwdev->tx_report.q_lock, flags); skb_queue_purge(&rtwdev->tx_report.queue); diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index d012eefcd0da..b7690666fd57 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -193,6 +193,11 @@ enum rtw_rx_queue_type { RTK_MAX_RX_QUEUE_NUM }; +enum rtw_fw_type { + RTW_NORMAL_FW = 0x0, + RTW_WOWLAN_FW = 0x1, +}; + enum rtw_rate_index { RTW_RATEID_BGN_40M_2SS = 0, RTW_RATEID_BGN_40M_1SS = 1, @@ -1030,6 +1035,8 @@ struct rtw_chip_info { u8 bfer_su_max_num; u8 bfer_mu_max_num; + const char *wow_fw_name; + /* coex paras */ u32 coex_para_ver; u8 bt_desired_ver; @@ -1456,6 +1463,7 @@ struct rtw_fifo_conf { struct rtw_fw_state { const struct firmware *firmware; + struct rtw_dev *rtwdev; struct completion completion; u16 version; u8 sub_version; @@ -1580,6 +1588,8 @@ struct rtw_dev { u8 mp_mode; + struct rtw_fw_state wow_fw; + /* hci related data, must be last */ u8 priv[0] __aligned(sizeof(void *)); }; From 44bc17f7f5b3b2cc4084eba6307ba750078a8a73 Mon Sep 17 00:00:00 2001 From: Chin-Yen Lee Date: Thu, 19 Dec 2019 16:58:14 +0800 Subject: [PATCH 56/96] rtw88: support wowlan feature for 8822c Wake on WLAN(wowlan) is a feature which allows devices to be woken up from suspend state through wlan events. When user enables wowlan feature and then let the device enter suspend state, wowlan firmware will be loaded by the driver and periodically monitors wifi packets. Power consumption of wifi chip will be reduced in this state. If wowlan firmware detects that specific wlan event happens, it will issue wakeup signal to trigger resume process. Driver will load normal firmware and let wifi chip return to the original state. Currently supported wlan events include receiving magic packet, rekey packet and deauth packet, and disconnecting from AP. Signed-off-by: Chin-Yen Lee Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/Makefile | 1 + drivers/net/wireless/realtek/rtw88/debug.h | 1 + drivers/net/wireless/realtek/rtw88/fw.c | 86 +++ drivers/net/wireless/realtek/rtw88/fw.h | 69 +++ drivers/net/wireless/realtek/rtw88/mac80211.c | 44 ++ drivers/net/wireless/realtek/rtw88/main.c | 3 + drivers/net/wireless/realtek/rtw88/main.h | 18 + drivers/net/wireless/realtek/rtw88/pci.c | 18 + drivers/net/wireless/realtek/rtw88/reg.h | 13 + drivers/net/wireless/realtek/rtw88/rtw8822c.c | 12 + drivers/net/wireless/realtek/rtw88/util.h | 2 + drivers/net/wireless/realtek/rtw88/wow.c | 531 ++++++++++++++++++ drivers/net/wireless/realtek/rtw88/wow.h | 38 ++ 13 files changed, 836 insertions(+) create mode 100644 drivers/net/wireless/realtek/rtw88/wow.c create mode 100644 drivers/net/wireless/realtek/rtw88/wow.h diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile index 15e12155a04c..cac148d13cf1 100644 --- a/drivers/net/wireless/realtek/rtw88/Makefile +++ b/drivers/net/wireless/realtek/rtw88/Makefile @@ -15,6 +15,7 @@ rtw88-y += main.o \ ps.o \ sec.o \ bf.o \ + wow.o \ regd.o rtw88-$(CONFIG_RTW88_8822BE) += rtw8822b.o rtw8822b_table.o diff --git a/drivers/net/wireless/realtek/rtw88/debug.h b/drivers/net/wireless/realtek/rtw88/debug.h index cd28f675e9cb..a0f36f29b4a6 100644 --- a/drivers/net/wireless/realtek/rtw88/debug.h +++ b/drivers/net/wireless/realtek/rtw88/debug.h @@ -18,6 +18,7 @@ enum rtw_debug_mask { RTW_DBG_DEBUGFS = 0x00000200, RTW_DBG_PS = 0x00000400, RTW_DBG_BF = 0x00000800, + RTW_DBG_WOW = 0x00001000, RTW_DBG_ALL = 0xffffffff }; diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index b8c581161f61..16ff59576154 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -10,6 +10,7 @@ #include "sec.h" #include "debug.h" #include "util.h" +#include "wow.h" static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev, struct sk_buff *skb) @@ -482,6 +483,91 @@ void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev) rtw_fw_send_h2c_command(rtwdev, h2c_pkt); } +void rtw_fw_set_keep_alive_cmd(struct rtw_dev *rtwdev, bool enable) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + struct rtw_fw_wow_keep_alive_para mode = { + .adopt = true, + .pkt_type = KEEP_ALIVE_NULL_PKT, + .period = 5, + }; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_KEEP_ALIVE); + SET_KEEP_ALIVE_ENABLE(h2c_pkt, enable); + SET_KEEP_ALIVE_ADOPT(h2c_pkt, mode.adopt); + SET_KEEP_ALIVE_PKT_TYPE(h2c_pkt, mode.pkt_type); + SET_KEEP_ALIVE_CHECK_PERIOD(h2c_pkt, mode.period); + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +void rtw_fw_set_disconnect_decision_cmd(struct rtw_dev *rtwdev, bool enable) +{ + struct rtw_wow_param *rtw_wow = &rtwdev->wow; + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + struct rtw_fw_wow_disconnect_para mode = { + .adopt = true, + .period = 30, + .retry_count = 5, + }; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_DISCONNECT_DECISION); + + if (test_bit(RTW_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags)) { + SET_DISCONNECT_DECISION_ENABLE(h2c_pkt, enable); + SET_DISCONNECT_DECISION_ADOPT(h2c_pkt, mode.adopt); + SET_DISCONNECT_DECISION_CHECK_PERIOD(h2c_pkt, mode.period); + SET_DISCONNECT_DECISION_TRY_PKT_NUM(h2c_pkt, mode.retry_count); + } + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +void rtw_fw_set_wowlan_ctrl_cmd(struct rtw_dev *rtwdev, bool enable) +{ + struct rtw_wow_param *rtw_wow = &rtwdev->wow; + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_WOWLAN); + + SET_WOWLAN_FUNC_ENABLE(h2c_pkt, enable); + if (rtw_wow_mgd_linked(rtwdev)) { + if (test_bit(RTW_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags)) + SET_WOWLAN_MAGIC_PKT_ENABLE(h2c_pkt, enable); + if (test_bit(RTW_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags)) + SET_WOWLAN_DEAUTH_WAKEUP_ENABLE(h2c_pkt, enable); + if (test_bit(RTW_WOW_FLAG_EN_REKEY_PKT, rtw_wow->flags)) + SET_WOWLAN_REKEY_WAKEUP_ENABLE(h2c_pkt, enable); + } + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +void rtw_fw_set_aoac_global_info_cmd(struct rtw_dev *rtwdev, + u8 pairwise_key_enc, + u8 group_key_enc) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_AOAC_GLOBAL_INFO); + + SET_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(h2c_pkt, pairwise_key_enc); + SET_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(h2c_pkt, group_key_enc); + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + +void rtw_fw_set_remote_wake_ctrl_cmd(struct rtw_dev *rtwdev, bool enable) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_REMOTE_WAKE_CTRL); + + SET_REMOTE_WAKECTRL_ENABLE(h2c_pkt, enable); + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + static u8 rtw_get_rsvd_page_location(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type type) { diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h index 73d1b9ca8efc..9ffc1b1ea895 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.h +++ b/drivers/net/wireless/realtek/rtw88/fw.h @@ -100,6 +100,23 @@ struct rtw_rsvd_page { bool add_txdesc; }; +enum rtw_keep_alive_pkt_type { + KEEP_ALIVE_NULL_PKT = 0, + KEEP_ALIVE_ARP_RSP = 1, +}; + +struct rtw_fw_wow_keep_alive_para { + bool adopt; + u8 pkt_type; + u8 period; /* unit: sec */ +}; + +struct rtw_fw_wow_disconnect_para { + bool adopt; + u8 period; /* unit: sec */ + u8 retry_count; +}; + struct rtw_fw_hdr { __le16 signature; u8 category; @@ -198,6 +215,11 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) #define H2C_CMD_QUERY_BT_MP_INFO 0x67 #define H2C_CMD_BT_WIFI_CONTROL 0x69 +#define H2C_CMD_KEEP_ALIVE 0x03 +#define H2C_CMD_DISCONNECT_DECISION 0x04 +#define H2C_CMD_WOWLAN 0x80 +#define H2C_CMD_REMOTE_WAKE_CTRL 0x81 +#define H2C_CMD_AOAC_GLOBAL_INFO 0x82 #define SET_H2C_CMD_ID_CLASS(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(7, 0)) @@ -301,6 +323,45 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) #define SET_BT_WIFI_CONTROL_DATA5(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16)) +#define SET_KEEP_ALIVE_ENABLE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) +#define SET_KEEP_ALIVE_ADOPT(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(9)) +#define SET_KEEP_ALIVE_PKT_TYPE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(10)) +#define SET_KEEP_ALIVE_CHECK_PERIOD(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) + +#define SET_DISCONNECT_DECISION_ENABLE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) +#define SET_DISCONNECT_DECISION_ADOPT(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(9)) +#define SET_DISCONNECT_DECISION_CHECK_PERIOD(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) +#define SET_DISCONNECT_DECISION_TRY_PKT_NUM(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24)) + +#define SET_WOWLAN_FUNC_ENABLE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) +#define SET_WOWLAN_MAGIC_PKT_ENABLE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(10)) +#define SET_WOWLAN_UNICAST_PKT_ENABLE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(11)) +#define SET_WOWLAN_REKEY_WAKEUP_ENABLE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(14)) +#define SET_WOWLAN_DEAUTH_WAKEUP_ENABLE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(15)) + +#define SET_REMOTE_WAKECTRL_ENABLE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) +#define SET_REMOTE_WAKE_CTRL_NLO_OFFLOAD_EN(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(12)) + +#define SET_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8)) +#define SET_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) + static inline struct rtw_c2h_cmd *get_c2h_from_skb(struct sk_buff *skb) { u32 pkt_offset; @@ -340,4 +401,12 @@ int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev, void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev); int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev, u32 offset, u32 size, u32 *buf); +void rtw_fw_set_remote_wake_ctrl_cmd(struct rtw_dev *rtwdev, bool enable); +void rtw_fw_set_wowlan_ctrl_cmd(struct rtw_dev *rtwdev, bool enable); +void rtw_fw_set_keep_alive_cmd(struct rtw_dev *rtwdev, bool enable); +void rtw_fw_set_disconnect_decision_cmd(struct rtw_dev *rtwdev, bool enable); +void rtw_fw_set_aoac_global_info_cmd(struct rtw_dev *rtwdev, + u8 pairwise_key_enc, + u8 group_key_enc); + #endif diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index 34a1c3b53cd4..1150e42539a9 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -12,6 +12,7 @@ #include "reg.h" #include "bf.h" #include "debug.h" +#include "wow.h" static void rtw_ops_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, @@ -735,6 +736,44 @@ static int rtw_ops_set_bitrate_mask(struct ieee80211_hw *hw, return 0; } +#ifdef CONFIG_PM +static int rtw_ops_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan) +{ + struct rtw_dev *rtwdev = hw->priv; + int ret; + + mutex_lock(&rtwdev->mutex); + ret = rtw_wow_suspend(rtwdev, wowlan); + if (ret) + rtw_err(rtwdev, "failed to suspend for wow %d\n", ret); + mutex_unlock(&rtwdev->mutex); + + return ret ? 1 : 0; +} + +static int rtw_ops_resume(struct ieee80211_hw *hw) +{ + struct rtw_dev *rtwdev = hw->priv; + int ret; + + mutex_lock(&rtwdev->mutex); + ret = rtw_wow_resume(rtwdev); + if (ret) + rtw_err(rtwdev, "failed to resume for wow %d\n", ret); + mutex_unlock(&rtwdev->mutex); + + return ret ? 1 : 0; +} + +static void rtw_ops_set_wakeup(struct ieee80211_hw *hw, bool enabled) +{ + struct rtw_dev *rtwdev = hw->priv; + + device_set_wakeup_enable(rtwdev->dev, enabled); +} +#endif + const struct ieee80211_ops rtw_ops = { .tx = rtw_ops_tx, .wake_tx_queue = rtw_ops_wake_tx_queue, @@ -757,5 +796,10 @@ const struct ieee80211_ops rtw_ops = { .sta_statistics = rtw_ops_sta_statistics, .flush = rtw_ops_flush, .set_bitrate_mask = rtw_ops_set_bitrate_mask, +#ifdef CONFIG_PM + .suspend = rtw_ops_suspend, + .resume = rtw_ops_resume, + .set_wakeup = rtw_ops_set_wakeup, +#endif }; EXPORT_SYMBOL(rtw_ops); diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 54e8a0cef14b..1ac48ccdb3c8 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -1493,6 +1493,9 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); +#ifdef CONFIG_PM + hw->wiphy->wowlan = rtwdev->chip->wowlan_stub; +#endif rtw_set_supported_band(hw, rtwdev->chip); SET_IEEE80211_PERM_ADDR(hw, rtwdev->efuse.addr); diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index b7690666fd57..e403d24adbcf 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -342,6 +342,7 @@ enum rtw_flags { RTW_FLAG_LEISURE_PS_DEEP, RTW_FLAG_DIG_DISABLE, RTW_FLAG_BUSY_TRAFFIC, + RTW_FLAG_WOWLAN, NUM_OF_RTW_FLAGS, }; @@ -372,6 +373,15 @@ enum rtw_snr { RTW_SNR_NUM }; +enum rtw_wow_flags { + RTW_WOW_FLAG_EN_MAGIC_PKT, + RTW_WOW_FLAG_EN_REKEY_PKT, + RTW_WOW_FLAG_EN_DISCONNECT, + + /* keep it last */ + RTW_WOW_FLAG_MAX, +}; + /* the power index is represented by differences, which cck-1s & ht40-1s are * the base values, so for 1s's differences, there are only ht20 & ofdm */ @@ -907,6 +917,12 @@ struct rtw_intf_phy_para { u16 platform; }; +struct rtw_wow_param { + struct ieee80211_vif *wow_vif; + DECLARE_BITMAP(flags, RTW_WOW_FLAG_MAX); + u8 txpause; +}; + struct rtw_intf_phy_para_table { struct rtw_intf_phy_para *usb2_para; struct rtw_intf_phy_para *usb3_para; @@ -1036,6 +1052,7 @@ struct rtw_chip_info { u8 bfer_mu_max_num; const char *wow_fw_name; + const struct wiphy_wowlan_support *wowlan_stub; /* coex paras */ u32 coex_para_ver; @@ -1589,6 +1606,7 @@ struct rtw_dev { u8 mp_mode; struct rtw_fw_state wow_fw; + struct rtw_wow_param wow; /* hci related data, must be last */ u8 priv[0] __aligned(sizeof(void *)); diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index a60d9b107006..f7770304ba42 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -1282,6 +1282,23 @@ static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev) rtw_pci_link_cfg(rtwdev); } +#ifdef CONFIG_PM +static int rtw_pci_suspend(struct device *dev) +{ + return 0; +} + +static int rtw_pci_resume(struct device *dev) +{ + return 0; +} + +static SIMPLE_DEV_PM_OPS(rtw_pm_ops, rtw_pci_suspend, rtw_pci_resume); +#define RTW_PM_OPS (&rtw_pm_ops) +#else +#define RTW_PM_OPS NULL +#endif + static int rtw_pci_claim(struct rtw_dev *rtwdev, struct pci_dev *pdev) { int ret; @@ -1508,6 +1525,7 @@ static struct pci_driver rtw_pci_driver = { .id_table = rtw_pci_id_table, .probe = rtw_pci_probe, .remove = rtw_pci_remove, + .driver.pm = RTW_PM_OPS, }; module_pci_driver(rtw_pci_driver); diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h index cd6b14c379ba..77f31420599f 100644 --- a/drivers/net/wireless/realtek/rtw88/reg.h +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -9,6 +9,8 @@ #define BIT_FEN_CPUEN BIT(2) #define BIT_FEN_BB_GLB_RST BIT(1) #define BIT_FEN_BB_RSTB BIT(0) +#define BIT_R_DIS_PRST BIT(6) +#define BIT_WLOCK_1C_B6 BIT(5) #define REG_SYS_PW_CTRL 0x0004 #define REG_SYS_CLK_CTRL 0x0008 #define BIT_CPU_CLK_EN BIT(14) @@ -160,8 +162,12 @@ #define REG_CR 0x0100 #define REG_TRXFF_BNDY 0x0114 #define REG_RXFF_BNDY 0x011C +#define REG_FE1IMR 0x0120 +#define BIT_FS_RXDONE BIT(16) #define REG_PKTBUF_DBG_CTRL 0x0140 #define REG_C2HEVT 0x01A0 +#define REG_MCUTST_II 0x01C4 +#define REG_WOWLAN_WAKE_REASON 0x01C7 #define REG_HMETFR 0x01CC #define REG_HMEBOX0 0x01D0 #define REG_HMEBOX1 0x01D4 @@ -192,11 +198,18 @@ #define REG_H2C_TAIL 0x0248 #define REG_H2C_READ_ADDR 0x024C #define REG_H2C_INFO 0x0254 +#define REG_RXPKT_NUM 0x0284 +#define BIT_RXDMA_REQ BIT(19) +#define BIT_RW_RELEASE BIT(18) +#define BIT_RXDMA_IDLE BIT(17) +#define REG_RXPKTNUM 0x02B0 #define REG_INT_MIG 0x0304 #define REG_HCI_MIX_CFG 0x03FC #define BIT_PCIE_EMAC_PDN_AUX_TO_FAST_CLK BIT(26) +#define REG_BCNQ_INFO 0x0418 +#define BIT_MGQ_CPU_EMPTY BIT(24) #define REG_FWHW_TXQ_CTRL 0x0420 #define BIT_EN_BCNQ_DL BIT(22) #define BIT_EN_WR_FREE_TAIL BIT(20) diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 174029836833..e10fe672f79c 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -4060,6 +4060,13 @@ static const struct rtw_pwr_track_tbl rtw8822c_rtw_pwr_track_tbl = { .pwrtrk_2g_ccka_p = rtw8822c_pwrtrk_2g_cck_a_p, }; +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support rtw_wowlan_stub_8822c = { + .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_GTK_REKEY_FAILURE | + WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY, +}; +#endif + struct rtw_chip_info rtw8822c_hw_spec = { .ops = &rtw8822c_ops, .id = RTW_CHIP_TYPE_8822C, @@ -4106,6 +4113,10 @@ struct rtw_chip_info rtw8822c_hw_spec = { .bfer_su_max_num = 2, .bfer_mu_max_num = 1, +#ifdef CONFIG_PM + .wow_fw_name = "rtw88/rtw8822c_wow_fw.bin", + .wowlan_stub = &rtw_wowlan_stub_8822c, +#endif .coex_para_ver = 0x19062706, .bt_desired_ver = 0x6, .scbd_support = true, @@ -4135,3 +4146,4 @@ struct rtw_chip_info rtw8822c_hw_spec = { EXPORT_SYMBOL(rtw8822c_hw_spec); MODULE_FIRMWARE("rtw88/rtw8822c_fw.bin"); +MODULE_FIRMWARE("rtw88/rtw8822c_wow_fw.bin"); diff --git a/drivers/net/wireless/realtek/rtw88/util.h b/drivers/net/wireless/realtek/rtw88/util.h index 7bd2843b0bce..41c10e7144df 100644 --- a/drivers/net/wireless/realtek/rtw88/util.h +++ b/drivers/net/wireless/realtek/rtw88/util.h @@ -15,6 +15,8 @@ struct rtw_dev; IEEE80211_IFACE_ITER_NORMAL, iterator, data) #define rtw_iterate_stas_atomic(rtwdev, iterator, data) \ ieee80211_iterate_stations_atomic(rtwdev->hw, iterator, data) +#define rtw_iterate_keys(rtwdev, vif, iterator, data) \ + ieee80211_iter_keys(rtwdev->hw, vif, iterator, data) static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) { diff --git a/drivers/net/wireless/realtek/rtw88/wow.c b/drivers/net/wireless/realtek/rtw88/wow.c new file mode 100644 index 000000000000..70289bccd5e4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/wow.c @@ -0,0 +1,531 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#include "main.h" +#include "fw.h" +#include "wow.h" +#include "reg.h" +#include "debug.h" +#include "mac.h" +#include "ps.h" + +static void rtw_wow_show_wakeup_reason(struct rtw_dev *rtwdev) +{ + u8 reason; + + reason = rtw_read8(rtwdev, REG_WOWLAN_WAKE_REASON); + + if (reason == RTW_WOW_RSN_RX_DEAUTH) + rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx deauth\n"); + else if (reason == RTW_WOW_RSN_DISCONNECT) + rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: AP is off\n"); + else if (reason == RTW_WOW_RSN_RX_MAGIC_PKT) + rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx magic packet\n"); + else if (reason == RTW_WOW_RSN_RX_GTK_REKEY) + rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx gtk rekey\n"); + else if (reason == RTW_WOW_RSN_RX_PTK_REKEY) + rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx ptk rekey\n"); + else + rtw_warn(rtwdev, "Unknown wakeup reason %x\n", reason); +} + +static void rtw_wow_bb_stop(struct rtw_dev *rtwdev) +{ + struct rtw_wow_param *rtw_wow = &rtwdev->wow; + + /* wait 100ms for firmware to finish TX */ + msleep(100); + + if (!rtw_read32_mask(rtwdev, REG_BCNQ_INFO, BIT_MGQ_CPU_EMPTY)) + rtw_warn(rtwdev, "Wrong status of MGQ_CPU empty!\n"); + + rtw_wow->txpause = rtw_read8(rtwdev, REG_TXPAUSE); + rtw_write8(rtwdev, REG_TXPAUSE, 0xff); + rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_BB_RSTB); +} + +static void rtw_wow_bb_start(struct rtw_dev *rtwdev) +{ + struct rtw_wow_param *rtw_wow = &rtwdev->wow; + + rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_BB_RSTB); + rtw_write8(rtwdev, REG_TXPAUSE, rtw_wow->txpause); +} + +static void rtw_wow_rx_dma_stop(struct rtw_dev *rtwdev) +{ + /* wait 100ms for HW to finish rx dma */ + msleep(100); + + rtw_write32_set(rtwdev, REG_RXPKT_NUM, BIT_RW_RELEASE); + + if (!check_hw_ready(rtwdev, REG_RXPKT_NUM, BIT_RXDMA_IDLE, 1)) + rtw_err(rtwdev, "failed to stop rx dma\n"); +} + +static void rtw_wow_rx_dma_start(struct rtw_dev *rtwdev) +{ + rtw_write32_clr(rtwdev, REG_RXPKT_NUM, BIT_RW_RELEASE); +} + +static bool rtw_wow_check_fw_status(struct rtw_dev *rtwdev, bool wow_enable) +{ + bool ret; + + /* wait 100ms for wow firmware to finish work */ + msleep(100); + + if (wow_enable) { + if (!rtw_read8(rtwdev, REG_WOWLAN_WAKE_REASON)) + ret = 0; + } else { + if (rtw_read32_mask(rtwdev, REG_FE1IMR, BIT_FS_RXDONE) == 0 && + rtw_read32_mask(rtwdev, REG_RXPKT_NUM, BIT_RW_RELEASE) == 0) + ret = 0; + } + + if (ret) + rtw_err(rtwdev, "failed to check wow status %s\n", + wow_enable ? "enabled" : "disabled"); + + return ret; +} + +static void rtw_wow_fw_security_type_iter(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, + void *data) +{ + struct rtw_fw_key_type_iter_data *iter_data = data; + struct rtw_dev *rtwdev = hw->priv; + u8 hw_key_type; + + if (vif != rtwdev->wow.wow_vif) + return; + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + hw_key_type = RTW_CAM_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + hw_key_type = RTW_CAM_WEP104; + break; + case WLAN_CIPHER_SUITE_TKIP: + hw_key_type = RTW_CAM_TKIP; + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + break; + case WLAN_CIPHER_SUITE_CCMP: + hw_key_type = RTW_CAM_AES; + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; + break; + default: + rtw_err(rtwdev, "Unsupported key type for wowlan mode\n"); + hw_key_type = 0; + break; + } + + if (sta) + iter_data->pairwise_key_type = hw_key_type; + else + iter_data->group_key_type = hw_key_type; +} + +static void rtw_wow_fw_security_type(struct rtw_dev *rtwdev) +{ + struct rtw_fw_key_type_iter_data data = {}; + struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; + + data.rtwdev = rtwdev; + rtw_iterate_keys(rtwdev, wow_vif, + rtw_wow_fw_security_type_iter, &data); + rtw_fw_set_aoac_global_info_cmd(rtwdev, data.pairwise_key_type, + data.group_key_type); +} + +static int rtw_wow_fw_start(struct rtw_dev *rtwdev) +{ + if (rtw_wow_mgd_linked(rtwdev)) { + rtw_send_rsvd_page_h2c(rtwdev); + rtw_wow_fw_security_type(rtwdev); + rtw_fw_set_disconnect_decision_cmd(rtwdev, true); + rtw_fw_set_keep_alive_cmd(rtwdev, true); + } + + rtw_fw_set_wowlan_ctrl_cmd(rtwdev, true); + rtw_fw_set_remote_wake_ctrl_cmd(rtwdev, true); + + return rtw_wow_check_fw_status(rtwdev, true); +} + +static int rtw_wow_fw_stop(struct rtw_dev *rtwdev) +{ + if (rtw_wow_mgd_linked(rtwdev)) { + rtw_fw_set_disconnect_decision_cmd(rtwdev, false); + rtw_fw_set_keep_alive_cmd(rtwdev, false); + } + + rtw_fw_set_wowlan_ctrl_cmd(rtwdev, false); + rtw_fw_set_remote_wake_ctrl_cmd(rtwdev, false); + + return rtw_wow_check_fw_status(rtwdev, false); +} + +static void rtw_wow_avoid_reset_mac(struct rtw_dev *rtwdev) +{ + /* When resuming from wowlan mode, some hosts issue signal + * (PCIE: PREST, USB: SE0RST) to device, and lead to reset + * mac core. If it happens, the connection to AP will be lost. + * Setting REG_RSV_CTRL Register can avoid this process. + */ + switch (rtw_hci_type(rtwdev)) { + case RTW_HCI_TYPE_PCIE: + case RTW_HCI_TYPE_USB: + rtw_write8(rtwdev, REG_RSV_CTRL, BIT_WLOCK_1C_B6); + rtw_write8(rtwdev, REG_RSV_CTRL, + BIT_WLOCK_1C_B6 | BIT_R_DIS_PRST); + break; + default: + rtw_warn(rtwdev, "Unsupported hci type to disable reset MAC\n"); + break; + } +} + +static void rtw_wow_fw_media_status_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + struct rtw_fw_media_status_iter_data *iter_data = data; + struct rtw_dev *rtwdev = iter_data->rtwdev; + + rtw_fw_media_status_report(rtwdev, si->mac_id, iter_data->connect); +} + +static void rtw_wow_fw_media_status(struct rtw_dev *rtwdev, bool connect) +{ + struct rtw_fw_media_status_iter_data data; + + data.rtwdev = rtwdev; + data.connect = connect; + + rtw_iterate_stas_atomic(rtwdev, rtw_wow_fw_media_status_iter, &data); +} + +static void rtw_wow_config_linked_rsvd_page(struct rtw_dev *rtwdev) +{ + rtw_add_rsvd_page(rtwdev, RSVD_PS_POLL, true); + rtw_add_rsvd_page(rtwdev, RSVD_QOS_NULL, true); + rtw_add_rsvd_page(rtwdev, RSVD_NULL, true); + rtw_add_rsvd_page(rtwdev, RSVD_LPS_PG_DPK, true); + rtw_add_rsvd_page(rtwdev, RSVD_LPS_PG_INFO, true); +} + +static void rtw_wow_config_rsvd_page(struct rtw_dev *rtwdev) +{ + rtw_reset_rsvd_page(rtwdev); + + if (rtw_wow_mgd_linked(rtwdev)) + rtw_wow_config_linked_rsvd_page(rtwdev); +} + +static int rtw_wow_dl_fw_rsvd_page(struct rtw_dev *rtwdev) +{ + struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; + + rtw_wow_config_rsvd_page(rtwdev); + + return rtw_fw_download_rsvd_page(rtwdev, wow_vif); +} + +static int rtw_wow_swap_fw(struct rtw_dev *rtwdev, enum rtw_fw_type type) +{ + struct rtw_fw_state *fw; + int ret; + + switch (type) { + case RTW_WOWLAN_FW: + fw = &rtwdev->wow_fw; + break; + + case RTW_NORMAL_FW: + fw = &rtwdev->fw; + break; + + default: + rtw_warn(rtwdev, "unsupported firmware type to swap\n"); + return -ENOENT; + } + + ret = rtw_download_firmware(rtwdev, fw); + if (ret) + goto out; + + rtw_fw_send_general_info(rtwdev); + rtw_fw_send_phydm_info(rtwdev); + rtw_wow_fw_media_status(rtwdev, true); + +out: + return ret; +} + +static int rtw_wow_leave_linked_ps(struct rtw_dev *rtwdev) +{ + if (!test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) + cancel_delayed_work_sync(&rtwdev->watch_dog_work); + + return 0; +} + +static int rtw_wow_leave_ps(struct rtw_dev *rtwdev) +{ + int ret = 0; + + if (rtw_wow_mgd_linked(rtwdev)) + ret = rtw_wow_leave_linked_ps(rtwdev); + + return ret; +} + +static int rtw_wow_enter_linked_ps(struct rtw_dev *rtwdev) +{ + struct rtw_wow_param *rtw_wow = &rtwdev->wow; + struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; + struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv; + + rtw_enter_lps(rtwdev, rtwvif->port); + + return 0; +} + +static int rtw_wow_enter_ps(struct rtw_dev *rtwdev) +{ + int ret = 0; + + if (rtw_wow_mgd_linked(rtwdev)) + ret = rtw_wow_enter_linked_ps(rtwdev); + + return ret; +} + +static void rtw_wow_stop_trx(struct rtw_dev *rtwdev) +{ + rtw_wow_bb_stop(rtwdev); + rtw_wow_rx_dma_stop(rtwdev); +} + +static int rtw_wow_start(struct rtw_dev *rtwdev) +{ + int ret; + + ret = rtw_wow_fw_start(rtwdev); + if (ret) + goto out; + + rtw_hci_stop(rtwdev); + rtw_wow_bb_start(rtwdev); + rtw_wow_avoid_reset_mac(rtwdev); + +out: + return ret; +} + +static int rtw_wow_enable(struct rtw_dev *rtwdev) +{ + int ret = 0; + + rtw_wow_stop_trx(rtwdev); + + ret = rtw_wow_swap_fw(rtwdev, RTW_WOWLAN_FW); + if (ret) { + rtw_err(rtwdev, "failed to swap wow fw\n"); + goto error; + } + + set_bit(RTW_FLAG_WOWLAN, rtwdev->flags); + + ret = rtw_wow_dl_fw_rsvd_page(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to download wowlan rsvd page\n"); + goto error; + } + + ret = rtw_wow_start(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to start wow\n"); + goto error; + } + + return ret; + +error: + clear_bit(RTW_FLAG_WOWLAN, rtwdev->flags); + return ret; +} + +static int rtw_wow_stop(struct rtw_dev *rtwdev) +{ + int ret; + + /* some HCI related registers will be reset after resume, + * need to set them again. + */ + ret = rtw_hci_setup(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to setup hci\n"); + return ret; + } + + ret = rtw_hci_start(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to start hci\n"); + return ret; + } + + ret = rtw_wow_fw_stop(rtwdev); + if (ret) + rtw_err(rtwdev, "failed to stop wowlan fw\n"); + + rtw_wow_bb_stop(rtwdev); + + return ret; +} + +static void rtw_wow_resume_trx(struct rtw_dev *rtwdev) +{ + rtw_wow_rx_dma_start(rtwdev); + rtw_wow_bb_start(rtwdev); + ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work, + RTW_WATCH_DOG_DELAY_TIME); +} + +static int rtw_wow_disable(struct rtw_dev *rtwdev) +{ + int ret; + + clear_bit(RTW_FLAG_WOWLAN, rtwdev->flags); + + ret = rtw_wow_stop(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to stop wow\n"); + goto out; + } + + ret = rtw_wow_swap_fw(rtwdev, RTW_NORMAL_FW); + if (ret) { + rtw_err(rtwdev, "failed to swap normal fw\n"); + goto out; + } + + ret = rtw_wow_dl_fw_rsvd_page(rtwdev); + if (ret) + rtw_err(rtwdev, "failed to download normal rsvd page\n"); + +out: + rtw_wow_resume_trx(rtwdev); + return ret; +} + +static void rtw_wow_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) +{ + struct rtw_dev *rtwdev = data; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + struct rtw_wow_param *rtw_wow = &rtwdev->wow; + + /* Current wowlan function support setting of only one STATION vif. + * So when one suitable vif is found, stop the iteration. + */ + if (rtw_wow->wow_vif || vif->type != NL80211_IFTYPE_STATION) + return; + + switch (rtwvif->net_type) { + case RTW_NET_MGD_LINKED: + rtw_wow->wow_vif = vif; + break; + default: + break; + } +} + +static int rtw_wow_set_wakeups(struct rtw_dev *rtwdev, + struct cfg80211_wowlan *wowlan) +{ + struct rtw_wow_param *rtw_wow = &rtwdev->wow; + + if (wowlan->disconnect) + set_bit(RTW_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags); + if (wowlan->magic_pkt) + set_bit(RTW_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags); + if (wowlan->gtk_rekey_failure) + set_bit(RTW_WOW_FLAG_EN_REKEY_PKT, rtw_wow->flags); + + rtw_iterate_vifs_atomic(rtwdev, rtw_wow_vif_iter, rtwdev); + if (!rtw_wow->wow_vif) + return -EPERM; + + return 0; +} + +static void rtw_wow_clear_wakeups(struct rtw_dev *rtwdev) +{ + struct rtw_wow_param *rtw_wow = &rtwdev->wow; + + memset(rtw_wow, 0, sizeof(rtwdev->wow)); +} + +int rtw_wow_suspend(struct rtw_dev *rtwdev, struct cfg80211_wowlan *wowlan) +{ + int ret = 0; + + ret = rtw_wow_set_wakeups(rtwdev, wowlan); + if (ret) { + rtw_err(rtwdev, "failed to set wakeup event\n"); + goto out; + } + + ret = rtw_wow_leave_ps(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to leave ps from normal mode\n"); + goto out; + } + + ret = rtw_wow_enable(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to enable wow\n"); + goto out; + } + + ret = rtw_wow_enter_ps(rtwdev); + if (ret) + rtw_err(rtwdev, "failed to enter ps for wow\n"); + +out: + return ret; +} + +int rtw_wow_resume(struct rtw_dev *rtwdev) +{ + int ret; + + /* If wowlan mode is not enabled, do nothing */ + if (!test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) { + rtw_err(rtwdev, "wow is not enabled\n"); + ret = -EPERM; + goto out; + } + + ret = rtw_wow_leave_ps(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to leave ps from wowlan mode\n"); + goto out; + } + + rtw_wow_show_wakeup_reason(rtwdev); + + ret = rtw_wow_disable(rtwdev); + if (ret) + rtw_err(rtwdev, "failed to disable wow\n"); + +out: + rtw_wow_clear_wakeups(rtwdev); + return ret; +} diff --git a/drivers/net/wireless/realtek/rtw88/wow.h b/drivers/net/wireless/realtek/rtw88/wow.h new file mode 100644 index 000000000000..617806a2f28d --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/wow.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2018-2019 Realtek Corporation + */ + +#ifndef __RTW_WOW_H__ +#define __RTW_WOW_H__ + +enum rtw_wake_reason { + RTW_WOW_RSN_RX_PTK_REKEY = 0x1, + RTW_WOW_RSN_RX_GTK_REKEY = 0x2, + RTW_WOW_RSN_RX_DEAUTH = 0x8, + RTW_WOW_RSN_DISCONNECT = 0x10, + RTW_WOW_RSN_RX_MAGIC_PKT = 0x21, +}; + +struct rtw_fw_media_status_iter_data { + struct rtw_dev *rtwdev; + u8 connect; +}; + +struct rtw_fw_key_type_iter_data { + struct rtw_dev *rtwdev; + u8 group_key_type; + u8 pairwise_key_type; +}; + +static inline bool rtw_wow_mgd_linked(struct rtw_dev *rtwdev) +{ + struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; + struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv; + + return (rtwvif->net_type == RTW_NET_MGD_LINKED); +} + +int rtw_wow_suspend(struct rtw_dev *rtwdev, struct cfg80211_wowlan *wowlan); +int rtw_wow_resume(struct rtw_dev *rtwdev); + +#endif From e3e400df30078830871b927ca24826667d97d1f6 Mon Sep 17 00:00:00 2001 From: Chin-Yen Lee Date: Thu, 19 Dec 2019 16:58:15 +0800 Subject: [PATCH 57/96] rtw88: Add wowlan pattern match support Pattern match is an option of wowlan to allow the device to be woken up from suspend mode when receiving packets matched user-designed patterns. The patterns are written into hardware cam in suspend flow if users have set up them. If packets matched designed pattern are received, wowlan firmware will get an interrupt and then wake up the device. Signed-off-by: Chin-Yen Lee Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/fw.c | 6 + drivers/net/wireless/realtek/rtw88/fw.h | 4 + drivers/net/wireless/realtek/rtw88/main.h | 14 ++ drivers/net/wireless/realtek/rtw88/reg.h | 14 ++ drivers/net/wireless/realtek/rtw88/rtw8822c.c | 3 + drivers/net/wireless/realtek/rtw88/wow.c | 224 ++++++++++++++++++ drivers/net/wireless/realtek/rtw88/wow.h | 9 + 7 files changed, 274 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 16ff59576154..0523851cf98d 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -538,6 +538,8 @@ void rtw_fw_set_wowlan_ctrl_cmd(struct rtw_dev *rtwdev, bool enable) SET_WOWLAN_DEAUTH_WAKEUP_ENABLE(h2c_pkt, enable); if (test_bit(RTW_WOW_FLAG_EN_REKEY_PKT, rtw_wow->flags)) SET_WOWLAN_REKEY_WAKEUP_ENABLE(h2c_pkt, enable); + if (rtw_wow->pattern_cnt) + SET_WOWLAN_PATTERN_MATCH_ENABLE(h2c_pkt, enable); } rtw_fw_send_h2c_command(rtwdev, h2c_pkt); @@ -596,6 +598,7 @@ void rtw_fw_set_pg_info(struct rtw_dev *rtwdev) LPS_PG_INFO_LOC(h2c_pkt, loc_pg); LPS_PG_DPK_LOC(h2c_pkt, loc_dpk); LPS_PG_SEC_CAM_EN(h2c_pkt, conf->sec_cam_backup); + LPS_PG_PATTERN_CAM_EN(h2c_pkt, conf->pattern_cam_backup); rtw_fw_send_h2c_command(rtwdev, h2c_pkt); } @@ -677,6 +680,7 @@ static struct sk_buff *rtw_lps_pg_info_get(struct ieee80211_hw *hw, struct rtw_chip_info *chip = rtwdev->chip; struct rtw_lps_conf *conf = &rtwdev->lps_conf; struct rtw_lps_pg_info_hdr *pg_info_hdr; + struct rtw_wow_param *rtw_wow = &rtwdev->wow; struct sk_buff *skb; u32 size; @@ -691,8 +695,10 @@ static struct sk_buff *rtw_lps_pg_info_get(struct ieee80211_hw *hw, pg_info_hdr->macid = find_first_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM); pg_info_hdr->sec_cam_count = rtw_sec_cam_pg_backup(rtwdev, pg_info_hdr->sec_cam); + pg_info_hdr->pattern_count = rtw_wow->pattern_cnt; conf->sec_cam_backup = pg_info_hdr->sec_cam_count != 0; + conf->pattern_cam_backup = rtw_wow->pattern_cnt != 0; return skb; } diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h index 9ffc1b1ea895..9ea27cca11ac 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.h +++ b/drivers/net/wireless/realtek/rtw88/fw.h @@ -246,6 +246,8 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24)) #define LPS_PG_SEC_CAM_EN(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) +#define LPS_PG_PATTERN_CAM_EN(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(10)) #define SET_RSSI_INFO_MACID(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8)) #define SET_RSSI_INFO_RSSI(h2c_pkt, value) \ @@ -343,6 +345,8 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) #define SET_WOWLAN_FUNC_ENABLE(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) +#define SET_WOWLAN_PATTERN_MATCH_ENABLE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(9)) #define SET_WOWLAN_MAGIC_PKT_ENABLE(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(10)) #define SET_WOWLAN_UNICAST_PKT_ENABLE(h2c_pkt, value) \ diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index e403d24adbcf..74368ef954fa 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -19,6 +19,10 @@ #define RTW_MAX_SEC_CAM_NUM 32 #define MAX_PG_CAM_BACKUP_NUM 8 +#define RTW_MAX_PATTERN_NUM 12 +#define RTW_MAX_PATTERN_MASK_SIZE 16 +#define RTW_MAX_PATTERN_SIZE 128 + #define RTW_WATCH_DOG_DELAY_TIME round_jiffies_relative(HZ * 2) #define RFREG_MASK 0xfffff @@ -623,6 +627,7 @@ struct rtw_lps_conf { u8 smart_ps; u8 port_id; bool sec_cam_backup; + bool pattern_cam_backup; }; enum rtw_hw_key_type { @@ -917,10 +922,19 @@ struct rtw_intf_phy_para { u16 platform; }; +struct rtw_wow_pattern { + u16 crc; + u8 type; + u8 valid; + u8 mask[RTW_MAX_PATTERN_MASK_SIZE]; +}; + struct rtw_wow_param { struct ieee80211_vif *wow_vif; DECLARE_BITMAP(flags, RTW_WOW_FLAG_MAX); u8 txpause; + u8 pattern_cnt; + struct rtw_wow_pattern patterns[RTW_MAX_PATTERN_NUM]; }; struct rtw_intf_phy_para_table { diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h index 77f31420599f..9d94534c9674 100644 --- a/drivers/net/wireless/realtek/rtw88/reg.h +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -338,6 +338,20 @@ #define BIT_RFMOD_80M BIT(8) #define BIT_RFMOD_40M BIT(7) #define REG_WMAC_TRXPTCL_CTL_H 0x066C +#define REG_WKFMCAM_CMD 0x0698 +#define BIT_WKFCAM_POLLING_V1 BIT(31) +#define BIT_WKFCAM_CLR_V1 BIT(30) +#define BIT_WKFCAM_WE BIT(16) +#define BIT_SHIFT_WKFCAM_ADDR_V2 8 +#define BIT_MASK_WKFCAM_ADDR_V2 0xff +#define BIT_WKFCAM_ADDR_V2(x) \ + (((x) & BIT_MASK_WKFCAM_ADDR_V2) << BIT_SHIFT_WKFCAM_ADDR_V2) +#define REG_WKFMCAM_RWD 0x069C +#define BIT_WKFMCAM_VALID BIT(31) +#define BIT_WKFMCAM_BC BIT(26) +#define BIT_WKFMCAM_MC BIT(25) +#define BIT_WKFMCAM_UC BIT(24) + #define REG_RXFLTMAP0 0x06A0 #define REG_RXFLTMAP1 0x06A2 #define REG_RXFLTMAP2 0x06A4 diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index e10fe672f79c..4836c0044b05 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -4064,6 +4064,9 @@ static const struct rtw_pwr_track_tbl rtw8822c_rtw_pwr_track_tbl = { static const struct wiphy_wowlan_support rtw_wowlan_stub_8822c = { .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_GTK_REKEY_FAILURE | WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY, + .n_patterns = RTW_MAX_PATTERN_NUM, + .pattern_max_len = RTW_MAX_PATTERN_SIZE, + .pattern_min_len = 1, }; #endif diff --git a/drivers/net/wireless/realtek/rtw88/wow.c b/drivers/net/wireless/realtek/rtw88/wow.c index 70289bccd5e4..f4645f3c98e0 100644 --- a/drivers/net/wireless/realtek/rtw88/wow.c +++ b/drivers/net/wireless/realtek/rtw88/wow.c @@ -26,10 +26,220 @@ static void rtw_wow_show_wakeup_reason(struct rtw_dev *rtwdev) rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx gtk rekey\n"); else if (reason == RTW_WOW_RSN_RX_PTK_REKEY) rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx ptk rekey\n"); + else if (reason == RTW_WOW_RSN_RX_PATTERN_MATCH) + rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx pattern match packet\n"); else rtw_warn(rtwdev, "Unknown wakeup reason %x\n", reason); } +static void rtw_wow_pattern_write_cam(struct rtw_dev *rtwdev, u8 addr, + u32 wdata) +{ + rtw_write32(rtwdev, REG_WKFMCAM_RWD, wdata); + rtw_write32(rtwdev, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1 | + BIT_WKFCAM_WE | BIT_WKFCAM_ADDR_V2(addr)); + + if (!check_hw_ready(rtwdev, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1, 0)) + rtw_err(rtwdev, "failed to write pattern cam\n"); +} + +static void rtw_wow_pattern_write_cam_ent(struct rtw_dev *rtwdev, u8 id, + struct rtw_wow_pattern *rtw_pattern) +{ + int i; + u8 addr; + u32 wdata; + + for (i = 0; i < RTW_MAX_PATTERN_MASK_SIZE / 4; i++) { + addr = (id << 3) + i; + wdata = rtw_pattern->mask[i * 4]; + wdata |= rtw_pattern->mask[i * 4 + 1] << 8; + wdata |= rtw_pattern->mask[i * 4 + 2] << 16; + wdata |= rtw_pattern->mask[i * 4 + 3] << 24; + rtw_wow_pattern_write_cam(rtwdev, addr, wdata); + } + + wdata = rtw_pattern->crc; + addr = (id << 3) + RTW_MAX_PATTERN_MASK_SIZE / 4; + + switch (rtw_pattern->type) { + case RTW_PATTERN_BROADCAST: + wdata |= BIT_WKFMCAM_BC | BIT_WKFMCAM_VALID; + break; + case RTW_PATTERN_MULTICAST: + wdata |= BIT_WKFMCAM_MC | BIT_WKFMCAM_VALID; + break; + case RTW_PATTERN_UNICAST: + wdata |= BIT_WKFMCAM_UC | BIT_WKFMCAM_VALID; + break; + default: + break; + } + rtw_wow_pattern_write_cam(rtwdev, addr, wdata); +} + +/* RTK internal CRC16 for Pattern Cam */ +static u16 __rtw_cal_crc16(u8 data, u16 crc) +{ + u8 shift_in, data_bit; + u8 crc_bit4, crc_bit11, crc_bit15; + u16 crc_result; + int index; + + for (index = 0; index < 8; index++) { + crc_bit15 = ((crc & BIT(15)) ? 1 : 0); + data_bit = (data & (BIT(0) << index) ? 1 : 0); + shift_in = crc_bit15 ^ data_bit; + + crc_result = crc << 1; + + if (shift_in == 0) + crc_result &= (~BIT(0)); + else + crc_result |= BIT(0); + + crc_bit11 = ((crc & BIT(11)) ? 1 : 0) ^ shift_in; + + if (crc_bit11 == 0) + crc_result &= (~BIT(12)); + else + crc_result |= BIT(12); + + crc_bit4 = ((crc & BIT(4)) ? 1 : 0) ^ shift_in; + + if (crc_bit4 == 0) + crc_result &= (~BIT(5)); + else + crc_result |= BIT(5); + + crc = crc_result; + } + return crc; +} + +static u16 rtw_calc_crc(u8 *pdata, int length) +{ + u16 crc = 0xffff; + int i; + + for (i = 0; i < length; i++) + crc = __rtw_cal_crc16(pdata[i], crc); + + /* get 1' complement */ + return ~crc; +} + +static void rtw_wow_pattern_generate(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif, + const struct cfg80211_pkt_pattern *pkt_pattern, + struct rtw_wow_pattern *rtw_pattern) +{ + const u8 *mask; + const u8 *pattern; + u8 mask_hw[RTW_MAX_PATTERN_MASK_SIZE] = {0}; + u8 content[RTW_MAX_PATTERN_SIZE] = {0}; + u8 mac_addr[ETH_ALEN] = {0}; + u8 mask_len; + u16 count; + int len; + int i; + + pattern = pkt_pattern->pattern; + len = pkt_pattern->pattern_len; + mask = pkt_pattern->mask; + + ether_addr_copy(mac_addr, rtwvif->mac_addr); + memset(rtw_pattern, 0, sizeof(*rtw_pattern)); + + mask_len = DIV_ROUND_UP(len, 8); + + if (is_broadcast_ether_addr(pattern)) + rtw_pattern->type = RTW_PATTERN_BROADCAST; + else if (is_multicast_ether_addr(pattern)) + rtw_pattern->type = RTW_PATTERN_MULTICAST; + else if (ether_addr_equal(pattern, mac_addr)) + rtw_pattern->type = RTW_PATTERN_UNICAST; + else + rtw_pattern->type = RTW_PATTERN_INVALID; + + /* translate mask from os to mask for hw + * pattern from OS uses 'ethenet frame', like this: + * | 6 | 6 | 2 | 20 | Variable | 4 | + * |--------+--------+------+-----------+------------+-----| + * | 802.3 Mac Header | IP Header | TCP Packet | FCS | + * | DA | SA | Type | + * + * BUT, packet catched by our HW is in '802.11 frame', begin from LLC + * | 24 or 30 | 6 | 2 | 20 | Variable | 4 | + * |-------------------+--------+------+-----------+------------+-----| + * | 802.11 MAC Header | LLC | IP Header | TCP Packet | FCS | + * | Others | Tpye | + * + * Therefore, we need translate mask_from_OS to mask_to_hw. + * We should left-shift mask by 6 bits, then set the new bit[0~5] = 0, + * because new mask[0~5] means 'SA', but our HW packet begins from LLC, + * bit[0~5] corresponds to first 6 Bytes in LLC, they just don't match. + */ + + /* Shift 6 bits */ + for (i = 0; i < mask_len - 1; i++) { + mask_hw[i] = u8_get_bits(mask[i], GENMASK(7, 6)); + mask_hw[i] |= u8_get_bits(mask[i + 1], GENMASK(5, 0)) << 2; + } + mask_hw[i] = u8_get_bits(mask[i], GENMASK(7, 6)); + + /* Set bit 0-5 to zero */ + mask_hw[0] &= (~GENMASK(5, 0)); + + memcpy(rtw_pattern->mask, mask_hw, RTW_MAX_PATTERN_MASK_SIZE); + + /* To get the wake up pattern from the mask. + * We do not count first 12 bits which means + * DA[6] and SA[6] in the pattern to match HW design. + */ + count = 0; + for (i = 12; i < len; i++) { + if ((mask[i / 8] >> (i % 8)) & 0x01) { + content[count] = pattern[i]; + count++; + } + } + + rtw_pattern->crc = rtw_calc_crc(content, count); +} + +static void rtw_wow_pattern_clear_cam(struct rtw_dev *rtwdev) +{ + bool ret; + + rtw_write32(rtwdev, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1 | + BIT_WKFCAM_CLR_V1); + + ret = check_hw_ready(rtwdev, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1, 0); + if (!ret) + rtw_err(rtwdev, "failed to clean pattern cam\n"); +} + +static void rtw_wow_pattern_write(struct rtw_dev *rtwdev) +{ + struct rtw_wow_param *rtw_wow = &rtwdev->wow; + struct rtw_wow_pattern *rtw_pattern = rtw_wow->patterns; + int i = 0; + + for (i = 0; i < rtw_wow->pattern_cnt; i++) + rtw_wow_pattern_write_cam_ent(rtwdev, i, rtw_pattern + i); +} + +static void rtw_wow_pattern_clear(struct rtw_dev *rtwdev) +{ + struct rtw_wow_param *rtw_wow = &rtwdev->wow; + + rtw_wow_pattern_clear_cam(rtwdev); + + rtw_wow->pattern_cnt = 0; + memset(rtw_wow->patterns, 0, sizeof(rtw_wow->patterns)); +} + static void rtw_wow_bb_stop(struct rtw_dev *rtwdev) { struct rtw_wow_param *rtw_wow = &rtwdev->wow; @@ -148,6 +358,7 @@ static int rtw_wow_fw_start(struct rtw_dev *rtwdev) { if (rtw_wow_mgd_linked(rtwdev)) { rtw_send_rsvd_page_h2c(rtwdev); + rtw_wow_pattern_write(rtwdev); rtw_wow_fw_security_type(rtwdev); rtw_fw_set_disconnect_decision_cmd(rtwdev, true); rtw_fw_set_keep_alive_cmd(rtwdev, true); @@ -164,6 +375,7 @@ static int rtw_wow_fw_stop(struct rtw_dev *rtwdev) if (rtw_wow_mgd_linked(rtwdev)) { rtw_fw_set_disconnect_decision_cmd(rtwdev, false); rtw_fw_set_keep_alive_cmd(rtwdev, false); + rtw_wow_pattern_clear(rtwdev); } rtw_fw_set_wowlan_ctrl_cmd(rtwdev, false); @@ -450,6 +662,9 @@ static int rtw_wow_set_wakeups(struct rtw_dev *rtwdev, struct cfg80211_wowlan *wowlan) { struct rtw_wow_param *rtw_wow = &rtwdev->wow; + struct rtw_wow_pattern *rtw_patterns = rtw_wow->patterns; + struct rtw_vif *rtwvif; + int i; if (wowlan->disconnect) set_bit(RTW_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags); @@ -462,6 +677,15 @@ static int rtw_wow_set_wakeups(struct rtw_dev *rtwdev, if (!rtw_wow->wow_vif) return -EPERM; + rtwvif = (struct rtw_vif *)rtw_wow->wow_vif->drv_priv; + if (wowlan->n_patterns && wowlan->patterns) { + rtw_wow->pattern_cnt = wowlan->n_patterns; + for (i = 0; i < wowlan->n_patterns; i++) + rtw_wow_pattern_generate(rtwdev, rtwvif, + wowlan->patterns + i, + rtw_patterns + i); + } + return 0; } diff --git a/drivers/net/wireless/realtek/rtw88/wow.h b/drivers/net/wireless/realtek/rtw88/wow.h index 617806a2f28d..54f742f4c955 100644 --- a/drivers/net/wireless/realtek/rtw88/wow.h +++ b/drivers/net/wireless/realtek/rtw88/wow.h @@ -5,12 +5,21 @@ #ifndef __RTW_WOW_H__ #define __RTW_WOW_H__ +enum rtw_wow_pattern_type { + RTW_PATTERN_BROADCAST = 0, + RTW_PATTERN_MULTICAST, + RTW_PATTERN_UNICAST, + RTW_PATTERN_VALID, + RTW_PATTERN_INVALID, +}; + enum rtw_wake_reason { RTW_WOW_RSN_RX_PTK_REKEY = 0x1, RTW_WOW_RSN_RX_GTK_REKEY = 0x2, RTW_WOW_RSN_RX_DEAUTH = 0x8, RTW_WOW_RSN_DISCONNECT = 0x10, RTW_WOW_RSN_RX_MAGIC_PKT = 0x21, + RTW_WOW_RSN_RX_PATTERN_MATCH = 0x23, }; struct rtw_fw_media_status_iter_data { From b6c12908a33e4e413523e73464cd5957690f1a76 Mon Sep 17 00:00:00 2001 From: Chin-Yen Lee Date: Thu, 19 Dec 2019 16:58:16 +0800 Subject: [PATCH 58/96] rtw88: Add wowlan net-detect support Net-detect is an option of wowlan to allow the device to be woken up from suspend mode when configured network is detected. When user enables net-detect and lets the device enter suspend state, wowlan firmware will periodically scan until beacon or probe response of configured networks are received. Between two scans, wowlan firmware keeps wifi chip in idle mode to reduce power consumption. If configured networks are detected, wowlan firmware will trigger resume process. Signed-off-by: Chin-Yen Lee Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/fw.c | 296 +++++++++++++++++- drivers/net/wireless/realtek/rtw88/fw.h | 113 +++++++ drivers/net/wireless/realtek/rtw88/main.c | 1 + drivers/net/wireless/realtek/rtw88/main.h | 25 ++ drivers/net/wireless/realtek/rtw88/rtw8822c.c | 5 +- drivers/net/wireless/realtek/rtw88/wow.c | 139 +++++++- drivers/net/wireless/realtek/rtw88/wow.h | 11 + 7 files changed, 573 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 0523851cf98d..e3e91ae0d3d2 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -567,6 +567,9 @@ void rtw_fw_set_remote_wake_ctrl_cmd(struct rtw_dev *rtwdev, bool enable) SET_REMOTE_WAKECTRL_ENABLE(h2c_pkt, enable); + if (rtw_wow_no_link(rtwdev)) + SET_REMOTE_WAKE_CTRL_NLO_OFFLOAD_EN(h2c_pkt, enable); + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); } @@ -584,6 +587,26 @@ static u8 rtw_get_rsvd_page_location(struct rtw_dev *rtwdev, return location; } +void rtw_fw_set_nlo_info(struct rtw_dev *rtwdev, bool enable) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + u8 loc_nlo; + + loc_nlo = rtw_get_rsvd_page_location(rtwdev, RSVD_NLO_INFO); + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_NLO_INFO); + + SET_NLO_FUN_EN(h2c_pkt, enable); + if (enable) { + if (rtw_fw_lps_deep_mode) + SET_NLO_PS_32K(h2c_pkt, enable); + SET_NLO_IGNORE_SECURITY(h2c_pkt, enable); + SET_NLO_LOC_NLO_INFO(h2c_pkt, loc_nlo); + } + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); +} + void rtw_fw_set_pg_info(struct rtw_dev *rtwdev) { struct rtw_lps_conf *conf = &rtwdev->lps_conf; @@ -603,6 +626,40 @@ void rtw_fw_set_pg_info(struct rtw_dev *rtwdev) rtw_fw_send_h2c_command(rtwdev, h2c_pkt); } +u8 rtw_get_rsvd_page_probe_req_location(struct rtw_dev *rtwdev, + struct cfg80211_ssid *ssid) +{ + struct rtw_rsvd_page *rsvd_pkt; + u8 location = 0; + + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { + if (rsvd_pkt->type != RSVD_PROBE_REQ) + continue; + if ((!ssid && !rsvd_pkt->ssid) || + rtw_ssid_equal(rsvd_pkt->ssid, ssid)) + location = rsvd_pkt->page; + } + + return location; +} + +u16 rtw_get_rsvd_page_probe_req_size(struct rtw_dev *rtwdev, + struct cfg80211_ssid *ssid) +{ + struct rtw_rsvd_page *rsvd_pkt; + u16 size = 0; + + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { + if (rsvd_pkt->type != RSVD_PROBE_REQ) + continue; + if ((!ssid && !rsvd_pkt->ssid) || + rtw_ssid_equal(rsvd_pkt->ssid, ssid)) + size = rsvd_pkt->skb->len; + } + + return size; +} + void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev) { u8 h2c_pkt[H2C_PKT_SIZE] = {0}; @@ -648,6 +705,95 @@ rtw_beacon_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif) return skb_new; } +static struct sk_buff *rtw_nlo_info_get(struct ieee80211_hw *hw) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_pno_request *pno_req = &rtwdev->wow.pno_req; + struct rtw_nlo_info_hdr *nlo_hdr; + struct cfg80211_ssid *ssid; + struct sk_buff *skb; + u8 *pos, loc; + u32 size; + int i; + + if (!pno_req->inited || !pno_req->match_set_cnt) + return NULL; + + size = sizeof(struct rtw_nlo_info_hdr) + pno_req->match_set_cnt * + IEEE80211_MAX_SSID_LEN + chip->tx_pkt_desc_sz; + + skb = alloc_skb(size, GFP_KERNEL); + if (!skb) + return NULL; + + skb_reserve(skb, chip->tx_pkt_desc_sz); + + nlo_hdr = skb_put_zero(skb, sizeof(struct rtw_nlo_info_hdr)); + + nlo_hdr->nlo_count = pno_req->match_set_cnt; + nlo_hdr->hidden_ap_count = pno_req->match_set_cnt; + + /* pattern check for firmware */ + memset(nlo_hdr->pattern_check, 0xA5, FW_NLO_INFO_CHECK_SIZE); + + for (i = 0; i < pno_req->match_set_cnt; i++) + nlo_hdr->ssid_len[i] = pno_req->match_sets[i].ssid.ssid_len; + + for (i = 0; i < pno_req->match_set_cnt; i++) { + ssid = &pno_req->match_sets[i].ssid; + loc = rtw_get_rsvd_page_probe_req_location(rtwdev, ssid); + if (!loc) { + rtw_err(rtwdev, "failed to get probe req rsvd loc\n"); + kfree(skb); + return NULL; + } + nlo_hdr->location[i] = loc; + } + + for (i = 0; i < pno_req->match_set_cnt; i++) { + pos = skb_put_zero(skb, IEEE80211_MAX_SSID_LEN); + memcpy(pos, pno_req->match_sets[i].ssid.ssid, + pno_req->match_sets[i].ssid.ssid_len); + } + + return skb; +} + +static struct sk_buff *rtw_cs_channel_info_get(struct ieee80211_hw *hw) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_pno_request *pno_req = &rtwdev->wow.pno_req; + struct ieee80211_channel *channels = pno_req->channels; + struct sk_buff *skb; + int count = pno_req->channel_cnt; + u8 *pos; + int i = 0; + + skb = alloc_skb(4 * count + chip->tx_pkt_desc_sz, GFP_KERNEL); + if (!skb) + return NULL; + + skb_reserve(skb, chip->tx_pkt_desc_sz); + + for (i = 0; i < count; i++) { + pos = skb_put_zero(skb, 4); + + CHSW_INFO_SET_CH(pos, channels[i].hw_value); + + if (channels[i].flags & IEEE80211_CHAN_RADAR) + CHSW_INFO_SET_ACTION_ID(pos, 0); + else + CHSW_INFO_SET_ACTION_ID(pos, 1); + CHSW_INFO_SET_TIMEOUT(pos, 1); + CHSW_INFO_SET_PRI_CH_IDX(pos, 1); + CHSW_INFO_SET_BW(pos, 0); + } + + return skb; +} + static struct sk_buff *rtw_lps_pg_dpk_get(struct ieee80211_hw *hw) { struct rtw_dev *rtwdev = hw->priv; @@ -705,11 +851,12 @@ static struct sk_buff *rtw_lps_pg_info_get(struct ieee80211_hw *hw, static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum rtw_rsvd_packet_type type) + struct rtw_rsvd_page *rsvd_pkt) { struct sk_buff *skb_new; + struct cfg80211_ssid *ssid; - switch (type) { + switch (rsvd_pkt->type) { case RSVD_BEACON: skb_new = rtw_beacon_get(hw, vif); break; @@ -731,6 +878,21 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw, case RSVD_LPS_PG_INFO: skb_new = rtw_lps_pg_info_get(hw, vif); break; + case RSVD_PROBE_REQ: + ssid = (struct cfg80211_ssid *)rsvd_pkt->ssid; + if (ssid) + skb_new = ieee80211_probereq_get(hw, vif->addr, + ssid->ssid, + ssid->ssid_len, 0); + else + skb_new = ieee80211_probereq_get(hw, vif->addr, NULL, 0, 0); + break; + case RSVD_NLO_INFO: + skb_new = rtw_nlo_info_get(hw); + break; + case RSVD_CH_INFO: + skb_new = rtw_cs_channel_info_get(hw); + break; default: return NULL; } @@ -772,25 +934,53 @@ static void rtw_rsvd_page_list_to_buf(struct rtw_dev *rtwdev, u8 page_size, memcpy(buf, skb->data, skb->len); } +static struct rtw_rsvd_page *rtw_alloc_rsvd_page(struct rtw_dev *rtwdev, + enum rtw_rsvd_packet_type type, + bool txdesc) +{ + struct rtw_rsvd_page *rsvd_pkt = NULL; + + rsvd_pkt = kzalloc(sizeof(*rsvd_pkt), GFP_KERNEL); + + if (!rsvd_pkt) + return NULL; + + rsvd_pkt->type = type; + rsvd_pkt->add_txdesc = txdesc; + + return rsvd_pkt; +} + +static void rtw_insert_rsvd_page(struct rtw_dev *rtwdev, + struct rtw_rsvd_page *rsvd_pkt) +{ + lockdep_assert_held(&rtwdev->mutex); + list_add_tail(&rsvd_pkt->list, &rtwdev->rsvd_page_list); +} + void rtw_add_rsvd_page(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type type, bool txdesc) { struct rtw_rsvd_page *rsvd_pkt; - lockdep_assert_held(&rtwdev->mutex); - - list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { - if (rsvd_pkt->type == type) - return; - } - - rsvd_pkt = kmalloc(sizeof(*rsvd_pkt), GFP_KERNEL); + rsvd_pkt = rtw_alloc_rsvd_page(rtwdev, type, txdesc); if (!rsvd_pkt) return; - rsvd_pkt->type = type; - rsvd_pkt->add_txdesc = txdesc; - list_add_tail(&rsvd_pkt->list, &rtwdev->rsvd_page_list); + rtw_insert_rsvd_page(rtwdev, rsvd_pkt); +} + +void rtw_add_rsvd_page_probe_req(struct rtw_dev *rtwdev, + struct cfg80211_ssid *ssid) +{ + struct rtw_rsvd_page *rsvd_pkt; + + rsvd_pkt = rtw_alloc_rsvd_page(rtwdev, RSVD_PROBE_REQ, true); + if (!rsvd_pkt) + return; + + rsvd_pkt->ssid = ssid; + rtw_insert_rsvd_page(rtwdev, rsvd_pkt); } void rtw_reset_rsvd_page(struct rtw_dev *rtwdev) @@ -887,7 +1077,7 @@ static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, page_margin = page_size - tx_desc_sz; list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { - iter = rtw_get_rsvd_page_skb(hw, vif, rsvd_pkt->type); + iter = rtw_get_rsvd_page_skb(hw, vif, rsvd_pkt); if (!iter) { rtw_err(rtwdev, "failed to build rsvd packet\n"); goto release_skb; @@ -1065,3 +1255,81 @@ out: rtw_write8(rtwdev, REG_RCR + 2, rcr); return 0; } + +static void __rtw_fw_update_pkt(struct rtw_dev *rtwdev, u8 pkt_id, u16 size, + u8 location) +{ + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + u16 total_size = H2C_PKT_HDR_SIZE + H2C_PKT_UPDATE_PKT_LEN; + + rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_UPDATE_PKT); + + SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size); + UPDATE_PKT_SET_PKT_ID(h2c_pkt, pkt_id); + UPDATE_PKT_SET_LOCATION(h2c_pkt, location); + + /* include txdesc size */ + UPDATE_PKT_SET_SIZE(h2c_pkt, size); + + rtw_fw_send_h2c_packet(rtwdev, h2c_pkt); +} + +void rtw_fw_update_pkt_probe_req(struct rtw_dev *rtwdev, + struct cfg80211_ssid *ssid) +{ + u8 loc; + u32 size; + + loc = rtw_get_rsvd_page_probe_req_location(rtwdev, ssid); + if (!loc) { + rtw_err(rtwdev, "failed to get probe_req rsvd loc\n"); + return; + } + + size = rtw_get_rsvd_page_probe_req_size(rtwdev, ssid); + if (!size) { + rtw_err(rtwdev, "failed to get probe_req rsvd size\n"); + return; + } + + __rtw_fw_update_pkt(rtwdev, RTW_PACKET_PROBE_REQ, size, loc); +} + +void rtw_fw_channel_switch(struct rtw_dev *rtwdev, bool enable) +{ + struct rtw_pno_request *rtw_pno_req = &rtwdev->wow.pno_req; + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + u16 total_size = H2C_PKT_HDR_SIZE + H2C_PKT_CH_SWITCH_LEN; + u8 loc_ch_info; + const struct rtw_ch_switch_option cs_option = { + .dest_ch_en = 1, + .dest_ch = 1, + .periodic_option = 2, + .normal_period = 5, + .normal_period_sel = 0, + .normal_cycle = 10, + .slow_period = 1, + .slow_period_sel = 1, + }; + + rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_CH_SWITCH); + SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size); + + CH_SWITCH_SET_START(h2c_pkt, enable); + CH_SWITCH_SET_DEST_CH_EN(h2c_pkt, cs_option.dest_ch_en); + CH_SWITCH_SET_DEST_CH(h2c_pkt, cs_option.dest_ch); + CH_SWITCH_SET_NORMAL_PERIOD(h2c_pkt, cs_option.normal_period); + CH_SWITCH_SET_NORMAL_PERIOD_SEL(h2c_pkt, cs_option.normal_period_sel); + CH_SWITCH_SET_SLOW_PERIOD(h2c_pkt, cs_option.slow_period); + CH_SWITCH_SET_SLOW_PERIOD_SEL(h2c_pkt, cs_option.slow_period_sel); + CH_SWITCH_SET_NORMAL_CYCLE(h2c_pkt, cs_option.normal_cycle); + CH_SWITCH_SET_PERIODIC_OPT(h2c_pkt, cs_option.periodic_option); + + CH_SWITCH_SET_CH_NUM(h2c_pkt, rtw_pno_req->channel_cnt); + CH_SWITCH_SET_INFO_SIZE(h2c_pkt, rtw_pno_req->channel_cnt * 4); + + loc_ch_info = rtw_get_rsvd_page_location(rtwdev, RSVD_CH_INFO); + CH_SWITCH_SET_INFO_LOC(h2c_pkt, loc_ch_info); + + rtw_fw_send_h2c_packet(rtwdev, h2c_pkt); +} diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h index 9ea27cca11ac..ccd27bd45775 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.h +++ b/drivers/net/wireless/realtek/rtw88/fw.h @@ -12,6 +12,8 @@ #define FW_HDR_SIZE 64 #define FW_HDR_CHKSUM_SIZE 8 +#define FW_NLO_INFO_CHECK_SIZE 4 + #define FIFO_PAGE_SIZE_SHIFT 12 #define FIFO_PAGE_SIZE 4096 #define RSVD_PAGE_START_ADDR 0x780 @@ -45,6 +47,9 @@ enum rtw_rsvd_packet_type { RSVD_QOS_NULL, RSVD_LPS_PG_DPK, RSVD_LPS_PG_INFO, + RSVD_PROBE_REQ, + RSVD_NLO_INFO, + RSVD_CH_INFO, }; enum rtw_fw_rf_type { @@ -98,6 +103,7 @@ struct rtw_rsvd_page { enum rtw_rsvd_packet_type type; u8 page; bool add_txdesc; + struct cfg80211_ssid *ssid; }; enum rtw_keep_alive_pkt_type { @@ -105,6 +111,24 @@ enum rtw_keep_alive_pkt_type { KEEP_ALIVE_ARP_RSP = 1, }; +struct rtw_nlo_info_hdr { + u8 nlo_count; + u8 hidden_ap_count; + u8 rsvd1[2]; + u8 pattern_check[FW_NLO_INFO_CHECK_SIZE]; + u8 rsvd2[8]; + u8 ssid_len[16]; + u8 chiper[16]; + u8 rsvd3[16]; + u8 location[8]; +} __packed; + +enum rtw_packet_type { + RTW_PACKET_PROBE_REQ = 0x00, + + RTW_PACKET_UNDEFINE = 0x7FFFFFFF, +}; + struct rtw_fw_wow_keep_alive_para { bool adopt; u8 pkt_type; @@ -117,6 +141,21 @@ struct rtw_fw_wow_disconnect_para { u8 retry_count; }; +struct rtw_ch_switch_option { + u8 periodic_option; + u32 tsf_high; + u32 tsf_low; + u8 dest_ch_en; + u8 absolute_time_en; + u8 dest_ch; + u8 normal_period; + u8 normal_period_sel; + u8 normal_cycle; + u8 slow_period; + u8 slow_period_sel; + u8 nlo_en; +}; + struct rtw_fw_hdr { __le16 signature; u8 category; @@ -163,6 +202,12 @@ struct rtw_fw_hdr { #define H2C_PKT_PHYDM_INFO 0x11 #define H2C_PKT_IQK 0x0E +#define H2C_PKT_CH_SWITCH 0x02 +#define H2C_PKT_UPDATE_PKT 0x0C + +#define H2C_PKT_CH_SWITCH_LEN 0x20 +#define H2C_PKT_UPDATE_PKT_LEN 0x4 + #define SET_PKT_H2C_CATEGORY(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(6, 0)) #define SET_PKT_H2C_CMD_ID(h2c_pkt, value) \ @@ -199,6 +244,57 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) #define IQK_SET_SEGMENT_IQK(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(1)) +#define CHSW_INFO_SET_CH(pkt, value) \ + le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(7, 0)) +#define CHSW_INFO_SET_PRI_CH_IDX(pkt, value) \ + le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(11, 8)) +#define CHSW_INFO_SET_BW(pkt, value) \ + le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(15, 12)) +#define CHSW_INFO_SET_TIMEOUT(pkt, value) \ + le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(23, 16)) +#define CHSW_INFO_SET_ACTION_ID(pkt, value) \ + le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(30, 24)) + +#define UPDATE_PKT_SET_SIZE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 0)) +#define UPDATE_PKT_SET_PKT_ID(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16)) +#define UPDATE_PKT_SET_LOCATION(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(31, 24)) + +#define CH_SWITCH_SET_START(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(0)) +#define CH_SWITCH_SET_DEST_CH_EN(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(1)) +#define CH_SWITCH_SET_ABSOLUTE_TIME(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(2)) +#define CH_SWITCH_SET_PERIODIC_OPT(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(4, 3)) +#define CH_SWITCH_SET_INFO_LOC(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 8)) +#define CH_SWITCH_SET_CH_NUM(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16)) +#define CH_SWITCH_SET_PRI_CH_IDX(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(27, 24)) +#define CH_SWITCH_SET_DEST_CH(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(7, 0)) +#define CH_SWITCH_SET_NORMAL_PERIOD(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(13, 8)) +#define CH_SWITCH_SET_NORMAL_PERIOD_SEL(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(15, 14)) +#define CH_SWITCH_SET_SLOW_PERIOD(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(21, 16)) +#define CH_SWITCH_SET_SLOW_PERIOD_SEL(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(23, 22)) +#define CH_SWITCH_SET_NORMAL_CYCLE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(31, 24)) +#define CH_SWITCH_SET_TSF_HIGH(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x04, value, GENMASK(31, 0)) +#define CH_SWITCH_SET_TSF_LOW(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x05, value, GENMASK(31, 0)) +#define CH_SWITCH_SET_INFO_SIZE(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x06, value, GENMASK(15, 0)) + /* Command H2C */ #define H2C_CMD_RSVD_PAGE 0x0 #define H2C_CMD_MEDIA_STATUS_RPT 0x01 @@ -220,6 +316,8 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) #define H2C_CMD_WOWLAN 0x80 #define H2C_CMD_REMOTE_WAKE_CTRL 0x81 #define H2C_CMD_AOAC_GLOBAL_INFO 0x82 +#define H2C_CMD_NLO_INFO 0x8C + #define SET_H2C_CMD_ID_CLASS(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(7, 0)) @@ -366,6 +464,15 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) #define SET_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(h2c_pkt, value) \ le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) +#define SET_NLO_FUN_EN(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8)) +#define SET_NLO_PS_32K(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(9)) +#define SET_NLO_IGNORE_SECURITY(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(10)) +#define SET_NLO_LOC_NLO_INFO(h2c_pkt, value) \ + le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16)) + static inline struct rtw_c2h_cmd *get_c2h_from_skb(struct sk_buff *skb) { u32 pkt_offset; @@ -397,6 +504,8 @@ void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool conn); void rtw_add_rsvd_page(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type type, bool txdesc); +void rtw_add_rsvd_page_probe_req(struct rtw_dev *rtwdev, + struct cfg80211_ssid *ssid); int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, u8 *buf, u32 size); void rtw_reset_rsvd_page(struct rtw_dev *rtwdev); @@ -413,4 +522,8 @@ void rtw_fw_set_aoac_global_info_cmd(struct rtw_dev *rtwdev, u8 pairwise_key_enc, u8 group_key_enc); +void rtw_fw_set_nlo_info(struct rtw_dev *rtwdev, bool enable); +void rtw_fw_update_pkt_probe_req(struct rtw_dev *rtwdev, + struct cfg80211_ssid *ssid); +void rtw_fw_channel_switch(struct rtw_dev *rtwdev, bool enable); #endif diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 1ac48ccdb3c8..3d26c4a6e8da 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -1495,6 +1495,7 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) #ifdef CONFIG_PM hw->wiphy->wowlan = rtwdev->chip->wowlan_stub; + hw->wiphy->max_sched_scan_ssids = rtwdev->chip->max_sched_scan_ssids; #endif rtw_set_supported_band(hw, rtwdev->chip); SET_IEEE80211_PERM_ADDR(hw, rtwdev->efuse.addr); diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 74368ef954fa..4fa17aab3838 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -929,12 +929,24 @@ struct rtw_wow_pattern { u8 mask[RTW_MAX_PATTERN_MASK_SIZE]; }; +struct rtw_pno_request { + bool inited; + u32 match_set_cnt; + struct cfg80211_match_set *match_sets; + u8 channel_cnt; + struct ieee80211_channel *channels; + struct cfg80211_sched_scan_plan scan_plan; +}; + struct rtw_wow_param { struct ieee80211_vif *wow_vif; DECLARE_BITMAP(flags, RTW_WOW_FLAG_MAX); u8 txpause; u8 pattern_cnt; struct rtw_wow_pattern patterns[RTW_MAX_PATTERN_NUM]; + + bool ips_enabled; + struct rtw_pno_request pno_req; }; struct rtw_intf_phy_para_table { @@ -1067,6 +1079,7 @@ struct rtw_chip_info { const char *wow_fw_name; const struct wiphy_wowlan_support *wowlan_stub; + const u8 max_sched_scan_ssids; /* coex paras */ u32 coex_para_ver; @@ -1647,6 +1660,18 @@ static inline struct ieee80211_vif *rtwvif_to_vif(struct rtw_vif *rtwvif) return container_of(p, struct ieee80211_vif, drv_priv); } +static inline bool rtw_ssid_equal(struct cfg80211_ssid *a, + struct cfg80211_ssid *b) +{ + if (!a || !b || a->ssid_len != b->ssid_len) + return false; + + if (memcmp(a->ssid, b->ssid, a->ssid_len)) + return false; + + return true; +} + void rtw_get_channel_params(struct cfg80211_chan_def *chandef, struct rtw_channel_params *ch_param); bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 4836c0044b05..655ca9265f68 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -4063,10 +4063,12 @@ static const struct rtw_pwr_track_tbl rtw8822c_rtw_pwr_track_tbl = { #ifdef CONFIG_PM static const struct wiphy_wowlan_support rtw_wowlan_stub_8822c = { .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_GTK_REKEY_FAILURE | - WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY, + WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_NET_DETECT, .n_patterns = RTW_MAX_PATTERN_NUM, .pattern_max_len = RTW_MAX_PATTERN_SIZE, .pattern_min_len = 1, + .max_nd_match_sets = 4, }; #endif @@ -4119,6 +4121,7 @@ struct rtw_chip_info rtw8822c_hw_spec = { #ifdef CONFIG_PM .wow_fw_name = "rtw88/rtw8822c_wow_fw.bin", .wowlan_stub = &rtw_wowlan_stub_8822c, + .max_sched_scan_ssids = 4, #endif .coex_para_ver = 0x19062706, .bt_desired_ver = 0x6, diff --git a/drivers/net/wireless/realtek/rtw88/wow.c b/drivers/net/wireless/realtek/rtw88/wow.c index f4645f3c98e0..af5c27e1bb07 100644 --- a/drivers/net/wireless/realtek/rtw88/wow.c +++ b/drivers/net/wireless/realtek/rtw88/wow.c @@ -28,6 +28,8 @@ static void rtw_wow_show_wakeup_reason(struct rtw_dev *rtwdev) rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx ptk rekey\n"); else if (reason == RTW_WOW_RSN_RX_PATTERN_MATCH) rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx pattern match packet\n"); + else if (reason == RTW_WOW_RSN_RX_NLO) + rtw_dbg(rtwdev, RTW_DBG_WOW, "Rx NLO\n"); else rtw_warn(rtwdev, "Unknown wakeup reason %x\n", reason); } @@ -362,6 +364,10 @@ static int rtw_wow_fw_start(struct rtw_dev *rtwdev) rtw_wow_fw_security_type(rtwdev); rtw_fw_set_disconnect_decision_cmd(rtwdev, true); rtw_fw_set_keep_alive_cmd(rtwdev, true); + } else if (rtw_wow_no_link(rtwdev)) { + rtw_fw_set_nlo_info(rtwdev, true); + rtw_fw_update_pkt_probe_req(rtwdev, NULL); + rtw_fw_channel_switch(rtwdev, true); } rtw_fw_set_wowlan_ctrl_cmd(rtwdev, true); @@ -376,6 +382,9 @@ static int rtw_wow_fw_stop(struct rtw_dev *rtwdev) rtw_fw_set_disconnect_decision_cmd(rtwdev, false); rtw_fw_set_keep_alive_cmd(rtwdev, false); rtw_wow_pattern_clear(rtwdev); + } else if (rtw_wow_no_link(rtwdev)) { + rtw_fw_channel_switch(rtwdev, false); + rtw_fw_set_nlo_info(rtwdev, false); } rtw_fw_set_wowlan_ctrl_cmd(rtwdev, false); @@ -423,6 +432,22 @@ static void rtw_wow_fw_media_status(struct rtw_dev *rtwdev, bool connect) rtw_iterate_stas_atomic(rtwdev, rtw_wow_fw_media_status_iter, &data); } +static void rtw_wow_config_pno_rsvd_page(struct rtw_dev *rtwdev) +{ + struct rtw_wow_param *rtw_wow = &rtwdev->wow; + struct rtw_pno_request *rtw_pno_req = &rtw_wow->pno_req; + struct cfg80211_ssid *ssid; + int i; + + for (i = 0 ; i < rtw_pno_req->match_set_cnt; i++) { + ssid = &rtw_pno_req->match_sets[i].ssid; + rtw_add_rsvd_page_probe_req(rtwdev, ssid); + } + rtw_add_rsvd_page_probe_req(rtwdev, NULL); + rtw_add_rsvd_page(rtwdev, RSVD_NLO_INFO, false); + rtw_add_rsvd_page(rtwdev, RSVD_CH_INFO, true); +} + static void rtw_wow_config_linked_rsvd_page(struct rtw_dev *rtwdev) { rtw_add_rsvd_page(rtwdev, RSVD_PS_POLL, true); @@ -436,8 +461,12 @@ static void rtw_wow_config_rsvd_page(struct rtw_dev *rtwdev) { rtw_reset_rsvd_page(rtwdev); - if (rtw_wow_mgd_linked(rtwdev)) + if (rtw_wow_mgd_linked(rtwdev)) { rtw_wow_config_linked_rsvd_page(rtwdev); + } else if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags) && + rtw_wow_no_link(rtwdev)) { + rtw_wow_config_pno_rsvd_page(rtwdev); + } } static int rtw_wow_dl_fw_rsvd_page(struct rtw_dev *rtwdev) @@ -480,11 +509,75 @@ out: return ret; } +static void rtw_wow_check_pno(struct rtw_dev *rtwdev, + struct cfg80211_sched_scan_request *nd_config) +{ + struct rtw_wow_param *rtw_wow = &rtwdev->wow; + struct rtw_pno_request *pno_req = &rtw_wow->pno_req; + struct ieee80211_channel *channel; + int i, size; + + if (!nd_config->n_match_sets || !nd_config->n_channels) + goto err; + + pno_req->match_set_cnt = nd_config->n_match_sets; + size = sizeof(*pno_req->match_sets) * pno_req->match_set_cnt; + pno_req->match_sets = kmemdup(nd_config->match_sets, size, GFP_KERNEL); + if (!pno_req->match_sets) + goto err; + + pno_req->channel_cnt = nd_config->n_channels; + size = sizeof(*nd_config->channels[0]) * nd_config->n_channels; + pno_req->channels = kmalloc(size, GFP_KERNEL); + if (!pno_req->channels) + goto channel_err; + + for (i = 0 ; i < pno_req->channel_cnt; i++) { + channel = pno_req->channels + i; + memcpy(channel, nd_config->channels[i], sizeof(*channel)); + } + + pno_req->scan_plan = *nd_config->scan_plans; + pno_req->inited = true; + + rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: net-detect is enabled\n"); + + return; + +channel_err: + kfree(pno_req->match_sets); + +err: + rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: net-detect is disabled\n"); +} + static int rtw_wow_leave_linked_ps(struct rtw_dev *rtwdev) { if (!test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) cancel_delayed_work_sync(&rtwdev->watch_dog_work); + rtw_leave_lps(rtwdev); + + return 0; +} + +static int rtw_wow_leave_no_link_ps(struct rtw_dev *rtwdev) +{ + struct rtw_wow_param *rtw_wow = &rtwdev->wow; + int ret = 0; + + if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) { + if (rtw_fw_lps_deep_mode) + rtw_leave_lps_deep(rtwdev); + } else { + if (test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags)) { + rtw_wow->ips_enabled = true; + ret = rtw_leave_ips(rtwdev); + if (ret) + return ret; + } + } + return 0; } @@ -494,6 +587,18 @@ static int rtw_wow_leave_ps(struct rtw_dev *rtwdev) if (rtw_wow_mgd_linked(rtwdev)) ret = rtw_wow_leave_linked_ps(rtwdev); + else if (rtw_wow_no_link(rtwdev)) + ret = rtw_wow_leave_no_link_ps(rtwdev); + + return ret; +} + +static int rtw_wow_restore_ps(struct rtw_dev *rtwdev) +{ + int ret = 0; + + if (rtw_wow_no_link(rtwdev) && rtwdev->wow.ips_enabled) + ret = rtw_enter_ips(rtwdev); return ret; } @@ -509,12 +614,22 @@ static int rtw_wow_enter_linked_ps(struct rtw_dev *rtwdev) return 0; } +static int rtw_wow_enter_no_link_ps(struct rtw_dev *rtwdev) +{ + /* firmware enters deep ps by itself if supported */ + set_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags); + + return 0; +} + static int rtw_wow_enter_ps(struct rtw_dev *rtwdev) { int ret = 0; if (rtw_wow_mgd_linked(rtwdev)) ret = rtw_wow_enter_linked_ps(rtwdev); + else if (rtw_wow_no_link(rtwdev) && rtw_fw_lps_deep_mode) + ret = rtw_wow_enter_no_link_ps(rtwdev); return ret; } @@ -653,6 +768,10 @@ static void rtw_wow_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) case RTW_NET_MGD_LINKED: rtw_wow->wow_vif = vif; break; + case RTW_NET_NO_LINK: + if (rtw_wow->pno_req.inited) + rtwdev->wow.wow_vif = vif; + break; default: break; } @@ -673,6 +792,9 @@ static int rtw_wow_set_wakeups(struct rtw_dev *rtwdev, if (wowlan->gtk_rekey_failure) set_bit(RTW_WOW_FLAG_EN_REKEY_PKT, rtw_wow->flags); + if (wowlan->nd_config) + rtw_wow_check_pno(rtwdev, wowlan->nd_config); + rtw_iterate_vifs_atomic(rtwdev, rtw_wow_vif_iter, rtwdev); if (!rtw_wow->wow_vif) return -EPERM; @@ -692,6 +814,12 @@ static int rtw_wow_set_wakeups(struct rtw_dev *rtwdev, static void rtw_wow_clear_wakeups(struct rtw_dev *rtwdev) { struct rtw_wow_param *rtw_wow = &rtwdev->wow; + struct rtw_pno_request *pno_req = &rtw_wow->pno_req; + + if (pno_req->inited) { + kfree(pno_req->channels); + kfree(pno_req->match_sets); + } memset(rtw_wow, 0, sizeof(rtwdev->wow)); } @@ -715,6 +843,7 @@ int rtw_wow_suspend(struct rtw_dev *rtwdev, struct cfg80211_wowlan *wowlan) ret = rtw_wow_enable(rtwdev); if (ret) { rtw_err(rtwdev, "failed to enable wow\n"); + rtw_wow_restore_ps(rtwdev); goto out; } @@ -746,8 +875,14 @@ int rtw_wow_resume(struct rtw_dev *rtwdev) rtw_wow_show_wakeup_reason(rtwdev); ret = rtw_wow_disable(rtwdev); - if (ret) + if (ret) { rtw_err(rtwdev, "failed to disable wow\n"); + goto out; + } + + ret = rtw_wow_restore_ps(rtwdev); + if (ret) + rtw_err(rtwdev, "failed to restore ps to normal mode\n"); out: rtw_wow_clear_wakeups(rtwdev); diff --git a/drivers/net/wireless/realtek/rtw88/wow.h b/drivers/net/wireless/realtek/rtw88/wow.h index 54f742f4c955..289368a2cba4 100644 --- a/drivers/net/wireless/realtek/rtw88/wow.h +++ b/drivers/net/wireless/realtek/rtw88/wow.h @@ -5,6 +5,8 @@ #ifndef __RTW_WOW_H__ #define __RTW_WOW_H__ +#define PNO_CHECK_BYTE 4 + enum rtw_wow_pattern_type { RTW_PATTERN_BROADCAST = 0, RTW_PATTERN_MULTICAST, @@ -20,6 +22,7 @@ enum rtw_wake_reason { RTW_WOW_RSN_DISCONNECT = 0x10, RTW_WOW_RSN_RX_MAGIC_PKT = 0x21, RTW_WOW_RSN_RX_PATTERN_MATCH = 0x23, + RTW_WOW_RSN_RX_NLO = 0x55, }; struct rtw_fw_media_status_iter_data { @@ -41,6 +44,14 @@ static inline bool rtw_wow_mgd_linked(struct rtw_dev *rtwdev) return (rtwvif->net_type == RTW_NET_MGD_LINKED); } +static inline bool rtw_wow_no_link(struct rtw_dev *rtwdev) +{ + struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; + struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv; + + return (rtwvif->net_type == RTW_NET_NO_LINK); +} + int rtw_wow_suspend(struct rtw_dev *rtwdev, struct cfg80211_wowlan *wowlan); int rtw_wow_resume(struct rtw_dev *rtwdev); From 35a68fa5f96a80797e11b6952a47c5a84939a7bf Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 20 Dec 2019 17:21:46 +0800 Subject: [PATCH 59/96] rtw88: fix rate mask for 1SS chip The rate mask is used to tell firmware the supported rate depends on negotiation. We loop 2 times for all VHT/HT 2SS rate mask first, and then only keep the part according to chip's NSS. This commit fixes the logic error of '&' operations for VHT/HT rate, and we should run this logic before adding legacy rate. To access HT MCS map, index 0/1 represent MCS 0-7/8-15 respectively. Use NL80211_BAND_xxx is incorrect, so fix it as well. Signed-off-by: Ping-Ke Shih Signed-off-by: Yan-Hsuan Chuang Reviewed-by: Chris Chiu Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/main.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 3d26c4a6e8da..9144b2696618 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -706,8 +706,8 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) is_support_sgi = true; } else if (sta->ht_cap.ht_supported) { - ra_mask |= (sta->ht_cap.mcs.rx_mask[NL80211_BAND_5GHZ] << 20) | - (sta->ht_cap.mcs.rx_mask[NL80211_BAND_2GHZ] << 12); + ra_mask |= (sta->ht_cap.mcs.rx_mask[1] << 20) | + (sta->ht_cap.mcs.rx_mask[0] << 12); if (sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) stbc_en = HT_STBC_EN; if (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING) @@ -717,6 +717,9 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) is_support_sgi = true; } + if (efuse->hw_cap.nss == 1) + ra_mask &= RA_MASK_VHT_RATES_1SS | RA_MASK_HT_RATES_1SS; + if (hal->current_band_type == RTW_BAND_5G) { ra_mask |= (u64)sta->supp_rates[NL80211_BAND_5GHZ] << 4; if (sta->vht_cap.vht_supported) { @@ -750,11 +753,6 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) wireless_set = 0; } - if (efuse->hw_cap.nss == 1) { - ra_mask &= RA_MASK_VHT_RATES_1SS; - ra_mask &= RA_MASK_HT_RATES_1SS; - } - switch (sta->bandwidth) { case IEEE80211_STA_RX_BW_80: bw_mode = RTW_CHANNEL_WIDTH_80; From 73a2d0b83424f7150a1f607470dac67c95b8b2d4 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 20 Dec 2019 17:21:47 +0800 Subject: [PATCH 60/96] rtw88: fix TX secondary channel offset of 40M if current bw is 20M or 40M TX secondary channel offset is valid only if current bandwidth is 80M, otherwise leave this value as zero. The wrong value of txsc40 causes MAC unpredictable behavior. Signed-off-by: Ping-Ke Shih Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/mac.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index 03a82de053ea..cadf0abbe16b 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -16,10 +16,12 @@ void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw, u8 value8; txsc20 = primary_ch_idx; - if (txsc20 == 1 || txsc20 == 3) - txsc40 = 9; - else - txsc40 = 10; + if (bw == RTW_CHANNEL_WIDTH_80) { + if (txsc20 == 1 || txsc20 == 3) + txsc40 = 9; + else + txsc40 = 10; + } rtw_write8(rtwdev, REG_DATA_SC, BIT_TXSC_20M(txsc20) | BIT_TXSC_40M(txsc40)); From e339b649352437c529616daa0c15db04c76f0e85 Mon Sep 17 00:00:00 2001 From: Tzu-En Huang Date: Fri, 20 Dec 2019 17:21:49 +0800 Subject: [PATCH 61/96] rtw88: 8822c: update power sequence to v15 Update card enable power sequence flow, to fix CMD11 fail after reboot and wrong PLL clock. Signed-off-by: Tzu-En Huang Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/rtw8822c.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 655ca9265f68..3865097696d4 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -3487,12 +3487,12 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822c[] = { RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, RTW_PWR_ADDR_MAC, - RTW_PWR_CMD_WRITE, BIT(7), 0}, - {0x0005, + RTW_PWR_CMD_WRITE, (BIT(4) | BIT(3)), 0}, + {0x1018, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, RTW_PWR_ADDR_MAC, - RTW_PWR_CMD_WRITE, (BIT(4) | BIT(3)), 0}, + RTW_PWR_CMD_WRITE, BIT(2), BIT(2)}, {0x0005, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, From 3f43f10bd619b1acebb570bebf989265920aeb27 Mon Sep 17 00:00:00 2001 From: Tzu-En Huang Date: Fri, 20 Dec 2019 17:21:51 +0800 Subject: [PATCH 62/96] rtw88: remove unused spinlock dm_lock is never used. Thus, remove this redundant spinlock. Signed-off-by: Tzu-En Huang Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/main.c | 1 - drivers/net/wireless/realtek/rtw88/main.h | 3 --- 2 files changed, 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 9144b2696618..2a60f8333df0 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -1376,7 +1376,6 @@ int rtw_core_init(struct rtw_dev *rtwdev) skb_queue_head_init(&rtwdev->coex.queue); skb_queue_head_init(&rtwdev->tx_report.queue); - spin_lock_init(&rtwdev->dm_lock); spin_lock_init(&rtwdev->rf_lock); spin_lock_init(&rtwdev->h2c.lock); spin_lock_init(&rtwdev->txq_lock); diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 4fa17aab3838..0c9bac08ebf7 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -1586,9 +1586,6 @@ struct rtw_dev { /* ensures exclusive access from mac80211 callbacks */ struct mutex mutex; - /* lock for dm to use */ - spinlock_t dm_lock; - /* read/write rf register */ spinlock_t rf_lock; From 962562cde15463f712e9cc007086f6140930199d Mon Sep 17 00:00:00 2001 From: Yan-Hsuan Chuang Date: Fri, 20 Dec 2019 17:21:52 +0800 Subject: [PATCH 63/96] rtw88: remove unused variable 'in_lps' Unused, will not be used neither, because the hardware/firmware can only support one vif for LPS currnetly. If there's more than one vif, than driver will never enter LPS. So remove it. Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/mac80211.c | 1 - drivers/net/wireless/realtek/rtw88/main.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index 1150e42539a9..c8be4b4a9371 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -158,7 +158,6 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw, rtwvif->stats.rx_unicast = 0; rtwvif->stats.tx_cnt = 0; rtwvif->stats.rx_cnt = 0; - rtwvif->in_lps = false; memset(&rtwvif->bfee, 0, sizeof(struct rtw_bfee)); rtwvif->conf = &rtw_vif_port[port]; rtw_txq_init(rtwdev, vif->txq); diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 0c9bac08ebf7..107b17c86f9f 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -747,7 +747,6 @@ struct rtw_vif { const struct rtw_vif_port *conf; struct rtw_traffic_stats stats; - bool in_lps; struct rtw_bfee bfee; }; From 65ae64d375751cad79c6e74222d348f72e310e4c Mon Sep 17 00:00:00 2001 From: Yan-Hsuan Chuang Date: Fri, 20 Dec 2019 17:21:53 +0800 Subject: [PATCH 64/96] rtw88: remove unused vif pointer in struct rtw_vif As driver can easily get vif with container_of(), we can just remove it. Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/mac80211.c | 1 - drivers/net/wireless/realtek/rtw88/main.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index c8be4b4a9371..6fc33e11d08c 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -153,7 +153,6 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw, u8 bcn_ctrl = 0; rtwvif->port = port; - rtwvif->vif = vif; rtwvif->stats.tx_unicast = 0; rtwvif->stats.rx_unicast = 0; rtwvif->stats.tx_cnt = 0; diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 107b17c86f9f..f334d201bfb5 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -736,7 +736,6 @@ struct rtw_bf_info { }; struct rtw_vif { - struct ieee80211_vif *vif; enum rtw_net_type net_type; u16 aid; u8 mac_addr[ETH_ALEN]; From fc83c616d4d95c386e2bac7994b635b24662bca4 Mon Sep 17 00:00:00 2001 From: Chin-Yen Lee Date: Fri, 20 Dec 2019 17:21:54 +0800 Subject: [PATCH 65/96] rtw88: use rtw_hci_stop() instead of rtwdev->hci.ops->stop() Fix typo, should use rtw_hci_stop() Signed-off-by: Chin-Yen Lee Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 2a60f8333df0..2845d2838f7b 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -898,7 +898,7 @@ int rtw_core_start(struct rtw_dev *rtwdev) static void rtw_power_off(struct rtw_dev *rtwdev) { - rtwdev->hci.ops->stop(rtwdev); + rtw_hci_stop(rtwdev); rtw_mac_power_off(rtwdev); } From f48abf064ade7a08015bc3a50a873437375843b2 Mon Sep 17 00:00:00 2001 From: Yan-Hsuan Chuang Date: Fri, 20 Dec 2019 17:21:55 +0800 Subject: [PATCH 66/96] rtw88: assign NULL to skb after being kfree()'ed Should assign NULL to skb after kfree(), in case of driver trying to free the same skb again. This could happen if driver failed to allocate an skb when building reserved page. Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/fw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index e3e91ae0d3d2..243441453ead 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -1139,13 +1139,16 @@ static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, page += rtw_len_to_page(rsvd_pkt->skb->len, page_size); kfree_skb(rsvd_pkt->skb); + rsvd_pkt->skb = NULL; } return buf; release_skb: - list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { kfree_skb(rsvd_pkt->skb); + rsvd_pkt->skb = NULL; + } return NULL; } From bbdd1d854e0a97b771ab642fc07992b28e853036 Mon Sep 17 00:00:00 2001 From: Zong-Zhe Yang Date: Fri, 20 Dec 2019 17:21:56 +0800 Subject: [PATCH 67/96] rtw88: change max_num_of_tx_queue() definition to inline in pci.h It's more reasonable to define max_num_of_tx_queue() as an inline function. Signed-off-by: Zong-Zhe Yang Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/pci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw88/pci.h b/drivers/net/wireless/realtek/rtw88/pci.h index 49bf29a92152..1580cfc57361 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.h +++ b/drivers/net/wireless/realtek/rtw88/pci.h @@ -210,7 +210,7 @@ struct rtw_pci { void __iomem *mmap; }; -static u32 max_num_of_tx_queue(u8 queue) +static inline u32 max_num_of_tx_queue(u8 queue) { u32 max_num; From fd156bdf62bb06271084f45eff9384b24f734fd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 23 Dec 2019 13:37:07 +0100 Subject: [PATCH 68/96] rtlwifi: rtl8192cu: Fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace USB_VENDER_ID_REALTEK with USB_VENDOR_ID_REALTEK. Signed-off-by: Amadeusz Sławiński Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8192cu/sw.c | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c index ab3e4aebad39..6b954059e830 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c @@ -252,45 +252,45 @@ static struct rtl_hal_cfg rtl92cu_hal_cfg = { .maps[RTL_RC_HT_RATEMCS15] = DESC_RATEMCS15, }; -#define USB_VENDER_ID_REALTEK 0x0bda +#define USB_VENDOR_ID_REALTEK 0x0bda /* 2010-10-19 DID_USB_V3.4 */ static const struct usb_device_id rtl8192c_usb_ids[] = { /*=== Realtek demoboard ===*/ /* Default ID */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8191, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8191, rtl92cu_hal_cfg)}, /****** 8188CU ********/ /* RTL8188CTV */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x018a, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x018a, rtl92cu_hal_cfg)}, /* 8188CE-VAU USB minCard */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8170, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8170, rtl92cu_hal_cfg)}, /* 8188cu 1*1 dongle */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8176, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8176, rtl92cu_hal_cfg)}, /* 8188cu 1*1 dongle, (b/g mode only) */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8177, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8177, rtl92cu_hal_cfg)}, /* 8188cu Slim Solo */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817a, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x817a, rtl92cu_hal_cfg)}, /* 8188cu Slim Combo */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817b, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x817b, rtl92cu_hal_cfg)}, /* 8188RU High-power USB Dongle */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817d, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x817d, rtl92cu_hal_cfg)}, /* 8188CE-VAU USB minCard (b/g mode only) */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817e, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x817e, rtl92cu_hal_cfg)}, /* 8188RU in Alfa AWUS036NHR */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)}, /* RTL8188CUS-VL */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x818a, rtl92cu_hal_cfg)}, - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x819a, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x818a, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x819a, rtl92cu_hal_cfg)}, /* 8188 Combo for BC4 */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)}, /****** 8192CU ********/ /* 8192cu 2*2 */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8178, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8178, rtl92cu_hal_cfg)}, /* 8192CE-VAU USB minCard */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817c, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x817c, rtl92cu_hal_cfg)}, /*=== Customer ID ===*/ /****** 8188CU ********/ @@ -329,7 +329,7 @@ static const struct usb_device_id rtl8192c_usb_ids[] = { /****** 8188 RU ********/ /* Netcore */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x317f, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x317f, rtl92cu_hal_cfg)}, /****** 8188CUS Slim Solo********/ {RTL_USB_DEVICE(0x04f2, 0xaff7, rtl92cu_hal_cfg)}, /*Xavi*/ From 5d3f9145f54ee81b33752f68285eb15ef644e08a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 23 Dec 2019 13:37:08 +0100 Subject: [PATCH 69/96] rtlwifi: rtl8188ee: Make functions static & rm sw.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of functions which were exposed in sw.h, are only used in sw.c, so just make them static. This makes sw.h unnecessary, so remove it. Signed-off-by: Amadeusz Sławiński Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c | 7 +++---- drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h | 12 ------------ 2 files changed, 3 insertions(+), 16 deletions(-) delete mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c index a0eda51e833c..4865639ac9ea 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c @@ -9,7 +9,6 @@ #include "phy.h" #include "dm.h" #include "hw.h" -#include "sw.h" #include "trx.h" #include "led.h" #include "table.h" @@ -59,7 +58,7 @@ static void rtl88e_init_aspm_vars(struct ieee80211_hw *hw) rtlpci->const_support_pciaspm = rtlpriv->cfg->mod_params->aspm_support; } -int rtl88e_init_sw_vars(struct ieee80211_hw *hw) +static int rtl88e_init_sw_vars(struct ieee80211_hw *hw) { int err = 0; struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -173,7 +172,7 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw) return err; } -void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw) +static void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -189,7 +188,7 @@ void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw) } /* get bt coexist status */ -bool rtl88e_get_btc_status(void) +static bool rtl88e_get_btc_status(void) { return false; } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h deleted file mode 100644 index 1407151503f8..000000000000 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2009-2013 Realtek Corporation.*/ - -#ifndef __RTL92CE_SW_H__ -#define __RTL92CE_SW_H__ - -int rtl88e_init_sw_vars(struct ieee80211_hw *hw); -void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw); -bool rtl88e_get_btc_status(void); - - -#endif From be913e3f49ac943c230dca5de40974f3a5f7ae90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 23 Dec 2019 13:37:09 +0100 Subject: [PATCH 70/96] rtlwifi: rtl8192ce: Make functions static & rm sw.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of functions which were exposed in sw.h, are only used in sw.c, so just make them static. The rtl92c_init_var_map function is not defined anywhere, while declared in sw.h. Two other functions are also declared in phy.h (which is included in sw.c) and their definitions are in phy.c Overall sw.h is unnecessary and can be removed. Signed-off-by: Amadeusz Sławiński Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8192ce/sw.c | 5 ++--- .../net/wireless/realtek/rtlwifi/rtl8192ce/sw.h | 15 --------------- 2 files changed, 2 insertions(+), 18 deletions(-) delete mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c index 900788e4018c..ed68c850f9a2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c @@ -14,7 +14,6 @@ #include "../rtl8192c/phy_common.h" #include "hw.h" #include "rf.h" -#include "sw.h" #include "trx.h" #include "led.h" @@ -65,7 +64,7 @@ static void rtl92c_init_aspm_vars(struct ieee80211_hw *hw) rtlpci->const_support_pciaspm = rtlpriv->cfg->mod_params->aspm_support; } -int rtl92c_init_sw_vars(struct ieee80211_hw *hw) +static int rtl92c_init_sw_vars(struct ieee80211_hw *hw) { int err; struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -161,7 +160,7 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) return 0; } -void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw) +static void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h deleted file mode 100644 index f2d121a60159..000000000000 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2009-2012 Realtek Corporation.*/ - -#ifndef __RTL92CE_SW_H__ -#define __RTL92CE_SW_H__ - -int rtl92c_init_sw_vars(struct ieee80211_hw *hw); -void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw); -void rtl92c_init_var_map(struct ieee80211_hw *hw); -bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); -bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype); - -#endif From a3cda3c363ca747758a3bcc6fc23529003a1c983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 23 Dec 2019 13:37:10 +0100 Subject: [PATCH 71/96] rtlwifi: rtl8192cu: Remove sw.h header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It has one define, which is already defined in include from reg.h. All functions are declared in their own headers and included in *.c files belonging to them. This makes sw.h unnecessary, so we can remove it. Signed-off-by: Amadeusz Sławiński Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8192cu/sw.c | 1 - .../wireless/realtek/rtlwifi/rtl8192cu/sw.h | 27 ------------------- 2 files changed, 28 deletions(-) delete mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c index 6b954059e830..b53daf1b29f7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c @@ -12,7 +12,6 @@ #include "mac.h" #include "dm.h" #include "rf.h" -#include "sw.h" #include "trx.h" #include "led.h" #include "hw.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h deleted file mode 100644 index 662440c4cdc9..000000000000 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2009-2012 Realtek Corporation.*/ - -#ifndef __RTL92CU_SW_H__ -#define __RTL92CU_SW_H__ - -#define EFUSE_MAX_SECTION 16 - -void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *powerlevel); -void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); -bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); -bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype); -void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); -void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data); -bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); -u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask); -void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw); - -#endif From fef8a2d969af25638f48411930f491088d6ccea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 23 Dec 2019 13:37:11 +0100 Subject: [PATCH 72/96] rtlwifi: rtl8192ee: Make functions static & rm sw.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of functions which were exposed in sw.h, are only used in sw.c, so just make them static. This makes sw.h unnecessary, so remove it. Signed-off-by: Amadeusz Sławiński Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c | 7 +++---- drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h | 11 ----------- 2 files changed, 3 insertions(+), 15 deletions(-) delete mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c index b6ee7dae5943..b337d599b6f4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c @@ -9,7 +9,6 @@ #include "phy.h" #include "dm.h" #include "hw.h" -#include "sw.h" #include "fw.h" #include "trx.h" #include "led.h" @@ -65,7 +64,7 @@ static void rtl92ee_init_aspm_vars(struct ieee80211_hw *hw) rtlpci->const_support_pciaspm = rtlpriv->cfg->mod_params->aspm_support; } -int rtl92ee_init_sw_vars(struct ieee80211_hw *hw) +static int rtl92ee_init_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); @@ -164,7 +163,7 @@ int rtl92ee_init_sw_vars(struct ieee80211_hw *hw) return 0; } -void rtl92ee_deinit_sw_vars(struct ieee80211_hw *hw) +static void rtl92ee_deinit_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -175,7 +174,7 @@ void rtl92ee_deinit_sw_vars(struct ieee80211_hw *hw) } /* get bt coexist status */ -bool rtl92ee_get_btc_status(void) +static bool rtl92ee_get_btc_status(void) { return true; } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h deleted file mode 100644 index 36e29a2da0fd..000000000000 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2009-2014 Realtek Corporation.*/ - -#ifndef __RTL92E_SW_H__ -#define __RTL92E_SW_H__ - -int rtl92ee_init_sw_vars(struct ieee80211_hw *hw); -void rtl92ee_deinit_sw_vars(struct ieee80211_hw *hw); -bool rtl92ee_get_btc_status(void); - -#endif From 5b2640835a3443e629ee2af4b8367f6abdeb142a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 23 Dec 2019 13:37:12 +0100 Subject: [PATCH 73/96] rtlwifi: rtl8192se: Remove sw.h header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It has one define, which is already defined in include from reg.h. All the declared functions are not implemented anywhere, sw.c has ones with similar names which are already static. Signed-off-by: Amadeusz Sławiński Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c | 1 - drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h | 13 ------------- 2 files changed, 14 deletions(-) delete mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c index 1c7ee569f4bf..7a54497b7df2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c @@ -11,7 +11,6 @@ #include "dm.h" #include "fw.h" #include "hw.h" -#include "sw.h" #include "trx.h" #include "led.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h deleted file mode 100644 index a31efba0e6b5..000000000000 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2009-2012 Realtek Corporation.*/ - -#ifndef __REALTEK_PCI92SE_SW_H__ -#define __REALTEK_PCI92SE_SW_H__ - -#define EFUSE_MAX_SECTION 16 - -int rtl92se_init_sw(struct ieee80211_hw *hw); -void rtl92se_deinit_sw(struct ieee80211_hw *hw); -void rtl92se_init_var_map(struct ieee80211_hw *hw); - -#endif From c218acfaa637d02830549cf27798921f820ec818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 23 Dec 2019 13:37:13 +0100 Subject: [PATCH 74/96] rtlwifi: rtl8723ae: Make functions static & rm sw.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of functions which were exposed in sw.h, are only used in sw.c, so just make them static. This makes sw.h unnecessary, so remove it. Signed-off-by: Amadeusz Sławiński Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c | 7 +++---- drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h | 13 ------------- 2 files changed, 3 insertions(+), 17 deletions(-) delete mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c index 5702ac6deebf..ea86d5bf33d2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c @@ -11,7 +11,6 @@ #include "fw.h" #include "../rtl8723com/fw_common.h" #include "hw.h" -#include "sw.h" #include "trx.h" #include "led.h" #include "table.h" @@ -67,7 +66,7 @@ static void rtl8723e_init_aspm_vars(struct ieee80211_hw *hw) rtlpci->const_support_pciaspm = rtlpriv->cfg->mod_params->aspm_support; } -int rtl8723e_init_sw_vars(struct ieee80211_hw *hw) +static int rtl8723e_init_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); @@ -166,7 +165,7 @@ int rtl8723e_init_sw_vars(struct ieee80211_hw *hw) return 0; } -void rtl8723e_deinit_sw_vars(struct ieee80211_hw *hw) +static void rtl8723e_deinit_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -177,7 +176,7 @@ void rtl8723e_deinit_sw_vars(struct ieee80211_hw *hw) } /* get bt coexist status */ -bool rtl8723e_get_btc_status(void) +static bool rtl8723e_get_btc_status(void) { return true; } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h deleted file mode 100644 index 200ce39a0dd7..000000000000 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2009-2012 Realtek Corporation.*/ - -#ifndef __RTL8723E_SW_H__ -#define __RTL8723E_SW_H__ - -int rtl8723e_init_sw_vars(struct ieee80211_hw *hw); -void rtl8723e_deinit_sw_vars(struct ieee80211_hw *hw); -void rtl8723e_init_var_map(struct ieee80211_hw *hw); -bool rtl8723e_get_btc_status(void); - - -#endif From 02a214e29ea4415437d9e38c6bf5604e564397da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 23 Dec 2019 13:37:14 +0100 Subject: [PATCH 75/96] rtlwifi: rtl8723be: Make functions static & rm sw.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of functions which were exposed in sw.h, are only used in sw.c, so just make them static. This makes sw.h unnecessary, so remove it. Signed-off-by: Amadeusz Sławiński Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c | 7 +++---- drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h | 13 ------------- 2 files changed, 3 insertions(+), 17 deletions(-) delete mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c index 3c8528f0ecb3..36209ac5b208 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c @@ -13,7 +13,6 @@ #include "hw.h" #include "fw.h" #include "../rtl8723com/fw_common.h" -#include "sw.h" #include "trx.h" #include "led.h" #include "table.h" @@ -64,7 +63,7 @@ static void rtl8723be_init_aspm_vars(struct ieee80211_hw *hw) rtlpci->const_support_pciaspm = rtlpriv->cfg->mod_params->aspm_support; } -int rtl8723be_init_sw_vars(struct ieee80211_hw *hw) +static int rtl8723be_init_sw_vars(struct ieee80211_hw *hw) { int err = 0; struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -170,7 +169,7 @@ int rtl8723be_init_sw_vars(struct ieee80211_hw *hw) return 0; } -void rtl8723be_deinit_sw_vars(struct ieee80211_hw *hw) +static void rtl8723be_deinit_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -181,7 +180,7 @@ void rtl8723be_deinit_sw_vars(struct ieee80211_hw *hw) } /* get bt coexist status */ -bool rtl8723be_get_btc_status(void) +static bool rtl8723be_get_btc_status(void) { return true; } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h deleted file mode 100644 index 6ecacf9fbfd7..000000000000 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2009-2014 Realtek Corporation.*/ - -#ifndef __RTL8723BE_SW_H__ -#define __RTL8723BE_SW_H__ - -int rtl8723be_init_sw_vars(struct ieee80211_hw *hw); -void rtl8723be_deinit_sw_vars(struct ieee80211_hw *hw); -void rtl8723be_init_var_map(struct ieee80211_hw *hw); -bool rtl8723be_get_btc_status(void); - - -#endif From 8ddd4a2a6b5930b8318b994e416db4491795a8aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 23 Dec 2019 13:37:15 +0100 Subject: [PATCH 76/96] rtlwifi: rtl8821ae: Make functions static & rm sw.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of functions which were exposed in sw.h, are only used in sw.c, so just make them static. This makes sw.h unnecessary, so remove it. Signed-off-by: Amadeusz Sławiński Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c | 7 +++---- drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h | 12 ------------ 2 files changed, 3 insertions(+), 16 deletions(-) delete mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c index 3def6a2b3450..d8df816753cb 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c @@ -10,7 +10,6 @@ #include "dm.h" #include "hw.h" #include "fw.h" -#include "sw.h" #include "trx.h" #include "led.h" #include "table.h" @@ -65,7 +64,7 @@ static void rtl8821ae_init_aspm_vars(struct ieee80211_hw *hw) } /*InitializeVariables8812E*/ -int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw) +static int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw) { int err = 0; struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -211,7 +210,7 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw) return 0; } -void rtl8821ae_deinit_sw_vars(struct ieee80211_hw *hw) +static void rtl8821ae_deinit_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -228,7 +227,7 @@ void rtl8821ae_deinit_sw_vars(struct ieee80211_hw *hw) } /* get bt coexist status */ -bool rtl8821ae_get_btc_status(void) +static bool rtl8821ae_get_btc_status(void) { return true; } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h deleted file mode 100644 index 9d7610f84b20..000000000000 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2009-2010 Realtek Corporation.*/ - -#ifndef __RTL8821AE_SW_H__ -#define __RTL8821AE_SW_H__ - -int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw); -void rtl8821ae_deinit_sw_vars(struct ieee80211_hw *hw); -void rtl8821ae_init_var_map(struct ieee80211_hw *hw); -bool rtl8821ae_get_btc_status(void); - -#endif From 891984bccf64138cb721f87abae838af5636281a Mon Sep 17 00:00:00 2001 From: zhengbin Date: Tue, 24 Dec 2019 22:16:01 +0800 Subject: [PATCH 77/96] rtw88: use true,false for bool variable Fixes coccicheck warning: drivers/net/wireless/realtek/rtw88/phy.c:1437:1-24: WARNING: Assignment of 0/1 to bool variable Reported-by: Hulk Robot Signed-off-by: zhengbin Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index a3e1e9578b65..eea9d888fbf1 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -1434,7 +1434,7 @@ static void rtw_load_rfk_table(struct rtw_dev *rtwdev) rtw_load_table(rtwdev, chip->rfk_init_tbl); - dpk_info->is_dpk_pwr_on = 1; + dpk_info->is_dpk_pwr_on = true; } void rtw_phy_load_tables(struct rtw_dev *rtwdev) From ab36bb72d00e24ae637a87ce8cde568435322a56 Mon Sep 17 00:00:00 2001 From: zhengbin Date: Tue, 24 Dec 2019 22:16:02 +0800 Subject: [PATCH 78/96] cw1200: use true,false for bool variable Fixes coccicheck warning: drivers/net/wireless/st/cw1200/txrx.c:718:6-16: WARNING: Assignment of 0/1 to bool variable Reported-by: Hulk Robot Signed-off-by: zhengbin Signed-off-by: Kalle Valo --- drivers/net/wireless/st/cw1200/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/st/cw1200/txrx.c b/drivers/net/wireless/st/cw1200/txrx.c index 2dfcdb145944..400dd585916b 100644 --- a/drivers/net/wireless/st/cw1200/txrx.c +++ b/drivers/net/wireless/st/cw1200/txrx.c @@ -715,7 +715,7 @@ void cw1200_tx(struct ieee80211_hw *dev, }; struct ieee80211_sta *sta; struct wsm_tx *wsm; - bool tid_update = 0; + bool tid_update = false; u8 flags = 0; int ret; From b92c017deda819e45a0f054f6df6b53e645d7fe4 Mon Sep 17 00:00:00 2001 From: zhengbin Date: Tue, 24 Dec 2019 22:16:06 +0800 Subject: [PATCH 79/96] brcmfmac: use true,false for bool variable Fixes coccicheck warning: drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c:911:2-24: WARNING: Assignment of 0/1 to bool variable Reported-by: Hulk Robot Signed-off-by: zhengbin Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index 2bd892df83cc..5e1a11c07551 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -908,7 +908,7 @@ static u8 brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) wlh += wlh[1] + 2; if (entry->send_tim_signal) { - entry->send_tim_signal = 0; + entry->send_tim_signal = false; wlh[0] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP; wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; wlh[2] = entry->mac_handle; From 8c8e60fb86a90a30721bbd797f58f96b3980dcc1 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Thu, 26 Dec 2019 10:20:33 +0100 Subject: [PATCH 80/96] brcmfmac: sdio: Fix OOB interrupt initialization on brcm43362 Commit 262f2b53f679 ("brcmfmac: call brcmf_attach() just before calling brcmf_bus_started()") changed the initialization order of the brcmfmac SDIO driver. Unfortunately since brcmf_sdiod_intr_register() is now called before the sdiodev->bus_if initialization, it reads the wrong chip ID and fails to initialize the GPIO on brcm43362. Thus the chip cannot send interrupts and fails to probe: [ 12.517023] brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout [ 12.531214] ieee80211 phy0: brcmf_bus_started: failed: -110 [ 12.536976] ieee80211 phy0: brcmf_attach: dongle is not responding: err=-110 [ 12.566467] brcmfmac: brcmf_sdio_firmware_callback: brcmf_attach failed Initialize the bus interface earlier to ensure that brcmf_sdiod_intr_register() properly sets up the OOB interrupt. BugLink: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=908438 Fixes: 262f2b53f679 ("brcmfmac: call brcmf_attach() just before calling brcmf_bus_started()") Signed-off-by: Jean-Philippe Brucker Reviewed-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index f9df95bc7fa1..f9047db6a11d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -4243,6 +4243,12 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err, } if (err == 0) { + /* Assign bus interface call back */ + sdiod->bus_if->dev = sdiod->dev; + sdiod->bus_if->ops = &brcmf_sdio_bus_ops; + sdiod->bus_if->chip = bus->ci->chip; + sdiod->bus_if->chiprev = bus->ci->chiprev; + /* Allow full data communication using DPC from now on. */ brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA); @@ -4259,12 +4265,6 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err, sdio_release_host(sdiod->func1); - /* Assign bus interface call back */ - sdiod->bus_if->dev = sdiod->dev; - sdiod->bus_if->ops = &brcmf_sdio_bus_ops; - sdiod->bus_if->chip = bus->ci->chip; - sdiod->bus_if->chiprev = bus->ci->chiprev; - err = brcmf_alloc(sdiod->dev, sdiod->settings); if (err) { brcmf_err("brcmf_alloc failed\n"); From 24332f8068ff6df7f16aefee45d514de1de4de80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 26 Dec 2019 14:30:49 +0100 Subject: [PATCH 81/96] brcmfmac: simplify building interface combinations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move similar/duplicated code out of combination specific code blocks. This simplifies code a bit and allows adding more combinations later. A list of combinations remains unchanged. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 43 ++++++------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 6eb3064c3721..3ecb91aa765e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -6547,12 +6547,13 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) struct ieee80211_iface_limit *c0_limits = NULL; struct ieee80211_iface_limit *p2p_limits = NULL; struct ieee80211_iface_limit *mbss_limits = NULL; - bool mbss, p2p, rsdb; + bool mbss, p2p, rsdb, mchan; int i, c, n_combos; mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS); p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P); rsdb = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB); + mchan = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN); n_combos = 1 + !!(p2p && !rsdb) + !!mbss; combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL); @@ -6562,6 +6563,10 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); + if (p2p) + wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_P2P_DEVICE); c = 0; i = 0; @@ -6573,48 +6578,28 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) c0_limits = kcalloc(2, sizeof(*c0_limits), GFP_KERNEL); if (!c0_limits) goto err; - if (p2p && rsdb) { - combo[c].num_different_channels = 2; - wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO) | - BIT(NL80211_IFTYPE_P2P_DEVICE); - c0_limits[i].max = 2; - c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); + + combo[c].num_different_channels = 1 + (rsdb || (p2p && mchan)); + c0_limits[i].max = 1 + rsdb; + c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); + if (p2p) { c0_limits[i].max = 1; c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); - c0_limits[i].max = 2; + c0_limits[i].max = 1 + rsdb; c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO); + } + if (p2p && rsdb) { c0_limits[i].max = 2; c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); combo[c].max_interfaces = 5; } else if (p2p) { - if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) - combo[c].num_different_channels = 2; - else - combo[c].num_different_channels = 1; - c0_limits[i].max = 1; - c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); - wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO) | - BIT(NL80211_IFTYPE_P2P_DEVICE); - c0_limits[i].max = 1; - c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); - c0_limits[i].max = 1; - c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO); combo[c].max_interfaces = i; } else if (rsdb) { - combo[c].num_different_channels = 2; - c0_limits[i].max = 2; - c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); c0_limits[i].max = 2; c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); combo[c].max_interfaces = 3; } else { - combo[c].num_different_channels = 1; - c0_limits[i].max = 1; - c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); c0_limits[i].max = 1; c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); combo[c].max_interfaces = i; From 20f2c5fa3af060401c72e444999470a4cab641cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 26 Dec 2019 14:30:50 +0100 Subject: [PATCH 82/96] brcmfmac: add initial support for monitor mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Report monitor interface availability using cfg80211 and support it in the add_virtual_intf() and del_virtual_intf() callbacks. This new feature is conditional and depends on firmware flagging monitor packets. Receiving monitor frames is already handled by the brcmf_netif_mon_rx(). Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 112 ++++++++++++++++-- .../broadcom/brcm80211/brcmfmac/core.c | 68 ++++++++++- .../broadcom/brcm80211/brcmfmac/core.h | 2 + .../broadcom/brcm80211/brcmfmac/feature.c | 1 + .../broadcom/brcm80211/brcmfmac/feature.h | 2 + .../broadcom/brcm80211/brcmfmac/fwil.h | 2 + 6 files changed, 174 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 3ecb91aa765e..a2328d3eee03 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -619,6 +620,82 @@ static bool brcmf_is_ibssmode(struct brcmf_cfg80211_vif *vif) return vif->wdev.iftype == NL80211_IFTYPE_ADHOC; } +/** + * brcmf_mon_add_vif() - create monitor mode virtual interface + * + * @wiphy: wiphy device of new interface. + * @name: name of the new interface. + */ +static struct wireless_dev *brcmf_mon_add_vif(struct wiphy *wiphy, + const char *name) +{ + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_vif *vif; + struct net_device *ndev; + struct brcmf_if *ifp; + int err; + + if (cfg->pub->mon_if) { + err = -EEXIST; + goto err_out; + } + + vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_MONITOR); + if (IS_ERR(vif)) { + err = PTR_ERR(vif); + goto err_out; + } + + ndev = alloc_netdev(sizeof(*ifp), name, NET_NAME_UNKNOWN, ether_setup); + if (!ndev) { + err = -ENOMEM; + goto err_free_vif; + } + ndev->type = ARPHRD_IEEE80211_RADIOTAP; + ndev->ieee80211_ptr = &vif->wdev; + ndev->needs_free_netdev = true; + ndev->priv_destructor = brcmf_cfg80211_free_netdev; + SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy)); + + ifp = netdev_priv(ndev); + ifp->vif = vif; + ifp->ndev = ndev; + ifp->drvr = cfg->pub; + + vif->ifp = ifp; + vif->wdev.netdev = ndev; + + err = brcmf_net_mon_attach(ifp); + if (err) { + brcmf_err("Failed to attach %s device\n", ndev->name); + free_netdev(ndev); + goto err_free_vif; + } + + cfg->pub->mon_if = ifp; + + return &vif->wdev; + +err_free_vif: + brcmf_free_vif(vif); +err_out: + return ERR_PTR(err); +} + +static int brcmf_mon_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) +{ + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct net_device *ndev = wdev->netdev; + + ndev->netdev_ops->ndo_stop(ndev); + + brcmf_net_detach(ndev, true); + + cfg->pub->mon_if = NULL; + + return 0; +} + static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, const char *name, unsigned char name_assign_type, @@ -641,9 +718,10 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_WDS: - case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MESH_POINT: return ERR_PTR(-EOPNOTSUPP); + case NL80211_IFTYPE_MONITOR: + return brcmf_mon_add_vif(wiphy, name); case NL80211_IFTYPE_AP: wdev = brcmf_ap_add_vif(wiphy, name, params); break; @@ -826,9 +904,10 @@ int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_WDS: - case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MESH_POINT: return -EOPNOTSUPP; + case NL80211_IFTYPE_MONITOR: + return brcmf_mon_del_vif(wiphy, wdev); case NL80211_IFTYPE_AP: return brcmf_cfg80211_del_ap_iface(wiphy, wdev); case NL80211_IFTYPE_P2P_CLIENT: @@ -6547,9 +6626,10 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) struct ieee80211_iface_limit *c0_limits = NULL; struct ieee80211_iface_limit *p2p_limits = NULL; struct ieee80211_iface_limit *mbss_limits = NULL; - bool mbss, p2p, rsdb, mchan; - int i, c, n_combos; + bool mon_flag, mbss, p2p, rsdb, mchan; + int i, c, n_combos, n_limits; + mon_flag = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FLAG); mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS); p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P); rsdb = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB); @@ -6563,6 +6643,8 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); + if (mon_flag) + wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); if (p2p) wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) | @@ -6570,18 +6652,18 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) c = 0; i = 0; - if (p2p && rsdb) - c0_limits = kcalloc(4, sizeof(*c0_limits), GFP_KERNEL); - else if (p2p) - c0_limits = kcalloc(3, sizeof(*c0_limits), GFP_KERNEL); - else - c0_limits = kcalloc(2, sizeof(*c0_limits), GFP_KERNEL); + n_limits = 1 + mon_flag + (p2p ? 2 : 0) + (rsdb || !p2p); + c0_limits = kcalloc(n_limits, sizeof(*c0_limits), GFP_KERNEL); if (!c0_limits) goto err; combo[c].num_different_channels = 1 + (rsdb || (p2p && mchan)); c0_limits[i].max = 1 + rsdb; c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); + if (mon_flag) { + c0_limits[i].max = 1; + c0_limits[i++].types = BIT(NL80211_IFTYPE_MONITOR); + } if (p2p) { c0_limits[i].max = 1; c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); @@ -6630,14 +6712,20 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) if (mbss) { c++; i = 0; - mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL); + n_limits = 1 + mon_flag; + mbss_limits = kcalloc(n_limits, sizeof(*mbss_limits), + GFP_KERNEL); if (!mbss_limits) goto err; mbss_limits[i].max = 4; mbss_limits[i++].types = BIT(NL80211_IFTYPE_AP); + if (mon_flag) { + mbss_limits[i].max = 1; + mbss_limits[i++].types = BIT(NL80211_IFTYPE_MONITOR); + } combo[c].beacon_int_infra_match = true; combo[c].num_different_channels = 1; - combo[c].max_interfaces = 4; + combo[c].max_interfaces = 4 + mon_flag; combo[c].n_limits = i; combo[c].limits = mbss_limits; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index d3ddd97fe768..23627c953a5e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -673,7 +673,7 @@ fail: return -EBADE; } -static void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked) +void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked) { if (ndev->reg_state == NETREG_REGISTERED) { if (rtnl_locked) @@ -686,6 +686,72 @@ static void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked) } } +static int brcmf_net_mon_open(struct net_device *ndev) +{ + struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = ifp->drvr; + u32 monitor; + int err; + + brcmf_dbg(TRACE, "Enter\n"); + + err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_MONITOR, &monitor); + if (err) { + bphy_err(drvr, "BRCMF_C_GET_MONITOR error (%d)\n", err); + return err; + } else if (monitor) { + bphy_err(drvr, "Monitor mode is already enabled\n"); + return -EEXIST; + } + + monitor = 3; + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_MONITOR, monitor); + if (err) + bphy_err(drvr, "BRCMF_C_SET_MONITOR error (%d)\n", err); + + return err; +} + +static int brcmf_net_mon_stop(struct net_device *ndev) +{ + struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = ifp->drvr; + u32 monitor; + int err; + + brcmf_dbg(TRACE, "Enter\n"); + + monitor = 0; + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_MONITOR, monitor); + if (err) + bphy_err(drvr, "BRCMF_C_SET_MONITOR error (%d)\n", err); + + return err; +} + +static const struct net_device_ops brcmf_netdev_ops_mon = { + .ndo_open = brcmf_net_mon_open, + .ndo_stop = brcmf_net_mon_stop, +}; + +int brcmf_net_mon_attach(struct brcmf_if *ifp) +{ + struct brcmf_pub *drvr = ifp->drvr; + struct net_device *ndev; + int err; + + brcmf_dbg(TRACE, "Enter\n"); + + ndev = ifp->ndev; + ndev->netdev_ops = &brcmf_netdev_ops_mon; + + err = register_netdevice(ndev); + if (err) + bphy_err(drvr, "Failed to register %s device\n", ndev->name); + + return err; +} + void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on) { struct net_device *ndev; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index 6699637d3bf8..33b2ab3b54b0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -210,6 +210,8 @@ 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_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb); +void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked); +int brcmf_net_mon_attach(struct brcmf_if *ifp); void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); int __init brcmf_core_init(void); void __exit brcmf_core_exit(void); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c index 1c9c74cc958e..5da0dda0d899 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c @@ -38,6 +38,7 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = { { BRCMF_FEAT_MCHAN, "mchan" }, { BRCMF_FEAT_P2P, "p2p" }, { BRCMF_FEAT_MONITOR, "monitor" }, + { BRCMF_FEAT_MONITOR_FLAG, "rtap" }, { BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" }, { BRCMF_FEAT_DOT11H, "802.11h" }, { BRCMF_FEAT_SAE, "sae" }, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h index 280a1f6412d4..cda3fc1bab7f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h @@ -23,6 +23,7 @@ * GSCAN: enhanced scan offload feature. * FWSUP: Firmware supplicant. * MONITOR: firmware can pass monitor packets to host. + * MONITOR_FLAG: firmware flags monitor packets. * MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header * MONITOR_FMT_HW_RX_HDR: firmware provides monitor packets with hw/ucode header * DOT11H: firmware supports 802.11h @@ -44,6 +45,7 @@ BRCMF_FEAT_DEF(GSCAN) \ BRCMF_FEAT_DEF(FWSUP) \ BRCMF_FEAT_DEF(MONITOR) \ + BRCMF_FEAT_DEF(MONITOR_FLAG) \ BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP) \ BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR) \ BRCMF_FEAT_DEF(DOT11H) \ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h index 0ff6f5212a94..ae4cf4372908 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h @@ -49,6 +49,8 @@ #define BRCMF_C_GET_PM 85 #define BRCMF_C_SET_PM 86 #define BRCMF_C_GET_REVINFO 98 +#define BRCMF_C_GET_MONITOR 107 +#define BRCMF_C_SET_MONITOR 108 #define BRCMF_C_GET_CURR_RATESET 114 #define BRCMF_C_GET_AP 117 #define BRCMF_C_SET_AP 118 From f4f84ff8377d4cedf18317747bc407b2cf657d0f Mon Sep 17 00:00:00 2001 From: Yan-Hsuan Chuang Date: Tue, 7 Jan 2020 16:08:07 +0800 Subject: [PATCH 83/96] rtw88: fix potential NULL skb access in TX ISR Sometimes the TX queue may be empty and we could possible dequeue a NULL pointer, crash the kernel. If the skb is NULL then there is nothing to do, just leave the ISR. And the TX queue should not be empty here, so print an error to see if there is anything wrong for DMA ring. Fixes: e3037485c68e ("rtw88: new Realtek 802.11ac driver") Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/pci.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index f7770304ba42..1fbc14c149ec 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -835,6 +835,11 @@ static void rtw_pci_tx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, while (count--) { skb = skb_dequeue(&ring->queue); + if (!skb) { + rtw_err(rtwdev, "failed to dequeue %d skb TX queue %d, BD=0x%08x, rp %d -> %d\n", + count, hw_queue, bd_idx, ring->r.rp, cur_rp); + break; + } tx_data = rtw_pci_get_tx_data(skb); pci_unmap_single(rtwpci->pdev, tx_data->dma, skb->len, PCI_DMA_TODEVICE); From 6b6c150b8464e91af26be805f88d5e58c6d626ae Mon Sep 17 00:00:00 2001 From: Yan-Hsuan Chuang Date: Tue, 7 Jan 2020 22:27:29 +0800 Subject: [PATCH 84/96] rtw88: use shorter delay time to poll PS state When TX packet arrives, driver should leave deep PS state to make sure the DMA is working. After requested to leave deep PS state, driver needs to poll the PS state to check if the mode has been changed successfully. The driver used to check the state of the hardware every 20 msecs, which means upon the first failure of state check, the CPU is delayed 20 msecs for next check. This is harmful for some time-sensitive applications such as media players. So, use shorter delay time each check from 20 msecs to 100 usecs. The state should be changed in several tries. But we still need to reserve ~15 msecs in total in case of the state just took too long to be changed successfully. If the states of driver and the hardware is not synchronized, the power state could be locked forever, which mean we could never enter/leave the PS state. Signed-off-by: Yan-Hsuan Chuang Reviewed-by: Chris Chiu Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/ps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c index 913e6f47130f..7a189a9926fe 100644 --- a/drivers/net/wireless/realtek/rtw88/ps.c +++ b/drivers/net/wireless/realtek/rtw88/ps.c @@ -91,11 +91,11 @@ void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter) return; /* check confirm power mode has left power save state */ - for (polling_cnt = 0; polling_cnt < 3; polling_cnt++) { + for (polling_cnt = 0; polling_cnt < 50; polling_cnt++) { polling = rtw_read8(rtwdev, rtwdev->hci.cpwm_addr); if ((polling ^ confirm) & BIT_RPWM_TOGGLE) return; - mdelay(20); + udelay(100); } /* in case of fw/hw missed the request, retry */ From 627b0d094240c38393b2f2d40626c33a8fff6103 Mon Sep 17 00:00:00 2001 From: yuehaibing Date: Wed, 8 Jan 2020 21:57:48 +0800 Subject: [PATCH 85/96] brcmfmac: Remove always false 'idx < 0' statement idx is declared as u32, it will never less than 0. Signed-off-by: yuehaibing Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index e3dd8623be4e..8bb4f1fa790e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -365,7 +365,7 @@ brcmf_msgbuf_get_pktid(struct device *dev, struct brcmf_msgbuf_pktids *pktids, struct brcmf_msgbuf_pktid *pktid; struct sk_buff *skb; - if (idx < 0 || idx >= pktids->array_size) { + if (idx >= pktids->array_size) { brcmf_err("Invalid packet id %d (max %d)\n", idx, pktids->array_size); return NULL; From e92b07a20b5f039ccd8776dc7c6323a3e1d726d9 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Thu, 9 Jan 2020 16:17:51 +0300 Subject: [PATCH 86/96] qtnfmac: cleanup slave_radar access function Currently this parameter is global, it is not specific to mac. So this function does not need any input parameters. Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 2 +- drivers/net/wireless/quantenna/qtnfmac/core.c | 10 +++++----- drivers/net/wireless/quantenna/qtnfmac/core.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index 59d089e092f9..25a9b512b8ce 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -1056,7 +1056,7 @@ static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy, pr_debug("MAC%u: initiator=%d alpha=%c%c\n", mac->macid, req->initiator, req->alpha2[0], req->alpha2[1]); - ret = qtnf_cmd_reg_notify(mac, req, qtnf_mac_slave_radar_get(wiphy)); + ret = qtnf_cmd_reg_notify(mac, req, qtnf_slave_radar_get()); if (ret) { pr_err("MAC%u: failed to update region to %c%c: %d\n", mac->macid, req->alpha2[0], req->alpha2[1], ret); diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c index 648dfc38bd70..9bd952a62373 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.c +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c @@ -23,6 +23,11 @@ MODULE_PARM_DESC(slave_radar, "set 0 to disable radar detection in slave mode"); static struct dentry *qtnf_debugfs_dir; +bool qtnf_slave_radar_get(void) +{ + return slave_radar; +} + struct qtnf_wmac *qtnf_core_get_mac(const struct qtnf_bus *bus, u8 macid) { struct qtnf_wmac *mac = NULL; @@ -456,11 +461,6 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus, return mac; } -bool qtnf_mac_slave_radar_get(struct wiphy *wiphy) -{ - return slave_radar; -} - static const struct ethtool_ops qtnf_ethtool_ops = { .get_drvinfo = cfg80211_get_drvinfo, }; diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h index 116ec16aa15b..949219c6cb8c 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.h +++ b/drivers/net/wireless/quantenna/qtnfmac/core.h @@ -133,7 +133,7 @@ struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac); struct qtnf_vif *qtnf_mac_get_base_vif(struct qtnf_wmac *mac); void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac); void qtnf_mac_ext_caps_free(struct qtnf_wmac *mac); -bool qtnf_mac_slave_radar_get(struct wiphy *wiphy); +bool qtnf_slave_radar_get(void); struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus); int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *priv, const char *name, unsigned char name_assign_type); From 155b424c86f8169b30d30beb46ad216c5e61749a Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Thu, 9 Jan 2020 16:17:52 +0300 Subject: [PATCH 87/96] qtnfmac: add module param to configure DFS offload Firmware may support DFS offload. However the final decision on whether to use it or not should be up to the user. So even if firmware supports DFS offload, it should be enabled only if user explicitly requests it. For this purpose introduce kernel param dfs_offload which is disabled by default. Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 9 ++++++--- drivers/net/wireless/quantenna/qtnfmac/commands.c | 3 ++- drivers/net/wireless/quantenna/qtnfmac/commands.h | 2 +- drivers/net/wireless/quantenna/qtnfmac/core.c | 9 +++++++++ drivers/net/wireless/quantenna/qtnfmac/core.h | 1 + drivers/net/wireless/quantenna/qtnfmac/qlink.h | 5 +++-- 6 files changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index 25a9b512b8ce..8849faa5bc10 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -1056,7 +1056,8 @@ static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy, pr_debug("MAC%u: initiator=%d alpha=%c%c\n", mac->macid, req->initiator, req->alpha2[0], req->alpha2[1]); - ret = qtnf_cmd_reg_notify(mac, req, qtnf_slave_radar_get()); + ret = qtnf_cmd_reg_notify(mac, req, qtnf_slave_radar_get(), + qtnf_dfs_offload_get()); if (ret) { pr_err("MAC%u: failed to update region to %c%c: %d\n", mac->macid, req->alpha2[0], req->alpha2[1], ret); @@ -1078,7 +1079,8 @@ struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus) { struct wiphy *wiphy; - if (bus->hw_info.hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD) + if (qtnf_dfs_offload_get() && + (bus->hw_info.hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)) qtn_cfg80211_ops.start_radar_detection = NULL; if (!(bus->hw_info.hw_capab & QLINK_HW_CAPAB_PWR_MGMT)) @@ -1163,7 +1165,8 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) WIPHY_FLAG_NETNS_OK; wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; - if (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD) + if (qtnf_dfs_offload_get() && + (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD); if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_DWELL) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 548f6ff6d0f2..fbeff01f902a 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -2454,7 +2454,7 @@ out: } int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req, - bool slave_radar) + bool slave_radar, bool dfs_offload) { struct wiphy *wiphy = priv_to_wiphy(mac); struct qtnf_bus *bus = mac->bus; @@ -2517,6 +2517,7 @@ int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req, } cmd->slave_radar = slave_radar; + cmd->dfs_offload = dfs_offload; cmd->num_channels = 0; for (band = 0; band < NUM_NL80211_BANDS; band++) { diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h index 761755bf9ede..ab273257b078 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.h +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h @@ -58,7 +58,7 @@ int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up); int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req, - bool slave_radar); + bool slave_radar, bool dfs_offload); int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel, struct qtnf_chan_stats *stats); int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif, diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c index 9bd952a62373..b6e53415bea1 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.c +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c @@ -21,6 +21,10 @@ static bool slave_radar = true; module_param(slave_radar, bool, 0644); MODULE_PARM_DESC(slave_radar, "set 0 to disable radar detection in slave mode"); +static bool dfs_offload; +module_param(dfs_offload, bool, 0644); +MODULE_PARM_DESC(dfs_offload, "set 1 to enable DFS offload to firmware"); + static struct dentry *qtnf_debugfs_dir; bool qtnf_slave_radar_get(void) @@ -28,6 +32,11 @@ bool qtnf_slave_radar_get(void) return slave_radar; } +bool qtnf_dfs_offload_get(void) +{ + return dfs_offload; +} + struct qtnf_wmac *qtnf_core_get_mac(const struct qtnf_bus *bus, u8 macid) { struct qtnf_wmac *mac = NULL; diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h index 949219c6cb8c..d715e1cd0006 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.h +++ b/drivers/net/wireless/quantenna/qtnfmac/core.h @@ -134,6 +134,7 @@ struct qtnf_vif *qtnf_mac_get_base_vif(struct qtnf_wmac *mac); void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac); void qtnf_mac_ext_caps_free(struct qtnf_wmac *mac); bool qtnf_slave_radar_get(void); +bool qtnf_dfs_offload_get(void); struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus); int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *priv, const char *name, unsigned char name_assign_type); diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 75527f1bb306..799c622a160d 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -596,8 +596,9 @@ enum qlink_user_reg_hint_type { * of &enum qlink_user_reg_hint_type. * @num_channels: number of &struct qlink_tlv_channel in a variable portion of a * payload. - * @slave_radar: whether slave device should enable radar detection. * @dfs_region: one of &enum qlink_dfs_regions. + * @slave_radar: whether slave device should enable radar detection. + * @dfs_offload: enable or disable DFS offload to firmware. * @info: variable portion of regulatory notifier callback. */ struct qlink_cmd_reg_notify { @@ -608,7 +609,7 @@ struct qlink_cmd_reg_notify { u8 num_channels; u8 dfs_region; u8 slave_radar; - u8 rsvd[1]; + u8 dfs_offload; u8 info[0]; } __packed; From e14291752e568bf936907be7f11ae3cc39d89fd2 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Thu, 9 Jan 2020 16:17:53 +0300 Subject: [PATCH 88/96] qtnfmac: control qtnfmac wireless interfaces bridging Bridging qtnfmac interfaces is possible only if the following two conditions are fulfilled: - firmware advertises proper support with QLINK_HW_CAPAB_HW_BRIDGE - kernel is built with CONFIG_NET_SWITCHDEV support Otherwise adding qtnfmac wireless interfaces into the same bridge should not be allowed since packets flooded by kernel may break internal forwarding rules between interfaces. This patch disables adding qtnfmac wireless interfaces into the same bridge if no support is provided either by card or by kernel. Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/core.c | 52 ++++++++++++------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c index b6e53415bea1..4320180f8c07 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.c +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c @@ -225,9 +225,6 @@ static int qtnf_netdev_port_parent_id(struct net_device *ndev, const struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev); const struct qtnf_bus *bus = vif->mac->bus; - if (!(bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE)) - return -EOPNOTSUPP; - ppid->id_len = sizeof(bus->hw_id); memcpy(&ppid->id, bus->hw_id, ppid->id_len); @@ -665,12 +662,24 @@ bool qtnf_netdev_is_qtn(const struct net_device *ndev) return ndev->netdev_ops == &qtnf_netdev_ops; } +static int qtnf_check_br_ports(struct net_device *dev, void *data) +{ + struct net_device *ndev = data; + + if (dev != ndev && netdev_port_same_parent_id(dev, ndev)) + return -ENOTSUPP; + + return 0; +} + static int qtnf_core_netdevice_event(struct notifier_block *nb, unsigned long event, void *ptr) { struct net_device *ndev = netdev_notifier_info_to_dev(ptr); const struct netdev_notifier_changeupper_info *info; + struct net_device *brdev; struct qtnf_vif *vif; + struct qtnf_bus *bus; int br_domain; int ret = 0; @@ -681,25 +690,34 @@ static int qtnf_core_netdevice_event(struct notifier_block *nb, return NOTIFY_OK; vif = qtnf_netdev_get_priv(ndev); + bus = vif->mac->bus; switch (event) { case NETDEV_CHANGEUPPER: info = ptr; + brdev = info->upper_dev; - if (!netif_is_bridge_master(info->upper_dev)) + if (!netif_is_bridge_master(brdev)) break; pr_debug("[VIF%u.%u] change bridge: %s %s\n", - vif->mac->macid, vif->vifid, - netdev_name(info->upper_dev), + vif->mac->macid, vif->vifid, netdev_name(brdev), info->linking ? "add" : "del"); - if (info->linking) - br_domain = info->upper_dev->ifindex; - else - br_domain = ndev->ifindex; + if (IS_ENABLED(CONFIG_NET_SWITCHDEV) && + (bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE)) { + if (info->linking) + br_domain = brdev->ifindex; + else + br_domain = ndev->ifindex; + + ret = qtnf_cmd_netdev_changeupper(vif, br_domain); + } else { + ret = netdev_walk_all_lower_dev(brdev, + qtnf_check_br_ports, + ndev); + } - ret = qtnf_cmd_netdev_changeupper(vif, br_domain); break; default: break; @@ -772,13 +790,11 @@ int qtnf_core_attach(struct qtnf_bus *bus) } } - if (bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) { - bus->netdev_nb.notifier_call = qtnf_core_netdevice_event; - ret = register_netdevice_notifier(&bus->netdev_nb); - if (ret) { - pr_err("failed to register netdev notifier: %d\n", ret); - goto error; - } + bus->netdev_nb.notifier_call = qtnf_core_netdevice_event; + ret = register_netdevice_notifier(&bus->netdev_nb); + if (ret) { + pr_err("failed to register netdev notifier: %d\n", ret); + goto error; } bus->fw_state = QTNF_FW_STATE_RUNNING; From b73f0aac731ce87a656d9911cb9e2e79eb721d1a Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Thu, 9 Jan 2020 16:17:54 +0300 Subject: [PATCH 89/96] qtnfmac: add support for STA HE rates Add HE rates into STA info. Report HE Rx/Tx MCS if STA supports them. Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/commands.c | 2 ++ drivers/net/wireless/quantenna/qtnfmac/qlink.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index fbeff01f902a..fa932f771856 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -510,6 +510,8 @@ qtnf_sta_info_parse_rate(struct rate_info *rate_dst, rate_dst->flags |= RATE_INFO_FLAGS_MCS; else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_VHT_MCS) rate_dst->flags |= RATE_INFO_FLAGS_VHT_MCS; + else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_HE_MCS) + rate_dst->flags |= RATE_INFO_FLAGS_HE_MCS; if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_SHORT_GI) rate_dst->flags |= RATE_INFO_FLAGS_SHORT_GI; diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 799c622a160d..19e432b28de5 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -949,6 +949,7 @@ enum qlink_sta_info_rate_flags { QLINK_STA_INFO_RATE_FLAG_VHT_MCS = BIT(1), QLINK_STA_INFO_RATE_FLAG_SHORT_GI = BIT(2), QLINK_STA_INFO_RATE_FLAG_60G = BIT(3), + QLINK_STA_INFO_RATE_FLAG_HE_MCS = BIT(4), }; /** From ed7791d9d0abc7e24223ab1663931c8e5351fea8 Mon Sep 17 00:00:00 2001 From: Mikhail Karpenko Date: Thu, 9 Jan 2020 16:17:55 +0300 Subject: [PATCH 90/96] qtnfmac: add support for TWT responder and spatial reuse Add support for 11ax features: TWT responder and spatial reuse. Add separate structure for spatial reuse parameters and pass this structure to firmware along with other parameters in start_ap command. Pass TWT responder value to firmware. Bump qlink protocol version. Signed-off-by: Mikhail Karpenko Signed-off-by: Kalle Valo --- .../net/wireless/quantenna/qtnfmac/commands.c | 8 ++++ .../net/wireless/quantenna/qtnfmac/qlink.h | 46 ++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index fa932f771856..d0d7ec8794c4 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -257,6 +257,14 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif, cmd->pbss = s->pbss; cmd->ht_required = s->ht_required; cmd->vht_required = s->vht_required; + cmd->twt_responder = s->twt_responder; + if (s->he_obss_pd.enable) { + cmd->sr_params.sr_control |= QLINK_SR_SRG_INFORMATION_PRESENT; + cmd->sr_params.srg_obss_pd_min_offset = + s->he_obss_pd.min_offset; + cmd->sr_params.srg_obss_pd_max_offset = + s->he_obss_pd.max_offset; + } aen = &cmd->aen; aen->auth_type = s->auth_type; diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 19e432b28de5..b2edb03819d1 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -6,7 +6,7 @@ #include -#define QLINK_PROTO_VER 15 +#define QLINK_PROTO_VER 16 #define QLINK_MACID_RSVD 0xFF #define QLINK_VIFID_RSVD 0xFF @@ -196,6 +196,45 @@ struct qlink_sta_info_state { __le32 value; } __packed; +/** + * enum qlink_sr_ctrl_flags - control flags for spatial reuse parameter set + * + * @QLINK_SR_PSR_DISALLOWED: indicates whether or not PSR-based spatial reuse + * transmissions are allowed for STAs associated with the AP + * @QLINK_SR_NON_SRG_OBSS_PD_SR_DISALLOWED: indicates whether or not + * Non-SRG OBSS PD spatial reuse transmissions are allowed for STAs associated + * with the AP + * @NON_SRG_OFFSET_PRESENT: indicates whether or not Non-SRG OBSS PD Max offset + * field is valid in the element + * @QLINK_SR_SRG_INFORMATION_PRESENT: indicates whether or not SRG OBSS PD + * Min/Max offset fields ore valid in the element + */ +enum qlink_sr_ctrl_flags { + QLINK_SR_PSR_DISALLOWED = BIT(0), + QLINK_SR_NON_SRG_OBSS_PD_SR_DISALLOWED = BIT(1), + QLINK_SR_NON_SRG_OFFSET_PRESENT = BIT(2), + QLINK_SR_SRG_INFORMATION_PRESENT = BIT(3), +}; + +/** + * struct qlink_sr_params - spatial reuse parameters + * + * @sr_control: spatial reuse control field; flags contained in this field are + * defined in @qlink_sr_ctrl_flags + * @non_srg_obss_pd_max: added to -82 dBm to generate the value of the + * Non-SRG OBSS PD Max parameter + * @srg_obss_pd_min_offset: added to -82 dBm to generate the value of the + * SRG OBSS PD Min parameter + * @srg_obss_pd_max_offset: added to -82 dBm to generate the value of the + * SRG PBSS PD Max parameter + */ +struct qlink_sr_params { + u8 sr_control; + u8 non_srg_obss_pd_max; + u8 srg_obss_pd_min_offset; + u8 srg_obss_pd_max_offset; +} __packed; + /* QLINK Command messages related definitions */ @@ -651,6 +690,8 @@ enum qlink_hidden_ssid { * @ht_required: stations must support HT * @vht_required: stations must support VHT * @aen: encryption info + * @sr_params: spatial reuse parameters + * @twt_responder: enable Target Wake Time * @info: variable configurations */ struct qlink_cmd_start_ap { @@ -666,6 +707,9 @@ struct qlink_cmd_start_ap { u8 ht_required; u8 vht_required; struct qlink_auth_encr aen; + struct qlink_sr_params sr_params; + u8 twt_responder; + u8 rsvd[3]; u8 info[0]; } __packed; From c3a913357c3e3d2225a83508f06ece01f5bada20 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 14 Jan 2020 16:56:01 +0000 Subject: [PATCH 91/96] rtlwifi: rtl8188ee: remove redundant assignment to variable cond Variable cond is being assigned with a value that is never read, it is assigned a new value later on. The assignment is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Acked-by: Ping-Ke Shih Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c index 5ca900f97d66..d13983ec09ad 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c @@ -264,7 +264,7 @@ static bool _rtl88e_check_condition(struct ieee80211_hw *hw, u32 _board = rtlefuse->board_type; /*need efuse define*/ u32 _interface = rtlhal->interface; u32 _platform = 0x08;/*SupportPlatform */ - u32 cond = condition; + u32 cond; if (condition == 0xCDCDCDCD) return true; From cc071a6f26aae3321cf193dc2e8c35090709b8ab Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 21 Jan 2020 10:09:58 +0800 Subject: [PATCH 92/96] rtlwifi: rtl8821ae: remove unused variables drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c:142:17: warning: cckswing_table_ch1ch13 defined but not used [-Wunused-const-variable=] drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c:178:17: warning: cckswing_table_ch14 defined but not used [-Wunused-const-variable=] drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c:96:18: warning: ofdmswing_table defined but not used [-Wunused-const-variable=] These variable is never used, so remove them. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8821ae/dm.c | 118 ------------------ 1 file changed, 118 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c index b54230433a6b..f57e8794f0ec 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c @@ -93,124 +93,6 @@ static const u32 rtl8821ae_txscaling_table[TXSCALE_TABLE_SIZE] = { 0x3FE /* 36, +6.0dB */ }; -static const u32 ofdmswing_table[] = { - 0x0b40002d, /* 0, -15.0dB */ - 0x0c000030, /* 1, -14.5dB */ - 0x0cc00033, /* 2, -14.0dB */ - 0x0d800036, /* 3, -13.5dB */ - 0x0e400039, /* 4, -13.0dB */ - 0x0f00003c, /* 5, -12.5dB */ - 0x10000040, /* 6, -12.0dB */ - 0x11000044, /* 7, -11.5dB */ - 0x12000048, /* 8, -11.0dB */ - 0x1300004c, /* 9, -10.5dB */ - 0x14400051, /* 10, -10.0dB */ - 0x15800056, /* 11, -9.5dB */ - 0x16c0005b, /* 12, -9.0dB */ - 0x18000060, /* 13, -8.5dB */ - 0x19800066, /* 14, -8.0dB */ - 0x1b00006c, /* 15, -7.5dB */ - 0x1c800072, /* 16, -7.0dB */ - 0x1e400079, /* 17, -6.5dB */ - 0x20000080, /* 18, -6.0dB */ - 0x22000088, /* 19, -5.5dB */ - 0x24000090, /* 20, -5.0dB */ - 0x26000098, /* 21, -4.5dB */ - 0x288000a2, /* 22, -4.0dB */ - 0x2ac000ab, /* 23, -3.5dB */ - 0x2d4000b5, /* 24, -3.0dB */ - 0x300000c0, /* 25, -2.5dB */ - 0x32c000cb, /* 26, -2.0dB */ - 0x35c000d7, /* 27, -1.5dB */ - 0x390000e4, /* 28, -1.0dB */ - 0x3c8000f2, /* 29, -0.5dB */ - 0x40000100, /* 30, +0dB */ - 0x43c0010f, /* 31, +0.5dB */ - 0x47c0011f, /* 32, +1.0dB */ - 0x4c000130, /* 33, +1.5dB */ - 0x50800142, /* 34, +2.0dB */ - 0x55400155, /* 35, +2.5dB */ - 0x5a400169, /* 36, +3.0dB */ - 0x5fc0017f, /* 37, +3.5dB */ - 0x65400195, /* 38, +4.0dB */ - 0x6b8001ae, /* 39, +4.5dB */ - 0x71c001c7, /* 40, +5.0dB */ - 0x788001e2, /* 41, +5.5dB */ - 0x7f8001fe /* 42, +6.0dB */ -}; - -static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { - {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /* 0, -16.0dB */ - {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 1, -15.5dB */ - {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 2, -15.0dB */ - {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 3, -14.5dB */ - {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 4, -14.0dB */ - {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 5, -13.5dB */ - {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 6, -13.0dB */ - {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 7, -12.5dB */ - {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 8, -12.0dB */ - {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 9, -11.5dB */ - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */ - {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */ - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */ - {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */ - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */ - {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */ - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ - {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */ - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */ - {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */ - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */ - {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */ - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */ - {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */ - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */ - {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */ - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */ - {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */ - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */ - {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */ - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */ - {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */ - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04} /* 32, +0dB */ -}; - -static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { - {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /* 0, -16.0dB */ - {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 1, -15.5dB */ - {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 2, -15.0dB */ - {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 3, -14.5dB */ - {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 4, -14.0dB */ - {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 5, -13.5dB */ - {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 6, -13.0dB */ - {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 7, -12.5dB */ - {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 8, -12.0dB */ - {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 9, -11.5dB */ - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */ - {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */ - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */ - {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */ - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */ - {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */ - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ - {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */ - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */ - {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */ - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */ - {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */ - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */ - {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */ - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */ - {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */ - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */ - {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */ - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */ - {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */ - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */ - {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */ - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00} /* 32, +0dB */ -}; - static const u32 edca_setting_dl[PEER_MAX] = { 0xa44f, /* 0 UNKNOWN */ 0x5ea44f, /* 1 REALTEK_90 */ From 253e5aba937973fd29bd5c559d21e35d0642242e Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 21 Jan 2020 10:19:24 +0800 Subject: [PATCH 93/96] rtlwifi: rtl8192ee: remove unused variables drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c:15:18: warning: ofdmswing_table defined but not used [-Wunused-const-variable=] drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c:61:17: warning: cckswing_table_ch1ch13 defined but not used [-Wunused-const-variable=] drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c:97:17: warning: cckswing_table_ch14 defined but not used [-Wunused-const-variable=] These variable is never used, so remove them. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8192ee/dm.c | 118 ------------------ 1 file changed, 118 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c index 648f9108ed4b..551aa86825ed 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c @@ -12,124 +12,6 @@ #include "fw.h" #include "trx.h" -static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { - 0x7f8001fe, /* 0, +6.0dB */ - 0x788001e2, /* 1, +5.5dB */ - 0x71c001c7, /* 2, +5.0dB */ - 0x6b8001ae, /* 3, +4.5dB */ - 0x65400195, /* 4, +4.0dB */ - 0x5fc0017f, /* 5, +3.5dB */ - 0x5a400169, /* 6, +3.0dB */ - 0x55400155, /* 7, +2.5dB */ - 0x50800142, /* 8, +2.0dB */ - 0x4c000130, /* 9, +1.5dB */ - 0x47c0011f, /* 10, +1.0dB */ - 0x43c0010f, /* 11, +0.5dB */ - 0x40000100, /* 12, +0dB */ - 0x3c8000f2, /* 13, -0.5dB */ - 0x390000e4, /* 14, -1.0dB */ - 0x35c000d7, /* 15, -1.5dB */ - 0x32c000cb, /* 16, -2.0dB */ - 0x300000c0, /* 17, -2.5dB */ - 0x2d4000b5, /* 18, -3.0dB */ - 0x2ac000ab, /* 19, -3.5dB */ - 0x288000a2, /* 20, -4.0dB */ - 0x26000098, /* 21, -4.5dB */ - 0x24000090, /* 22, -5.0dB */ - 0x22000088, /* 23, -5.5dB */ - 0x20000080, /* 24, -6.0dB */ - 0x1e400079, /* 25, -6.5dB */ - 0x1c800072, /* 26, -7.0dB */ - 0x1b00006c, /* 27. -7.5dB */ - 0x19800066, /* 28, -8.0dB */ - 0x18000060, /* 29, -8.5dB */ - 0x16c0005b, /* 30, -9.0dB */ - 0x15800056, /* 31, -9.5dB */ - 0x14400051, /* 32, -10.0dB */ - 0x1300004c, /* 33, -10.5dB */ - 0x12000048, /* 34, -11.0dB */ - 0x11000044, /* 35, -11.5dB */ - 0x10000040, /* 36, -12.0dB */ - 0x0f00003c, /* 37, -12.5dB */ - 0x0e400039, /* 38, -13.0dB */ - 0x0d800036, /* 39, -13.5dB */ - 0x0cc00033, /* 40, -14.0dB */ - 0x0c000030, /* 41, -14.5dB */ - 0x0b40002d, /* 42, -15.0dB */ -}; - -static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */ - {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */ - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */ - {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */ - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */ - {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */ - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */ - {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */ - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */ - {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */ - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */ - {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */ - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */ - {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */ - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */ - {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */ - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ - {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */ - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */ - {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */ - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */ - {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */ - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */ - {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */ - {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */ - {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */ - {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */ - {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */ - {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */ - {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */ - {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */ - {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */ - {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */ -}; - -static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */ - {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */ - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */ - {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */ - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */ - {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */ - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */ - {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */ - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */ - {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */ - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */ - {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */ - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */ - {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */ - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */ - {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */ - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ - {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */ - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */ - {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */ - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */ - {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */ - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */ - {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */ - {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */ - {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */ - {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */ - {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */ - {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */ - {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */ - {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */ - {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */ - {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB */ -}; - static void rtl92ee_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) { u32 ret_value; From c5f9852411098474ab21f5d7b1b84e5cdd59ca5a Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 21 Jan 2020 11:04:28 +0800 Subject: [PATCH 94/96] rtlwifi: rtl8723ae: remove unused variables drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c:16:18: warning: ofdmswing_table defined but not used [-Wunused-const-variable=] drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c:56:17: warning: cckswing_table_ch1ch13 defined but not used [-Wunused-const-variable=] drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c:92:17: warning: cckswing_table_ch14 defined but not used [-Wunused-const-variable=] These variable is never used, so remove them. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8723ae/dm.c | 112 ------------------ 1 file changed, 112 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c index d8260c7afe09..c61a92df9d73 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c @@ -13,118 +13,6 @@ #include "fw.h" #include "hal_btc.h" -static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { - 0x7f8001fe, - 0x788001e2, - 0x71c001c7, - 0x6b8001ae, - 0x65400195, - 0x5fc0017f, - 0x5a400169, - 0x55400155, - 0x50800142, - 0x4c000130, - 0x47c0011f, - 0x43c0010f, - 0x40000100, - 0x3c8000f2, - 0x390000e4, - 0x35c000d7, - 0x32c000cb, - 0x300000c0, - 0x2d4000b5, - 0x2ac000ab, - 0x288000a2, - 0x26000098, - 0x24000090, - 0x22000088, - 0x20000080, - 0x1e400079, - 0x1c800072, - 0x1b00006c, - 0x19800066, - 0x18000060, - 0x16c0005b, - 0x15800056, - 0x14400051, - 0x1300004c, - 0x12000048, - 0x11000044, - 0x10000040, -}; - -static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, - {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, - {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, - {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, - {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, - {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, - {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, - {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, - {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, - {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, - {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, - {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, - {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, - {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, - {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, - {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, - {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, - {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, - {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, - {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, - {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, - {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} -}; - -static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, - {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, - {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, - {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, - {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, - {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, - {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, - {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, - {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, - {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, - {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, - {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, - {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, - {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, - {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, - {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, - {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, - {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, - {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, - {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, - {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, - {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} -}; - static u8 rtl8723e_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); From f76c34082b24534c813a9e3e175ef778c11e9950 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 22 Jan 2020 09:33:40 +0000 Subject: [PATCH 95/96] rtlwifi: btcoex: fix spelling mistake "initilized" -> "initialized" There is a spelling mistake in one of the fields in the btc_coexist struct, fix it. Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c | 2 +- drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c | 2 +- drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c index 3c96c320236c..658ff425c256 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c @@ -862,7 +862,7 @@ static void btc8192e2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, /* Resume RF Rx LPF corner * After initialized, we can use coex_dm->btRf0x1eBackup */ - if (btcoexist->initilized) { + if (btcoexist->initialized) { RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD, "[BTCoex], Resume RF Rx LPF corner!!\n"); btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c index 191dafd03189..a4940a3842de 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c @@ -1461,7 +1461,7 @@ void exhalbtc_init_coex_dm(struct btc_coexist *btcoexist) ex_btc8192e2ant_init_coex_dm(btcoexist); } - btcoexist->initilized = true; + btcoexist->initialized = true; } void exhalbtc_ips_notify(struct btc_coexist *btcoexist, u8 type) diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h index 8c0a7fdbf200..a96a995dd850 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h @@ -679,7 +679,7 @@ struct btc_coexist { bool auto_report_2ant; bool dbg_mode_1ant; bool dbg_mode_2ant; - bool initilized; + bool initialized; bool stop_coex_dm; bool manual_control; struct btc_statistics statistics; From c2f9a4e4a5abfc84c01b738496b3fd2d471e0b18 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 26 Jan 2020 00:09:54 +0000 Subject: [PATCH 96/96] iwlegacy: ensure loop counter addr does not wrap and cause an infinite loop The loop counter addr is a u16 where as the upper limit of the loop is an int. In the unlikely event that the il->cfg->eeprom_size is greater than 64K then we end up with an infinite loop since addr will wrap around an never reach upper loop limit. Fix this by making addr an int. Addresses-Coverity: ("Infinite loop") Fixes: be663ab67077 ("iwlwifi: split the drivers for agn and legacy devices 3945/4965") Signed-off-by: Colin Ian King Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/intel/iwlegacy/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c index d966b29b45ee..348c17ce72f5 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.c +++ b/drivers/net/wireless/intel/iwlegacy/common.c @@ -699,7 +699,7 @@ il_eeprom_init(struct il_priv *il) u32 gp = _il_rd(il, CSR_EEPROM_GP); int sz; int ret; - u16 addr; + int addr; /* allocate eeprom */ sz = il->cfg->eeprom_size;