diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-04-22 15:01:24 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-04-22 15:01:24 -0400 |
commit | bf4c69f7dd8e0c3427262cc11652227ec7256a75 (patch) | |
tree | 7e6fe4f8c3c126496b737962537d51645a826c2c | |
parent | 4a0c3d9fd1af83ad0519997043467b817d3738fc (diff) | |
parent | e03bbb62cfdf539ae8110b297493c685f9d12774 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
47 files changed, 1056 insertions, 786 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index 576f7ee38ca5..d169228f59e7 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c | |||
@@ -180,7 +180,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv) | |||
180 | goto done; | 180 | goto done; |
181 | } | 181 | } |
182 | IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n"); | 182 | IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n"); |
183 | iwl_trans_wait_tx_queue_empty(priv->trans); | 183 | iwl_trans_wait_tx_queue_empty(priv->trans, 0xffffffff); |
184 | done: | 184 | done: |
185 | ieee80211_wake_queues(priv->hw); | 185 | ieee80211_wake_queues(priv->hw); |
186 | mutex_unlock(&priv->mutex); | 186 | mutex_unlock(&priv->mutex); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index dd55c9cf7ba8..d3abc15125d6 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -1119,7 +1119,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | |||
1119 | } | 1119 | } |
1120 | } | 1120 | } |
1121 | IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n"); | 1121 | IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n"); |
1122 | iwl_trans_wait_tx_queue_empty(priv->trans); | 1122 | iwl_trans_wait_tx_queue_empty(priv->trans, 0xffffffff); |
1123 | done: | 1123 | done: |
1124 | mutex_unlock(&priv->mutex); | 1124 | mutex_unlock(&priv->mutex); |
1125 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1125 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 6a6df71af1d7..6a00353768f3 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
@@ -2053,6 +2053,17 @@ static bool iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | |||
2053 | return false; | 2053 | return false; |
2054 | } | 2054 | } |
2055 | 2055 | ||
2056 | static void iwl_napi_add(struct iwl_op_mode *op_mode, | ||
2057 | struct napi_struct *napi, | ||
2058 | struct net_device *napi_dev, | ||
2059 | int (*poll)(struct napi_struct *, int), | ||
2060 | int weight) | ||
2061 | { | ||
2062 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||
2063 | |||
2064 | ieee80211_napi_add(priv->hw, napi, napi_dev, poll, weight); | ||
2065 | } | ||
2066 | |||
2056 | static const struct iwl_op_mode_ops iwl_dvm_ops = { | 2067 | static const struct iwl_op_mode_ops iwl_dvm_ops = { |
2057 | .start = iwl_op_mode_dvm_start, | 2068 | .start = iwl_op_mode_dvm_start, |
2058 | .stop = iwl_op_mode_dvm_stop, | 2069 | .stop = iwl_op_mode_dvm_stop, |
@@ -2065,6 +2076,7 @@ static const struct iwl_op_mode_ops iwl_dvm_ops = { | |||
2065 | .cmd_queue_full = iwl_cmd_queue_full, | 2076 | .cmd_queue_full = iwl_cmd_queue_full, |
2066 | .nic_config = iwl_nic_config, | 2077 | .nic_config = iwl_nic_config, |
2067 | .wimax_active = iwl_wimax_active, | 2078 | .wimax_active = iwl_wimax_active, |
2079 | .napi_add = iwl_napi_add, | ||
2068 | }; | 2080 | }; |
2069 | 2081 | ||
2070 | /***************************************************************************** | 2082 | /***************************************************************************** |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 854ba84ccb73..c3817fae16c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -62,6 +62,7 @@ static const struct iwl_base_params iwl1000_base_params = { | |||
62 | .led_compensation = 51, | 62 | .led_compensation = 51, |
63 | .wd_timeout = IWL_WATCHDOG_DISABLED, | 63 | .wd_timeout = IWL_WATCHDOG_DISABLED, |
64 | .max_event_log_size = 128, | 64 | .max_event_log_size = 128, |
65 | .scd_chain_ext_wa = true, | ||
65 | }; | 66 | }; |
66 | 67 | ||
67 | static const struct iwl_ht_params iwl1000_ht_params = { | 68 | static const struct iwl_ht_params iwl1000_ht_params = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 3e63323637f3..21e5d0843a62 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c | |||
@@ -75,6 +75,7 @@ static const struct iwl_base_params iwl2000_base_params = { | |||
75 | .wd_timeout = IWL_DEF_WD_TIMEOUT, | 75 | .wd_timeout = IWL_DEF_WD_TIMEOUT, |
76 | .max_event_log_size = 512, | 76 | .max_event_log_size = 512, |
77 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ | 77 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ |
78 | .scd_chain_ext_wa = true, | ||
78 | }; | 79 | }; |
79 | 80 | ||
80 | 81 | ||
@@ -88,6 +89,7 @@ static const struct iwl_base_params iwl2030_base_params = { | |||
88 | .wd_timeout = IWL_LONG_WD_TIMEOUT, | 89 | .wd_timeout = IWL_LONG_WD_TIMEOUT, |
89 | .max_event_log_size = 512, | 90 | .max_event_log_size = 512, |
90 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ | 91 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ |
92 | .scd_chain_ext_wa = true, | ||
91 | }; | 93 | }; |
92 | 94 | ||
93 | static const struct iwl_ht_params iwl2000_ht_params = { | 95 | static const struct iwl_ht_params iwl2000_ht_params = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 6674f2c4541c..332bbede39e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -61,6 +61,7 @@ static const struct iwl_base_params iwl5000_base_params = { | |||
61 | .led_compensation = 51, | 61 | .led_compensation = 51, |
62 | .wd_timeout = IWL_WATCHDOG_DISABLED, | 62 | .wd_timeout = IWL_WATCHDOG_DISABLED, |
63 | .max_event_log_size = 512, | 63 | .max_event_log_size = 512, |
64 | .scd_chain_ext_wa = true, | ||
64 | }; | 65 | }; |
65 | 66 | ||
66 | static const struct iwl_ht_params iwl5000_ht_params = { | 67 | static const struct iwl_ht_params iwl5000_ht_params = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 8048de90233f..8f2c3c8c6b84 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -85,6 +85,7 @@ static const struct iwl_base_params iwl6000_base_params = { | |||
85 | .wd_timeout = IWL_DEF_WD_TIMEOUT, | 85 | .wd_timeout = IWL_DEF_WD_TIMEOUT, |
86 | .max_event_log_size = 512, | 86 | .max_event_log_size = 512, |
87 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ | 87 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ |
88 | .scd_chain_ext_wa = true, | ||
88 | }; | 89 | }; |
89 | 90 | ||
90 | static const struct iwl_base_params iwl6050_base_params = { | 91 | static const struct iwl_base_params iwl6050_base_params = { |
@@ -97,6 +98,7 @@ static const struct iwl_base_params iwl6050_base_params = { | |||
97 | .wd_timeout = IWL_DEF_WD_TIMEOUT, | 98 | .wd_timeout = IWL_DEF_WD_TIMEOUT, |
98 | .max_event_log_size = 1024, | 99 | .max_event_log_size = 1024, |
99 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ | 100 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ |
101 | .scd_chain_ext_wa = true, | ||
100 | }; | 102 | }; |
101 | 103 | ||
102 | static const struct iwl_base_params iwl6000_g2_base_params = { | 104 | static const struct iwl_base_params iwl6000_g2_base_params = { |
@@ -109,6 +111,7 @@ static const struct iwl_base_params iwl6000_g2_base_params = { | |||
109 | .wd_timeout = IWL_LONG_WD_TIMEOUT, | 111 | .wd_timeout = IWL_LONG_WD_TIMEOUT, |
110 | .max_event_log_size = 512, | 112 | .max_event_log_size = 512, |
111 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ | 113 | .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ |
114 | .scd_chain_ext_wa = true, | ||
112 | }; | 115 | }; |
113 | 116 | ||
114 | static const struct iwl_ht_params iwl6000_ht_params = { | 117 | static const struct iwl_ht_params iwl6000_ht_params = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 4c2d4ef28b22..f73de239cdc1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c | |||
@@ -71,12 +71,12 @@ | |||
71 | #define IWL3160_UCODE_API_MAX 9 | 71 | #define IWL3160_UCODE_API_MAX 9 |
72 | 72 | ||
73 | /* Oldest version we won't warn about */ | 73 | /* Oldest version we won't warn about */ |
74 | #define IWL7260_UCODE_API_OK 8 | 74 | #define IWL7260_UCODE_API_OK 9 |
75 | #define IWL3160_UCODE_API_OK 8 | 75 | #define IWL3160_UCODE_API_OK 9 |
76 | 76 | ||
77 | /* Lowest firmware API version supported */ | 77 | /* Lowest firmware API version supported */ |
78 | #define IWL7260_UCODE_API_MIN 7 | 78 | #define IWL7260_UCODE_API_MIN 8 |
79 | #define IWL3160_UCODE_API_MIN 7 | 79 | #define IWL3160_UCODE_API_MIN 8 |
80 | 80 | ||
81 | /* NVM versions */ | 81 | /* NVM versions */ |
82 | #define IWL7260_NVM_VERSION 0x0a1d | 82 | #define IWL7260_NVM_VERSION 0x0a1d |
@@ -107,6 +107,7 @@ static const struct iwl_base_params iwl7000_base_params = { | |||
107 | .max_event_log_size = 512, | 107 | .max_event_log_size = 512, |
108 | .shadow_reg_enable = true, | 108 | .shadow_reg_enable = true, |
109 | .pcie_l1_allowed = true, | 109 | .pcie_l1_allowed = true, |
110 | .apmg_wake_up_wa = true, | ||
110 | }; | 111 | }; |
111 | 112 | ||
112 | static const struct iwl_ht_params iwl7000_ht_params = { | 113 | static const struct iwl_ht_params iwl7000_ht_params = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 3f17dc3f2c8a..7ce82d9c7222 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -146,6 +146,9 @@ static inline u8 num_of_ant(u8 mask) | |||
146 | * @wd_timeout: TX queues watchdog timeout | 146 | * @wd_timeout: TX queues watchdog timeout |
147 | * @max_event_log_size: size of event log buffer size for ucode event logging | 147 | * @max_event_log_size: size of event log buffer size for ucode event logging |
148 | * @shadow_reg_enable: HW shadow register support | 148 | * @shadow_reg_enable: HW shadow register support |
149 | * @apmg_wake_up_wa: should the MAC access REQ be asserted when a command | ||
150 | * is in flight. This is due to a HW bug in 7260, 3160 and 7265. | ||
151 | * @scd_chain_ext_wa: should the chain extension feature in SCD be disabled. | ||
149 | */ | 152 | */ |
150 | struct iwl_base_params { | 153 | struct iwl_base_params { |
151 | int eeprom_size; | 154 | int eeprom_size; |
@@ -160,6 +163,8 @@ struct iwl_base_params { | |||
160 | u32 max_event_log_size; | 163 | u32 max_event_log_size; |
161 | const bool shadow_reg_enable; | 164 | const bool shadow_reg_enable; |
162 | const bool pcie_l1_allowed; | 165 | const bool pcie_l1_allowed; |
166 | const bool apmg_wake_up_wa; | ||
167 | const bool scd_chain_ext_wa; | ||
163 | }; | 168 | }; |
164 | 169 | ||
165 | /* | 170 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index d14f19339d61..f5927d0cf9b6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -77,26 +77,21 @@ | |||
77 | * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD | 77 | * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD |
78 | * @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan | 78 | * @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan |
79 | * offload profile config command. | 79 | * offload profile config command. |
80 | * @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api | ||
81 | * @IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API. | ||
82 | * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six | 80 | * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six |
83 | * (rather than two) IPv6 addresses | 81 | * (rather than two) IPv6 addresses |
84 | * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API | ||
85 | * @IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element | 82 | * @IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element |
86 | * from the probe request template. | 83 | * from the probe request template. |
87 | * @IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API: modified D3 API to allow keeping | ||
88 | * connection when going back to D0 | ||
89 | * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version) | 84 | * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version) |
90 | * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version) | 85 | * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version) |
91 | * @IWL_UCODE_TLV_FLAGS_SCHED_SCAN: this uCode image supports scheduled scan. | 86 | * @IWL_UCODE_TLV_FLAGS_P2P_PM: P2P client supports PM as a stand alone MAC |
92 | * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API | ||
93 | * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command | ||
94 | * containing CAM (Continuous Active Mode) indication. | ||
95 | * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_DCM: support power save on BSS station and | 87 | * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_DCM: support power save on BSS station and |
96 | * P2P client interfaces simultaneously if they are in different bindings. | 88 | * P2P client interfaces simultaneously if they are in different bindings. |
89 | * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_SCM: support power save on BSS station and | ||
90 | * P2P client interfaces simultaneously if they are in same bindings. | ||
97 | * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save | 91 | * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save |
98 | * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering. | 92 | * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering. |
99 | * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients | 93 | * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients |
94 | * @IWL_UCODE_TLV_FLAGS_EBS_SUPPORT: this uCode image supports EBS. | ||
100 | */ | 95 | */ |
101 | enum iwl_ucode_tlv_flag { | 96 | enum iwl_ucode_tlv_flag { |
102 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), | 97 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), |
@@ -104,22 +99,15 @@ enum iwl_ucode_tlv_flag { | |||
104 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), | 99 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), |
105 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), | 100 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), |
106 | IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), | 101 | IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), |
107 | IWL_UCODE_TLV_FLAGS_NEWBT_COEX = BIT(5), | ||
108 | IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT = BIT(6), | ||
109 | IWL_UCODE_TLV_FLAGS_SHORT_BL = BIT(7), | 102 | IWL_UCODE_TLV_FLAGS_SHORT_BL = BIT(7), |
110 | IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8), | ||
111 | IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 = BIT(9), | ||
112 | IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10), | 103 | IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10), |
113 | IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11), | ||
114 | IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID = BIT(12), | 104 | IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID = BIT(12), |
115 | IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API = BIT(14), | ||
116 | IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL = BIT(15), | 105 | IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL = BIT(15), |
117 | IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE = BIT(16), | 106 | IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE = BIT(16), |
118 | IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17), | 107 | IWL_UCODE_TLV_FLAGS_P2P_PM = BIT(21), |
119 | IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19), | ||
120 | IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20), | ||
121 | IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM = BIT(22), | 108 | IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM = BIT(22), |
122 | IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24), | 109 | IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM = BIT(23), |
110 | IWL_UCODE_TLV_FLAGS_EBS_SUPPORT = BIT(25), | ||
123 | IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26), | 111 | IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26), |
124 | IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29), | 112 | IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29), |
125 | IWL_UCODE_TLV_FLAGS_GO_UAPSD = BIT(30), | 113 | IWL_UCODE_TLV_FLAGS_GO_UAPSD = BIT(30), |
@@ -183,6 +171,7 @@ enum iwl_ucode_sec { | |||
183 | #define IWL_UCODE_SECTION_MAX 12 | 171 | #define IWL_UCODE_SECTION_MAX 12 |
184 | #define IWL_API_ARRAY_SIZE 1 | 172 | #define IWL_API_ARRAY_SIZE 1 |
185 | #define IWL_CAPABILITIES_ARRAY_SIZE 1 | 173 | #define IWL_CAPABILITIES_ARRAY_SIZE 1 |
174 | #define CPU1_CPU2_SEPARATOR_SECTION 0xFFFFCCCC | ||
186 | 175 | ||
187 | struct iwl_ucode_capabilities { | 176 | struct iwl_ucode_capabilities { |
188 | u32 max_probe_length; | 177 | u32 max_probe_length; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 6be30c698506..4049c0d626ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
@@ -134,12 +134,13 @@ static const u8 iwl_nvm_channels_family_8000[] = { | |||
134 | 149, 153, 157, 161, 165, 169, 173, 177, 181 | 134 | 149, 153, 157, 161, 165, 169, 173, 177, 181 |
135 | }; | 135 | }; |
136 | 136 | ||
137 | #define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels) | 137 | #define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels) |
138 | #define IWL_NUM_CHANNELS_FAMILY_8000 ARRAY_SIZE(iwl_nvm_channels_family_8000) | 138 | #define IWL_NUM_CHANNELS_FAMILY_8000 ARRAY_SIZE(iwl_nvm_channels_family_8000) |
139 | #define NUM_2GHZ_CHANNELS 14 | 139 | #define NUM_2GHZ_CHANNELS 14 |
140 | #define FIRST_2GHZ_HT_MINUS 5 | 140 | #define NUM_2GHZ_CHANNELS_FAMILY_8000 13 |
141 | #define LAST_2GHZ_HT_PLUS 9 | 141 | #define FIRST_2GHZ_HT_MINUS 5 |
142 | #define LAST_5GHZ_HT 161 | 142 | #define LAST_2GHZ_HT_PLUS 9 |
143 | #define LAST_5GHZ_HT 161 | ||
143 | 144 | ||
144 | #define DEFAULT_MAX_TX_POWER 16 | 145 | #define DEFAULT_MAX_TX_POWER 16 |
145 | 146 | ||
@@ -202,21 +203,23 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
202 | struct ieee80211_channel *channel; | 203 | struct ieee80211_channel *channel; |
203 | u16 ch_flags; | 204 | u16 ch_flags; |
204 | bool is_5ghz; | 205 | bool is_5ghz; |
205 | int num_of_ch; | 206 | int num_of_ch, num_2ghz_channels; |
206 | const u8 *nvm_chan; | 207 | const u8 *nvm_chan; |
207 | 208 | ||
208 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { | 209 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { |
209 | num_of_ch = IWL_NUM_CHANNELS; | 210 | num_of_ch = IWL_NUM_CHANNELS; |
210 | nvm_chan = &iwl_nvm_channels[0]; | 211 | nvm_chan = &iwl_nvm_channels[0]; |
212 | num_2ghz_channels = NUM_2GHZ_CHANNELS; | ||
211 | } else { | 213 | } else { |
212 | num_of_ch = IWL_NUM_CHANNELS_FAMILY_8000; | 214 | num_of_ch = IWL_NUM_CHANNELS_FAMILY_8000; |
213 | nvm_chan = &iwl_nvm_channels_family_8000[0]; | 215 | nvm_chan = &iwl_nvm_channels_family_8000[0]; |
216 | num_2ghz_channels = NUM_2GHZ_CHANNELS_FAMILY_8000; | ||
214 | } | 217 | } |
215 | 218 | ||
216 | for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { | 219 | for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { |
217 | ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); | 220 | ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); |
218 | 221 | ||
219 | if (ch_idx >= NUM_2GHZ_CHANNELS && | 222 | if (ch_idx >= num_2ghz_channels && |
220 | !data->sku_cap_band_52GHz_enable) | 223 | !data->sku_cap_band_52GHz_enable) |
221 | ch_flags &= ~NVM_CHANNEL_VALID; | 224 | ch_flags &= ~NVM_CHANNEL_VALID; |
222 | 225 | ||
@@ -225,7 +228,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
225 | "Ch. %d Flags %x [%sGHz] - No traffic\n", | 228 | "Ch. %d Flags %x [%sGHz] - No traffic\n", |
226 | nvm_chan[ch_idx], | 229 | nvm_chan[ch_idx], |
227 | ch_flags, | 230 | ch_flags, |
228 | (ch_idx >= NUM_2GHZ_CHANNELS) ? | 231 | (ch_idx >= num_2ghz_channels) ? |
229 | "5.2" : "2.4"); | 232 | "5.2" : "2.4"); |
230 | continue; | 233 | continue; |
231 | } | 234 | } |
@@ -234,7 +237,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
234 | n_channels++; | 237 | n_channels++; |
235 | 238 | ||
236 | channel->hw_value = nvm_chan[ch_idx]; | 239 | channel->hw_value = nvm_chan[ch_idx]; |
237 | channel->band = (ch_idx < NUM_2GHZ_CHANNELS) ? | 240 | channel->band = (ch_idx < num_2ghz_channels) ? |
238 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | 241 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; |
239 | channel->center_freq = | 242 | channel->center_freq = |
240 | ieee80211_channel_to_frequency( | 243 | ieee80211_channel_to_frequency( |
@@ -242,7 +245,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
242 | 245 | ||
243 | /* TODO: Need to be dependent to the NVM */ | 246 | /* TODO: Need to be dependent to the NVM */ |
244 | channel->flags = IEEE80211_CHAN_NO_HT40; | 247 | channel->flags = IEEE80211_CHAN_NO_HT40; |
245 | if (ch_idx < NUM_2GHZ_CHANNELS && | 248 | if (ch_idx < num_2ghz_channels && |
246 | (ch_flags & NVM_CHANNEL_40MHZ)) { | 249 | (ch_flags & NVM_CHANNEL_40MHZ)) { |
247 | if (nvm_chan[ch_idx] <= LAST_2GHZ_HT_PLUS) | 250 | if (nvm_chan[ch_idx] <= LAST_2GHZ_HT_PLUS) |
248 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; | 251 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; |
@@ -250,7 +253,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
250 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; | 253 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; |
251 | } else if (nvm_chan[ch_idx] <= LAST_5GHZ_HT && | 254 | } else if (nvm_chan[ch_idx] <= LAST_5GHZ_HT && |
252 | (ch_flags & NVM_CHANNEL_40MHZ)) { | 255 | (ch_flags & NVM_CHANNEL_40MHZ)) { |
253 | if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0) | 256 | if ((ch_idx - num_2ghz_channels) % 2 == 0) |
254 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; | 257 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; |
255 | else | 258 | else |
256 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; | 259 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index ea29504ac617..99785c892f96 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h | |||
@@ -63,6 +63,7 @@ | |||
63 | #ifndef __iwl_op_mode_h__ | 63 | #ifndef __iwl_op_mode_h__ |
64 | #define __iwl_op_mode_h__ | 64 | #define __iwl_op_mode_h__ |
65 | 65 | ||
66 | #include <linux/netdevice.h> | ||
66 | #include <linux/debugfs.h> | 67 | #include <linux/debugfs.h> |
67 | 68 | ||
68 | struct iwl_op_mode; | 69 | struct iwl_op_mode; |
@@ -112,8 +113,11 @@ struct iwl_cfg; | |||
112 | * @stop: stop the op_mode. Must free all the memory allocated. | 113 | * @stop: stop the op_mode. Must free all the memory allocated. |
113 | * May sleep | 114 | * May sleep |
114 | * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the | 115 | * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the |
115 | * HCMD this Rx responds to. | 116 | * HCMD this Rx responds to. Can't sleep. |
116 | * This callback may sleep, it is called from a threaded IRQ handler. | 117 | * @napi_add: NAPI initialisation. The transport is fully responsible for NAPI, |
118 | * but the higher layers need to know about it (in particular mac80211 to | ||
119 | * to able to call the right NAPI RX functions); this function is needed | ||
120 | * to eventually call netif_napi_add() with higher layer involvement. | ||
117 | * @queue_full: notifies that a HW queue is full. | 121 | * @queue_full: notifies that a HW queue is full. |
118 | * Must be atomic and called with BH disabled. | 122 | * Must be atomic and called with BH disabled. |
119 | * @queue_not_full: notifies that a HW queue is not full any more. | 123 | * @queue_not_full: notifies that a HW queue is not full any more. |
@@ -143,6 +147,11 @@ struct iwl_op_mode_ops { | |||
143 | void (*stop)(struct iwl_op_mode *op_mode); | 147 | void (*stop)(struct iwl_op_mode *op_mode); |
144 | int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, | 148 | int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, |
145 | struct iwl_device_cmd *cmd); | 149 | struct iwl_device_cmd *cmd); |
150 | void (*napi_add)(struct iwl_op_mode *op_mode, | ||
151 | struct napi_struct *napi, | ||
152 | struct net_device *napi_dev, | ||
153 | int (*poll)(struct napi_struct *, int), | ||
154 | int weight); | ||
146 | void (*queue_full)(struct iwl_op_mode *op_mode, int queue); | 155 | void (*queue_full)(struct iwl_op_mode *op_mode, int queue); |
147 | void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue); | 156 | void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue); |
148 | bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state); | 157 | bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state); |
@@ -180,7 +189,6 @@ static inline int iwl_op_mode_rx(struct iwl_op_mode *op_mode, | |||
180 | struct iwl_rx_cmd_buffer *rxb, | 189 | struct iwl_rx_cmd_buffer *rxb, |
181 | struct iwl_device_cmd *cmd) | 190 | struct iwl_device_cmd *cmd) |
182 | { | 191 | { |
183 | might_sleep(); | ||
184 | return op_mode->ops->rx(op_mode, rxb, cmd); | 192 | return op_mode->ops->rx(op_mode, rxb, cmd); |
185 | } | 193 | } |
186 | 194 | ||
@@ -249,4 +257,15 @@ static inline int iwl_op_mode_exit_d0i3(struct iwl_op_mode *op_mode) | |||
249 | return op_mode->ops->exit_d0i3(op_mode); | 257 | return op_mode->ops->exit_d0i3(op_mode); |
250 | } | 258 | } |
251 | 259 | ||
260 | static inline void iwl_op_mode_napi_add(struct iwl_op_mode *op_mode, | ||
261 | struct napi_struct *napi, | ||
262 | struct net_device *napi_dev, | ||
263 | int (*poll)(struct napi_struct *, int), | ||
264 | int weight) | ||
265 | { | ||
266 | if (!op_mode->ops->napi_add) | ||
267 | return; | ||
268 | op_mode->ops->napi_add(op_mode, napi, napi_dev, poll, weight); | ||
269 | } | ||
270 | |||
252 | #endif /* __iwl_op_mode_h__ */ | 271 | #endif /* __iwl_op_mode_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 5f657c501406..779311080a9e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -348,4 +348,12 @@ enum secure_load_status_reg { | |||
348 | 348 | ||
349 | #define LMPM_SECURE_TIME_OUT (100) | 349 | #define LMPM_SECURE_TIME_OUT (100) |
350 | 350 | ||
351 | /* Rx FIFO */ | ||
352 | #define RXF_SIZE_ADDR (0xa00c88) | ||
353 | #define RXF_SIZE_BYTE_CND_POS (7) | ||
354 | #define RXF_SIZE_BYTE_CNT_MSK (0x3ff << RXF_SIZE_BYTE_CND_POS) | ||
355 | |||
356 | #define RXF_LD_FENCE_OFFSET_ADDR (0xa00c10) | ||
357 | #define RXF_FIFO_RD_FENCE_ADDR (0xa00c0c) | ||
358 | |||
351 | #endif /* __iwl_prph_h__ */ | 359 | #endif /* __iwl_prph_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 8cdb0dd618a6..22fd94ec8048 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -437,8 +437,7 @@ struct iwl_trans; | |||
437 | * this one. The op_mode must not configure the HCMD queue. May sleep. | 437 | * this one. The op_mode must not configure the HCMD queue. May sleep. |
438 | * @txq_disable: de-configure a Tx queue to send AMPDUs | 438 | * @txq_disable: de-configure a Tx queue to send AMPDUs |
439 | * Must be atomic | 439 | * Must be atomic |
440 | * @wait_tx_queue_empty: wait until all tx queues are empty | 440 | * @wait_tx_queue_empty: wait until tx queues are empty. May sleep. |
441 | * May sleep | ||
442 | * @dbgfs_register: add the dbgfs files under this directory. Files will be | 441 | * @dbgfs_register: add the dbgfs files under this directory. Files will be |
443 | * automatically deleted. | 442 | * automatically deleted. |
444 | * @write8: write a u8 to a register at offset ofs from the BAR | 443 | * @write8: write a u8 to a register at offset ofs from the BAR |
@@ -490,7 +489,7 @@ struct iwl_trans_ops { | |||
490 | void (*txq_disable)(struct iwl_trans *trans, int queue); | 489 | void (*txq_disable)(struct iwl_trans *trans, int queue); |
491 | 490 | ||
492 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); | 491 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); |
493 | int (*wait_tx_queue_empty)(struct iwl_trans *trans); | 492 | int (*wait_tx_queue_empty)(struct iwl_trans *trans, u32 txq_bm); |
494 | 493 | ||
495 | void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val); | 494 | void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val); |
496 | void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val); | 495 | void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val); |
@@ -759,12 +758,13 @@ static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, | |||
759 | IWL_MAX_TID_COUNT, IWL_FRAME_LIMIT, 0); | 758 | IWL_MAX_TID_COUNT, IWL_FRAME_LIMIT, 0); |
760 | } | 759 | } |
761 | 760 | ||
762 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) | 761 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans, |
762 | u32 txq_bm) | ||
763 | { | 763 | { |
764 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) | 764 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
765 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); | 765 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
766 | 766 | ||
767 | return trans->ops->wait_tx_queue_empty(trans); | 767 | return trans->ops->wait_tx_queue_empty(trans, txq_bm); |
768 | } | 768 | } |
769 | 769 | ||
770 | static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, | 770 | static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index fa858d548d13..8f4b03dbaf3f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c | |||
@@ -104,11 +104,8 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { | |||
104 | #define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65) | 104 | #define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65) |
105 | #define BT_ANTENNA_COUPLING_THRESHOLD (30) | 105 | #define BT_ANTENNA_COUPLING_THRESHOLD (30) |
106 | 106 | ||
107 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) | 107 | static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) |
108 | { | 108 | { |
109 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX)) | ||
110 | return 0; | ||
111 | |||
112 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC, | 109 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC, |
113 | sizeof(struct iwl_bt_coex_prio_tbl_cmd), | 110 | sizeof(struct iwl_bt_coex_prio_tbl_cmd), |
114 | &iwl_bt_prio_tbl); | 111 | &iwl_bt_prio_tbl); |
@@ -573,8 +570,9 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
573 | int ret; | 570 | int ret; |
574 | u32 flags; | 571 | u32 flags; |
575 | 572 | ||
576 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX)) | 573 | ret = iwl_send_bt_prio_tbl(mvm); |
577 | return 0; | 574 | if (ret) |
575 | return ret; | ||
578 | 576 | ||
579 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); | 577 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); |
580 | if (!bt_cmd) | 578 | if (!bt_cmd) |
@@ -582,10 +580,12 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
582 | cmd.data[0] = bt_cmd; | 580 | cmd.data[0] = bt_cmd; |
583 | 581 | ||
584 | bt_cmd->max_kill = 5; | 582 | bt_cmd->max_kill = 5; |
585 | bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD, | 583 | bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD; |
586 | bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling, | 584 | bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling; |
587 | bt_cmd->bt4_tx_tx_delta_freq_thr = 15, | 585 | bt_cmd->bt4_tx_tx_delta_freq_thr = 15; |
588 | bt_cmd->bt4_tx_rx_max_freq0 = 15, | 586 | bt_cmd->bt4_tx_rx_max_freq0 = 15; |
587 | bt_cmd->override_primary_lut = BT_COEX_INVALID_LUT; | ||
588 | bt_cmd->override_secondary_lut = BT_COEX_INVALID_LUT; | ||
589 | 589 | ||
590 | flags = iwlwifi_mod_params.bt_coex_active ? | 590 | flags = iwlwifi_mod_params.bt_coex_active ? |
591 | BT_COEX_NW : BT_COEX_DISABLE; | 591 | BT_COEX_NW : BT_COEX_DISABLE; |
@@ -1215,6 +1215,17 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, | |||
1215 | return iwl_get_coex_type(mvm, mvmsta->vif) == BT_COEX_TIGHT_LUT; | 1215 | return iwl_get_coex_type(mvm, mvmsta->vif) == BT_COEX_TIGHT_LUT; |
1216 | } | 1216 | } |
1217 | 1217 | ||
1218 | bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm, | ||
1219 | enum ieee80211_band band) | ||
1220 | { | ||
1221 | u32 bt_activity = le32_to_cpu(mvm->last_bt_notif.bt_activity_grading); | ||
1222 | |||
1223 | if (band != IEEE80211_BAND_2GHZ) | ||
1224 | return false; | ||
1225 | |||
1226 | return bt_activity >= BT_LOW_TRAFFIC; | ||
1227 | } | ||
1228 | |||
1218 | u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, | 1229 | u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, |
1219 | struct ieee80211_tx_info *info, u8 ac) | 1230 | struct ieee80211_tx_info *info, u8 ac) |
1220 | { | 1231 | { |
@@ -1249,9 +1260,6 @@ u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, | |||
1249 | 1260 | ||
1250 | void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm) | 1261 | void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm) |
1251 | { | 1262 | { |
1252 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX)) | ||
1253 | return; | ||
1254 | |||
1255 | iwl_mvm_bt_coex_notif_handle(mvm); | 1263 | iwl_mvm_bt_coex_notif_handle(mvm); |
1256 | } | 1264 | } |
1257 | 1265 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index e56f5a0edf85..7694472a303e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -744,10 +744,8 @@ static int iwl_mvm_get_last_nonqos_seq(struct iwl_mvm *mvm, | |||
744 | int err; | 744 | int err; |
745 | u32 size; | 745 | u32 size; |
746 | 746 | ||
747 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API) { | 747 | cmd.data[0] = &query_cmd; |
748 | cmd.data[0] = &query_cmd; | 748 | cmd.len[0] = sizeof(query_cmd); |
749 | cmd.len[0] = sizeof(query_cmd); | ||
750 | } | ||
751 | 749 | ||
752 | err = iwl_mvm_send_cmd(mvm, &cmd); | 750 | err = iwl_mvm_send_cmd(mvm, &cmd); |
753 | if (err) | 751 | if (err) |
@@ -758,10 +756,8 @@ static int iwl_mvm_get_last_nonqos_seq(struct iwl_mvm *mvm, | |||
758 | err = -EINVAL; | 756 | err = -EINVAL; |
759 | } else { | 757 | } else { |
760 | err = le16_to_cpup((__le16 *)cmd.resp_pkt->data); | 758 | err = le16_to_cpup((__le16 *)cmd.resp_pkt->data); |
761 | /* new API returns next, not last-used seqno */ | 759 | /* firmware returns next, not last-used seqno */ |
762 | if (mvm->fw->ucode_capa.flags & | 760 | err = (u16) (err - 0x10); |
763 | IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API) | ||
764 | err = (u16) (err - 0x10); | ||
765 | } | 761 | } |
766 | 762 | ||
767 | iwl_free_resp(&cmd); | 763 | iwl_free_resp(&cmd); |
@@ -785,10 +781,6 @@ void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
785 | 781 | ||
786 | mvmvif->seqno_valid = false; | 782 | mvmvif->seqno_valid = false; |
787 | 783 | ||
788 | if (!(mvm->fw->ucode_capa.flags & | ||
789 | IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API)) | ||
790 | return; | ||
791 | |||
792 | if (iwl_mvm_send_cmd_pdu(mvm, NON_QOS_TX_COUNTER_CMD, CMD_SYNC, | 784 | if (iwl_mvm_send_cmd_pdu(mvm, NON_QOS_TX_COUNTER_CMD, CMD_SYNC, |
793 | sizeof(query_cmd), &query_cmd)) | 785 | sizeof(query_cmd), &query_cmd)) |
794 | IWL_ERR(mvm, "failed to set non-QoS seqno\n"); | 786 | IWL_ERR(mvm, "failed to set non-QoS seqno\n"); |
@@ -1082,6 +1074,15 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
1082 | 1074 | ||
1083 | int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | 1075 | int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) |
1084 | { | 1076 | { |
1077 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
1078 | |||
1079 | if (iwl_mvm_is_d0i3_supported(mvm)) { | ||
1080 | mutex_lock(&mvm->d0i3_suspend_mutex); | ||
1081 | __set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags); | ||
1082 | mutex_unlock(&mvm->d0i3_suspend_mutex); | ||
1083 | return 0; | ||
1084 | } | ||
1085 | |||
1085 | return __iwl_mvm_suspend(hw, wowlan, false); | 1086 | return __iwl_mvm_suspend(hw, wowlan, false); |
1086 | } | 1087 | } |
1087 | 1088 | ||
@@ -1277,7 +1278,7 @@ static void iwl_mvm_set_tkip_rx_seq(struct tkip_sc *scs, | |||
1277 | } | 1278 | } |
1278 | 1279 | ||
1279 | static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key, | 1280 | static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key, |
1280 | struct iwl_wowlan_status_v6 *status) | 1281 | struct iwl_wowlan_status *status) |
1281 | { | 1282 | { |
1282 | union iwl_all_tsc_rsc *rsc = &status->gtk.rsc.all_tsc_rsc; | 1283 | union iwl_all_tsc_rsc *rsc = &status->gtk.rsc.all_tsc_rsc; |
1283 | 1284 | ||
@@ -1294,7 +1295,7 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key, | |||
1294 | } | 1295 | } |
1295 | 1296 | ||
1296 | struct iwl_mvm_d3_gtk_iter_data { | 1297 | struct iwl_mvm_d3_gtk_iter_data { |
1297 | struct iwl_wowlan_status_v6 *status; | 1298 | struct iwl_wowlan_status *status; |
1298 | void *last_gtk; | 1299 | void *last_gtk; |
1299 | u32 cipher; | 1300 | u32 cipher; |
1300 | bool find_phase, unhandled_cipher; | 1301 | bool find_phase, unhandled_cipher; |
@@ -1370,7 +1371,7 @@ static void iwl_mvm_d3_update_gtks(struct ieee80211_hw *hw, | |||
1370 | 1371 | ||
1371 | static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm, | 1372 | static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm, |
1372 | struct ieee80211_vif *vif, | 1373 | struct ieee80211_vif *vif, |
1373 | struct iwl_wowlan_status_v6 *status) | 1374 | struct iwl_wowlan_status *status) |
1374 | { | 1375 | { |
1375 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 1376 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
1376 | struct iwl_mvm_d3_gtk_iter_data gtkdata = { | 1377 | struct iwl_mvm_d3_gtk_iter_data gtkdata = { |
@@ -1468,7 +1469,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
1468 | .flags = CMD_SYNC | CMD_WANT_SKB, | 1469 | .flags = CMD_SYNC | CMD_WANT_SKB, |
1469 | }; | 1470 | }; |
1470 | struct iwl_wowlan_status_data status; | 1471 | struct iwl_wowlan_status_data status; |
1471 | struct iwl_wowlan_status_v6 *status_v6; | 1472 | struct iwl_wowlan_status *fw_status; |
1472 | int ret, len, status_size, i; | 1473 | int ret, len, status_size, i; |
1473 | bool keep; | 1474 | bool keep; |
1474 | struct ieee80211_sta *ap_sta; | 1475 | struct ieee80211_sta *ap_sta; |
@@ -1505,10 +1506,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
1505 | if (!cmd.resp_pkt) | 1506 | if (!cmd.resp_pkt) |
1506 | goto out_unlock; | 1507 | goto out_unlock; |
1507 | 1508 | ||
1508 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API) | 1509 | status_size = sizeof(*fw_status); |
1509 | status_size = sizeof(struct iwl_wowlan_status_v6); | ||
1510 | else | ||
1511 | status_size = sizeof(struct iwl_wowlan_status_v4); | ||
1512 | 1510 | ||
1513 | len = iwl_rx_packet_payload_len(cmd.resp_pkt); | 1511 | len = iwl_rx_packet_payload_len(cmd.resp_pkt); |
1514 | if (len < status_size) { | 1512 | if (len < status_size) { |
@@ -1516,35 +1514,18 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
1516 | goto out_free_resp; | 1514 | goto out_free_resp; |
1517 | } | 1515 | } |
1518 | 1516 | ||
1519 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API) { | 1517 | fw_status = (void *)cmd.resp_pkt->data; |
1520 | status_v6 = (void *)cmd.resp_pkt->data; | 1518 | |
1521 | 1519 | status.pattern_number = le16_to_cpu(fw_status->pattern_number); | |
1522 | status.pattern_number = le16_to_cpu(status_v6->pattern_number); | 1520 | for (i = 0; i < 8; i++) |
1523 | for (i = 0; i < 8; i++) | 1521 | status.qos_seq_ctr[i] = |
1524 | status.qos_seq_ctr[i] = | 1522 | le16_to_cpu(fw_status->qos_seq_ctr[i]); |
1525 | le16_to_cpu(status_v6->qos_seq_ctr[i]); | 1523 | status.wakeup_reasons = le32_to_cpu(fw_status->wakeup_reasons); |
1526 | status.wakeup_reasons = le32_to_cpu(status_v6->wakeup_reasons); | 1524 | status.wake_packet_length = |
1527 | status.wake_packet_length = | 1525 | le32_to_cpu(fw_status->wake_packet_length); |
1528 | le32_to_cpu(status_v6->wake_packet_length); | 1526 | status.wake_packet_bufsize = |
1529 | status.wake_packet_bufsize = | 1527 | le32_to_cpu(fw_status->wake_packet_bufsize); |
1530 | le32_to_cpu(status_v6->wake_packet_bufsize); | 1528 | status.wake_packet = fw_status->wake_packet; |
1531 | status.wake_packet = status_v6->wake_packet; | ||
1532 | } else { | ||
1533 | struct iwl_wowlan_status_v4 *status_v4; | ||
1534 | status_v6 = NULL; | ||
1535 | status_v4 = (void *)cmd.resp_pkt->data; | ||
1536 | |||
1537 | status.pattern_number = le16_to_cpu(status_v4->pattern_number); | ||
1538 | for (i = 0; i < 8; i++) | ||
1539 | status.qos_seq_ctr[i] = | ||
1540 | le16_to_cpu(status_v4->qos_seq_ctr[i]); | ||
1541 | status.wakeup_reasons = le32_to_cpu(status_v4->wakeup_reasons); | ||
1542 | status.wake_packet_length = | ||
1543 | le32_to_cpu(status_v4->wake_packet_length); | ||
1544 | status.wake_packet_bufsize = | ||
1545 | le32_to_cpu(status_v4->wake_packet_bufsize); | ||
1546 | status.wake_packet = status_v4->wake_packet; | ||
1547 | } | ||
1548 | 1529 | ||
1549 | if (len != status_size + ALIGN(status.wake_packet_bufsize, 4)) { | 1530 | if (len != status_size + ALIGN(status.wake_packet_bufsize, 4)) { |
1550 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | 1531 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); |
@@ -1571,7 +1552,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
1571 | 1552 | ||
1572 | iwl_mvm_report_wakeup_reasons(mvm, vif, &status); | 1553 | iwl_mvm_report_wakeup_reasons(mvm, vif, &status); |
1573 | 1554 | ||
1574 | keep = iwl_mvm_setup_connection_keep(mvm, vif, status_v6); | 1555 | keep = iwl_mvm_setup_connection_keep(mvm, vif, fw_status); |
1575 | 1556 | ||
1576 | iwl_free_resp(&cmd); | 1557 | iwl_free_resp(&cmd); |
1577 | return keep; | 1558 | return keep; |
@@ -1674,6 +1655,19 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) | |||
1674 | { | 1655 | { |
1675 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1656 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1676 | 1657 | ||
1658 | if (iwl_mvm_is_d0i3_supported(mvm)) { | ||
1659 | bool exit_now; | ||
1660 | |||
1661 | mutex_lock(&mvm->d0i3_suspend_mutex); | ||
1662 | __clear_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags); | ||
1663 | exit_now = __test_and_clear_bit(D0I3_PENDING_WAKEUP, | ||
1664 | &mvm->d0i3_suspend_flags); | ||
1665 | mutex_unlock(&mvm->d0i3_suspend_mutex); | ||
1666 | if (exit_now) | ||
1667 | _iwl_mvm_exit_d0i3(mvm); | ||
1668 | return 0; | ||
1669 | } | ||
1670 | |||
1677 | return __iwl_mvm_resume(mvm, false); | 1671 | return __iwl_mvm_resume(mvm, false); |
1678 | } | 1672 | } |
1679 | 1673 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 9b59e1d7ae71..6047cfdafb95 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | |||
@@ -103,10 +103,6 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, | |||
103 | IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val); | 103 | IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val); |
104 | dbgfs_pm->tx_data_timeout = val; | 104 | dbgfs_pm->tx_data_timeout = val; |
105 | break; | 105 | break; |
106 | case MVM_DEBUGFS_PM_DISABLE_POWER_OFF: | ||
107 | IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val); | ||
108 | dbgfs_pm->disable_power_off = val; | ||
109 | break; | ||
110 | case MVM_DEBUGFS_PM_LPRX_ENA: | 106 | case MVM_DEBUGFS_PM_LPRX_ENA: |
111 | IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled"); | 107 | IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled"); |
112 | dbgfs_pm->lprx_ena = val; | 108 | dbgfs_pm->lprx_ena = val; |
@@ -154,12 +150,6 @@ static ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf, | |||
154 | if (sscanf(buf + 16, "%d", &val) != 1) | 150 | if (sscanf(buf + 16, "%d", &val) != 1) |
155 | return -EINVAL; | 151 | return -EINVAL; |
156 | param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT; | 152 | param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT; |
157 | } else if (!strncmp("disable_power_off=", buf, 18) && | ||
158 | !(mvm->fw->ucode_capa.flags & | ||
159 | IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) { | ||
160 | if (sscanf(buf + 18, "%d", &val) != 1) | ||
161 | return -EINVAL; | ||
162 | param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF; | ||
163 | } else if (!strncmp("lprx=", buf, 5)) { | 153 | } else if (!strncmp("lprx=", buf, 5)) { |
164 | if (sscanf(buf + 5, "%d", &val) != 1) | 154 | if (sscanf(buf + 5, "%d", &val) != 1) |
165 | return -EINVAL; | 155 | return -EINVAL; |
@@ -592,8 +582,7 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
592 | return; | 582 | return; |
593 | } | 583 | } |
594 | 584 | ||
595 | if ((mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT) && | 585 | if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM && |
596 | iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM && | ||
597 | ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) || | 586 | ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) || |
598 | (vif->type == NL80211_IFTYPE_STATION && vif->p2p && | 587 | (vif->type == NL80211_IFTYPE_STATION && vif->p2p && |
599 | mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM))) | 588 | mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM))) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 1b52deea6081..f462c9baa2b5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -136,9 +136,6 @@ static int iwl_dbgfs_fw_error_dump_open(struct inode *inode, struct file *file) | |||
136 | 136 | ||
137 | file->private_data = mvm->fw_error_dump; | 137 | file->private_data = mvm->fw_error_dump; |
138 | mvm->fw_error_dump = NULL; | 138 | mvm->fw_error_dump = NULL; |
139 | kfree(mvm->fw_error_sram); | ||
140 | mvm->fw_error_sram = NULL; | ||
141 | mvm->fw_error_sram_len = 0; | ||
142 | ret = 0; | 139 | ret = 0; |
143 | 140 | ||
144 | out: | 141 | out: |
@@ -1004,6 +1001,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file, | |||
1004 | PRINT_MVM_REF(IWL_MVM_REF_P2P_CLIENT); | 1001 | PRINT_MVM_REF(IWL_MVM_REF_P2P_CLIENT); |
1005 | PRINT_MVM_REF(IWL_MVM_REF_AP_IBSS); | 1002 | PRINT_MVM_REF(IWL_MVM_REF_AP_IBSS); |
1006 | PRINT_MVM_REF(IWL_MVM_REF_USER); | 1003 | PRINT_MVM_REF(IWL_MVM_REF_USER); |
1004 | PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK); | ||
1007 | 1005 | ||
1008 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1006 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1009 | } | 1007 | } |
@@ -1108,9 +1106,9 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); | |||
1108 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); | 1106 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); |
1109 | 1107 | ||
1110 | static const struct file_operations iwl_dbgfs_fw_error_dump_ops = { | 1108 | static const struct file_operations iwl_dbgfs_fw_error_dump_ops = { |
1111 | .open = iwl_dbgfs_fw_error_dump_open, | 1109 | .open = iwl_dbgfs_fw_error_dump_open, |
1112 | .read = iwl_dbgfs_fw_error_dump_read, | 1110 | .read = iwl_dbgfs_fw_error_dump_read, |
1113 | .release = iwl_dbgfs_fw_error_dump_release, | 1111 | .release = iwl_dbgfs_fw_error_dump_release, |
1114 | }; | 1112 | }; |
1115 | 1113 | ||
1116 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING | 1114 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING |
@@ -1138,9 +1136,8 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
1138 | MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR); | 1136 | MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR); |
1139 | MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); | 1137 | MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); |
1140 | MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR); | 1138 | MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR); |
1141 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD) | 1139 | MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, |
1142 | MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, | 1140 | S_IRUSR | S_IWUSR); |
1143 | S_IRUSR | S_IWUSR); | ||
1144 | MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR); | 1141 | MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR); |
1145 | MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, S_IRUSR); | 1142 | MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, S_IRUSR); |
1146 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); | 1143 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h index 21877e5966a8..5fe82c29c8ad 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h | |||
@@ -141,7 +141,8 @@ enum iwl_bt_coex_lut_type { | |||
141 | BT_COEX_TX_DIS_LUT, | 141 | BT_COEX_TX_DIS_LUT, |
142 | 142 | ||
143 | BT_COEX_MAX_LUT, | 143 | BT_COEX_MAX_LUT, |
144 | }; | 144 | BT_COEX_INVALID_LUT = 0xff, |
145 | }; /* BT_COEX_DECISION_LUT_INDEX_API_E_VER_1 */ | ||
145 | 146 | ||
146 | #define BT_COEX_LUT_SIZE (12) | 147 | #define BT_COEX_LUT_SIZE (12) |
147 | #define BT_COEX_CORUN_LUT_SIZE (32) | 148 | #define BT_COEX_CORUN_LUT_SIZE (32) |
@@ -154,19 +155,23 @@ enum iwl_bt_coex_lut_type { | |||
154 | * @flags:&enum iwl_bt_coex_flags | 155 | * @flags:&enum iwl_bt_coex_flags |
155 | * @max_kill: | 156 | * @max_kill: |
156 | * @bt_reduced_tx_power: enum %iwl_bt_reduced_tx_power | 157 | * @bt_reduced_tx_power: enum %iwl_bt_reduced_tx_power |
157 | * @bt4_antenna_isolation: | 158 | * @override_primary_lut: enum %iwl_bt_coex_lut_type: BT_COEX_INVALID_LUT |
158 | * @bt4_antenna_isolation_thr: | 159 | * should be set by default |
159 | * @bt4_tx_tx_delta_freq_thr: | 160 | * @override_secondary_lut: enum %iwl_bt_coex_lut_type: BT_COEX_INVALID_LUT |
160 | * @bt4_tx_rx_max_freq0: | 161 | * should be set by default |
161 | * @bt_prio_boost: | 162 | * @bt4_antenna_isolation: antenna isolation |
163 | * @bt4_antenna_isolation_thr: antenna threshold value | ||
164 | * @bt4_tx_tx_delta_freq_thr: TxTx delta frequency | ||
165 | * @bt4_tx_rx_max_freq0: TxRx max frequency | ||
166 | * @bt_prio_boost: BT priority boost registers | ||
162 | * @wifi_tx_prio_boost: SW boost of wifi tx priority | 167 | * @wifi_tx_prio_boost: SW boost of wifi tx priority |
163 | * @wifi_rx_prio_boost: SW boost of wifi rx priority | 168 | * @wifi_rx_prio_boost: SW boost of wifi rx priority |
164 | * @kill_ack_msk: | 169 | * @kill_ack_msk: kill ACK mask. 1 - Tx ACK, 0 - kill Tx of ACK. |
165 | * @kill_cts_msk: | 170 | * @kill_cts_msk: kill CTS mask. 1 - Tx CTS, 0 - kill Tx of CTS. |
166 | * @decision_lut: | 171 | * @decision_lut: PTA decision LUT, per Prio-Ch |
167 | * @bt4_multiprio_lut: | 172 | * @bt4_multiprio_lut: multi priority LUT configuration |
168 | * @bt4_corun_lut20: | 173 | * @bt4_corun_lut20: co-running 20 MHz LUT configuration |
169 | * @bt4_corun_lut40: | 174 | * @bt4_corun_lut40: co-running 40 MHz LUT configuration |
170 | * @valid_bit_msk: enum %iwl_bt_coex_valid_bit_msk | 175 | * @valid_bit_msk: enum %iwl_bt_coex_valid_bit_msk |
171 | * | 176 | * |
172 | * The structure is used for the BT_COEX command. | 177 | * The structure is used for the BT_COEX command. |
@@ -175,7 +180,8 @@ struct iwl_bt_coex_cmd { | |||
175 | __le32 flags; | 180 | __le32 flags; |
176 | u8 max_kill; | 181 | u8 max_kill; |
177 | u8 bt_reduced_tx_power; | 182 | u8 bt_reduced_tx_power; |
178 | u8 reserved[2]; | 183 | u8 override_primary_lut; |
184 | u8 override_secondary_lut; | ||
179 | 185 | ||
180 | u8 bt4_antenna_isolation; | 186 | u8 bt4_antenna_isolation; |
181 | u8 bt4_antenna_isolation_thr; | 187 | u8 bt4_antenna_isolation_thr; |
@@ -194,7 +200,7 @@ struct iwl_bt_coex_cmd { | |||
194 | __le32 bt4_corun_lut40[BT_COEX_CORUN_LUT_SIZE]; | 200 | __le32 bt4_corun_lut40[BT_COEX_CORUN_LUT_SIZE]; |
195 | 201 | ||
196 | __le32 valid_bit_msk; | 202 | __le32 valid_bit_msk; |
197 | } __packed; /* BT_COEX_CMD_API_S_VER_3 */ | 203 | } __packed; /* BT_COEX_CMD_API_S_VER_5 */ |
198 | 204 | ||
199 | /** | 205 | /** |
200 | * struct iwl_bt_coex_ci_cmd - bt coex channel inhibition command | 206 | * struct iwl_bt_coex_ci_cmd - bt coex channel inhibition command |
@@ -282,7 +288,7 @@ enum iwl_bt_activity_grading { | |||
282 | BT_ON_NO_CONNECTION = 1, | 288 | BT_ON_NO_CONNECTION = 1, |
283 | BT_LOW_TRAFFIC = 2, | 289 | BT_LOW_TRAFFIC = 2, |
284 | BT_HIGH_TRAFFIC = 3, | 290 | BT_HIGH_TRAFFIC = 3, |
285 | }; | 291 | }; /* BT_COEX_BT_ACTIVITY_GRADING_API_E_VER_1 */ |
286 | 292 | ||
287 | /** | 293 | /** |
288 | * struct iwl_bt_coex_profile_notif - notification about BT coex | 294 | * struct iwl_bt_coex_profile_notif - notification about BT coex |
@@ -310,7 +316,7 @@ struct iwl_bt_coex_profile_notif { | |||
310 | __le32 primary_ch_lut; | 316 | __le32 primary_ch_lut; |
311 | __le32 secondary_ch_lut; | 317 | __le32 secondary_ch_lut; |
312 | __le32 bt_activity_grading; | 318 | __le32 bt_activity_grading; |
313 | } __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_2 */ | 319 | } __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_3 */ |
314 | 320 | ||
315 | enum iwl_bt_coex_prio_table_event { | 321 | enum iwl_bt_coex_prio_table_event { |
316 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB1 = 0, | 322 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB1 = 0, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h index 10fcc1a79ebd..13696fe419b7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h | |||
@@ -345,21 +345,6 @@ enum iwl_wowlan_wakeup_reason { | |||
345 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12), | 345 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12), |
346 | }; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */ | 346 | }; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */ |
347 | 347 | ||
348 | struct iwl_wowlan_status_v4 { | ||
349 | __le64 replay_ctr; | ||
350 | __le16 pattern_number; | ||
351 | __le16 non_qos_seq_ctr; | ||
352 | __le16 qos_seq_ctr[8]; | ||
353 | __le32 wakeup_reasons; | ||
354 | __le32 rekey_status; | ||
355 | __le32 num_of_gtk_rekeys; | ||
356 | __le32 transmitted_ndps; | ||
357 | __le32 received_beacons; | ||
358 | __le32 wake_packet_length; | ||
359 | __le32 wake_packet_bufsize; | ||
360 | u8 wake_packet[]; /* can be truncated from _length to _bufsize */ | ||
361 | } __packed; /* WOWLAN_STATUSES_API_S_VER_4 */ | ||
362 | |||
363 | struct iwl_wowlan_gtk_status { | 348 | struct iwl_wowlan_gtk_status { |
364 | u8 key_index; | 349 | u8 key_index; |
365 | u8 reserved[3]; | 350 | u8 reserved[3]; |
@@ -368,7 +353,7 @@ struct iwl_wowlan_gtk_status { | |||
368 | struct iwl_wowlan_rsc_tsc_params_cmd rsc; | 353 | struct iwl_wowlan_rsc_tsc_params_cmd rsc; |
369 | } __packed; | 354 | } __packed; |
370 | 355 | ||
371 | struct iwl_wowlan_status_v6 { | 356 | struct iwl_wowlan_status { |
372 | struct iwl_wowlan_gtk_status gtk; | 357 | struct iwl_wowlan_gtk_status gtk; |
373 | __le64 replay_ctr; | 358 | __le64 replay_ctr; |
374 | __le16 pattern_number; | 359 | __le16 pattern_number; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h index 39148b5bb332..8bb5b94bf963 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h | |||
@@ -334,7 +334,7 @@ enum { | |||
334 | */ | 334 | */ |
335 | struct iwl_lq_cmd { | 335 | struct iwl_lq_cmd { |
336 | u8 sta_id; | 336 | u8 sta_id; |
337 | u8 reserved1; | 337 | u8 reduced_tpc; |
338 | u16 control; | 338 | u16 control; |
339 | /* LINK_QUAL_GENERAL_PARAMS_API_S_VER_1 */ | 339 | /* LINK_QUAL_GENERAL_PARAMS_API_S_VER_1 */ |
340 | u8 flags; | 340 | u8 flags; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 9426905de6b2..6174c027ff59 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | |||
@@ -169,8 +169,12 @@ enum iwl_scan_type { | |||
169 | SCAN_TYPE_DISCOVERY_FORCED = 6, | 169 | SCAN_TYPE_DISCOVERY_FORCED = 6, |
170 | }; /* SCAN_ACTIVITY_TYPE_E_VER_1 */ | 170 | }; /* SCAN_ACTIVITY_TYPE_E_VER_1 */ |
171 | 171 | ||
172 | /* Maximal number of channels to scan */ | 172 | /** |
173 | #define MAX_NUM_SCAN_CHANNELS 0x24 | 173 | * Maximal number of channels to scan |
174 | * it should be equal to: | ||
175 | * max(IWL_NUM_CHANNELS, IWL_NUM_CHANNELS_FAMILY_8000) | ||
176 | */ | ||
177 | #define MAX_NUM_SCAN_CHANNELS 50 | ||
174 | 178 | ||
175 | /** | 179 | /** |
176 | * struct iwl_scan_cmd - scan request command | 180 | * struct iwl_scan_cmd - scan request command |
@@ -534,13 +538,16 @@ struct iwl_scan_offload_schedule { | |||
534 | * | 538 | * |
535 | * IWL_SCAN_OFFLOAD_FLAG_PASS_ALL: pass all results - no filtering. | 539 | * IWL_SCAN_OFFLOAD_FLAG_PASS_ALL: pass all results - no filtering. |
536 | * IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL: add cached channels to partial scan. | 540 | * IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL: add cached channels to partial scan. |
537 | * IWL_SCAN_OFFLOAD_FLAG_ENERGY_SCAN: use energy based scan before partial scan | 541 | * IWL_SCAN_OFFLOAD_FLAG_EBS_QUICK_MODE: EBS duration is 100mSec - typical |
538 | * on A band. | 542 | * beacon period. Finding channel activity in this mode is not guaranteed. |
543 | * IWL_SCAN_OFFLOAD_FLAG_EBS_ACCURATE_MODE: EBS duration is 200mSec. | ||
544 | * Assuming beacon period is 100ms finding channel activity is guaranteed. | ||
539 | */ | 545 | */ |
540 | enum iwl_scan_offload_flags { | 546 | enum iwl_scan_offload_flags { |
541 | IWL_SCAN_OFFLOAD_FLAG_PASS_ALL = BIT(0), | 547 | IWL_SCAN_OFFLOAD_FLAG_PASS_ALL = BIT(0), |
542 | IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL = BIT(2), | 548 | IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL = BIT(2), |
543 | IWL_SCAN_OFFLOAD_FLAG_ENERGY_SCAN = BIT(3), | 549 | IWL_SCAN_OFFLOAD_FLAG_EBS_QUICK_MODE = BIT(5), |
550 | IWL_SCAN_OFFLOAD_FLAG_EBS_ACCURATE_MODE = BIT(6), | ||
544 | }; | 551 | }; |
545 | 552 | ||
546 | /** | 553 | /** |
@@ -563,17 +570,24 @@ enum iwl_scan_offload_compleate_status { | |||
563 | IWL_SCAN_OFFLOAD_ABORTED = 2, | 570 | IWL_SCAN_OFFLOAD_ABORTED = 2, |
564 | }; | 571 | }; |
565 | 572 | ||
573 | enum iwl_scan_ebs_status { | ||
574 | IWL_SCAN_EBS_SUCCESS, | ||
575 | IWL_SCAN_EBS_FAILED, | ||
576 | IWL_SCAN_EBS_CHAN_NOT_FOUND, | ||
577 | }; | ||
578 | |||
566 | /** | 579 | /** |
567 | * iwl_scan_offload_complete - SCAN_OFFLOAD_COMPLETE_NTF_API_S_VER_1 | 580 | * iwl_scan_offload_complete - SCAN_OFFLOAD_COMPLETE_NTF_API_S_VER_1 |
568 | * @last_schedule_line: last schedule line executed (fast or regular) | 581 | * @last_schedule_line: last schedule line executed (fast or regular) |
569 | * @last_schedule_iteration: last scan iteration executed before scan abort | 582 | * @last_schedule_iteration: last scan iteration executed before scan abort |
570 | * @status: enum iwl_scan_offload_compleate_status | 583 | * @status: enum iwl_scan_offload_compleate_status |
584 | * @ebs_status: last EBS status, see IWL_SCAN_EBS_* | ||
571 | */ | 585 | */ |
572 | struct iwl_scan_offload_complete { | 586 | struct iwl_scan_offload_complete { |
573 | u8 last_schedule_line; | 587 | u8 last_schedule_line; |
574 | u8 last_schedule_iteration; | 588 | u8 last_schedule_iteration; |
575 | u8 status; | 589 | u8 status; |
576 | u8 reserved; | 590 | u8 ebs_status; |
577 | } __packed; | 591 | } __packed; |
578 | 592 | ||
579 | /** | 593 | /** |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h index d63647867262..39cebee8016f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h | |||
@@ -255,22 +255,19 @@ struct iwl_mvm_keyinfo { | |||
255 | } __packed; | 255 | } __packed; |
256 | 256 | ||
257 | /** | 257 | /** |
258 | * struct iwl_mvm_add_sta_cmd_v5 - Add/modify a station in the fw's sta table. | 258 | * struct iwl_mvm_add_sta_cmd - Add/modify a station in the fw's sta table. |
259 | * ( REPLY_ADD_STA = 0x18 ) | 259 | * ( REPLY_ADD_STA = 0x18 ) |
260 | * @add_modify: 1: modify existing, 0: add new station | 260 | * @add_modify: 1: modify existing, 0: add new station |
261 | * @unicast_tx_key_id: unicast tx key id. Relevant only when unicast key sent | 261 | * @awake_acs: |
262 | * @multicast_tx_key_id: multicast tx key id. Relevant only when multicast key | 262 | * @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable |
263 | * sent | 263 | * AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field. |
264 | * @mac_id_n_color: the Mac context this station belongs to | 264 | * @mac_id_n_color: the Mac context this station belongs to |
265 | * @addr[ETH_ALEN]: station's MAC address | 265 | * @addr[ETH_ALEN]: station's MAC address |
266 | * @sta_id: index of station in uCode's station table | 266 | * @sta_id: index of station in uCode's station table |
267 | * @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave | 267 | * @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave |
268 | * alone. 1 - modify, 0 - don't change. | 268 | * alone. 1 - modify, 0 - don't change. |
269 | * @key: look at %iwl_mvm_keyinfo | ||
270 | * @station_flags: look at %iwl_sta_flags | 269 | * @station_flags: look at %iwl_sta_flags |
271 | * @station_flags_msk: what of %station_flags have changed | 270 | * @station_flags_msk: what of %station_flags have changed |
272 | * @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable | ||
273 | * AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field. | ||
274 | * @add_immediate_ba_tid: tid for which to add block-ack support (Rx) | 271 | * @add_immediate_ba_tid: tid for which to add block-ack support (Rx) |
275 | * Set %STA_MODIFY_ADD_BA_TID to use this field, and also set | 272 | * Set %STA_MODIFY_ADD_BA_TID to use this field, and also set |
276 | * add_immediate_ba_ssn. | 273 | * add_immediate_ba_ssn. |
@@ -294,40 +291,7 @@ struct iwl_mvm_keyinfo { | |||
294 | * ADD_STA sets up the table entry for one station, either creating a new | 291 | * ADD_STA sets up the table entry for one station, either creating a new |
295 | * entry, or modifying a pre-existing one. | 292 | * entry, or modifying a pre-existing one. |
296 | */ | 293 | */ |
297 | struct iwl_mvm_add_sta_cmd_v5 { | 294 | struct iwl_mvm_add_sta_cmd { |
298 | u8 add_modify; | ||
299 | u8 unicast_tx_key_id; | ||
300 | u8 multicast_tx_key_id; | ||
301 | u8 reserved1; | ||
302 | __le32 mac_id_n_color; | ||
303 | u8 addr[ETH_ALEN]; | ||
304 | __le16 reserved2; | ||
305 | u8 sta_id; | ||
306 | u8 modify_mask; | ||
307 | __le16 reserved3; | ||
308 | struct iwl_mvm_keyinfo key; | ||
309 | __le32 station_flags; | ||
310 | __le32 station_flags_msk; | ||
311 | __le16 tid_disable_tx; | ||
312 | __le16 reserved4; | ||
313 | u8 add_immediate_ba_tid; | ||
314 | u8 remove_immediate_ba_tid; | ||
315 | __le16 add_immediate_ba_ssn; | ||
316 | __le16 sleep_tx_count; | ||
317 | __le16 sleep_state_flags; | ||
318 | __le16 assoc_id; | ||
319 | __le16 beamform_flags; | ||
320 | __le32 tfd_queue_msk; | ||
321 | } __packed; /* ADD_STA_CMD_API_S_VER_5 */ | ||
322 | |||
323 | /** | ||
324 | * struct iwl_mvm_add_sta_cmd_v7 - Add / modify a station | ||
325 | * VER_7 of this command is quite similar to VER_5 except | ||
326 | * exclusion of all fields related to the security key installation. | ||
327 | * It only differs from VER_6 by the "awake_acs" field that is | ||
328 | * reserved and ignored in VER_6. | ||
329 | */ | ||
330 | struct iwl_mvm_add_sta_cmd_v7 { | ||
331 | u8 add_modify; | 295 | u8 add_modify; |
332 | u8 awake_acs; | 296 | u8 awake_acs; |
333 | __le16 tid_disable_tx; | 297 | __le16 tid_disable_tx; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h index 8e122f3a7a74..6cc5f52b807f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | |||
@@ -482,7 +482,8 @@ struct iwl_mvm_tx_resp { | |||
482 | u8 pa_integ_res_b[3]; | 482 | u8 pa_integ_res_b[3]; |
483 | u8 pa_integ_res_c[3]; | 483 | u8 pa_integ_res_c[3]; |
484 | __le16 measurement_req_id; | 484 | __le16 measurement_req_id; |
485 | __le16 reserved; | 485 | u8 reduced_tpc; |
486 | u8 reserved; | ||
486 | 487 | ||
487 | __le32 tfd_info; | 488 | __le32 tfd_info; |
488 | __le16 seq_ctl; | 489 | __le16 seq_ctl; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 6e75b52588de..309a9b9a94fe 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -71,6 +71,7 @@ | |||
71 | #include "fw-api-power.h" | 71 | #include "fw-api-power.h" |
72 | #include "fw-api-d3.h" | 72 | #include "fw-api-d3.h" |
73 | #include "fw-api-coex.h" | 73 | #include "fw-api-coex.h" |
74 | #include "fw-api-scan.h" | ||
74 | 75 | ||
75 | /* maximal number of Tx queues in any platform */ | 76 | /* maximal number of Tx queues in any platform */ |
76 | #define IWL_MVM_MAX_QUEUES 20 | 77 | #define IWL_MVM_MAX_QUEUES 20 |
@@ -604,52 +605,7 @@ enum { | |||
604 | TE_V1_NOTIF_INTERNAL_FRAG_END = BIT(7), | 605 | TE_V1_NOTIF_INTERNAL_FRAG_END = BIT(7), |
605 | }; /* MAC_EVENT_ACTION_API_E_VER_2 */ | 606 | }; /* MAC_EVENT_ACTION_API_E_VER_2 */ |
606 | 607 | ||
607 | 608 | /* Time event - defines for command API */ | |
608 | /** | ||
609 | * struct iwl_time_event_cmd_api_v1 - configuring Time Events | ||
610 | * with struct MAC_TIME_EVENT_DATA_API_S_VER_1 (see also | ||
611 | * with version 2. determined by IWL_UCODE_TLV_FLAGS) | ||
612 | * ( TIME_EVENT_CMD = 0x29 ) | ||
613 | * @id_and_color: ID and color of the relevant MAC | ||
614 | * @action: action to perform, one of FW_CTXT_ACTION_* | ||
615 | * @id: this field has two meanings, depending on the action: | ||
616 | * If the action is ADD, then it means the type of event to add. | ||
617 | * For all other actions it is the unique event ID assigned when the | ||
618 | * event was added by the FW. | ||
619 | * @apply_time: When to start the Time Event (in GP2) | ||
620 | * @max_delay: maximum delay to event's start (apply time), in TU | ||
621 | * @depends_on: the unique ID of the event we depend on (if any) | ||
622 | * @interval: interval between repetitions, in TU | ||
623 | * @interval_reciprocal: 2^32 / interval | ||
624 | * @duration: duration of event in TU | ||
625 | * @repeat: how many repetitions to do, can be TE_REPEAT_ENDLESS | ||
626 | * @dep_policy: one of TE_V1_INDEPENDENT, TE_V1_DEP_OTHER, TE_V1_DEP_TSF | ||
627 | * and TE_V1_EVENT_SOCIOPATHIC | ||
628 | * @is_present: 0 or 1, are we present or absent during the Time Event | ||
629 | * @max_frags: maximal number of fragments the Time Event can be divided to | ||
630 | * @notify: notifications using TE_V1_NOTIF_* (whom to notify when) | ||
631 | */ | ||
632 | struct iwl_time_event_cmd_v1 { | ||
633 | /* COMMON_INDEX_HDR_API_S_VER_1 */ | ||
634 | __le32 id_and_color; | ||
635 | __le32 action; | ||
636 | __le32 id; | ||
637 | /* MAC_TIME_EVENT_DATA_API_S_VER_1 */ | ||
638 | __le32 apply_time; | ||
639 | __le32 max_delay; | ||
640 | __le32 dep_policy; | ||
641 | __le32 depends_on; | ||
642 | __le32 is_present; | ||
643 | __le32 max_frags; | ||
644 | __le32 interval; | ||
645 | __le32 interval_reciprocal; | ||
646 | __le32 duration; | ||
647 | __le32 repeat; | ||
648 | __le32 notify; | ||
649 | } __packed; /* MAC_TIME_EVENT_CMD_API_S_VER_1 */ | ||
650 | |||
651 | |||
652 | /* Time event - defines for command API v2 */ | ||
653 | 609 | ||
654 | /* | 610 | /* |
655 | * @TE_V2_FRAG_NONE: fragmentation of the time event is NOT allowed. | 611 | * @TE_V2_FRAG_NONE: fragmentation of the time event is NOT allowed. |
@@ -680,7 +636,7 @@ enum { | |||
680 | #define TE_V2_PLACEMENT_POS 12 | 636 | #define TE_V2_PLACEMENT_POS 12 |
681 | #define TE_V2_ABSENCE_POS 15 | 637 | #define TE_V2_ABSENCE_POS 15 |
682 | 638 | ||
683 | /* Time event policy values (for time event cmd api v2) | 639 | /* Time event policy values |
684 | * A notification (both event and fragment) includes a status indicating weather | 640 | * A notification (both event and fragment) includes a status indicating weather |
685 | * the FW was able to schedule the event or not. For fragment start/end | 641 | * the FW was able to schedule the event or not. For fragment start/end |
686 | * notification the status is always success. There is no start/end fragment | 642 | * notification the status is always success. There is no start/end fragment |
@@ -727,7 +683,7 @@ enum { | |||
727 | }; | 683 | }; |
728 | 684 | ||
729 | /** | 685 | /** |
730 | * struct iwl_time_event_cmd_api_v2 - configuring Time Events | 686 | * struct iwl_time_event_cmd_api - configuring Time Events |
731 | * with struct MAC_TIME_EVENT_DATA_API_S_VER_2 (see also | 687 | * with struct MAC_TIME_EVENT_DATA_API_S_VER_2 (see also |
732 | * with version 1. determined by IWL_UCODE_TLV_FLAGS) | 688 | * with version 1. determined by IWL_UCODE_TLV_FLAGS) |
733 | * ( TIME_EVENT_CMD = 0x29 ) | 689 | * ( TIME_EVENT_CMD = 0x29 ) |
@@ -750,7 +706,7 @@ enum { | |||
750 | * TE_EVENT_SOCIOPATHIC | 706 | * TE_EVENT_SOCIOPATHIC |
751 | * using TE_ABSENCE and using TE_NOTIF_* | 707 | * using TE_ABSENCE and using TE_NOTIF_* |
752 | */ | 708 | */ |
753 | struct iwl_time_event_cmd_v2 { | 709 | struct iwl_time_event_cmd { |
754 | /* COMMON_INDEX_HDR_API_S_VER_1 */ | 710 | /* COMMON_INDEX_HDR_API_S_VER_1 */ |
755 | __le32 id_and_color; | 711 | __le32 id_and_color; |
756 | __le32 action; | 712 | __le32 action; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h b/drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h index 58c8941c0d95..f381908be7e5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h | |||
@@ -71,10 +71,12 @@ | |||
71 | * enum iwl_fw_error_dump_type - types of data in the dump file | 71 | * enum iwl_fw_error_dump_type - types of data in the dump file |
72 | * @IWL_FW_ERROR_DUMP_SRAM: | 72 | * @IWL_FW_ERROR_DUMP_SRAM: |
73 | * @IWL_FW_ERROR_DUMP_REG: | 73 | * @IWL_FW_ERROR_DUMP_REG: |
74 | * @IWL_FW_ERROR_DUMP_RXF: | ||
74 | */ | 75 | */ |
75 | enum iwl_fw_error_dump_type { | 76 | enum iwl_fw_error_dump_type { |
76 | IWL_FW_ERROR_DUMP_SRAM = 0, | 77 | IWL_FW_ERROR_DUMP_SRAM = 0, |
77 | IWL_FW_ERROR_DUMP_REG = 1, | 78 | IWL_FW_ERROR_DUMP_REG = 1, |
79 | IWL_FW_ERROR_DUMP_RXF = 2, | ||
78 | 80 | ||
79 | IWL_FW_ERROR_DUMP_MAX, | 81 | IWL_FW_ERROR_DUMP_MAX, |
80 | }; | 82 | }; |
@@ -89,7 +91,7 @@ struct iwl_fw_error_dump_data { | |||
89 | __le32 type; | 91 | __le32 type; |
90 | __le32 len; | 92 | __le32 len; |
91 | __u8 data[]; | 93 | __u8 data[]; |
92 | } __packed __aligned(4); | 94 | } __packed; |
93 | 95 | ||
94 | /** | 96 | /** |
95 | * struct iwl_fw_error_dump_file - the layout of the header of the file | 97 | * struct iwl_fw_error_dump_file - the layout of the header of the file |
@@ -101,6 +103,6 @@ struct iwl_fw_error_dump_file { | |||
101 | __le32 barker; | 103 | __le32 barker; |
102 | __le32 file_len; | 104 | __le32 file_len; |
103 | u8 data[0]; | 105 | u8 data[0]; |
104 | } __packed __aligned(4); | 106 | } __packed; |
105 | 107 | ||
106 | #endif /* __fw_error_dump_h__ */ | 108 | #endif /* __fw_error_dump_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 7ce20062f32d..3d99cf564ba6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -288,7 +288,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
288 | goto error; | 288 | goto error; |
289 | } | 289 | } |
290 | 290 | ||
291 | ret = iwl_send_bt_prio_tbl(mvm); | 291 | ret = iwl_send_bt_init_conf(mvm); |
292 | if (ret) | 292 | if (ret) |
293 | goto error; | 293 | goto error; |
294 | 294 | ||
@@ -424,10 +424,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
424 | if (ret) | 424 | if (ret) |
425 | goto error; | 425 | goto error; |
426 | 426 | ||
427 | ret = iwl_send_bt_prio_tbl(mvm); | ||
428 | if (ret) | ||
429 | goto error; | ||
430 | |||
431 | ret = iwl_send_bt_init_conf(mvm); | 427 | ret = iwl_send_bt_init_conf(mvm); |
432 | if (ret) | 428 | if (ret) |
433 | goto error; | 429 | goto error; |
@@ -468,12 +464,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
468 | /* Initialize tx backoffs to the minimal possible */ | 464 | /* Initialize tx backoffs to the minimal possible */ |
469 | iwl_mvm_tt_tx_backoff(mvm, 0); | 465 | iwl_mvm_tt_tx_backoff(mvm, 0); |
470 | 466 | ||
471 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) { | ||
472 | ret = iwl_power_legacy_set_cam_mode(mvm); | ||
473 | if (ret) | ||
474 | goto error; | ||
475 | } | ||
476 | |||
477 | ret = iwl_mvm_power_update_device(mvm); | 467 | ret = iwl_mvm_power_update_device(mvm); |
478 | if (ret) | 468 | if (ret) |
479 | goto error; | 469 | goto error; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 9ccec10bba16..7110ec2605d6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -667,12 +667,9 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, | |||
667 | if (vif->bss_conf.qos) | 667 | if (vif->bss_conf.qos) |
668 | cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA); | 668 | cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA); |
669 | 669 | ||
670 | /* Don't use cts to self as the fw doesn't support it currently. */ | ||
671 | if (vif->bss_conf.use_cts_prot) { | 670 | if (vif->bss_conf.use_cts_prot) { |
672 | cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT); | 671 | cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT); |
673 | if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8) | 672 | cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_SELF_CTS_EN); |
674 | cmd->protection_flags |= | ||
675 | cpu_to_le32(MAC_PROT_FLG_SELF_CTS_EN); | ||
676 | } | 673 | } |
677 | IWL_DEBUG_RATE(mvm, "use_cts_prot %d, ht_operation_mode %d\n", | 674 | IWL_DEBUG_RATE(mvm, "use_cts_prot %d, ht_operation_mode %d\n", |
678 | vif->bss_conf.use_cts_prot, | 675 | vif->bss_conf.use_cts_prot, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index f0cebf12c7b8..97c3deae6552 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -276,6 +276,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
276 | IEEE80211_HW_AMPDU_AGGREGATION | | 276 | IEEE80211_HW_AMPDU_AGGREGATION | |
277 | IEEE80211_HW_TIMING_BEACON_ONLY | | 277 | IEEE80211_HW_TIMING_BEACON_ONLY | |
278 | IEEE80211_HW_CONNECTION_MONITOR | | 278 | IEEE80211_HW_CONNECTION_MONITOR | |
279 | IEEE80211_HW_SUPPORTS_UAPSD | | ||
279 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 280 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
280 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | 281 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; |
281 | 282 | ||
@@ -285,6 +286,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
285 | IEEE80211_RADIOTAP_MCS_HAVE_STBC; | 286 | IEEE80211_RADIOTAP_MCS_HAVE_STBC; |
286 | hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC; | 287 | hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC; |
287 | hw->rate_control_algorithm = "iwl-mvm-rs"; | 288 | hw->rate_control_algorithm = "iwl-mvm-rs"; |
289 | hw->uapsd_queues = IWL_UAPSD_AC_INFO; | ||
290 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; | ||
288 | 291 | ||
289 | /* | 292 | /* |
290 | * Enable 11w if advertised by firmware and software crypto | 293 | * Enable 11w if advertised by firmware and software crypto |
@@ -295,11 +298,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
295 | !iwlwifi_mod_params.sw_crypto) | 298 | !iwlwifi_mod_params.sw_crypto) |
296 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; | 299 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; |
297 | 300 | ||
298 | if (0 && mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT) { | 301 | /* Disable uAPSD due to firmware issues */ |
299 | hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD; | 302 | if (true) |
300 | hw->uapsd_queues = IWL_UAPSD_AC_INFO; | 303 | hw->flags &= ~IEEE80211_HW_SUPPORTS_UAPSD; |
301 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; | ||
302 | } | ||
303 | 304 | ||
304 | hw->sta_data_size = sizeof(struct iwl_mvm_sta); | 305 | hw->sta_data_size = sizeof(struct iwl_mvm_sta); |
305 | hw->vif_data_size = sizeof(struct iwl_mvm_vif); | 306 | hw->vif_data_size = sizeof(struct iwl_mvm_vif); |
@@ -309,11 +310,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
309 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | 310 | BIT(NL80211_IFTYPE_P2P_CLIENT) | |
310 | BIT(NL80211_IFTYPE_AP) | | 311 | BIT(NL80211_IFTYPE_AP) | |
311 | BIT(NL80211_IFTYPE_P2P_GO) | | 312 | BIT(NL80211_IFTYPE_P2P_GO) | |
312 | BIT(NL80211_IFTYPE_P2P_DEVICE); | 313 | BIT(NL80211_IFTYPE_P2P_DEVICE) | |
313 | 314 | BIT(NL80211_IFTYPE_ADHOC); | |
314 | /* IBSS has bugs in older versions */ | ||
315 | if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8) | ||
316 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); | ||
317 | 315 | ||
318 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 316 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
319 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | | 317 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | |
@@ -365,14 +363,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
365 | else | 363 | else |
366 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 364 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
367 | 365 | ||
368 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) { | 366 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; |
369 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | 367 | hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX; |
370 | hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX; | 368 | hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES; |
371 | hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES; | 369 | /* we create the 802.11 header and zero length SSID IE. */ |
372 | /* we create the 802.11 header and zero length SSID IE. */ | 370 | hw->wiphy->max_sched_scan_ie_len = SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2; |
373 | hw->wiphy->max_sched_scan_ie_len = | ||
374 | SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2; | ||
375 | } | ||
376 | 371 | ||
377 | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | | 372 | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | |
378 | NL80211_FEATURE_P2P_GO_OPPPS; | 373 | NL80211_FEATURE_P2P_GO_OPPPS; |
@@ -386,7 +381,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
386 | } | 381 | } |
387 | 382 | ||
388 | #ifdef CONFIG_PM_SLEEP | 383 | #ifdef CONFIG_PM_SLEEP |
389 | if (mvm->fw->img[IWL_UCODE_WOWLAN].sec[0].len && | 384 | if (iwl_mvm_is_d0i3_supported(mvm) && |
385 | device_can_wakeup(mvm->trans->dev)) { | ||
386 | mvm->wowlan.flags = WIPHY_WOWLAN_ANY; | ||
387 | hw->wiphy->wowlan = &mvm->wowlan; | ||
388 | } else if (mvm->fw->img[IWL_UCODE_WOWLAN].sec[0].len && | ||
390 | mvm->trans->ops->d3_suspend && | 389 | mvm->trans->ops->d3_suspend && |
391 | mvm->trans->ops->d3_resume && | 390 | mvm->trans->ops->d3_resume && |
392 | device_can_wakeup(mvm->trans->dev)) { | 391 | device_can_wakeup(mvm->trans->dev)) { |
@@ -827,8 +826,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
827 | goto out_remove_mac; | 826 | goto out_remove_mac; |
828 | 827 | ||
829 | if (!mvm->bf_allowed_vif && | 828 | if (!mvm->bf_allowed_vif && |
830 | vif->type == NL80211_IFTYPE_STATION && !vif->p2p && | 829 | vif->type == NL80211_IFTYPE_STATION && !vif->p2p) { |
831 | mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED){ | ||
832 | mvm->bf_allowed_vif = mvmvif; | 830 | mvm->bf_allowed_vif = mvmvif; |
833 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | | 831 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | |
834 | IEEE80211_VIF_SUPPORTS_CQM_RSSI; | 832 | IEEE80211_VIF_SUPPORTS_CQM_RSSI; |
@@ -1223,6 +1221,10 @@ static int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm, | |||
1223 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING)) | 1221 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING)) |
1224 | return 0; | 1222 | return 0; |
1225 | 1223 | ||
1224 | /* bcast filtering isn't supported for P2P client */ | ||
1225 | if (vif->p2p) | ||
1226 | return 0; | ||
1227 | |||
1226 | if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) | 1228 | if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) |
1227 | return 0; | 1229 | return 0; |
1228 | 1230 | ||
@@ -1697,6 +1699,11 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | |||
1697 | ret = iwl_mvm_add_sta(mvm, vif, sta); | 1699 | ret = iwl_mvm_add_sta(mvm, vif, sta); |
1698 | } else if (old_state == IEEE80211_STA_NONE && | 1700 | } else if (old_state == IEEE80211_STA_NONE && |
1699 | new_state == IEEE80211_STA_AUTH) { | 1701 | new_state == IEEE80211_STA_AUTH) { |
1702 | /* | ||
1703 | * EBS may be disabled due to previous failures reported by FW. | ||
1704 | * Reset EBS status here assuming environment has been changed. | ||
1705 | */ | ||
1706 | mvm->last_ebs_successful = true; | ||
1700 | ret = 0; | 1707 | ret = 0; |
1701 | } else if (old_state == IEEE80211_STA_AUTH && | 1708 | } else if (old_state == IEEE80211_STA_AUTH && |
1702 | new_state == IEEE80211_STA_ASSOC) { | 1709 | new_state == IEEE80211_STA_ASSOC) { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index d564233a65da..17c42da5f9f2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -164,7 +164,6 @@ enum iwl_dbgfs_pm_mask { | |||
164 | MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS = BIT(2), | 164 | MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS = BIT(2), |
165 | MVM_DEBUGFS_PM_RX_DATA_TIMEOUT = BIT(3), | 165 | MVM_DEBUGFS_PM_RX_DATA_TIMEOUT = BIT(3), |
166 | MVM_DEBUGFS_PM_TX_DATA_TIMEOUT = BIT(4), | 166 | MVM_DEBUGFS_PM_TX_DATA_TIMEOUT = BIT(4), |
167 | MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5), | ||
168 | MVM_DEBUGFS_PM_LPRX_ENA = BIT(6), | 167 | MVM_DEBUGFS_PM_LPRX_ENA = BIT(6), |
169 | MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7), | 168 | MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7), |
170 | MVM_DEBUGFS_PM_SNOOZE_ENABLE = BIT(8), | 169 | MVM_DEBUGFS_PM_SNOOZE_ENABLE = BIT(8), |
@@ -177,7 +176,6 @@ struct iwl_dbgfs_pm { | |||
177 | u32 tx_data_timeout; | 176 | u32 tx_data_timeout; |
178 | bool skip_over_dtim; | 177 | bool skip_over_dtim; |
179 | u8 skip_dtim_periods; | 178 | u8 skip_dtim_periods; |
180 | bool disable_power_off; | ||
181 | bool lprx_ena; | 179 | bool lprx_ena; |
182 | u32 lprx_rssi_threshold; | 180 | u32 lprx_rssi_threshold; |
183 | bool snooze_ena; | 181 | bool snooze_ena; |
@@ -232,6 +230,7 @@ enum iwl_mvm_ref_type { | |||
232 | IWL_MVM_REF_USER, | 230 | IWL_MVM_REF_USER, |
233 | IWL_MVM_REF_TX, | 231 | IWL_MVM_REF_TX, |
234 | IWL_MVM_REF_TX_AGG, | 232 | IWL_MVM_REF_TX_AGG, |
233 | IWL_MVM_REF_EXIT_WORK, | ||
235 | 234 | ||
236 | IWL_MVM_REF_COUNT, | 235 | IWL_MVM_REF_COUNT, |
237 | }; | 236 | }; |
@@ -265,6 +264,7 @@ struct iwl_mvm_vif_bf_data { | |||
265 | * @uploaded: indicates the MAC context has been added to the device | 264 | * @uploaded: indicates the MAC context has been added to the device |
266 | * @ap_ibss_active: indicates that AP/IBSS is configured and that the interface | 265 | * @ap_ibss_active: indicates that AP/IBSS is configured and that the interface |
267 | * should get quota etc. | 266 | * should get quota etc. |
267 | * @pm_enabled - Indicate if MAC power management is allowed | ||
268 | * @monitor_active: indicates that monitor context is configured, and that the | 268 | * @monitor_active: indicates that monitor context is configured, and that the |
269 | * interface should get quota etc. | 269 | * interface should get quota etc. |
270 | * @low_latency: indicates that this interface is in low-latency mode | 270 | * @low_latency: indicates that this interface is in low-latency mode |
@@ -283,6 +283,7 @@ struct iwl_mvm_vif { | |||
283 | 283 | ||
284 | bool uploaded; | 284 | bool uploaded; |
285 | bool ap_ibss_active; | 285 | bool ap_ibss_active; |
286 | bool pm_enabled; | ||
286 | bool monitor_active; | 287 | bool monitor_active; |
287 | bool low_latency; | 288 | bool low_latency; |
288 | struct iwl_mvm_vif_bf_data bf_data; | 289 | struct iwl_mvm_vif_bf_data bf_data; |
@@ -451,6 +452,11 @@ struct iwl_mvm_frame_stats { | |||
451 | int last_frame_idx; | 452 | int last_frame_idx; |
452 | }; | 453 | }; |
453 | 454 | ||
455 | enum { | ||
456 | D0I3_DEFER_WAKEUP, | ||
457 | D0I3_PENDING_WAKEUP, | ||
458 | }; | ||
459 | |||
454 | struct iwl_mvm { | 460 | struct iwl_mvm { |
455 | /* for logger access */ | 461 | /* for logger access */ |
456 | struct device *dev; | 462 | struct device *dev; |
@@ -535,6 +541,8 @@ struct iwl_mvm { | |||
535 | /* Internal station */ | 541 | /* Internal station */ |
536 | struct iwl_mvm_int_sta aux_sta; | 542 | struct iwl_mvm_int_sta aux_sta; |
537 | 543 | ||
544 | bool last_ebs_successful; | ||
545 | |||
538 | u8 scan_last_antenna_idx; /* to toggle TX between antennas */ | 546 | u8 scan_last_antenna_idx; /* to toggle TX between antennas */ |
539 | u8 mgmt_last_antenna_idx; | 547 | u8 mgmt_last_antenna_idx; |
540 | 548 | ||
@@ -578,6 +586,8 @@ struct iwl_mvm { | |||
578 | void *fw_error_dump; | 586 | void *fw_error_dump; |
579 | void *fw_error_sram; | 587 | void *fw_error_sram; |
580 | u32 fw_error_sram_len; | 588 | u32 fw_error_sram_len; |
589 | u32 *fw_error_rxf; | ||
590 | u32 fw_error_rxf_len; | ||
581 | 591 | ||
582 | struct led_classdev led; | 592 | struct led_classdev led; |
583 | 593 | ||
@@ -601,6 +611,9 @@ struct iwl_mvm { | |||
601 | bool d0i3_offloading; | 611 | bool d0i3_offloading; |
602 | struct work_struct d0i3_exit_work; | 612 | struct work_struct d0i3_exit_work; |
603 | struct sk_buff_head d0i3_tx; | 613 | struct sk_buff_head d0i3_tx; |
614 | /* protect d0i3_suspend_flags */ | ||
615 | struct mutex d0i3_suspend_mutex; | ||
616 | unsigned long d0i3_suspend_flags; | ||
604 | /* sync d0i3_tx queue and IWL_MVM_STATUS_IN_D0I3 status flag */ | 617 | /* sync d0i3_tx queue and IWL_MVM_STATUS_IN_D0I3 status flag */ |
605 | spinlock_t d0i3_tx_lock; | 618 | spinlock_t d0i3_tx_lock; |
606 | wait_queue_head_t d0i3_exit_waitq; | 619 | wait_queue_head_t d0i3_exit_waitq; |
@@ -629,8 +642,6 @@ struct iwl_mvm { | |||
629 | 642 | ||
630 | /* Indicate if device power save is allowed */ | 643 | /* Indicate if device power save is allowed */ |
631 | bool ps_disabled; | 644 | bool ps_disabled; |
632 | /* Indicate if device power management is allowed */ | ||
633 | bool pm_disabled; | ||
634 | }; | 645 | }; |
635 | 646 | ||
636 | /* Extract MVM priv from op_mode and _hw */ | 647 | /* Extract MVM priv from op_mode and _hw */ |
@@ -705,6 +716,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); | |||
705 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 716 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
706 | void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm); | 717 | void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm); |
707 | void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm); | 718 | void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm); |
719 | void iwl_mvm_fw_error_rxf_dump(struct iwl_mvm *mvm); | ||
708 | #endif | 720 | #endif |
709 | u8 first_antenna(u8 mask); | 721 | u8 first_antenna(u8 mask); |
710 | u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx); | 722 | u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx); |
@@ -874,8 +886,6 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, | |||
874 | int rs_pretty_print_rate(char *buf, const u32 rate); | 886 | int rs_pretty_print_rate(char *buf, const u32 rate); |
875 | 887 | ||
876 | /* power management */ | 888 | /* power management */ |
877 | int iwl_power_legacy_set_cam_mode(struct iwl_mvm *mvm); | ||
878 | |||
879 | int iwl_mvm_power_update_device(struct iwl_mvm *mvm); | 889 | int iwl_mvm_power_update_device(struct iwl_mvm *mvm); |
880 | int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 890 | int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
881 | int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 891 | int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
@@ -922,9 +932,9 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, | |||
922 | void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); | 932 | void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); |
923 | void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); | 933 | void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type); |
924 | void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq); | 934 | void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq); |
935 | int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm); | ||
925 | 936 | ||
926 | /* BT Coex */ | 937 | /* BT Coex */ |
927 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm); | ||
928 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm); | 938 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm); |
929 | int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | 939 | int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, |
930 | struct iwl_rx_cmd_buffer *rxb, | 940 | struct iwl_rx_cmd_buffer *rxb, |
@@ -936,6 +946,8 @@ u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm, | |||
936 | struct ieee80211_sta *sta); | 946 | struct ieee80211_sta *sta); |
937 | bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, | 947 | bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, |
938 | struct ieee80211_sta *sta); | 948 | struct ieee80211_sta *sta); |
949 | bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm, | ||
950 | enum ieee80211_band band); | ||
939 | u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, | 951 | u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, |
940 | struct ieee80211_tx_info *info, u8 ac); | 952 | struct ieee80211_tx_info *info, u8 ac); |
941 | int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable); | 953 | int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 9545d7fdd4bf..7a5a8bac5fd0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -402,6 +402,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
402 | mvm->sf_state = SF_UNINIT; | 402 | mvm->sf_state = SF_UNINIT; |
403 | 403 | ||
404 | mutex_init(&mvm->mutex); | 404 | mutex_init(&mvm->mutex); |
405 | mutex_init(&mvm->d0i3_suspend_mutex); | ||
405 | spin_lock_init(&mvm->async_handlers_lock); | 406 | spin_lock_init(&mvm->async_handlers_lock); |
406 | INIT_LIST_HEAD(&mvm->time_event_list); | 407 | INIT_LIST_HEAD(&mvm->time_event_list); |
407 | INIT_LIST_HEAD(&mvm->async_handlers_list); | 408 | INIT_LIST_HEAD(&mvm->async_handlers_list); |
@@ -538,6 +539,7 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
538 | kfree(mvm->scan_cmd); | 539 | kfree(mvm->scan_cmd); |
539 | vfree(mvm->fw_error_dump); | 540 | vfree(mvm->fw_error_dump); |
540 | kfree(mvm->fw_error_sram); | 541 | kfree(mvm->fw_error_sram); |
542 | kfree(mvm->fw_error_rxf); | ||
541 | kfree(mvm->mcast_filter_cmd); | 543 | kfree(mvm->mcast_filter_cmd); |
542 | mvm->mcast_filter_cmd = NULL; | 544 | mvm->mcast_filter_cmd = NULL; |
543 | 545 | ||
@@ -821,8 +823,9 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
821 | return; | 823 | return; |
822 | 824 | ||
823 | file_len = mvm->fw_error_sram_len + | 825 | file_len = mvm->fw_error_sram_len + |
826 | mvm->fw_error_rxf_len + | ||
824 | sizeof(*dump_file) + | 827 | sizeof(*dump_file) + |
825 | sizeof(*dump_data); | 828 | sizeof(*dump_data) * 2; |
826 | 829 | ||
827 | dump_file = vmalloc(file_len); | 830 | dump_file = vmalloc(file_len); |
828 | if (!dump_file) | 831 | if (!dump_file) |
@@ -833,7 +836,12 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
833 | dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER); | 836 | dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER); |
834 | dump_file->file_len = cpu_to_le32(file_len); | 837 | dump_file->file_len = cpu_to_le32(file_len); |
835 | dump_data = (void *)dump_file->data; | 838 | dump_data = (void *)dump_file->data; |
836 | dump_data->type = IWL_FW_ERROR_DUMP_SRAM; | 839 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF); |
840 | dump_data->len = cpu_to_le32(mvm->fw_error_rxf_len); | ||
841 | memcpy(dump_data->data, mvm->fw_error_rxf, mvm->fw_error_rxf_len); | ||
842 | |||
843 | dump_data = (void *)((u8 *)dump_data->data + mvm->fw_error_rxf_len); | ||
844 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM); | ||
837 | dump_data->len = cpu_to_le32(mvm->fw_error_sram_len); | 845 | dump_data->len = cpu_to_le32(mvm->fw_error_sram_len); |
838 | 846 | ||
839 | /* | 847 | /* |
@@ -842,6 +850,14 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
842 | * mvm->fw_error_sram right now. | 850 | * mvm->fw_error_sram right now. |
843 | */ | 851 | */ |
844 | memcpy(dump_data->data, mvm->fw_error_sram, mvm->fw_error_sram_len); | 852 | memcpy(dump_data->data, mvm->fw_error_sram, mvm->fw_error_sram_len); |
853 | |||
854 | kfree(mvm->fw_error_rxf); | ||
855 | mvm->fw_error_rxf = NULL; | ||
856 | mvm->fw_error_rxf_len = 0; | ||
857 | |||
858 | kfree(mvm->fw_error_sram); | ||
859 | mvm->fw_error_sram = NULL; | ||
860 | mvm->fw_error_sram_len = 0; | ||
845 | } | 861 | } |
846 | #endif | 862 | #endif |
847 | 863 | ||
@@ -853,6 +869,7 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) | |||
853 | 869 | ||
854 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 870 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
855 | iwl_mvm_fw_error_sram_dump(mvm); | 871 | iwl_mvm_fw_error_sram_dump(mvm); |
872 | iwl_mvm_fw_error_rxf_dump(mvm); | ||
856 | #endif | 873 | #endif |
857 | 874 | ||
858 | iwl_mvm_nic_restart(mvm); | 875 | iwl_mvm_nic_restart(mvm); |
@@ -1128,7 +1145,7 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) | |||
1128 | .id = WOWLAN_GET_STATUSES, | 1145 | .id = WOWLAN_GET_STATUSES, |
1129 | .flags = CMD_SYNC | CMD_HIGH_PRIO | CMD_WANT_SKB, | 1146 | .flags = CMD_SYNC | CMD_HIGH_PRIO | CMD_WANT_SKB, |
1130 | }; | 1147 | }; |
1131 | struct iwl_wowlan_status_v6 *status; | 1148 | struct iwl_wowlan_status *status; |
1132 | int ret; | 1149 | int ret; |
1133 | u32 disconnection_reasons, wakeup_reasons; | 1150 | u32 disconnection_reasons, wakeup_reasons; |
1134 | __le16 *qos_seq = NULL; | 1151 | __le16 *qos_seq = NULL; |
@@ -1158,18 +1175,27 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) | |||
1158 | iwl_free_resp(&get_status_cmd); | 1175 | iwl_free_resp(&get_status_cmd); |
1159 | out: | 1176 | out: |
1160 | iwl_mvm_d0i3_enable_tx(mvm, qos_seq); | 1177 | iwl_mvm_d0i3_enable_tx(mvm, qos_seq); |
1178 | iwl_mvm_unref(mvm, IWL_MVM_REF_EXIT_WORK); | ||
1161 | mutex_unlock(&mvm->mutex); | 1179 | mutex_unlock(&mvm->mutex); |
1162 | } | 1180 | } |
1163 | 1181 | ||
1164 | static int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode) | 1182 | int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm) |
1165 | { | 1183 | { |
1166 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
1167 | u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE | | 1184 | u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE | |
1168 | CMD_WAKE_UP_TRANS; | 1185 | CMD_WAKE_UP_TRANS; |
1169 | int ret; | 1186 | int ret; |
1170 | 1187 | ||
1171 | IWL_DEBUG_RPM(mvm, "MVM exiting D0i3\n"); | 1188 | IWL_DEBUG_RPM(mvm, "MVM exiting D0i3\n"); |
1172 | 1189 | ||
1190 | mutex_lock(&mvm->d0i3_suspend_mutex); | ||
1191 | if (test_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags)) { | ||
1192 | IWL_DEBUG_RPM(mvm, "Deferring d0i3 exit until resume\n"); | ||
1193 | __set_bit(D0I3_PENDING_WAKEUP, &mvm->d0i3_suspend_flags); | ||
1194 | mutex_unlock(&mvm->d0i3_suspend_mutex); | ||
1195 | return 0; | ||
1196 | } | ||
1197 | mutex_unlock(&mvm->d0i3_suspend_mutex); | ||
1198 | |||
1173 | ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, flags, 0, NULL); | 1199 | ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, flags, 0, NULL); |
1174 | if (ret) | 1200 | if (ret) |
1175 | goto out; | 1201 | goto out; |
@@ -1183,6 +1209,25 @@ out: | |||
1183 | return ret; | 1209 | return ret; |
1184 | } | 1210 | } |
1185 | 1211 | ||
1212 | static int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode) | ||
1213 | { | ||
1214 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
1215 | |||
1216 | iwl_mvm_ref(mvm, IWL_MVM_REF_EXIT_WORK); | ||
1217 | return _iwl_mvm_exit_d0i3(mvm); | ||
1218 | } | ||
1219 | |||
1220 | static void iwl_mvm_napi_add(struct iwl_op_mode *op_mode, | ||
1221 | struct napi_struct *napi, | ||
1222 | struct net_device *napi_dev, | ||
1223 | int (*poll)(struct napi_struct *, int), | ||
1224 | int weight) | ||
1225 | { | ||
1226 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
1227 | |||
1228 | ieee80211_napi_add(mvm->hw, napi, napi_dev, poll, weight); | ||
1229 | } | ||
1230 | |||
1186 | static const struct iwl_op_mode_ops iwl_mvm_ops = { | 1231 | static const struct iwl_op_mode_ops iwl_mvm_ops = { |
1187 | .start = iwl_op_mode_mvm_start, | 1232 | .start = iwl_op_mode_mvm_start, |
1188 | .stop = iwl_op_mode_mvm_stop, | 1233 | .stop = iwl_op_mode_mvm_stop, |
@@ -1196,4 +1241,5 @@ static const struct iwl_op_mode_ops iwl_mvm_ops = { | |||
1196 | .nic_config = iwl_mvm_nic_config, | 1241 | .nic_config = iwl_mvm_nic_config, |
1197 | .enter_d0i3 = iwl_mvm_enter_d0i3, | 1242 | .enter_d0i3 = iwl_mvm_enter_d0i3, |
1198 | .exit_d0i3 = iwl_mvm_exit_d0i3, | 1243 | .exit_d0i3 = iwl_mvm_exit_d0i3, |
1244 | .napi_add = iwl_mvm_napi_add, | ||
1199 | }; | 1245 | }; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 6b636eab3339..78309f7d0b7b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -268,6 +268,30 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm, | |||
268 | IWL_MVM_PS_HEAVY_RX_THLD_PERCENT; | 268 | IWL_MVM_PS_HEAVY_RX_THLD_PERCENT; |
269 | } | 269 | } |
270 | 270 | ||
271 | static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, | ||
272 | struct ieee80211_vif *vif) | ||
273 | { | ||
274 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
275 | |||
276 | if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid, | ||
277 | ETH_ALEN)) | ||
278 | return false; | ||
279 | |||
280 | if (vif->p2p && | ||
281 | !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD)) | ||
282 | return false; | ||
283 | /* | ||
284 | * Avoid using uAPSD if P2P client is associated to GO that uses | ||
285 | * opportunistic power save. This is due to current FW limitation. | ||
286 | */ | ||
287 | if (vif->p2p && | ||
288 | (vif->bss_conf.p2p_noa_attr.oppps_ctwindow & | ||
289 | IEEE80211_P2P_OPPPS_ENABLE_BIT)) | ||
290 | return false; | ||
291 | |||
292 | return true; | ||
293 | } | ||
294 | |||
271 | static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | 295 | static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, |
272 | struct ieee80211_vif *vif, | 296 | struct ieee80211_vif *vif, |
273 | struct iwl_mac_power_cmd *cmd) | 297 | struct iwl_mac_power_cmd *cmd) |
@@ -280,7 +304,6 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
280 | bool radar_detect = false; | 304 | bool radar_detect = false; |
281 | struct iwl_mvm_vif *mvmvif __maybe_unused = | 305 | struct iwl_mvm_vif *mvmvif __maybe_unused = |
282 | iwl_mvm_vif_from_mac80211(vif); | 306 | iwl_mvm_vif_from_mac80211(vif); |
283 | bool allow_uapsd = true; | ||
284 | 307 | ||
285 | cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, | 308 | cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, |
286 | mvmvif->color)); | 309 | mvmvif->color)); |
@@ -303,13 +326,8 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
303 | 326 | ||
304 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); | 327 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); |
305 | 328 | ||
306 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
307 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF && | ||
308 | mvmvif->dbgfs_pm.disable_power_off) | ||
309 | cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK); | ||
310 | #endif | ||
311 | if (!vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif) || | 329 | if (!vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif) || |
312 | mvm->pm_disabled) | 330 | !mvmvif->pm_enabled) |
313 | return; | 331 | return; |
314 | 332 | ||
315 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); | 333 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); |
@@ -351,23 +369,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
351 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); | 369 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); |
352 | } | 370 | } |
353 | 371 | ||
354 | if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid, | 372 | if (iwl_mvm_power_allow_uapsd(mvm, vif)) |
355 | ETH_ALEN)) | ||
356 | allow_uapsd = false; | ||
357 | |||
358 | if (vif->p2p && | ||
359 | !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD)) | ||
360 | allow_uapsd = false; | ||
361 | /* | ||
362 | * Avoid using uAPSD if P2P client is associated to GO that uses | ||
363 | * opportunistic power save. This is due to current FW limitation. | ||
364 | */ | ||
365 | if (vif->p2p && | ||
366 | vif->bss_conf.p2p_noa_attr.oppps_ctwindow & | ||
367 | IEEE80211_P2P_OPPPS_ENABLE_BIT) | ||
368 | allow_uapsd = false; | ||
369 | |||
370 | if (allow_uapsd) | ||
371 | iwl_mvm_power_configure_uapsd(mvm, vif, cmd); | 373 | iwl_mvm_power_configure_uapsd(mvm, vif, cmd); |
372 | 374 | ||
373 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 375 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
@@ -421,13 +423,6 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm, | |||
421 | { | 423 | { |
422 | struct iwl_mac_power_cmd cmd = {}; | 424 | struct iwl_mac_power_cmd cmd = {}; |
423 | 425 | ||
424 | if (vif->type != NL80211_IFTYPE_STATION) | ||
425 | return 0; | ||
426 | |||
427 | if (vif->p2p && | ||
428 | !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)) | ||
429 | return 0; | ||
430 | |||
431 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | 426 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); |
432 | iwl_mvm_power_log(mvm, &cmd); | 427 | iwl_mvm_power_log(mvm, &cmd); |
433 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 428 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
@@ -444,12 +439,6 @@ int iwl_mvm_power_update_device(struct iwl_mvm *mvm) | |||
444 | .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK), | 439 | .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK), |
445 | }; | 440 | }; |
446 | 441 | ||
447 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) | ||
448 | return 0; | ||
449 | |||
450 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) | ||
451 | return 0; | ||
452 | |||
453 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) | 442 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) |
454 | mvm->ps_disabled = true; | 443 | mvm->ps_disabled = true; |
455 | 444 | ||
@@ -508,86 +497,69 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm, | |||
508 | return 0; | 497 | return 0; |
509 | } | 498 | } |
510 | 499 | ||
511 | struct iwl_power_constraint { | 500 | struct iwl_power_vifs { |
512 | struct ieee80211_vif *bf_vif; | 501 | struct ieee80211_vif *bf_vif; |
513 | struct ieee80211_vif *bss_vif; | 502 | struct ieee80211_vif *bss_vif; |
514 | struct ieee80211_vif *p2p_vif; | 503 | struct ieee80211_vif *p2p_vif; |
515 | u16 bss_phyctx_id; | 504 | struct ieee80211_vif *ap_vif; |
516 | u16 p2p_phyctx_id; | 505 | struct ieee80211_vif *monitor_vif; |
517 | bool pm_disabled; | 506 | bool p2p_active; |
518 | bool ps_disabled; | 507 | bool bss_active; |
519 | struct iwl_mvm *mvm; | 508 | bool ap_active; |
509 | bool monitor_active; | ||
520 | }; | 510 | }; |
521 | 511 | ||
522 | static void iwl_mvm_power_iterator(void *_data, u8 *mac, | 512 | static void iwl_mvm_power_iterator(void *_data, u8 *mac, |
523 | struct ieee80211_vif *vif) | 513 | struct ieee80211_vif *vif) |
524 | { | 514 | { |
525 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 515 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
526 | struct iwl_power_constraint *power_iterator = _data; | 516 | struct iwl_power_vifs *power_iterator = _data; |
527 | struct iwl_mvm *mvm = power_iterator->mvm; | ||
528 | 517 | ||
518 | mvmvif->pm_enabled = false; | ||
529 | switch (ieee80211_vif_type_p2p(vif)) { | 519 | switch (ieee80211_vif_type_p2p(vif)) { |
530 | case NL80211_IFTYPE_P2P_DEVICE: | 520 | case NL80211_IFTYPE_P2P_DEVICE: |
531 | break; | 521 | break; |
532 | 522 | ||
533 | case NL80211_IFTYPE_P2P_GO: | 523 | case NL80211_IFTYPE_P2P_GO: |
534 | case NL80211_IFTYPE_AP: | 524 | case NL80211_IFTYPE_AP: |
535 | /* no BSS power mgmt if we have an active AP */ | 525 | /* only a single MAC of the same type */ |
536 | if (mvmvif->ap_ibss_active) | 526 | WARN_ON(power_iterator->ap_vif); |
537 | power_iterator->pm_disabled = true; | 527 | power_iterator->ap_vif = vif; |
528 | if (mvmvif->phy_ctxt) | ||
529 | if (mvmvif->phy_ctxt->id < MAX_PHYS) | ||
530 | power_iterator->ap_active = true; | ||
538 | break; | 531 | break; |
539 | 532 | ||
540 | case NL80211_IFTYPE_MONITOR: | 533 | case NL80211_IFTYPE_MONITOR: |
541 | /* no BSS power mgmt and no device power save */ | 534 | /* only a single MAC of the same type */ |
542 | power_iterator->pm_disabled = true; | 535 | WARN_ON(power_iterator->monitor_vif); |
543 | power_iterator->ps_disabled = true; | 536 | power_iterator->monitor_vif = vif; |
537 | if (mvmvif->phy_ctxt) | ||
538 | if (mvmvif->phy_ctxt->id < MAX_PHYS) | ||
539 | power_iterator->monitor_active = true; | ||
544 | break; | 540 | break; |
545 | 541 | ||
546 | case NL80211_IFTYPE_P2P_CLIENT: | 542 | case NL80211_IFTYPE_P2P_CLIENT: |
547 | if (mvmvif->phy_ctxt) | 543 | /* only a single MAC of the same type */ |
548 | power_iterator->p2p_phyctx_id = mvmvif->phy_ctxt->id; | ||
549 | |||
550 | /* we should have only one P2P vif */ | ||
551 | WARN_ON(power_iterator->p2p_vif); | 544 | WARN_ON(power_iterator->p2p_vif); |
552 | power_iterator->p2p_vif = vif; | 545 | power_iterator->p2p_vif = vif; |
553 | 546 | if (mvmvif->phy_ctxt) | |
554 | IWL_DEBUG_POWER(mvm, "p2p: p2p_id=%d, bss_id=%d\n", | 547 | if (mvmvif->phy_ctxt->id < MAX_PHYS) |
555 | power_iterator->p2p_phyctx_id, | 548 | power_iterator->p2p_active = true; |
556 | power_iterator->bss_phyctx_id); | ||
557 | if (!(mvm->fw->ucode_capa.flags & | ||
558 | IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)) { | ||
559 | /* no BSS power mgmt if we have a P2P client*/ | ||
560 | power_iterator->pm_disabled = true; | ||
561 | } else if (power_iterator->p2p_phyctx_id < MAX_PHYS && | ||
562 | power_iterator->bss_phyctx_id < MAX_PHYS && | ||
563 | power_iterator->p2p_phyctx_id == | ||
564 | power_iterator->bss_phyctx_id) { | ||
565 | power_iterator->pm_disabled = true; | ||
566 | } | ||
567 | break; | 549 | break; |
568 | 550 | ||
569 | case NL80211_IFTYPE_STATION: | 551 | case NL80211_IFTYPE_STATION: |
570 | if (mvmvif->phy_ctxt) | 552 | /* only a single MAC of the same type */ |
571 | power_iterator->bss_phyctx_id = mvmvif->phy_ctxt->id; | ||
572 | |||
573 | /* we should have only one BSS vif */ | ||
574 | WARN_ON(power_iterator->bss_vif); | 553 | WARN_ON(power_iterator->bss_vif); |
575 | power_iterator->bss_vif = vif; | 554 | power_iterator->bss_vif = vif; |
555 | if (mvmvif->phy_ctxt) | ||
556 | if (mvmvif->phy_ctxt->id < MAX_PHYS) | ||
557 | power_iterator->bss_active = true; | ||
576 | 558 | ||
577 | if (mvmvif->bf_data.bf_enabled && | 559 | if (mvmvif->bf_data.bf_enabled && |
578 | !WARN_ON(power_iterator->bf_vif)) | 560 | !WARN_ON(power_iterator->bf_vif)) |
579 | power_iterator->bf_vif = vif; | 561 | power_iterator->bf_vif = vif; |
580 | 562 | ||
581 | IWL_DEBUG_POWER(mvm, "bss: p2p_id=%d, bss_id=%d\n", | ||
582 | power_iterator->p2p_phyctx_id, | ||
583 | power_iterator->bss_phyctx_id); | ||
584 | if (mvm->fw->ucode_capa.flags & | ||
585 | IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM && | ||
586 | (power_iterator->p2p_phyctx_id < MAX_PHYS && | ||
587 | power_iterator->bss_phyctx_id < MAX_PHYS && | ||
588 | power_iterator->p2p_phyctx_id == | ||
589 | power_iterator->bss_phyctx_id)) | ||
590 | power_iterator->pm_disabled = true; | ||
591 | break; | 563 | break; |
592 | 564 | ||
593 | default: | 565 | default: |
@@ -596,70 +568,118 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac, | |||
596 | } | 568 | } |
597 | 569 | ||
598 | static void | 570 | static void |
599 | iwl_mvm_power_get_global_constraint(struct iwl_mvm *mvm, | 571 | iwl_mvm_power_set_pm(struct iwl_mvm *mvm, |
600 | struct iwl_power_constraint *constraint) | 572 | struct iwl_power_vifs *vifs) |
601 | { | 573 | { |
602 | lockdep_assert_held(&mvm->mutex); | 574 | struct iwl_mvm_vif *bss_mvmvif = NULL; |
575 | struct iwl_mvm_vif *p2p_mvmvif = NULL; | ||
576 | struct iwl_mvm_vif *ap_mvmvif = NULL; | ||
577 | bool client_same_channel = false; | ||
578 | bool ap_same_channel = false; | ||
603 | 579 | ||
604 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) { | 580 | lockdep_assert_held(&mvm->mutex); |
605 | constraint->pm_disabled = true; | ||
606 | constraint->ps_disabled = true; | ||
607 | } | ||
608 | 581 | ||
582 | /* get vifs info + set pm_enable to false */ | ||
609 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | 583 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, |
610 | IEEE80211_IFACE_ITER_NORMAL, | 584 | IEEE80211_IFACE_ITER_NORMAL, |
611 | iwl_mvm_power_iterator, constraint); | 585 | iwl_mvm_power_iterator, vifs); |
586 | |||
587 | if (vifs->bss_vif) | ||
588 | bss_mvmvif = iwl_mvm_vif_from_mac80211(vifs->bss_vif); | ||
589 | |||
590 | if (vifs->p2p_vif) | ||
591 | p2p_mvmvif = iwl_mvm_vif_from_mac80211(vifs->p2p_vif); | ||
592 | |||
593 | if (vifs->ap_vif) | ||
594 | ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif); | ||
595 | |||
596 | /* enable PM on bss if bss stand alone */ | ||
597 | if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) { | ||
598 | bss_mvmvif->pm_enabled = true; | ||
599 | return; | ||
600 | } | ||
601 | |||
602 | /* enable PM on p2p if p2p stand alone */ | ||
603 | if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active) { | ||
604 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM) | ||
605 | p2p_mvmvif->pm_enabled = true; | ||
606 | return; | ||
607 | } | ||
608 | |||
609 | if (vifs->bss_active && vifs->p2p_active) | ||
610 | client_same_channel = (bss_mvmvif->phy_ctxt->id == | ||
611 | p2p_mvmvif->phy_ctxt->id); | ||
612 | if (vifs->bss_active && vifs->ap_active) | ||
613 | ap_same_channel = (bss_mvmvif->phy_ctxt->id == | ||
614 | ap_mvmvif->phy_ctxt->id); | ||
615 | |||
616 | /* bss is not stand alone: enable PM if alone on its channel */ | ||
617 | if (vifs->bss_active && !(client_same_channel || ap_same_channel) && | ||
618 | (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)) { | ||
619 | bss_mvmvif->pm_enabled = true; | ||
620 | return; | ||
621 | } | ||
622 | |||
623 | /* | ||
624 | * There is only one channel in the system and there are only | ||
625 | * bss and p2p clients that share it | ||
626 | */ | ||
627 | if (client_same_channel && !vifs->ap_active && | ||
628 | (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM)) { | ||
629 | /* share same channel*/ | ||
630 | bss_mvmvif->pm_enabled = true; | ||
631 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM) | ||
632 | p2p_mvmvif->pm_enabled = true; | ||
633 | } | ||
612 | } | 634 | } |
613 | 635 | ||
614 | int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 636 | int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
615 | { | 637 | { |
616 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 638 | struct iwl_mvm_vif *mvmvif; |
617 | struct iwl_power_constraint constraint = { | 639 | struct iwl_power_vifs vifs = {}; |
618 | .p2p_phyctx_id = MAX_PHYS, | ||
619 | .bss_phyctx_id = MAX_PHYS, | ||
620 | .mvm = mvm, | ||
621 | }; | ||
622 | bool ba_enable; | 640 | bool ba_enable; |
623 | int ret; | 641 | int ret; |
624 | 642 | ||
625 | lockdep_assert_held(&mvm->mutex); | 643 | lockdep_assert_held(&mvm->mutex); |
626 | 644 | ||
627 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) | 645 | iwl_mvm_power_set_pm(mvm, &vifs); |
628 | return 0; | ||
629 | |||
630 | iwl_mvm_power_get_global_constraint(mvm, &constraint); | ||
631 | mvm->ps_disabled = constraint.ps_disabled; | ||
632 | mvm->pm_disabled = constraint.pm_disabled; | ||
633 | 646 | ||
647 | /* disable PS if CAM */ | ||
648 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) { | ||
649 | mvm->ps_disabled = true; | ||
650 | } else { | ||
634 | /* don't update device power state unless we add / remove monitor */ | 651 | /* don't update device power state unless we add / remove monitor */ |
635 | if (vif->type == NL80211_IFTYPE_MONITOR) { | 652 | if (vifs.monitor_vif) { |
636 | ret = iwl_mvm_power_update_device(mvm); | 653 | if (vifs.monitor_active) |
637 | if (ret) | 654 | mvm->ps_disabled = true; |
638 | return ret; | 655 | ret = iwl_mvm_power_update_device(mvm); |
656 | if (ret) | ||
657 | return ret; | ||
658 | } | ||
639 | } | 659 | } |
640 | 660 | ||
641 | if (constraint.bss_vif) { | 661 | if (vifs.bss_vif) { |
642 | ret = iwl_mvm_power_send_cmd(mvm, constraint.bss_vif); | 662 | ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif); |
643 | if (ret) | 663 | if (ret) |
644 | return ret; | 664 | return ret; |
645 | } | 665 | } |
646 | 666 | ||
647 | if (constraint.p2p_vif) { | 667 | if (vifs.p2p_vif) { |
648 | ret = iwl_mvm_power_send_cmd(mvm, constraint.p2p_vif); | 668 | ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif); |
649 | if (ret) | 669 | if (ret) |
650 | return ret; | 670 | return ret; |
651 | } | 671 | } |
652 | 672 | ||
653 | if (!constraint.bf_vif) | 673 | if (!vifs.bf_vif) |
654 | return 0; | 674 | return 0; |
655 | 675 | ||
656 | vif = constraint.bf_vif; | 676 | vif = vifs.bf_vif; |
657 | mvmvif = iwl_mvm_vif_from_mac80211(vif); | 677 | mvmvif = iwl_mvm_vif_from_mac80211(vif); |
658 | 678 | ||
659 | ba_enable = !(constraint.pm_disabled || constraint.ps_disabled || | 679 | ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled || |
660 | !vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif)); | 680 | !vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif)); |
661 | 681 | ||
662 | return iwl_mvm_update_beacon_abort(mvm, constraint.bf_vif, ba_enable); | 682 | return iwl_mvm_update_beacon_abort(mvm, vifs.bf_vif, ba_enable); |
663 | } | 683 | } |
664 | 684 | ||
665 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 685 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
@@ -671,19 +691,10 @@ int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, | |||
671 | struct iwl_mac_power_cmd cmd = {}; | 691 | struct iwl_mac_power_cmd cmd = {}; |
672 | int pos = 0; | 692 | int pos = 0; |
673 | 693 | ||
674 | if (WARN_ON(!(mvm->fw->ucode_capa.flags & | ||
675 | IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT))) | ||
676 | return 0; | ||
677 | |||
678 | mutex_lock(&mvm->mutex); | 694 | mutex_lock(&mvm->mutex); |
679 | memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd)); | 695 | memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd)); |
680 | mutex_unlock(&mvm->mutex); | 696 | mutex_unlock(&mvm->mutex); |
681 | 697 | ||
682 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) | ||
683 | pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n", | ||
684 | (cmd.flags & | ||
685 | cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ? | ||
686 | 0 : 1); | ||
687 | pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", | 698 | pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", |
688 | iwlmvm_mod_params.power_scheme); | 699 | iwlmvm_mod_params.power_scheme); |
689 | pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n", | 700 | pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n", |
@@ -826,8 +837,7 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, | |||
826 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 837 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
827 | int ret; | 838 | int ret; |
828 | 839 | ||
829 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED) || | 840 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) |
830 | vif->type != NL80211_IFTYPE_STATION || vif->p2p) | ||
831 | return 0; | 841 | return 0; |
832 | 842 | ||
833 | ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags); | 843 | ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags); |
@@ -914,13 +924,3 @@ int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm, | |||
914 | 924 | ||
915 | return iwl_mvm_enable_beacon_filter(mvm, vif, flags); | 925 | return iwl_mvm_enable_beacon_filter(mvm, vif, flags); |
916 | } | 926 | } |
917 | |||
918 | int iwl_power_legacy_set_cam_mode(struct iwl_mvm *mvm) | ||
919 | { | ||
920 | struct iwl_powertable_cmd cmd = { | ||
921 | .keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC, | ||
922 | }; | ||
923 | |||
924 | return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, | ||
925 | sizeof(cmd), &cmd); | ||
926 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 9f52c5b3f0ec..d44b2b33b5cc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -527,6 +527,9 @@ static void rs_rate_scale_clear_tbl_windows(struct iwl_mvm *mvm, | |||
527 | IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); | 527 | IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); |
528 | for (i = 0; i < IWL_RATE_COUNT; i++) | 528 | for (i = 0; i < IWL_RATE_COUNT; i++) |
529 | rs_rate_scale_clear_window(&tbl->win[i]); | 529 | rs_rate_scale_clear_window(&tbl->win[i]); |
530 | |||
531 | for (i = 0; i < ARRAY_SIZE(tbl->tpc_win); i++) | ||
532 | rs_rate_scale_clear_window(&tbl->tpc_win[i]); | ||
530 | } | 533 | } |
531 | 534 | ||
532 | static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) | 535 | static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) |
@@ -656,17 +659,34 @@ static int _rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, | |||
656 | return 0; | 659 | return 0; |
657 | } | 660 | } |
658 | 661 | ||
659 | static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, | 662 | static int rs_collect_tx_data(struct iwl_lq_sta *lq_sta, |
660 | int scale_index, int attempts, int successes) | 663 | struct iwl_scale_tbl_info *tbl, |
664 | int scale_index, int attempts, int successes, | ||
665 | u8 reduced_txp) | ||
661 | { | 666 | { |
662 | struct iwl_rate_scale_data *window = NULL; | 667 | struct iwl_rate_scale_data *window = NULL; |
668 | int ret; | ||
663 | 669 | ||
664 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) | 670 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) |
665 | return -EINVAL; | 671 | return -EINVAL; |
666 | 672 | ||
673 | if (tbl->column != RS_COLUMN_INVALID) { | ||
674 | lq_sta->tx_stats[tbl->column][scale_index].total += attempts; | ||
675 | lq_sta->tx_stats[tbl->column][scale_index].success += successes; | ||
676 | } | ||
677 | |||
667 | /* Select window for current tx bit rate */ | 678 | /* Select window for current tx bit rate */ |
668 | window = &(tbl->win[scale_index]); | 679 | window = &(tbl->win[scale_index]); |
669 | 680 | ||
681 | ret = _rs_collect_tx_data(tbl, scale_index, attempts, successes, | ||
682 | window); | ||
683 | if (ret) | ||
684 | return ret; | ||
685 | |||
686 | if (WARN_ON_ONCE(reduced_txp > TPC_MAX_REDUCTION)) | ||
687 | return -EINVAL; | ||
688 | |||
689 | window = &tbl->tpc_win[reduced_txp]; | ||
670 | return _rs_collect_tx_data(tbl, scale_index, attempts, successes, | 690 | return _rs_collect_tx_data(tbl, scale_index, attempts, successes, |
671 | window); | 691 | window); |
672 | } | 692 | } |
@@ -1000,6 +1020,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, | |||
1000 | u32 ucode_rate; | 1020 | u32 ucode_rate; |
1001 | struct rs_rate rate; | 1021 | struct rs_rate rate; |
1002 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; | 1022 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; |
1023 | u8 reduced_txp = (uintptr_t)info->status.status_driver_data[0]; | ||
1003 | 1024 | ||
1004 | /* Treat uninitialized rate scaling data same as non-existing. */ | 1025 | /* Treat uninitialized rate scaling data same as non-existing. */ |
1005 | if (!lq_sta) { | 1026 | if (!lq_sta) { |
@@ -1141,9 +1162,10 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, | |||
1141 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { | 1162 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { |
1142 | ucode_rate = le32_to_cpu(table->rs_table[0]); | 1163 | ucode_rate = le32_to_cpu(table->rs_table[0]); |
1143 | rs_rate_from_ucode_rate(ucode_rate, info->band, &rate); | 1164 | rs_rate_from_ucode_rate(ucode_rate, info->band, &rate); |
1144 | rs_collect_tx_data(curr_tbl, rate.index, | 1165 | rs_collect_tx_data(lq_sta, curr_tbl, rate.index, |
1145 | info->status.ampdu_len, | 1166 | info->status.ampdu_len, |
1146 | info->status.ampdu_ack_len); | 1167 | info->status.ampdu_ack_len, |
1168 | reduced_txp); | ||
1147 | 1169 | ||
1148 | /* Update success/fail counts if not searching for new mode */ | 1170 | /* Update success/fail counts if not searching for new mode */ |
1149 | if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { | 1171 | if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { |
@@ -1176,8 +1198,9 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, | |||
1176 | else | 1198 | else |
1177 | continue; | 1199 | continue; |
1178 | 1200 | ||
1179 | rs_collect_tx_data(tmp_tbl, rate.index, 1, | 1201 | rs_collect_tx_data(lq_sta, tmp_tbl, rate.index, 1, |
1180 | i < retries ? 0 : legacy_success); | 1202 | i < retries ? 0 : legacy_success, |
1203 | reduced_txp); | ||
1181 | } | 1204 | } |
1182 | 1205 | ||
1183 | /* Update success/fail counts if not searching for new mode */ | 1206 | /* Update success/fail counts if not searching for new mode */ |
@@ -1188,6 +1211,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, | |||
1188 | } | 1211 | } |
1189 | /* The last TX rate is cached in lq_sta; it's set in if/else above */ | 1212 | /* The last TX rate is cached in lq_sta; it's set in if/else above */ |
1190 | lq_sta->last_rate_n_flags = ucode_rate; | 1213 | lq_sta->last_rate_n_flags = ucode_rate; |
1214 | IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp); | ||
1191 | done: | 1215 | done: |
1192 | /* See if there's a better rate or modulation mode to try. */ | 1216 | /* See if there's a better rate or modulation mode to try. */ |
1193 | if (sta && sta->supp_rates[sband->band]) | 1217 | if (sta && sta->supp_rates[sband->band]) |
@@ -1769,6 +1793,198 @@ out: | |||
1769 | return action; | 1793 | return action; |
1770 | } | 1794 | } |
1771 | 1795 | ||
1796 | static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index, | ||
1797 | int *weaker, int *stronger) | ||
1798 | { | ||
1799 | *weaker = index + TPC_TX_POWER_STEP; | ||
1800 | if (*weaker > TPC_MAX_REDUCTION) | ||
1801 | *weaker = TPC_INVALID; | ||
1802 | |||
1803 | *stronger = index - TPC_TX_POWER_STEP; | ||
1804 | if (*stronger < 0) | ||
1805 | *stronger = TPC_INVALID; | ||
1806 | } | ||
1807 | |||
1808 | static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct rs_rate *rate, | ||
1809 | enum ieee80211_band band) | ||
1810 | { | ||
1811 | int index = rate->index; | ||
1812 | |||
1813 | /* | ||
1814 | * allow tpc only if power management is enabled, or bt coex | ||
1815 | * activity grade allows it and we are on 2.4Ghz. | ||
1816 | */ | ||
1817 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM && | ||
1818 | !iwl_mvm_bt_coex_is_tpc_allowed(mvm, band)) | ||
1819 | return false; | ||
1820 | |||
1821 | IWL_DEBUG_RATE(mvm, "check rate, table type: %d\n", rate->type); | ||
1822 | if (is_legacy(rate)) | ||
1823 | return index == IWL_RATE_54M_INDEX; | ||
1824 | if (is_ht(rate)) | ||
1825 | return index == IWL_RATE_MCS_7_INDEX; | ||
1826 | if (is_vht(rate)) | ||
1827 | return index == IWL_RATE_MCS_7_INDEX || | ||
1828 | index == IWL_RATE_MCS_8_INDEX || | ||
1829 | index == IWL_RATE_MCS_9_INDEX; | ||
1830 | |||
1831 | WARN_ON_ONCE(1); | ||
1832 | return false; | ||
1833 | } | ||
1834 | |||
1835 | enum tpc_action { | ||
1836 | TPC_ACTION_STAY, | ||
1837 | TPC_ACTION_DECREASE, | ||
1838 | TPC_ACTION_INCREASE, | ||
1839 | TPC_ACTION_NO_RESTIRCTION, | ||
1840 | }; | ||
1841 | |||
1842 | static enum tpc_action rs_get_tpc_action(struct iwl_mvm *mvm, | ||
1843 | s32 sr, int weak, int strong, | ||
1844 | int current_tpt, | ||
1845 | int weak_tpt, int strong_tpt) | ||
1846 | { | ||
1847 | /* stay until we have valid tpt */ | ||
1848 | if (current_tpt == IWL_INVALID_VALUE) { | ||
1849 | IWL_DEBUG_RATE(mvm, "no current tpt. stay.\n"); | ||
1850 | return TPC_ACTION_STAY; | ||
1851 | } | ||
1852 | |||
1853 | /* Too many failures, increase txp */ | ||
1854 | if (sr <= TPC_SR_FORCE_INCREASE || current_tpt == 0) { | ||
1855 | IWL_DEBUG_RATE(mvm, "increase txp because of weak SR\n"); | ||
1856 | return TPC_ACTION_NO_RESTIRCTION; | ||
1857 | } | ||
1858 | |||
1859 | /* try decreasing first if applicable */ | ||
1860 | if (weak != TPC_INVALID) { | ||
1861 | if (weak_tpt == IWL_INVALID_VALUE && | ||
1862 | (strong_tpt == IWL_INVALID_VALUE || | ||
1863 | current_tpt >= strong_tpt)) { | ||
1864 | IWL_DEBUG_RATE(mvm, | ||
1865 | "no weak txp measurement. decrease txp\n"); | ||
1866 | return TPC_ACTION_DECREASE; | ||
1867 | } | ||
1868 | |||
1869 | if (weak_tpt > current_tpt) { | ||
1870 | IWL_DEBUG_RATE(mvm, | ||
1871 | "lower txp has better tpt. decrease txp\n"); | ||
1872 | return TPC_ACTION_DECREASE; | ||
1873 | } | ||
1874 | } | ||
1875 | |||
1876 | /* next, increase if needed */ | ||
1877 | if (sr < TPC_SR_NO_INCREASE && strong != TPC_INVALID) { | ||
1878 | if (weak_tpt == IWL_INVALID_VALUE && | ||
1879 | strong_tpt != IWL_INVALID_VALUE && | ||
1880 | current_tpt < strong_tpt) { | ||
1881 | IWL_DEBUG_RATE(mvm, | ||
1882 | "higher txp has better tpt. increase txp\n"); | ||
1883 | return TPC_ACTION_INCREASE; | ||
1884 | } | ||
1885 | |||
1886 | if (weak_tpt < current_tpt && | ||
1887 | (strong_tpt == IWL_INVALID_VALUE || | ||
1888 | strong_tpt > current_tpt)) { | ||
1889 | IWL_DEBUG_RATE(mvm, | ||
1890 | "lower txp has worse tpt. increase txp\n"); | ||
1891 | return TPC_ACTION_INCREASE; | ||
1892 | } | ||
1893 | } | ||
1894 | |||
1895 | IWL_DEBUG_RATE(mvm, "no need to increase or decrease txp - stay\n"); | ||
1896 | return TPC_ACTION_STAY; | ||
1897 | } | ||
1898 | |||
1899 | static bool rs_tpc_perform(struct iwl_mvm *mvm, | ||
1900 | struct ieee80211_sta *sta, | ||
1901 | struct iwl_lq_sta *lq_sta, | ||
1902 | struct iwl_scale_tbl_info *tbl) | ||
1903 | { | ||
1904 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; | ||
1905 | struct ieee80211_vif *vif = mvm_sta->vif; | ||
1906 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
1907 | enum ieee80211_band band; | ||
1908 | struct iwl_rate_scale_data *window; | ||
1909 | struct rs_rate *rate = &tbl->rate; | ||
1910 | enum tpc_action action; | ||
1911 | s32 sr; | ||
1912 | u8 cur = lq_sta->lq.reduced_tpc; | ||
1913 | int current_tpt; | ||
1914 | int weak, strong; | ||
1915 | int weak_tpt = IWL_INVALID_VALUE, strong_tpt = IWL_INVALID_VALUE; | ||
1916 | |||
1917 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
1918 | if (lq_sta->dbg_fixed_txp_reduction <= TPC_MAX_REDUCTION) { | ||
1919 | IWL_DEBUG_RATE(mvm, "fixed tpc: %d", | ||
1920 | lq_sta->dbg_fixed_txp_reduction); | ||
1921 | lq_sta->lq.reduced_tpc = lq_sta->dbg_fixed_txp_reduction; | ||
1922 | return cur != lq_sta->dbg_fixed_txp_reduction; | ||
1923 | } | ||
1924 | #endif | ||
1925 | |||
1926 | rcu_read_lock(); | ||
1927 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | ||
1928 | if (WARN_ON(!chanctx_conf)) | ||
1929 | band = IEEE80211_NUM_BANDS; | ||
1930 | else | ||
1931 | band = chanctx_conf->def.chan->band; | ||
1932 | rcu_read_unlock(); | ||
1933 | |||
1934 | if (!rs_tpc_allowed(mvm, rate, band)) { | ||
1935 | IWL_DEBUG_RATE(mvm, | ||
1936 | "tpc is not allowed. remove txp restrictions"); | ||
1937 | lq_sta->lq.reduced_tpc = TPC_NO_REDUCTION; | ||
1938 | return cur != TPC_NO_REDUCTION; | ||
1939 | } | ||
1940 | |||
1941 | rs_get_adjacent_txp(mvm, cur, &weak, &strong); | ||
1942 | |||
1943 | /* Collect measured throughputs for current and adjacent rates */ | ||
1944 | window = tbl->tpc_win; | ||
1945 | sr = window[cur].success_ratio; | ||
1946 | current_tpt = window[cur].average_tpt; | ||
1947 | if (weak != TPC_INVALID) | ||
1948 | weak_tpt = window[weak].average_tpt; | ||
1949 | if (strong != TPC_INVALID) | ||
1950 | strong_tpt = window[strong].average_tpt; | ||
1951 | |||
1952 | IWL_DEBUG_RATE(mvm, | ||
1953 | "(TPC: %d): cur_tpt %d SR %d weak %d strong %d weak_tpt %d strong_tpt %d\n", | ||
1954 | cur, current_tpt, sr, weak, strong, | ||
1955 | weak_tpt, strong_tpt); | ||
1956 | |||
1957 | action = rs_get_tpc_action(mvm, sr, weak, strong, | ||
1958 | current_tpt, weak_tpt, strong_tpt); | ||
1959 | |||
1960 | /* override actions if we are on the edge */ | ||
1961 | if (weak == TPC_INVALID && action == TPC_ACTION_DECREASE) { | ||
1962 | IWL_DEBUG_RATE(mvm, "already in lowest txp, stay"); | ||
1963 | action = TPC_ACTION_STAY; | ||
1964 | } else if (strong == TPC_INVALID && | ||
1965 | (action == TPC_ACTION_INCREASE || | ||
1966 | action == TPC_ACTION_NO_RESTIRCTION)) { | ||
1967 | IWL_DEBUG_RATE(mvm, "already in highest txp, stay"); | ||
1968 | action = TPC_ACTION_STAY; | ||
1969 | } | ||
1970 | |||
1971 | switch (action) { | ||
1972 | case TPC_ACTION_DECREASE: | ||
1973 | lq_sta->lq.reduced_tpc = weak; | ||
1974 | return true; | ||
1975 | case TPC_ACTION_INCREASE: | ||
1976 | lq_sta->lq.reduced_tpc = strong; | ||
1977 | return true; | ||
1978 | case TPC_ACTION_NO_RESTIRCTION: | ||
1979 | lq_sta->lq.reduced_tpc = TPC_NO_REDUCTION; | ||
1980 | return true; | ||
1981 | case TPC_ACTION_STAY: | ||
1982 | /* do nothing */ | ||
1983 | break; | ||
1984 | } | ||
1985 | return false; | ||
1986 | } | ||
1987 | |||
1772 | /* | 1988 | /* |
1773 | * Do rate scaling and search for new modulation mode. | 1989 | * Do rate scaling and search for new modulation mode. |
1774 | */ | 1990 | */ |
@@ -2019,6 +2235,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
2019 | break; | 2235 | break; |
2020 | case RS_ACTION_STAY: | 2236 | case RS_ACTION_STAY: |
2021 | /* No change */ | 2237 | /* No change */ |
2238 | update_lq = rs_tpc_perform(mvm, sta, lq_sta, tbl); | ||
2239 | break; | ||
2022 | default: | 2240 | default: |
2023 | break; | 2241 | break; |
2024 | } | 2242 | } |
@@ -2478,6 +2696,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
2478 | lq_sta->is_agg = 0; | 2696 | lq_sta->is_agg = 0; |
2479 | #ifdef CONFIG_MAC80211_DEBUGFS | 2697 | #ifdef CONFIG_MAC80211_DEBUGFS |
2480 | lq_sta->dbg_fixed_rate = 0; | 2698 | lq_sta->dbg_fixed_rate = 0; |
2699 | lq_sta->dbg_fixed_txp_reduction = TPC_INVALID; | ||
2481 | #endif | 2700 | #endif |
2482 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 2701 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
2483 | iwl_mvm_reset_frame_stats(mvm, &mvm->drv_rx_stats); | 2702 | iwl_mvm_reset_frame_stats(mvm, &mvm->drv_rx_stats); |
@@ -2653,6 +2872,7 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm, | |||
2653 | rs_build_rates_table_from_fixed(mvm, lq_cmd, | 2872 | rs_build_rates_table_from_fixed(mvm, lq_cmd, |
2654 | lq_sta->band, | 2873 | lq_sta->band, |
2655 | lq_sta->dbg_fixed_rate); | 2874 | lq_sta->dbg_fixed_rate); |
2875 | lq_cmd->reduced_tpc = 0; | ||
2656 | ant = (lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) >> | 2876 | ant = (lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) >> |
2657 | RATE_MCS_ANT_POS; | 2877 | RATE_MCS_ANT_POS; |
2658 | } else | 2878 | } else |
@@ -2783,7 +3003,6 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, | |||
2783 | size_t buf_size; | 3003 | size_t buf_size; |
2784 | u32 parsed_rate; | 3004 | u32 parsed_rate; |
2785 | 3005 | ||
2786 | |||
2787 | mvm = lq_sta->drv; | 3006 | mvm = lq_sta->drv; |
2788 | memset(buf, 0, sizeof(buf)); | 3007 | memset(buf, 0, sizeof(buf)); |
2789 | buf_size = min(count, sizeof(buf) - 1); | 3008 | buf_size = min(count, sizeof(buf) - 1); |
@@ -2856,6 +3075,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
2856 | lq_sta->lq.agg_disable_start_th, | 3075 | lq_sta->lq.agg_disable_start_th, |
2857 | lq_sta->lq.agg_frame_cnt_limit); | 3076 | lq_sta->lq.agg_frame_cnt_limit); |
2858 | 3077 | ||
3078 | desc += sprintf(buff+desc, "reduced tpc=%d\n", lq_sta->lq.reduced_tpc); | ||
2859 | desc += sprintf(buff+desc, | 3079 | desc += sprintf(buff+desc, |
2860 | "Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n", | 3080 | "Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n", |
2861 | lq_sta->lq.initial_rate_index[0], | 3081 | lq_sta->lq.initial_rate_index[0], |
@@ -2928,6 +3148,94 @@ static const struct file_operations rs_sta_dbgfs_stats_table_ops = { | |||
2928 | .llseek = default_llseek, | 3148 | .llseek = default_llseek, |
2929 | }; | 3149 | }; |
2930 | 3150 | ||
3151 | static ssize_t rs_sta_dbgfs_drv_tx_stats_read(struct file *file, | ||
3152 | char __user *user_buf, | ||
3153 | size_t count, loff_t *ppos) | ||
3154 | { | ||
3155 | static const char * const column_name[] = { | ||
3156 | [RS_COLUMN_LEGACY_ANT_A] = "LEGACY_ANT_A", | ||
3157 | [RS_COLUMN_LEGACY_ANT_B] = "LEGACY_ANT_B", | ||
3158 | [RS_COLUMN_SISO_ANT_A] = "SISO_ANT_A", | ||
3159 | [RS_COLUMN_SISO_ANT_B] = "SISO_ANT_B", | ||
3160 | [RS_COLUMN_SISO_ANT_A_SGI] = "SISO_ANT_A_SGI", | ||
3161 | [RS_COLUMN_SISO_ANT_B_SGI] = "SISO_ANT_B_SGI", | ||
3162 | [RS_COLUMN_MIMO2] = "MIMO2", | ||
3163 | [RS_COLUMN_MIMO2_SGI] = "MIMO2_SGI", | ||
3164 | }; | ||
3165 | |||
3166 | static const char * const rate_name[] = { | ||
3167 | [IWL_RATE_1M_INDEX] = "1M", | ||
3168 | [IWL_RATE_2M_INDEX] = "2M", | ||
3169 | [IWL_RATE_5M_INDEX] = "5.5M", | ||
3170 | [IWL_RATE_11M_INDEX] = "11M", | ||
3171 | [IWL_RATE_6M_INDEX] = "6M|MCS0", | ||
3172 | [IWL_RATE_9M_INDEX] = "9M", | ||
3173 | [IWL_RATE_12M_INDEX] = "12M|MCS1", | ||
3174 | [IWL_RATE_18M_INDEX] = "18M|MCS2", | ||
3175 | [IWL_RATE_24M_INDEX] = "24M|MCS3", | ||
3176 | [IWL_RATE_36M_INDEX] = "36M|MCS4", | ||
3177 | [IWL_RATE_48M_INDEX] = "48M|MCS5", | ||
3178 | [IWL_RATE_54M_INDEX] = "54M|MCS6", | ||
3179 | [IWL_RATE_MCS_7_INDEX] = "MCS7", | ||
3180 | [IWL_RATE_MCS_8_INDEX] = "MCS8", | ||
3181 | [IWL_RATE_MCS_9_INDEX] = "MCS9", | ||
3182 | }; | ||
3183 | |||
3184 | char *buff, *pos, *endpos; | ||
3185 | int col, rate; | ||
3186 | ssize_t ret; | ||
3187 | struct iwl_lq_sta *lq_sta = file->private_data; | ||
3188 | struct rs_rate_stats *stats; | ||
3189 | static const size_t bufsz = 1024; | ||
3190 | |||
3191 | buff = kmalloc(bufsz, GFP_KERNEL); | ||
3192 | if (!buff) | ||
3193 | return -ENOMEM; | ||
3194 | |||
3195 | pos = buff; | ||
3196 | endpos = pos + bufsz; | ||
3197 | |||
3198 | pos += scnprintf(pos, endpos - pos, "COLUMN,"); | ||
3199 | for (rate = 0; rate < IWL_RATE_COUNT; rate++) | ||
3200 | pos += scnprintf(pos, endpos - pos, "%s,", rate_name[rate]); | ||
3201 | pos += scnprintf(pos, endpos - pos, "\n"); | ||
3202 | |||
3203 | for (col = 0; col < RS_COLUMN_COUNT; col++) { | ||
3204 | pos += scnprintf(pos, endpos - pos, | ||
3205 | "%s,", column_name[col]); | ||
3206 | |||
3207 | for (rate = 0; rate < IWL_RATE_COUNT; rate++) { | ||
3208 | stats = &(lq_sta->tx_stats[col][rate]); | ||
3209 | pos += scnprintf(pos, endpos - pos, | ||
3210 | "%llu/%llu,", | ||
3211 | stats->success, | ||
3212 | stats->total); | ||
3213 | } | ||
3214 | pos += scnprintf(pos, endpos - pos, "\n"); | ||
3215 | } | ||
3216 | |||
3217 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff); | ||
3218 | kfree(buff); | ||
3219 | return ret; | ||
3220 | } | ||
3221 | |||
3222 | static ssize_t rs_sta_dbgfs_drv_tx_stats_write(struct file *file, | ||
3223 | const char __user *user_buf, | ||
3224 | size_t count, loff_t *ppos) | ||
3225 | { | ||
3226 | struct iwl_lq_sta *lq_sta = file->private_data; | ||
3227 | memset(lq_sta->tx_stats, 0, sizeof(lq_sta->tx_stats)); | ||
3228 | |||
3229 | return count; | ||
3230 | } | ||
3231 | |||
3232 | static const struct file_operations rs_sta_dbgfs_drv_tx_stats_ops = { | ||
3233 | .read = rs_sta_dbgfs_drv_tx_stats_read, | ||
3234 | .write = rs_sta_dbgfs_drv_tx_stats_write, | ||
3235 | .open = simple_open, | ||
3236 | .llseek = default_llseek, | ||
3237 | }; | ||
3238 | |||
2931 | static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir) | 3239 | static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir) |
2932 | { | 3240 | { |
2933 | struct iwl_lq_sta *lq_sta = mvm_sta; | 3241 | struct iwl_lq_sta *lq_sta = mvm_sta; |
@@ -2937,9 +3245,15 @@ static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir) | |||
2937 | lq_sta->rs_sta_dbgfs_stats_table_file = | 3245 | lq_sta->rs_sta_dbgfs_stats_table_file = |
2938 | debugfs_create_file("rate_stats_table", S_IRUSR, dir, | 3246 | debugfs_create_file("rate_stats_table", S_IRUSR, dir, |
2939 | lq_sta, &rs_sta_dbgfs_stats_table_ops); | 3247 | lq_sta, &rs_sta_dbgfs_stats_table_ops); |
3248 | lq_sta->rs_sta_dbgfs_drv_tx_stats_file = | ||
3249 | debugfs_create_file("drv_tx_stats", S_IRUSR | S_IWUSR, dir, | ||
3250 | lq_sta, &rs_sta_dbgfs_drv_tx_stats_ops); | ||
2940 | lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = | 3251 | lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = |
2941 | debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir, | 3252 | debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir, |
2942 | &lq_sta->tx_agg_tid_en); | 3253 | &lq_sta->tx_agg_tid_en); |
3254 | lq_sta->rs_sta_dbgfs_reduced_txp_file = | ||
3255 | debugfs_create_u8("reduced_tpc", S_IRUSR | S_IWUSR, dir, | ||
3256 | &lq_sta->dbg_fixed_txp_reduction); | ||
2943 | } | 3257 | } |
2944 | 3258 | ||
2945 | static void rs_remove_debugfs(void *mvm, void *mvm_sta) | 3259 | static void rs_remove_debugfs(void *mvm, void *mvm_sta) |
@@ -2947,7 +3261,9 @@ static void rs_remove_debugfs(void *mvm, void *mvm_sta) | |||
2947 | struct iwl_lq_sta *lq_sta = mvm_sta; | 3261 | struct iwl_lq_sta *lq_sta = mvm_sta; |
2948 | debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); | 3262 | debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); |
2949 | debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); | 3263 | debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); |
3264 | debugfs_remove(lq_sta->rs_sta_dbgfs_drv_tx_stats_file); | ||
2950 | debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); | 3265 | debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); |
3266 | debugfs_remove(lq_sta->rs_sta_dbgfs_reduced_txp_file); | ||
2951 | } | 3267 | } |
2952 | #endif | 3268 | #endif |
2953 | 3269 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 0acfac96a56c..374a83d7db25 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h | |||
@@ -158,6 +158,13 @@ enum { | |||
158 | #define RS_SR_FORCE_DECREASE 1920 /* 15% */ | 158 | #define RS_SR_FORCE_DECREASE 1920 /* 15% */ |
159 | #define RS_SR_NO_DECREASE 10880 /* 85% */ | 159 | #define RS_SR_NO_DECREASE 10880 /* 85% */ |
160 | 160 | ||
161 | #define TPC_SR_FORCE_INCREASE 9600 /* 75% */ | ||
162 | #define TPC_SR_NO_INCREASE 10880 /* 85% */ | ||
163 | #define TPC_TX_POWER_STEP 3 | ||
164 | #define TPC_MAX_REDUCTION 15 | ||
165 | #define TPC_NO_REDUCTION 0 | ||
166 | #define TPC_INVALID 0xff | ||
167 | |||
161 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ | 168 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ |
162 | #define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000) | 169 | #define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000) |
163 | #define LINK_QUAL_AGG_TIME_LIMIT_MIN (100) | 170 | #define LINK_QUAL_AGG_TIME_LIMIT_MIN (100) |
@@ -266,9 +273,16 @@ enum rs_column { | |||
266 | RS_COLUMN_MIMO2_SGI, | 273 | RS_COLUMN_MIMO2_SGI, |
267 | 274 | ||
268 | RS_COLUMN_LAST = RS_COLUMN_MIMO2_SGI, | 275 | RS_COLUMN_LAST = RS_COLUMN_MIMO2_SGI, |
276 | RS_COLUMN_COUNT = RS_COLUMN_LAST + 1, | ||
269 | RS_COLUMN_INVALID, | 277 | RS_COLUMN_INVALID, |
270 | }; | 278 | }; |
271 | 279 | ||
280 | /* Packet stats per rate */ | ||
281 | struct rs_rate_stats { | ||
282 | u64 success; | ||
283 | u64 total; | ||
284 | }; | ||
285 | |||
272 | /** | 286 | /** |
273 | * struct iwl_scale_tbl_info -- tx params and success history for all rates | 287 | * struct iwl_scale_tbl_info -- tx params and success history for all rates |
274 | * | 288 | * |
@@ -280,6 +294,8 @@ struct iwl_scale_tbl_info { | |||
280 | enum rs_column column; | 294 | enum rs_column column; |
281 | const u16 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ | 295 | const u16 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ |
282 | struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ | 296 | struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ |
297 | /* per txpower-reduction history */ | ||
298 | struct iwl_rate_scale_data tpc_win[TPC_MAX_REDUCTION + 1]; | ||
283 | }; | 299 | }; |
284 | 300 | ||
285 | enum { | 301 | enum { |
@@ -315,6 +331,8 @@ struct iwl_lq_sta { | |||
315 | bool is_vht; | 331 | bool is_vht; |
316 | enum ieee80211_band band; | 332 | enum ieee80211_band band; |
317 | 333 | ||
334 | struct rs_rate_stats tx_stats[RS_COLUMN_COUNT][IWL_RATE_COUNT]; | ||
335 | |||
318 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | 336 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ |
319 | unsigned long active_legacy_rate; | 337 | unsigned long active_legacy_rate; |
320 | unsigned long active_siso_rate; | 338 | unsigned long active_siso_rate; |
@@ -334,8 +352,11 @@ struct iwl_lq_sta { | |||
334 | #ifdef CONFIG_MAC80211_DEBUGFS | 352 | #ifdef CONFIG_MAC80211_DEBUGFS |
335 | struct dentry *rs_sta_dbgfs_scale_table_file; | 353 | struct dentry *rs_sta_dbgfs_scale_table_file; |
336 | struct dentry *rs_sta_dbgfs_stats_table_file; | 354 | struct dentry *rs_sta_dbgfs_stats_table_file; |
355 | struct dentry *rs_sta_dbgfs_drv_tx_stats_file; | ||
337 | struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; | 356 | struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; |
357 | struct dentry *rs_sta_dbgfs_reduced_txp_file; | ||
338 | u32 dbg_fixed_rate; | 358 | u32 dbg_fixed_rate; |
359 | u8 dbg_fixed_txp_reduction; | ||
339 | #endif | 360 | #endif |
340 | struct iwl_mvm *drv; | 361 | struct iwl_mvm *drv; |
341 | 362 | ||
@@ -345,6 +366,9 @@ struct iwl_lq_sta { | |||
345 | u32 last_rate_n_flags; | 366 | u32 last_rate_n_flags; |
346 | /* packets destined for this STA are aggregated */ | 367 | /* packets destined for this STA are aggregated */ |
347 | u8 is_agg; | 368 | u8 is_agg; |
369 | |||
370 | /* tx power reduce for this sta */ | ||
371 | int tpc_reduce; | ||
348 | }; | 372 | }; |
349 | 373 | ||
350 | /* Initialize station's rate scaling information after adding station */ | 374 | /* Initialize station's rate scaling information after adding station */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 6061553a5e44..cf7276967acd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
@@ -60,7 +60,6 @@ | |||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
61 | *****************************************************************************/ | 61 | *****************************************************************************/ |
62 | #include "iwl-trans.h" | 62 | #include "iwl-trans.h" |
63 | |||
64 | #include "mvm.h" | 63 | #include "mvm.h" |
65 | #include "fw-api.h" | 64 | #include "fw-api.h" |
66 | 65 | ||
@@ -130,42 +129,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, | |||
130 | 129 | ||
131 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | 130 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); |
132 | 131 | ||
133 | ieee80211_rx_ni(mvm->hw, skb); | 132 | ieee80211_rx(mvm->hw, skb); |
134 | } | ||
135 | |||
136 | static void iwl_mvm_calc_rssi(struct iwl_mvm *mvm, | ||
137 | struct iwl_rx_phy_info *phy_info, | ||
138 | struct ieee80211_rx_status *rx_status) | ||
139 | { | ||
140 | int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm; | ||
141 | u32 agc_a, agc_b; | ||
142 | u32 val; | ||
143 | |||
144 | val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]); | ||
145 | agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS; | ||
146 | agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS; | ||
147 | |||
148 | val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_AB_IDX]); | ||
149 | rssi_a = (val & IWL_OFDM_RSSI_INBAND_A_MSK) >> IWL_OFDM_RSSI_A_POS; | ||
150 | rssi_b = (val & IWL_OFDM_RSSI_INBAND_B_MSK) >> IWL_OFDM_RSSI_B_POS; | ||
151 | |||
152 | /* | ||
153 | * dBm = rssi dB - agc dB - constant. | ||
154 | * Higher AGC (higher radio gain) means lower signal. | ||
155 | */ | ||
156 | rssi_a_dbm = rssi_a - IWL_RSSI_OFFSET - agc_a; | ||
157 | rssi_b_dbm = rssi_b - IWL_RSSI_OFFSET - agc_b; | ||
158 | max_rssi_dbm = max_t(int, rssi_a_dbm, rssi_b_dbm); | ||
159 | |||
160 | IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n", | ||
161 | rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b); | ||
162 | |||
163 | rx_status->signal = max_rssi_dbm; | ||
164 | rx_status->chains = (le16_to_cpu(phy_info->phy_flags) & | ||
165 | RX_RES_PHY_FLAGS_ANTENNA) | ||
166 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
167 | rx_status->chain_signal[0] = rssi_a_dbm; | ||
168 | rx_status->chain_signal[1] = rssi_b_dbm; | ||
169 | } | 133 | } |
170 | 134 | ||
171 | /* | 135 | /* |
@@ -337,10 +301,7 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
337 | */ | 301 | */ |
338 | /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/ | 302 | /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/ |
339 | 303 | ||
340 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_RX_ENERGY_API) | 304 | iwl_mvm_get_signal_strength(mvm, phy_info, &rx_status); |
341 | iwl_mvm_get_signal_strength(mvm, phy_info, &rx_status); | ||
342 | else | ||
343 | iwl_mvm_calc_rssi(mvm, phy_info, &rx_status); | ||
344 | 305 | ||
345 | IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal, | 306 | IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal, |
346 | (unsigned long long)rx_status.mactime); | 307 | (unsigned long long)rx_status.mactime); |
@@ -394,6 +355,8 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
394 | rx_status.rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; | 355 | rx_status.rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; |
395 | rx_status.flag |= RX_FLAG_VHT; | 356 | rx_status.flag |= RX_FLAG_VHT; |
396 | rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT; | 357 | rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT; |
358 | if (rate_n_flags & RATE_MCS_BF_MSK) | ||
359 | rx_status.vht_flag |= RX_VHT_FLAG_BF; | ||
397 | } else { | 360 | } else { |
398 | rx_status.rate_idx = | 361 | rx_status.rate_idx = |
399 | iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, | 362 | iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index c91dc8498852..63e7b16edb55 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -348,7 +348,10 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
348 | struct iwl_mvm_scan_params params = {}; | 348 | struct iwl_mvm_scan_params params = {}; |
349 | 349 | ||
350 | lockdep_assert_held(&mvm->mutex); | 350 | lockdep_assert_held(&mvm->mutex); |
351 | BUG_ON(mvm->scan_cmd == NULL); | 351 | |
352 | /* we should have failed registration if scan_cmd was NULL */ | ||
353 | if (WARN_ON(mvm->scan_cmd == NULL)) | ||
354 | return -ENOMEM; | ||
352 | 355 | ||
353 | IWL_DEBUG_SCAN(mvm, "Handling mac80211 scan request\n"); | 356 | IWL_DEBUG_SCAN(mvm, "Handling mac80211 scan request\n"); |
354 | mvm->scan_status = IWL_MVM_SCAN_OS; | 357 | mvm->scan_status = IWL_MVM_SCAN_OS; |
@@ -567,9 +570,13 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | |||
567 | /* scan status must be locked for proper checking */ | 570 | /* scan status must be locked for proper checking */ |
568 | lockdep_assert_held(&mvm->mutex); | 571 | lockdep_assert_held(&mvm->mutex); |
569 | 572 | ||
570 | IWL_DEBUG_SCAN(mvm, "Scheduled scan completed, status %s\n", | 573 | IWL_DEBUG_SCAN(mvm, |
574 | "Scheduled scan completed, status %s EBS status %s:%d\n", | ||
571 | scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ? | 575 | scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ? |
572 | "completed" : "aborted"); | 576 | "completed" : "aborted", scan_notif->ebs_status == |
577 | IWL_SCAN_EBS_SUCCESS ? "success" : "failed", | ||
578 | scan_notif->ebs_status); | ||
579 | |||
573 | 580 | ||
574 | /* only call mac80211 completion if the stop was initiated by FW */ | 581 | /* only call mac80211 completion if the stop was initiated by FW */ |
575 | if (mvm->scan_status == IWL_MVM_SCAN_SCHED) { | 582 | if (mvm->scan_status == IWL_MVM_SCAN_SCHED) { |
@@ -577,6 +584,8 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | |||
577 | ieee80211_sched_scan_stopped(mvm->hw); | 584 | ieee80211_sched_scan_stopped(mvm->hw); |
578 | } | 585 | } |
579 | 586 | ||
587 | mvm->last_ebs_successful = !scan_notif->ebs_status; | ||
588 | |||
580 | return 0; | 589 | return 0; |
581 | } | 590 | } |
582 | 591 | ||
@@ -913,6 +922,11 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | |||
913 | scan_req.flags |= cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_PASS_ALL); | 922 | scan_req.flags |= cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_PASS_ALL); |
914 | } | 923 | } |
915 | 924 | ||
925 | if (mvm->last_ebs_successful && | ||
926 | mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT) | ||
927 | scan_req.flags |= | ||
928 | cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_EBS_ACCURATE_MODE); | ||
929 | |||
916 | return iwl_mvm_send_cmd_pdu(mvm, SCAN_OFFLOAD_REQUEST_CMD, CMD_SYNC, | 930 | return iwl_mvm_send_cmd_pdu(mvm, SCAN_OFFLOAD_REQUEST_CMD, CMD_SYNC, |
917 | sizeof(scan_req), &scan_req); | 931 | sizeof(scan_req), &scan_req); |
918 | } | 932 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c index 88809b2d1654..7edfd15efc9d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sf.c +++ b/drivers/net/wireless/iwlwifi/mvm/sf.c | |||
@@ -237,9 +237,6 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif, | |||
237 | .sta_vif_ap_sta_id = IWL_MVM_STATION_COUNT, | 237 | .sta_vif_ap_sta_id = IWL_MVM_STATION_COUNT, |
238 | }; | 238 | }; |
239 | 239 | ||
240 | if (IWL_UCODE_API(mvm->fw->ucode_ver) < 8) | ||
241 | return 0; | ||
242 | |||
243 | /* | 240 | /* |
244 | * Ignore the call if we are in HW Restart flow, or if the handled | 241 | * Ignore the call if we are in HW Restart flow, or if the handled |
245 | * vif is a p2p device. | 242 | * vif is a p2p device. |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index f339ef884250..3e11b9d802e7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -66,115 +66,6 @@ | |||
66 | #include "sta.h" | 66 | #include "sta.h" |
67 | #include "rs.h" | 67 | #include "rs.h" |
68 | 68 | ||
69 | static void iwl_mvm_add_sta_cmd_v7_to_v5(struct iwl_mvm_add_sta_cmd_v7 *cmd_v7, | ||
70 | struct iwl_mvm_add_sta_cmd_v5 *cmd_v5) | ||
71 | { | ||
72 | memset(cmd_v5, 0, sizeof(*cmd_v5)); | ||
73 | |||
74 | cmd_v5->add_modify = cmd_v7->add_modify; | ||
75 | cmd_v5->tid_disable_tx = cmd_v7->tid_disable_tx; | ||
76 | cmd_v5->mac_id_n_color = cmd_v7->mac_id_n_color; | ||
77 | memcpy(cmd_v5->addr, cmd_v7->addr, ETH_ALEN); | ||
78 | cmd_v5->sta_id = cmd_v7->sta_id; | ||
79 | cmd_v5->modify_mask = cmd_v7->modify_mask; | ||
80 | cmd_v5->station_flags = cmd_v7->station_flags; | ||
81 | cmd_v5->station_flags_msk = cmd_v7->station_flags_msk; | ||
82 | cmd_v5->add_immediate_ba_tid = cmd_v7->add_immediate_ba_tid; | ||
83 | cmd_v5->remove_immediate_ba_tid = cmd_v7->remove_immediate_ba_tid; | ||
84 | cmd_v5->add_immediate_ba_ssn = cmd_v7->add_immediate_ba_ssn; | ||
85 | cmd_v5->sleep_tx_count = cmd_v7->sleep_tx_count; | ||
86 | cmd_v5->sleep_state_flags = cmd_v7->sleep_state_flags; | ||
87 | cmd_v5->assoc_id = cmd_v7->assoc_id; | ||
88 | cmd_v5->beamform_flags = cmd_v7->beamform_flags; | ||
89 | cmd_v5->tfd_queue_msk = cmd_v7->tfd_queue_msk; | ||
90 | } | ||
91 | |||
92 | static void | ||
93 | iwl_mvm_add_sta_key_to_add_sta_cmd_v5(struct iwl_mvm_add_sta_key_cmd *key_cmd, | ||
94 | struct iwl_mvm_add_sta_cmd_v5 *sta_cmd, | ||
95 | u32 mac_id_n_color) | ||
96 | { | ||
97 | memset(sta_cmd, 0, sizeof(*sta_cmd)); | ||
98 | |||
99 | sta_cmd->sta_id = key_cmd->sta_id; | ||
100 | sta_cmd->add_modify = STA_MODE_MODIFY; | ||
101 | sta_cmd->modify_mask = STA_MODIFY_KEY; | ||
102 | sta_cmd->mac_id_n_color = cpu_to_le32(mac_id_n_color); | ||
103 | |||
104 | sta_cmd->key.key_offset = key_cmd->key_offset; | ||
105 | sta_cmd->key.key_flags = key_cmd->key_flags; | ||
106 | memcpy(sta_cmd->key.key, key_cmd->key, sizeof(sta_cmd->key.key)); | ||
107 | sta_cmd->key.tkip_rx_tsc_byte2 = key_cmd->tkip_rx_tsc_byte2; | ||
108 | memcpy(sta_cmd->key.tkip_rx_ttak, key_cmd->tkip_rx_ttak, | ||
109 | sizeof(sta_cmd->key.tkip_rx_ttak)); | ||
110 | } | ||
111 | |||
112 | static int iwl_mvm_send_add_sta_cmd_status(struct iwl_mvm *mvm, | ||
113 | struct iwl_mvm_add_sta_cmd_v7 *cmd, | ||
114 | int *status) | ||
115 | { | ||
116 | struct iwl_mvm_add_sta_cmd_v5 cmd_v5; | ||
117 | |||
118 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD) | ||
119 | return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(*cmd), | ||
120 | cmd, status); | ||
121 | |||
122 | iwl_mvm_add_sta_cmd_v7_to_v5(cmd, &cmd_v5); | ||
123 | |||
124 | return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd_v5), | ||
125 | &cmd_v5, status); | ||
126 | } | ||
127 | |||
128 | static int iwl_mvm_send_add_sta_cmd(struct iwl_mvm *mvm, u32 flags, | ||
129 | struct iwl_mvm_add_sta_cmd_v7 *cmd) | ||
130 | { | ||
131 | struct iwl_mvm_add_sta_cmd_v5 cmd_v5; | ||
132 | |||
133 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD) | ||
134 | return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, | ||
135 | sizeof(*cmd), cmd); | ||
136 | |||
137 | iwl_mvm_add_sta_cmd_v7_to_v5(cmd, &cmd_v5); | ||
138 | |||
139 | return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, sizeof(cmd_v5), | ||
140 | &cmd_v5); | ||
141 | } | ||
142 | |||
143 | static int | ||
144 | iwl_mvm_send_add_sta_key_cmd_status(struct iwl_mvm *mvm, | ||
145 | struct iwl_mvm_add_sta_key_cmd *cmd, | ||
146 | u32 mac_id_n_color, | ||
147 | int *status) | ||
148 | { | ||
149 | struct iwl_mvm_add_sta_cmd_v5 sta_cmd; | ||
150 | |||
151 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD) | ||
152 | return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, | ||
153 | sizeof(*cmd), cmd, status); | ||
154 | |||
155 | iwl_mvm_add_sta_key_to_add_sta_cmd_v5(cmd, &sta_cmd, mac_id_n_color); | ||
156 | |||
157 | return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(sta_cmd), | ||
158 | &sta_cmd, status); | ||
159 | } | ||
160 | |||
161 | static int iwl_mvm_send_add_sta_key_cmd(struct iwl_mvm *mvm, | ||
162 | u32 flags, | ||
163 | struct iwl_mvm_add_sta_key_cmd *cmd, | ||
164 | u32 mac_id_n_color) | ||
165 | { | ||
166 | struct iwl_mvm_add_sta_cmd_v5 sta_cmd; | ||
167 | |||
168 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD) | ||
169 | return iwl_mvm_send_cmd_pdu(mvm, ADD_STA_KEY, flags, | ||
170 | sizeof(*cmd), cmd); | ||
171 | |||
172 | iwl_mvm_add_sta_key_to_add_sta_cmd_v5(cmd, &sta_cmd, mac_id_n_color); | ||
173 | |||
174 | return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, sizeof(sta_cmd), | ||
175 | &sta_cmd); | ||
176 | } | ||
177 | |||
178 | static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, | 69 | static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, |
179 | enum nl80211_iftype iftype) | 70 | enum nl80211_iftype iftype) |
180 | { | 71 | { |
@@ -207,7 +98,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
207 | bool update) | 98 | bool update) |
208 | { | 99 | { |
209 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; | 100 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; |
210 | struct iwl_mvm_add_sta_cmd_v7 add_sta_cmd; | 101 | struct iwl_mvm_add_sta_cmd add_sta_cmd; |
211 | int ret; | 102 | int ret; |
212 | u32 status; | 103 | u32 status; |
213 | u32 agg_size = 0, mpdu_dens = 0; | 104 | u32 agg_size = 0, mpdu_dens = 0; |
@@ -295,7 +186,8 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
295 | cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT); | 186 | cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT); |
296 | 187 | ||
297 | status = ADD_STA_SUCCESS; | 188 | status = ADD_STA_SUCCESS; |
298 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &add_sta_cmd, &status); | 189 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(add_sta_cmd), |
190 | &add_sta_cmd, &status); | ||
299 | if (ret) | 191 | if (ret) |
300 | return ret; | 192 | return ret; |
301 | 193 | ||
@@ -380,7 +272,7 @@ int iwl_mvm_update_sta(struct iwl_mvm *mvm, | |||
380 | int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, | 272 | int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, |
381 | bool drain) | 273 | bool drain) |
382 | { | 274 | { |
383 | struct iwl_mvm_add_sta_cmd_v7 cmd = {}; | 275 | struct iwl_mvm_add_sta_cmd cmd = {}; |
384 | int ret; | 276 | int ret; |
385 | u32 status; | 277 | u32 status; |
386 | 278 | ||
@@ -393,7 +285,8 @@ int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, | |||
393 | cmd.station_flags_msk = cpu_to_le32(STA_FLG_DRAIN_FLOW); | 285 | cmd.station_flags_msk = cpu_to_le32(STA_FLG_DRAIN_FLOW); |
394 | 286 | ||
395 | status = ADD_STA_SUCCESS; | 287 | status = ADD_STA_SUCCESS; |
396 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status); | 288 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), |
289 | &cmd, &status); | ||
397 | if (ret) | 290 | if (ret) |
398 | return ret; | 291 | return ret; |
399 | 292 | ||
@@ -498,7 +391,7 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk) | |||
498 | sta_id); | 391 | sta_id); |
499 | continue; | 392 | continue; |
500 | } | 393 | } |
501 | rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], NULL); | 394 | RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta_id], NULL); |
502 | clear_bit(sta_id, mvm->sta_drained); | 395 | clear_bit(sta_id, mvm->sta_drained); |
503 | } | 396 | } |
504 | 397 | ||
@@ -520,14 +413,6 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, | |||
520 | /* flush its queues here since we are freeing mvm_sta */ | 413 | /* flush its queues here since we are freeing mvm_sta */ |
521 | ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true); | 414 | ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true); |
522 | 415 | ||
523 | /* | ||
524 | * Put a non-NULL since the fw station isn't removed. | ||
525 | * It will be removed after the MAC will be set as | ||
526 | * unassoc. | ||
527 | */ | ||
528 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], | ||
529 | ERR_PTR(-EINVAL)); | ||
530 | |||
531 | /* if we are associated - we can't remove the AP STA now */ | 416 | /* if we are associated - we can't remove the AP STA now */ |
532 | if (vif->bss_conf.assoc) | 417 | if (vif->bss_conf.assoc) |
533 | return ret; | 418 | return ret; |
@@ -557,7 +442,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, | |||
557 | } else { | 442 | } else { |
558 | spin_unlock_bh(&mvm_sta->lock); | 443 | spin_unlock_bh(&mvm_sta->lock); |
559 | ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id); | 444 | ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id); |
560 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL); | 445 | RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL); |
561 | } | 446 | } |
562 | 447 | ||
563 | return ret; | 448 | return ret; |
@@ -571,7 +456,7 @@ int iwl_mvm_rm_sta_id(struct iwl_mvm *mvm, | |||
571 | 456 | ||
572 | lockdep_assert_held(&mvm->mutex); | 457 | lockdep_assert_held(&mvm->mutex); |
573 | 458 | ||
574 | rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], NULL); | 459 | RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta_id], NULL); |
575 | return ret; | 460 | return ret; |
576 | } | 461 | } |
577 | 462 | ||
@@ -593,7 +478,7 @@ int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta, | |||
593 | 478 | ||
594 | void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta) | 479 | void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta) |
595 | { | 480 | { |
596 | rcu_assign_pointer(mvm->fw_id_to_mac_id[sta->sta_id], NULL); | 481 | RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta->sta_id], NULL); |
597 | memset(sta, 0, sizeof(struct iwl_mvm_int_sta)); | 482 | memset(sta, 0, sizeof(struct iwl_mvm_int_sta)); |
598 | sta->sta_id = IWL_MVM_STATION_COUNT; | 483 | sta->sta_id = IWL_MVM_STATION_COUNT; |
599 | } | 484 | } |
@@ -603,13 +488,13 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, | |||
603 | const u8 *addr, | 488 | const u8 *addr, |
604 | u16 mac_id, u16 color) | 489 | u16 mac_id, u16 color) |
605 | { | 490 | { |
606 | struct iwl_mvm_add_sta_cmd_v7 cmd; | 491 | struct iwl_mvm_add_sta_cmd cmd; |
607 | int ret; | 492 | int ret; |
608 | u32 status; | 493 | u32 status; |
609 | 494 | ||
610 | lockdep_assert_held(&mvm->mutex); | 495 | lockdep_assert_held(&mvm->mutex); |
611 | 496 | ||
612 | memset(&cmd, 0, sizeof(struct iwl_mvm_add_sta_cmd_v7)); | 497 | memset(&cmd, 0, sizeof(cmd)); |
613 | cmd.sta_id = sta->sta_id; | 498 | cmd.sta_id = sta->sta_id; |
614 | cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id, | 499 | cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id, |
615 | color)); | 500 | color)); |
@@ -619,7 +504,8 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, | |||
619 | if (addr) | 504 | if (addr) |
620 | memcpy(cmd.addr, addr, ETH_ALEN); | 505 | memcpy(cmd.addr, addr, ETH_ALEN); |
621 | 506 | ||
622 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status); | 507 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), |
508 | &cmd, &status); | ||
623 | if (ret) | 509 | if (ret) |
624 | return ret; | 510 | return ret; |
625 | 511 | ||
@@ -753,7 +639,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
753 | int tid, u16 ssn, bool start) | 639 | int tid, u16 ssn, bool start) |
754 | { | 640 | { |
755 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; | 641 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; |
756 | struct iwl_mvm_add_sta_cmd_v7 cmd = {}; | 642 | struct iwl_mvm_add_sta_cmd cmd = {}; |
757 | int ret; | 643 | int ret; |
758 | u32 status; | 644 | u32 status; |
759 | 645 | ||
@@ -777,7 +663,8 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
777 | STA_MODIFY_REMOVE_BA_TID; | 663 | STA_MODIFY_REMOVE_BA_TID; |
778 | 664 | ||
779 | status = ADD_STA_SUCCESS; | 665 | status = ADD_STA_SUCCESS; |
780 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status); | 666 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), |
667 | &cmd, &status); | ||
781 | if (ret) | 668 | if (ret) |
782 | return ret; | 669 | return ret; |
783 | 670 | ||
@@ -812,7 +699,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
812 | int tid, u8 queue, bool start) | 699 | int tid, u8 queue, bool start) |
813 | { | 700 | { |
814 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; | 701 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; |
815 | struct iwl_mvm_add_sta_cmd_v7 cmd = {}; | 702 | struct iwl_mvm_add_sta_cmd cmd = {}; |
816 | int ret; | 703 | int ret; |
817 | u32 status; | 704 | u32 status; |
818 | 705 | ||
@@ -834,7 +721,8 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
834 | cmd.tid_disable_tx = cpu_to_le16(mvm_sta->tid_disable_agg); | 721 | cmd.tid_disable_tx = cpu_to_le16(mvm_sta->tid_disable_agg); |
835 | 722 | ||
836 | status = ADD_STA_SUCCESS; | 723 | status = ADD_STA_SUCCESS; |
837 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status); | 724 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), |
725 | &cmd, &status); | ||
838 | if (ret) | 726 | if (ret) |
839 | return ret; | 727 | return ret; |
840 | 728 | ||
@@ -1129,12 +1017,11 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, | |||
1129 | u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k, | 1017 | u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k, |
1130 | u32 cmd_flags) | 1018 | u32 cmd_flags) |
1131 | { | 1019 | { |
1132 | __le16 key_flags; | ||
1133 | struct iwl_mvm_add_sta_key_cmd cmd = {}; | 1020 | struct iwl_mvm_add_sta_key_cmd cmd = {}; |
1021 | __le16 key_flags; | ||
1134 | int ret, status; | 1022 | int ret, status; |
1135 | u16 keyidx; | 1023 | u16 keyidx; |
1136 | int i; | 1024 | int i; |
1137 | u32 mac_id_n_color = mvm_sta->mac_id_n_color; | ||
1138 | 1025 | ||
1139 | keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & | 1026 | keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & |
1140 | STA_KEY_FLG_KEYID_MSK; | 1027 | STA_KEY_FLG_KEYID_MSK; |
@@ -1167,12 +1054,11 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, | |||
1167 | 1054 | ||
1168 | status = ADD_STA_SUCCESS; | 1055 | status = ADD_STA_SUCCESS; |
1169 | if (cmd_flags == CMD_SYNC) | 1056 | if (cmd_flags == CMD_SYNC) |
1170 | ret = iwl_mvm_send_add_sta_key_cmd_status(mvm, &cmd, | 1057 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd), |
1171 | mac_id_n_color, | 1058 | &cmd, &status); |
1172 | &status); | ||
1173 | else | 1059 | else |
1174 | ret = iwl_mvm_send_add_sta_key_cmd(mvm, CMD_ASYNC, &cmd, | 1060 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA_KEY, CMD_ASYNC, |
1175 | mac_id_n_color); | 1061 | sizeof(cmd), &cmd); |
1176 | 1062 | ||
1177 | switch (status) { | 1063 | switch (status) { |
1178 | case ADD_STA_SUCCESS: | 1064 | case ADD_STA_SUCCESS: |
@@ -1399,9 +1285,8 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, | |||
1399 | cmd.sta_id = sta_id; | 1285 | cmd.sta_id = sta_id; |
1400 | 1286 | ||
1401 | status = ADD_STA_SUCCESS; | 1287 | status = ADD_STA_SUCCESS; |
1402 | ret = iwl_mvm_send_add_sta_key_cmd_status(mvm, &cmd, | 1288 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd), |
1403 | mvm_sta->mac_id_n_color, | 1289 | &cmd, &status); |
1404 | &status); | ||
1405 | 1290 | ||
1406 | switch (status) { | 1291 | switch (status) { |
1407 | case ADD_STA_SUCCESS: | 1292 | case ADD_STA_SUCCESS: |
@@ -1448,7 +1333,7 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, | |||
1448 | struct ieee80211_sta *sta) | 1333 | struct ieee80211_sta *sta) |
1449 | { | 1334 | { |
1450 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 1335 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
1451 | struct iwl_mvm_add_sta_cmd_v7 cmd = { | 1336 | struct iwl_mvm_add_sta_cmd cmd = { |
1452 | .add_modify = STA_MODE_MODIFY, | 1337 | .add_modify = STA_MODE_MODIFY, |
1453 | .sta_id = mvmsta->sta_id, | 1338 | .sta_id = mvmsta->sta_id, |
1454 | .station_flags_msk = cpu_to_le32(STA_FLG_PS), | 1339 | .station_flags_msk = cpu_to_le32(STA_FLG_PS), |
@@ -1456,7 +1341,7 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, | |||
1456 | }; | 1341 | }; |
1457 | int ret; | 1342 | int ret; |
1458 | 1343 | ||
1459 | ret = iwl_mvm_send_add_sta_cmd(mvm, CMD_ASYNC, &cmd); | 1344 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); |
1460 | if (ret) | 1345 | if (ret) |
1461 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); | 1346 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); |
1462 | } | 1347 | } |
@@ -1468,7 +1353,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, | |||
1468 | bool agg) | 1353 | bool agg) |
1469 | { | 1354 | { |
1470 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 1355 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
1471 | struct iwl_mvm_add_sta_cmd_v7 cmd = { | 1356 | struct iwl_mvm_add_sta_cmd cmd = { |
1472 | .add_modify = STA_MODE_MODIFY, | 1357 | .add_modify = STA_MODE_MODIFY, |
1473 | .sta_id = mvmsta->sta_id, | 1358 | .sta_id = mvmsta->sta_id, |
1474 | .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT, | 1359 | .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT, |
@@ -1538,7 +1423,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, | |||
1538 | cmd.sleep_state_flags |= cpu_to_le16(STA_SLEEP_STATE_UAPSD); | 1423 | cmd.sleep_state_flags |= cpu_to_le16(STA_SLEEP_STATE_UAPSD); |
1539 | } | 1424 | } |
1540 | 1425 | ||
1541 | ret = iwl_mvm_send_add_sta_cmd(mvm, CMD_ASYNC, &cmd); | 1426 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); |
1542 | if (ret) | 1427 | if (ret) |
1543 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); | 1428 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); |
1544 | } | 1429 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index 2ed84c421481..e5e3071ff252 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h | |||
@@ -253,6 +253,8 @@ enum iwl_mvm_agg_state { | |||
253 | * This is basically (last acked packet++). | 253 | * This is basically (last acked packet++). |
254 | * @rate_n_flags: Rate at which Tx was attempted. Holds the data between the | 254 | * @rate_n_flags: Rate at which Tx was attempted. Holds the data between the |
255 | * Tx response (TX_CMD), and the block ack notification (COMPRESSED_BA). | 255 | * Tx response (TX_CMD), and the block ack notification (COMPRESSED_BA). |
256 | * @reduced_tpc: Reduced tx power. Holds the data between the | ||
257 | * Tx response (TX_CMD), and the block ack notification (COMPRESSED_BA). | ||
256 | * @state: state of the BA agreement establishment / tear down. | 258 | * @state: state of the BA agreement establishment / tear down. |
257 | * @txq_id: Tx queue used by the BA session | 259 | * @txq_id: Tx queue used by the BA session |
258 | * @ssn: the first packet to be sent in AGG HW queue in Tx AGG start flow, or | 260 | * @ssn: the first packet to be sent in AGG HW queue in Tx AGG start flow, or |
@@ -265,6 +267,7 @@ struct iwl_mvm_tid_data { | |||
265 | u16 next_reclaimed; | 267 | u16 next_reclaimed; |
266 | /* The rest is Tx AGG related */ | 268 | /* The rest is Tx AGG related */ |
267 | u32 rate_n_flags; | 269 | u32 rate_n_flags; |
270 | u8 reduced_tpc; | ||
268 | enum iwl_mvm_agg_state state; | 271 | enum iwl_mvm_agg_state state; |
269 | u16 txq_id; | 272 | u16 txq_id; |
270 | u16 ssn; | 273 | u16 ssn; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index 61331245ad93..a9402937f767 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -273,67 +273,10 @@ static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait, | |||
273 | return true; | 273 | return true; |
274 | } | 274 | } |
275 | 275 | ||
276 | /* used to convert from time event API v2 to v1 */ | ||
277 | #define TE_V2_DEP_POLICY_MSK (TE_V2_DEP_OTHER | TE_V2_DEP_TSF |\ | ||
278 | TE_V2_EVENT_SOCIOPATHIC) | ||
279 | static inline u16 te_v2_get_notify(__le16 policy) | ||
280 | { | ||
281 | return le16_to_cpu(policy) & TE_V2_NOTIF_MSK; | ||
282 | } | ||
283 | |||
284 | static inline u16 te_v2_get_dep_policy(__le16 policy) | ||
285 | { | ||
286 | return (le16_to_cpu(policy) & TE_V2_DEP_POLICY_MSK) >> | ||
287 | TE_V2_PLACEMENT_POS; | ||
288 | } | ||
289 | |||
290 | static inline u16 te_v2_get_absence(__le16 policy) | ||
291 | { | ||
292 | return (le16_to_cpu(policy) & TE_V2_ABSENCE) >> TE_V2_ABSENCE_POS; | ||
293 | } | ||
294 | |||
295 | static void iwl_mvm_te_v2_to_v1(const struct iwl_time_event_cmd_v2 *cmd_v2, | ||
296 | struct iwl_time_event_cmd_v1 *cmd_v1) | ||
297 | { | ||
298 | cmd_v1->id_and_color = cmd_v2->id_and_color; | ||
299 | cmd_v1->action = cmd_v2->action; | ||
300 | cmd_v1->id = cmd_v2->id; | ||
301 | cmd_v1->apply_time = cmd_v2->apply_time; | ||
302 | cmd_v1->max_delay = cmd_v2->max_delay; | ||
303 | cmd_v1->depends_on = cmd_v2->depends_on; | ||
304 | cmd_v1->interval = cmd_v2->interval; | ||
305 | cmd_v1->duration = cmd_v2->duration; | ||
306 | if (cmd_v2->repeat == TE_V2_REPEAT_ENDLESS) | ||
307 | cmd_v1->repeat = cpu_to_le32(TE_V1_REPEAT_ENDLESS); | ||
308 | else | ||
309 | cmd_v1->repeat = cpu_to_le32(cmd_v2->repeat); | ||
310 | cmd_v1->max_frags = cpu_to_le32(cmd_v2->max_frags); | ||
311 | cmd_v1->interval_reciprocal = 0; /* unused */ | ||
312 | |||
313 | cmd_v1->dep_policy = cpu_to_le32(te_v2_get_dep_policy(cmd_v2->policy)); | ||
314 | cmd_v1->is_present = cpu_to_le32(!te_v2_get_absence(cmd_v2->policy)); | ||
315 | cmd_v1->notify = cpu_to_le32(te_v2_get_notify(cmd_v2->policy)); | ||
316 | } | ||
317 | |||
318 | static int iwl_mvm_send_time_event_cmd(struct iwl_mvm *mvm, | ||
319 | const struct iwl_time_event_cmd_v2 *cmd) | ||
320 | { | ||
321 | struct iwl_time_event_cmd_v1 cmd_v1; | ||
322 | |||
323 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2) | ||
324 | return iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, | ||
325 | sizeof(*cmd), cmd); | ||
326 | |||
327 | iwl_mvm_te_v2_to_v1(cmd, &cmd_v1); | ||
328 | return iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, | ||
329 | sizeof(cmd_v1), &cmd_v1); | ||
330 | } | ||
331 | |||
332 | |||
333 | static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, | 276 | static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, |
334 | struct ieee80211_vif *vif, | 277 | struct ieee80211_vif *vif, |
335 | struct iwl_mvm_time_event_data *te_data, | 278 | struct iwl_mvm_time_event_data *te_data, |
336 | struct iwl_time_event_cmd_v2 *te_cmd) | 279 | struct iwl_time_event_cmd *te_cmd) |
337 | { | 280 | { |
338 | static const u8 time_event_response[] = { TIME_EVENT_CMD }; | 281 | static const u8 time_event_response[] = { TIME_EVENT_CMD }; |
339 | struct iwl_notification_wait wait_time_event; | 282 | struct iwl_notification_wait wait_time_event; |
@@ -369,7 +312,8 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, | |||
369 | ARRAY_SIZE(time_event_response), | 312 | ARRAY_SIZE(time_event_response), |
370 | iwl_mvm_time_event_response, te_data); | 313 | iwl_mvm_time_event_response, te_data); |
371 | 314 | ||
372 | ret = iwl_mvm_send_time_event_cmd(mvm, te_cmd); | 315 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, |
316 | sizeof(*te_cmd), te_cmd); | ||
373 | if (ret) { | 317 | if (ret) { |
374 | IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret); | 318 | IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret); |
375 | iwl_remove_notification(&mvm->notif_wait, &wait_time_event); | 319 | iwl_remove_notification(&mvm->notif_wait, &wait_time_event); |
@@ -397,7 +341,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, | |||
397 | { | 341 | { |
398 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 342 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
399 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; | 343 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; |
400 | struct iwl_time_event_cmd_v2 time_cmd = {}; | 344 | struct iwl_time_event_cmd time_cmd = {}; |
401 | 345 | ||
402 | lockdep_assert_held(&mvm->mutex); | 346 | lockdep_assert_held(&mvm->mutex); |
403 | 347 | ||
@@ -453,7 +397,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm, | |||
453 | struct iwl_mvm_vif *mvmvif, | 397 | struct iwl_mvm_vif *mvmvif, |
454 | struct iwl_mvm_time_event_data *te_data) | 398 | struct iwl_mvm_time_event_data *te_data) |
455 | { | 399 | { |
456 | struct iwl_time_event_cmd_v2 time_cmd = {}; | 400 | struct iwl_time_event_cmd time_cmd = {}; |
457 | u32 id, uid; | 401 | u32 id, uid; |
458 | int ret; | 402 | int ret; |
459 | 403 | ||
@@ -490,7 +434,8 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm, | |||
490 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); | 434 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); |
491 | 435 | ||
492 | IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); | 436 | IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); |
493 | ret = iwl_mvm_send_time_event_cmd(mvm, &time_cmd); | 437 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, |
438 | sizeof(time_cmd), &time_cmd); | ||
494 | if (WARN_ON(ret)) | 439 | if (WARN_ON(ret)) |
495 | return; | 440 | return; |
496 | } | 441 | } |
@@ -510,7 +455,7 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
510 | { | 455 | { |
511 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 456 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
512 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; | 457 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; |
513 | struct iwl_time_event_cmd_v2 time_cmd = {}; | 458 | struct iwl_time_event_cmd time_cmd = {}; |
514 | 459 | ||
515 | lockdep_assert_held(&mvm->mutex); | 460 | lockdep_assert_held(&mvm->mutex); |
516 | if (te_data->running) { | 461 | if (te_data->running) { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index 7a99fa361954..39a3e03a0acd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c | |||
@@ -468,13 +468,14 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm) | |||
468 | } | 468 | } |
469 | 469 | ||
470 | if (params->support_tx_backoff) { | 470 | if (params->support_tx_backoff) { |
471 | tx_backoff = 0; | 471 | tx_backoff = tt->min_backoff; |
472 | for (i = 0; i < TT_TX_BACKOFF_SIZE; i++) { | 472 | for (i = 0; i < TT_TX_BACKOFF_SIZE; i++) { |
473 | if (temperature < params->tx_backoff[i].temperature) | 473 | if (temperature < params->tx_backoff[i].temperature) |
474 | break; | 474 | break; |
475 | tx_backoff = params->tx_backoff[i].backoff; | 475 | tx_backoff = max(tt->min_backoff, |
476 | params->tx_backoff[i].backoff); | ||
476 | } | 477 | } |
477 | if (tx_backoff != 0) | 478 | if (tx_backoff != tt->min_backoff) |
478 | throttle_enable = true; | 479 | throttle_enable = true; |
479 | if (tt->tx_backoff != tx_backoff) | 480 | if (tt->tx_backoff != tx_backoff) |
480 | iwl_mvm_tt_tx_backoff(mvm, tx_backoff); | 481 | iwl_mvm_tt_tx_backoff(mvm, tx_backoff); |
@@ -484,7 +485,8 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm) | |||
484 | IWL_WARN(mvm, | 485 | IWL_WARN(mvm, |
485 | "Due to high temperature thermal throttling initiated\n"); | 486 | "Due to high temperature thermal throttling initiated\n"); |
486 | tt->throttle = true; | 487 | tt->throttle = true; |
487 | } else if (tt->throttle && !tt->dynamic_smps && tt->tx_backoff == 0 && | 488 | } else if (tt->throttle && !tt->dynamic_smps && |
489 | tt->tx_backoff == tt->min_backoff && | ||
488 | temperature <= params->tx_protection_exit) { | 490 | temperature <= params->tx_protection_exit) { |
489 | IWL_WARN(mvm, | 491 | IWL_WARN(mvm, |
490 | "Temperature is back to normal thermal throttling stopped\n"); | 492 | "Temperature is back to normal thermal throttling stopped\n"); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 879aeac46cc1..ff1b630e130e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -636,7 +636,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
636 | seq_ctl = le16_to_cpu(hdr->seq_ctrl); | 636 | seq_ctl = le16_to_cpu(hdr->seq_ctrl); |
637 | } | 637 | } |
638 | 638 | ||
639 | ieee80211_tx_status_ni(mvm->hw, skb); | 639 | BUILD_BUG_ON(ARRAY_SIZE(info->status.status_driver_data) < 1); |
640 | info->status.status_driver_data[0] = | ||
641 | (void *)(uintptr_t)tx_resp->reduced_tpc; | ||
642 | |||
643 | ieee80211_tx_status(mvm->hw, skb); | ||
640 | } | 644 | } |
641 | 645 | ||
642 | if (txq_id >= mvm->first_agg_queue) { | 646 | if (txq_id >= mvm->first_agg_queue) { |
@@ -815,6 +819,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm, | |||
815 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 819 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
816 | mvmsta->tid_data[tid].rate_n_flags = | 820 | mvmsta->tid_data[tid].rate_n_flags = |
817 | le32_to_cpu(tx_resp->initial_rate); | 821 | le32_to_cpu(tx_resp->initial_rate); |
822 | mvmsta->tid_data[tid].reduced_tpc = tx_resp->reduced_tpc; | ||
818 | } | 823 | } |
819 | 824 | ||
820 | rcu_read_unlock(); | 825 | rcu_read_unlock(); |
@@ -928,6 +933,8 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
928 | info->status.ampdu_len = ba_notif->txed; | 933 | info->status.ampdu_len = ba_notif->txed; |
929 | iwl_mvm_hwrate_to_tx_status(tid_data->rate_n_flags, | 934 | iwl_mvm_hwrate_to_tx_status(tid_data->rate_n_flags, |
930 | info); | 935 | info); |
936 | info->status.status_driver_data[0] = | ||
937 | (void *)(uintptr_t)tid_data->reduced_tpc; | ||
931 | } | 938 | } |
932 | } | 939 | } |
933 | 940 | ||
@@ -937,7 +944,7 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
937 | 944 | ||
938 | while (!skb_queue_empty(&reclaimed_skbs)) { | 945 | while (!skb_queue_empty(&reclaimed_skbs)) { |
939 | skb = __skb_dequeue(&reclaimed_skbs); | 946 | skb = __skb_dequeue(&reclaimed_skbs); |
940 | ieee80211_tx_status_ni(mvm->hw, skb); | 947 | ieee80211_tx_status(mvm->hw, skb); |
941 | } | 948 | } |
942 | 949 | ||
943 | return 0; | 950 | return 0; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index d619851745a1..c5f4532cafa9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -64,6 +64,7 @@ | |||
64 | 64 | ||
65 | #include "iwl-debug.h" | 65 | #include "iwl-debug.h" |
66 | #include "iwl-io.h" | 66 | #include "iwl-io.h" |
67 | #include "iwl-prph.h" | ||
67 | 68 | ||
68 | #include "mvm.h" | 69 | #include "mvm.h" |
69 | #include "fw-api-rs.h" | 70 | #include "fw-api-rs.h" |
@@ -469,6 +470,8 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) | |||
469 | mvm->status, table.valid); | 470 | mvm->status, table.valid); |
470 | } | 471 | } |
471 | 472 | ||
473 | /* Do not change this output - scripts rely on it */ | ||
474 | |||
472 | IWL_ERR(mvm, "Loaded firmware version: %s\n", mvm->fw->fw_version); | 475 | IWL_ERR(mvm, "Loaded firmware version: %s\n", mvm->fw->fw_version); |
473 | 476 | ||
474 | trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low, | 477 | trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low, |
@@ -522,7 +525,7 @@ void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm) | |||
522 | u32 ofs, sram_len; | 525 | u32 ofs, sram_len; |
523 | void *sram; | 526 | void *sram; |
524 | 527 | ||
525 | if (!mvm->ucode_loaded || mvm->fw_error_sram) | 528 | if (!mvm->ucode_loaded || mvm->fw_error_sram || mvm->fw_error_dump) |
526 | return; | 529 | return; |
527 | 530 | ||
528 | img = &mvm->fw->img[mvm->cur_ucode]; | 531 | img = &mvm->fw->img[mvm->cur_ucode]; |
@@ -538,6 +541,47 @@ void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm) | |||
538 | mvm->fw_error_sram_len = sram_len; | 541 | mvm->fw_error_sram_len = sram_len; |
539 | } | 542 | } |
540 | 543 | ||
544 | void iwl_mvm_fw_error_rxf_dump(struct iwl_mvm *mvm) | ||
545 | { | ||
546 | int i, reg_val; | ||
547 | unsigned long flags; | ||
548 | |||
549 | if (!mvm->ucode_loaded || mvm->fw_error_rxf || mvm->fw_error_dump) | ||
550 | return; | ||
551 | |||
552 | /* reading buffer size */ | ||
553 | reg_val = iwl_trans_read_prph(mvm->trans, RXF_SIZE_ADDR); | ||
554 | mvm->fw_error_rxf_len = | ||
555 | (reg_val & RXF_SIZE_BYTE_CNT_MSK) >> RXF_SIZE_BYTE_CND_POS; | ||
556 | |||
557 | /* the register holds the value divided by 128 */ | ||
558 | mvm->fw_error_rxf_len = mvm->fw_error_rxf_len << 7; | ||
559 | |||
560 | if (!mvm->fw_error_rxf_len) | ||
561 | return; | ||
562 | |||
563 | mvm->fw_error_rxf = kzalloc(mvm->fw_error_rxf_len, GFP_ATOMIC); | ||
564 | if (!mvm->fw_error_rxf) { | ||
565 | mvm->fw_error_rxf_len = 0; | ||
566 | return; | ||
567 | } | ||
568 | |||
569 | if (!iwl_trans_grab_nic_access(mvm->trans, false, &flags)) { | ||
570 | kfree(mvm->fw_error_rxf); | ||
571 | mvm->fw_error_rxf = NULL; | ||
572 | mvm->fw_error_rxf_len = 0; | ||
573 | return; | ||
574 | } | ||
575 | |||
576 | for (i = 0; i < (mvm->fw_error_rxf_len / sizeof(u32)); i++) { | ||
577 | iwl_trans_write_prph(mvm->trans, RXF_LD_FENCE_OFFSET_ADDR, | ||
578 | i * sizeof(u32)); | ||
579 | mvm->fw_error_rxf[i] = | ||
580 | iwl_trans_read_prph(mvm->trans, RXF_FIFO_RD_FENCE_ADDR); | ||
581 | } | ||
582 | iwl_trans_release_nic_access(mvm->trans, &flags); | ||
583 | } | ||
584 | |||
541 | /** | 585 | /** |
542 | * iwl_mvm_send_lq_cmd() - Send link quality command | 586 | * iwl_mvm_send_lq_cmd() - Send link quality command |
543 | * @init: This command is sent as part of station initialization right | 587 | * @init: This command is sent as part of station initialization right |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 9091513ea738..1b95d856dfd5 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -102,7 +102,7 @@ struct iwl_rxq { | |||
102 | u32 write_actual; | 102 | u32 write_actual; |
103 | struct list_head rx_free; | 103 | struct list_head rx_free; |
104 | struct list_head rx_used; | 104 | struct list_head rx_used; |
105 | int need_update; | 105 | bool need_update; |
106 | struct iwl_rb_status *rb_stts; | 106 | struct iwl_rb_status *rb_stts; |
107 | dma_addr_t rb_stts_dma; | 107 | dma_addr_t rb_stts_dma; |
108 | spinlock_t lock; | 108 | spinlock_t lock; |
@@ -231,7 +231,7 @@ struct iwl_txq { | |||
231 | spinlock_t lock; | 231 | spinlock_t lock; |
232 | struct timer_list stuck_timer; | 232 | struct timer_list stuck_timer; |
233 | struct iwl_trans_pcie *trans_pcie; | 233 | struct iwl_trans_pcie *trans_pcie; |
234 | u8 need_update; | 234 | bool need_update; |
235 | u8 active; | 235 | u8 active; |
236 | bool ampdu; | 236 | bool ampdu; |
237 | }; | 237 | }; |
@@ -270,6 +270,9 @@ struct iwl_trans_pcie { | |||
270 | struct iwl_trans *trans; | 270 | struct iwl_trans *trans; |
271 | struct iwl_drv *drv; | 271 | struct iwl_drv *drv; |
272 | 272 | ||
273 | struct net_device napi_dev; | ||
274 | struct napi_struct napi; | ||
275 | |||
273 | /* INT ICT Table */ | 276 | /* INT ICT Table */ |
274 | __le32 *ict_tbl; | 277 | __le32 *ict_tbl; |
275 | dma_addr_t ict_tbl_dma; | 278 | dma_addr_t ict_tbl_dma; |
@@ -362,7 +365,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, | |||
362 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue); | 365 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue); |
363 | int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | 366 | int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, |
364 | struct iwl_device_cmd *dev_cmd, int txq_id); | 367 | struct iwl_device_cmd *dev_cmd, int txq_id); |
365 | void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq); | 368 | void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans); |
366 | int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); | 369 | int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); |
367 | void iwl_pcie_hcmd_complete(struct iwl_trans *trans, | 370 | void iwl_pcie_hcmd_complete(struct iwl_trans *trans, |
368 | struct iwl_rx_cmd_buffer *rxb, int handler_status); | 371 | struct iwl_rx_cmd_buffer *rxb, int handler_status); |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index fdfa3969cac9..4a26a082a1ba 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -145,15 +145,13 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans) | |||
145 | /* | 145 | /* |
146 | * iwl_pcie_rxq_inc_wr_ptr - Update the write pointer for the RX queue | 146 | * iwl_pcie_rxq_inc_wr_ptr - Update the write pointer for the RX queue |
147 | */ | 147 | */ |
148 | static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, | 148 | static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans) |
149 | struct iwl_rxq *rxq) | ||
150 | { | 149 | { |
150 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
151 | struct iwl_rxq *rxq = &trans_pcie->rxq; | ||
151 | u32 reg; | 152 | u32 reg; |
152 | 153 | ||
153 | spin_lock(&rxq->lock); | 154 | lockdep_assert_held(&rxq->lock); |
154 | |||
155 | if (rxq->need_update == 0) | ||
156 | goto exit_unlock; | ||
157 | 155 | ||
158 | /* | 156 | /* |
159 | * explicitly wake up the NIC if: | 157 | * explicitly wake up the NIC if: |
@@ -169,13 +167,27 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, | |||
169 | reg); | 167 | reg); |
170 | iwl_set_bit(trans, CSR_GP_CNTRL, | 168 | iwl_set_bit(trans, CSR_GP_CNTRL, |
171 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 169 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
172 | goto exit_unlock; | 170 | rxq->need_update = true; |
171 | return; | ||
173 | } | 172 | } |
174 | } | 173 | } |
175 | 174 | ||
176 | rxq->write_actual = round_down(rxq->write, 8); | 175 | rxq->write_actual = round_down(rxq->write, 8); |
177 | iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); | 176 | iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); |
178 | rxq->need_update = 0; | 177 | } |
178 | |||
179 | static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans) | ||
180 | { | ||
181 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
182 | struct iwl_rxq *rxq = &trans_pcie->rxq; | ||
183 | |||
184 | spin_lock(&rxq->lock); | ||
185 | |||
186 | if (!rxq->need_update) | ||
187 | goto exit_unlock; | ||
188 | |||
189 | iwl_pcie_rxq_inc_wr_ptr(trans); | ||
190 | rxq->need_update = false; | ||
179 | 191 | ||
180 | exit_unlock: | 192 | exit_unlock: |
181 | spin_unlock(&rxq->lock); | 193 | spin_unlock(&rxq->lock); |
@@ -236,9 +248,8 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) | |||
236 | * Increment device's write pointer in multiples of 8. */ | 248 | * Increment device's write pointer in multiples of 8. */ |
237 | if (rxq->write_actual != (rxq->write & ~0x7)) { | 249 | if (rxq->write_actual != (rxq->write & ~0x7)) { |
238 | spin_lock(&rxq->lock); | 250 | spin_lock(&rxq->lock); |
239 | rxq->need_update = 1; | 251 | iwl_pcie_rxq_inc_wr_ptr(trans); |
240 | spin_unlock(&rxq->lock); | 252 | spin_unlock(&rxq->lock); |
241 | iwl_pcie_rxq_inc_wr_ptr(trans, rxq); | ||
242 | } | 253 | } |
243 | } | 254 | } |
244 | 255 | ||
@@ -362,20 +373,9 @@ static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans) | |||
362 | * Also restock the Rx queue via iwl_pcie_rxq_restock. | 373 | * Also restock the Rx queue via iwl_pcie_rxq_restock. |
363 | * This is called as a scheduled work item (except for during initialization) | 374 | * This is called as a scheduled work item (except for during initialization) |
364 | */ | 375 | */ |
365 | static void iwl_pcie_rx_replenish(struct iwl_trans *trans) | 376 | static void iwl_pcie_rx_replenish(struct iwl_trans *trans, gfp_t gfp) |
366 | { | ||
367 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
368 | |||
369 | iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL); | ||
370 | |||
371 | spin_lock(&trans_pcie->irq_lock); | ||
372 | iwl_pcie_rxq_restock(trans); | ||
373 | spin_unlock(&trans_pcie->irq_lock); | ||
374 | } | ||
375 | |||
376 | static void iwl_pcie_rx_replenish_now(struct iwl_trans *trans) | ||
377 | { | 377 | { |
378 | iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC); | 378 | iwl_pcie_rxq_alloc_rbs(trans, gfp); |
379 | 379 | ||
380 | iwl_pcie_rxq_restock(trans); | 380 | iwl_pcie_rxq_restock(trans); |
381 | } | 381 | } |
@@ -385,7 +385,7 @@ static void iwl_pcie_rx_replenish_work(struct work_struct *data) | |||
385 | struct iwl_trans_pcie *trans_pcie = | 385 | struct iwl_trans_pcie *trans_pcie = |
386 | container_of(data, struct iwl_trans_pcie, rx_replenish); | 386 | container_of(data, struct iwl_trans_pcie, rx_replenish); |
387 | 387 | ||
388 | iwl_pcie_rx_replenish(trans_pcie->trans); | 388 | iwl_pcie_rx_replenish(trans_pcie->trans, GFP_KERNEL); |
389 | } | 389 | } |
390 | 390 | ||
391 | static int iwl_pcie_rx_alloc(struct iwl_trans *trans) | 391 | static int iwl_pcie_rx_alloc(struct iwl_trans *trans) |
@@ -521,14 +521,13 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) | |||
521 | memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); | 521 | memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); |
522 | spin_unlock(&rxq->lock); | 522 | spin_unlock(&rxq->lock); |
523 | 523 | ||
524 | iwl_pcie_rx_replenish(trans); | 524 | iwl_pcie_rx_replenish(trans, GFP_KERNEL); |
525 | 525 | ||
526 | iwl_pcie_rx_hw_init(trans, rxq); | 526 | iwl_pcie_rx_hw_init(trans, rxq); |
527 | 527 | ||
528 | spin_lock(&trans_pcie->irq_lock); | 528 | spin_lock(&rxq->lock); |
529 | rxq->need_update = 1; | 529 | iwl_pcie_rxq_inc_wr_ptr(trans); |
530 | iwl_pcie_rxq_inc_wr_ptr(trans, rxq); | 530 | spin_unlock(&rxq->lock); |
531 | spin_unlock(&trans_pcie->irq_lock); | ||
532 | 531 | ||
533 | return 0; | 532 | return 0; |
534 | } | 533 | } |
@@ -673,7 +672,6 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, | |||
673 | /* Reuse the page if possible. For notification packets and | 672 | /* Reuse the page if possible. For notification packets and |
674 | * SKBs that fail to Rx correctly, add them back into the | 673 | * SKBs that fail to Rx correctly, add them back into the |
675 | * rx_free list for reuse later. */ | 674 | * rx_free list for reuse later. */ |
676 | spin_lock(&rxq->lock); | ||
677 | if (rxb->page != NULL) { | 675 | if (rxb->page != NULL) { |
678 | rxb->page_dma = | 676 | rxb->page_dma = |
679 | dma_map_page(trans->dev, rxb->page, 0, | 677 | dma_map_page(trans->dev, rxb->page, 0, |
@@ -694,7 +692,6 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, | |||
694 | } | 692 | } |
695 | } else | 693 | } else |
696 | list_add_tail(&rxb->list, &rxq->rx_used); | 694 | list_add_tail(&rxb->list, &rxq->rx_used); |
697 | spin_unlock(&rxq->lock); | ||
698 | } | 695 | } |
699 | 696 | ||
700 | /* | 697 | /* |
@@ -709,6 +706,8 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans) | |||
709 | u32 count = 8; | 706 | u32 count = 8; |
710 | int total_empty; | 707 | int total_empty; |
711 | 708 | ||
709 | restart: | ||
710 | spin_lock(&rxq->lock); | ||
712 | /* uCode's read index (stored in shared DRAM) indicates the last Rx | 711 | /* uCode's read index (stored in shared DRAM) indicates the last Rx |
713 | * buffer that the driver may process (last buffer filled by ucode). */ | 712 | * buffer that the driver may process (last buffer filled by ucode). */ |
714 | r = le16_to_cpu(ACCESS_ONCE(rxq->rb_stts->closed_rb_num)) & 0x0FFF; | 713 | r = le16_to_cpu(ACCESS_ONCE(rxq->rb_stts->closed_rb_num)) & 0x0FFF; |
@@ -743,18 +742,25 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans) | |||
743 | count++; | 742 | count++; |
744 | if (count >= 8) { | 743 | if (count >= 8) { |
745 | rxq->read = i; | 744 | rxq->read = i; |
746 | iwl_pcie_rx_replenish_now(trans); | 745 | spin_unlock(&rxq->lock); |
746 | iwl_pcie_rx_replenish(trans, GFP_ATOMIC); | ||
747 | count = 0; | 747 | count = 0; |
748 | goto restart; | ||
748 | } | 749 | } |
749 | } | 750 | } |
750 | } | 751 | } |
751 | 752 | ||
752 | /* Backtrack one entry */ | 753 | /* Backtrack one entry */ |
753 | rxq->read = i; | 754 | rxq->read = i; |
755 | spin_unlock(&rxq->lock); | ||
756 | |||
754 | if (fill_rx) | 757 | if (fill_rx) |
755 | iwl_pcie_rx_replenish_now(trans); | 758 | iwl_pcie_rx_replenish(trans, GFP_ATOMIC); |
756 | else | 759 | else |
757 | iwl_pcie_rxq_restock(trans); | 760 | iwl_pcie_rxq_restock(trans); |
761 | |||
762 | if (trans_pcie->napi.poll) | ||
763 | napi_gro_flush(&trans_pcie->napi, false); | ||
758 | } | 764 | } |
759 | 765 | ||
760 | /* | 766 | /* |
@@ -876,7 +882,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | |||
876 | struct isr_statistics *isr_stats = &trans_pcie->isr_stats; | 882 | struct isr_statistics *isr_stats = &trans_pcie->isr_stats; |
877 | u32 inta = 0; | 883 | u32 inta = 0; |
878 | u32 handled = 0; | 884 | u32 handled = 0; |
879 | u32 i; | ||
880 | 885 | ||
881 | lock_map_acquire(&trans->sync_cmd_lockdep_map); | 886 | lock_map_acquire(&trans->sync_cmd_lockdep_map); |
882 | 887 | ||
@@ -1028,9 +1033,8 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | |||
1028 | /* uCode wakes up after power-down sleep */ | 1033 | /* uCode wakes up after power-down sleep */ |
1029 | if (inta & CSR_INT_BIT_WAKEUP) { | 1034 | if (inta & CSR_INT_BIT_WAKEUP) { |
1030 | IWL_DEBUG_ISR(trans, "Wakeup interrupt\n"); | 1035 | IWL_DEBUG_ISR(trans, "Wakeup interrupt\n"); |
1031 | iwl_pcie_rxq_inc_wr_ptr(trans, &trans_pcie->rxq); | 1036 | iwl_pcie_rxq_check_wrptr(trans); |
1032 | for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) | 1037 | iwl_pcie_txq_check_wrptrs(trans); |
1033 | iwl_pcie_txq_inc_wr_ptr(trans, &trans_pcie->txq[i]); | ||
1034 | 1038 | ||
1035 | isr_stats->wakeup++; | 1039 | isr_stats->wakeup++; |
1036 | 1040 | ||
@@ -1068,8 +1072,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | |||
1068 | iwl_write8(trans, CSR_INT_PERIODIC_REG, | 1072 | iwl_write8(trans, CSR_INT_PERIODIC_REG, |
1069 | CSR_INT_PERIODIC_DIS); | 1073 | CSR_INT_PERIODIC_DIS); |
1070 | 1074 | ||
1071 | iwl_pcie_rx_handle(trans); | ||
1072 | |||
1073 | /* | 1075 | /* |
1074 | * Enable periodic interrupt in 8 msec only if we received | 1076 | * Enable periodic interrupt in 8 msec only if we received |
1075 | * real RX interrupt (instead of just periodic int), to catch | 1077 | * real RX interrupt (instead of just periodic int), to catch |
@@ -1082,6 +1084,10 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | |||
1082 | CSR_INT_PERIODIC_ENA); | 1084 | CSR_INT_PERIODIC_ENA); |
1083 | 1085 | ||
1084 | isr_stats->rx++; | 1086 | isr_stats->rx++; |
1087 | |||
1088 | local_bh_disable(); | ||
1089 | iwl_pcie_rx_handle(trans); | ||
1090 | local_bh_enable(); | ||
1085 | } | 1091 | } |
1086 | 1092 | ||
1087 | /* This "Tx" DMA channel is used only for loading uCode */ | 1093 | /* This "Tx" DMA channel is used only for loading uCode */ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index dcfd6d866d09..f98ef1e62eb9 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -103,7 +103,6 @@ static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux) | |||
103 | 103 | ||
104 | /* PCI registers */ | 104 | /* PCI registers */ |
105 | #define PCI_CFG_RETRY_TIMEOUT 0x041 | 105 | #define PCI_CFG_RETRY_TIMEOUT 0x041 |
106 | #define CPU1_CPU2_SEPARATOR_SECTION 0xFFFFCCCC | ||
107 | 106 | ||
108 | static void iwl_pcie_apm_config(struct iwl_trans *trans) | 107 | static void iwl_pcie_apm_config(struct iwl_trans *trans) |
109 | { | 108 | { |
@@ -1053,6 +1052,12 @@ static void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, | |||
1053 | iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val); | 1052 | iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val); |
1054 | } | 1053 | } |
1055 | 1054 | ||
1055 | static int iwl_pcie_dummy_napi_poll(struct napi_struct *napi, int budget) | ||
1056 | { | ||
1057 | WARN_ON(1); | ||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1056 | static void iwl_trans_pcie_configure(struct iwl_trans *trans, | 1061 | static void iwl_trans_pcie_configure(struct iwl_trans *trans, |
1057 | const struct iwl_trans_config *trans_cfg) | 1062 | const struct iwl_trans_config *trans_cfg) |
1058 | { | 1063 | { |
@@ -1079,6 +1084,18 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, | |||
1079 | 1084 | ||
1080 | trans_pcie->command_names = trans_cfg->command_names; | 1085 | trans_pcie->command_names = trans_cfg->command_names; |
1081 | trans_pcie->bc_table_dword = trans_cfg->bc_table_dword; | 1086 | trans_pcie->bc_table_dword = trans_cfg->bc_table_dword; |
1087 | |||
1088 | /* Initialize NAPI here - it should be before registering to mac80211 | ||
1089 | * in the opmode but after the HW struct is allocated. | ||
1090 | * As this function may be called again in some corner cases don't | ||
1091 | * do anything if NAPI was already initialized. | ||
1092 | */ | ||
1093 | if (!trans_pcie->napi.poll && trans->op_mode->ops->napi_add) { | ||
1094 | init_dummy_netdev(&trans_pcie->napi_dev); | ||
1095 | iwl_op_mode_napi_add(trans->op_mode, &trans_pcie->napi, | ||
1096 | &trans_pcie->napi_dev, | ||
1097 | iwl_pcie_dummy_napi_poll, 64); | ||
1098 | } | ||
1082 | } | 1099 | } |
1083 | 1100 | ||
1084 | void iwl_trans_pcie_free(struct iwl_trans *trans) | 1101 | void iwl_trans_pcie_free(struct iwl_trans *trans) |
@@ -1099,6 +1116,9 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) | |||
1099 | pci_disable_device(trans_pcie->pci_dev); | 1116 | pci_disable_device(trans_pcie->pci_dev); |
1100 | kmem_cache_destroy(trans->dev_cmd_pool); | 1117 | kmem_cache_destroy(trans->dev_cmd_pool); |
1101 | 1118 | ||
1119 | if (trans_pcie->napi.poll) | ||
1120 | netif_napi_del(&trans_pcie->napi); | ||
1121 | |||
1102 | kfree(trans); | 1122 | kfree(trans); |
1103 | } | 1123 | } |
1104 | 1124 | ||
@@ -1237,7 +1257,7 @@ static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr, | |||
1237 | 1257 | ||
1238 | #define IWL_FLUSH_WAIT_MS 2000 | 1258 | #define IWL_FLUSH_WAIT_MS 2000 |
1239 | 1259 | ||
1240 | static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans) | 1260 | static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm) |
1241 | { | 1261 | { |
1242 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1262 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1243 | struct iwl_txq *txq; | 1263 | struct iwl_txq *txq; |
@@ -1250,13 +1270,31 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans) | |||
1250 | 1270 | ||
1251 | /* waiting for all the tx frames complete might take a while */ | 1271 | /* waiting for all the tx frames complete might take a while */ |
1252 | for (cnt = 0; cnt < trans->cfg->base_params->num_of_queues; cnt++) { | 1272 | for (cnt = 0; cnt < trans->cfg->base_params->num_of_queues; cnt++) { |
1273 | u8 wr_ptr; | ||
1274 | |||
1253 | if (cnt == trans_pcie->cmd_queue) | 1275 | if (cnt == trans_pcie->cmd_queue) |
1254 | continue; | 1276 | continue; |
1277 | if (!test_bit(cnt, trans_pcie->queue_used)) | ||
1278 | continue; | ||
1279 | if (!(BIT(cnt) & txq_bm)) | ||
1280 | continue; | ||
1281 | |||
1282 | IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", cnt); | ||
1255 | txq = &trans_pcie->txq[cnt]; | 1283 | txq = &trans_pcie->txq[cnt]; |
1256 | q = &txq->q; | 1284 | q = &txq->q; |
1257 | while (q->read_ptr != q->write_ptr && !time_after(jiffies, | 1285 | wr_ptr = ACCESS_ONCE(q->write_ptr); |
1258 | now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) | 1286 | |
1287 | while (q->read_ptr != ACCESS_ONCE(q->write_ptr) && | ||
1288 | !time_after(jiffies, | ||
1289 | now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) { | ||
1290 | u8 write_ptr = ACCESS_ONCE(q->write_ptr); | ||
1291 | |||
1292 | if (WARN_ONCE(wr_ptr != write_ptr, | ||
1293 | "WR pointer moved while flushing %d -> %d\n", | ||
1294 | wr_ptr, write_ptr)) | ||
1295 | return -ETIMEDOUT; | ||
1259 | msleep(1); | 1296 | msleep(1); |
1297 | } | ||
1260 | 1298 | ||
1261 | if (q->read_ptr != q->write_ptr) { | 1299 | if (q->read_ptr != q->write_ptr) { |
1262 | IWL_ERR(trans, | 1300 | IWL_ERR(trans, |
@@ -1264,6 +1302,7 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans) | |||
1264 | ret = -ETIMEDOUT; | 1302 | ret = -ETIMEDOUT; |
1265 | break; | 1303 | break; |
1266 | } | 1304 | } |
1305 | IWL_DEBUG_TX_QUEUES(trans, "Queue %d is now empty.\n", cnt); | ||
1267 | } | 1306 | } |
1268 | 1307 | ||
1269 | if (!ret) | 1308 | if (!ret) |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 3b0c72c10054..dde6031f4257 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -287,14 +287,14 @@ static void iwl_pcie_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, | |||
287 | /* | 287 | /* |
288 | * iwl_pcie_txq_inc_wr_ptr - Send new write index to hardware | 288 | * iwl_pcie_txq_inc_wr_ptr - Send new write index to hardware |
289 | */ | 289 | */ |
290 | void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) | 290 | static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, |
291 | struct iwl_txq *txq) | ||
291 | { | 292 | { |
292 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 293 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
293 | u32 reg = 0; | 294 | u32 reg = 0; |
294 | int txq_id = txq->q.id; | 295 | int txq_id = txq->q.id; |
295 | 296 | ||
296 | if (txq->need_update == 0) | 297 | lockdep_assert_held(&txq->lock); |
297 | return; | ||
298 | 298 | ||
299 | /* | 299 | /* |
300 | * explicitly wake up the NIC if: | 300 | * explicitly wake up the NIC if: |
@@ -317,6 +317,7 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) | |||
317 | txq_id, reg); | 317 | txq_id, reg); |
318 | iwl_set_bit(trans, CSR_GP_CNTRL, | 318 | iwl_set_bit(trans, CSR_GP_CNTRL, |
319 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 319 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
320 | txq->need_update = true; | ||
320 | return; | 321 | return; |
321 | } | 322 | } |
322 | } | 323 | } |
@@ -327,8 +328,23 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) | |||
327 | */ | 328 | */ |
328 | IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id, txq->q.write_ptr); | 329 | IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id, txq->q.write_ptr); |
329 | iwl_write32(trans, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); | 330 | iwl_write32(trans, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); |
331 | } | ||
332 | |||
333 | void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans) | ||
334 | { | ||
335 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
336 | int i; | ||
330 | 337 | ||
331 | txq->need_update = 0; | 338 | for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { |
339 | struct iwl_txq *txq = &trans_pcie->txq[i]; | ||
340 | |||
341 | spin_lock(&txq->lock); | ||
342 | if (trans_pcie->txq[i].need_update) { | ||
343 | iwl_pcie_txq_inc_wr_ptr(trans, txq); | ||
344 | trans_pcie->txq[i].need_update = false; | ||
345 | } | ||
346 | spin_unlock(&txq->lock); | ||
347 | } | ||
332 | } | 348 | } |
333 | 349 | ||
334 | static inline dma_addr_t iwl_pcie_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) | 350 | static inline dma_addr_t iwl_pcie_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) |
@@ -542,7 +558,7 @@ static int iwl_pcie_txq_init(struct iwl_trans *trans, struct iwl_txq *txq, | |||
542 | { | 558 | { |
543 | int ret; | 559 | int ret; |
544 | 560 | ||
545 | txq->need_update = 0; | 561 | txq->need_update = false; |
546 | 562 | ||
547 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise | 563 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise |
548 | * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ | 564 | * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ |
@@ -680,7 +696,8 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr) | |||
680 | /* The chain extension of the SCD doesn't work well. This feature is | 696 | /* The chain extension of the SCD doesn't work well. This feature is |
681 | * enabled by default by the HW, so we need to disable it manually. | 697 | * enabled by default by the HW, so we need to disable it manually. |
682 | */ | 698 | */ |
683 | iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); | 699 | if (trans->cfg->base_params->scd_chain_ext_wa) |
700 | iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); | ||
684 | 701 | ||
685 | iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue, | 702 | iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue, |
686 | trans_pcie->cmd_fifo); | 703 | trans_pcie->cmd_fifo); |
@@ -1028,7 +1045,8 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) | |||
1028 | } | 1045 | } |
1029 | } | 1046 | } |
1030 | 1047 | ||
1031 | if (q->read_ptr == q->write_ptr) { | 1048 | if (trans->cfg->base_params->apmg_wake_up_wa && |
1049 | q->read_ptr == q->write_ptr) { | ||
1032 | spin_lock_irqsave(&trans_pcie->reg_lock, flags); | 1050 | spin_lock_irqsave(&trans_pcie->reg_lock, flags); |
1033 | WARN_ON(!trans_pcie->cmd_in_flight); | 1051 | WARN_ON(!trans_pcie->cmd_in_flight); |
1034 | trans_pcie->cmd_in_flight = false; | 1052 | trans_pcie->cmd_in_flight = false; |
@@ -1392,8 +1410,6 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1392 | kfree(txq->entries[idx].free_buf); | 1410 | kfree(txq->entries[idx].free_buf); |
1393 | txq->entries[idx].free_buf = dup_buf; | 1411 | txq->entries[idx].free_buf = dup_buf; |
1394 | 1412 | ||
1395 | txq->need_update = 1; | ||
1396 | |||
1397 | trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr); | 1413 | trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr); |
1398 | 1414 | ||
1399 | /* start timer if queue currently empty */ | 1415 | /* start timer if queue currently empty */ |
@@ -1405,9 +1421,11 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1405 | /* | 1421 | /* |
1406 | * wake up the NIC to make sure that the firmware will see the host | 1422 | * wake up the NIC to make sure that the firmware will see the host |
1407 | * command - we will let the NIC sleep once all the host commands | 1423 | * command - we will let the NIC sleep once all the host commands |
1408 | * returned. | 1424 | * returned. This needs to be done only on NICs that have |
1425 | * apmg_wake_up_wa set. | ||
1409 | */ | 1426 | */ |
1410 | if (!trans_pcie->cmd_in_flight) { | 1427 | if (trans->cfg->base_params->apmg_wake_up_wa && |
1428 | !trans_pcie->cmd_in_flight) { | ||
1411 | trans_pcie->cmd_in_flight = true; | 1429 | trans_pcie->cmd_in_flight = true; |
1412 | __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, | 1430 | __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, |
1413 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 1431 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
@@ -1661,7 +1679,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1661 | dma_addr_t tb0_phys, tb1_phys, scratch_phys; | 1679 | dma_addr_t tb0_phys, tb1_phys, scratch_phys; |
1662 | void *tb1_addr; | 1680 | void *tb1_addr; |
1663 | u16 len, tb1_len, tb2_len; | 1681 | u16 len, tb1_len, tb2_len; |
1664 | u8 wait_write_ptr = 0; | 1682 | bool wait_write_ptr; |
1665 | __le16 fc = hdr->frame_control; | 1683 | __le16 fc = hdr->frame_control; |
1666 | u8 hdr_len = ieee80211_hdrlen(fc); | 1684 | u8 hdr_len = ieee80211_hdrlen(fc); |
1667 | u16 wifi_seq; | 1685 | u16 wifi_seq; |
@@ -1762,12 +1780,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1762 | trace_iwlwifi_dev_tx_data(trans->dev, skb, | 1780 | trace_iwlwifi_dev_tx_data(trans->dev, skb, |
1763 | skb->data + hdr_len, tb2_len); | 1781 | skb->data + hdr_len, tb2_len); |
1764 | 1782 | ||
1765 | if (!ieee80211_has_morefrags(fc)) { | 1783 | wait_write_ptr = ieee80211_has_morefrags(fc); |
1766 | txq->need_update = 1; | ||
1767 | } else { | ||
1768 | wait_write_ptr = 1; | ||
1769 | txq->need_update = 0; | ||
1770 | } | ||
1771 | 1784 | ||
1772 | /* start timer if queue currently empty */ | 1785 | /* start timer if queue currently empty */ |
1773 | if (txq->need_update && q->read_ptr == q->write_ptr && | 1786 | if (txq->need_update && q->read_ptr == q->write_ptr && |
@@ -1776,21 +1789,18 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1776 | 1789 | ||
1777 | /* Tell device the write index *just past* this latest filled TFD */ | 1790 | /* Tell device the write index *just past* this latest filled TFD */ |
1778 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 1791 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
1779 | iwl_pcie_txq_inc_wr_ptr(trans, txq); | 1792 | if (!wait_write_ptr) |
1793 | iwl_pcie_txq_inc_wr_ptr(trans, txq); | ||
1780 | 1794 | ||
1781 | /* | 1795 | /* |
1782 | * At this point the frame is "transmitted" successfully | 1796 | * At this point the frame is "transmitted" successfully |
1783 | * and we will get a TX status notification eventually, | 1797 | * and we will get a TX status notification eventually. |
1784 | * regardless of the value of ret. "ret" only indicates | ||
1785 | * whether or not we should update the write pointer. | ||
1786 | */ | 1798 | */ |
1787 | if (iwl_queue_space(q) < q->high_mark) { | 1799 | if (iwl_queue_space(q) < q->high_mark) { |
1788 | if (wait_write_ptr) { | 1800 | if (wait_write_ptr) |
1789 | txq->need_update = 1; | ||
1790 | iwl_pcie_txq_inc_wr_ptr(trans, txq); | 1801 | iwl_pcie_txq_inc_wr_ptr(trans, txq); |
1791 | } else { | 1802 | else |
1792 | iwl_stop_queue(trans, txq); | 1803 | iwl_stop_queue(trans, txq); |
1793 | } | ||
1794 | } | 1804 | } |
1795 | spin_unlock(&txq->lock); | 1805 | spin_unlock(&txq->lock); |
1796 | return 0; | 1806 | return 0; |