diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-08-16 14:48:40 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-08-16 14:48:40 -0400 |
commit | 24de851b79a414f0e1813eb131a7d90849cc22c2 (patch) | |
tree | 4da554a6d83adbfea3e00e242f97028a69cc0bb7 /drivers/net | |
parent | d0746663667f37e7be5646bf68cb452c8375a23d (diff) | |
parent | 89716344806bd49d213ad5960661e8c2d38c4982 (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
Diffstat (limited to 'drivers/net')
20 files changed, 809 insertions, 713 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index e5c133ee7901..3eb2102ce236 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -22,6 +22,8 @@ config IWLWIFI | |||
22 | Intel Wireless WiFi Link 6150BGN 2 Adapter | 22 | Intel Wireless WiFi Link 6150BGN 2 Adapter |
23 | Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN) | 23 | Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN) |
24 | Intel 2000 Series Wi-Fi Adapters | 24 | Intel 2000 Series Wi-Fi Adapters |
25 | Intel 7260 Wi-Fi Adapter | ||
26 | Intel 3160 Wi-Fi Adapter | ||
25 | 27 | ||
26 | 28 | ||
27 | This driver uses the kernel's mac80211 subsystem. | 29 | This driver uses the kernel's mac80211 subsystem. |
@@ -46,17 +48,16 @@ config IWLDVM | |||
46 | depends on IWLWIFI | 48 | depends on IWLWIFI |
47 | default IWLWIFI | 49 | default IWLWIFI |
48 | help | 50 | help |
49 | This is the driver supporting the DVM firmware which is | 51 | This is the driver that supports the DVM firmware which is |
50 | currently the only firmware available for existing devices. | 52 | used by most existing devices (with the exception of 7260 |
53 | and 3160). | ||
51 | 54 | ||
52 | config IWLMVM | 55 | config IWLMVM |
53 | tristate "Intel Wireless WiFi MVM Firmware support" | 56 | tristate "Intel Wireless WiFi MVM Firmware support" |
54 | depends on IWLWIFI | 57 | depends on IWLWIFI |
55 | help | 58 | help |
56 | This is the driver supporting the MVM firmware which is | 59 | This is the driver that supports the MVM firmware which is |
57 | currently only available for 7000 series devices. | 60 | currently only available for 7260 and 3160 devices. |
58 | |||
59 | Say yes if you have such a device. | ||
60 | 61 | ||
61 | # don't call it _MODULE -- will confuse Kconfig/fixdep/... | 62 | # don't call it _MODULE -- will confuse Kconfig/fixdep/... |
62 | config IWLWIFI_OPMODE_MODULAR | 63 | config IWLWIFI_OPMODE_MODULAR |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 7edb8519c8a4..b2bb32a781dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -145,6 +145,7 @@ do { \ | |||
145 | #define IWL_DL_RX 0x01000000 | 145 | #define IWL_DL_RX 0x01000000 |
146 | #define IWL_DL_ISR 0x02000000 | 146 | #define IWL_DL_ISR 0x02000000 |
147 | #define IWL_DL_HT 0x04000000 | 147 | #define IWL_DL_HT 0x04000000 |
148 | #define IWL_DL_EXTERNAL 0x08000000 | ||
148 | /* 0xF0000000 - 0x10000000 */ | 149 | /* 0xF0000000 - 0x10000000 */ |
149 | #define IWL_DL_11H 0x10000000 | 150 | #define IWL_DL_11H 0x10000000 |
150 | #define IWL_DL_STATS 0x20000000 | 151 | #define IWL_DL_STATS 0x20000000 |
@@ -153,6 +154,7 @@ do { \ | |||
153 | 154 | ||
154 | #define IWL_DEBUG_INFO(p, f, a...) IWL_DEBUG(p, IWL_DL_INFO, f, ## a) | 155 | #define IWL_DEBUG_INFO(p, f, a...) IWL_DEBUG(p, IWL_DL_INFO, f, ## a) |
155 | #define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a) | 156 | #define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a) |
157 | #define IWL_DEBUG_EXTERNAL(p, f, a...) IWL_DEBUG(p, IWL_DL_EXTERNAL, f, ## a) | ||
156 | #define IWL_DEBUG_TEMP(p, f, a...) IWL_DEBUG(p, IWL_DL_TEMP, f, ## a) | 158 | #define IWL_DEBUG_TEMP(p, f, a...) IWL_DEBUG(p, IWL_DL_TEMP, f, ## a) |
157 | #define IWL_DEBUG_SCAN(p, f, a...) IWL_DEBUG(p, IWL_DL_SCAN, f, ## a) | 159 | #define IWL_DEBUG_SCAN(p, f, a...) IWL_DEBUG(p, IWL_DL_SCAN, f, ## a) |
158 | #define IWL_DEBUG_RX(p, f, a...) IWL_DEBUG(p, IWL_DL_RX, f, ## a) | 160 | #define IWL_DEBUG_RX(p, f, a...) IWL_DEBUG(p, IWL_DL_RX, f, ## a) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index d0162d426f88..99e1da3123c9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -843,7 +843,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
843 | int i; | 843 | int i; |
844 | bool load_module = false; | 844 | bool load_module = false; |
845 | 845 | ||
846 | fw->ucode_capa.max_probe_length = 200; | 846 | fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH; |
847 | fw->ucode_capa.standard_phy_calibration_size = | 847 | fw->ucode_capa.standard_phy_calibration_size = |
848 | IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE; | 848 | IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE; |
849 | 849 | ||
@@ -1032,8 +1032,10 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans, | |||
1032 | int ret; | 1032 | int ret; |
1033 | 1033 | ||
1034 | drv = kzalloc(sizeof(*drv), GFP_KERNEL); | 1034 | drv = kzalloc(sizeof(*drv), GFP_KERNEL); |
1035 | if (!drv) | 1035 | if (!drv) { |
1036 | return NULL; | 1036 | ret = -ENOMEM; |
1037 | goto err; | ||
1038 | } | ||
1037 | 1039 | ||
1038 | drv->trans = trans; | 1040 | drv->trans = trans; |
1039 | drv->dev = trans->dev; | 1041 | drv->dev = trans->dev; |
@@ -1078,7 +1080,7 @@ err_free_dbgfs: | |||
1078 | err_free_drv: | 1080 | err_free_drv: |
1079 | #endif | 1081 | #endif |
1080 | kfree(drv); | 1082 | kfree(drv); |
1081 | 1083 | err: | |
1082 | return ERR_PTR(ret); | 1084 | return ERR_PTR(ret); |
1083 | } | 1085 | } |
1084 | 1086 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index bd335f0c40d1..a1223680bc70 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -76,6 +76,7 @@ | |||
76 | * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS | 76 | * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS |
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_RX_ENERGY_API: supports rx signal strength api | 78 | * @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api |
79 | * @IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API. | ||
79 | * @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 |
80 | * (rather than two) IPv6 addresses | 81 | * (rather than two) IPv6 addresses |
81 | * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API | 82 | * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API |
@@ -88,6 +89,7 @@ enum iwl_ucode_tlv_flag { | |||
88 | IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), | 89 | IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), |
89 | IWL_UCODE_TLV_FLAGS_UAPSD = BIT(6), | 90 | IWL_UCODE_TLV_FLAGS_UAPSD = BIT(6), |
90 | IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8), | 91 | IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8), |
92 | IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 = BIT(9), | ||
91 | IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10), | 93 | IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10), |
92 | IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11), | 94 | IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11), |
93 | }; | 95 | }; |
@@ -97,6 +99,9 @@ enum iwl_ucode_tlv_flag { | |||
97 | #define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE 19 | 99 | #define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE 19 |
98 | #define IWL_MAX_PHY_CALIBRATE_TBL_SIZE 253 | 100 | #define IWL_MAX_PHY_CALIBRATE_TBL_SIZE 253 |
99 | 101 | ||
102 | /* The default max probe length if not specified by the firmware file */ | ||
103 | #define IWL_DEFAULT_MAX_PROBE_LENGTH 200 | ||
104 | |||
100 | /** | 105 | /** |
101 | * enum iwl_ucode_type | 106 | * enum iwl_ucode_type |
102 | * | 107 | * |
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index 64656e0c8f91..2bf29f7992ee 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h | |||
@@ -67,5 +67,14 @@ | |||
67 | #define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC) | 67 | #define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC) |
68 | #define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC) | 68 | #define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC) |
69 | #define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC) | 69 | #define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC) |
70 | #define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC) | ||
71 | #define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC) | ||
72 | #define IWL_MVM_PS_HEAVY_TX_THLD_PACKETS 20 | ||
73 | #define IWL_MVM_PS_HEAVY_RX_THLD_PACKETS 20 | ||
74 | #define IWL_MVM_PS_HEAVY_TX_THLD_PERCENT 50 | ||
75 | #define IWL_MVM_PS_HEAVY_RX_THLD_PERCENT 50 | ||
76 | #define IWL_MVM_PS_SNOOZE_INTERVAL 25 | ||
77 | #define IWL_MVM_PS_SNOOZE_WINDOW 50 | ||
78 | #define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW 25 | ||
70 | 79 | ||
71 | #endif /* __MVM_CONSTANTS_H */ | 80 | #endif /* __MVM_CONSTANTS_H */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index d0d7a20266e6..417639f77b01 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -1109,73 +1109,16 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
1109 | return __iwl_mvm_suspend(hw, wowlan, false); | 1109 | return __iwl_mvm_suspend(hw, wowlan, false); |
1110 | } | 1110 | } |
1111 | 1111 | ||
1112 | static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | 1112 | static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm, |
1113 | struct ieee80211_vif *vif) | 1113 | struct ieee80211_vif *vif, |
1114 | struct iwl_wowlan_status *status) | ||
1114 | { | 1115 | { |
1115 | u32 base = mvm->error_event_table; | 1116 | struct sk_buff *pkt = NULL; |
1116 | struct error_table_start { | ||
1117 | /* cf. struct iwl_error_event_table */ | ||
1118 | u32 valid; | ||
1119 | u32 error_id; | ||
1120 | } err_info; | ||
1121 | struct cfg80211_wowlan_wakeup wakeup = { | 1117 | struct cfg80211_wowlan_wakeup wakeup = { |
1122 | .pattern_idx = -1, | 1118 | .pattern_idx = -1, |
1123 | }; | 1119 | }; |
1124 | struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup; | 1120 | struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup; |
1125 | struct iwl_host_cmd cmd = { | 1121 | u32 reasons = le32_to_cpu(status->wakeup_reasons); |
1126 | .id = WOWLAN_GET_STATUSES, | ||
1127 | .flags = CMD_SYNC | CMD_WANT_SKB, | ||
1128 | }; | ||
1129 | struct iwl_wowlan_status *status; | ||
1130 | u32 reasons; | ||
1131 | int ret, len; | ||
1132 | struct sk_buff *pkt = NULL; | ||
1133 | |||
1134 | iwl_trans_read_mem_bytes(mvm->trans, base, | ||
1135 | &err_info, sizeof(err_info)); | ||
1136 | |||
1137 | if (err_info.valid) { | ||
1138 | IWL_INFO(mvm, "error table is valid (%d)\n", | ||
1139 | err_info.valid); | ||
1140 | if (err_info.error_id == RF_KILL_INDICATOR_FOR_WOWLAN) { | ||
1141 | wakeup.rfkill_release = true; | ||
1142 | ieee80211_report_wowlan_wakeup(vif, &wakeup, | ||
1143 | GFP_KERNEL); | ||
1144 | } | ||
1145 | return; | ||
1146 | } | ||
1147 | |||
1148 | /* only for tracing for now */ | ||
1149 | ret = iwl_mvm_send_cmd_pdu(mvm, OFFLOADS_QUERY_CMD, CMD_SYNC, 0, NULL); | ||
1150 | if (ret) | ||
1151 | IWL_ERR(mvm, "failed to query offload statistics (%d)\n", ret); | ||
1152 | |||
1153 | ret = iwl_mvm_send_cmd(mvm, &cmd); | ||
1154 | if (ret) { | ||
1155 | IWL_ERR(mvm, "failed to query status (%d)\n", ret); | ||
1156 | return; | ||
1157 | } | ||
1158 | |||
1159 | /* RF-kill already asserted again... */ | ||
1160 | if (!cmd.resp_pkt) | ||
1161 | return; | ||
1162 | |||
1163 | len = le32_to_cpu(cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
1164 | if (len - sizeof(struct iwl_cmd_header) < sizeof(*status)) { | ||
1165 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | ||
1166 | goto out; | ||
1167 | } | ||
1168 | |||
1169 | status = (void *)cmd.resp_pkt->data; | ||
1170 | |||
1171 | if (len - sizeof(struct iwl_cmd_header) != | ||
1172 | sizeof(*status) + | ||
1173 | ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) { | ||
1174 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | ||
1175 | goto out; | ||
1176 | } | ||
1177 | |||
1178 | reasons = le32_to_cpu(status->wakeup_reasons); | ||
1179 | 1122 | ||
1180 | if (reasons == IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS) { | 1123 | if (reasons == IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS) { |
1181 | wakeup_report = NULL; | 1124 | wakeup_report = NULL; |
@@ -1238,6 +1181,12 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
1238 | pktsize -= hdrlen; | 1181 | pktsize -= hdrlen; |
1239 | 1182 | ||
1240 | if (ieee80211_has_protected(hdr->frame_control)) { | 1183 | if (ieee80211_has_protected(hdr->frame_control)) { |
1184 | /* | ||
1185 | * This is unlocked and using gtk_i(c)vlen, | ||
1186 | * but since everything is under RTNL still | ||
1187 | * that's not really a problem - changing | ||
1188 | * it would be difficult. | ||
1189 | */ | ||
1241 | if (is_multicast_ether_addr(hdr->addr1)) { | 1190 | if (is_multicast_ether_addr(hdr->addr1)) { |
1242 | ivlen = mvm->gtk_ivlen; | 1191 | ivlen = mvm->gtk_ivlen; |
1243 | icvlen += mvm->gtk_icvlen; | 1192 | icvlen += mvm->gtk_icvlen; |
@@ -1288,9 +1237,82 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
1288 | report: | 1237 | report: |
1289 | ieee80211_report_wowlan_wakeup(vif, wakeup_report, GFP_KERNEL); | 1238 | ieee80211_report_wowlan_wakeup(vif, wakeup_report, GFP_KERNEL); |
1290 | kfree_skb(pkt); | 1239 | kfree_skb(pkt); |
1240 | } | ||
1291 | 1241 | ||
1292 | out: | 1242 | /* releases the MVM mutex */ |
1243 | static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | ||
1244 | struct ieee80211_vif *vif) | ||
1245 | { | ||
1246 | u32 base = mvm->error_event_table; | ||
1247 | struct error_table_start { | ||
1248 | /* cf. struct iwl_error_event_table */ | ||
1249 | u32 valid; | ||
1250 | u32 error_id; | ||
1251 | } err_info; | ||
1252 | struct iwl_host_cmd cmd = { | ||
1253 | .id = WOWLAN_GET_STATUSES, | ||
1254 | .flags = CMD_SYNC | CMD_WANT_SKB, | ||
1255 | }; | ||
1256 | struct iwl_wowlan_status *status; | ||
1257 | int ret, len; | ||
1258 | |||
1259 | iwl_trans_read_mem_bytes(mvm->trans, base, | ||
1260 | &err_info, sizeof(err_info)); | ||
1261 | |||
1262 | if (err_info.valid) { | ||
1263 | IWL_INFO(mvm, "error table is valid (%d)\n", | ||
1264 | err_info.valid); | ||
1265 | if (err_info.error_id == RF_KILL_INDICATOR_FOR_WOWLAN) { | ||
1266 | struct cfg80211_wowlan_wakeup wakeup = { | ||
1267 | .rfkill_release = true, | ||
1268 | }; | ||
1269 | ieee80211_report_wowlan_wakeup(vif, &wakeup, | ||
1270 | GFP_KERNEL); | ||
1271 | } | ||
1272 | goto out_unlock; | ||
1273 | } | ||
1274 | |||
1275 | /* only for tracing for now */ | ||
1276 | ret = iwl_mvm_send_cmd_pdu(mvm, OFFLOADS_QUERY_CMD, CMD_SYNC, 0, NULL); | ||
1277 | if (ret) | ||
1278 | IWL_ERR(mvm, "failed to query offload statistics (%d)\n", ret); | ||
1279 | |||
1280 | ret = iwl_mvm_send_cmd(mvm, &cmd); | ||
1281 | if (ret) { | ||
1282 | IWL_ERR(mvm, "failed to query status (%d)\n", ret); | ||
1283 | goto out_unlock; | ||
1284 | } | ||
1285 | |||
1286 | /* RF-kill already asserted again... */ | ||
1287 | if (!cmd.resp_pkt) | ||
1288 | goto out_unlock; | ||
1289 | |||
1290 | len = le32_to_cpu(cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
1291 | if (len - sizeof(struct iwl_cmd_header) < sizeof(*status)) { | ||
1292 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | ||
1293 | goto out_free_resp; | ||
1294 | } | ||
1295 | |||
1296 | status = (void *)cmd.resp_pkt->data; | ||
1297 | |||
1298 | if (len - sizeof(struct iwl_cmd_header) != | ||
1299 | sizeof(*status) + | ||
1300 | ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) { | ||
1301 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | ||
1302 | goto out_free_resp; | ||
1303 | } | ||
1304 | |||
1305 | /* now we have all the data we need, unlock to avoid mac80211 issues */ | ||
1306 | mutex_unlock(&mvm->mutex); | ||
1307 | |||
1308 | iwl_mvm_report_wakeup_reasons(mvm, vif, status); | ||
1309 | iwl_free_resp(&cmd); | ||
1310 | return; | ||
1311 | |||
1312 | out_free_resp: | ||
1293 | iwl_free_resp(&cmd); | 1313 | iwl_free_resp(&cmd); |
1314 | out_unlock: | ||
1315 | mutex_unlock(&mvm->mutex); | ||
1294 | } | 1316 | } |
1295 | 1317 | ||
1296 | static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) | 1318 | static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) |
@@ -1347,10 +1369,13 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | |||
1347 | iwl_mvm_read_d3_sram(mvm); | 1369 | iwl_mvm_read_d3_sram(mvm); |
1348 | 1370 | ||
1349 | iwl_mvm_query_wakeup_reasons(mvm, vif); | 1371 | iwl_mvm_query_wakeup_reasons(mvm, vif); |
1372 | /* has unlocked the mutex, so skip that */ | ||
1373 | goto out; | ||
1350 | 1374 | ||
1351 | out_unlock: | 1375 | out_unlock: |
1352 | mutex_unlock(&mvm->mutex); | 1376 | mutex_unlock(&mvm->mutex); |
1353 | 1377 | ||
1378 | out: | ||
1354 | if (!test && vif) | 1379 | if (!test && vif) |
1355 | ieee80211_resume_disconnect(vif); | 1380 | ieee80211_resume_disconnect(vif); |
1356 | 1381 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index cc157734eb21..aac81b8984b0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -352,6 +352,10 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, | |||
352 | IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val); | 352 | IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val); |
353 | dbgfs_pm->lprx_rssi_threshold = val; | 353 | dbgfs_pm->lprx_rssi_threshold = val; |
354 | break; | 354 | break; |
355 | case MVM_DEBUGFS_PM_SNOOZE_ENABLE: | ||
356 | IWL_DEBUG_POWER(mvm, "snooze_enable=%d\n", val); | ||
357 | dbgfs_pm->snooze_ena = val; | ||
358 | break; | ||
355 | } | 359 | } |
356 | } | 360 | } |
357 | 361 | ||
@@ -405,6 +409,10 @@ static ssize_t iwl_dbgfs_pm_params_write(struct file *file, | |||
405 | POWER_LPRX_RSSI_THRESHOLD_MIN) | 409 | POWER_LPRX_RSSI_THRESHOLD_MIN) |
406 | return -EINVAL; | 410 | return -EINVAL; |
407 | param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD; | 411 | param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD; |
412 | } else if (!strncmp("snooze_enable=", buf, 14)) { | ||
413 | if (sscanf(buf + 14, "%d", &val) != 1) | ||
414 | return -EINVAL; | ||
415 | param = MVM_DEBUGFS_PM_SNOOZE_ENABLE; | ||
408 | } else { | 416 | } else { |
409 | return -EINVAL; | 417 | return -EINVAL; |
410 | } | 418 | } |
@@ -424,7 +432,7 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file, | |||
424 | struct ieee80211_vif *vif = file->private_data; | 432 | struct ieee80211_vif *vif = file->private_data; |
425 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 433 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
426 | struct iwl_mvm *mvm = mvmvif->dbgfs_data; | 434 | struct iwl_mvm *mvm = mvmvif->dbgfs_data; |
427 | char buf[256]; | 435 | char buf[512]; |
428 | int bufsz = sizeof(buf); | 436 | int bufsz = sizeof(buf); |
429 | int pos; | 437 | int pos; |
430 | 438 | ||
@@ -895,10 +903,7 @@ static ssize_t iwl_dbgfs_bf_params_write(struct file *file, | |||
895 | if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value) { | 903 | if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value) { |
896 | ret = iwl_mvm_disable_beacon_filter(mvm, vif); | 904 | ret = iwl_mvm_disable_beacon_filter(mvm, vif); |
897 | } else { | 905 | } else { |
898 | if (mvmvif->bf_enabled) | 906 | ret = iwl_mvm_enable_beacon_filter(mvm, vif); |
899 | ret = iwl_mvm_enable_beacon_filter(mvm, vif); | ||
900 | else | ||
901 | ret = iwl_mvm_disable_beacon_filter(mvm, vif); | ||
902 | } | 907 | } |
903 | mutex_unlock(&mvm->mutex); | 908 | mutex_unlock(&mvm->mutex); |
904 | 909 | ||
@@ -923,7 +928,7 @@ static ssize_t iwl_dbgfs_bf_params_read(struct file *file, | |||
923 | }; | 928 | }; |
924 | 929 | ||
925 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); | 930 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); |
926 | if (mvmvif->bf_enabled) | 931 | if (mvmvif->bf_data.bf_enabled) |
927 | cmd.bf_enable_beacon_filter = cpu_to_le32(1); | 932 | cmd.bf_enable_beacon_filter = cpu_to_le32(1); |
928 | else | 933 | else |
929 | cmd.bf_enable_beacon_filter = 0; | 934 | cmd.bf_enable_beacon_filter = 0; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index 060e630b3d82..8e7ab41079ca 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | |||
@@ -155,8 +155,12 @@ struct iwl_powertable_cmd { | |||
155 | * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled. | 155 | * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled. |
156 | * Default: 80dbm | 156 | * Default: 80dbm |
157 | * @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set | 157 | * @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set |
158 | * @snooze_interval: TBD | 158 | * @snooze_interval: Maximum time between attempts to retrieve buffered data |
159 | * @snooze_window: TBD | 159 | * from the AP [msec] |
160 | * @snooze_window: A window of time in which PBW snoozing insures that all | ||
161 | * packets received. It is also the minimum time from last | ||
162 | * received unicast RX packet, before client stops snoozing | ||
163 | * for data. [msec] | ||
160 | * @snooze_step: TBD | 164 | * @snooze_step: TBD |
161 | * @qndp_tid: TID client shall use for uAPSD QNDP triggers | 165 | * @qndp_tid: TID client shall use for uAPSD QNDP triggers |
162 | * @uapsd_ac_flags: Set trigger-enabled and delivery-enabled indication for | 166 | * @uapsd_ac_flags: Set trigger-enabled and delivery-enabled indication for |
@@ -164,10 +168,10 @@ struct iwl_powertable_cmd { | |||
164 | * Use IEEE80211_WMM_IE_STA_QOSINFO_AC* for correct values. | 168 | * Use IEEE80211_WMM_IE_STA_QOSINFO_AC* for correct values. |
165 | * @uapsd_max_sp: Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct | 169 | * @uapsd_max_sp: Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct |
166 | * values. | 170 | * values. |
167 | * @heavy_traffic_thr_tx_pkts: TX threshold measured in number of packets | 171 | * @heavy_tx_thld_packets: TX threshold measured in number of packets |
168 | * @heavy_traffic_thr_rx_pkts: RX threshold measured in number of packets | 172 | * @heavy_rx_thld_packets: RX threshold measured in number of packets |
169 | * @heavy_traffic_thr_tx_load: TX threshold measured in load's percentage | 173 | * @heavy_tx_thld_percentage: TX threshold measured in load's percentage |
170 | * @heavy_traffic_thr_rx_load: RX threshold measured in load's percentage | 174 | * @heavy_rx_thld_percentage: RX threshold measured in load's percentage |
171 | * @limited_ps_threshold: | 175 | * @limited_ps_threshold: |
172 | */ | 176 | */ |
173 | struct iwl_mac_power_cmd { | 177 | struct iwl_mac_power_cmd { |
@@ -189,10 +193,10 @@ struct iwl_mac_power_cmd { | |||
189 | u8 qndp_tid; | 193 | u8 qndp_tid; |
190 | u8 uapsd_ac_flags; | 194 | u8 uapsd_ac_flags; |
191 | u8 uapsd_max_sp; | 195 | u8 uapsd_max_sp; |
192 | u8 heavy_traffic_threshold_tx_packets; | 196 | u8 heavy_tx_thld_packets; |
193 | u8 heavy_traffic_threshold_rx_packets; | 197 | u8 heavy_rx_thld_packets; |
194 | u8 heavy_traffic_threshold_tx_percentage; | 198 | u8 heavy_tx_thld_percentage; |
195 | u8 heavy_traffic_threshold_rx_percentage; | 199 | u8 heavy_rx_thld_percentage; |
196 | u8 limited_ps_threshold; | 200 | u8 limited_ps_threshold; |
197 | u8 reserved; | 201 | u8 reserved; |
198 | } __packed; | 202 | } __packed; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 55854a309f94..66264cc5a016 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -499,71 +499,199 @@ enum iwl_time_event_type { | |||
499 | TE_MAX | 499 | TE_MAX |
500 | }; /* MAC_EVENT_TYPE_API_E_VER_1 */ | 500 | }; /* MAC_EVENT_TYPE_API_E_VER_1 */ |
501 | 501 | ||
502 | |||
503 | |||
504 | /* Time event - defines for command API v1 */ | ||
505 | |||
506 | /* | ||
507 | * @TE_V1_FRAG_NONE: fragmentation of the time event is NOT allowed. | ||
508 | * @TE_V1_FRAG_SINGLE: fragmentation of the time event is allowed, but only | ||
509 | * the first fragment is scheduled. | ||
510 | * @TE_V1_FRAG_DUAL: fragmentation of the time event is allowed, but only | ||
511 | * the first 2 fragments are scheduled. | ||
512 | * @TE_V1_FRAG_ENDLESS: fragmentation of the time event is allowed, and any | ||
513 | * number of fragments are valid. | ||
514 | * | ||
515 | * Other than the constant defined above, specifying a fragmentation value 'x' | ||
516 | * means that the event can be fragmented but only the first 'x' will be | ||
517 | * scheduled. | ||
518 | */ | ||
519 | enum { | ||
520 | TE_V1_FRAG_NONE = 0, | ||
521 | TE_V1_FRAG_SINGLE = 1, | ||
522 | TE_V1_FRAG_DUAL = 2, | ||
523 | TE_V1_FRAG_ENDLESS = 0xffffffff | ||
524 | }; | ||
525 | |||
526 | /* If a Time Event can be fragmented, this is the max number of fragments */ | ||
527 | #define TE_V1_FRAG_MAX_MSK 0x0fffffff | ||
528 | /* Repeat the time event endlessly (until removed) */ | ||
529 | #define TE_V1_REPEAT_ENDLESS 0xffffffff | ||
530 | /* If a Time Event has bounded repetitions, this is the maximal value */ | ||
531 | #define TE_V1_REPEAT_MAX_MSK_V1 0x0fffffff | ||
532 | |||
502 | /* Time Event dependencies: none, on another TE, or in a specific time */ | 533 | /* Time Event dependencies: none, on another TE, or in a specific time */ |
503 | enum { | 534 | enum { |
504 | TE_INDEPENDENT = 0, | 535 | TE_V1_INDEPENDENT = 0, |
505 | TE_DEP_OTHER = 1, | 536 | TE_V1_DEP_OTHER = BIT(0), |
506 | TE_DEP_TSF = 2, | 537 | TE_V1_DEP_TSF = BIT(1), |
507 | TE_EVENT_SOCIOPATHIC = 4, | 538 | TE_V1_EVENT_SOCIOPATHIC = BIT(2), |
508 | }; /* MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */ | 539 | }; /* MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */ |
540 | |||
509 | /* | 541 | /* |
542 | * @TE_V1_NOTIF_NONE: no notifications | ||
543 | * @TE_V1_NOTIF_HOST_EVENT_START: request/receive notification on event start | ||
544 | * @TE_V1_NOTIF_HOST_EVENT_END:request/receive notification on event end | ||
545 | * @TE_V1_NOTIF_INTERNAL_EVENT_START: internal FW use | ||
546 | * @TE_V1_NOTIF_INTERNAL_EVENT_END: internal FW use. | ||
547 | * @TE_V1_NOTIF_HOST_FRAG_START: request/receive notification on frag start | ||
548 | * @TE_V1_NOTIF_HOST_FRAG_END:request/receive notification on frag end | ||
549 | * @TE_V1_NOTIF_INTERNAL_FRAG_START: internal FW use. | ||
550 | * @TE_V1_NOTIF_INTERNAL_FRAG_END: internal FW use. | ||
551 | * | ||
510 | * Supported Time event notifications configuration. | 552 | * Supported Time event notifications configuration. |
511 | * A notification (both event and fragment) includes a status indicating weather | 553 | * A notification (both event and fragment) includes a status indicating weather |
512 | * the FW was able to schedule the event or not. For fragment start/end | 554 | * the FW was able to schedule the event or not. For fragment start/end |
513 | * notification the status is always success. There is no start/end fragment | 555 | * notification the status is always success. There is no start/end fragment |
514 | * notification for monolithic events. | 556 | * notification for monolithic events. |
515 | * | ||
516 | * @TE_NOTIF_NONE: no notifications | ||
517 | * @TE_NOTIF_HOST_EVENT_START: request/receive notification on event start | ||
518 | * @TE_NOTIF_HOST_EVENT_END:request/receive notification on event end | ||
519 | * @TE_NOTIF_INTERNAL_EVENT_START: internal FW use | ||
520 | * @TE_NOTIF_INTERNAL_EVENT_END: internal FW use. | ||
521 | * @TE_NOTIF_HOST_FRAG_START: request/receive notification on frag start | ||
522 | * @TE_NOTIF_HOST_FRAG_END:request/receive notification on frag end | ||
523 | * @TE_NOTIF_INTERNAL_FRAG_START: internal FW use. | ||
524 | * @TE_NOTIF_INTERNAL_FRAG_END: internal FW use. | ||
525 | */ | 557 | */ |
526 | enum { | 558 | enum { |
527 | TE_NOTIF_NONE = 0, | 559 | TE_V1_NOTIF_NONE = 0, |
528 | TE_NOTIF_HOST_EVENT_START = 0x1, | 560 | TE_V1_NOTIF_HOST_EVENT_START = BIT(0), |
529 | TE_NOTIF_HOST_EVENT_END = 0x2, | 561 | TE_V1_NOTIF_HOST_EVENT_END = BIT(1), |
530 | TE_NOTIF_INTERNAL_EVENT_START = 0x4, | 562 | TE_V1_NOTIF_INTERNAL_EVENT_START = BIT(2), |
531 | TE_NOTIF_INTERNAL_EVENT_END = 0x8, | 563 | TE_V1_NOTIF_INTERNAL_EVENT_END = BIT(3), |
532 | TE_NOTIF_HOST_FRAG_START = 0x10, | 564 | TE_V1_NOTIF_HOST_FRAG_START = BIT(4), |
533 | TE_NOTIF_HOST_FRAG_END = 0x20, | 565 | TE_V1_NOTIF_HOST_FRAG_END = BIT(5), |
534 | TE_NOTIF_INTERNAL_FRAG_START = 0x40, | 566 | TE_V1_NOTIF_INTERNAL_FRAG_START = BIT(6), |
535 | TE_NOTIF_INTERNAL_FRAG_END = 0x80 | 567 | TE_V1_NOTIF_INTERNAL_FRAG_END = BIT(7), |
536 | }; /* MAC_EVENT_ACTION_API_E_VER_2 */ | 568 | }; /* MAC_EVENT_ACTION_API_E_VER_2 */ |
537 | 569 | ||
570 | |||
571 | /** | ||
572 | * struct iwl_time_event_cmd_api_v1 - configuring Time Events | ||
573 | * with struct MAC_TIME_EVENT_DATA_API_S_VER_1 (see also | ||
574 | * with version 2. determined by IWL_UCODE_TLV_FLAGS) | ||
575 | * ( TIME_EVENT_CMD = 0x29 ) | ||
576 | * @id_and_color: ID and color of the relevant MAC | ||
577 | * @action: action to perform, one of FW_CTXT_ACTION_* | ||
578 | * @id: this field has two meanings, depending on the action: | ||
579 | * If the action is ADD, then it means the type of event to add. | ||
580 | * For all other actions it is the unique event ID assigned when the | ||
581 | * event was added by the FW. | ||
582 | * @apply_time: When to start the Time Event (in GP2) | ||
583 | * @max_delay: maximum delay to event's start (apply time), in TU | ||
584 | * @depends_on: the unique ID of the event we depend on (if any) | ||
585 | * @interval: interval between repetitions, in TU | ||
586 | * @interval_reciprocal: 2^32 / interval | ||
587 | * @duration: duration of event in TU | ||
588 | * @repeat: how many repetitions to do, can be TE_REPEAT_ENDLESS | ||
589 | * @dep_policy: one of TE_V1_INDEPENDENT, TE_V1_DEP_OTHER, TE_V1_DEP_TSF | ||
590 | * and TE_V1_EVENT_SOCIOPATHIC | ||
591 | * @is_present: 0 or 1, are we present or absent during the Time Event | ||
592 | * @max_frags: maximal number of fragments the Time Event can be divided to | ||
593 | * @notify: notifications using TE_V1_NOTIF_* (whom to notify when) | ||
594 | */ | ||
595 | struct iwl_time_event_cmd_v1 { | ||
596 | /* COMMON_INDEX_HDR_API_S_VER_1 */ | ||
597 | __le32 id_and_color; | ||
598 | __le32 action; | ||
599 | __le32 id; | ||
600 | /* MAC_TIME_EVENT_DATA_API_S_VER_1 */ | ||
601 | __le32 apply_time; | ||
602 | __le32 max_delay; | ||
603 | __le32 dep_policy; | ||
604 | __le32 depends_on; | ||
605 | __le32 is_present; | ||
606 | __le32 max_frags; | ||
607 | __le32 interval; | ||
608 | __le32 interval_reciprocal; | ||
609 | __le32 duration; | ||
610 | __le32 repeat; | ||
611 | __le32 notify; | ||
612 | } __packed; /* MAC_TIME_EVENT_CMD_API_S_VER_1 */ | ||
613 | |||
614 | |||
615 | /* Time event - defines for command API v2 */ | ||
616 | |||
538 | /* | 617 | /* |
539 | * @TE_FRAG_NONE: fragmentation of the time event is NOT allowed. | 618 | * @TE_V2_FRAG_NONE: fragmentation of the time event is NOT allowed. |
540 | * @TE_FRAG_SINGLE: fragmentation of the time event is allowed, but only | 619 | * @TE_V2_FRAG_SINGLE: fragmentation of the time event is allowed, but only |
541 | * the first fragment is scheduled. | 620 | * the first fragment is scheduled. |
542 | * @TE_FRAG_DUAL: fragmentation of the time event is allowed, but only | 621 | * @TE_V2_FRAG_DUAL: fragmentation of the time event is allowed, but only |
543 | * the first 2 fragments are scheduled. | 622 | * the first 2 fragments are scheduled. |
544 | * @TE_FRAG_ENDLESS: fragmentation of the time event is allowed, and any number | 623 | * @TE_V2_FRAG_ENDLESS: fragmentation of the time event is allowed, and any |
545 | * of fragments are valid. | 624 | * number of fragments are valid. |
546 | * | 625 | * |
547 | * Other than the constant defined above, specifying a fragmentation value 'x' | 626 | * Other than the constant defined above, specifying a fragmentation value 'x' |
548 | * means that the event can be fragmented but only the first 'x' will be | 627 | * means that the event can be fragmented but only the first 'x' will be |
549 | * scheduled. | 628 | * scheduled. |
550 | */ | 629 | */ |
551 | enum { | 630 | enum { |
552 | TE_FRAG_NONE = 0, | 631 | TE_V2_FRAG_NONE = 0, |
553 | TE_FRAG_SINGLE = 1, | 632 | TE_V2_FRAG_SINGLE = 1, |
554 | TE_FRAG_DUAL = 2, | 633 | TE_V2_FRAG_DUAL = 2, |
555 | TE_FRAG_ENDLESS = 0xffffffff | 634 | TE_V2_FRAG_MAX = 0xfe, |
635 | TE_V2_FRAG_ENDLESS = 0xff | ||
556 | }; | 636 | }; |
557 | 637 | ||
558 | /* Repeat the time event endlessly (until removed) */ | 638 | /* Repeat the time event endlessly (until removed) */ |
559 | #define TE_REPEAT_ENDLESS (0xffffffff) | 639 | #define TE_V2_REPEAT_ENDLESS 0xff |
560 | /* If a Time Event has bounded repetitions, this is the maximal value */ | 640 | /* If a Time Event has bounded repetitions, this is the maximal value */ |
561 | #define TE_REPEAT_MAX_MSK (0x0fffffff) | 641 | #define TE_V2_REPEAT_MAX 0xfe |
562 | /* If a Time Event can be fragmented, this is the max number of fragments */ | 642 | |
563 | #define TE_FRAG_MAX_MSK (0x0fffffff) | 643 | #define TE_V2_PLACEMENT_POS 12 |
644 | #define TE_V2_ABSENCE_POS 15 | ||
645 | |||
646 | /* Time event policy values (for time event cmd api v2) | ||
647 | * A notification (both event and fragment) includes a status indicating weather | ||
648 | * the FW was able to schedule the event or not. For fragment start/end | ||
649 | * notification the status is always success. There is no start/end fragment | ||
650 | * notification for monolithic events. | ||
651 | * | ||
652 | * @TE_V2_DEFAULT_POLICY: independent, social, present, unoticable | ||
653 | * @TE_V2_NOTIF_HOST_EVENT_START: request/receive notification on event start | ||
654 | * @TE_V2_NOTIF_HOST_EVENT_END:request/receive notification on event end | ||
655 | * @TE_V2_NOTIF_INTERNAL_EVENT_START: internal FW use | ||
656 | * @TE_V2_NOTIF_INTERNAL_EVENT_END: internal FW use. | ||
657 | * @TE_V2_NOTIF_HOST_FRAG_START: request/receive notification on frag start | ||
658 | * @TE_V2_NOTIF_HOST_FRAG_END:request/receive notification on frag end | ||
659 | * @TE_V2_NOTIF_INTERNAL_FRAG_START: internal FW use. | ||
660 | * @TE_V2_NOTIF_INTERNAL_FRAG_END: internal FW use. | ||
661 | * @TE_V2_DEP_OTHER: depends on another time event | ||
662 | * @TE_V2_DEP_TSF: depends on a specific time | ||
663 | * @TE_V2_EVENT_SOCIOPATHIC: can't co-exist with other events of tha same MAC | ||
664 | * @TE_V2_ABSENCE: are we present or absent during the Time Event. | ||
665 | */ | ||
666 | enum { | ||
667 | TE_V2_DEFAULT_POLICY = 0x0, | ||
668 | |||
669 | /* notifications (event start/stop, fragment start/stop) */ | ||
670 | TE_V2_NOTIF_HOST_EVENT_START = BIT(0), | ||
671 | TE_V2_NOTIF_HOST_EVENT_END = BIT(1), | ||
672 | TE_V2_NOTIF_INTERNAL_EVENT_START = BIT(2), | ||
673 | TE_V2_NOTIF_INTERNAL_EVENT_END = BIT(3), | ||
674 | |||
675 | TE_V2_NOTIF_HOST_FRAG_START = BIT(4), | ||
676 | TE_V2_NOTIF_HOST_FRAG_END = BIT(5), | ||
677 | TE_V2_NOTIF_INTERNAL_FRAG_START = BIT(6), | ||
678 | TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7), | ||
679 | |||
680 | TE_V2_NOTIF_MSK = 0xff, | ||
681 | |||
682 | /* placement characteristics */ | ||
683 | TE_V2_DEP_OTHER = BIT(TE_V2_PLACEMENT_POS), | ||
684 | TE_V2_DEP_TSF = BIT(TE_V2_PLACEMENT_POS + 1), | ||
685 | TE_V2_EVENT_SOCIOPATHIC = BIT(TE_V2_PLACEMENT_POS + 2), | ||
686 | |||
687 | /* are we present or absent during the Time Event. */ | ||
688 | TE_V2_ABSENCE = BIT(TE_V2_ABSENCE_POS), | ||
689 | }; | ||
564 | 690 | ||
565 | /** | 691 | /** |
566 | * struct iwl_time_event_cmd - configuring Time Events | 692 | * struct iwl_time_event_cmd_api_v2 - configuring Time Events |
693 | * with struct MAC_TIME_EVENT_DATA_API_S_VER_2 (see also | ||
694 | * with version 1. determined by IWL_UCODE_TLV_FLAGS) | ||
567 | * ( TIME_EVENT_CMD = 0x29 ) | 695 | * ( TIME_EVENT_CMD = 0x29 ) |
568 | * @id_and_color: ID and color of the relevant MAC | 696 | * @id_and_color: ID and color of the relevant MAC |
569 | * @action: action to perform, one of FW_CTXT_ACTION_* | 697 | * @action: action to perform, one of FW_CTXT_ACTION_* |
@@ -575,32 +703,30 @@ enum { | |||
575 | * @max_delay: maximum delay to event's start (apply time), in TU | 703 | * @max_delay: maximum delay to event's start (apply time), in TU |
576 | * @depends_on: the unique ID of the event we depend on (if any) | 704 | * @depends_on: the unique ID of the event we depend on (if any) |
577 | * @interval: interval between repetitions, in TU | 705 | * @interval: interval between repetitions, in TU |
578 | * @interval_reciprocal: 2^32 / interval | ||
579 | * @duration: duration of event in TU | 706 | * @duration: duration of event in TU |
580 | * @repeat: how many repetitions to do, can be TE_REPEAT_ENDLESS | 707 | * @repeat: how many repetitions to do, can be TE_REPEAT_ENDLESS |
581 | * @dep_policy: one of TE_INDEPENDENT, TE_DEP_OTHER, TE_DEP_TSF | ||
582 | * @is_present: 0 or 1, are we present or absent during the Time Event | ||
583 | * @max_frags: maximal number of fragments the Time Event can be divided to | 708 | * @max_frags: maximal number of fragments the Time Event can be divided to |
584 | * @notify: notifications using TE_NOTIF_* (whom to notify when) | 709 | * @policy: defines whether uCode shall notify the host or other uCode modules |
710 | * on event and/or fragment start and/or end | ||
711 | * using one of TE_INDEPENDENT, TE_DEP_OTHER, TE_DEP_TSF | ||
712 | * TE_EVENT_SOCIOPATHIC | ||
713 | * using TE_ABSENCE and using TE_NOTIF_* | ||
585 | */ | 714 | */ |
586 | struct iwl_time_event_cmd { | 715 | struct iwl_time_event_cmd_v2 { |
587 | /* COMMON_INDEX_HDR_API_S_VER_1 */ | 716 | /* COMMON_INDEX_HDR_API_S_VER_1 */ |
588 | __le32 id_and_color; | 717 | __le32 id_and_color; |
589 | __le32 action; | 718 | __le32 action; |
590 | __le32 id; | 719 | __le32 id; |
591 | /* MAC_TIME_EVENT_DATA_API_S_VER_1 */ | 720 | /* MAC_TIME_EVENT_DATA_API_S_VER_2 */ |
592 | __le32 apply_time; | 721 | __le32 apply_time; |
593 | __le32 max_delay; | 722 | __le32 max_delay; |
594 | __le32 dep_policy; | ||
595 | __le32 depends_on; | 723 | __le32 depends_on; |
596 | __le32 is_present; | ||
597 | __le32 max_frags; | ||
598 | __le32 interval; | 724 | __le32 interval; |
599 | __le32 interval_reciprocal; | ||
600 | __le32 duration; | 725 | __le32 duration; |
601 | __le32 repeat; | 726 | u8 repeat; |
602 | __le32 notify; | 727 | u8 max_frags; |
603 | } __packed; /* MAC_TIME_EVENT_CMD_API_S_VER_1 */ | 728 | __le16 policy; |
729 | } __packed; /* MAC_TIME_EVENT_CMD_API_S_VER_2 */ | ||
604 | 730 | ||
605 | /** | 731 | /** |
606 | * struct iwl_time_event_resp - response structure to iwl_time_event_cmd | 732 | * struct iwl_time_event_resp - response structure to iwl_time_event_cmd |
@@ -1195,7 +1321,7 @@ struct mvm_statistics_general { | |||
1195 | struct mvm_statistics_general_common common; | 1321 | struct mvm_statistics_general_common common; |
1196 | __le32 beacon_filtered; | 1322 | __le32 beacon_filtered; |
1197 | __le32 missed_beacons; | 1323 | __le32 missed_beacons; |
1198 | __s8 beacon_filter_everage_energy; | 1324 | __s8 beacon_filter_average_energy; |
1199 | __s8 beacon_filter_reason; | 1325 | __s8 beacon_filter_reason; |
1200 | __s8 beacon_filter_current_energy; | 1326 | __s8 beacon_filter_current_energy; |
1201 | __s8 beacon_filter_reserved; | 1327 | __s8 beacon_filter_reserved; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 995f0250105e..9833cdf6177c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -155,7 +155,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
155 | IEEE80211_HW_TIMING_BEACON_ONLY | | 155 | IEEE80211_HW_TIMING_BEACON_ONLY | |
156 | IEEE80211_HW_CONNECTION_MONITOR | | 156 | IEEE80211_HW_CONNECTION_MONITOR | |
157 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 157 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
158 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | 158 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | |
159 | IEEE80211_HW_SUPPORTS_UAPSD; | ||
159 | 160 | ||
160 | hw->queues = IWL_MVM_FIRST_AGG_QUEUE; | 161 | hw->queues = IWL_MVM_FIRST_AGG_QUEUE; |
161 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; | 162 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; |
@@ -190,6 +191,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
190 | 191 | ||
191 | hw->wiphy->max_remain_on_channel_duration = 10000; | 192 | hw->wiphy->max_remain_on_channel_duration = 10000; |
192 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | 193 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; |
194 | hw->uapsd_queues = IWL_UAPSD_AC_INFO; | ||
195 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; | ||
193 | 196 | ||
194 | /* Extract MAC address */ | 197 | /* Extract MAC address */ |
195 | memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN); | 198 | memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN); |
@@ -577,7 +580,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
577 | vif->type == NL80211_IFTYPE_STATION && !vif->p2p && | 580 | vif->type == NL80211_IFTYPE_STATION && !vif->p2p && |
578 | mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED){ | 581 | mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED){ |
579 | mvm->bf_allowed_vif = mvmvif; | 582 | mvm->bf_allowed_vif = mvmvif; |
580 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; | 583 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | |
584 | IEEE80211_VIF_SUPPORTS_CQM_RSSI; | ||
581 | } | 585 | } |
582 | 586 | ||
583 | /* | 587 | /* |
@@ -617,7 +621,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
617 | out_free_bf: | 621 | out_free_bf: |
618 | if (mvm->bf_allowed_vif == mvmvif) { | 622 | if (mvm->bf_allowed_vif == mvmvif) { |
619 | mvm->bf_allowed_vif = NULL; | 623 | mvm->bf_allowed_vif = NULL; |
620 | vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; | 624 | vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER | |
625 | IEEE80211_VIF_SUPPORTS_CQM_RSSI); | ||
621 | } | 626 | } |
622 | out_remove_mac: | 627 | out_remove_mac: |
623 | mvmvif->phy_ctxt = NULL; | 628 | mvmvif->phy_ctxt = NULL; |
@@ -683,7 +688,8 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | |||
683 | 688 | ||
684 | if (mvm->bf_allowed_vif == mvmvif) { | 689 | if (mvm->bf_allowed_vif == mvmvif) { |
685 | mvm->bf_allowed_vif = NULL; | 690 | mvm->bf_allowed_vif = NULL; |
686 | vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; | 691 | vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER | |
692 | IEEE80211_VIF_SUPPORTS_CQM_RSSI); | ||
687 | } | 693 | } |
688 | 694 | ||
689 | iwl_mvm_vif_dbgfs_clean(mvm, vif); | 695 | iwl_mvm_vif_dbgfs_clean(mvm, vif); |
@@ -801,6 +807,10 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
801 | if (ret) | 807 | if (ret) |
802 | IWL_ERR(mvm, "failed to update quotas\n"); | 808 | IWL_ERR(mvm, "failed to update quotas\n"); |
803 | } | 809 | } |
810 | |||
811 | /* reset rssi values */ | ||
812 | mvmvif->bf_data.ave_beacon_signal = 0; | ||
813 | |||
804 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD)) { | 814 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD)) { |
805 | /* Workaround for FW bug, otherwise FW disables device | 815 | /* Workaround for FW bug, otherwise FW disables device |
806 | * power save upon disassociation | 816 | * power save upon disassociation |
@@ -817,7 +827,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
817 | */ | 827 | */ |
818 | iwl_mvm_remove_time_event(mvm, mvmvif, | 828 | iwl_mvm_remove_time_event(mvm, mvmvif, |
819 | &mvmvif->time_event_data); | 829 | &mvmvif->time_event_data); |
820 | } else if (changes & BSS_CHANGED_PS) { | 830 | } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_QOS)) { |
821 | ret = iwl_mvm_power_update_mode(mvm, vif); | 831 | ret = iwl_mvm_power_update_mode(mvm, vif); |
822 | if (ret) | 832 | if (ret) |
823 | IWL_ERR(mvm, "failed to update power mode\n"); | 833 | IWL_ERR(mvm, "failed to update power mode\n"); |
@@ -827,6 +837,15 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
827 | bss_conf->txpower); | 837 | bss_conf->txpower); |
828 | iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower); | 838 | iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower); |
829 | } | 839 | } |
840 | |||
841 | if (changes & BSS_CHANGED_CQM) { | ||
842 | IWL_DEBUG_MAC80211(mvm, "cqm info_changed"); | ||
843 | /* reset cqm events tracking */ | ||
844 | mvmvif->bf_data.last_cqm_event = 0; | ||
845 | ret = iwl_mvm_update_beacon_filter(mvm, vif); | ||
846 | if (ret) | ||
847 | IWL_ERR(mvm, "failed to update CQM thresholds\n"); | ||
848 | } | ||
830 | } | 849 | } |
831 | 850 | ||
832 | static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 851 | static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 4173bb57585f..b0389279cc1e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -153,6 +153,11 @@ enum iwl_power_scheme { | |||
153 | }; | 153 | }; |
154 | 154 | ||
155 | #define IWL_CONN_MAX_LISTEN_INTERVAL 70 | 155 | #define IWL_CONN_MAX_LISTEN_INTERVAL 70 |
156 | #define IWL_UAPSD_AC_INFO (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\ | ||
157 | IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\ | ||
158 | IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\ | ||
159 | IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) | ||
160 | #define IWL_UAPSD_MAX_SP IEEE80211_WMM_IE_STA_QOSINFO_SP_2 | ||
156 | 161 | ||
157 | struct iwl_mvm_power_ops { | 162 | struct iwl_mvm_power_ops { |
158 | int (*power_update_mode)(struct iwl_mvm *mvm, | 163 | int (*power_update_mode)(struct iwl_mvm *mvm, |
@@ -175,6 +180,7 @@ enum iwl_dbgfs_pm_mask { | |||
175 | MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5), | 180 | MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5), |
176 | MVM_DEBUGFS_PM_LPRX_ENA = BIT(6), | 181 | MVM_DEBUGFS_PM_LPRX_ENA = BIT(6), |
177 | MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7), | 182 | MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7), |
183 | MVM_DEBUGFS_PM_SNOOZE_ENABLE = BIT(8), | ||
178 | }; | 184 | }; |
179 | 185 | ||
180 | struct iwl_dbgfs_pm { | 186 | struct iwl_dbgfs_pm { |
@@ -186,6 +192,7 @@ struct iwl_dbgfs_pm { | |||
186 | bool disable_power_off; | 192 | bool disable_power_off; |
187 | bool lprx_ena; | 193 | bool lprx_ena; |
188 | u32 lprx_rssi_threshold; | 194 | u32 lprx_rssi_threshold; |
195 | bool snooze_ena; | ||
189 | int mask; | 196 | int mask; |
190 | }; | 197 | }; |
191 | 198 | ||
@@ -228,6 +235,21 @@ enum iwl_mvm_smps_type_request { | |||
228 | }; | 235 | }; |
229 | 236 | ||
230 | /** | 237 | /** |
238 | * struct iwl_mvm_vif_bf_data - beacon filtering related data | ||
239 | * @bf_enabled: indicates if beacon filtering is enabled | ||
240 | * @ba_enabled: indicated if beacon abort is enabled | ||
241 | * @last_beacon_signal: last beacon rssi signal in dbm | ||
242 | * @ave_beacon_signal: average beacon signal | ||
243 | * @last_cqm_event: rssi of the last cqm event | ||
244 | */ | ||
245 | struct iwl_mvm_vif_bf_data { | ||
246 | bool bf_enabled; | ||
247 | bool ba_enabled; | ||
248 | s8 ave_beacon_signal; | ||
249 | s8 last_cqm_event; | ||
250 | }; | ||
251 | |||
252 | /** | ||
231 | * struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context | 253 | * struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context |
232 | * @id: between 0 and 3 | 254 | * @id: between 0 and 3 |
233 | * @color: to solve races upon MAC addition and removal | 255 | * @color: to solve races upon MAC addition and removal |
@@ -252,8 +274,7 @@ struct iwl_mvm_vif { | |||
252 | bool uploaded; | 274 | bool uploaded; |
253 | bool ap_active; | 275 | bool ap_active; |
254 | bool monitor_active; | 276 | bool monitor_active; |
255 | /* indicate whether beacon filtering is enabled */ | 277 | struct iwl_mvm_vif_bf_data bf_data; |
256 | bool bf_enabled; | ||
257 | 278 | ||
258 | u32 ap_beacon_time; | 279 | u32 ap_beacon_time; |
259 | 280 | ||
@@ -754,6 +775,8 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, | |||
754 | struct iwl_beacon_filter_cmd *cmd); | 775 | struct iwl_beacon_filter_cmd *cmd); |
755 | int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, | 776 | int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, |
756 | struct ieee80211_vif *vif, bool enable); | 777 | struct ieee80211_vif *vif, bool enable); |
778 | int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm, | ||
779 | struct ieee80211_vif *vif); | ||
757 | 780 | ||
758 | /* SMPS */ | 781 | /* SMPS */ |
759 | void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 782 | void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 4e7c9f245846..21407a353a3b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -110,6 +110,23 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, | |||
110 | return ret; | 110 | return ret; |
111 | } | 111 | } |
112 | 112 | ||
113 | static | ||
114 | void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm, | ||
115 | struct ieee80211_vif *vif, | ||
116 | struct iwl_beacon_filter_cmd *cmd) | ||
117 | { | ||
118 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
119 | |||
120 | if (vif->bss_conf.cqm_rssi_thold) { | ||
121 | cmd->bf_energy_delta = | ||
122 | cpu_to_le32(vif->bss_conf.cqm_rssi_hyst); | ||
123 | /* fw uses an absolute value for this */ | ||
124 | cmd->bf_roaming_state = | ||
125 | cpu_to_le32(-vif->bss_conf.cqm_rssi_thold); | ||
126 | } | ||
127 | cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->bf_data.ba_enabled); | ||
128 | } | ||
129 | |||
113 | int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, | 130 | int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, |
114 | struct ieee80211_vif *vif, bool enable) | 131 | struct ieee80211_vif *vif, bool enable) |
115 | { | 132 | { |
@@ -120,12 +137,14 @@ int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, | |||
120 | .ba_enable_beacon_abort = cpu_to_le32(enable), | 137 | .ba_enable_beacon_abort = cpu_to_le32(enable), |
121 | }; | 138 | }; |
122 | 139 | ||
123 | if (!mvmvif->bf_enabled) | 140 | if (!mvmvif->bf_data.bf_enabled) |
124 | return 0; | 141 | return 0; |
125 | 142 | ||
126 | if (mvm->cur_ucode == IWL_UCODE_WOWLAN) | 143 | if (mvm->cur_ucode == IWL_UCODE_WOWLAN) |
127 | cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3); | 144 | cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3); |
128 | 145 | ||
146 | mvmvif->bf_data.ba_enabled = enable; | ||
147 | iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, &cmd); | ||
129 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); | 148 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); |
130 | return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); | 149 | return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); |
131 | } | 150 | } |
@@ -140,17 +159,30 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm, | |||
140 | IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", | 159 | IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", |
141 | le16_to_cpu(cmd->keep_alive_seconds)); | 160 | le16_to_cpu(cmd->keep_alive_seconds)); |
142 | 161 | ||
143 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) { | 162 | if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK))) { |
144 | IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n", | 163 | IWL_DEBUG_POWER(mvm, "Disable power management\n"); |
145 | le32_to_cpu(cmd->rx_data_timeout)); | 164 | return; |
146 | IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n", | 165 | } |
147 | le32_to_cpu(cmd->tx_data_timeout)); | 166 | |
148 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) | 167 | IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n", |
149 | IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n", | 168 | le32_to_cpu(cmd->rx_data_timeout)); |
150 | cmd->skip_dtim_periods); | 169 | IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n", |
151 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) | 170 | le32_to_cpu(cmd->tx_data_timeout)); |
152 | IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", | 171 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) |
153 | cmd->lprx_rssi_threshold); | 172 | IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n", |
173 | cmd->skip_dtim_periods); | ||
174 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) | ||
175 | IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", | ||
176 | cmd->lprx_rssi_threshold); | ||
177 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) { | ||
178 | IWL_DEBUG_POWER(mvm, "uAPSD enabled\n"); | ||
179 | IWL_DEBUG_POWER(mvm, "Rx timeout (uAPSD) = %u usec\n", | ||
180 | le32_to_cpu(cmd->rx_data_timeout_uapsd)); | ||
181 | IWL_DEBUG_POWER(mvm, "Tx timeout (uAPSD) = %u usec\n", | ||
182 | le32_to_cpu(cmd->tx_data_timeout_uapsd)); | ||
183 | IWL_DEBUG_POWER(mvm, "QNDP TID = %d\n", cmd->qndp_tid); | ||
184 | IWL_DEBUG_POWER(mvm, "ACs flags = 0x%x\n", cmd->uapsd_ac_flags); | ||
185 | IWL_DEBUG_POWER(mvm, "Max SP = %d\n", cmd->uapsd_max_sp); | ||
154 | } | 186 | } |
155 | } | 187 | } |
156 | 188 | ||
@@ -166,6 +198,8 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
166 | bool radar_detect = false; | 198 | bool radar_detect = false; |
167 | struct iwl_mvm_vif *mvmvif __maybe_unused = | 199 | struct iwl_mvm_vif *mvmvif __maybe_unused = |
168 | iwl_mvm_vif_from_mac80211(vif); | 200 | iwl_mvm_vif_from_mac80211(vif); |
201 | enum ieee80211_ac_numbers ac; | ||
202 | bool tid_found = false; | ||
169 | 203 | ||
170 | cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, | 204 | cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, |
171 | mvmvif->color)); | 205 | mvmvif->color)); |
@@ -235,6 +269,63 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
235 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); | 269 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); |
236 | } | 270 | } |
237 | 271 | ||
272 | for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) { | ||
273 | if (!mvmvif->queue_params[ac].uapsd) | ||
274 | continue; | ||
275 | |||
276 | cmd->flags |= cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK); | ||
277 | cmd->uapsd_ac_flags |= BIT(ac); | ||
278 | |||
279 | /* QNDP TID - the highest TID with no admission control */ | ||
280 | if (!tid_found && !mvmvif->queue_params[ac].acm) { | ||
281 | tid_found = true; | ||
282 | switch (ac) { | ||
283 | case IEEE80211_AC_VO: | ||
284 | cmd->qndp_tid = 6; | ||
285 | break; | ||
286 | case IEEE80211_AC_VI: | ||
287 | cmd->qndp_tid = 5; | ||
288 | break; | ||
289 | case IEEE80211_AC_BE: | ||
290 | cmd->qndp_tid = 0; | ||
291 | break; | ||
292 | case IEEE80211_AC_BK: | ||
293 | cmd->qndp_tid = 1; | ||
294 | break; | ||
295 | } | ||
296 | } | ||
297 | } | ||
298 | |||
299 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) { | ||
300 | cmd->rx_data_timeout_uapsd = | ||
301 | cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT); | ||
302 | cmd->tx_data_timeout_uapsd = | ||
303 | cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT); | ||
304 | |||
305 | if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) | | ||
306 | BIT(IEEE80211_AC_VI) | | ||
307 | BIT(IEEE80211_AC_BE) | | ||
308 | BIT(IEEE80211_AC_BK))) { | ||
309 | cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK); | ||
310 | cmd->snooze_interval = | ||
311 | cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL); | ||
312 | cmd->snooze_window = | ||
313 | (mvm->cur_ucode == IWL_UCODE_WOWLAN) ? | ||
314 | cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) : | ||
315 | cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW); | ||
316 | } | ||
317 | |||
318 | cmd->uapsd_max_sp = IWL_UAPSD_MAX_SP; | ||
319 | cmd->heavy_tx_thld_packets = | ||
320 | IWL_MVM_PS_HEAVY_TX_THLD_PACKETS; | ||
321 | cmd->heavy_rx_thld_packets = | ||
322 | IWL_MVM_PS_HEAVY_RX_THLD_PACKETS; | ||
323 | cmd->heavy_tx_thld_percentage = | ||
324 | IWL_MVM_PS_HEAVY_TX_THLD_PERCENT; | ||
325 | cmd->heavy_rx_thld_percentage = | ||
326 | IWL_MVM_PS_HEAVY_RX_THLD_PERCENT; | ||
327 | } | ||
328 | |||
238 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 329 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
239 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE) | 330 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE) |
240 | cmd->keep_alive_seconds = | 331 | cmd->keep_alive_seconds = |
@@ -263,6 +354,14 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
263 | } | 354 | } |
264 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD) | 355 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD) |
265 | cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold; | 356 | cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold; |
357 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SNOOZE_ENABLE) { | ||
358 | if (mvmvif->dbgfs_pm.snooze_ena) | ||
359 | cmd->flags |= | ||
360 | cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK); | ||
361 | else | ||
362 | cmd->flags &= | ||
363 | cpu_to_le16(~POWER_FLAGS_SNOOZE_ENA_MSK); | ||
364 | } | ||
266 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 365 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
267 | } | 366 | } |
268 | 367 | ||
@@ -342,8 +441,6 @@ static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, | |||
342 | (cmd.flags & | 441 | (cmd.flags & |
343 | cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ? | 442 | cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ? |
344 | 0 : 1); | 443 | 0 : 1); |
345 | pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n", | ||
346 | cmd.skip_dtim_periods); | ||
347 | pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", | 444 | pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", |
348 | iwlmvm_mod_params.power_scheme); | 445 | iwlmvm_mod_params.power_scheme); |
349 | pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n", | 446 | pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n", |
@@ -356,14 +453,64 @@ static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, | |||
356 | (cmd.flags & | 453 | (cmd.flags & |
357 | cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? | 454 | cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? |
358 | 1 : 0); | 455 | 1 : 0); |
359 | pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n", | 456 | pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n", |
360 | le32_to_cpu(cmd.rx_data_timeout)); | 457 | cmd.skip_dtim_periods); |
361 | pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n", | 458 | if (!(cmd.flags & |
362 | le32_to_cpu(cmd.tx_data_timeout)); | 459 | cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) { |
460 | pos += scnprintf(buf+pos, bufsz-pos, | ||
461 | "rx_data_timeout = %d\n", | ||
462 | le32_to_cpu(cmd.rx_data_timeout)); | ||
463 | pos += scnprintf(buf+pos, bufsz-pos, | ||
464 | "tx_data_timeout = %d\n", | ||
465 | le32_to_cpu(cmd.tx_data_timeout)); | ||
466 | } | ||
363 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) | 467 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) |
364 | pos += scnprintf(buf+pos, bufsz-pos, | 468 | pos += scnprintf(buf+pos, bufsz-pos, |
365 | "lprx_rssi_threshold = %d\n", | 469 | "lprx_rssi_threshold = %d\n", |
366 | cmd.lprx_rssi_threshold); | 470 | cmd.lprx_rssi_threshold); |
471 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) { | ||
472 | pos += | ||
473 | scnprintf(buf+pos, bufsz-pos, | ||
474 | "rx_data_timeout_uapsd = %d\n", | ||
475 | le32_to_cpu(cmd.rx_data_timeout_uapsd)); | ||
476 | pos += | ||
477 | scnprintf(buf+pos, bufsz-pos, | ||
478 | "tx_data_timeout_uapsd = %d\n", | ||
479 | le32_to_cpu(cmd.tx_data_timeout_uapsd)); | ||
480 | pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n", | ||
481 | cmd.qndp_tid); | ||
482 | pos += scnprintf(buf+pos, bufsz-pos, | ||
483 | "uapsd_ac_flags = 0x%x\n", | ||
484 | cmd.uapsd_ac_flags); | ||
485 | pos += scnprintf(buf+pos, bufsz-pos, | ||
486 | "uapsd_max_sp = %d\n", | ||
487 | cmd.uapsd_max_sp); | ||
488 | pos += scnprintf(buf+pos, bufsz-pos, | ||
489 | "heavy_tx_thld_packets = %d\n", | ||
490 | cmd.heavy_tx_thld_packets); | ||
491 | pos += scnprintf(buf+pos, bufsz-pos, | ||
492 | "heavy_rx_thld_packets = %d\n", | ||
493 | cmd.heavy_rx_thld_packets); | ||
494 | pos += scnprintf(buf+pos, bufsz-pos, | ||
495 | "heavy_tx_thld_percentage = %d\n", | ||
496 | cmd.heavy_tx_thld_percentage); | ||
497 | pos += scnprintf(buf+pos, bufsz-pos, | ||
498 | "heavy_rx_thld_percentage = %d\n", | ||
499 | cmd.heavy_rx_thld_percentage); | ||
500 | pos += | ||
501 | scnprintf(buf+pos, bufsz-pos, "snooze_enable = %d\n", | ||
502 | (cmd.flags & | ||
503 | cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) ? | ||
504 | 1 : 0); | ||
505 | } | ||
506 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { | ||
507 | pos += scnprintf(buf+pos, bufsz-pos, | ||
508 | "snooze_interval = %d\n", | ||
509 | cmd.snooze_interval); | ||
510 | pos += scnprintf(buf+pos, bufsz-pos, | ||
511 | "snooze_window = %d\n", | ||
512 | cmd.snooze_window); | ||
513 | } | ||
367 | } | 514 | } |
368 | return pos; | 515 | return pos; |
369 | } | 516 | } |
@@ -417,11 +564,12 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, | |||
417 | vif->type != NL80211_IFTYPE_STATION || vif->p2p) | 564 | vif->type != NL80211_IFTYPE_STATION || vif->p2p) |
418 | return 0; | 565 | return 0; |
419 | 566 | ||
567 | iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, &cmd); | ||
420 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); | 568 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); |
421 | ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); | 569 | ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); |
422 | 570 | ||
423 | if (!ret) | 571 | if (!ret) |
424 | mvmvif->bf_enabled = true; | 572 | mvmvif->bf_data.bf_enabled = true; |
425 | 573 | ||
426 | return ret; | 574 | return ret; |
427 | } | 575 | } |
@@ -440,11 +588,22 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, | |||
440 | ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); | 588 | ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); |
441 | 589 | ||
442 | if (!ret) | 590 | if (!ret) |
443 | mvmvif->bf_enabled = false; | 591 | mvmvif->bf_data.bf_enabled = false; |
444 | 592 | ||
445 | return ret; | 593 | return ret; |
446 | } | 594 | } |
447 | 595 | ||
596 | int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm, | ||
597 | struct ieee80211_vif *vif) | ||
598 | { | ||
599 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
600 | |||
601 | if (!mvmvif->bf_data.bf_enabled) | ||
602 | return 0; | ||
603 | |||
604 | return iwl_mvm_enable_beacon_filter(mvm, vif); | ||
605 | } | ||
606 | |||
448 | const struct iwl_mvm_power_ops pm_mac_ops = { | 607 | const struct iwl_mvm_power_ops pm_mac_ops = { |
449 | .power_update_mode = iwl_mvm_power_mac_update_mode, | 608 | .power_update_mode = iwl_mvm_power_mac_update_mode, |
450 | .power_disable = iwl_mvm_power_mac_disable, | 609 | .power_disable = iwl_mvm_power_mac_disable, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index c47a635b56ff..4ffaa3fa153f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -82,41 +82,35 @@ static const u8 ant_toggle_lookup[] = { | |||
82 | [ANT_ABC] = ANT_ABC, | 82 | [ANT_ABC] = ANT_ABC, |
83 | }; | 83 | }; |
84 | 84 | ||
85 | #define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \ | 85 | #define IWL_DECLARE_RATE_INFO(r, s, rp, rn) \ |
86 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ | 86 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ |
87 | IWL_RATE_SISO_##s##M_PLCP, \ | 87 | IWL_RATE_SISO_##s##M_PLCP, \ |
88 | IWL_RATE_MIMO2_##s##M_PLCP,\ | 88 | IWL_RATE_MIMO2_##s##M_PLCP,\ |
89 | IWL_RATE_MIMO3_##s##M_PLCP,\ | ||
90 | IWL_RATE_##r##M_IEEE, \ | ||
91 | IWL_RATE_##ip##M_INDEX, \ | ||
92 | IWL_RATE_##in##M_INDEX, \ | ||
93 | IWL_RATE_##rp##M_INDEX, \ | 89 | IWL_RATE_##rp##M_INDEX, \ |
94 | IWL_RATE_##rn##M_INDEX, \ | 90 | IWL_RATE_##rn##M_INDEX } |
95 | IWL_RATE_##pp##M_INDEX, \ | ||
96 | IWL_RATE_##np##M_INDEX } | ||
97 | 91 | ||
98 | /* | 92 | /* |
99 | * Parameter order: | 93 | * Parameter order: |
100 | * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate | 94 | * rate, ht rate, prev rate, next rate |
101 | * | 95 | * |
102 | * If there isn't a valid next or previous rate then INV is used which | 96 | * If there isn't a valid next or previous rate then INV is used which |
103 | * maps to IWL_RATE_INVALID | 97 | * maps to IWL_RATE_INVALID |
104 | * | 98 | * |
105 | */ | 99 | */ |
106 | static const struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = { | 100 | static const struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = { |
107 | IWL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2), /* 1mbps */ | 101 | IWL_DECLARE_RATE_INFO(1, INV, INV, 2), /* 1mbps */ |
108 | IWL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5), /* 2mbps */ | 102 | IWL_DECLARE_RATE_INFO(2, INV, 1, 5), /* 2mbps */ |
109 | IWL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11), /*5.5mbps */ | 103 | IWL_DECLARE_RATE_INFO(5, INV, 2, 11), /*5.5mbps */ |
110 | IWL_DECLARE_RATE_INFO(11, INV, 9, 12, 9, 12, 5, 18), /* 11mbps */ | 104 | IWL_DECLARE_RATE_INFO(11, INV, 9, 12), /* 11mbps */ |
111 | IWL_DECLARE_RATE_INFO(6, 6, 5, 9, 5, 11, 5, 11), /* 6mbps */ | 105 | IWL_DECLARE_RATE_INFO(6, 6, 5, 11), /* 6mbps */ |
112 | IWL_DECLARE_RATE_INFO(9, 6, 6, 11, 6, 11, 5, 11), /* 9mbps */ | 106 | IWL_DECLARE_RATE_INFO(9, 6, 6, 11), /* 9mbps */ |
113 | IWL_DECLARE_RATE_INFO(12, 12, 11, 18, 11, 18, 11, 18), /* 12mbps */ | 107 | IWL_DECLARE_RATE_INFO(12, 12, 11, 18), /* 12mbps */ |
114 | IWL_DECLARE_RATE_INFO(18, 18, 12, 24, 12, 24, 11, 24), /* 18mbps */ | 108 | IWL_DECLARE_RATE_INFO(18, 18, 12, 24), /* 18mbps */ |
115 | IWL_DECLARE_RATE_INFO(24, 24, 18, 36, 18, 36, 18, 36), /* 24mbps */ | 109 | IWL_DECLARE_RATE_INFO(24, 24, 18, 36), /* 24mbps */ |
116 | IWL_DECLARE_RATE_INFO(36, 36, 24, 48, 24, 48, 24, 48), /* 36mbps */ | 110 | IWL_DECLARE_RATE_INFO(36, 36, 24, 48), /* 36mbps */ |
117 | IWL_DECLARE_RATE_INFO(48, 48, 36, 54, 36, 54, 36, 54), /* 48mbps */ | 111 | IWL_DECLARE_RATE_INFO(48, 48, 36, 54), /* 48mbps */ |
118 | IWL_DECLARE_RATE_INFO(54, 54, 48, INV, 48, INV, 48, INV),/* 54mbps */ | 112 | IWL_DECLARE_RATE_INFO(54, 54, 48, INV), /* 54mbps */ |
119 | IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */ | 113 | IWL_DECLARE_RATE_INFO(60, 60, 48, INV), /* 60mbps */ |
120 | /* FIXME:RS: ^^ should be INV (legacy) */ | 114 | /* FIXME:RS: ^^ should be INV (legacy) */ |
121 | }; | 115 | }; |
122 | 116 | ||
@@ -134,9 +128,8 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) | |||
134 | if (rate_n_flags & RATE_MCS_HT_MSK) { | 128 | if (rate_n_flags & RATE_MCS_HT_MSK) { |
135 | idx = rs_extract_rate(rate_n_flags); | 129 | idx = rs_extract_rate(rate_n_flags); |
136 | 130 | ||
137 | if (idx >= IWL_RATE_MIMO3_6M_PLCP) | 131 | WARN_ON_ONCE(idx >= IWL_RATE_MIMO3_6M_PLCP); |
138 | idx = idx - IWL_RATE_MIMO3_6M_PLCP; | 132 | if (idx >= IWL_RATE_MIMO2_6M_PLCP) |
139 | else if (idx >= IWL_RATE_MIMO2_6M_PLCP) | ||
140 | idx = idx - IWL_RATE_MIMO2_6M_PLCP; | 133 | idx = idx - IWL_RATE_MIMO2_6M_PLCP; |
141 | 134 | ||
142 | idx += IWL_FIRST_OFDM_RATE; | 135 | idx += IWL_FIRST_OFDM_RATE; |
@@ -168,10 +161,10 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search); | |||
168 | 161 | ||
169 | #ifdef CONFIG_MAC80211_DEBUGFS | 162 | #ifdef CONFIG_MAC80211_DEBUGFS |
170 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | 163 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, |
171 | u32 *rate_n_flags, int index); | 164 | u32 *rate_n_flags); |
172 | #else | 165 | #else |
173 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | 166 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, |
174 | u32 *rate_n_flags, int index) | 167 | u32 *rate_n_flags) |
175 | {} | 168 | {} |
176 | #endif | 169 | #endif |
177 | 170 | ||
@@ -218,20 +211,6 @@ static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = { | |||
218 | {0, 0, 0, 0, 186, 0, 329, 439, 527, 667, 764, 803, 838}, /* AGG+SGI */ | 211 | {0, 0, 0, 0, 186, 0, 329, 439, 527, 667, 764, 803, 838}, /* AGG+SGI */ |
219 | }; | 212 | }; |
220 | 213 | ||
221 | static s32 expected_tpt_mimo3_20MHz[4][IWL_RATE_COUNT] = { | ||
222 | {0, 0, 0, 0, 99, 0, 153, 186, 208, 239, 256, 263, 268}, /* Norm */ | ||
223 | {0, 0, 0, 0, 106, 0, 162, 194, 215, 246, 262, 268, 273}, /* SGI */ | ||
224 | {0, 0, 0, 0, 134, 0, 249, 346, 431, 574, 685, 732, 775}, /* AGG */ | ||
225 | {0, 0, 0, 0, 148, 0, 272, 376, 465, 614, 727, 775, 818}, /* AGG+SGI */ | ||
226 | }; | ||
227 | |||
228 | static s32 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = { | ||
229 | {0, 0, 0, 0, 152, 0, 211, 239, 255, 279, 290, 294, 297}, /* Norm */ | ||
230 | {0, 0, 0, 0, 160, 0, 219, 245, 261, 284, 294, 297, 300}, /* SGI */ | ||
231 | {0, 0, 0, 0, 254, 0, 443, 584, 695, 868, 984, 1030, 1070}, /* AGG */ | ||
232 | {0, 0, 0, 0, 277, 0, 478, 624, 737, 911, 1026, 1070, 1109}, /* AGG+SGI */ | ||
233 | }; | ||
234 | |||
235 | /* mbps, mcs */ | 214 | /* mbps, mcs */ |
236 | static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { | 215 | static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { |
237 | { "1", "BPSK DSSS"}, | 216 | { "1", "BPSK DSSS"}, |
@@ -279,7 +258,6 @@ static void rs_program_fix_rate(struct iwl_mvm *mvm, | |||
279 | lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ | 258 | lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ |
280 | lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ | 259 | lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ |
281 | lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ | 260 | lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ |
282 | lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ | ||
283 | 261 | ||
284 | IWL_DEBUG_RATE(mvm, "sta_id %d rate 0x%X\n", | 262 | IWL_DEBUG_RATE(mvm, "sta_id %d rate 0x%X\n", |
285 | lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); | 263 | lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); |
@@ -459,7 +437,7 @@ static u32 rate_n_flags_from_tbl(struct iwl_mvm *mvm, | |||
459 | else if (is_mimo2(tbl->lq_type)) | 437 | else if (is_mimo2(tbl->lq_type)) |
460 | rate_n_flags |= iwl_rates[index].plcp_mimo2; | 438 | rate_n_flags |= iwl_rates[index].plcp_mimo2; |
461 | else | 439 | else |
462 | rate_n_flags |= iwl_rates[index].plcp_mimo3; | 440 | WARN_ON_ONCE(1); |
463 | } else { | 441 | } else { |
464 | IWL_ERR(mvm, "Invalid tbl->lq_type %d\n", tbl->lq_type); | 442 | IWL_ERR(mvm, "Invalid tbl->lq_type %d\n", tbl->lq_type); |
465 | } | 443 | } |
@@ -497,7 +475,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, | |||
497 | u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); | 475 | u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); |
498 | u8 mcs; | 476 | u8 mcs; |
499 | 477 | ||
500 | memset(tbl, 0, sizeof(struct iwl_scale_tbl_info)); | 478 | memset(tbl, 0, offsetof(struct iwl_scale_tbl_info, win)); |
501 | *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | 479 | *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); |
502 | 480 | ||
503 | if (*rate_idx == IWL_RATE_INVALID) { | 481 | if (*rate_idx == IWL_RATE_INVALID) { |
@@ -536,12 +514,8 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, | |||
536 | } else if (mcs <= IWL_RATE_MIMO2_60M_PLCP) { | 514 | } else if (mcs <= IWL_RATE_MIMO2_60M_PLCP) { |
537 | if (num_of_ant == 2) | 515 | if (num_of_ant == 2) |
538 | tbl->lq_type = LQ_MIMO2; | 516 | tbl->lq_type = LQ_MIMO2; |
539 | /* MIMO3 */ | ||
540 | } else { | 517 | } else { |
541 | if (num_of_ant == 3) { | 518 | WARN_ON_ONCE(num_of_ant == 3); |
542 | tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH; | ||
543 | tbl->lq_type = LQ_MIMO3; | ||
544 | } | ||
545 | } | 519 | } |
546 | } | 520 | } |
547 | return 0; | 521 | return 0; |
@@ -607,10 +581,10 @@ static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, | |||
607 | } else { | 581 | } else { |
608 | if (is_siso(rate_type)) | 582 | if (is_siso(rate_type)) |
609 | return lq_sta->active_siso_rate; | 583 | return lq_sta->active_siso_rate; |
610 | else if (is_mimo2(rate_type)) | 584 | else { |
585 | WARN_ON_ONCE(!is_mimo2(rate_type)); | ||
611 | return lq_sta->active_mimo2_rate; | 586 | return lq_sta->active_mimo2_rate; |
612 | else | 587 | } |
613 | return lq_sta->active_mimo3_rate; | ||
614 | } | 588 | } |
615 | } | 589 | } |
616 | 590 | ||
@@ -985,7 +959,7 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, | |||
985 | } | 959 | } |
986 | 960 | ||
987 | /* Choose among many HT tables depending on number of streams | 961 | /* Choose among many HT tables depending on number of streams |
988 | * (SISO/MIMO2/MIMO3), channel width (20/40), SGI, and aggregation | 962 | * (SISO/MIMO2), channel width (20/40), SGI, and aggregation |
989 | * status */ | 963 | * status */ |
990 | if (is_siso(tbl->lq_type) && !tbl->is_ht40) | 964 | if (is_siso(tbl->lq_type) && !tbl->is_ht40) |
991 | ht_tbl_pointer = expected_tpt_siso20MHz; | 965 | ht_tbl_pointer = expected_tpt_siso20MHz; |
@@ -993,12 +967,10 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, | |||
993 | ht_tbl_pointer = expected_tpt_siso40MHz; | 967 | ht_tbl_pointer = expected_tpt_siso40MHz; |
994 | else if (is_mimo2(tbl->lq_type) && !tbl->is_ht40) | 968 | else if (is_mimo2(tbl->lq_type) && !tbl->is_ht40) |
995 | ht_tbl_pointer = expected_tpt_mimo2_20MHz; | 969 | ht_tbl_pointer = expected_tpt_mimo2_20MHz; |
996 | else if (is_mimo2(tbl->lq_type)) | 970 | else { |
971 | WARN_ON_ONCE(!is_mimo2(tbl->lq_type)); | ||
997 | ht_tbl_pointer = expected_tpt_mimo2_40MHz; | 972 | ht_tbl_pointer = expected_tpt_mimo2_40MHz; |
998 | else if (is_mimo3(tbl->lq_type) && !tbl->is_ht40) | 973 | } |
999 | ht_tbl_pointer = expected_tpt_mimo3_20MHz; | ||
1000 | else /* if (is_mimo3(tbl->lq_type)) <-- must be true */ | ||
1001 | ht_tbl_pointer = expected_tpt_mimo3_40MHz; | ||
1002 | 974 | ||
1003 | if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */ | 975 | if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */ |
1004 | tbl->expected_tpt = ht_tbl_pointer[0]; | 976 | tbl->expected_tpt = ht_tbl_pointer[0]; |
@@ -1170,58 +1142,6 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm, | |||
1170 | } | 1142 | } |
1171 | 1143 | ||
1172 | /* | 1144 | /* |
1173 | * Set up search table for MIMO3 | ||
1174 | */ | ||
1175 | static int rs_switch_to_mimo3(struct iwl_mvm *mvm, | ||
1176 | struct iwl_lq_sta *lq_sta, | ||
1177 | struct ieee80211_sta *sta, | ||
1178 | struct iwl_scale_tbl_info *tbl, int index) | ||
1179 | { | ||
1180 | u16 rate_mask; | ||
1181 | s32 rate; | ||
1182 | s8 is_green = lq_sta->is_green; | ||
1183 | |||
1184 | if (!sta->ht_cap.ht_supported) | ||
1185 | return -1; | ||
1186 | |||
1187 | if (sta->smps_mode == IEEE80211_SMPS_STATIC) | ||
1188 | return -1; | ||
1189 | |||
1190 | /* Need both Tx chains/antennas to support MIMO */ | ||
1191 | if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 3) | ||
1192 | return -1; | ||
1193 | |||
1194 | IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO3\n"); | ||
1195 | |||
1196 | tbl->lq_type = LQ_MIMO3; | ||
1197 | tbl->action = 0; | ||
1198 | tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH; | ||
1199 | rate_mask = lq_sta->active_mimo3_rate; | ||
1200 | |||
1201 | if (iwl_is_ht40_tx_allowed(sta)) | ||
1202 | tbl->is_ht40 = 1; | ||
1203 | else | ||
1204 | tbl->is_ht40 = 0; | ||
1205 | |||
1206 | rs_set_expected_tpt_table(lq_sta, tbl); | ||
1207 | |||
1208 | rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); | ||
1209 | |||
1210 | IWL_DEBUG_RATE(mvm, "LQ: MIMO3 best rate %d mask %X\n", | ||
1211 | rate, rate_mask); | ||
1212 | if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { | ||
1213 | IWL_DEBUG_RATE(mvm, "Can't switch with index %d rate mask %x\n", | ||
1214 | rate, rate_mask); | ||
1215 | return -1; | ||
1216 | } | ||
1217 | tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, rate, is_green); | ||
1218 | |||
1219 | IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index is green %X\n", | ||
1220 | tbl->current_rate, is_green); | ||
1221 | return 0; | ||
1222 | } | ||
1223 | |||
1224 | /* | ||
1225 | * Set up search table for SISO | 1145 | * Set up search table for SISO |
1226 | */ | 1146 | */ |
1227 | static int rs_switch_to_siso(struct iwl_mvm *mvm, | 1147 | static int rs_switch_to_siso(struct iwl_mvm *mvm, |
@@ -1330,21 +1250,14 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, | |||
1330 | } | 1250 | } |
1331 | 1251 | ||
1332 | break; | 1252 | break; |
1333 | case IWL_LEGACY_SWITCH_MIMO2_AB: | 1253 | case IWL_LEGACY_SWITCH_MIMO2: |
1334 | case IWL_LEGACY_SWITCH_MIMO2_AC: | ||
1335 | case IWL_LEGACY_SWITCH_MIMO2_BC: | ||
1336 | IWL_DEBUG_RATE(mvm, "LQ: Legacy switch to MIMO2\n"); | 1254 | IWL_DEBUG_RATE(mvm, "LQ: Legacy switch to MIMO2\n"); |
1337 | 1255 | ||
1338 | /* Set up search table to try MIMO */ | 1256 | /* Set up search table to try MIMO */ |
1339 | memcpy(search_tbl, tbl, sz); | 1257 | memcpy(search_tbl, tbl, sz); |
1340 | search_tbl->is_SGI = 0; | 1258 | search_tbl->is_SGI = 0; |
1341 | 1259 | ||
1342 | if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AB) | 1260 | search_tbl->ant_type = ANT_AB; |
1343 | search_tbl->ant_type = ANT_AB; | ||
1344 | else if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AC) | ||
1345 | search_tbl->ant_type = ANT_AC; | ||
1346 | else | ||
1347 | search_tbl->ant_type = ANT_BC; | ||
1348 | 1261 | ||
1349 | if (!rs_is_valid_ant(valid_tx_ant, | 1262 | if (!rs_is_valid_ant(valid_tx_ant, |
1350 | search_tbl->ant_type)) | 1263 | search_tbl->ant_type)) |
@@ -1357,30 +1270,11 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, | |||
1357 | goto out; | 1270 | goto out; |
1358 | } | 1271 | } |
1359 | break; | 1272 | break; |
1360 | 1273 | default: | |
1361 | case IWL_LEGACY_SWITCH_MIMO3_ABC: | 1274 | WARN_ON_ONCE(1); |
1362 | IWL_DEBUG_RATE(mvm, "LQ: Legacy switch to MIMO3\n"); | ||
1363 | |||
1364 | /* Set up search table to try MIMO3 */ | ||
1365 | memcpy(search_tbl, tbl, sz); | ||
1366 | search_tbl->is_SGI = 0; | ||
1367 | |||
1368 | search_tbl->ant_type = ANT_ABC; | ||
1369 | |||
1370 | if (!rs_is_valid_ant(valid_tx_ant, | ||
1371 | search_tbl->ant_type)) | ||
1372 | break; | ||
1373 | |||
1374 | ret = rs_switch_to_mimo3(mvm, lq_sta, sta, | ||
1375 | search_tbl, index); | ||
1376 | if (!ret) { | ||
1377 | lq_sta->action_counter = 0; | ||
1378 | goto out; | ||
1379 | } | ||
1380 | break; | ||
1381 | } | 1275 | } |
1382 | tbl->action++; | 1276 | tbl->action++; |
1383 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) | 1277 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO2) |
1384 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; | 1278 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; |
1385 | 1279 | ||
1386 | if (tbl->action == start_action) | 1280 | if (tbl->action == start_action) |
@@ -1392,7 +1286,7 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, | |||
1392 | out: | 1286 | out: |
1393 | lq_sta->search_better_tbl = 1; | 1287 | lq_sta->search_better_tbl = 1; |
1394 | tbl->action++; | 1288 | tbl->action++; |
1395 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) | 1289 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO2) |
1396 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; | 1290 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; |
1397 | if (update_search_tbl_counter) | 1291 | if (update_search_tbl_counter) |
1398 | search_tbl->action = tbl->action; | 1292 | search_tbl->action = tbl->action; |
@@ -1427,7 +1321,7 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
1427 | case IWL_BT_COEX_TRAFFIC_LOAD_LOW: | 1321 | case IWL_BT_COEX_TRAFFIC_LOAD_LOW: |
1428 | /* avoid antenna B unless MIMO */ | 1322 | /* avoid antenna B unless MIMO */ |
1429 | if (tbl->action == IWL_SISO_SWITCH_ANTENNA2) | 1323 | if (tbl->action == IWL_SISO_SWITCH_ANTENNA2) |
1430 | tbl->action = IWL_SISO_SWITCH_MIMO2_AB; | 1324 | tbl->action = IWL_SISO_SWITCH_MIMO2; |
1431 | break; | 1325 | break; |
1432 | case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: | 1326 | case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: |
1433 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | 1327 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: |
@@ -1469,19 +1363,12 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
1469 | goto out; | 1363 | goto out; |
1470 | } | 1364 | } |
1471 | break; | 1365 | break; |
1472 | case IWL_SISO_SWITCH_MIMO2_AB: | 1366 | case IWL_SISO_SWITCH_MIMO2: |
1473 | case IWL_SISO_SWITCH_MIMO2_AC: | ||
1474 | case IWL_SISO_SWITCH_MIMO2_BC: | ||
1475 | IWL_DEBUG_RATE(mvm, "LQ: SISO switch to MIMO2\n"); | 1367 | IWL_DEBUG_RATE(mvm, "LQ: SISO switch to MIMO2\n"); |
1476 | memcpy(search_tbl, tbl, sz); | 1368 | memcpy(search_tbl, tbl, sz); |
1477 | search_tbl->is_SGI = 0; | 1369 | search_tbl->is_SGI = 0; |
1478 | 1370 | ||
1479 | if (tbl->action == IWL_SISO_SWITCH_MIMO2_AB) | 1371 | search_tbl->ant_type = ANT_AB; |
1480 | search_tbl->ant_type = ANT_AB; | ||
1481 | else if (tbl->action == IWL_SISO_SWITCH_MIMO2_AC) | ||
1482 | search_tbl->ant_type = ANT_AC; | ||
1483 | else | ||
1484 | search_tbl->ant_type = ANT_BC; | ||
1485 | 1372 | ||
1486 | if (!rs_is_valid_ant(valid_tx_ant, | 1373 | if (!rs_is_valid_ant(valid_tx_ant, |
1487 | search_tbl->ant_type)) | 1374 | search_tbl->ant_type)) |
@@ -1522,24 +1409,11 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
1522 | index, is_green); | 1409 | index, is_green); |
1523 | update_search_tbl_counter = 1; | 1410 | update_search_tbl_counter = 1; |
1524 | goto out; | 1411 | goto out; |
1525 | case IWL_SISO_SWITCH_MIMO3_ABC: | 1412 | default: |
1526 | IWL_DEBUG_RATE(mvm, "LQ: SISO switch to MIMO3\n"); | 1413 | WARN_ON_ONCE(1); |
1527 | memcpy(search_tbl, tbl, sz); | ||
1528 | search_tbl->is_SGI = 0; | ||
1529 | search_tbl->ant_type = ANT_ABC; | ||
1530 | |||
1531 | if (!rs_is_valid_ant(valid_tx_ant, | ||
1532 | search_tbl->ant_type)) | ||
1533 | break; | ||
1534 | |||
1535 | ret = rs_switch_to_mimo3(mvm, lq_sta, sta, | ||
1536 | search_tbl, index); | ||
1537 | if (!ret) | ||
1538 | goto out; | ||
1539 | break; | ||
1540 | } | 1414 | } |
1541 | tbl->action++; | 1415 | tbl->action++; |
1542 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) | 1416 | if (tbl->action > IWL_SISO_SWITCH_GI) |
1543 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1417 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1544 | 1418 | ||
1545 | if (tbl->action == start_action) | 1419 | if (tbl->action == start_action) |
@@ -1551,7 +1425,7 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
1551 | out: | 1425 | out: |
1552 | lq_sta->search_better_tbl = 1; | 1426 | lq_sta->search_better_tbl = 1; |
1553 | tbl->action++; | 1427 | tbl->action++; |
1554 | if (tbl->action > IWL_SISO_SWITCH_MIMO3_ABC) | 1428 | if (tbl->action > IWL_SISO_SWITCH_GI) |
1555 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1429 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1556 | if (update_search_tbl_counter) | 1430 | if (update_search_tbl_counter) |
1557 | search_tbl->action = tbl->action; | 1431 | search_tbl->action = tbl->action; |
@@ -1592,8 +1466,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
1592 | break; | 1466 | break; |
1593 | case IWL_BT_COEX_TRAFFIC_LOAD_LOW: | 1467 | case IWL_BT_COEX_TRAFFIC_LOAD_LOW: |
1594 | /* avoid antenna B unless MIMO */ | 1468 | /* avoid antenna B unless MIMO */ |
1595 | if (tbl->action == IWL_MIMO2_SWITCH_SISO_B || | 1469 | if (tbl->action == IWL_MIMO2_SWITCH_SISO_B) |
1596 | tbl->action == IWL_MIMO2_SWITCH_SISO_C) | ||
1597 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; | 1470 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; |
1598 | break; | 1471 | break; |
1599 | default: | 1472 | default: |
@@ -1626,7 +1499,6 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
1626 | break; | 1499 | break; |
1627 | case IWL_MIMO2_SWITCH_SISO_A: | 1500 | case IWL_MIMO2_SWITCH_SISO_A: |
1628 | case IWL_MIMO2_SWITCH_SISO_B: | 1501 | case IWL_MIMO2_SWITCH_SISO_B: |
1629 | case IWL_MIMO2_SWITCH_SISO_C: | ||
1630 | IWL_DEBUG_RATE(mvm, "LQ: MIMO2 switch to SISO\n"); | 1502 | IWL_DEBUG_RATE(mvm, "LQ: MIMO2 switch to SISO\n"); |
1631 | 1503 | ||
1632 | /* Set up new search table for SISO */ | 1504 | /* Set up new search table for SISO */ |
@@ -1634,10 +1506,8 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
1634 | 1506 | ||
1635 | if (tbl->action == IWL_MIMO2_SWITCH_SISO_A) | 1507 | if (tbl->action == IWL_MIMO2_SWITCH_SISO_A) |
1636 | search_tbl->ant_type = ANT_A; | 1508 | search_tbl->ant_type = ANT_A; |
1637 | else if (tbl->action == IWL_MIMO2_SWITCH_SISO_B) | 1509 | else /* tbl->action == IWL_MIMO2_SWITCH_SISO_B */ |
1638 | search_tbl->ant_type = ANT_B; | 1510 | search_tbl->ant_type = ANT_B; |
1639 | else | ||
1640 | search_tbl->ant_type = ANT_C; | ||
1641 | 1511 | ||
1642 | if (!rs_is_valid_ant(valid_tx_ant, | 1512 | if (!rs_is_valid_ant(valid_tx_ant, |
1643 | search_tbl->ant_type)) | 1513 | search_tbl->ant_type)) |
@@ -1680,26 +1550,11 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
1680 | index, is_green); | 1550 | index, is_green); |
1681 | update_search_tbl_counter = 1; | 1551 | update_search_tbl_counter = 1; |
1682 | goto out; | 1552 | goto out; |
1683 | 1553 | default: | |
1684 | case IWL_MIMO2_SWITCH_MIMO3_ABC: | 1554 | WARN_ON_ONCE(1); |
1685 | IWL_DEBUG_RATE(mvm, "LQ: MIMO2 switch to MIMO3\n"); | ||
1686 | memcpy(search_tbl, tbl, sz); | ||
1687 | search_tbl->is_SGI = 0; | ||
1688 | search_tbl->ant_type = ANT_ABC; | ||
1689 | |||
1690 | if (!rs_is_valid_ant(valid_tx_ant, | ||
1691 | search_tbl->ant_type)) | ||
1692 | break; | ||
1693 | |||
1694 | ret = rs_switch_to_mimo3(mvm, lq_sta, sta, | ||
1695 | search_tbl, index); | ||
1696 | if (!ret) | ||
1697 | goto out; | ||
1698 | |||
1699 | break; | ||
1700 | } | 1555 | } |
1701 | tbl->action++; | 1556 | tbl->action++; |
1702 | if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC) | 1557 | if (tbl->action > IWL_MIMO2_SWITCH_GI) |
1703 | tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; | 1558 | tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; |
1704 | 1559 | ||
1705 | if (tbl->action == start_action) | 1560 | if (tbl->action == start_action) |
@@ -1710,7 +1565,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
1710 | out: | 1565 | out: |
1711 | lq_sta->search_better_tbl = 1; | 1566 | lq_sta->search_better_tbl = 1; |
1712 | tbl->action++; | 1567 | tbl->action++; |
1713 | if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC) | 1568 | if (tbl->action > IWL_MIMO2_SWITCH_GI) |
1714 | tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; | 1569 | tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; |
1715 | if (update_search_tbl_counter) | 1570 | if (update_search_tbl_counter) |
1716 | search_tbl->action = tbl->action; | 1571 | search_tbl->action = tbl->action; |
@@ -1719,171 +1574,6 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
1719 | } | 1574 | } |
1720 | 1575 | ||
1721 | /* | 1576 | /* |
1722 | * Try to switch to new modulation mode from MIMO3 | ||
1723 | */ | ||
1724 | static int rs_move_mimo3_to_other(struct iwl_mvm *mvm, | ||
1725 | struct iwl_lq_sta *lq_sta, | ||
1726 | struct ieee80211_sta *sta, int index) | ||
1727 | { | ||
1728 | s8 is_green = lq_sta->is_green; | ||
1729 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | ||
1730 | struct iwl_scale_tbl_info *search_tbl = | ||
1731 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); | ||
1732 | struct iwl_rate_scale_data *window = &(tbl->win[index]); | ||
1733 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
1734 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | ||
1735 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | ||
1736 | u8 start_action; | ||
1737 | u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); | ||
1738 | u8 tx_chains_num = num_of_ant(valid_tx_ant); | ||
1739 | int ret; | ||
1740 | u8 update_search_tbl_counter = 0; | ||
1741 | |||
1742 | switch (BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { | ||
1743 | case IWL_BT_COEX_TRAFFIC_LOAD_NONE: | ||
1744 | /* nothing */ | ||
1745 | break; | ||
1746 | case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: | ||
1747 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | ||
1748 | /* avoid antenna B and MIMO */ | ||
1749 | if (tbl->action != IWL_MIMO3_SWITCH_SISO_A) | ||
1750 | tbl->action = IWL_MIMO3_SWITCH_SISO_A; | ||
1751 | break; | ||
1752 | case IWL_BT_COEX_TRAFFIC_LOAD_LOW: | ||
1753 | /* avoid antenna B unless MIMO */ | ||
1754 | if (tbl->action == IWL_MIMO3_SWITCH_SISO_B || | ||
1755 | tbl->action == IWL_MIMO3_SWITCH_SISO_C) | ||
1756 | tbl->action = IWL_MIMO3_SWITCH_SISO_A; | ||
1757 | break; | ||
1758 | default: | ||
1759 | IWL_ERR(mvm, "Invalid BT load %d", | ||
1760 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)); | ||
1761 | break; | ||
1762 | } | ||
1763 | |||
1764 | start_action = tbl->action; | ||
1765 | while (1) { | ||
1766 | lq_sta->action_counter++; | ||
1767 | switch (tbl->action) { | ||
1768 | case IWL_MIMO3_SWITCH_ANTENNA1: | ||
1769 | case IWL_MIMO3_SWITCH_ANTENNA2: | ||
1770 | IWL_DEBUG_RATE(mvm, "LQ: MIMO3 toggle Antennas\n"); | ||
1771 | |||
1772 | if (tx_chains_num <= 3) | ||
1773 | break; | ||
1774 | |||
1775 | if (window->success_ratio >= IWL_RS_GOOD_RATIO) | ||
1776 | break; | ||
1777 | |||
1778 | memcpy(search_tbl, tbl, sz); | ||
1779 | if (rs_toggle_antenna(valid_tx_ant, | ||
1780 | &search_tbl->current_rate, | ||
1781 | search_tbl)) | ||
1782 | goto out; | ||
1783 | break; | ||
1784 | case IWL_MIMO3_SWITCH_SISO_A: | ||
1785 | case IWL_MIMO3_SWITCH_SISO_B: | ||
1786 | case IWL_MIMO3_SWITCH_SISO_C: | ||
1787 | IWL_DEBUG_RATE(mvm, "LQ: MIMO3 switch to SISO\n"); | ||
1788 | |||
1789 | /* Set up new search table for SISO */ | ||
1790 | memcpy(search_tbl, tbl, sz); | ||
1791 | |||
1792 | if (tbl->action == IWL_MIMO3_SWITCH_SISO_A) | ||
1793 | search_tbl->ant_type = ANT_A; | ||
1794 | else if (tbl->action == IWL_MIMO3_SWITCH_SISO_B) | ||
1795 | search_tbl->ant_type = ANT_B; | ||
1796 | else | ||
1797 | search_tbl->ant_type = ANT_C; | ||
1798 | |||
1799 | if (!rs_is_valid_ant(valid_tx_ant, | ||
1800 | search_tbl->ant_type)) | ||
1801 | break; | ||
1802 | |||
1803 | ret = rs_switch_to_siso(mvm, lq_sta, sta, | ||
1804 | search_tbl, index); | ||
1805 | if (!ret) | ||
1806 | goto out; | ||
1807 | |||
1808 | break; | ||
1809 | |||
1810 | case IWL_MIMO3_SWITCH_MIMO2_AB: | ||
1811 | case IWL_MIMO3_SWITCH_MIMO2_AC: | ||
1812 | case IWL_MIMO3_SWITCH_MIMO2_BC: | ||
1813 | IWL_DEBUG_RATE(mvm, "LQ: MIMO3 switch to MIMO2\n"); | ||
1814 | |||
1815 | memcpy(search_tbl, tbl, sz); | ||
1816 | search_tbl->is_SGI = 0; | ||
1817 | if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AB) | ||
1818 | search_tbl->ant_type = ANT_AB; | ||
1819 | else if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AC) | ||
1820 | search_tbl->ant_type = ANT_AC; | ||
1821 | else | ||
1822 | search_tbl->ant_type = ANT_BC; | ||
1823 | |||
1824 | if (!rs_is_valid_ant(valid_tx_ant, | ||
1825 | search_tbl->ant_type)) | ||
1826 | break; | ||
1827 | |||
1828 | ret = rs_switch_to_mimo2(mvm, lq_sta, sta, | ||
1829 | search_tbl, index); | ||
1830 | if (!ret) | ||
1831 | goto out; | ||
1832 | |||
1833 | break; | ||
1834 | |||
1835 | case IWL_MIMO3_SWITCH_GI: | ||
1836 | if (!tbl->is_ht40 && !(ht_cap->cap & | ||
1837 | IEEE80211_HT_CAP_SGI_20)) | ||
1838 | break; | ||
1839 | if (tbl->is_ht40 && !(ht_cap->cap & | ||
1840 | IEEE80211_HT_CAP_SGI_40)) | ||
1841 | break; | ||
1842 | |||
1843 | IWL_DEBUG_RATE(mvm, "LQ: MIMO3 toggle SGI/NGI\n"); | ||
1844 | |||
1845 | /* Set up new search table for MIMO */ | ||
1846 | memcpy(search_tbl, tbl, sz); | ||
1847 | search_tbl->is_SGI = !tbl->is_SGI; | ||
1848 | rs_set_expected_tpt_table(lq_sta, search_tbl); | ||
1849 | /* | ||
1850 | * If active table already uses the fastest possible | ||
1851 | * modulation (dual stream with short guard interval), | ||
1852 | * and it's working well, there's no need to look | ||
1853 | * for a better type of modulation! | ||
1854 | */ | ||
1855 | if (tbl->is_SGI) { | ||
1856 | s32 tpt = lq_sta->last_tpt / 100; | ||
1857 | if (tpt >= search_tbl->expected_tpt[index]) | ||
1858 | break; | ||
1859 | } | ||
1860 | search_tbl->current_rate = | ||
1861 | rate_n_flags_from_tbl(mvm, search_tbl, | ||
1862 | index, is_green); | ||
1863 | update_search_tbl_counter = 1; | ||
1864 | goto out; | ||
1865 | } | ||
1866 | tbl->action++; | ||
1867 | if (tbl->action > IWL_MIMO3_SWITCH_GI) | ||
1868 | tbl->action = IWL_MIMO3_SWITCH_ANTENNA1; | ||
1869 | |||
1870 | if (tbl->action == start_action) | ||
1871 | break; | ||
1872 | } | ||
1873 | search_tbl->lq_type = LQ_NONE; | ||
1874 | return 0; | ||
1875 | out: | ||
1876 | lq_sta->search_better_tbl = 1; | ||
1877 | tbl->action++; | ||
1878 | if (tbl->action > IWL_MIMO3_SWITCH_GI) | ||
1879 | tbl->action = IWL_MIMO3_SWITCH_ANTENNA1; | ||
1880 | if (update_search_tbl_counter) | ||
1881 | search_tbl->action = tbl->action; | ||
1882 | |||
1883 | return 0; | ||
1884 | } | ||
1885 | |||
1886 | /* | ||
1887 | * Check whether we should continue using same modulation mode, or | 1577 | * Check whether we should continue using same modulation mode, or |
1888 | * begin search for a new mode, based on: | 1578 | * begin search for a new mode, based on: |
1889 | * 1) # tx successes or failures while using this mode | 1579 | * 1) # tx successes or failures while using this mode |
@@ -2289,8 +1979,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
2289 | scale_action = 0; | 1979 | scale_action = 0; |
2290 | 1980 | ||
2291 | if ((BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= | 1981 | if ((BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= |
2292 | IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && | 1982 | IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && (is_mimo(tbl->lq_type))) { |
2293 | (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) { | ||
2294 | if (lq_sta->last_bt_traffic > | 1983 | if (lq_sta->last_bt_traffic > |
2295 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { | 1984 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { |
2296 | /* | 1985 | /* |
@@ -2307,8 +1996,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
2307 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD); | 1996 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD); |
2308 | 1997 | ||
2309 | if ((BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= | 1998 | if ((BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= |
2310 | IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && | 1999 | IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && is_mimo(tbl->lq_type)) { |
2311 | (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) { | ||
2312 | /* search for a new modulation */ | 2000 | /* search for a new modulation */ |
2313 | rs_stay_in_table(lq_sta, true); | 2001 | rs_stay_in_table(lq_sta, true); |
2314 | goto lq_update; | 2002 | goto lq_update; |
@@ -2368,7 +2056,7 @@ lq_update: | |||
2368 | else if (is_mimo2(tbl->lq_type)) | 2056 | else if (is_mimo2(tbl->lq_type)) |
2369 | rs_move_mimo2_to_other(mvm, lq_sta, sta, index); | 2057 | rs_move_mimo2_to_other(mvm, lq_sta, sta, index); |
2370 | else | 2058 | else |
2371 | rs_move_mimo3_to_other(mvm, lq_sta, sta, index); | 2059 | WARN_ON_ONCE(1); |
2372 | 2060 | ||
2373 | /* If new "search" mode was selected, set up in uCode table */ | 2061 | /* If new "search" mode was selected, set up in uCode table */ |
2374 | if (lq_sta->search_better_tbl) { | 2062 | if (lq_sta->search_better_tbl) { |
@@ -2533,11 +2221,10 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta, | |||
2533 | rate_idx -= IWL_FIRST_OFDM_RATE; | 2221 | rate_idx -= IWL_FIRST_OFDM_RATE; |
2534 | /* 6M and 9M shared same MCS index */ | 2222 | /* 6M and 9M shared same MCS index */ |
2535 | rate_idx = (rate_idx > 0) ? (rate_idx - 1) : 0; | 2223 | rate_idx = (rate_idx > 0) ? (rate_idx - 1) : 0; |
2224 | WARN_ON_ONCE(rs_extract_rate(lq_sta->last_rate_n_flags) >= | ||
2225 | IWL_RATE_MIMO3_6M_PLCP); | ||
2536 | if (rs_extract_rate(lq_sta->last_rate_n_flags) >= | 2226 | if (rs_extract_rate(lq_sta->last_rate_n_flags) >= |
2537 | IWL_RATE_MIMO3_6M_PLCP) | 2227 | IWL_RATE_MIMO2_6M_PLCP) |
2538 | rate_idx = rate_idx + (2 * MCS_INDEX_PER_STREAM); | ||
2539 | else if (rs_extract_rate(lq_sta->last_rate_n_flags) >= | ||
2540 | IWL_RATE_MIMO2_6M_PLCP) | ||
2541 | rate_idx = rate_idx + MCS_INDEX_PER_STREAM; | 2228 | rate_idx = rate_idx + MCS_INDEX_PER_STREAM; |
2542 | info->control.rates[0].flags = IEEE80211_TX_RC_MCS; | 2229 | info->control.rates[0].flags = IEEE80211_TX_RC_MCS; |
2543 | if (lq_sta->last_rate_n_flags & RATE_MCS_SGI_MSK) | 2230 | if (lq_sta->last_rate_n_flags & RATE_MCS_SGI_MSK) |
@@ -2636,16 +2323,10 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
2636 | lq_sta->active_mimo2_rate &= ~((u16)0x2); | 2323 | lq_sta->active_mimo2_rate &= ~((u16)0x2); |
2637 | lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; | 2324 | lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; |
2638 | 2325 | ||
2639 | lq_sta->active_mimo3_rate = ht_cap->mcs.rx_mask[2] << 1; | ||
2640 | lq_sta->active_mimo3_rate |= ht_cap->mcs.rx_mask[2] & 0x1; | ||
2641 | lq_sta->active_mimo3_rate &= ~((u16)0x2); | ||
2642 | lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; | ||
2643 | |||
2644 | IWL_DEBUG_RATE(mvm, | 2326 | IWL_DEBUG_RATE(mvm, |
2645 | "SISO-RATE=%X MIMO2-RATE=%X MIMO3-RATE=%X\n", | 2327 | "SISO-RATE=%X MIMO2-RATE=%X\n", |
2646 | lq_sta->active_siso_rate, | 2328 | lq_sta->active_siso_rate, |
2647 | lq_sta->active_mimo2_rate, | 2329 | lq_sta->active_mimo2_rate); |
2648 | lq_sta->active_mimo3_rate); | ||
2649 | 2330 | ||
2650 | /* These values will be overridden later */ | 2331 | /* These values will be overridden later */ |
2651 | lq_sta->lq.single_stream_ant_msk = | 2332 | lq_sta->lq.single_stream_ant_msk = |
@@ -2689,7 +2370,7 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, | |||
2689 | struct iwl_lq_cmd *lq_cmd = &lq_sta->lq; | 2370 | struct iwl_lq_cmd *lq_cmd = &lq_sta->lq; |
2690 | 2371 | ||
2691 | /* Override starting rate (index 0) if needed for debug purposes */ | 2372 | /* Override starting rate (index 0) if needed for debug purposes */ |
2692 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); | 2373 | rs_dbgfs_set_mcs(lq_sta, &new_rate); |
2693 | 2374 | ||
2694 | /* Interpret new_rate (rate_n_flags) */ | 2375 | /* Interpret new_rate (rate_n_flags) */ |
2695 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, | 2376 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, |
@@ -2736,7 +2417,7 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, | |||
2736 | } | 2417 | } |
2737 | 2418 | ||
2738 | /* Override next rate if needed for debug purposes */ | 2419 | /* Override next rate if needed for debug purposes */ |
2739 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); | 2420 | rs_dbgfs_set_mcs(lq_sta, &new_rate); |
2740 | 2421 | ||
2741 | /* Fill next table entry */ | 2422 | /* Fill next table entry */ |
2742 | lq_cmd->rs_table[index] = | 2423 | lq_cmd->rs_table[index] = |
@@ -2778,7 +2459,7 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, | |||
2778 | use_ht_possible = 0; | 2459 | use_ht_possible = 0; |
2779 | 2460 | ||
2780 | /* Override next rate if needed for debug purposes */ | 2461 | /* Override next rate if needed for debug purposes */ |
2781 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); | 2462 | rs_dbgfs_set_mcs(lq_sta, &new_rate); |
2782 | 2463 | ||
2783 | /* Fill next table entry */ | 2464 | /* Fill next table entry */ |
2784 | lq_cmd->rs_table[index] = cpu_to_le32(new_rate); | 2465 | lq_cmd->rs_table[index] = cpu_to_le32(new_rate); |
@@ -2823,7 +2504,7 @@ static void rs_free_sta(void *mvm_r, struct ieee80211_sta *sta, | |||
2823 | 2504 | ||
2824 | #ifdef CONFIG_MAC80211_DEBUGFS | 2505 | #ifdef CONFIG_MAC80211_DEBUGFS |
2825 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | 2506 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, |
2826 | u32 *rate_n_flags, int index) | 2507 | u32 *rate_n_flags) |
2827 | { | 2508 | { |
2828 | struct iwl_mvm *mvm; | 2509 | struct iwl_mvm *mvm; |
2829 | u8 valid_tx_ant; | 2510 | u8 valid_tx_ant; |
@@ -2908,8 +2589,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
2908 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); | 2589 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); |
2909 | if (is_Ht(tbl->lq_type)) { | 2590 | if (is_Ht(tbl->lq_type)) { |
2910 | desc += sprintf(buff+desc, " %s", | 2591 | desc += sprintf(buff+desc, " %s", |
2911 | (is_siso(tbl->lq_type)) ? "SISO" : | 2592 | (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2"); |
2912 | ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); | ||
2913 | desc += sprintf(buff+desc, " %s", | 2593 | desc += sprintf(buff+desc, " %s", |
2914 | (tbl->is_ht40) ? "40MHz" : "20MHz"); | 2594 | (tbl->is_ht40) ? "40MHz" : "20MHz"); |
2915 | desc += sprintf(buff+desc, " %s %s %s\n", | 2595 | desc += sprintf(buff+desc, " %s %s %s\n", |
@@ -3009,32 +2689,6 @@ static const struct file_operations rs_sta_dbgfs_stats_table_ops = { | |||
3009 | .llseek = default_llseek, | 2689 | .llseek = default_llseek, |
3010 | }; | 2690 | }; |
3011 | 2691 | ||
3012 | static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, | ||
3013 | char __user *user_buf, size_t count, loff_t *ppos) | ||
3014 | { | ||
3015 | struct iwl_lq_sta *lq_sta = file->private_data; | ||
3016 | struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl]; | ||
3017 | char buff[120]; | ||
3018 | int desc = 0; | ||
3019 | |||
3020 | if (is_Ht(tbl->lq_type)) | ||
3021 | desc += sprintf(buff+desc, | ||
3022 | "Bit Rate= %d Mb/s\n", | ||
3023 | tbl->expected_tpt[lq_sta->last_txrate_idx]); | ||
3024 | else | ||
3025 | desc += sprintf(buff+desc, | ||
3026 | "Bit Rate= %d Mb/s\n", | ||
3027 | iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); | ||
3028 | |||
3029 | return simple_read_from_buffer(user_buf, count, ppos, buff, desc); | ||
3030 | } | ||
3031 | |||
3032 | static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = { | ||
3033 | .read = rs_sta_dbgfs_rate_scale_data_read, | ||
3034 | .open = simple_open, | ||
3035 | .llseek = default_llseek, | ||
3036 | }; | ||
3037 | |||
3038 | static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir) | 2692 | static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir) |
3039 | { | 2693 | { |
3040 | struct iwl_lq_sta *lq_sta = mvm_sta; | 2694 | struct iwl_lq_sta *lq_sta = mvm_sta; |
@@ -3044,9 +2698,6 @@ static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir) | |||
3044 | lq_sta->rs_sta_dbgfs_stats_table_file = | 2698 | lq_sta->rs_sta_dbgfs_stats_table_file = |
3045 | debugfs_create_file("rate_stats_table", S_IRUSR, dir, | 2699 | debugfs_create_file("rate_stats_table", S_IRUSR, dir, |
3046 | lq_sta, &rs_sta_dbgfs_stats_table_ops); | 2700 | lq_sta, &rs_sta_dbgfs_stats_table_ops); |
3047 | lq_sta->rs_sta_dbgfs_rate_scale_data_file = | ||
3048 | debugfs_create_file("rate_scale_data", S_IRUSR, dir, | ||
3049 | lq_sta, &rs_sta_dbgfs_rate_scale_data_ops); | ||
3050 | lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = | 2701 | lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = |
3051 | debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir, | 2702 | debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir, |
3052 | &lq_sta->tx_agg_tid_en); | 2703 | &lq_sta->tx_agg_tid_en); |
@@ -3057,7 +2708,6 @@ static void rs_remove_debugfs(void *mvm, void *mvm_sta) | |||
3057 | struct iwl_lq_sta *lq_sta = mvm_sta; | 2708 | struct iwl_lq_sta *lq_sta = mvm_sta; |
3058 | debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); | 2709 | debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); |
3059 | debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); | 2710 | debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); |
3060 | debugfs_remove(lq_sta->rs_sta_dbgfs_rate_scale_data_file); | ||
3061 | debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); | 2711 | debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); |
3062 | } | 2712 | } |
3063 | #endif | 2713 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 4a99a4d200ac..335cf1682902 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h | |||
@@ -38,14 +38,8 @@ struct iwl_rs_rate_info { | |||
38 | u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ | 38 | u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ |
39 | u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ | 39 | u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ |
40 | u8 plcp_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */ | 40 | u8 plcp_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */ |
41 | u8 plcp_mimo3; /* uCode API: IWL_RATE_MIMO3_6M_PLCP, etc. */ | ||
42 | u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */ | ||
43 | u8 prev_ieee; /* previous rate in IEEE speeds */ | ||
44 | u8 next_ieee; /* next rate in IEEE speeds */ | ||
45 | u8 prev_rs; /* previous rate used in rs algo */ | 41 | u8 prev_rs; /* previous rate used in rs algo */ |
46 | u8 next_rs; /* next rate used in rs algo */ | 42 | u8 next_rs; /* next rate used in rs algo */ |
47 | u8 prev_rs_tgg; /* previous rate used in TGG rs algo */ | ||
48 | u8 next_rs_tgg; /* next rate used in TGG rs algo */ | ||
49 | }; | 43 | }; |
50 | 44 | ||
51 | #define IWL_RATE_60M_PLCP 3 | 45 | #define IWL_RATE_60M_PLCP 3 |
@@ -120,23 +114,6 @@ enum { | |||
120 | IWL_RATE_MIMO3_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP, | 114 | IWL_RATE_MIMO3_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP, |
121 | }; | 115 | }; |
122 | 116 | ||
123 | /* MAC header values for bit rates */ | ||
124 | enum { | ||
125 | IWL_RATE_6M_IEEE = 12, | ||
126 | IWL_RATE_9M_IEEE = 18, | ||
127 | IWL_RATE_12M_IEEE = 24, | ||
128 | IWL_RATE_18M_IEEE = 36, | ||
129 | IWL_RATE_24M_IEEE = 48, | ||
130 | IWL_RATE_36M_IEEE = 72, | ||
131 | IWL_RATE_48M_IEEE = 96, | ||
132 | IWL_RATE_54M_IEEE = 108, | ||
133 | IWL_RATE_60M_IEEE = 120, | ||
134 | IWL_RATE_1M_IEEE = 2, | ||
135 | IWL_RATE_2M_IEEE = 4, | ||
136 | IWL_RATE_5M_IEEE = 11, | ||
137 | IWL_RATE_11M_IEEE = 22, | ||
138 | }; | ||
139 | |||
140 | #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) | 117 | #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) |
141 | 118 | ||
142 | #define IWL_INVALID_VALUE -1 | 119 | #define IWL_INVALID_VALUE -1 |
@@ -165,47 +142,22 @@ enum { | |||
165 | #define IWL_LEGACY_SWITCH_ANTENNA1 0 | 142 | #define IWL_LEGACY_SWITCH_ANTENNA1 0 |
166 | #define IWL_LEGACY_SWITCH_ANTENNA2 1 | 143 | #define IWL_LEGACY_SWITCH_ANTENNA2 1 |
167 | #define IWL_LEGACY_SWITCH_SISO 2 | 144 | #define IWL_LEGACY_SWITCH_SISO 2 |
168 | #define IWL_LEGACY_SWITCH_MIMO2_AB 3 | 145 | #define IWL_LEGACY_SWITCH_MIMO2 3 |
169 | #define IWL_LEGACY_SWITCH_MIMO2_AC 4 | ||
170 | #define IWL_LEGACY_SWITCH_MIMO2_BC 5 | ||
171 | #define IWL_LEGACY_SWITCH_MIMO3_ABC 6 | ||
172 | 146 | ||
173 | /* possible actions when in siso mode */ | 147 | /* possible actions when in siso mode */ |
174 | #define IWL_SISO_SWITCH_ANTENNA1 0 | 148 | #define IWL_SISO_SWITCH_ANTENNA1 0 |
175 | #define IWL_SISO_SWITCH_ANTENNA2 1 | 149 | #define IWL_SISO_SWITCH_ANTENNA2 1 |
176 | #define IWL_SISO_SWITCH_MIMO2_AB 2 | 150 | #define IWL_SISO_SWITCH_MIMO2 2 |
177 | #define IWL_SISO_SWITCH_MIMO2_AC 3 | 151 | #define IWL_SISO_SWITCH_GI 3 |
178 | #define IWL_SISO_SWITCH_MIMO2_BC 4 | ||
179 | #define IWL_SISO_SWITCH_GI 5 | ||
180 | #define IWL_SISO_SWITCH_MIMO3_ABC 6 | ||
181 | |||
182 | 152 | ||
183 | /* possible actions when in mimo mode */ | 153 | /* possible actions when in mimo mode */ |
184 | #define IWL_MIMO2_SWITCH_ANTENNA1 0 | 154 | #define IWL_MIMO2_SWITCH_ANTENNA1 0 |
185 | #define IWL_MIMO2_SWITCH_ANTENNA2 1 | 155 | #define IWL_MIMO2_SWITCH_ANTENNA2 1 |
186 | #define IWL_MIMO2_SWITCH_SISO_A 2 | 156 | #define IWL_MIMO2_SWITCH_SISO_A 2 |
187 | #define IWL_MIMO2_SWITCH_SISO_B 3 | 157 | #define IWL_MIMO2_SWITCH_SISO_B 3 |
188 | #define IWL_MIMO2_SWITCH_SISO_C 4 | 158 | #define IWL_MIMO2_SWITCH_GI 4 |
189 | #define IWL_MIMO2_SWITCH_GI 5 | ||
190 | #define IWL_MIMO2_SWITCH_MIMO3_ABC 6 | ||
191 | |||
192 | |||
193 | /* possible actions when in mimo3 mode */ | ||
194 | #define IWL_MIMO3_SWITCH_ANTENNA1 0 | ||
195 | #define IWL_MIMO3_SWITCH_ANTENNA2 1 | ||
196 | #define IWL_MIMO3_SWITCH_SISO_A 2 | ||
197 | #define IWL_MIMO3_SWITCH_SISO_B 3 | ||
198 | #define IWL_MIMO3_SWITCH_SISO_C 4 | ||
199 | #define IWL_MIMO3_SWITCH_MIMO2_AB 5 | ||
200 | #define IWL_MIMO3_SWITCH_MIMO2_AC 6 | ||
201 | #define IWL_MIMO3_SWITCH_MIMO2_BC 7 | ||
202 | #define IWL_MIMO3_SWITCH_GI 8 | ||
203 | |||
204 | |||
205 | #define IWL_MAX_11N_MIMO3_SEARCH IWL_MIMO3_SWITCH_GI | ||
206 | #define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_MIMO3_ABC | ||
207 | 159 | ||
208 | /*FIXME:RS:add possible actions for MIMO3*/ | 160 | #define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_GI |
209 | 161 | ||
210 | #define IWL_ACTION_LIMIT 3 /* # possible actions */ | 162 | #define IWL_ACTION_LIMIT 3 /* # possible actions */ |
211 | 163 | ||
@@ -240,15 +192,13 @@ enum iwl_table_type { | |||
240 | LQ_A, | 192 | LQ_A, |
241 | LQ_SISO, /* high-throughput types */ | 193 | LQ_SISO, /* high-throughput types */ |
242 | LQ_MIMO2, | 194 | LQ_MIMO2, |
243 | LQ_MIMO3, | ||
244 | LQ_MAX, | 195 | LQ_MAX, |
245 | }; | 196 | }; |
246 | 197 | ||
247 | #define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A)) | 198 | #define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A)) |
248 | #define is_siso(tbl) ((tbl) == LQ_SISO) | 199 | #define is_siso(tbl) ((tbl) == LQ_SISO) |
249 | #define is_mimo2(tbl) ((tbl) == LQ_MIMO2) | 200 | #define is_mimo2(tbl) ((tbl) == LQ_MIMO2) |
250 | #define is_mimo3(tbl) ((tbl) == LQ_MIMO3) | 201 | #define is_mimo(tbl) is_mimo2(tbl) |
251 | #define is_mimo(tbl) (is_mimo2(tbl) || is_mimo3(tbl)) | ||
252 | #define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl)) | 202 | #define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl)) |
253 | #define is_a_band(tbl) ((tbl) == LQ_A) | 203 | #define is_a_band(tbl) ((tbl) == LQ_A) |
254 | #define is_g_and(tbl) ((tbl) == LQ_G) | 204 | #define is_g_and(tbl) ((tbl) == LQ_G) |
@@ -320,7 +270,6 @@ struct iwl_lq_sta { | |||
320 | u16 active_legacy_rate; | 270 | u16 active_legacy_rate; |
321 | u16 active_siso_rate; | 271 | u16 active_siso_rate; |
322 | u16 active_mimo2_rate; | 272 | u16 active_mimo2_rate; |
323 | u16 active_mimo3_rate; | ||
324 | s8 max_rate_idx; /* Max rate set by user */ | 273 | s8 max_rate_idx; /* Max rate set by user */ |
325 | u8 missed_rate_counter; | 274 | u8 missed_rate_counter; |
326 | 275 | ||
@@ -330,7 +279,6 @@ struct iwl_lq_sta { | |||
330 | #ifdef CONFIG_MAC80211_DEBUGFS | 279 | #ifdef CONFIG_MAC80211_DEBUGFS |
331 | struct dentry *rs_sta_dbgfs_scale_table_file; | 280 | struct dentry *rs_sta_dbgfs_scale_table_file; |
332 | struct dentry *rs_sta_dbgfs_stats_table_file; | 281 | struct dentry *rs_sta_dbgfs_stats_table_file; |
333 | struct dentry *rs_sta_dbgfs_rate_scale_data_file; | ||
334 | struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; | 282 | struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; |
335 | u32 dbg_fixed_rate; | 283 | u32 dbg_fixed_rate; |
336 | #endif | 284 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index ee6547d22287..2a8cb5a60535 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
@@ -396,11 +396,62 @@ static void iwl_mvm_update_rx_statistics(struct iwl_mvm *mvm, | |||
396 | memcpy(&mvm->rx_stats, &stats->rx, sizeof(struct mvm_statistics_rx)); | 396 | memcpy(&mvm->rx_stats, &stats->rx, sizeof(struct mvm_statistics_rx)); |
397 | } | 397 | } |
398 | 398 | ||
399 | struct iwl_mvm_stat_data { | ||
400 | struct iwl_notif_statistics *stats; | ||
401 | struct iwl_mvm *mvm; | ||
402 | }; | ||
403 | |||
404 | static void iwl_mvm_stat_iterator(void *_data, u8 *mac, | ||
405 | struct ieee80211_vif *vif) | ||
406 | { | ||
407 | struct iwl_mvm_stat_data *data = _data; | ||
408 | struct iwl_notif_statistics *stats = data->stats; | ||
409 | struct iwl_mvm *mvm = data->mvm; | ||
410 | int sig = -stats->general.beacon_filter_average_energy; | ||
411 | int last_event; | ||
412 | int thold = vif->bss_conf.cqm_rssi_thold; | ||
413 | int hyst = vif->bss_conf.cqm_rssi_hyst; | ||
414 | u16 id = le32_to_cpu(stats->rx.general.mac_id); | ||
415 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
416 | |||
417 | if (mvmvif->id != id) | ||
418 | return; | ||
419 | |||
420 | if (vif->type != NL80211_IFTYPE_STATION) | ||
421 | return; | ||
422 | |||
423 | mvmvif->bf_data.ave_beacon_signal = sig; | ||
424 | |||
425 | if (!(vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)) | ||
426 | return; | ||
427 | |||
428 | /* CQM Notification */ | ||
429 | last_event = mvmvif->bf_data.last_cqm_event; | ||
430 | if (thold && sig < thold && (last_event == 0 || | ||
431 | sig < last_event - hyst)) { | ||
432 | mvmvif->bf_data.last_cqm_event = sig; | ||
433 | IWL_DEBUG_RX(mvm, "cqm_iterator cqm low %d\n", | ||
434 | sig); | ||
435 | ieee80211_cqm_rssi_notify( | ||
436 | vif, | ||
437 | NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, | ||
438 | GFP_KERNEL); | ||
439 | } else if (sig > thold && | ||
440 | (last_event == 0 || sig > last_event + hyst)) { | ||
441 | mvmvif->bf_data.last_cqm_event = sig; | ||
442 | IWL_DEBUG_RX(mvm, "cqm_iterator cqm high %d\n", | ||
443 | sig); | ||
444 | ieee80211_cqm_rssi_notify( | ||
445 | vif, | ||
446 | NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, | ||
447 | GFP_KERNEL); | ||
448 | } | ||
449 | } | ||
450 | |||
399 | /* | 451 | /* |
400 | * iwl_mvm_rx_statistics - STATISTICS_NOTIFICATION handler | 452 | * iwl_mvm_rx_statistics - STATISTICS_NOTIFICATION handler |
401 | * | 453 | * |
402 | * TODO: This handler is implemented partially. | 454 | * TODO: This handler is implemented partially. |
403 | * It only gets the NIC's temperature. | ||
404 | */ | 455 | */ |
405 | int iwl_mvm_rx_statistics(struct iwl_mvm *mvm, | 456 | int iwl_mvm_rx_statistics(struct iwl_mvm *mvm, |
406 | struct iwl_rx_cmd_buffer *rxb, | 457 | struct iwl_rx_cmd_buffer *rxb, |
@@ -409,6 +460,10 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm, | |||
409 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 460 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
410 | struct iwl_notif_statistics *stats = (void *)&pkt->data; | 461 | struct iwl_notif_statistics *stats = (void *)&pkt->data; |
411 | struct mvm_statistics_general_common *common = &stats->general.common; | 462 | struct mvm_statistics_general_common *common = &stats->general.common; |
463 | struct iwl_mvm_stat_data data = { | ||
464 | .stats = stats, | ||
465 | .mvm = mvm, | ||
466 | }; | ||
412 | 467 | ||
413 | if (mvm->temperature != le32_to_cpu(common->temperature)) { | 468 | if (mvm->temperature != le32_to_cpu(common->temperature)) { |
414 | mvm->temperature = le32_to_cpu(common->temperature); | 469 | mvm->temperature = le32_to_cpu(common->temperature); |
@@ -416,5 +471,9 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm, | |||
416 | } | 471 | } |
417 | iwl_mvm_update_rx_statistics(mvm, stats); | 472 | iwl_mvm_update_rx_statistics(mvm, stats); |
418 | 473 | ||
474 | ieee80211_iterate_active_interfaces(mvm->hw, | ||
475 | IEEE80211_IFACE_ITER_NORMAL, | ||
476 | iwl_mvm_stat_iterator, | ||
477 | &data); | ||
419 | return 0; | 478 | return 0; |
420 | } | 479 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index 9f100363b177..f5329d22840e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -165,7 +165,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, | |||
165 | WARN_ONCE(!le32_to_cpu(notif->status), | 165 | WARN_ONCE(!le32_to_cpu(notif->status), |
166 | "Failed to schedule time event\n"); | 166 | "Failed to schedule time event\n"); |
167 | 167 | ||
168 | if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_END) { | 168 | if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_END) { |
169 | IWL_DEBUG_TE(mvm, | 169 | IWL_DEBUG_TE(mvm, |
170 | "TE ended - current time %lu, estimated end %lu\n", | 170 | "TE ended - current time %lu, estimated end %lu\n", |
171 | jiffies, te_data->end_jiffies); | 171 | jiffies, te_data->end_jiffies); |
@@ -188,7 +188,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, | |||
188 | } | 188 | } |
189 | 189 | ||
190 | iwl_mvm_te_clear_data(mvm, te_data); | 190 | iwl_mvm_te_clear_data(mvm, te_data); |
191 | } else if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_START) { | 191 | } else if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_START) { |
192 | te_data->running = true; | 192 | te_data->running = true; |
193 | te_data->end_jiffies = TU_TO_EXP_TIME(te_data->duration); | 193 | te_data->end_jiffies = TU_TO_EXP_TIME(te_data->duration); |
194 | 194 | ||
@@ -255,10 +255,67 @@ static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait, | |||
255 | return true; | 255 | return true; |
256 | } | 256 | } |
257 | 257 | ||
258 | /* used to convert from time event API v2 to v1 */ | ||
259 | #define TE_V2_DEP_POLICY_MSK (TE_V2_DEP_OTHER | TE_V2_DEP_TSF |\ | ||
260 | TE_V2_EVENT_SOCIOPATHIC) | ||
261 | static inline u16 te_v2_get_notify(__le16 policy) | ||
262 | { | ||
263 | return le16_to_cpu(policy) & TE_V2_NOTIF_MSK; | ||
264 | } | ||
265 | |||
266 | static inline u16 te_v2_get_dep_policy(__le16 policy) | ||
267 | { | ||
268 | return (le16_to_cpu(policy) & TE_V2_DEP_POLICY_MSK) >> | ||
269 | TE_V2_PLACEMENT_POS; | ||
270 | } | ||
271 | |||
272 | static inline u16 te_v2_get_absence(__le16 policy) | ||
273 | { | ||
274 | return (le16_to_cpu(policy) & TE_V2_ABSENCE) >> TE_V2_ABSENCE_POS; | ||
275 | } | ||
276 | |||
277 | static void iwl_mvm_te_v2_to_v1(const struct iwl_time_event_cmd_v2 *cmd_v2, | ||
278 | struct iwl_time_event_cmd_v1 *cmd_v1) | ||
279 | { | ||
280 | cmd_v1->id_and_color = cmd_v2->id_and_color; | ||
281 | cmd_v1->action = cmd_v2->action; | ||
282 | cmd_v1->id = cmd_v2->id; | ||
283 | cmd_v1->apply_time = cmd_v2->apply_time; | ||
284 | cmd_v1->max_delay = cmd_v2->max_delay; | ||
285 | cmd_v1->depends_on = cmd_v2->depends_on; | ||
286 | cmd_v1->interval = cmd_v2->interval; | ||
287 | cmd_v1->duration = cmd_v2->duration; | ||
288 | if (cmd_v2->repeat == TE_V2_REPEAT_ENDLESS) | ||
289 | cmd_v1->repeat = cpu_to_le32(TE_V1_REPEAT_ENDLESS); | ||
290 | else | ||
291 | cmd_v1->repeat = cpu_to_le32(cmd_v2->repeat); | ||
292 | cmd_v1->max_frags = cpu_to_le32(cmd_v2->max_frags); | ||
293 | cmd_v1->interval_reciprocal = 0; /* unused */ | ||
294 | |||
295 | cmd_v1->dep_policy = cpu_to_le32(te_v2_get_dep_policy(cmd_v2->policy)); | ||
296 | cmd_v1->is_present = cpu_to_le32(!te_v2_get_absence(cmd_v2->policy)); | ||
297 | cmd_v1->notify = cpu_to_le32(te_v2_get_notify(cmd_v2->policy)); | ||
298 | } | ||
299 | |||
300 | static int iwl_mvm_send_time_event_cmd(struct iwl_mvm *mvm, | ||
301 | const struct iwl_time_event_cmd_v2 *cmd) | ||
302 | { | ||
303 | struct iwl_time_event_cmd_v1 cmd_v1; | ||
304 | |||
305 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2) | ||
306 | return iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, | ||
307 | sizeof(*cmd), cmd); | ||
308 | |||
309 | iwl_mvm_te_v2_to_v1(cmd, &cmd_v1); | ||
310 | return iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, | ||
311 | sizeof(cmd_v1), &cmd_v1); | ||
312 | } | ||
313 | |||
314 | |||
258 | static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, | 315 | static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, |
259 | struct ieee80211_vif *vif, | 316 | struct ieee80211_vif *vif, |
260 | struct iwl_mvm_time_event_data *te_data, | 317 | struct iwl_mvm_time_event_data *te_data, |
261 | struct iwl_time_event_cmd *te_cmd) | 318 | struct iwl_time_event_cmd_v2 *te_cmd) |
262 | { | 319 | { |
263 | static const u8 time_event_response[] = { TIME_EVENT_CMD }; | 320 | static const u8 time_event_response[] = { TIME_EVENT_CMD }; |
264 | struct iwl_notification_wait wait_time_event; | 321 | struct iwl_notification_wait wait_time_event; |
@@ -294,8 +351,7 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, | |||
294 | ARRAY_SIZE(time_event_response), | 351 | ARRAY_SIZE(time_event_response), |
295 | iwl_mvm_time_event_response, te_data); | 352 | iwl_mvm_time_event_response, te_data); |
296 | 353 | ||
297 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, | 354 | ret = iwl_mvm_send_time_event_cmd(mvm, te_cmd); |
298 | sizeof(*te_cmd), te_cmd); | ||
299 | if (ret) { | 355 | if (ret) { |
300 | IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret); | 356 | IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret); |
301 | iwl_remove_notification(&mvm->notif_wait, &wait_time_event); | 357 | iwl_remove_notification(&mvm->notif_wait, &wait_time_event); |
@@ -322,7 +378,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, | |||
322 | { | 378 | { |
323 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 379 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
324 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; | 380 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; |
325 | struct iwl_time_event_cmd time_cmd = {}; | 381 | struct iwl_time_event_cmd_v2 time_cmd = {}; |
326 | 382 | ||
327 | lockdep_assert_held(&mvm->mutex); | 383 | lockdep_assert_held(&mvm->mutex); |
328 | 384 | ||
@@ -356,17 +412,14 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, | |||
356 | time_cmd.apply_time = | 412 | time_cmd.apply_time = |
357 | cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG)); | 413 | cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG)); |
358 | 414 | ||
359 | time_cmd.dep_policy = TE_INDEPENDENT; | 415 | time_cmd.max_frags = TE_V2_FRAG_NONE; |
360 | time_cmd.is_present = cpu_to_le32(1); | ||
361 | time_cmd.max_frags = cpu_to_le32(TE_FRAG_NONE); | ||
362 | time_cmd.max_delay = cpu_to_le32(500); | 416 | time_cmd.max_delay = cpu_to_le32(500); |
363 | /* TODO: why do we need to interval = bi if it is not periodic? */ | 417 | /* TODO: why do we need to interval = bi if it is not periodic? */ |
364 | time_cmd.interval = cpu_to_le32(1); | 418 | time_cmd.interval = cpu_to_le32(1); |
365 | time_cmd.interval_reciprocal = cpu_to_le32(iwl_mvm_reciprocal(1)); | ||
366 | time_cmd.duration = cpu_to_le32(duration); | 419 | time_cmd.duration = cpu_to_le32(duration); |
367 | time_cmd.repeat = cpu_to_le32(1); | 420 | time_cmd.repeat = 1; |
368 | time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_EVENT_START | | 421 | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | |
369 | TE_NOTIF_HOST_EVENT_END); | 422 | TE_V2_NOTIF_HOST_EVENT_END); |
370 | 423 | ||
371 | iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); | 424 | iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); |
372 | } | 425 | } |
@@ -380,7 +433,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm, | |||
380 | struct iwl_mvm_vif *mvmvif, | 433 | struct iwl_mvm_vif *mvmvif, |
381 | struct iwl_mvm_time_event_data *te_data) | 434 | struct iwl_mvm_time_event_data *te_data) |
382 | { | 435 | { |
383 | struct iwl_time_event_cmd time_cmd = {}; | 436 | struct iwl_time_event_cmd_v2 time_cmd = {}; |
384 | u32 id, uid; | 437 | u32 id, uid; |
385 | int ret; | 438 | int ret; |
386 | 439 | ||
@@ -417,8 +470,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm, | |||
417 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); | 470 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); |
418 | 471 | ||
419 | IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); | 472 | IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); |
420 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, | 473 | ret = iwl_mvm_send_time_event_cmd(mvm, &time_cmd); |
421 | sizeof(time_cmd), &time_cmd); | ||
422 | if (WARN_ON(ret)) | 474 | if (WARN_ON(ret)) |
423 | return; | 475 | return; |
424 | } | 476 | } |
@@ -438,7 +490,7 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
438 | { | 490 | { |
439 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 491 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
440 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; | 492 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; |
441 | struct iwl_time_event_cmd time_cmd = {}; | 493 | struct iwl_time_event_cmd_v2 time_cmd = {}; |
442 | 494 | ||
443 | lockdep_assert_held(&mvm->mutex); | 495 | lockdep_assert_held(&mvm->mutex); |
444 | if (te_data->running) { | 496 | if (te_data->running) { |
@@ -469,8 +521,6 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
469 | } | 521 | } |
470 | 522 | ||
471 | time_cmd.apply_time = cpu_to_le32(0); | 523 | time_cmd.apply_time = cpu_to_le32(0); |
472 | time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT); | ||
473 | time_cmd.is_present = cpu_to_le32(1); | ||
474 | time_cmd.interval = cpu_to_le32(1); | 524 | time_cmd.interval = cpu_to_le32(1); |
475 | 525 | ||
476 | /* | 526 | /* |
@@ -479,12 +529,12 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
479 | * scheduled. To improve the chances of it being scheduled, allow them | 529 | * scheduled. To improve the chances of it being scheduled, allow them |
480 | * to be fragmented, and in addition allow them to be delayed. | 530 | * to be fragmented, and in addition allow them to be delayed. |
481 | */ | 531 | */ |
482 | time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20); | 532 | time_cmd.max_frags = min(MSEC_TO_TU(duration)/50, TE_V2_FRAG_ENDLESS); |
483 | time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2)); | 533 | time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2)); |
484 | time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration)); | 534 | time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration)); |
485 | time_cmd.repeat = cpu_to_le32(1); | 535 | time_cmd.repeat = 1; |
486 | time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_EVENT_START | | 536 | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | |
487 | TE_NOTIF_HOST_EVENT_END); | 537 | TE_V2_NOTIF_HOST_EVENT_END); |
488 | 538 | ||
489 | return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); | 539 | return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); |
490 | } | 540 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 158669ee4ce5..dc02cb9792af 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
@@ -325,15 +325,15 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
325 | int ret; | 325 | int ret; |
326 | 326 | ||
327 | iwl_trans = iwl_trans_pcie_alloc(pdev, ent, cfg); | 327 | iwl_trans = iwl_trans_pcie_alloc(pdev, ent, cfg); |
328 | if (iwl_trans == NULL) | 328 | if (IS_ERR(iwl_trans)) |
329 | return -ENOMEM; | 329 | return PTR_ERR(iwl_trans); |
330 | 330 | ||
331 | pci_set_drvdata(pdev, iwl_trans); | 331 | pci_set_drvdata(pdev, iwl_trans); |
332 | 332 | ||
333 | trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans); | 333 | trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans); |
334 | trans_pcie->drv = iwl_drv_start(iwl_trans, cfg); | 334 | trans_pcie->drv = iwl_drv_start(iwl_trans, cfg); |
335 | 335 | ||
336 | if (IS_ERR_OR_NULL(trans_pcie->drv)) { | 336 | if (IS_ERR(trans_pcie->drv)) { |
337 | ret = PTR_ERR(trans_pcie->drv); | 337 | ret = PTR_ERR(trans_pcie->drv); |
338 | goto out_free_trans; | 338 | goto out_free_trans; |
339 | } | 339 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 68837d4e9fa0..a4c7aeb786d2 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -112,15 +112,16 @@ | |||
112 | */ | 112 | */ |
113 | static int iwl_rxq_space(const struct iwl_rxq *rxq) | 113 | static int iwl_rxq_space(const struct iwl_rxq *rxq) |
114 | { | 114 | { |
115 | int s = rxq->read - rxq->write; | 115 | /* Make sure RX_QUEUE_SIZE is a power of 2 */ |
116 | 116 | BUILD_BUG_ON(RX_QUEUE_SIZE & (RX_QUEUE_SIZE - 1)); | |
117 | if (s <= 0) | 117 | |
118 | s += RX_QUEUE_SIZE; | 118 | /* |
119 | /* keep some buffer to not confuse full and empty queue */ | 119 | * There can be up to (RX_QUEUE_SIZE - 1) free slots, to avoid ambiguity |
120 | s -= 2; | 120 | * between empty and completely full queues. |
121 | if (s < 0) | 121 | * The following is equivalent to modulo by RX_QUEUE_SIZE and is well |
122 | s = 0; | 122 | * defined for negative dividends. |
123 | return s; | 123 | */ |
124 | return (rxq->read - rxq->write - 1) & (RX_QUEUE_SIZE - 1); | ||
124 | } | 125 | } |
125 | 126 | ||
126 | /* | 127 | /* |
@@ -1128,6 +1129,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data) | |||
1128 | struct iwl_trans *trans = data; | 1129 | struct iwl_trans *trans = data; |
1129 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1130 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1130 | u32 inta, inta_mask; | 1131 | u32 inta, inta_mask; |
1132 | irqreturn_t ret = IRQ_NONE; | ||
1131 | 1133 | ||
1132 | lockdep_assert_held(&trans_pcie->irq_lock); | 1134 | lockdep_assert_held(&trans_pcie->irq_lock); |
1133 | 1135 | ||
@@ -1176,10 +1178,8 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data) | |||
1176 | /* the thread will service interrupts and re-enable them */ | 1178 | /* the thread will service interrupts and re-enable them */ |
1177 | if (likely(inta)) | 1179 | if (likely(inta)) |
1178 | return IRQ_WAKE_THREAD; | 1180 | return IRQ_WAKE_THREAD; |
1179 | else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && | 1181 | |
1180 | !trans_pcie->inta) | 1182 | ret = IRQ_HANDLED; |
1181 | iwl_enable_interrupts(trans); | ||
1182 | return IRQ_HANDLED; | ||
1183 | 1183 | ||
1184 | none: | 1184 | none: |
1185 | /* re-enable interrupts here since we don't have anything to service. */ | 1185 | /* re-enable interrupts here since we don't have anything to service. */ |
@@ -1188,7 +1188,7 @@ none: | |||
1188 | !trans_pcie->inta) | 1188 | !trans_pcie->inta) |
1189 | iwl_enable_interrupts(trans); | 1189 | iwl_enable_interrupts(trans); |
1190 | 1190 | ||
1191 | return IRQ_NONE; | 1191 | return ret; |
1192 | } | 1192 | } |
1193 | 1193 | ||
1194 | /* interrupt handler using ict table, with this interrupt driver will | 1194 | /* interrupt handler using ict table, with this interrupt driver will |
@@ -1207,6 +1207,7 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data) | |||
1207 | u32 val = 0; | 1207 | u32 val = 0; |
1208 | u32 read; | 1208 | u32 read; |
1209 | unsigned long flags; | 1209 | unsigned long flags; |
1210 | irqreturn_t ret = IRQ_NONE; | ||
1210 | 1211 | ||
1211 | if (!trans) | 1212 | if (!trans) |
1212 | return IRQ_NONE; | 1213 | return IRQ_NONE; |
@@ -1219,7 +1220,7 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data) | |||
1219 | * use legacy interrupt. | 1220 | * use legacy interrupt. |
1220 | */ | 1221 | */ |
1221 | if (unlikely(!trans_pcie->use_ict)) { | 1222 | if (unlikely(!trans_pcie->use_ict)) { |
1222 | irqreturn_t ret = iwl_pcie_isr(irq, data); | 1223 | ret = iwl_pcie_isr(irq, data); |
1223 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 1224 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
1224 | return ret; | 1225 | return ret; |
1225 | } | 1226 | } |
@@ -1288,17 +1289,9 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data) | |||
1288 | if (likely(inta)) { | 1289 | if (likely(inta)) { |
1289 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 1290 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
1290 | return IRQ_WAKE_THREAD; | 1291 | return IRQ_WAKE_THREAD; |
1291 | } else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && | ||
1292 | !trans_pcie->inta) { | ||
1293 | /* Allow interrupt if was disabled by this handler and | ||
1294 | * no tasklet was schedules, We should not enable interrupt, | ||
1295 | * tasklet will enable it. | ||
1296 | */ | ||
1297 | iwl_enable_interrupts(trans); | ||
1298 | } | 1292 | } |
1299 | 1293 | ||
1300 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 1294 | ret = IRQ_HANDLED; |
1301 | return IRQ_HANDLED; | ||
1302 | 1295 | ||
1303 | none: | 1296 | none: |
1304 | /* re-enable interrupts here since we don't have anything to service. | 1297 | /* re-enable interrupts here since we don't have anything to service. |
@@ -1309,5 +1302,5 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data) | |||
1309 | iwl_enable_interrupts(trans); | 1302 | iwl_enable_interrupts(trans); |
1310 | 1303 | ||
1311 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 1304 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
1312 | return IRQ_NONE; | 1305 | return ret; |
1313 | } | 1306 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index e52d1ce1501c..bad95d28d50d 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -1386,9 +1386,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
1386 | 1386 | ||
1387 | trans = kzalloc(sizeof(struct iwl_trans) + | 1387 | trans = kzalloc(sizeof(struct iwl_trans) + |
1388 | sizeof(struct iwl_trans_pcie), GFP_KERNEL); | 1388 | sizeof(struct iwl_trans_pcie), GFP_KERNEL); |
1389 | 1389 | if (!trans) { | |
1390 | if (!trans) | 1390 | err = -ENOMEM; |
1391 | return NULL; | 1391 | goto out; |
1392 | } | ||
1392 | 1393 | ||
1393 | trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1394 | trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1394 | 1395 | ||
@@ -1411,10 +1412,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
1411 | PCIE_LINK_STATE_CLKPM); | 1412 | PCIE_LINK_STATE_CLKPM); |
1412 | } | 1413 | } |
1413 | 1414 | ||
1414 | if (pci_enable_device(pdev)) { | 1415 | err = pci_enable_device(pdev); |
1415 | err = -ENODEV; | 1416 | if (err) |
1416 | goto out_no_pci; | 1417 | goto out_no_pci; |
1417 | } | ||
1418 | 1418 | ||
1419 | pci_set_master(pdev); | 1419 | pci_set_master(pdev); |
1420 | 1420 | ||
@@ -1483,17 +1483,20 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
1483 | SLAB_HWCACHE_ALIGN, | 1483 | SLAB_HWCACHE_ALIGN, |
1484 | NULL); | 1484 | NULL); |
1485 | 1485 | ||
1486 | if (!trans->dev_cmd_pool) | 1486 | if (!trans->dev_cmd_pool) { |
1487 | err = -ENOMEM; | ||
1487 | goto out_pci_disable_msi; | 1488 | goto out_pci_disable_msi; |
1489 | } | ||
1488 | 1490 | ||
1489 | trans_pcie->inta_mask = CSR_INI_SET_MASK; | 1491 | trans_pcie->inta_mask = CSR_INI_SET_MASK; |
1490 | 1492 | ||
1491 | if (iwl_pcie_alloc_ict(trans)) | 1493 | if (iwl_pcie_alloc_ict(trans)) |
1492 | goto out_free_cmd_pool; | 1494 | goto out_free_cmd_pool; |
1493 | 1495 | ||
1494 | if (request_threaded_irq(pdev->irq, iwl_pcie_isr_ict, | 1496 | err = request_threaded_irq(pdev->irq, iwl_pcie_isr_ict, |
1495 | iwl_pcie_irq_handler, | 1497 | iwl_pcie_irq_handler, |
1496 | IRQF_SHARED, DRV_NAME, trans)) { | 1498 | IRQF_SHARED, DRV_NAME, trans); |
1499 | if (err) { | ||
1497 | IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq); | 1500 | IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq); |
1498 | goto out_free_ict; | 1501 | goto out_free_ict; |
1499 | } | 1502 | } |
@@ -1512,5 +1515,6 @@ out_pci_disable_device: | |||
1512 | pci_disable_device(pdev); | 1515 | pci_disable_device(pdev); |
1513 | out_no_pci: | 1516 | out_no_pci: |
1514 | kfree(trans); | 1517 | kfree(trans); |
1515 | return NULL; | 1518 | out: |
1519 | return ERR_PTR(err); | ||
1516 | } | 1520 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 011167c22da8..f45eb29c2ede 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -65,18 +65,30 @@ | |||
65 | ***************************************************/ | 65 | ***************************************************/ |
66 | static int iwl_queue_space(const struct iwl_queue *q) | 66 | static int iwl_queue_space(const struct iwl_queue *q) |
67 | { | 67 | { |
68 | int s = q->read_ptr - q->write_ptr; | 68 | unsigned int max; |
69 | 69 | unsigned int used; | |
70 | if (q->read_ptr > q->write_ptr) | 70 | |
71 | s -= q->n_bd; | 71 | /* |
72 | 72 | * To avoid ambiguity between empty and completely full queues, there | |
73 | if (s <= 0) | 73 | * should always be less than q->n_bd elements in the queue. |
74 | s += q->n_window; | 74 | * If q->n_window is smaller than q->n_bd, there is no need to reserve |
75 | /* keep some reserve to not confuse empty and full situations */ | 75 | * any queue entries for this purpose. |
76 | s -= 2; | 76 | */ |
77 | if (s < 0) | 77 | if (q->n_window < q->n_bd) |
78 | s = 0; | 78 | max = q->n_window; |
79 | return s; | 79 | else |
80 | max = q->n_bd - 1; | ||
81 | |||
82 | /* | ||
83 | * q->n_bd is a power of 2, so the following is equivalent to modulo by | ||
84 | * q->n_bd and is well defined for negative dividends. | ||
85 | */ | ||
86 | used = (q->write_ptr - q->read_ptr) & (q->n_bd - 1); | ||
87 | |||
88 | if (WARN_ON(used > max)) | ||
89 | return 0; | ||
90 | |||
91 | return max - used; | ||
80 | } | 92 | } |
81 | 93 | ||
82 | /* | 94 | /* |
@@ -826,7 +838,7 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans) | |||
826 | sizeof(struct iwl_txq), GFP_KERNEL); | 838 | sizeof(struct iwl_txq), GFP_KERNEL); |
827 | if (!trans_pcie->txq) { | 839 | if (!trans_pcie->txq) { |
828 | IWL_ERR(trans, "Not enough memory for txq\n"); | 840 | IWL_ERR(trans, "Not enough memory for txq\n"); |
829 | ret = ENOMEM; | 841 | ret = -ENOMEM; |
830 | goto error; | 842 | goto error; |
831 | } | 843 | } |
832 | 844 | ||