pull request: iwlwifi-next 2013-03-18
Hi John,
Here is another pull request for 3.15. I guess it will be the last one unless some issue arises.
I have a fix for a "merge damage" which is not really a merge damage: it enables scheduled scan which has been disabled in wireless.git. Since you merged wireless.git into wireless-next.git, this can now be fixed in wireless-next.git.
Besides this, Alex made a workaround for a hardware bug. This fix allows us to consume less power in S3. Arik and Eliad continue to work on D0i3 which is a run-time power saving feature. Eliad also contributes a few bits to the rate scaling logic to which Eyal adds his own contribution. Avri dives deep in the power code - newer firmware will allow to enable power save in newer scenarios. Johannes made a few clean-ups. I have the regular amount of BT Coex boring stuff. I disable uAPSD since we identified firmware bugs that cause packet loss. One thing that do stand out is the udev event that we now send when the FW asserts. I hope it will allow us to debug the FW more easily.
The udev thing will need tiny effort from distributions: to put the script and the udev rule (copied in the commit message) in place. Note that we have a debugfs hook to trigger a FW assert, so that it shouldn't really be an issue to put that in place and test that it actually works. The purpose of this is to have a file in /var/log (or wherever) with FW state / logs that we can give to the FW teams. I took the idea from the GPU folks who have a similar concept and Ubuntu even has a udev rule that dumps the error when something bad occurs (/sys/kernel/debug/dri/0/i915_error_state). I used debugfs, but I saw that Ubuntu ships with debugfs compiled and mounted (I hope this is the standard configuration). I haven't done an extensive research about other distros though...
Let me know if you have issues with this!
The following changes since commit 3e3831c4fdc53aabf3a56419ef6d96a841c52435:
brcmfmac: reset suspend flag upon sdio suspend failure (2014-02-28 14:33:49 -0500)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git for-john
for you to fetch changes up to 4a482d61e0f87a655f1e022a09ec48bca11dd898:
iwlwifi: mvm: disable uAPSD due to bugs in the firmware (2014-03-18 16:32:45 +0200)
----------------------------------------------------------------
Alexander Bondar (4):
iwlwifi: pcie: enable LP XTAL to reduce power consumption
iwlwifi: mvm: Change beacon filter enablement condition
iwlwifi: mvm: restructure scan parameters calculation
iwlwifi: mvm: configure low latency dependent scan parameters
Arik Nemtsov (3):
iwlwifi: mvm: wait for stop sched-scan completion
iwlwifi: mvm: abort scan on sched_scan request
iwlwifi: mvm: reconfigure qos seq on D0i3 exit
Avri Altman (1):
iwlwifi: mvm: disable power on P2P client when BSS is added
Eliad Peller (5):
iwlwifi: mvm: check for d0i3 fw capability
iwlwifi: rs: split rs_collect_tx_data
iwlwifi: add rs_rate_scale_clear_tbl_windows helper function
iwlwifi: mvm: configure seq_num to D0i3
iwlwifi: mvm: configure protocol offloading on D0i3
Emmanuel Grumbach (12):
iwlwifi: mvm: fix quota for D3 image
iwlwifi: mvm: fix scan offload for BGN SKU
iwlwifi: mvm: BT Coex add support for Co-running block
iwlwifi: mvm: make bt-coex.c generic
iwlwifi: mvm: BT Coex - classify packet priority in BT code
iwlwifi: mvm: BT Coex - enable per-AC BT priority
iwlwifi: mvm: fix merge damage
iwlwifi: mvm: don't fail completely if led mode is not supported
iwlwifi: mvm: send udev event upon firmware error to dump logs
iwlwifi: mvm: BT Coex - add debugfs hook to set BT Tx priority
iwlwifi: mvm: fix theoretical NULL ptr dereference
iwlwifi: mvm: disable uAPSD due to bugs in the firmware
Eyal Shapira (3):
iwlwifi: mvm: cleanups in iwl_dbgfs_frame_stats_read
iwlwifi: mvm: rs: fix search cycle rules
iwlwifi: mvm: don't enable protection for all AMPDUs
Johannes Berg (7):
iwlwifi: mvm: init drv_stats_lock
iwlwifi: pcie: suppress ACPI related error message
iwlwifi: nvm: fix VHT capability antenna-dependent fields
iwlwifi: return whether to stop from rfkill method
iwlwifi: mvm: remove using max_duration in firmware API
iwlwifi: mvm: remove spurious blank line
iwlwifi: mvm: ignore unchanged low-latency flag
drivers/net/wireless/iwlwifi/dvm/main.c | 4 +-
drivers/net/wireless/iwlwifi/iwl-7000.c | 4 +
drivers/net/wireless/iwlwifi/iwl-config.h | 1 +
drivers/net/wireless/iwlwifi/iwl-csr.h | 38 +++++++++
drivers/net/wireless/iwlwifi/iwl-fw.h | 16 ++++
drivers/net/wireless/iwlwifi/iwl-io.c | 4 +-
drivers/net/wireless/iwlwifi/iwl-io.h | 2 +
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 19 +++--
drivers/net/wireless/iwlwifi/iwl-op-mode.h | 11 +--
drivers/net/wireless/iwlwifi/iwl-prph.h | 23 +++++-
drivers/net/wireless/iwlwifi/mvm/Makefile | 4 +-
drivers/net/wireless/iwlwifi/mvm/{bt-coex.c => coex.c} | 336 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
drivers/net/wireless/iwlwifi/mvm/constants.h | 4 +-
drivers/net/wireless/iwlwifi/mvm/d3.c | 195 ++++++++--------------------------------------
drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | 5 ++
drivers/net/wireless/iwlwifi/mvm/debugfs.c | 109 ++++++++++++++++++++++----
drivers/net/wireless/iwlwifi/mvm/{fw-api-bt-coex.h => fw-api-coex.h} | 4 +
drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h | 8 +-
drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | 3 +
drivers/net/wireless/iwlwifi/mvm/fw-api.h | 3 +-
drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h | 106 +++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/mvm/led.c | 2 +
drivers/net/wireless/iwlwifi/mvm/mac80211.c | 145 ++++++++++++++++++++++++++++-------
drivers/net/wireless/iwlwifi/mvm/mvm.h | 56 ++++++++++++--
drivers/net/wireless/iwlwifi/mvm/offloading.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/mvm/ops.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++++++---
drivers/net/wireless/iwlwifi/mvm/power.c | 17 ++--
drivers/net/wireless/iwlwifi/mvm/quota.c | 23 +-----
drivers/net/wireless/iwlwifi/mvm/rs.c | 88 +++++++++++----------
drivers/net/wireless/iwlwifi/mvm/scan.c | 240 ++++++++++++++++++++++++++++++++++++---------------------
drivers/net/wireless/iwlwifi/mvm/sta.c | 12 ++-
drivers/net/wireless/iwlwifi/mvm/tx.c | 16 ++--
drivers/net/wireless/iwlwifi/mvm/utils.c | 49 ++++++++----
drivers/net/wireless/iwlwifi/pcie/drv.c | 5 +-
drivers/net/wireless/iwlwifi/pcie/internal.h | 2 +
drivers/net/wireless/iwlwifi/pcie/rx.c | 2 +-
drivers/net/wireless/iwlwifi/pcie/trans.c | 143 +++++++++++++++++++++++++++++++++-
37 files changed, 1705 insertions(+), 438 deletions(-)
rename drivers/net/wireless/iwlwifi/mvm/{bt-coex.c => coex.c} (70%)
rename drivers/net/wireless/iwlwifi/mvm/{fw-api-bt-coex.h => fw-api-coex.h} (99%)
create mode 100644 drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h
create mode 100644 drivers/net/wireless/iwlwifi/mvm/offloading.cPATCH 1/35 iwlwifi: mvm: init drv_stats_lock
From: Johannes Berg <[email protected]>
Otherwise lockdep complains about the lock, I'm not sure why we didn't see this before.
--- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/wireless/iwlwifi/mvm/debugfs.c +2 -0
@@ -1049,6 +1049,8 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)struct dentry *bcast_dir__maybe_unused ;char buf[100 ]; +spin_lock_init (&mvm->drv_stats_lock); + mvm->debugfs_dir = dbgfs_dir;MVM_DEBUGFS_ADD_FILE (tx_flush, mvm->debugfs_dir,S_IWUSR );
Signature · 1 line
1.8.3.2
PATCH 2/35 iwlwifi: pcie: suppress ACPI related error message
In reply to Emmanuel GrumbachFrom: Johannes Berg <[email protected]>
This message triggers on systems that don't support the API, so suppress them when not debugging as it's not useful to see it there.
--- drivers/net/wireless/iwlwifi/pcie/drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/iwlwifi/pcie/drv.c +2 -1
@@ -448,7 +448,8 @@ static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev) pxsx_handle =ACPI_HANDLE (&pdev->dev);if (!pxsx_handle) { -IWL_ERR (trans,"Could not retrieve root port ACPI handle" ); +IWL_DEBUG_INFO (trans, +"Could not retrieve root port ACPI handle" );return ; }
Signature · 1 line
1.8.3.2
PATCH 3/35 iwlwifi: mvm: cleanups in iwl_dbgfs_frame_stats_read
In reply to Emmanuel GrumbachFrom: Eyal Shapira <[email protected]>
Switch pos to char * which makes the code a bit shorter as well as other minor cleanups suggested by Joe Perches.
--- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 34 +++++++++++++++++------------- 1 file changed, 19 insertions(+), 15 deletions(-)
drivers/net/wireless/iwlwifi/mvm/debugfs.c +19 -15
@@ -536,56 +536,60 @@ static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,loff_t *ppos, struct iwl_mvm_frame_stats *stats) { - char *buff; -int pos =0 , idx, i; + char *buff, *pos, *endpos; +int idx, i;int ret; -size_t bufsz =1024 ; +static const size_t bufsz =1024 ; buff =kmalloc (bufsz,GFP_KERNEL );if (!buff)return -ENOMEM ;spin_lock_bh (&mvm->drv_stats_lock); - pos +=scnprintf (buff + pos, bufsz - pos, + + pos = buff; + endpos = pos + bufsz; + + pos +=scnprintf (pos, endpos - pos,"Legacy/HT/VHT\t:\t%d/%d/%d\n" , stats->legacy_frames, stats->ht_frames, stats->vht_frames); - pos +=scnprintf (buff + pos, bufsz - pos,"20/40/80\t:\t%d/%d/%d\n" , + pos +=scnprintf (pos, endpos - pos,"20/40/80\t:\t%d/%d/%d\n" , stats->bw_20_frames, stats->bw_40_frames, stats->bw_80_frames); - pos +=scnprintf (buff + pos, bufsz - pos,"NGI/SGI\t\t:\t%d/%d\n" , + pos +=scnprintf (pos, endpos - pos,"NGI/SGI\t\t:\t%d/%d\n" , stats->ngi_frames, stats->sgi_frames); - pos +=scnprintf (buff + pos, bufsz - pos,"SISO/MIMO2\t:\t%d/%d\n" , + pos +=scnprintf (pos, endpos - pos,"SISO/MIMO2\t:\t%d/%d\n" , stats->siso_frames, stats->mimo2_frames); - pos +=scnprintf (buff + pos, bufsz - pos,"FAIL/SCSS\t:\t%d/%d\n" , + pos +=scnprintf (pos, endpos - pos,"FAIL/SCSS\t:\t%d/%d\n" , stats->fail_frames, stats->success_frames); - pos +=scnprintf (buff + pos, bufsz - pos,"MPDUs agg\t:\t%d\n" , + pos +=scnprintf (pos, endpos - pos,"MPDUs agg\t:\t%d\n" , stats->agg_frames); - pos +=scnprintf (buff + pos, bufsz - pos,"A-MPDUs\t\t:\t%d\n" , + pos +=scnprintf (pos, endpos - pos,"A-MPDUs\t\t:\t%d\n" , stats->ampdu_count); - pos +=scnprintf (buff + pos, bufsz - pos,"Avg MPDUs/A-MPDU:\t%d\n" , + pos +=scnprintf (pos, endpos - pos,"Avg MPDUs/A-MPDU:\t%d\n" , stats->ampdu_count >0 ? (stats->agg_frames / stats->ampdu_count) :0 ); - pos +=scnprintf (buff + pos, bufsz - pos,"Last Rates\n" ); + pos +=scnprintf (pos, endpos - pos,"Last Rates\n" ); idx = stats->last_frame_idx -1 ;for (i =0 ; i <ARRAY_SIZE (stats->last_rates); i++) { idx = (idx +1 ) %ARRAY_SIZE (stats->last_rates);if (stats->last_rates[idx] ==0 )continue ; - pos +=scnprintf (buff + pos, bufsz - pos,"Rate[%d]: " , + pos +=scnprintf (pos, endpos - pos,"Rate[%d]: " , (int )(ARRAY_SIZE (stats->last_rates) - i)); - pos +=rs_pretty_print_rate (buff + pos, stats->last_rates[idx]); + pos +=rs_pretty_print_rate (pos, stats->last_rates[idx]); }spin_unlock_bh (&mvm->drv_stats_lock); - ret =simple_read_from_buffer (user_buf, count, ppos, buff, pos); + ret =simple_read_from_buffer (user_buf, count, ppos, buff, pos - buff);kfree (buff);return ret;
Signature · 1 line
1.8.3.2
PATCH 4/35 iwlwifi: mvm: fix quota for D3 image
In reply to Emmanuel GrumbachFrom: Emmanuel Grumbach <[email protected]>
New firmware enforce valid values for the quota in D3. The values given to the firmware when suspending and using WoWLAN where dummy - change them to realistics values.
--- drivers/net/wireless/iwlwifi/mvm/d3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/iwlwifi/mvm/d3.c +2 -2
@@ -846,8 +846,8 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, quota_cmd.quotas[0 ].id_and_color =cpu_to_le32 (FW_CMD_ID_AND_COLOR (mvmvif->phy_ctxt->id, mvmvif->phy_ctxt->color)); - quota_cmd.quotas[0 ].quota =cpu_to_le32 (100 ); - quota_cmd.quotas[0 ].max_duration =cpu_to_le32 (1000 ); + quota_cmd.quotas[0 ].quota =cpu_to_le32 (IWL_MVM_MAX_QUOTA ); + quota_cmd.quotas[0 ].max_duration =cpu_to_le32 (IWL_MVM_MAX_QUOTA );for (i =1 ; i <MAX_BINDINGS ; i++) quota_cmd.quotas[i].id_and_color =cpu_to_le32 (FW_CTXT_INVALID );
Signature · 1 line
1.8.3.2
PATCH 5/35 iwlwifi: nvm: fix VHT capability antenna-dependent fields
In reply to Emmanuel GrumbachFrom: Johannes Berg <[email protected]>
As the antenna dependent fields depend on the firmware file and not the NVM, use those fields in the VHT capability creation.
Additionally, fix the STBC and antenna pattern consistency fields.
--- drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +11 -8
@@ -299,9 +299,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,static void iwl_init_vht_hw_capab (const struct iwl_cfg *cfg,struct iwl_nvm_data *data, -struct ieee80211_sta_vht_cap *vht_cap) +struct ieee80211_sta_vht_cap *vht_cap, +u8 tx_chains,u8 rx_chains) { -int num_ants =num_of_ant (data->valid_rx_ant); +int num_rx_ants =num_of_ant (rx_chains); +int num_tx_ants =num_of_ant (tx_chains); vht_cap->vht_supported = true;
@@ -311,8 +313,10 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,3 <<IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT |7 <<IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT ; -if (num_ants >1 ) +if (num_tx_ants >1 ) vht_cap->cap |=IEEE80211_VHT_CAP_TXSTBC ; +else + vht_cap->cap |=IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN ;if (iwlwifi_mod_params.amsdu_size_8K) vht_cap->cap |=IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 ;
@@ -327,10 +331,8 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,IEEE80211_VHT_MCS_NOT_SUPPORTED <<12 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 14); -if (num_ants ==1 || - cfg->rx_with_siso_diversity) { - vht_cap->cap |=IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | -IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN ; +if (num_rx_ants ==1 || cfg->rx_with_siso_diversity) { + vht_cap->cap |=IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN ;/* this works because NOT_SUPPORTED == 3 */ vht_cap->vht_mcs.rx_mcs_map |=cpu_to_le16 (IEEE80211_VHT_MCS_NOT_SUPPORTED <<2 );
@@ -375,7 +377,8 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,iwl_init_ht_hw_capab (cfg, data, &sband->ht_cap,IEEE80211_BAND_5GHZ , tx_chains, rx_chains);if (enable_vht) -iwl_init_vht_hw_capab (cfg, data, &sband->vht_cap); +iwl_init_vht_hw_capab (cfg, data, &sband->vht_cap, + tx_chains, rx_chains);if (n_channels != n_used) IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
Signature · 1 line
1.8.3.2
PATCH 6/35 iwlwifi: mvm: disable power on P2P client when BSS is added
In reply to Emmanuel GrumbachFrom: Avri Altman <[email protected]>
When power update is initiated on BSS STA while P2P client exists, the power command will be sent only on BSS STA vif ignoring P2P client.
Since the firmware has symmetric constraints on the power save enablement we can simplify the code a bit.
The current firmware doesn't know how to enable power management on P2P client. Even BSS power management must be disabled when a P2P client is added.
Future firmware will support power save on BSS and P2P client as long as they are on different channels.
This was buggy since we didn't disable power management on P2P client interface if BSS added on the same channel.
--- drivers/net/wireless/iwlwifi/mvm/power.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/net/wireless/iwlwifi/mvm/power.c +12 -5
@@ -511,6 +511,7 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,struct iwl_power_constraint {struct ieee80211_vif *bf_vif;struct ieee80211_vif *bss_vif; +struct ieee80211_vif *p2p_vif;u16 bss_phyctx_id;u16 p2p_phyctx_id;bool pm_disabled;
@@ -546,6 +547,10 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,if (mvmvif->phy_ctxt) power_iterator->p2p_phyctx_id = mvmvif->phy_ctxt->id; +/* we should have only one P2P vif */ +WARN_ON (power_iterator->p2p_vif); + power_iterator->p2p_vif = vif; +IWL_DEBUG_POWER (mvm,"p2p: p2p_id=%d, bss_id=%d\n" , power_iterator->p2p_phyctx_id, power_iterator->bss_phyctx_id);
@@ -633,16 +638,18 @@ int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif)return ret; } - ret =iwl_mvm_power_send_cmd (mvm, vif); -if (ret) -return ret; - -if (constraint.bss_vif && vif != constraint.bss_vif) { +if (constraint.bss_vif) { ret =iwl_mvm_power_send_cmd (mvm, constraint.bss_vif);if (ret)return ret; } +if (constraint.p2p_vif) { + ret =iwl_mvm_power_send_cmd (mvm, constraint.p2p_vif); +if (ret) +return ret; + } +if (!constraint.bf_vif)return 0 ;
Signature · 1 line
1.8.3.2
PATCH 7/35 iwlwifi: pcie: enable LP XTAL to reduce power consumption
In reply to Emmanuel GrumbachFrom: Alexander Bondar <[email protected]>
1. Enable LP XTAL to avoid HW bug where device may consume much power if FW is not loaded after device reset. LP XTAL is disabled by default after device HW reset. Configure device's "persistence" mode to avoid resetting XTAL again when SHRD_HW_RST occurs in S3.
2. Add methods to access SHR (shared block memory space) directly from PCI bus w/o need to power up MAC HW.
Shared internal registers (e.g. SHR_APMG_GP1, SHR_APMG_XTAL_CFG)can be accessed directly from PCI bus through SHR arbiter even when MAC HW is powered down. This is possible due to indirect read/write via HEEP_CTRL_WRD_PCIEX_CTRL (0xEC) and HEEP_CTRL_WRD_PCIEX_DATA (0xF4) registers.
Use iwl_write32()/iwl_read32() family to access these registers. The MAC HW need not be powered up so no "grab inc access" is required.
For example, to read from SHR_APMG_GP1 register (0x1DC),
first, write to the control register:
HEEP_CTRL_WRD_PCIEX_CTRL[15:0] = 0x1DC (offset of the SHR_APMG_GP1 register) HEEP_CTRL_WRD_PCIEX_CTRL[29:28] = 2 (read access)
second, read from the data register HEEP_CTRL_WRD_PCIEX_DATA[31:0].
To write the register, first, write to the data register HEEP_CTRL_WRD_PCIEX_DATA[31:0] and then:
HEEP_CTRL_WRD_PCIEX_CTRL[15:0] = 0x1DC (offset of the SHR_APMG_GP1 register) HEEP_CTRL_WRD_PCIEX_CTRL[29:28] = 3 (write access)
--- drivers/net/wireless/iwlwifi/iwl-7000.c | 4 + drivers/net/wireless/iwlwifi/iwl-config.h | 1 + drivers/net/wireless/iwlwifi/iwl-csr.h | 38 +++++++++ drivers/net/wireless/iwlwifi/iwl-io.c | 4 +- drivers/net/wireless/iwlwifi/iwl-io.h | 2 + drivers/net/wireless/iwlwifi/iwl-prph.h | 23 +++++- drivers/net/wireless/iwlwifi/pcie/trans.c | 131 ++++++++++++++++++++++++++++++ 7 files changed, 200 insertions(+), 3 deletions(-)
drivers/net/wireless/iwlwifi/iwl-7000.c +4 -0
@@ -134,6 +134,7 @@ const struct iwl_cfg iwl7260_2ac_cfg = { .nvm_ver = IWL7260_NVM_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION, .host_interrupt_operation_mode = true, + .lp_xtal_workaround = true, };const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
@@ -145,6 +146,7 @@ const struct iwl_cfg iwl7260_2ac_cfg_high_temp = { .nvm_calib_ver = IWL7260_TX_POWER_VERSION, .high_temp = true, .host_interrupt_operation_mode = true, + .lp_xtal_workaround = true, };const struct iwl_cfg iwl7260_2n_cfg = {
@@ -155,6 +157,7 @@ const struct iwl_cfg iwl7260_2n_cfg = { .nvm_ver = IWL7260_NVM_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION, .host_interrupt_operation_mode = true, + .lp_xtal_workaround = true, };const struct iwl_cfg iwl7260_n_cfg = {
@@ -165,6 +168,7 @@ const struct iwl_cfg iwl7260_n_cfg = { .nvm_ver = IWL7260_NVM_VERSION, .nvm_calib_ver = IWL7260_TX_POWER_VERSION, .host_interrupt_operation_mode = true, + .lp_xtal_workaround = true, };const struct iwl_cfg iwl3160_2ac_cfg = {
drivers/net/wireless/iwlwifi/iwl-config.h +1 -0
@@ -262,6 +262,7 @@ struct iwl_cfg {bool high_temp;bool d0i3;u8 nvm_hw_section_num; +bool lp_xtal_workaround;const struct iwl_pwr_tx_backoff *pwr_tx_backoffs; };
drivers/net/wireless/iwlwifi/iwl-csr.h +38 -0
@@ -139,6 +139,13 @@#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c)/* +* CSR HW resources monitor registers +*/ +#define CSR_MONITOR_CFG_REG (CSR_BASE+0x214) +#define CSR_MONITOR_STATUS_REG (CSR_BASE+0x228) +#define CSR_MONITOR_XTAL_RESOURCES (0x00000010) + +/* * CSR Hardware Revision Workaround Register. Indicates hardware rev; * "step" determines CCK backoff for txpower calculation. Used for 4965 only. * See also CSR_HW_REV register.
@@ -173,6 +180,7 @@#define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000)/* PCI_OWN_SEM */ #define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000)/* ME_OWN */ #define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000)/* WAKE_ME */ +#define CSR_HW_IF_CONFIG_REG_PERSIST_MODE (0x40000000)/* PERSISTENCE */ #define CSR_INT_PERIODIC_DIS (0x00)/* disable periodic int*/ #define CSR_INT_PERIODIC_ENA (0xFF)/* 255*32 usec ~ 8 msec*/
@@ -240,6 +248,7 @@* 001 -- MAC power-down * 010 -- PHY (radio) power-down * 011 -- Error +* 10: XTAL ON request * 9-6: SYS_CONFIG * Indicates current system configuration, reflecting pins on chip * as forced high/low by device circuit board.
@@ -271,6 +280,7 @@#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004)#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)
@@ -396,6 +406,34 @@#define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27)/* +* SHR target access (Shared block memory space) +* +* Shared internal registers can be accessed directly from PCI bus through SHR +* arbiter without need for the MAC HW to be powered up. This is possible due to +* indirect read/write via HEEP_CTRL_WRD_PCIEX_CTRL (0xEC) and +* HEEP_CTRL_WRD_PCIEX_DATA (0xF4) registers. +* +* Use iwl_write32()/iwl_read32() family to access these registers. The MAC HW +* need not be powered up so no "grab inc access" is required. +*/ + +/* +* Registers for accessing shared registers (e.g. SHR_APMG_GP1, +* SHR_APMG_XTAL_CFG). For example, to read from SHR_APMG_GP1 register (0x1DC), +* first, write to the control register: +* HEEP_CTRL_WRD_PCIEX_CTRL[15:0] = 0x1DC (offset of the SHR_APMG_GP1 register) +* HEEP_CTRL_WRD_PCIEX_CTRL[29:28] = 2 (read access) +* second, read from the data register HEEP_CTRL_WRD_PCIEX_DATA[31:0]. +* +* To write the register, first, write to the data register +* HEEP_CTRL_WRD_PCIEX_DATA[31:0] and then: +* HEEP_CTRL_WRD_PCIEX_CTRL[15:0] = 0x1DC (offset of the SHR_APMG_GP1 register) +* HEEP_CTRL_WRD_PCIEX_CTRL[29:28] = 3 (write access) +*/ +#define HEEP_CTRL_WRD_PCIEX_CTRL_REG (CSR_BASE+0x0ec) +#define HEEP_CTRL_WRD_PCIEX_DATA_REG (CSR_BASE+0x0f4) + +/* * HBUS (Host-side Bus) * * HBUS registers are mapped directly into PCI bus space, but are used
drivers/net/wireless/iwlwifi/iwl-io.c +2 -2
@@ -93,14 +93,14 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, }IWL_EXPORT_SYMBOL (iwl_poll_direct_bit); -static inline u32 __iwl_read_prph (struct iwl_trans *trans,u32 ofs) +u32 __iwl_read_prph (struct iwl_trans *trans,u32 ofs) {u32 val =iwl_trans_read_prph (trans, ofs);trace_iwlwifi_dev_ioread_prph32 (trans->dev, ofs, val);return val; } -static inline void __iwl_write_prph (struct iwl_trans *trans,u32 ofs,u32 val) +void __iwl_write_prph (struct iwl_trans *trans,u32 ofs,u32 val) {trace_iwlwifi_dev_iowrite_prph32 (trans->dev, ofs, val);iwl_trans_write_prph (trans, ofs, val);
drivers/net/wireless/iwlwifi/iwl-io.h +2 -0
@@ -70,7 +70,9 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg);void iwl_write_direct32 (struct iwl_trans *trans,u32 reg,u32 value); +u32 __iwl_read_prph (struct iwl_trans *trans,u32 ofs);u32 iwl_read_prph (struct iwl_trans *trans,u32 ofs); +void __iwl_write_prph (struct iwl_trans *trans,u32 ofs,u32 val);void iwl_write_prph (struct iwl_trans *trans,u32 ofs,u32 val);int iwl_poll_prph_bit (struct iwl_trans *trans,u32 addr,u32 bits,u32 mask,int timeout);
drivers/net/wireless/iwlwifi/iwl-prph.h +22 -1
@@ -95,7 +95,8 @@#define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0)/* bit 8:5 */ #define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060) -#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) +#define APMG_PCIDEV_STT_VAL_PERSIST_DIS (0x00000200) +#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)#define APMG_RTC_INT_STT_RFKILL (0x10000000)
@@ -105,6 +106,26 @@/* Device NMI register */ #define DEVICE_SET_NMI_REG 0x00a01c30 +/* Shared registers (0x0..0x3ff, via target indirect or periphery */ +#define SHR_BASE 0x00a10000 + +/* Shared GP1 register */ +#define SHR_APMG_GP1_REG 0x01dc +#define SHR_APMG_GP1_REG_PRPH (SHR_BASE + SHR_APMG_GP1_REG) +#define SHR_APMG_GP1_WF_XTAL_LP_EN 0x00000004 +#define SHR_APMG_GP1_CHICKEN_BIT_SELECT 0x80000000 + +/* Shared DL_CFG register */ +#define SHR_APMG_DL_CFG_REG 0x01c4 +#define SHR_APMG_DL_CFG_REG_PRPH (SHR_BASE + SHR_APMG_DL_CFG_REG) +#define SHR_APMG_DL_CFG_RTCS_CLK_SELECTOR_MSK 0x000000c0 +#define SHR_APMG_DL_CFG_RTCS_CLK_INTERNAL_XTAL 0x00000080 +#define SHR_APMG_DL_CFG_DL_CLOCK_POWER_UP 0x00000100 + +/* Shared APMG_XTAL_CFG register */ +#define SHR_APMG_XTAL_CFG_REG 0x1c0 +#define SHR_APMG_XTAL_CFG_XTAL_ON_REQ 0x80000000 +/* * Device reset for family 8000 * write to bit 24 in order to reset the CPU
drivers/net/wireless/iwlwifi/pcie/trans.c +131 -0
161 lines not on this page · raw message
Signature · 1 line
1.8.3.2
PATCH 8/35 iwlwifi: return whether to stop from rfkill method
In reply to Emmanuel GrumbachFrom: Johannes Berg <[email protected]>
When indicating RF-kill toggle to the higher layer, that may in turn call back to the transport (for MVM at least) to turn off the device quickly. Instead of that, allow it to return whether or not the device should be turned off, this gets rid of the call indirection and will help make the API more consistent when we go back to non-threaded interrupts again for PCIe.
--- drivers/net/wireless/iwlwifi/dvm/main.c | 4 +++- drivers/net/wireless/iwlwifi/iwl-op-mode.h | 11 ++++++----- drivers/net/wireless/iwlwifi/mvm/ops.c | 6 +++--- drivers/net/wireless/iwlwifi/pcie/drv.c | 2 +- drivers/net/wireless/iwlwifi/pcie/internal.h | 2 ++ drivers/net/wireless/iwlwifi/pcie/rx.c | 2 +- drivers/net/wireless/iwlwifi/pcie/trans.c | 12 +++++++++--- 7 files changed, 25 insertions(+), 14 deletions(-)
drivers/net/wireless/iwlwifi/dvm/main.c +3 -1
@@ -2035,7 +2035,7 @@ static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)ieee80211_free_txskb (priv->hw, skb); } -static void iwl_set_hw_rfkill_state (struct iwl_op_mode *op_mode,bool state) +static bool iwl_set_hw_rfkill_state (struct iwl_op_mode *op_mode,bool state) {struct iwl_priv *priv =IWL_OP_MODE_GET_DVM (op_mode);
@@ -2045,6 +2045,8 @@ static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)clear_bit (STATUS_RF_KILL_HW , &priv->status);wiphy_rfkill_set_hw_state (priv->hw->wiphy, state); + +return false; }static const struct iwl_op_mode_ops iwl_dvm_ops = {
drivers/net/wireless/iwlwifi/iwl-op-mode.h +6 -5
@@ -119,7 +119,8 @@ struct iwl_cfg;* @queue_not_full: notifies that a HW queue is not full any more. * Must be atomic and called with BH disabled. * @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that -* the radio is killed. May sleep. +* the radio is killed. Return %true if the device should be stopped by +* the transport immediately after the call. May sleep. * @free_skb: allows the transport layer to free skbs that haven't been * reclaimed by the op_mode. This can happen when the driver is freed and * there are Tx packets pending in the transport layer.
@@ -144,7 +145,7 @@ struct iwl_op_mode_ops { struct iwl_device_cmd *cmd);void (*queue_full)(struct iwl_op_mode *op_mode,int queue);void (*queue_not_full)(struct iwl_op_mode *op_mode,int queue); -void (*hw_rf_kill)(struct iwl_op_mode *op_mode,bool state); +bool (*hw_rf_kill)(struct iwl_op_mode *op_mode,bool state);void (*free_skb)(struct iwl_op_mode *op_mode,struct sk_buff *skb);void (*nic_error)(struct iwl_op_mode *op_mode);void (*cmd_queue_full)(struct iwl_op_mode *op_mode);
@@ -195,11 +196,11 @@ static inline void iwl_op_mode_queue_not_full(struct iwl_op_mode *op_mode, op_mode->ops->queue_not_full (op_mode, queue); } -static inline void iwl_op_mode_hw_rf_kill (struct iwl_op_mode *op_mode, -bool state) +static inline bool __must_check +iwl_op_mode_hw_rf_kill (struct iwl_op_mode *op_mode,bool state) {might_sleep (); - op_mode->ops->hw_rf_kill (op_mode, state); +return op_mode->ops->hw_rf_kill (op_mode, state); } static inline void iwl_op_mode_free_skb(struct iwl_op_mode *op_mode,
drivers/net/wireless/iwlwifi/mvm/ops.c +3 -3
@@ -690,7 +690,7 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state)wiphy_rfkill_set_hw_state (mvm->hw->wiphy,iwl_mvm_is_radio_killed (mvm)); } -static void iwl_mvm_set_hw_rfkill_state (struct iwl_op_mode *op_mode,bool state) +static bool iwl_mvm_set_hw_rfkill_state (struct iwl_op_mode *op_mode,bool state) {struct iwl_mvm *mvm =IWL_OP_MODE_GET_MVM (op_mode);
@@ -699,9 +699,9 @@ static void iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)else clear_bit (IWL_MVM_STATUS_HW_RFKILL , &mvm->status); -if (state && mvm->cur_ucode !=IWL_UCODE_INIT ) -iwl_trans_stop_device (mvm->trans);wiphy_rfkill_set_hw_state (mvm->hw->wiphy,iwl_mvm_is_radio_killed (mvm)); + +return state && mvm->cur_ucode !=IWL_UCODE_INIT ; }static void iwl_mvm_free_skb (struct iwl_op_mode *op_mode,struct sk_buff *skb)
drivers/net/wireless/iwlwifi/pcie/drv.c +1 -1
@@ -561,7 +561,7 @@ static int iwl_pci_resume(struct device *device)iwl_enable_rfkill_int (trans); hw_rfkill =iwl_is_rfkill_set (trans); -iwl_op_mode_hw_rf_kill (trans->op_mode, hw_rfkill); +iwl_trans_pcie_rf_kill (trans, hw_rfkill);return 0 ; }
drivers/net/wireless/iwlwifi/pcie/internal.h +2 -0
@@ -488,4 +488,6 @@ static inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans, __iwl_trans_pcie_set_bits_mask(trans, reg, mask, mask); } +void iwl_trans_pcie_rf_kill (struct iwl_trans *trans,bool state); +#endif /* __iwl_trans_int_pcie_h__ */
drivers/net/wireless/iwlwifi/pcie/rx.c +1 -1
@@ -994,7 +994,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) isr_stats->rfkill++; -iwl_op_mode_hw_rf_kill (trans->op_mode, hw_rfkill); +iwl_trans_pcie_rf_kill (trans, hw_rfkill);if (hw_rfkill) {set_bit (STATUS_RFKILL , &trans->status); if (test_and_clear_bit(STATUS_SYNC_HCMD_ACTIVE,
drivers/net/wireless/iwlwifi/pcie/trans.c +9 -3
@@ -770,7 +770,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,set_bit (STATUS_RFKILL , &trans->status); else clear_bit(STATUS_RFKILL, &trans->status); -iwl_op_mode_hw_rf_kill (trans->op_mode, hw_rfkill); +iwl_trans_pcie_rf_kill (trans, hw_rfkill);if (hw_rfkill && !run_in_rfkill)return -ERFKILL ;
@@ -885,7 +885,13 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)else clear_bit (STATUS_RFKILL , &trans->status);if (hw_rfkill != was_hw_rfkill) -iwl_op_mode_hw_rf_kill (trans->op_mode, hw_rfkill); +iwl_trans_pcie_rf_kill (trans, hw_rfkill); +} + +void iwl_trans_pcie_rf_kill (struct iwl_trans *trans,bool state) +{ +if (iwl_op_mode_hw_rf_kill (trans->op_mode, state)) +iwl_trans_pcie_stop_device (trans); }static void iwl_trans_pcie_d3_suspend (struct iwl_trans *trans,bool test)
@@ -994,7 +1000,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)set_bit (STATUS_RFKILL , &trans->status); else clear_bit(STATUS_RFKILL, &trans->status); -iwl_op_mode_hw_rf_kill (trans->op_mode, hw_rfkill); +iwl_trans_pcie_rf_kill (trans, hw_rfkill);return 0 ; }
Signature · 1 line
1.8.3.2
PATCH 9/35 iwlwifi: mvm: fix scan offload for BGN SKU
In reply to Emmanuel GrumbachFrom: Emmanuel Grumbach <[email protected]>
BGN SKU won't scan on 5.2GHz obviously, but the firmware still expects the driver to reserve space for the the probe request for the 5.2GHz band.
Fix this by allocating space and leave it empty.
This fixes https://bugzilla.kernel.org/show_bug.cgi?id=69541
--- drivers/net/wireless/iwlwifi/mvm/scan.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
drivers/net/wireless/iwlwifi/mvm/scan.c +1 -7
@@ -709,7 +709,6 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,struct cfg80211_sched_scan_request *req, struct ieee80211_sched_scan_ies *ies) { - int supported_bands = 0; int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels;int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ ].n_channels;int head =0 ;
@@ -726,13 +725,8 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,lockdep_assert_held (&mvm->mutex); -if (band_2ghz) - supported_bands++; -if (band_5ghz) - supported_bands++; - cmd_len =sizeof (struct iwl_scan_offload_cfg ) + - supported_bands *SCAN_OFFLOAD_PROBE_REQ_SIZE ; +2 *SCAN_OFFLOAD_PROBE_REQ_SIZE ; scan_cfg =kzalloc (cmd_len,GFP_KERNEL );if (!scan_cfg)
Signature · 1 line
1.8.3.2
PATCH 10/35 iwlwifi: mvm: check for d0i3 fw capability
In reply to Emmanuel GrumbachFrom: Eliad Peller <[email protected]>
Check for both cfg->d0i3 and fw d0i3 support in order to enable d0i3 support.
--- drivers/net/wireless/iwlwifi/iwl-fw.h | 8 ++++++++ drivers/net/wireless/iwlwifi/mvm/mac80211.c | 6 +++--- drivers/net/wireless/iwlwifi/mvm/mvm.h | 6 ++++++ 3 files changed, 17 insertions(+), 3 deletions(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +8 -0
@@ -125,6 +125,14 @@ enum iwl_ucode_tlv_flag { IWL_UCODE_TLV_FLAGS_GO_UAPSD = BIT(30), }; +/** +* enum iwl_ucode_tlv_capa - ucode capabilities +* @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3 +*/ +enum iwl_ucode_tlv_capa { +IWL_UCODE_TLV_CAPA_D0I3_SUPPORT =BIT (0 ), +}; +/* The default calibrate table size if not specified by firmware file */ #define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18#define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE 19
drivers/net/wireless/iwlwifi/mvm/mac80211.c +3 -3
@@ -205,7 +205,7 @@ static const struct iwl_fw_bcast_filter iwl_mvm_default_bcast_filters[] = {void iwl_mvm_ref (struct iwl_mvm *mvm,enum iwl_mvm_ref_type ref_type) { -if (!mvm->trans->cfg->d0i3) +if (!iwl_mvm_is_d0i3_supported (mvm))return ;IWL_DEBUG_RPM (mvm,"Take mvm reference - type %d\n" , ref_type);
@@ -215,7 +215,7 @@ void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)void iwl_mvm_unref (struct iwl_mvm *mvm,enum iwl_mvm_ref_type ref_type) { -if (!mvm->trans->cfg->d0i3) +if (!iwl_mvm_is_d0i3_supported (mvm))return ;IWL_DEBUG_RPM (mvm,"Leave mvm reference - type %d\n" , ref_type);
@@ -228,7 +228,7 @@ iwl_mvm_unref_all_except(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref) {int i; -if (!mvm->trans->cfg->d0i3) +if (!iwl_mvm_is_d0i3_supported (mvm))return ;for_each_set_bit (i, mvm->ref_bitmap,IWL_MVM_REF_COUNT ) {
drivers/net/wireless/iwlwifi/mvm/mvm.h +6 -0
@@ -656,6 +656,12 @@ iwl_mvm_sta_from_staid_protected(struct iwl_mvm *mvm, u8 sta_id)return iwl_mvm_sta_from_mac80211 (sta); } +static inline bool iwl_mvm_is_d0i3_supported (struct iwl_mvm *mvm) +{ +return mvm->trans->cfg->d0i3 && + (mvm->fw->ucode_capa.capa[0 ] &IWL_UCODE_TLV_CAPA_D0I3_SUPPORT ); +} +extern const u8 iwl_mvm_ac_to_tx_fifo[];struct iwl_rate_info {
Signature · 1 line
1.8.3.2
PATCH 11/35 iwlwifi: mvm: wait for stop sched-scan completion
In reply to Emmanuel GrumbachFrom: Arik Nemtsov <[email protected]>
cfg80211 assumes a scheduled scan is stopped synchronously. Wait for the FW before returning to caller.
Don't do anything in the async handler in the stop-from-above flow. There's no need to call the mac80211 sched-scan completion as the cleanup will be automatic. Make sure the async handler is called before the next incoming scan changes the scan_status by flushing the async handlers after all invocations.
--- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 24 +++++------------ drivers/net/wireless/iwlwifi/mvm/mvm.h | 7 ++++- drivers/net/wireless/iwlwifi/mvm/scan.c | 42 ++++++++++++++++++++++------- 3 files changed, 46 insertions(+), 27 deletions(-)
drivers/net/wireless/iwlwifi/mvm/mac80211.c +7 -17
@@ -1419,8 +1419,6 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req) {struct iwl_mvm *mvm =IWL_MAC80211_GET_MVM (hw); -struct iwl_notification_wait wait_scan_done; -static const u8 scan_done_notif[] = {SCAN_OFFLOAD_COMPLETE , };int ret;if (req->n_channels ==0 || req->n_channels >MAX_NUM_SCAN_CHANNELS )
@@ -1430,22 +1428,11 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,switch (mvm->scan_status) {case IWL_MVM_SCAN_SCHED : -iwl_init_notification_wait (&mvm->notif_wait, &wait_scan_done, - scan_done_notif, -ARRAY_SIZE (scan_done_notif), -NULL ,NULL ); -iwl_mvm_sched_scan_stop (mvm); - ret =iwl_wait_notification (&mvm->notif_wait, - &wait_scan_done,HZ ); + ret =iwl_mvm_sched_scan_stop (mvm);if (ret) { ret = -EBUSY ; goto out; } -/* iwl_mvm_rx_scan_offload_complete_notif() will be called -* soon but will not reset the scan status as it won't be -* IWL_MVM_SCAN_SCHED any more since we queue the next scan -* immediately (below) -*/ break ;case IWL_MVM_SCAN_NONE :break ;
@@ -1461,7 +1448,8 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,iwl_mvm_unref (mvm,IWL_MVM_REF_SCAN ); out:mutex_unlock (&mvm->mutex); - +/* make sure to flush the Rx handler before the next scan arrives */ +iwl_mvm_wait_for_async_handlers (mvm);return ret; }
@@ -1751,12 +1739,14 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif) {struct iwl_mvm *mvm =IWL_MAC80211_GET_MVM (hw); +int ret;mutex_lock (&mvm->mutex); -iwl_mvm_sched_scan_stop (mvm); + ret =iwl_mvm_sched_scan_stop (mvm);mutex_unlock (&mvm->mutex); +iwl_mvm_wait_for_async_handlers (mvm); -return 0 ; +return ret; } static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
drivers/net/wireless/iwlwifi/mvm/mvm.h +6 -1
@@ -712,6 +712,11 @@ static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; }int iwl_mvm_flush_tx_path (struct iwl_mvm *mvm,u32 tfd_msk,bool sync);void iwl_mvm_async_handlers_purge (struct iwl_mvm *mvm); +static inline void iwl_mvm_wait_for_async_handlers (struct iwl_mvm *mvm) +{ +flush_work (&mvm->async_handlers_wk); +} +/* Statistics */ int iwl_mvm_rx_reply_statistics(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
@@ -813,7 +818,7 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, struct cfg80211_sched_scan_request *req);int iwl_mvm_sched_scan_start (struct iwl_mvm *mvm,struct cfg80211_sched_scan_request *req); -void iwl_mvm_sched_scan_stop (struct iwl_mvm *mvm); +int iwl_mvm_sched_scan_stop (struct iwl_mvm *mvm);int iwl_mvm_rx_sched_scan_results (struct iwl_mvm *mvm,struct iwl_rx_cmd_buffer *rxb,struct iwl_device_cmd *cmd);
drivers/net/wireless/iwlwifi/mvm/scan.c +33 -9
69 lines not on this page · raw message
Signature · 1 line
1.8.3.2
PATCH 12/35 iwlwifi: mvm: abort scan on sched_scan request
In reply to Emmanuel GrumbachFrom: Arik Nemtsov <[email protected]>
A scheduled scan is a more persistent setting and should take priority over temporary regular scans. Abort the regular when a sched_scan request arrives and then request the sched_scan.
The kernel API allows sending a sched_scan without canceling a regular scan in progress, so this is our way to abstract the FW's limitations.
Make the scan-cancel Rx handler async and flush after invocation to ensure new scans can't creep in before it.
--- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 25 ++++++++++++++++++++++--- drivers/net/wireless/iwlwifi/mvm/mvm.h | 2 +- drivers/net/wireless/iwlwifi/mvm/ops.c | 2 +- drivers/net/wireless/iwlwifi/mvm/scan.c | 18 +++++++++--------- 4 files changed, 33 insertions(+), 14 deletions(-)
drivers/net/wireless/iwlwifi/mvm/mac80211.c +22 -3
@@ -1708,9 +1708,26 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,mutex_lock (&mvm->mutex); -if (mvm->scan_status !=IWL_MVM_SCAN_NONE ) { -IWL_DEBUG_SCAN (mvm, -"SCHED SCAN request during internal scan - abort\n" ); +switch (mvm->scan_status) { +case IWL_MVM_SCAN_OS : +IWL_DEBUG_SCAN (mvm,"Stopping previous scan for sched_scan\n" ); + ret =iwl_mvm_cancel_scan (mvm); +if (ret) { + ret = -EBUSY ; + goto out; + } + +/* +* iwl_mvm_rx_scan_complete() will be called soon but will +* not reset the scan status as it won't be IWL_MVM_SCAN_OS +* any more since we queue the next scan immediately (below). +* We make sure it is called before the next scan starts by +* flushing the async-handlers work. +*/ +break ; +case IWL_MVM_SCAN_NONE : +break ; +default : ret = -EBUSY ; goto out; }
@@ -1732,6 +1749,8 @@ err: mvm->scan_status =IWL_MVM_SCAN_NONE ; out:mutex_unlock (&mvm->mutex); +/* make sure to flush the Rx handler before the next scan arrives */ +iwl_mvm_wait_for_async_handlers (mvm);return ret; }
drivers/net/wireless/iwlwifi/mvm/mvm.h +1 -1
@@ -804,7 +804,7 @@ int iwl_mvm_rx_scan_response(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd);int iwl_mvm_rx_scan_complete (struct iwl_mvm *mvm,struct iwl_rx_cmd_buffer *rxb,struct iwl_device_cmd *cmd); -void iwl_mvm_cancel_scan (struct iwl_mvm *mvm); +int iwl_mvm_cancel_scan (struct iwl_mvm *mvm);/* Scheduled scan */ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
drivers/net/wireless/iwlwifi/mvm/ops.c +1 -1
@@ -226,7 +226,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {RX_HANDLER (EOSP_NOTIFICATION , iwl_mvm_rx_eosp_notif, false),RX_HANDLER (SCAN_REQUEST_CMD , iwl_mvm_rx_scan_response, false), -RX_HANDLER (SCAN_COMPLETE_NOTIFICATION , iwl_mvm_rx_scan_complete, false), +RX_HANDLER (SCAN_COMPLETE_NOTIFICATION , iwl_mvm_rx_scan_complete, true),RX_HANDLER (SCAN_OFFLOAD_COMPLETE , iwl_mvm_rx_scan_offload_complete_notif, true), RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_sched_scan_results,
drivers/net/wireless/iwlwifi/mvm/scan.c +9 -9
@@ -402,10 +402,13 @@ int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,struct iwl_rx_packet *pkt =rxb_addr (rxb);struct iwl_scan_complete_notif *notif = (void *)pkt->data; +lockdep_assert_held (&mvm->mutex); +IWL_DEBUG_SCAN (mvm,"Scan complete: status=0x%x scanned channels=%d\n" , notif->status, notif->scanned_channels); - mvm->scan_status =IWL_MVM_SCAN_NONE ; +if (mvm->scan_status ==IWL_MVM_SCAN_OS ) + mvm->scan_status =IWL_MVM_SCAN_NONE ;ieee80211_scan_completed (mvm->hw, notif->status !=SCAN_COMP_STATUS_OK );iwl_mvm_unref (mvm,IWL_MVM_REF_SCAN );
@@ -466,7 +469,7 @@ static bool iwl_mvm_scan_abort_notif(struct iwl_notif_wait_data *notif_wait, }; } -void iwl_mvm_cancel_scan (struct iwl_mvm *mvm) +int iwl_mvm_cancel_scan (struct iwl_mvm *mvm) {struct iwl_notification_wait wait_scan_abort;static const u8 scan_abort_notif[] = {SCAN_ABORT_CMD ,
@@ -474,13 +477,13 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm)int ret;if (mvm->scan_status ==IWL_MVM_SCAN_NONE ) -return ; +return 0 ;if (iwl_mvm_is_radio_killed (mvm)) {ieee80211_scan_completed (mvm->hw, true);iwl_mvm_unref (mvm,IWL_MVM_REF_SCAN ); mvm->scan_status =IWL_MVM_SCAN_NONE ; -return ; +return 0 ; } iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort,
@@ -495,14 +498,11 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm) goto out_remove_notif; } - ret =iwl_wait_notification (&mvm->notif_wait, &wait_scan_abort,1 *HZ ); -if (ret) -IWL_ERR (mvm,"%s - failed on timeout\n" , __func__); - -return ; +return iwl_wait_notification (&mvm->notif_wait, &wait_scan_abort,HZ ); out_remove_notif:iwl_remove_notification (&mvm->notif_wait, &wait_scan_abort); +return ret; } int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
Signature · 1 line
1.8.3.2
PATCH 13/35 iwlwifi: mvm: BT Coex add support for Co-running block
In reply to Emmanuel GrumbachFrom: Emmanuel Grumbach <[email protected]>
7265 features a new calibration which is called antenna coupling. The purpose of this calibration (which isn't really a calibration), is to measure the isolation between the antennas and that can give us useful information for the Coex modules.
With this information, we can tune the LookUpTables (LUTs) that define the BT / WiFi contention policy.
The LUTs currently contain dummy values - but they will be updated soon.
While at it, change the current code to stop duplicate the host command while sending. This was needed back then, when the command was short enough to be allocated on the stack. Since then, the command grew a lot and is now allocated on the heap - hence we can use the NOCOPY option instead.
--- drivers/net/wireless/iwlwifi/mvm/bt-coex.c | 291 +++++++++++++++++++++- drivers/net/wireless/iwlwifi/mvm/constants.h | 1 + drivers/net/wireless/iwlwifi/mvm/debugfs.c | 3 + drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h | 2 + drivers/net/wireless/iwlwifi/mvm/fw-api.h | 1 + drivers/net/wireless/iwlwifi/mvm/mvm.h | 5 + drivers/net/wireless/iwlwifi/mvm/ops.c | 3 + 7 files changed, 303 insertions(+), 3 deletions(-)
drivers/net/wireless/iwlwifi/mvm/bt-coex.c +288 -3
@@ -305,6 +305,215 @@ static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = { cpu_to_le32(0x33113311), }; +struct corunning_block_luts { +u8 range; +__le32 lut20[BT_COEX_CORUN_LUT_SIZE ]; +}; + +/* +* Ranges for the antenna coupling calibration / co-running block LUT: +* LUT0: [ 0, 12[ +* LUT1: [12, 20[ +* LUT2: [20, 21[ +* LUT3: [21, 23[ +* LUT4: [23, 27[ +* LUT5: [27, 30[ +* LUT6: [30, 32[ +* LUT7: [32, 33[ +* LUT8: [33, - [ +*/ +static const struct corunning_block_luts antenna_coupling_ranges[] = { + { + .range =0 , + .lut20 = { +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), + }, + }, + { + .range =12 , + .lut20 = { +cpu_to_le32 (0x00000001 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), + }, + }, + { + .range =20 , + .lut20 = { +cpu_to_le32 (0x00000002 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), + }, + }, + { + .range =21 , + .lut20 = { +cpu_to_le32 (0x00000003 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), + }, + }, + { + .range =23 , + .lut20 = { +cpu_to_le32 (0x00000004 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), + }, + }, + { + .range =27 , + .lut20 = { +cpu_to_le32 (0x00000005 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), + }, + }, + { + .range =30 , + .lut20 = { +cpu_to_le32 (0x00000006 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), + }, + }, + { + .range =32 , + .lut20 = { +cpu_to_le32 (0x00000007 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), + }, + }, + { + .range =33 , + .lut20 = { +cpu_to_le32 (0x00000008 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), +cpu_to_le32 (0x00000000 ),cpu_to_le32 (0x00000000 ), + }, + }, +}; +static enum iwl_bt_coex_lut_type iwl_get_coex_type (struct iwl_mvm *mvm,const struct ieee80211_vif *vif) {
@@ -390,8 +599,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)BT_VALID_LUT |BT_VALID_WIFI_RX_SW_PRIO_BOOST |BT_VALID_WIFI_TX_SW_PRIO_BOOST | -BT_VALID_CORUN_LUT_20 | -BT_VALID_CORUN_LUT_40 |BT_VALID_ANT_ISOLATION |BT_VALID_ANT_ISOLATION_THRS | BT_VALID_TXTX_DELTA_FREQ_THRS |
@@ -401,6 +608,12 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)if (IWL_MVM_BT_COEX_SYNC2SCO ) bt_cmd->flags |=cpu_to_le32 (BT_COEX_SYNC2SCO ); +if (IWL_MVM_BT_COEX_CORUNNING ) { + bt_cmd->valid_bit_msk =cpu_to_le32 (BT_VALID_CORUN_LUT_20 | +BT_VALID_CORUN_LUT_40 ); + bt_cmd->flags |=cpu_to_le32 (BT_COEX_CORUNNING ); + } +if (mvm->cfg->bt_shared_single_ant)memcpy (&bt_cmd->decision_lut, iwl_single_shared_ant,sizeof (iwl_single_shared_ant));
@@ -408,6 +621,12 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)memcpy (&bt_cmd->decision_lut, iwl_combined_lookup,sizeof (iwl_combined_lookup)); +/* Take first Co-running block LUT to get started */ +memcpy (bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[0 ].lut20, +sizeof (bt_cmd->bt4_corun_lut20)); +memcpy (bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[0 ].lut20, +sizeof (bt_cmd->bt4_corun_lut40)); +memcpy (&bt_cmd->bt_prio_boost, iwl_bt_prio_boost,sizeof (iwl_bt_prio_boost)); memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut,
@@ -498,7 +717,7 @@ int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable)struct iwl_host_cmd cmd = { .id =BT_CONFIG , .len = {sizeof (*bt_cmd), }, - .dataflags = {IWL_HCMD_DFL_DUP , }, + .dataflags = {IWL_HCMD_DFL_NOCOPY , }, .flags =CMD_ASYNC , };struct iwl_mvm_sta *mvmsta;
@@ -993,3 +1212,69 @@ void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm)iwl_mvm_bt_coex_notif_handle (mvm); } + +int iwl_mvm_rx_ant_coupling_notif (struct iwl_mvm *mvm, +struct iwl_rx_cmd_buffer *rxb, +struct iwl_device_cmd *dev_cmd) +{ +struct iwl_rx_packet *pkt =rxb_addr (rxb); +u32 ant_isolation =le32_to_cpup ((void *)pkt->data); +u8 __maybe_unused lower_bound, upper_bound; +u8 lut; + +struct iwl_bt_coex_cmd *bt_cmd; +struct iwl_host_cmd cmd = { + .id =BT_CONFIG , + .len = {sizeof (*bt_cmd), }, + .dataflags = {IWL_HCMD_DFL_NOCOPY , }, + .flags =CMD_SYNC , + }; + +if (!IWL_MVM_BT_COEX_CORUNNING ) +return 0 ; + +lockdep_assert_held (&mvm->mutex); + +if (ant_isolation == mvm->last_ant_isol) +return 0 ; + +for (lut =0 ; lut <ARRAY_SIZE (antenna_coupling_ranges) -1 ; lut++) +if (ant_isolation < antenna_coupling_ranges[lut +1 ].range) +break ; + + lower_bound = antenna_coupling_ranges[lut].range; + +if (lut <ARRAY_SIZE (antenna_coupling_ranges) -1 ) + upper_bound = antenna_coupling_ranges[lut +1 ].range; +else + upper_bound = antenna_coupling_ranges[lut].range; + +IWL_DEBUG_COEX (mvm,"Antenna isolation=%d in range [%d,%d[, lut=%d\n" , + ant_isolation, lower_bound, upper_bound, lut); + + mvm->last_ant_isol = ant_isolation; + +if (mvm->last_corun_lut == lut) +return 0 ; + + mvm->last_corun_lut = lut; + + bt_cmd =kzalloc (sizeof (*bt_cmd),GFP_KERNEL ); +if (!bt_cmd) +return 0 ; + cmd.data[0 ] = bt_cmd; + + bt_cmd->flags =cpu_to_le32 (BT_COEX_NW ); + bt_cmd->valid_bit_msk |=cpu_to_le32 (BT_VALID_ENABLE | +BT_VALID_CORUN_LUT_20 | +BT_VALID_CORUN_LUT_40 ); + +/* For the moment, use the same LUT for 20GHz and 40GHz */ +memcpy (bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[lut].lut20, +sizeof (bt_cmd->bt4_corun_lut20)); + +memcpy (bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20, +sizeof (bt_cmd->bt4_corun_lut40)); + +return 0 ; +}
drivers/net/wireless/iwlwifi/mvm/constants.h +1 -0
@@ -82,5 +82,6 @@#define IWL_MVM_LOWLAT_SINGLE_BINDING_MAXDUR 24/* TU */ #define IWL_MVM_LOWLAT_DUAL_BINDING_MAXDUR 24/* TU */ #define IWL_MVM_BT_COEX_SYNC2SCO 1 +#define IWL_MVM_BT_COEX_CORUNNING 1#endif /* __MVM_CONSTANTS_H */
drivers/net/wireless/iwlwifi/mvm/debugfs.c +3 -0
@@ -350,6 +350,9 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf, le32_to_cpu(notif->secondary_ch_lut)); pos +=scnprintf (buf+pos, bufsz-pos,"bt_activity_grading = %d\n" ,le32_to_cpu (notif->bt_activity_grading)); + pos +=scnprintf (buf+pos, bufsz-pos, +"antenna isolation = %d CORUN LUT index = %d\n" , + mvm->last_ant_isol, mvm->last_corun_lut);mutex_unlock (&mvm->mutex);
drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h +2 -0
@@ -77,6 +77,7 @@* @BT_COEX_3W: * @BT_COEX_NW: * @BT_COEX_SYNC2SCO: +* @BT_COEX_CORUNNING: * * The COEX_MODE must be set for each command. Even if it is not changed. */
@@ -88,6 +89,7 @@ enum iwl_bt_coex_flags {BT_COEX_3W =0x2 <<BT_COEX_MODE_POS ,BT_COEX_NW =0x3 <<BT_COEX_MODE_POS ,BT_COEX_SYNC2SCO =BIT (7 ), + BT_COEX_CORUNNING = BIT(8), };/*
drivers/net/wireless/iwlwifi/mvm/fw-api.h +1 -0
@@ -95,6 +95,7 @@ enum {/* PHY context commands */ PHY_CONTEXT_CMD =0x8 ,DBG_CFG =0x9 , +ANTENNA_COUPLING_NOTIFICATION =0xa ,/* station table */ ADD_STA_KEY = 0x17,
drivers/net/wireless/iwlwifi/mvm/mvm.h +5 -0
@@ -597,6 +597,8 @@ struct iwl_mvm {u8 bt_kill_msk;struct iwl_bt_coex_profile_notif last_bt_notif;struct iwl_bt_coex_ci_cmd last_bt_ci_cmd; +u32 last_ant_isol; +u8 last_corun_lut;/* Thermal Throttling and CTkill */ struct iwl_mvm_tt_mgmt thermal_throttle;
@@ -750,6 +752,9 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd);int iwl_mvm_rx_radio_ver (struct iwl_mvm *mvm,struct iwl_rx_cmd_buffer *rxb,struct iwl_device_cmd *cmd); +int iwl_mvm_rx_ant_coupling_notif (struct iwl_mvm *mvm, +struct iwl_rx_cmd_buffer *rxb, +struct iwl_device_cmd *cmd);int iwl_mvm_rx_fw_error (struct iwl_mvm *mvm,struct iwl_rx_cmd_buffer *rxb,struct iwl_device_cmd *cmd); int iwl_mvm_rx_card_state_notif(struct iwl_mvm *mvm,
drivers/net/wireless/iwlwifi/mvm/ops.c +3 -0
@@ -220,6 +220,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {RX_HANDLER (BT_PROFILE_NOTIFICATION , iwl_mvm_rx_bt_coex_notif, true),RX_HANDLER (BEACON_NOTIFICATION , iwl_mvm_rx_beacon_notif, false),RX_HANDLER (STATISTICS_NOTIFICATION , iwl_mvm_rx_statistics, true), +RX_HANDLER (ANTENNA_COUPLING_NOTIFICATION , + iwl_mvm_rx_ant_coupling_notif, true), RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false),
@@ -321,6 +323,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {CMD (MAC_PM_POWER_TABLE ),CMD (BT_COEX_CI ),CMD (PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION ), + CMD(ANTENNA_COUPLING_NOTIFICATION), };#undef CMD
Signature · 1 line
1.8.3.2
PATCH 14/35 iwlwifi: mvm: make bt-coex.c generic
In reply to Emmanuel GrumbachFrom: Emmanuel Grumbach <[email protected]>
Make bt-coex generic to allow other coex mechanisms.
--- drivers/net/wireless/iwlwifi/mvm/Makefile | 2 +- drivers/net/wireless/iwlwifi/mvm/bt-coex.c | 1280 --------------------- drivers/net/wireless/iwlwifi/mvm/coex.c | 1280 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h | 350 ------ drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h | 350 ++++++ drivers/net/wireless/iwlwifi/mvm/fw-api.h | 2 +- drivers/net/wireless/iwlwifi/mvm/mvm.h | 4 +- drivers/net/wireless/iwlwifi/mvm/rs.c | 2 +- 8 files changed, 1635 insertions(+), 1635 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/mvm/bt-coex.c create mode 100644 drivers/net/wireless/iwlwifi/mvm/coex.c delete mode 100644 drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h create mode 100644 drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
drivers/net/wireless/iwlwifi/mvm/Makefile +1 -1
@@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM) += iwlmvm.o iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o iwlmvm-y += scan.o time-event.o rs.o -iwlmvm-y += power.o bt-coex.o +iwlmvm-y += power.o coex.o iwlmvm-y += led.o tt.o iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
drivers/net/wireless/iwlwifi/mvm/bt-coex.c deleted +0 -1280
1,280 lines not on this page · raw message
drivers/net/wireless/iwlwifi/mvm/coex.c new file +1280 -0
1,280 lines not on this page · raw message
drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h deleted +0 -350
350 lines not on this page · raw message
drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h new file +350 -0
82 lines not on this page · raw message
drivers/net/wireless/iwlwifi/mvm/fw-api.h +1 -1
Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Signature · 1 line
1.8.3.2
Part of the diff is not shown here. View the raw message.
PATCH 15/35 iwlwifi: mvm: BT Coex - classify packet priority in BT code
In reply to Emmanuel GrumbachFrom: Emmanuel Grumbach <[email protected]>
This code is really related to BT Coex - move it to the coex file.
Also - prepare for a FW API change that will happen soon:
Bits 11 and 12 will be allocated for BT priority. Today, we only have bit 12.
--- drivers/net/wireless/iwlwifi/mvm/coex.c | 17 +++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | 3 +++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 2 ++ drivers/net/wireless/iwlwifi/mvm/tx.c | 8 ++------ 4 files changed, 24 insertions(+), 6 deletions(-)
drivers/net/wireless/iwlwifi/mvm/coex.c +17 -0
@@ -61,6 +61,8 @@* *****************************************************************************/ +#include <linux/ieee80211.h> +#include <linux/etherdevice.h> #include <net/mac80211.h> #include "fw-api-coex.h"
@@ -1205,6 +1207,21 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,return iwl_get_coex_type (mvm, mvmsta->vif) ==BT_COEX_TIGHT_LUT ; } +u8 iwl_mvm_bt_coex_tx_prio (struct iwl_mvm *mvm,struct ieee80211_hdr *hdr, +struct ieee80211_tx_info *info) +{ +__le16 fc = hdr->frame_control; + +/* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */ +if (info->band ==IEEE80211_BAND_2GHZ && + (info->control.flags &IEEE80211_TX_CTRL_PORT_CTRL_PROTO || +is_multicast_ether_addr (hdr->addr1) || +ieee80211_is_back_req (fc) ||ieee80211_is_mgmt (fc))) +return 2 ; + +return 0 ; +} +void iwl_mvm_bt_coex_vif_change (struct iwl_mvm *mvm) {if (!(mvm->fw->ucode_capa.flags &IWL_UCODE_TLV_FLAGS_NEWBT_COEX ))
drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +3 -0
@@ -76,6 +76,8 @@* @TX_CMD_FLG_VHT_NDPA: mark frame is NDPA for VHT beamformer sequence * @TX_CMD_FLG_HT_NDPA: mark frame is NDPA for HT beamformer sequence * @TX_CMD_FLG_CSI_FDBK2HOST: mark to send feedback to host (only if good CRC) +* @TX_CMD_FLG_BT_PRIO_POS: the position of the BT priority (bit 11 is ignored +* on old firmwares). * @TX_CMD_FLG_BT_DIS: disable BT priority for this frame * @TX_CMD_FLG_SEQ_CTL: set if FW should override the sequence control. * Should be set for mgmt, non-QOS data, mcast, bcast and in scan command
@@ -107,6 +109,7 @@ enum iwl_tx_flags {TX_CMD_FLG_VHT_NDPA =BIT (8 ),TX_CMD_FLG_HT_NDPA =BIT (9 ),TX_CMD_FLG_CSI_FDBK2HOST =BIT (10 ), +TX_CMD_FLG_BT_PRIO_POS =11 ,TX_CMD_FLG_BT_DIS =BIT (12 ),TX_CMD_FLG_SEQ_CTL =BIT (13 ), TX_CMD_FLG_MORE_FRAG = BIT(14),
drivers/net/wireless/iwlwifi/mvm/mvm.h +2 -0
@@ -912,6 +912,8 @@ u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm, struct ieee80211_sta *sta);bool iwl_mvm_bt_coex_is_mimo_allowed (struct iwl_mvm *mvm,struct ieee80211_sta *sta); +u8 iwl_mvm_bt_coex_tx_prio (struct iwl_mvm *mvm,struct ieee80211_hdr *hdr, +struct ieee80211_tx_info *info);int iwl_mvm_bt_coex_reduced_txp (struct iwl_mvm *mvm,u8 sta_id,bool enable);enum iwl_bt_kill_msk {
drivers/net/wireless/iwlwifi/mvm/tx.c +2 -6
@@ -90,12 +90,8 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,else if (ieee80211_is_back_req (fc)) tx_flags |=TX_CMD_FLG_ACK |TX_CMD_FLG_BAR ; -/* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */ -if (info->band ==IEEE80211_BAND_2GHZ && - (info->control.flags &IEEE80211_TX_CTRL_PORT_CTRL_PROTO || -is_multicast_ether_addr (hdr->addr1) || -ieee80211_is_back_req (fc) ||ieee80211_is_mgmt (fc))) - tx_flags |=TX_CMD_FLG_BT_DIS ; + tx_flags |=iwl_mvm_bt_coex_tx_prio (mvm, hdr, info) << +TX_CMD_FLG_BT_PRIO_POS ;if (ieee80211_has_morefrags (fc)) tx_flags |=TX_CMD_FLG_MORE_FRAG ;
Signature · 1 line
1.8.3.2
PATCH 16/35 iwlwifi: mvm: BT Coex - enable per-AC BT priority
In reply to Emmanuel GrumbachFrom: Emmanuel Grumbach <[email protected]>
We can now define the priority against BT per AC. This is possible with a newer firmware that allows to define the priority with 2 bits.
Note that this change is compatible with older firmware since older firmware will simply ignore the new bit (11), and we still set the old bit (12) in the same cases as before.
--- drivers/net/wireless/iwlwifi/mvm/coex.c | 22 ++++++++++++++++++---- drivers/net/wireless/iwlwifi/mvm/mvm.h | 4 +++- drivers/net/wireless/iwlwifi/mvm/sta.c | 2 +- drivers/net/wireless/iwlwifi/mvm/tx.c | 9 ++++++--- 4 files changed, 28 insertions(+), 9 deletions(-)
drivers/net/wireless/iwlwifi/mvm/coex.c +18 -4
@@ -1208,16 +1208,30 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, }u8 iwl_mvm_bt_coex_tx_prio (struct iwl_mvm *mvm,struct ieee80211_hdr *hdr, -struct ieee80211_tx_info *info) +struct ieee80211_tx_info *info,u8 ac) {__le16 fc = hdr->frame_control; +if (info->band !=IEEE80211_BAND_2GHZ ) +return 0 ; +/* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */ -if (info->band ==IEEE80211_BAND_2GHZ && - (info->control.flags &IEEE80211_TX_CTRL_PORT_CTRL_PROTO || +if (info->control.flags &IEEE80211_TX_CTRL_PORT_CTRL_PROTO ||is_multicast_ether_addr (hdr->addr1) || -ieee80211_is_back_req (fc) ||ieee80211_is_mgmt (fc))) +ieee80211_is_ctl (fc) ||ieee80211_is_mgmt (fc) || +ieee80211_is_nullfunc (fc) ||ieee80211_is_qos_nullfunc (fc)) +return 3 ; + +switch (ac) { +case IEEE80211_AC_BE : +return 1 ; +case IEEE80211_AC_VO : +return 3 ; +case IEEE80211_AC_VI :return 2 ; +default : +break ; + }return 0 ; }
drivers/net/wireless/iwlwifi/mvm/mvm.h +3 -1
@@ -346,6 +346,8 @@ iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif)return (void *)vif->drv_priv; } +extern const u8 tid_to_mac80211_ac[]; +enum iwl_scan_status {IWL_MVM_SCAN_NONE ,IWL_MVM_SCAN_OS ,
@@ -913,7 +915,7 @@ u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm,bool iwl_mvm_bt_coex_is_mimo_allowed (struct iwl_mvm *mvm,struct ieee80211_sta *sta);u8 iwl_mvm_bt_coex_tx_prio (struct iwl_mvm *mvm,struct ieee80211_hdr *hdr, -struct ieee80211_tx_info *info); +struct ieee80211_tx_info *info,u8 ac);int iwl_mvm_bt_coex_reduced_txp (struct iwl_mvm *mvm,u8 sta_id,bool enable);enum iwl_bt_kill_msk {
drivers/net/wireless/iwlwifi/mvm/sta.c +1 -1
@@ -851,7 +851,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,return ret; } -static const u8 tid_to_mac80211_ac[] = { +const u8 tid_to_mac80211_ac[] = {IEEE80211_AC_BE ,IEEE80211_AC_BK ,IEEE80211_AC_BK ,
drivers/net/wireless/iwlwifi/mvm/tx.c +6 -3
@@ -79,6 +79,7 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,__le16 fc = hdr->frame_control;u32 tx_flags =le32_to_cpu (tx_cmd->tx_flags);u32 len = skb->len +FCS_LEN ; +u8 ac;if (!(info->flags &IEEE80211_TX_CTL_NO_ACK )) tx_flags |=TX_CMD_FLG_ACK ;
@@ -90,9 +91,6 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,else if (ieee80211_is_back_req (fc)) tx_flags |=TX_CMD_FLG_ACK |TX_CMD_FLG_BAR ; - tx_flags |=iwl_mvm_bt_coex_tx_prio (mvm, hdr, info) << -TX_CMD_FLG_BT_PRIO_POS ; -if (ieee80211_has_morefrags (fc)) tx_flags |=TX_CMD_FLG_MORE_FRAG ;
@@ -108,6 +106,11 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, tx_flags &= ~TX_CMD_FLG_SEQ_CTL ; } +/* tid_tspec will default to 0 = BE when QOS isn't enabled */ + ac = tid_to_mac80211_ac[tx_cmd->tid_tspec]; + tx_flags |=iwl_mvm_bt_coex_tx_prio (mvm, hdr, info, ac) << +TX_CMD_FLG_BT_PRIO_POS ; +if (ieee80211_is_mgmt (fc)) {if (ieee80211_is_assoc_req (fc) ||ieee80211_is_reassoc_req (fc)) tx_cmd->pm_frame_timeout =cpu_to_le16 (3 );
Signature · 1 line
1.8.3.2
PATCH 17/35 iwlwifi: mvm: fix merge damage
In reply to Emmanuel GrumbachFrom: Emmanuel Grumbach <[email protected]>
Scheduled scan was disabled because it was broken. Now it is fixed and got disabled by mistake by a merge.
--- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/iwlwifi/mvm/mac80211.c +1 -1
@@ -365,7 +365,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)else hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT ; -if (0 && mvm->fw->ucode_capa.flags &IWL_UCODE_TLV_FLAGS_SCHED_SCAN ) { +if (mvm->fw->ucode_capa.flags &IWL_UCODE_TLV_FLAGS_SCHED_SCAN ) { hw->wiphy->flags |=WIPHY_FLAG_SUPPORTS_SCHED_SCAN ; hw->wiphy->max_sched_scan_ssids =PROBE_OPTION_MAX ; hw->wiphy->max_match_sets =IWL_SCAN_MAX_PROFILES ;
Signature · 1 line
1.8.3.2
PATCH 18/35 iwlwifi: mvm: rs: fix search cycle rules
In reply to Emmanuel GrumbachFrom: Eyal Shapira <[email protected]>
We should explore all possible columns when searching to be as resilient as possible to changing conditions. This fixes for example a scenario where even after a sudden creation of rssi difference between the 2 antennas we would keep doing MIMO at a low rate instead of switching to SISO at a higher rate using the better antenna which was the optimal configuration.
--- drivers/net/wireless/iwlwifi/mvm/rs.c | 36 +++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-)
drivers/net/wireless/iwlwifi/mvm/rs.c +18 -18
@@ -211,9 +211,9 @@ static const struct rs_tx_column rs_tx_columns[] = { .next_columns = {RS_COLUMN_LEGACY_ANT_B ,RS_COLUMN_SISO_ANT_A , +RS_COLUMN_SISO_ANT_B ,RS_COLUMN_MIMO2 , -RS_COLUMN_INVALID , - RS_COLUMN_INVALID, + RS_COLUMN_MIMO2_SGI, }, }, [RS_COLUMN_LEGACY_ANT_B] = {
@@ -221,10 +221,10 @@ static const struct rs_tx_column rs_tx_columns[] = { .ant = ANT_B, .next_columns = {RS_COLUMN_LEGACY_ANT_A , +RS_COLUMN_SISO_ANT_A ,RS_COLUMN_SISO_ANT_B ,RS_COLUMN_MIMO2 , -RS_COLUMN_INVALID , - RS_COLUMN_INVALID, + RS_COLUMN_MIMO2_SGI, }, }, [RS_COLUMN_SISO_ANT_A] = {
@@ -234,8 +234,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_B,RS_COLUMN_MIMO2 ,RS_COLUMN_SISO_ANT_A_SGI , -RS_COLUMN_INVALID , -RS_COLUMN_INVALID , +RS_COLUMN_SISO_ANT_B_SGI , +RS_COLUMN_MIMO2_SGI , }, .checks = { rs_siso_allow,
@@ -248,8 +248,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A,RS_COLUMN_MIMO2 ,RS_COLUMN_SISO_ANT_B_SGI , -RS_COLUMN_INVALID , -RS_COLUMN_INVALID , +RS_COLUMN_SISO_ANT_A_SGI , +RS_COLUMN_MIMO2_SGI , }, .checks = { rs_siso_allow,
@@ -263,8 +263,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_B_SGI,RS_COLUMN_MIMO2_SGI ,RS_COLUMN_SISO_ANT_A , -RS_COLUMN_INVALID , -RS_COLUMN_INVALID , +RS_COLUMN_SISO_ANT_B , +RS_COLUMN_MIMO2 , }, .checks = { rs_siso_allow,
@@ -279,8 +279,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A_SGI,RS_COLUMN_MIMO2_SGI ,RS_COLUMN_SISO_ANT_B , -RS_COLUMN_INVALID , -RS_COLUMN_INVALID , +RS_COLUMN_SISO_ANT_A , +RS_COLUMN_MIMO2 , }, .checks = { rs_siso_allow,
@@ -292,10 +292,10 @@ static const struct rs_tx_column rs_tx_columns[] = { .ant = ANT_AB, .next_columns = {RS_COLUMN_SISO_ANT_A , +RS_COLUMN_SISO_ANT_B , +RS_COLUMN_SISO_ANT_A_SGI , +RS_COLUMN_SISO_ANT_B_SGI , RS_COLUMN_MIMO2_SGI, -RS_COLUMN_INVALID , -RS_COLUMN_INVALID , - RS_COLUMN_INVALID, }, .checks = { rs_mimo_allow,
@@ -307,10 +307,10 @@ static const struct rs_tx_column rs_tx_columns[] = { .sgi = true, .next_columns = {RS_COLUMN_SISO_ANT_A_SGI , +RS_COLUMN_SISO_ANT_B_SGI , +RS_COLUMN_SISO_ANT_A , +RS_COLUMN_SISO_ANT_B , RS_COLUMN_MIMO2, -RS_COLUMN_INVALID , -RS_COLUMN_INVALID , - RS_COLUMN_INVALID, }, .checks = { rs_mimo_allow,
Signature · 1 line
1.8.3.2
PATCH 19/35 iwlwifi: mvm: don't enable protection for all AMPDUs
In reply to Emmanuel GrumbachFrom: Eyal Shapira <[email protected]>
Currently RTS protection was done whenever trasnmitting an AMPDU. This limits throughput in cases where there's no need for protection. Disable this too inclusive protection for now.
--- drivers/net/wireless/iwlwifi/mvm/tx.c | 3 --- 1 file changed, 3 deletions(-)
drivers/net/wireless/iwlwifi/mvm/tx.c +0 -3
@@ -127,9 +127,6 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, tx_cmd->pm_frame_timeout =0 ; } -if (info->flags &IEEE80211_TX_CTL_AMPDU ) - tx_flags |=TX_CMD_FLG_PROT_REQUIRE ; -if (ieee80211_is_data (fc) && len > mvm->rts_threshold && !is_multicast_ether_addr (ieee80211_get_DA (hdr))) tx_flags |=TX_CMD_FLG_PROT_REQUIRE ;
Signature · 1 line
1.8.3.2
PATCH 20/35 iwlwifi: rs: split rs_collect_tx_data
In reply to Emmanuel GrumbachFrom: Eliad Peller <[email protected]>
Make _rs_collect_tx_data get window as param, in order to be able to set various windows.
This will be used later for saving tpc statistics
as well.
--- drivers/net/wireless/iwlwifi/mvm/rs.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-)
drivers/net/wireless/iwlwifi/mvm/rs.c +18 -9
@@ -566,19 +566,13 @@ static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)* at this rate. window->data contains the bitmask of successful * packets. */ -static int rs_collect_tx_data (struct iwl_scale_tbl_info *tbl, -int scale_index,int attempts,int successes) +static int _rs_collect_tx_data (struct iwl_scale_tbl_info *tbl, +int scale_index,int attempts,int successes, +struct iwl_rate_scale_data *window) { -struct iwl_rate_scale_data *window =NULL ;static const u64 mask = (((u64 )1 ) << (IWL_RATE_MAX_WINDOW -1 ));s32 fail_count, tpt; -if (scale_index <0 || scale_index >=IWL_RATE_COUNT ) -return -EINVAL ; - -/* Select window for current tx bit rate */ - window = &(tbl->win[scale_index]); -/* Get expected throughput */ tpt =get_expected_tpt (tbl, scale_index);
@@ -636,6 +630,21 @@ static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl,return 0 ; } +static int rs_collect_tx_data (struct iwl_scale_tbl_info *tbl, +int scale_index,int attempts,int successes) +{ +struct iwl_rate_scale_data *window =NULL ; + +if (scale_index <0 || scale_index >=IWL_RATE_COUNT ) +return -EINVAL ; + +/* Select window for current tx bit rate */ + window = &(tbl->win[scale_index]); + +return _rs_collect_tx_data (tbl, scale_index, attempts, successes, + window); +} +/* Convert rs_rate object into ucode rate bitmask */ static u32 ucode_rate_from_rs_rate (struct iwl_mvm *mvm,struct rs_rate *rate)
Signature · 1 line
1.8.3.2
PATCH 21/35 iwlwifi: add rs_rate_scale_clear_tbl_windows helper function
In reply to Emmanuel GrumbachFrom: Eliad Peller <[email protected]>
instead of duplicating the same loop multiple times, use a new function for it.
this will be later used also for clearing other windows in the table.
--- drivers/net/wireless/iwlwifi/mvm/rs.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-)
drivers/net/wireless/iwlwifi/mvm/rs.c +12 -11
@@ -503,6 +503,14 @@ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) window->average_tpt =IWL_INVALID_VALUE ; } +static void rs_rate_scale_clear_tbl_windows (struct iwl_scale_tbl_info *tbl) +{ +int i; + +for (i =0 ; i <IWL_RATE_COUNT ; i++) +rs_rate_scale_clear_window (&tbl->win[i]); +} +static inline u8 rs_is_valid_ant (u8 valid_antenna,u8 ant_type) {return (ant_type & valid_antenna) == ant_type;
@@ -1370,7 +1378,6 @@ static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta)static void rs_stay_in_table (struct iwl_lq_sta *lq_sta,bool force_search) {struct iwl_scale_tbl_info *tbl; -int i;int active_tbl;int flush_interval_passed =0 ;struct iwl_mvm *mvm;
@@ -1431,9 +1438,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)IWL_DEBUG_RATE (mvm,"LQ: stay in table clear win\n" ); -for (i =0 ; i <IWL_RATE_COUNT ; i++) -rs_rate_scale_clear_window ( - &(tbl->win[i])); +rs_rate_scale_clear_tbl_windows (tbl); } }
@@ -1442,8 +1447,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)* "search" table). */ if (lq_sta->rs_state ==RS_STATE_SEARCH_CYCLE_STARTED ) {IWL_DEBUG_RATE (mvm,"Clearing up window stats\n" ); -for (i =0 ; i <IWL_RATE_COUNT ; i++) -rs_rate_scale_clear_window (&(tbl->win[i])); +rs_rate_scale_clear_tbl_windows (tbl); } } }
@@ -1733,7 +1737,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,int low =IWL_RATE_INVALID ;int high =IWL_RATE_INVALID ;int index; -int i;struct iwl_rate_scale_data *window =NULL ;int current_tpt =IWL_INVALID_VALUE ;int low_tpt =IWL_INVALID_VALUE ;
@@ -2018,8 +2021,7 @@ lq_update:if (lq_sta->search_better_tbl) {/* Access the "search" table, clear its history. */ tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); -for (i =0 ; i <IWL_RATE_COUNT ; i++) -rs_rate_scale_clear_window (&(tbl->win[i])); +rs_rate_scale_clear_tbl_windows (tbl);/* Use new "search" start rate */ index = tbl->rate.index;
@@ -2340,8 +2342,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, lq_sta->lq.sta_id = sta_priv->sta_id;for (j =0 ; j <LQ_SIZE ; j++) -for (i =0 ; i <IWL_RATE_COUNT ; i++) -rs_rate_scale_clear_window (&lq_sta->lq_info[j].win[i]); +rs_rate_scale_clear_tbl_windows (&lq_sta->lq_info[j]); lq_sta->flush_timer =0 ;
Signature · 1 line
1.8.3.2
PATCH 22/35 iwlwifi: mvm: don't fail completely if led mode is not supported
In reply to Emmanuel GrumbachFrom: Emmanuel Grumbach <[email protected]>
Blink led mode is not supported by iwlmvm. This doesn't mean that we should prevent any operation if it is selected by the user.
Instead of failing without any notice to the user, fallback to the default mode (RF mode) if the blink mode
is selected and print an error to inform the user.
--- drivers/net/wireless/iwlwifi/mvm/led.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/wireless/iwlwifi/mvm/led.c +2 -0
@@ -94,6 +94,8 @@ int iwl_mvm_leds_init(struct iwl_mvm *mvm)int ret;switch (mode) { +case IWL_LED_BLINK : +IWL_ERR (mvm,"Blink led mode not supported, used default\n" );case IWL_LED_DEFAULT :case IWL_LED_RF_STATE : mode =IWL_LED_RF_STATE ;
Signature · 1 line
1.8.3.2
PATCH 23/35 iwlwifi: mvm: Change beacon filter enablement condition
In reply to Emmanuel GrumbachFrom: Alexander Bondar <[email protected]>
Enable beacon filter only if at least one beacon from candidate AP is received before or after association. Check this condition before enabling BF upon secured association completion. Add BF enablement to mac80211 event that indicates beacon is received after association. Too early beacon filtering enablement can lead to disconnection due to missing AP's beacon after association.
--- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/wireless/iwlwifi/mvm/mac80211.c +4 -1
@@ -1237,6 +1237,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,*/ iwl_mvm_remove_time_event (mvm, mvmvif, &mvmvif->time_event_data); +WARN_ON (iwl_mvm_enable_beacon_filter (mvm, vif,CMD_SYNC )); }else if (changes & (BSS_CHANGED_PS |BSS_CHANGED_P2P_PS |BSS_CHANGED_QOS )) { ret =iwl_mvm_power_update_mac (mvm, vif);
@@ -1611,7 +1612,9 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, }else if (old_state ==IEEE80211_STA_ASSOC && new_state ==IEEE80211_STA_AUTHORIZED ) {/* enable beacon filtering */ -WARN_ON (iwl_mvm_enable_beacon_filter (mvm, vif,CMD_SYNC )); +if (vif->bss_conf.dtim_period) +WARN_ON (iwl_mvm_enable_beacon_filter (mvm, vif, +CMD_SYNC )); ret =0 ; }else if (old_state ==IEEE80211_STA_AUTHORIZED && new_state ==IEEE80211_STA_ASSOC ) {
Signature · 1 line
1.8.3.2
PATCH 24/35 iwlwifi: mvm: configure seq_num to D0i3
In reply to Emmanuel GrumbachFrom: Eliad Peller <[email protected]>
Configure the QoS counters when entering D0i3.
The fw might use them later when performing protocol offloading (we'll update the the counters back on d0i3 exit in a following patch).
Non-QoS counter is handled internally in the fw, so no need to configure it.
Also, add support for a new version of WOWLAN_CONFIG_CMD
--- drivers/net/wireless/iwlwifi/iwl-fw.h | 8 + drivers/net/wireless/iwlwifi/mvm/Makefile | 2 +- drivers/net/wireless/iwlwifi/mvm/d3.c | 189 ++++------------------- drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h | 8 +- drivers/net/wireless/iwlwifi/mvm/mvm.h | 5 +- drivers/net/wireless/iwlwifi/mvm/offloading.c | 214 ++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/ops.c | 41 ++++- 7 files changed, 300 insertions(+), 167 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/mvm/offloading.c
drivers/net/wireless/iwlwifi/iwl-fw.h +8 -0
@@ -126,6 +126,14 @@ enum iwl_ucode_tlv_flag { };/** +* enum iwl_ucode_tlv_api - ucode api +* @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field. +*/ +enum iwl_ucode_tlv_api { +IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID =BIT (0 ), +}; + +/** * enum iwl_ucode_tlv_capa - ucode capabilities * @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3 */
drivers/net/wireless/iwlwifi/mvm/Makefile +1 -1
@@ -3,7 +3,7 @@ iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o iwlmvm-y += scan.o time-event.o rs.o iwlmvm-y += power.o coex.o -iwlmvm-y += led.o tt.o +iwlmvm-y += led.o tt.o offloading.o iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
drivers/net/wireless/iwlwifi/mvm/d3.c +30 -159
254 lines not on this page · raw message
drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h +7 -1
@@ -239,7 +239,7 @@ enum iwl_wowlan_wakeup_filters { IWL_WOWLAN_WAKEUP_BCN_FILTERING = BIT(16), }; /* WOWLAN_WAKEUP_FILTER_API_E_VER_4 */ -struct iwl_wowlan_config_cmd { +struct iwl_wowlan_config_cmd_v2 {__le32 wakeup_filter;__le16 non_qos_seq;__le16 qos_seq[8 ];
@@ -247,6 +247,12 @@ struct iwl_wowlan_config_cmd {u8 is_11n_connection; } __packed;/* WOWLAN_CONFIG_API_S_VER_2 */ +struct iwl_wowlan_config_cmd_v3 { +struct iwl_wowlan_config_cmd_v2 common; +u8 offloading_tid; +u8 reserved[3 ]; +} __packed;/* WOWLAN_CONFIG_API_S_VER_3 */ +/* * WOWLAN_TSC_RSC_PARAMS */
drivers/net/wireless/iwlwifi/mvm/mvm.h +4 -1
@@ -317,13 +317,13 @@ struct iwl_mvm_vif {bool seqno_valid;u16 seqno; +#endif #if IS_ENABLED (CONFIG_IPV6 )/* IPv6 addresses for WoWLAN */ struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX ];int num_target_ipv6_addrs;#endif -#endif #ifdef CONFIG_IWLWIFI_DEBUGFS struct iwl_mvm *mvm;
@@ -896,6 +896,9 @@ iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { }#endif +void iwl_mvm_set_wowlan_qos_seq (struct iwl_mvm_sta *mvm_ap_sta, +struct iwl_wowlan_config_cmd_v2 *cmd); +int iwl_mvm_send_proto_offload (struct iwl_mvm *mvm,struct ieee80211_vif *vif);/* D0i3 */ void iwl_mvm_ref (struct iwl_mvm *mvm,enum iwl_mvm_ref_type ref_type);
drivers/net/wireless/iwlwifi/mvm/offloading.c new file +214 -0
214 lines not on this page · raw message
drivers/net/wireless/iwlwifi/mvm/ops.c +36 -5
59 lines not on this page · raw message
Signature · 1 line
1.8.3.2
PATCH 25/35 iwlwifi: mvm: reconfigure qos seq on D0i3 exit
In reply to Emmanuel GrumbachFrom: Arik Nemtsov <[email protected]>
In order to restore the qos seq number on d0i3 exit, we need to read it from the wowlan status.
However, in order to make sure we use correct seq num for tx frames, we need to defer any outgoing frames, and re-enqueue them only after the seq num is configured correctly.
Sync new Tx aggregations with D0i3 so that the correct seq num is used for them. Wait synchronously for D0i3 exit before starting a new Tx agg.
--- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 69 +++++++++++++++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 9 ++ drivers/net/wireless/iwlwifi/mvm/ops.c | 132 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/sta.c | 10 ++- 4 files changed, 219 insertions(+), 1 deletion(-)
drivers/net/wireless/iwlwifi/mvm/mac80211.c +69 -0
@@ -424,6 +424,47 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)return ret; } +static bool iwl_mvm_defer_tx (struct iwl_mvm *mvm, +struct ieee80211_sta *sta, +struct sk_buff *skb) +{ +struct iwl_mvm_sta *mvmsta; +bool defer = false; + +/* +* double check the IN_D0I3 flag both before and after +* taking the spinlock, in order to prevent taking +* the spinlock when not needed. +*/ +if (likely (!test_bit (IWL_MVM_STATUS_IN_D0I3 , &mvm->status))) +return false; + +spin_lock (&mvm->d0i3_tx_lock); +/* +* testing the flag again ensures the skb dequeue +* loop (on d0i3 exit) hasn't run yet. +*/ +if (!test_bit (IWL_MVM_STATUS_IN_D0I3 , &mvm->status)) + goto out; + + mvmsta =iwl_mvm_sta_from_mac80211 (sta); +if (mvmsta->sta_id ==IWL_MVM_STATION_COUNT || + mvmsta->sta_id != mvm->d0i3_ap_sta_id) + goto out; + +__skb_queue_tail (&mvm->d0i3_tx, skb); +ieee80211_stop_queues (mvm->hw); + +/* trigger wakeup */ +iwl_mvm_ref (mvm,IWL_MVM_REF_TX ); +iwl_mvm_unref (mvm,IWL_MVM_REF_TX ); + + defer = true; +out: +spin_unlock (&mvm->d0i3_tx_lock); +return defer; +} +static void iwl_mvm_mac_tx (struct ieee80211_hw *hw,struct ieee80211_tx_control *control,struct sk_buff *skb)
@@ -451,6 +492,8 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, sta =NULL ;if (sta) { +if (iwl_mvm_defer_tx (mvm, sta, skb)) +return ;if (iwl_mvm_tx_skb (mvm, skb, sta)) goto drop;return ;
@@ -471,6 +514,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, {struct iwl_mvm *mvm =IWL_MAC80211_GET_MVM (hw);int ret; +bool tx_agg_ref = false;IWL_DEBUG_HT (mvm,"A-MPDU action on addr %pM tid %d: action %d\n" , sta->addr, tid, action);
@@ -478,6 +522,23 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,if (!(mvm->nvm_data->sku_cap_11n_enable))return -EACCES ; +/* return from D0i3 before starting a new Tx aggregation */ +if (action ==IEEE80211_AMPDU_TX_START ) { +iwl_mvm_ref (mvm,IWL_MVM_REF_TX_AGG ); + tx_agg_ref = true; + +/* +* wait synchronously until D0i3 exit to get the correct +* sequence number for the tid +*/ +if (!wait_event_timeout (mvm->d0i3_exit_waitq, + !test_bit (IWL_MVM_STATUS_IN_D0I3 , &mvm->status),HZ )) { +WARN_ON_ONCE (1 ); +iwl_mvm_unref (mvm,IWL_MVM_REF_TX_AGG ); +return -EIO ; + } + } +mutex_lock (&mvm->mutex);switch (action) {
@@ -515,6 +576,13 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, }mutex_unlock (&mvm->mutex); +/* +* If the tid is marked as started, we won't use it for offloaded +* traffic on the next D0i3 entry. It's safe to unref. +*/ +if (tx_agg_ref) +iwl_mvm_unref (mvm,IWL_MVM_REF_TX_AGG ); +return ret; }
@@ -592,6 +660,7 @@ static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw)mutex_lock (&mvm->mutex);clear_bit (IWL_MVM_STATUS_IN_HW_RESTART , &mvm->status); +iwl_mvm_d0i3_enable_tx (mvm,NULL ); ret =iwl_mvm_update_quotas (mvm,NULL );if (ret) IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n",
drivers/net/wireless/iwlwifi/mvm/mvm.h +9 -0
@@ -230,6 +230,8 @@ enum iwl_mvm_ref_type {IWL_MVM_REF_P2P_CLIENT ,IWL_MVM_REF_AP_IBSS ,IWL_MVM_REF_USER , +IWL_MVM_REF_TX , +IWL_MVM_REF_TX_AGG , IWL_MVM_REF_COUNT, };
@@ -593,7 +595,12 @@ struct iwl_mvm {/* d0i3 */ u8 d0i3_ap_sta_id; +bool d0i3_offloading;struct work_struct d0i3_exit_work; +struct sk_buff_head d0i3_tx; +/* sync d0i3_tx queue and IWL_MVM_STATUS_IN_D0I3 status flag */ +spinlock_t d0i3_tx_lock; +wait_queue_head_t d0i3_exit_waitq;/* BT-Coex */ u8 bt_kill_msk;
@@ -634,6 +641,7 @@ enum iwl_mvm_status {IWL_MVM_STATUS_HW_CTKILL ,IWL_MVM_STATUS_ROC_RUNNING ,IWL_MVM_STATUS_IN_HW_RESTART , + IWL_MVM_STATUS_IN_D0I3, };static inline bool iwl_mvm_is_radio_killed (struct iwl_mvm *mvm)
@@ -903,6 +911,7 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, struct ieee80211_vif *vif);/* D0i3 */ void iwl_mvm_ref (struct iwl_mvm *mvm,enum iwl_mvm_ref_type ref_type);void iwl_mvm_unref (struct iwl_mvm *mvm,enum iwl_mvm_ref_type ref_type); +void iwl_mvm_d0i3_enable_tx (struct iwl_mvm *mvm,__le16 *qos_seq);/* BT Coex */ int iwl_send_bt_prio_tbl (struct iwl_mvm *mvm);
drivers/net/wireless/iwlwifi/mvm/ops.c +132 -0
197 lines not on this page · raw message
drivers/net/wireless/iwlwifi/mvm/sta.c +9 -1
@@ -902,10 +902,18 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,return -EIO ; } +spin_lock_bh (&mvmsta->lock); + +/* possible race condition - we entered D0i3 while starting agg */ +if (test_bit (IWL_MVM_STATUS_IN_D0I3 , &mvm->status)) { +spin_unlock_bh (&mvmsta->lock); +IWL_ERR (mvm,"Entered D0i3 while starting Tx agg\n" ); +return -EIO ; + } +/* the new tx queue is still connected to the same mac80211 queue */ mvm->queue_to_mac80211[txq_id] = vif->hw_queue[tid_to_mac80211_ac[tid]]; -spin_lock_bh (&mvmsta->lock); tid_data = &mvmsta->tid_data[tid]; tid_data->ssn =IEEE80211_SEQ_TO_SN (tid_data->seq_number); tid_data->txq_id = txq_id;
Signature · 1 line
1.8.3.2
PATCH 26/35 iwlwifi: mvm: configure protocol offloading on D0i3
In reply to Emmanuel GrumbachFrom: Eliad Peller <[email protected]>
Enable protocol offloading (arp and NS) on D0i3.
The offloading allows the fw answer NS and arp requests without waking up the host.
Since protocol offloading is saved between D0i3 entries, we have to explicitly disable it in case we don't want it.
--- drivers/net/wireless/iwlwifi/mvm/d3.c | 2 +- drivers/net/wireless/iwlwifi/mvm/mvm.h | 5 ++++- drivers/net/wireless/iwlwifi/mvm/offloading.c | 13 +++++++------ drivers/net/wireless/iwlwifi/mvm/ops.c | 1 + 4 files changed, 13 insertions(+), 8 deletions(-)
drivers/net/wireless/iwlwifi/mvm/d3.c +1 -1
@@ -1031,7 +1031,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,if (ret) goto out; - ret =iwl_mvm_send_proto_offload (mvm, vif); + ret =iwl_mvm_send_proto_offload (mvm, vif, false,CMD_SYNC );if (ret) goto out;
drivers/net/wireless/iwlwifi/mvm/mvm.h +4 -1
@@ -906,7 +906,10 @@ iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif)#endif void iwl_mvm_set_wowlan_qos_seq (struct iwl_mvm_sta *mvm_ap_sta,struct iwl_wowlan_config_cmd_v2 *cmd); -int iwl_mvm_send_proto_offload (struct iwl_mvm *mvm,struct ieee80211_vif *vif); +int iwl_mvm_send_proto_offload (struct iwl_mvm *mvm, +struct ieee80211_vif *vif, +bool disable_offloading, +u32 cmd_flags);/* D0i3 */ void iwl_mvm_ref (struct iwl_mvm *mvm,enum iwl_mvm_ref_type ref_type);
drivers/net/wireless/iwlwifi/mvm/offloading.c +7 -6
@@ -81,7 +81,10 @@ void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta, } } -int iwl_mvm_send_proto_offload (struct iwl_mvm *mvm,struct ieee80211_vif *vif) +int iwl_mvm_send_proto_offload (struct iwl_mvm *mvm, +struct ieee80211_vif *vif, +bool disable_offloading, +u32 cmd_flags) {union {struct iwl_proto_offload_cmd_v1 v1;
@@ -91,7 +94,7 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, struct ieee80211_vif *vif) } cmd = {};struct iwl_host_cmd hcmd = { .id =PROT_OFFLOAD_CONFIG_CMD , - .flags =CMD_SYNC , + .flags = cmd_flags, .data[0 ] = &cmd, .dataflags[0 ] =IWL_HCMD_DFL_DUP , };
@@ -204,10 +207,8 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, struct ieee80211_vif *vif)memcpy (common->arp_mac_addr, vif->addr,ETH_ALEN ); } -if (!enabled) -return 0 ; - - common->enabled =cpu_to_le32 (enabled); +if (!disable_offloading) + common->enabled =cpu_to_le32 (enabled); hcmd.len[0 ] = size;return iwl_mvm_send_cmd (mvm, &hcmd);
drivers/net/wireless/iwlwifi/mvm/ops.c +1 -0
@@ -905,6 +905,7 @@ static void iwl_mvm_enter_d0i3_iterator(void *_data, u8 *mac, data->disable_offloading = true;iwl_mvm_update_d0i3_power_mode (mvm, vif, true, flags); +iwl_mvm_send_proto_offload (mvm, vif, data->disable_offloading, flags);/* * on init/association, mvm already configures POWER_TABLE_CMD
Signature · 1 line
1.8.3.2
PATCH 27/35 iwlwifi: mvm: send udev event upon firmware error to dump logs
In reply to Emmanuel GrumbachFrom: Emmanuel Grumbach <[email protected]>
When the firmware asserts, the driver will dump the firmware state to an internal buffer. This buffer is kept aside until it is dumped through debugfs. Once an external application fetched the data, the buffer is freed and a new buffer can be allocated in case another assert occurs.
A udev event is sent to trigger an external application.
A simple rule like:
DRIVER=="iwlwifi", ACTION=="change", RUN+="/sbin/dump_sram.sh"
can fetch the data from debugfs.
Here is my dump_sram.sh:
phyname=$(basename ${DEVPATH})
date=$(date +%F_%H_%M) filename=/var/log/iwl-sram-${phyname}-${date}.bin
cat /sys/kernel/debug/ieee80211/${phyname}/iwlwifi/iwlmvm/fw_error_dump > ${filename}
The current SRAM size is 80KB so, currently:
$ ls -lh iwl-sram-phy0-2014-03-16_13_14.bin -rw-r--r-- 1 emmanuel emmanuel 81K Mar 16 13:15 iwl-sram-phy0-2014-03-16_13_14.bin
and after compression:
$ ls -lh iwl-sram-phy0-2014-03-16_13_14.bin.xz -rw-r--r-- 1 emmanuel emmanuel 13K Mar 16 13:15 iwl-sram-phy0-2014-03-16_13_14.bin.xz
--- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 52 +++++++++++ drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h | 106 +++++++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/mac80211.c | 9 ++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 8 +- drivers/net/wireless/iwlwifi/mvm/ops.c | 44 +++++++++- drivers/net/wireless/iwlwifi/mvm/utils.c | 27 +++--- 6 files changed, 226 insertions(+), 20 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h
drivers/net/wireless/iwlwifi/mvm/debugfs.c +52 -0
@@ -65,6 +65,7 @@#include "iwl-io.h" #include "iwl-prph.h" #include "debugfs.h" +#include "fw-error-dump.h" static ssize_t iwl_dbgfs_tx_flush_write (struct iwl_mvm *mvm,char *buf,size_t count,loff_t *ppos)
@@ -117,6 +118,50 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,return ret; } +static int iwl_dbgfs_fw_error_dump_open (struct inode *inode,struct file *file) +{ +struct iwl_mvm *mvm = inode->i_private; +int ret; + +if (!mvm) +return -EINVAL ; + +mutex_lock (&mvm->mutex); +if (!mvm->fw_error_dump) { + ret = -ENODATA ; + goto out; + } + + file->private_data = mvm->fw_error_dump; + mvm->fw_error_dump =NULL ; + mvm->fw_error_sram =NULL ; + mvm->fw_error_sram_len =0 ; + ret =0 ; + +out: +mutex_unlock (&mvm->mutex); +return ret; +} + +static ssize_t iwl_dbgfs_fw_error_dump_read (struct file *file, +char __user *user_buf, +size_t count,loff_t *ppos) +{ +struct iwl_fw_error_dump_file *dump_file = file->private_data; + +return simple_read_from_buffer (user_buf, count, ppos, + dump_file, +le32_to_cpu (dump_file->file_len)); +} + +static int iwl_dbgfs_fw_error_dump_release (struct inode *inode, +struct file *file) +{ +vfree (file->private_data); + +return 0 ; +} +static ssize_t iwl_dbgfs_sram_read (struct file *file,char __user *user_buf,size_t count,loff_t *ppos) {
@@ -1042,6 +1087,12 @@ MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);MVM_DEBUGFS_READ_WRITE_FILE_OPS (scan_ant_rxchain,8 );MVM_DEBUGFS_READ_WRITE_FILE_OPS (d0i3_refs,8 ); +static const struct file_operations iwl_dbgfs_fw_error_dump_ops = { + .open = iwl_dbgfs_fw_error_dump_open, + .read = iwl_dbgfs_fw_error_dump_read, + .release = iwl_dbgfs_fw_error_dump_release, +}; +#ifdef CONFIG_IWLWIFI_BCAST_FILTERING MVM_DEBUGFS_READ_WRITE_FILE_OPS (bcast_filters,256 );MVM_DEBUGFS_READ_WRITE_FILE_OPS (bcast_filters_macs,256 );
@@ -1064,6 +1115,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)MVM_DEBUGFS_ADD_FILE (sta_drain, mvm->debugfs_dir,S_IWUSR );MVM_DEBUGFS_ADD_FILE (sram, mvm->debugfs_dir,S_IWUSR |S_IRUSR );MVM_DEBUGFS_ADD_FILE (stations, dbgfs_dir,S_IRUSR ); +MVM_DEBUGFS_ADD_FILE (fw_error_dump, dbgfs_dir,S_IRUSR );MVM_DEBUGFS_ADD_FILE (bt_notif, dbgfs_dir,S_IRUSR );MVM_DEBUGFS_ADD_FILE (bt_cmd, dbgfs_dir,S_IRUSR );if (mvm->fw->ucode_capa.flags &IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD )
drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h new file +106 -0
106 lines not on this page · raw message
drivers/net/wireless/iwlwifi/mvm/mac80211.c +9 -0
@@ -607,6 +607,15 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,static void iwl_mvm_restart_cleanup (struct iwl_mvm *mvm) { +#ifdef CONFIG_IWLWIFI_DEBUGFS +static char *env[] = {"DRIVER=iwlwifi" ,"EVENT=error_dump" ,NULL }; + +iwl_mvm_fw_error_dump (mvm); + +/* notify the userspace about the error we had */ +kobject_uevent_env (&mvm->hw->wiphy->dev.kobj,KOBJ_CHANGE , env); +#endif +iwl_trans_stop_device (mvm->trans); mvm->scan_status =IWL_MVM_SCAN_NONE ;
drivers/net/wireless/iwlwifi/mvm/mvm.h +7 -1
@@ -575,6 +575,9 @@ struct iwl_mvm {/* -1 for always, 0 for never, >0 for that many times */ s8 restart_fw; +void *fw_error_dump; +void *fw_error_sram; +u32 fw_error_sram_len;struct led_classdev led;
@@ -698,7 +701,10 @@ void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, struct ieee80211_tx_rate *r);u8 iwl_mvm_mac80211_idx_to_hwrate (int rate_idx);void iwl_mvm_dump_nic_error_log (struct iwl_mvm *mvm); -void iwl_mvm_dump_sram (struct iwl_mvm *mvm); +#ifdef CONFIG_IWLWIFI_DEBUGFS +void iwl_mvm_fw_error_dump (struct iwl_mvm *mvm); +void iwl_mvm_fw_error_sram_dump (struct iwl_mvm *mvm); +#endif u8 first_antenna (u8 mask);u8 iwl_mvm_next_antenna (struct iwl_mvm *mvm,u8 valid,u8 last_idx);
drivers/net/wireless/iwlwifi/mvm/ops.c +42 -2
73 lines not on this page · raw message
drivers/net/wireless/iwlwifi/mvm/utils.c +10 -17
@@ -516,33 +516,26 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)iwl_mvm_dump_umac_error_log (mvm); } -void iwl_mvm_dump_sram (struct iwl_mvm *mvm) +void iwl_mvm_fw_error_sram_dump (struct iwl_mvm *mvm) {const struct fw_img *img; -int ofs, len =0 ; -int i; -__le32 *buf; +u32 ofs, sram_len; +void *sram; -if (!mvm->ucode_loaded) +if (!mvm->ucode_loaded || mvm->fw_error_sram)return ; img = &mvm->fw->img[mvm->cur_ucode]; ofs = img->sec[IWL_UCODE_SECTION_DATA ].offset; - len = img->sec[IWL_UCODE_SECTION_DATA ].len; + sram_len = img->sec[IWL_UCODE_SECTION_DATA ].len; - buf =kzalloc (len,GFP_ATOMIC ); -if (!buf) + sram =kzalloc (sram_len,GFP_ATOMIC ); +if (!sram)return ; -iwl_trans_read_mem_bytes (mvm->trans, ofs, buf, len); - len = len >>2 ; -for (i =0 ; i < len; i++) { -IWL_ERR (mvm,"0x%08X\n" ,le32_to_cpu (buf[i])); -/* Add a small delay to let syslog catch up */ -udelay (10 ); - } - -kfree (buf); +iwl_trans_read_mem_bytes (mvm->trans, ofs, sram, sram_len); + mvm->fw_error_sram = sram; + mvm->fw_error_sram_len = sram_len; }/**
Signature · 1 line
1.8.3.2
PATCH 28/35 iwlwifi: mvm: BT Coex - add debugfs hook to set BT Tx priority
In reply to Emmanuel GrumbachFrom: Emmanuel Grumbach <[email protected]>
In order to debug the firmware, we need to be able to set the BT priority of WiFi packets. This priority is set based on the type of the packet (control frames, EAPOL etc...). For debugging purposes, allow to override this priority by a debugfs controlled value.
Enable this feature that needs this priority to be able to test it.
--- drivers/net/wireless/iwlwifi/mvm/coex.c | 8 ++++++++ drivers/net/wireless/iwlwifi/mvm/constants.h | 1 + drivers/net/wireless/iwlwifi/mvm/debugfs.c | 18 ++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h | 2 ++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 1 + 5 files changed, 30 insertions(+)
drivers/net/wireless/iwlwifi/mvm/coex.c +8 -0
@@ -616,6 +616,11 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) bt_cmd->flags |=cpu_to_le32 (BT_COEX_CORUNNING ); } +if (IWL_MVM_BT_COEX_MPLUT ) { + bt_cmd->flags |=cpu_to_le32 (BT_COEX_MPLUT ); + bt_cmd->valid_bit_msk =cpu_to_le32 (BT_VALID_MULTI_PRIO_LUT ); + } +if (mvm->cfg->bt_shared_single_ant)memcpy (&bt_cmd->decision_lut, iwl_single_shared_ant,sizeof (iwl_single_shared_ant));
@@ -1215,6 +1220,9 @@ u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,if (info->band !=IEEE80211_BAND_2GHZ )return 0 ; +if (unlikely (mvm->bt_tx_prio)) +return mvm->bt_tx_prio -1 ; +/* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */ if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO || is_multicast_ether_addr(hdr->addr1) ||
drivers/net/wireless/iwlwifi/mvm/constants.h +1 -0
@@ -83,5 +83,6 @@#define IWL_MVM_LOWLAT_DUAL_BINDING_MAXDUR 24/* TU */ #define IWL_MVM_BT_COEX_SYNC2SCO 1#define IWL_MVM_BT_COEX_CORUNNING 1 +#define IWL_MVM_BT_COEX_MPLUT 1#endif /* __MVM_CONSTANTS_H */
drivers/net/wireless/iwlwifi/mvm/debugfs.c +18 -0
@@ -440,6 +440,22 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,return simple_read_from_buffer (user_buf, count, ppos, buf, pos); } +static ssize_t +iwl_dbgfs_bt_tx_prio_write (struct iwl_mvm *mvm,char *buf, +size_t count,loff_t *ppos) +{ +u32 bt_tx_prio; + +if (sscanf (buf,"%u" , &bt_tx_prio) !=1 ) +return -EINVAL ; +if (bt_tx_prio >4 ) +return -EINVAL ; + + mvm->bt_tx_prio = bt_tx_prio; + +return count; +} +#define PRINT_STATS_LE32 (_str, _val) \ pos += scnprintf(buf + pos, bufsz - pos, \ fmt_table, _str, \
@@ -1084,6 +1100,7 @@ MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);MVM_DEBUGFS_READ_FILE_OPS (drv_rx_stats);MVM_DEBUGFS_WRITE_FILE_OPS (fw_restart,10 );MVM_DEBUGFS_WRITE_FILE_OPS (fw_nmi,10 ); +MVM_DEBUGFS_WRITE_FILE_OPS (bt_tx_prio,10 );MVM_DEBUGFS_READ_WRITE_FILE_OPS (scan_ant_rxchain,8 );MVM_DEBUGFS_READ_WRITE_FILE_OPS (d0i3_refs,8 );
@@ -1125,6 +1142,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)MVM_DEBUGFS_ADD_FILE (drv_rx_stats, mvm->debugfs_dir,S_IRUSR );MVM_DEBUGFS_ADD_FILE (fw_restart, mvm->debugfs_dir,S_IWUSR );MVM_DEBUGFS_ADD_FILE (fw_nmi, mvm->debugfs_dir,S_IWUSR ); +MVM_DEBUGFS_ADD_FILE (bt_tx_prio, mvm->debugfs_dir,S_IWUSR );MVM_DEBUGFS_ADD_FILE (scan_ant_rxchain, mvm->debugfs_dir,S_IWUSR |S_IRUSR );MVM_DEBUGFS_ADD_FILE (prph_reg, mvm->debugfs_dir,S_IWUSR |S_IRUSR );
drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h +2 -0
@@ -78,6 +78,7 @@* @BT_COEX_NW: * @BT_COEX_SYNC2SCO: * @BT_COEX_CORUNNING: +* @BT_COEX_MPLUT: * * The COEX_MODE must be set for each command. Even if it is not changed. */
@@ -90,6 +91,7 @@ enum iwl_bt_coex_flags {BT_COEX_NW =0x3 <<BT_COEX_MODE_POS ,BT_COEX_SYNC2SCO =BIT (7 ),BT_COEX_CORUNNING =BIT (8 ), + BT_COEX_MPLUT = BIT(9), };/*
drivers/net/wireless/iwlwifi/mvm/mvm.h +1 -0
@@ -611,6 +611,7 @@ struct iwl_mvm {struct iwl_bt_coex_ci_cmd last_bt_ci_cmd;u32 last_ant_isol;u8 last_corun_lut; +u8 bt_tx_prio;/* Thermal Throttling and CTkill */ struct iwl_mvm_tt_mgmt thermal_throttle;
Signature · 1 line
1.8.3.2
PATCH 29/35 iwlwifi: mvm: remove using max_duration in firmware API
In reply to Emmanuel GrumbachFrom: Johannes Berg <[email protected]>
The firmware decided to not implement this API in this way, so for now remove setting the field completely. This will allow the firmware to change how to use this field later.
--- drivers/net/wireless/iwlwifi/mvm/constants.h | 2 -- drivers/net/wireless/iwlwifi/mvm/quota.c | 22 +--------------------- 2 files changed, 1 insertion(+), 23 deletions(-)
drivers/net/wireless/iwlwifi/mvm/constants.h +0 -2
@@ -79,8 +79,6 @@#define IWL_MVM_PS_SNOOZE_WINDOW 50#define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW 25#define IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT 64 -#define IWL_MVM_LOWLAT_SINGLE_BINDING_MAXDUR 24/* TU */ -#define IWL_MVM_LOWLAT_DUAL_BINDING_MAXDUR 24/* TU */ #define IWL_MVM_BT_COEX_SYNC2SCO 1#define IWL_MVM_BT_COEX_CORUNNING 1#define IWL_MVM_BT_COEX_MPLUT 1
drivers/net/wireless/iwlwifi/mvm/quota.c +1 -21
@@ -180,7 +180,6 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) .colors = { -1, -1, -1, -1 }, .new_vif = newvif, }; -u32 ll_max_duration;lockdep_assert_held (&mvm->mutex);
@@ -199,21 +198,6 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)iwl_mvm_quota_iterator (&data, newvif->addr, newvif); } -switch (data.n_low_latency_bindings) { -case 0 :/* no low latency - use default */ - ll_max_duration =0 ; -break ; -case 1 :/* SingleBindingLowLatencyMode */ - ll_max_duration =IWL_MVM_LOWLAT_SINGLE_BINDING_MAXDUR ; -break ; -case 2 :/* DualBindingLowLatencyMode */ - ll_max_duration =IWL_MVM_LOWLAT_DUAL_BINDING_MAXDUR ; -break ; -default :/* MultiBindingLowLatencyMode */ - ll_max_duration =0 ; -break ; - } -/* * The FW's scheduling session consists of * IWL_MVM_MAX_QUOTA fragments. Divide these fragments
@@ -287,11 +271,7 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)"Binding=%d, quota=%u > max=%u\n" , idx, le32_to_cpu(cmd.quotas[idx].quota), QUOTA_100); -if (data.n_interfaces[i] && !data.low_latency[i]) - cmd.quotas[idx].max_duration = -cpu_to_le32 (ll_max_duration); -else - cmd.quotas[idx].max_duration =cpu_to_le32 (0 ); + cmd.quotas[idx].max_duration =cpu_to_le32 (0 ); idx++; }
Signature · 1 line
1.8.3.2
PATCH 32/35 iwlwifi: mvm: fix theoretical NULL ptr dereference
In reply to Emmanuel GrumbachFrom: Emmanuel Grumbach <[email protected]>
mvmsta could have been NULL / ERR.
--- drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +5 -0
@@ -312,6 +312,11 @@ static ssize_t iwl_dbgfs_reduced_txp_write(struct ieee80211_vif *vif,mutex_lock (&mvm->mutex); mvmsta =iwl_mvm_sta_from_staid_protected (mvm, mvmvif->ap_sta_id); +if (IS_ERR_OR_NULL (mvmsta)) { +mutex_unlock (&mvm->mutex); +return -ENOTCONN ; + } + mvmsta->bt_reduced_txpower_dbg = false; ret =iwl_mvm_bt_coex_reduced_txp (mvm, mvmvif->ap_sta_id, reduced_tx_power);
Signature · 1 line
1.8.3.2
PATCH 31/35 iwlwifi: mvm: configure low latency dependent scan parameters
In reply to Emmanuel GrumbachFrom: Alexander Bondar <[email protected]>
In case of system low latency configure passive scan to be fragmented. Set the following scan parameters for both immediate and scheduled scan:
- passive scan fragment duration = 20ms
- out-of-channel time = 70ms
- suspend time = 105ms
Restructure channel's active/passive dwell time configuration to better suit the above change.
The idea is that under low latency traffic passive scan is fragmented, i.e. that dwell on a particular channel will be fragmented. Each fragment dwell time is 20ms and fragments period is 105ms. Skipping to next channel will be delayed by the same period (105ms). So suspend_time parameter describing both fragments and channels skipping periods is set to 105ms. This value is chosen so that overall passive scan duration will not be too long. Max_out_time in this case is set to 70ms, so for active scanning operating channel will be left for 70ms while for passive still for 20ms (fragment dwell).
--- drivers/net/wireless/iwlwifi/mvm/mvm.h | 2 + drivers/net/wireless/iwlwifi/mvm/scan.c | 108 +++++++++++++++++++++++-------- drivers/net/wireless/iwlwifi/mvm/utils.c | 19 ++++++ 3 files changed, 101 insertions(+), 28 deletions(-)
drivers/net/wireless/iwlwifi/mvm/mvm.h +2 -0
@@ -984,6 +984,8 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,/* Low latency */ int iwl_mvm_update_low_latency (struct iwl_mvm *mvm,struct ieee80211_vif *vif,bool value); +/* get SystemLowLatencyMode - only needed for beacon threshold? */ +bool iwl_mvm_low_latency (struct iwl_mvm *mvm);/* get VMACLowLatencyMode */ static inline bool iwl_mvm_vif_low_latency (struct iwl_mvm_vif *mvmvif) {
drivers/net/wireless/iwlwifi/mvm/scan.c +80 -28
223 lines not on this page · raw message
drivers/net/wireless/iwlwifi/mvm/utils.c +19 -0
@@ -622,3 +622,22 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif,return iwl_mvm_power_update_mac (mvm, vif); } + +static void iwl_mvm_ll_iter (void *_data,u8 *mac,struct ieee80211_vif *vif) +{ +bool *result = _data; + +if (iwl_mvm_vif_low_latency (iwl_mvm_vif_from_mac80211 (vif))) + *result = true; +} + +bool iwl_mvm_low_latency (struct iwl_mvm *mvm) +{ +bool result = false; + +ieee80211_iterate_active_interfaces_atomic ( + mvm->hw,IEEE80211_IFACE_ITER_NORMAL , + iwl_mvm_ll_iter, &result); + +return result; +}
Signature · 1 line
1.8.3.2
PATCH 33/35 iwlwifi: mvm: remove spurious blank line
In reply to Emmanuel GrumbachFrom: Johannes Berg <[email protected]>
Remove a spurious blank line in the quota code.
--- drivers/net/wireless/iwlwifi/mvm/quota.c | 1 - 1 file changed, 1 deletion(-)
drivers/net/wireless/iwlwifi/mvm/quota.c +0 -1
@@ -262,7 +262,6 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)* binding. */ cmd.quotas[idx].quota =cpu_to_le32 (QUOTA_LOWLAT_MIN ); - else cmd.quotas[idx].quota =cpu_to_le32 (quota * data.n_interfaces[i]);
Signature · 1 line
1.8.3.2
PATCH 35/35 iwlwifi: mvm: disable uAPSD due to bugs in the firmware
In reply to Emmanuel GrumbachFrom: Emmanuel Grumbach <[email protected]>
The current firmware advertises support for uAPSD, but critical bugs force us to disable the feature. When a fixed firmware will be available, we will be able to re-enable uAPSD.
--- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/iwlwifi/mvm/mac80211.c +1 -1
@@ -295,7 +295,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) !iwlwifi_mod_params.sw_crypto) hw->flags |=IEEE80211_HW_MFP_CAPABLE ; -if (mvm->fw->ucode_capa.flags &IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT ) { +if (0 && mvm->fw->ucode_capa.flags &IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT ) { hw->flags |=IEEE80211_HW_SUPPORTS_UAPSD ; hw->uapsd_queues =IWL_UAPSD_AC_INFO ; hw->uapsd_max_sp_len =IWL_UAPSD_MAX_SP ;
Signature · 1 line
1.8.3.2
PATCH 30/35 iwlwifi: mvm: restructure scan parameters calculation
In reply to Emmanuel GrumbachFrom: Alexander Bondar <[email protected]>
Some scan parameters should be dependent on traffic conditions. Centralize conditions verification in one function and obtain scan max out-of-channel and suspend time in that new function. Rely on bound interfaces indication instead of association state to calculate scan parameters. If no bound interfaces use default values for out-of-channel and suspend time parameters.
Additionally, get rid of NL80211_SCAN_FLAG_LOW_PRIORITY checks since no use case for this exists so far.
--- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 3 +- drivers/net/wireless/iwlwifi/mvm/scan.c | 82 ++++++++++++++--------------- 2 files changed, 41 insertions(+), 44 deletions(-)
drivers/net/wireless/iwlwifi/mvm/mac80211.c +1 -2
@@ -375,8 +375,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) } hw->wiphy->features |=NL80211_FEATURE_P2P_GO_CTWIN | -NL80211_FEATURE_P2P_GO_OPPPS | -NL80211_FEATURE_LOW_PRIORITY_SCAN ; +NL80211_FEATURE_P2P_GO_OPPPS ; mvm->rts_threshold =IEEE80211_MAX_RTS_THRESHOLD ;
drivers/net/wireless/iwlwifi/mvm/scan.c +40 -42
137 lines not on this page · raw message
Signature · 1 line
1.8.3.2
PATCH 34/35 iwlwifi: mvm: ignore unchanged low-latency flag
In reply to Emmanuel GrumbachFrom: Johannes Berg <[email protected]>
If the low-latency update is called but there's no change then ignore the update instead of triggering all the required work.
--- drivers/net/wireless/iwlwifi/mvm/utils.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/wireless/iwlwifi/mvm/utils.c +3 -0
@@ -612,6 +612,9 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif,lockdep_assert_held (&mvm->mutex); +if (mvmvif->low_latency == value) +return 0 ; + mvmvif->low_latency = value; res =iwl_mvm_update_quotas (mvm,NULL );
Signature · 1 line
1.8.3.2
Quoted 5 lines
The following changes since commit
3e3831c4fdc53aabf3a56419ef6d96a841c52435:brcmfmac: reset suspend flag upon sdio suspend failure (2014-02-28 14:33:49 -0500)
Quoted 8 lines
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.gitfor-johnfor you to fetch changes up to
4a482d61e0f87a655f1e022a09ec48bca11dd898:iwlwifi: mvm: disable uAPSD due to bugs in the firmware (2014-03-18 16:32:45 +0200)
I had to amend one commit - new HEAD: a82dda6cd492b8c88952be6f6527f3656f7ac585
Quoted 7 lines · Emmanuel Grumbach
Quoted 7 lines
The following changes since commit
3e3831c4fdc53aabf3a56419ef6d96a841c52435:brcmfmac: reset suspend flag upon sdio suspend failure (2014-02-28 14:33:49 -0500)
are available in the git repository at:
Quoted 8 lines
Quoted 6 lines
git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.gitfor-johnfor you to fetch changes up to
4a482d61e0f87a655f1e022a09ec48bca11dd898:iwlwifi: mvm: disable uAPSD due to bugs in the firmware (2014-03-18 16:32:45 +0200)
I had to amend one commit - new HEAD:
a82dda6cd492b8c88952be6f6527f3656f7ac585
Pulling now...
Signature · 2 lines
John W. Linville Someday the world will need a hero, and you [email protected] might be all we have. Be ready.