Commit 5a292f7bc641bc16277173d1ff7cfe8cba298f00
Exists in
master
and in
13 other branches
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
John W. Linville says: ==================== pull request: wireless 2014-04-17 Please pull this batch of fixes intended for the 3.15 stream... For the mac80211 bits, Johannes says: "We have a fix from Chun-Yeow to not look at management frame bitrates that are typically really low, two fixes from Felix for AP_VLAN interfaces, a fix from Ido to disable SMPS settings when a monitor interface is enabled, a radar detection fix from Michał and a fix from myself for a very old remain-on-channel bug." For the iwlwifi bits, Emmanuel says: "I have new device IDs and a new firmware API. These are the trivial ones. The less trivial ones are Johannes's fix that delays the enablement of an interrupt coalescing hardware until after association - this fixes a few connection problems seen in the field. Eyal has a bunch of rate control fixes. I decided to add these for 3.15 because they fix some disconnection and packet loss scenarios which were reported by the field. I also have a fix for a memory leak that happens only with a very new NIC." Along with those... Amitkumar Karwar fixes a couple of problems relating to driver/firmware interactions in mwifiex. Christian Engelmayer avoids a couple of potential memory leaks in the new rsi driver. Eliad Peller provides a wl18xx mailbox alignment fix for problems when using new firmware. Frederic Danis adds a couple of missing debugging strings to the cw1200 driver. Geert Uytterhoeven adds a variable initialization inside of the rsi driver. Luciano Coelho patches the wlcore code to ignore dummy packet events in PLT mode in order to work around a firmware bug. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 18 changed files Side-by-side Diff
- drivers/net/wireless/cw1200/debug.c
- drivers/net/wireless/iwlwifi/iwl-7000.c
- drivers/net/wireless/iwlwifi/mvm/coex.c
- drivers/net/wireless/iwlwifi/mvm/mac80211.c
- drivers/net/wireless/iwlwifi/mvm/rs.c
- drivers/net/wireless/iwlwifi/mvm/rs.h
- drivers/net/wireless/iwlwifi/mvm/sf.c
- drivers/net/wireless/iwlwifi/pcie/drv.c
- drivers/net/wireless/mwifiex/main.c
- drivers/net/wireless/mwifiex/sta_ioctl.c
- drivers/net/wireless/rsi/rsi_91x_core.c
- drivers/net/wireless/rsi/rsi_91x_mgmt.c
- drivers/net/wireless/ti/wl18xx/event.h
- drivers/net/wireless/ti/wlcore/event.c
- net/mac80211/chan.c
- net/mac80211/main.c
- net/mac80211/offchannel.c
- net/mac80211/status.c
drivers/net/wireless/cw1200/debug.c
drivers/net/wireless/iwlwifi/iwl-7000.c
... | ... | @@ -67,8 +67,8 @@ |
67 | 67 | #include "iwl-agn-hw.h" |
68 | 68 | |
69 | 69 | /* Highest firmware API version supported */ |
70 | -#define IWL7260_UCODE_API_MAX 8 | |
71 | -#define IWL3160_UCODE_API_MAX 8 | |
70 | +#define IWL7260_UCODE_API_MAX 9 | |
71 | +#define IWL3160_UCODE_API_MAX 9 | |
72 | 72 | |
73 | 73 | /* Oldest version we won't warn about */ |
74 | 74 | #define IWL7260_UCODE_API_OK 8 |
... | ... | @@ -244,4 +244,5 @@ |
244 | 244 | |
245 | 245 | MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); |
246 | 246 | MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); |
247 | +MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); |
drivers/net/wireless/iwlwifi/mvm/coex.c
... | ... | @@ -190,7 +190,7 @@ |
190 | 190 | cpu_to_le32(0xcc00aaaa), |
191 | 191 | cpu_to_le32(0x0000aaaa), |
192 | 192 | cpu_to_le32(0xc0004000), |
193 | - cpu_to_le32(0x00000000), | |
193 | + cpu_to_le32(0x00004000), | |
194 | 194 | cpu_to_le32(0xf0005000), |
195 | 195 | cpu_to_le32(0xf0005000), |
196 | 196 | }, |
197 | 197 | |
198 | 198 | |
... | ... | @@ -213,16 +213,16 @@ |
213 | 213 | /* Tx Tx disabled */ |
214 | 214 | cpu_to_le32(0xaaaaaaaa), |
215 | 215 | cpu_to_le32(0xaaaaaaaa), |
216 | + cpu_to_le32(0xeeaaaaaa), | |
216 | 217 | cpu_to_le32(0xaaaaaaaa), |
217 | - cpu_to_le32(0xaaaaaaaa), | |
218 | 218 | cpu_to_le32(0xcc00ff28), |
219 | 219 | cpu_to_le32(0x0000aaaa), |
220 | 220 | cpu_to_le32(0xcc00aaaa), |
221 | 221 | cpu_to_le32(0x0000aaaa), |
222 | - cpu_to_le32(0xC0004000), | |
223 | - cpu_to_le32(0xC0004000), | |
224 | - cpu_to_le32(0xF0005000), | |
225 | - cpu_to_le32(0xF0005000), | |
222 | + cpu_to_le32(0xc0004000), | |
223 | + cpu_to_le32(0xc0004000), | |
224 | + cpu_to_le32(0xf0005000), | |
225 | + cpu_to_le32(0xf0005000), | |
226 | 226 | }, |
227 | 227 | }; |
228 | 228 | |
... | ... | @@ -1262,6 +1262,7 @@ |
1262 | 1262 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1263 | 1263 | u32 ant_isolation = le32_to_cpup((void *)pkt->data); |
1264 | 1264 | u8 __maybe_unused lower_bound, upper_bound; |
1265 | + int ret; | |
1265 | 1266 | u8 lut; |
1266 | 1267 | |
1267 | 1268 | struct iwl_bt_coex_cmd *bt_cmd; |
... | ... | @@ -1318,6 +1319,9 @@ |
1318 | 1319 | memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20, |
1319 | 1320 | sizeof(bt_cmd->bt4_corun_lut40)); |
1320 | 1321 | |
1321 | - return 0; | |
1322 | + ret = iwl_mvm_send_cmd(mvm, &cmd); | |
1323 | + | |
1324 | + kfree(bt_cmd); | |
1325 | + return ret; | |
1322 | 1326 | } |
drivers/net/wireless/iwlwifi/mvm/mac80211.c
... | ... | @@ -1332,6 +1332,7 @@ |
1332 | 1332 | */ |
1333 | 1333 | iwl_mvm_remove_time_event(mvm, mvmvif, |
1334 | 1334 | &mvmvif->time_event_data); |
1335 | + iwl_mvm_sf_update(mvm, vif, false); | |
1335 | 1336 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC)); |
1336 | 1337 | } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | |
1337 | 1338 | BSS_CHANGED_QOS)) { |
drivers/net/wireless/iwlwifi/mvm/rs.c
... | ... | @@ -59,8 +59,8 @@ |
59 | 59 | /* max allowed rate miss before sync LQ cmd */ |
60 | 60 | #define IWL_MISSED_RATE_MAX 15 |
61 | 61 | #define RS_STAY_IN_COLUMN_TIMEOUT (5*HZ) |
62 | +#define RS_IDLE_TIMEOUT (5*HZ) | |
62 | 63 | |
63 | - | |
64 | 64 | static u8 rs_ht_to_legacy[] = { |
65 | 65 | [IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX, |
66 | 66 | [IWL_RATE_MCS_1_INDEX] = IWL_RATE_9M_INDEX, |
... | ... | @@ -142,7 +142,7 @@ |
142 | 142 | RS_MIMO2, |
143 | 143 | }; |
144 | 144 | |
145 | -#define MAX_NEXT_COLUMNS 5 | |
145 | +#define MAX_NEXT_COLUMNS 7 | |
146 | 146 | #define MAX_COLUMN_CHECKS 3 |
147 | 147 | |
148 | 148 | typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm, |
... | ... | @@ -212,8 +212,10 @@ |
212 | 212 | RS_COLUMN_LEGACY_ANT_B, |
213 | 213 | RS_COLUMN_SISO_ANT_A, |
214 | 214 | RS_COLUMN_SISO_ANT_B, |
215 | - RS_COLUMN_MIMO2, | |
216 | - RS_COLUMN_MIMO2_SGI, | |
215 | + RS_COLUMN_INVALID, | |
216 | + RS_COLUMN_INVALID, | |
217 | + RS_COLUMN_INVALID, | |
218 | + RS_COLUMN_INVALID, | |
217 | 219 | }, |
218 | 220 | }, |
219 | 221 | [RS_COLUMN_LEGACY_ANT_B] = { |
... | ... | @@ -223,8 +225,10 @@ |
223 | 225 | RS_COLUMN_LEGACY_ANT_A, |
224 | 226 | RS_COLUMN_SISO_ANT_A, |
225 | 227 | RS_COLUMN_SISO_ANT_B, |
226 | - RS_COLUMN_MIMO2, | |
227 | - RS_COLUMN_MIMO2_SGI, | |
228 | + RS_COLUMN_INVALID, | |
229 | + RS_COLUMN_INVALID, | |
230 | + RS_COLUMN_INVALID, | |
231 | + RS_COLUMN_INVALID, | |
228 | 232 | }, |
229 | 233 | }, |
230 | 234 | [RS_COLUMN_SISO_ANT_A] = { |
... | ... | @@ -235,7 +239,9 @@ |
235 | 239 | RS_COLUMN_MIMO2, |
236 | 240 | RS_COLUMN_SISO_ANT_A_SGI, |
237 | 241 | RS_COLUMN_SISO_ANT_B_SGI, |
238 | - RS_COLUMN_MIMO2_SGI, | |
242 | + RS_COLUMN_LEGACY_ANT_A, | |
243 | + RS_COLUMN_LEGACY_ANT_B, | |
244 | + RS_COLUMN_INVALID, | |
239 | 245 | }, |
240 | 246 | .checks = { |
241 | 247 | rs_siso_allow, |
... | ... | @@ -249,7 +255,9 @@ |
249 | 255 | RS_COLUMN_MIMO2, |
250 | 256 | RS_COLUMN_SISO_ANT_B_SGI, |
251 | 257 | RS_COLUMN_SISO_ANT_A_SGI, |
252 | - RS_COLUMN_MIMO2_SGI, | |
258 | + RS_COLUMN_LEGACY_ANT_A, | |
259 | + RS_COLUMN_LEGACY_ANT_B, | |
260 | + RS_COLUMN_INVALID, | |
253 | 261 | }, |
254 | 262 | .checks = { |
255 | 263 | rs_siso_allow, |
... | ... | @@ -265,6 +273,8 @@ |
265 | 273 | RS_COLUMN_SISO_ANT_A, |
266 | 274 | RS_COLUMN_SISO_ANT_B, |
267 | 275 | RS_COLUMN_MIMO2, |
276 | + RS_COLUMN_LEGACY_ANT_A, | |
277 | + RS_COLUMN_LEGACY_ANT_B, | |
268 | 278 | }, |
269 | 279 | .checks = { |
270 | 280 | rs_siso_allow, |
... | ... | @@ -281,6 +291,8 @@ |
281 | 291 | RS_COLUMN_SISO_ANT_B, |
282 | 292 | RS_COLUMN_SISO_ANT_A, |
283 | 293 | RS_COLUMN_MIMO2, |
294 | + RS_COLUMN_LEGACY_ANT_A, | |
295 | + RS_COLUMN_LEGACY_ANT_B, | |
284 | 296 | }, |
285 | 297 | .checks = { |
286 | 298 | rs_siso_allow, |
... | ... | @@ -296,6 +308,8 @@ |
296 | 308 | RS_COLUMN_SISO_ANT_A_SGI, |
297 | 309 | RS_COLUMN_SISO_ANT_B_SGI, |
298 | 310 | RS_COLUMN_MIMO2_SGI, |
311 | + RS_COLUMN_LEGACY_ANT_A, | |
312 | + RS_COLUMN_LEGACY_ANT_B, | |
299 | 313 | }, |
300 | 314 | .checks = { |
301 | 315 | rs_mimo_allow, |
... | ... | @@ -311,6 +325,8 @@ |
311 | 325 | RS_COLUMN_SISO_ANT_A, |
312 | 326 | RS_COLUMN_SISO_ANT_B, |
313 | 327 | RS_COLUMN_MIMO2, |
328 | + RS_COLUMN_LEGACY_ANT_A, | |
329 | + RS_COLUMN_LEGACY_ANT_B, | |
314 | 330 | }, |
315 | 331 | .checks = { |
316 | 332 | rs_mimo_allow, |
317 | 333 | |
... | ... | @@ -503,10 +519,12 @@ |
503 | 519 | window->average_tpt = IWL_INVALID_VALUE; |
504 | 520 | } |
505 | 521 | |
506 | -static void rs_rate_scale_clear_tbl_windows(struct iwl_scale_tbl_info *tbl) | |
522 | +static void rs_rate_scale_clear_tbl_windows(struct iwl_mvm *mvm, | |
523 | + struct iwl_scale_tbl_info *tbl) | |
507 | 524 | { |
508 | 525 | int i; |
509 | 526 | |
527 | + IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); | |
510 | 528 | for (i = 0; i < IWL_RATE_COUNT; i++) |
511 | 529 | rs_rate_scale_clear_window(&tbl->win[i]); |
512 | 530 | } |
... | ... | @@ -992,6 +1010,13 @@ |
992 | 1010 | return; |
993 | 1011 | } |
994 | 1012 | |
1013 | +#ifdef CPTCFG_MAC80211_DEBUGFS | |
1014 | + /* Disable last tx check if we are debugging with fixed rate */ | |
1015 | + if (lq_sta->dbg_fixed_rate) { | |
1016 | + IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n"); | |
1017 | + return; | |
1018 | + } | |
1019 | +#endif | |
995 | 1020 | if (!ieee80211_is_data(hdr->frame_control) || |
996 | 1021 | info->flags & IEEE80211_TX_CTL_NO_ACK) |
997 | 1022 | return; |
... | ... | @@ -1034,6 +1059,18 @@ |
1034 | 1059 | mac_index++; |
1035 | 1060 | } |
1036 | 1061 | |
1062 | + if (time_after(jiffies, | |
1063 | + (unsigned long)(lq_sta->last_tx + RS_IDLE_TIMEOUT))) { | |
1064 | + int tid; | |
1065 | + IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n"); | |
1066 | + for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) | |
1067 | + ieee80211_stop_tx_ba_session(sta, tid); | |
1068 | + | |
1069 | + iwl_mvm_rs_rate_init(mvm, sta, sband->band, false); | |
1070 | + return; | |
1071 | + } | |
1072 | + lq_sta->last_tx = jiffies; | |
1073 | + | |
1037 | 1074 | /* Here we actually compare this rate to the latest LQ command */ |
1038 | 1075 | if ((mac_index < 0) || |
1039 | 1076 | (rate.sgi != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || |
1040 | 1077 | |
... | ... | @@ -1186,9 +1223,26 @@ |
1186 | 1223 | lq_sta->visited_columns = 0; |
1187 | 1224 | } |
1188 | 1225 | |
1226 | +static int rs_get_max_allowed_rate(struct iwl_lq_sta *lq_sta, | |
1227 | + const struct rs_tx_column *column) | |
1228 | +{ | |
1229 | + switch (column->mode) { | |
1230 | + case RS_LEGACY: | |
1231 | + return lq_sta->max_legacy_rate_idx; | |
1232 | + case RS_SISO: | |
1233 | + return lq_sta->max_siso_rate_idx; | |
1234 | + case RS_MIMO2: | |
1235 | + return lq_sta->max_mimo2_rate_idx; | |
1236 | + default: | |
1237 | + WARN_ON_ONCE(1); | |
1238 | + } | |
1239 | + | |
1240 | + return lq_sta->max_legacy_rate_idx; | |
1241 | +} | |
1242 | + | |
1189 | 1243 | static const u16 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta, |
1190 | - const struct rs_tx_column *column, | |
1191 | - u32 bw) | |
1244 | + const struct rs_tx_column *column, | |
1245 | + u32 bw) | |
1192 | 1246 | { |
1193 | 1247 | /* Used to choose among HT tables */ |
1194 | 1248 | const u16 (*ht_tbl_pointer)[IWL_RATE_COUNT]; |
... | ... | @@ -1438,7 +1492,7 @@ |
1438 | 1492 | |
1439 | 1493 | IWL_DEBUG_RATE(mvm, |
1440 | 1494 | "LQ: stay in table clear win\n"); |
1441 | - rs_rate_scale_clear_tbl_windows(tbl); | |
1495 | + rs_rate_scale_clear_tbl_windows(mvm, tbl); | |
1442 | 1496 | } |
1443 | 1497 | } |
1444 | 1498 | |
... | ... | @@ -1446,8 +1500,7 @@ |
1446 | 1500 | * bitmaps and stats in active table (this will become the new |
1447 | 1501 | * "search" table). */ |
1448 | 1502 | if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) { |
1449 | - IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); | |
1450 | - rs_rate_scale_clear_tbl_windows(tbl); | |
1503 | + rs_rate_scale_clear_tbl_windows(mvm, tbl); | |
1451 | 1504 | } |
1452 | 1505 | } |
1453 | 1506 | } |
1454 | 1507 | |
... | ... | @@ -1485,14 +1538,14 @@ |
1485 | 1538 | struct ieee80211_sta *sta, |
1486 | 1539 | struct iwl_scale_tbl_info *tbl) |
1487 | 1540 | { |
1488 | - int i, j, n; | |
1541 | + int i, j, max_rate; | |
1489 | 1542 | enum rs_column next_col_id; |
1490 | 1543 | const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column]; |
1491 | 1544 | const struct rs_tx_column *next_col; |
1492 | 1545 | allow_column_func_t allow_func; |
1493 | 1546 | u8 valid_ants = mvm->fw->valid_tx_ant; |
1494 | 1547 | const u16 *expected_tpt_tbl; |
1495 | - s32 tpt, max_expected_tpt; | |
1548 | + u16 tpt, max_expected_tpt; | |
1496 | 1549 | |
1497 | 1550 | for (i = 0; i < MAX_NEXT_COLUMNS; i++) { |
1498 | 1551 | next_col_id = curr_col->next_columns[i]; |
1499 | 1552 | |
... | ... | @@ -1535,11 +1588,11 @@ |
1535 | 1588 | if (WARN_ON_ONCE(!expected_tpt_tbl)) |
1536 | 1589 | continue; |
1537 | 1590 | |
1538 | - max_expected_tpt = 0; | |
1539 | - for (n = 0; n < IWL_RATE_COUNT; n++) | |
1540 | - if (expected_tpt_tbl[n] > max_expected_tpt) | |
1541 | - max_expected_tpt = expected_tpt_tbl[n]; | |
1591 | + max_rate = rs_get_max_allowed_rate(lq_sta, next_col); | |
1592 | + if (WARN_ON_ONCE(max_rate == IWL_RATE_INVALID)) | |
1593 | + continue; | |
1542 | 1594 | |
1595 | + max_expected_tpt = expected_tpt_tbl[max_rate]; | |
1543 | 1596 | if (tpt >= max_expected_tpt) { |
1544 | 1597 | IWL_DEBUG_RATE(mvm, |
1545 | 1598 | "Skip column %d: can't beat current TPT. Max expected %d current %d\n", |
1546 | 1599 | |
... | ... | @@ -1547,14 +1600,15 @@ |
1547 | 1600 | continue; |
1548 | 1601 | } |
1549 | 1602 | |
1603 | + IWL_DEBUG_RATE(mvm, | |
1604 | + "Found potential column %d. Max expected %d current %d\n", | |
1605 | + next_col_id, max_expected_tpt, tpt); | |
1550 | 1606 | break; |
1551 | 1607 | } |
1552 | 1608 | |
1553 | 1609 | if (i == MAX_NEXT_COLUMNS) |
1554 | 1610 | return RS_COLUMN_INVALID; |
1555 | 1611 | |
1556 | - IWL_DEBUG_RATE(mvm, "Found potential column %d\n", next_col_id); | |
1557 | - | |
1558 | 1612 | return next_col_id; |
1559 | 1613 | } |
1560 | 1614 | |
1561 | 1615 | |
1562 | 1616 | |
1563 | 1617 | |
1564 | 1618 | |
1565 | 1619 | |
1566 | 1620 | |
1567 | 1621 | |
1568 | 1622 | |
... | ... | @@ -1640,87 +1694,78 @@ |
1640 | 1694 | { |
1641 | 1695 | enum rs_action action = RS_ACTION_STAY; |
1642 | 1696 | |
1643 | - /* Too many failures, decrease rate */ | |
1644 | 1697 | if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) { |
1645 | 1698 | IWL_DEBUG_RATE(mvm, |
1646 | - "decrease rate because of low SR\n"); | |
1647 | - action = RS_ACTION_DOWNSCALE; | |
1648 | - /* No throughput measured yet for adjacent rates; try increase. */ | |
1649 | - } else if ((low_tpt == IWL_INVALID_VALUE) && | |
1650 | - (high_tpt == IWL_INVALID_VALUE)) { | |
1651 | - if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) { | |
1652 | - IWL_DEBUG_RATE(mvm, | |
1653 | - "Good SR and no high rate measurement. " | |
1654 | - "Increase rate\n"); | |
1655 | - action = RS_ACTION_UPSCALE; | |
1656 | - } else if (low != IWL_RATE_INVALID) { | |
1657 | - IWL_DEBUG_RATE(mvm, | |
1658 | - "Remain in current rate\n"); | |
1659 | - action = RS_ACTION_STAY; | |
1660 | - } | |
1699 | + "Decrease rate because of low SR\n"); | |
1700 | + return RS_ACTION_DOWNSCALE; | |
1661 | 1701 | } |
1662 | 1702 | |
1663 | - /* Both adjacent throughputs are measured, but neither one has better | |
1664 | - * throughput; we're using the best rate, don't change it! | |
1665 | - */ | |
1666 | - else if ((low_tpt != IWL_INVALID_VALUE) && | |
1667 | - (high_tpt != IWL_INVALID_VALUE) && | |
1668 | - (low_tpt < current_tpt) && | |
1669 | - (high_tpt < current_tpt)) { | |
1703 | + if ((low_tpt == IWL_INVALID_VALUE) && | |
1704 | + (high_tpt == IWL_INVALID_VALUE) && | |
1705 | + (high != IWL_RATE_INVALID)) { | |
1670 | 1706 | IWL_DEBUG_RATE(mvm, |
1671 | - "Both high and low are worse. " | |
1672 | - "Maintain rate\n"); | |
1673 | - action = RS_ACTION_STAY; | |
1707 | + "No data about high/low rates. Increase rate\n"); | |
1708 | + return RS_ACTION_UPSCALE; | |
1674 | 1709 | } |
1675 | 1710 | |
1676 | - /* At least one adjacent rate's throughput is measured, | |
1677 | - * and may have better performance. | |
1678 | - */ | |
1679 | - else { | |
1680 | - /* Higher adjacent rate's throughput is measured */ | |
1681 | - if (high_tpt != IWL_INVALID_VALUE) { | |
1682 | - /* Higher rate has better throughput */ | |
1683 | - if (high_tpt > current_tpt && | |
1684 | - sr >= IWL_RATE_INCREASE_TH) { | |
1685 | - IWL_DEBUG_RATE(mvm, | |
1686 | - "Higher rate is better and good " | |
1687 | - "SR. Increate rate\n"); | |
1688 | - action = RS_ACTION_UPSCALE; | |
1689 | - } else { | |
1690 | - IWL_DEBUG_RATE(mvm, | |
1691 | - "Higher rate isn't better OR " | |
1692 | - "no good SR. Maintain rate\n"); | |
1693 | - action = RS_ACTION_STAY; | |
1694 | - } | |
1711 | + if ((high_tpt == IWL_INVALID_VALUE) && | |
1712 | + (high != IWL_RATE_INVALID) && | |
1713 | + (low_tpt != IWL_INVALID_VALUE) && | |
1714 | + (low_tpt < current_tpt)) { | |
1715 | + IWL_DEBUG_RATE(mvm, | |
1716 | + "No data about high rate and low rate is worse. Increase rate\n"); | |
1717 | + return RS_ACTION_UPSCALE; | |
1718 | + } | |
1695 | 1719 | |
1696 | - /* Lower adjacent rate's throughput is measured */ | |
1697 | - } else if (low_tpt != IWL_INVALID_VALUE) { | |
1698 | - /* Lower rate has better throughput */ | |
1699 | - if (low_tpt > current_tpt) { | |
1700 | - IWL_DEBUG_RATE(mvm, | |
1701 | - "Lower rate is better. " | |
1702 | - "Decrease rate\n"); | |
1703 | - action = RS_ACTION_DOWNSCALE; | |
1704 | - } else if (sr >= IWL_RATE_INCREASE_TH) { | |
1705 | - IWL_DEBUG_RATE(mvm, | |
1706 | - "Lower rate isn't better and " | |
1707 | - "good SR. Increase rate\n"); | |
1708 | - action = RS_ACTION_UPSCALE; | |
1709 | - } | |
1710 | - } | |
1720 | + if ((high_tpt != IWL_INVALID_VALUE) && | |
1721 | + (high_tpt > current_tpt)) { | |
1722 | + IWL_DEBUG_RATE(mvm, | |
1723 | + "Higher rate is better. Increate rate\n"); | |
1724 | + return RS_ACTION_UPSCALE; | |
1711 | 1725 | } |
1712 | 1726 | |
1713 | - /* Sanity check; asked for decrease, but success rate or throughput | |
1714 | - * has been good at old rate. Don't change it. | |
1715 | - */ | |
1716 | - if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID) && | |
1717 | - ((sr > IWL_RATE_HIGH_TH) || | |
1718 | - (current_tpt > (100 * tbl->expected_tpt[low])))) { | |
1727 | + if ((low_tpt != IWL_INVALID_VALUE) && | |
1728 | + (high_tpt != IWL_INVALID_VALUE) && | |
1729 | + (low_tpt < current_tpt) && | |
1730 | + (high_tpt < current_tpt)) { | |
1719 | 1731 | IWL_DEBUG_RATE(mvm, |
1720 | - "Sanity check failed. Maintain rate\n"); | |
1721 | - action = RS_ACTION_STAY; | |
1732 | + "Both high and low are worse. Maintain rate\n"); | |
1733 | + return RS_ACTION_STAY; | |
1722 | 1734 | } |
1723 | 1735 | |
1736 | + if ((low_tpt != IWL_INVALID_VALUE) && | |
1737 | + (low_tpt > current_tpt)) { | |
1738 | + IWL_DEBUG_RATE(mvm, | |
1739 | + "Lower rate is better\n"); | |
1740 | + action = RS_ACTION_DOWNSCALE; | |
1741 | + goto out; | |
1742 | + } | |
1743 | + | |
1744 | + if ((low_tpt == IWL_INVALID_VALUE) && | |
1745 | + (low != IWL_RATE_INVALID)) { | |
1746 | + IWL_DEBUG_RATE(mvm, | |
1747 | + "No data about lower rate\n"); | |
1748 | + action = RS_ACTION_DOWNSCALE; | |
1749 | + goto out; | |
1750 | + } | |
1751 | + | |
1752 | + IWL_DEBUG_RATE(mvm, "Maintain rate\n"); | |
1753 | + | |
1754 | +out: | |
1755 | + if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID)) { | |
1756 | + if (sr >= RS_SR_NO_DECREASE) { | |
1757 | + IWL_DEBUG_RATE(mvm, | |
1758 | + "SR is above NO DECREASE. Avoid downscale\n"); | |
1759 | + action = RS_ACTION_STAY; | |
1760 | + } else if (current_tpt > (100 * tbl->expected_tpt[low])) { | |
1761 | + IWL_DEBUG_RATE(mvm, | |
1762 | + "Current TPT is higher than max expected in low rate. Avoid downscale\n"); | |
1763 | + action = RS_ACTION_STAY; | |
1764 | + } else { | |
1765 | + IWL_DEBUG_RATE(mvm, "Decrease rate\n"); | |
1766 | + } | |
1767 | + } | |
1768 | + | |
1724 | 1769 | return action; |
1725 | 1770 | } |
1726 | 1771 | |
... | ... | @@ -1792,6 +1837,7 @@ |
1792 | 1837 | "Aggregation changed: prev %d current %d. Update expected TPT table\n", |
1793 | 1838 | prev_agg, lq_sta->is_agg); |
1794 | 1839 | rs_set_expected_tpt_table(lq_sta, tbl); |
1840 | + rs_rate_scale_clear_tbl_windows(mvm, tbl); | |
1795 | 1841 | } |
1796 | 1842 | |
1797 | 1843 | /* current tx rate */ |
... | ... | @@ -2021,7 +2067,7 @@ |
2021 | 2067 | if (lq_sta->search_better_tbl) { |
2022 | 2068 | /* Access the "search" table, clear its history. */ |
2023 | 2069 | tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
2024 | - rs_rate_scale_clear_tbl_windows(tbl); | |
2070 | + rs_rate_scale_clear_tbl_windows(mvm, tbl); | |
2025 | 2071 | |
2026 | 2072 | /* Use new "search" start rate */ |
2027 | 2073 | index = tbl->rate.index; |
2028 | 2074 | |
... | ... | @@ -2042,8 +2088,18 @@ |
2042 | 2088 | * stay with best antenna legacy modulation for a while |
2043 | 2089 | * before next round of mode comparisons. */ |
2044 | 2090 | tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); |
2045 | - if (is_legacy(&tbl1->rate) && !sta->ht_cap.ht_supported) { | |
2091 | + if (is_legacy(&tbl1->rate)) { | |
2046 | 2092 | IWL_DEBUG_RATE(mvm, "LQ: STAY in legacy table\n"); |
2093 | + | |
2094 | + if (tid != IWL_MAX_TID_COUNT) { | |
2095 | + tid_data = &sta_priv->tid_data[tid]; | |
2096 | + if (tid_data->state != IWL_AGG_OFF) { | |
2097 | + IWL_DEBUG_RATE(mvm, | |
2098 | + "Stop aggregation on tid %d\n", | |
2099 | + tid); | |
2100 | + ieee80211_stop_tx_ba_session(sta, tid); | |
2101 | + } | |
2102 | + } | |
2047 | 2103 | rs_set_stay_in_table(mvm, 1, lq_sta); |
2048 | 2104 | } else { |
2049 | 2105 | /* If we're in an HT mode, and all 3 mode switch actions |
2050 | 2106 | |
... | ... | @@ -2342,9 +2398,10 @@ |
2342 | 2398 | lq_sta->lq.sta_id = sta_priv->sta_id; |
2343 | 2399 | |
2344 | 2400 | for (j = 0; j < LQ_SIZE; j++) |
2345 | - rs_rate_scale_clear_tbl_windows(&lq_sta->lq_info[j]); | |
2401 | + rs_rate_scale_clear_tbl_windows(mvm, &lq_sta->lq_info[j]); | |
2346 | 2402 | |
2347 | 2403 | lq_sta->flush_timer = 0; |
2404 | + lq_sta->last_tx = jiffies; | |
2348 | 2405 | |
2349 | 2406 | IWL_DEBUG_RATE(mvm, |
2350 | 2407 | "LQ: *** rate scale station global init for station %d ***\n", |
2351 | 2408 | |
... | ... | @@ -2388,11 +2445,22 @@ |
2388 | 2445 | lq_sta->is_vht = true; |
2389 | 2446 | } |
2390 | 2447 | |
2391 | - IWL_DEBUG_RATE(mvm, | |
2392 | - "SISO-RATE=%X MIMO2-RATE=%X VHT=%d\n", | |
2448 | + lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate, | |
2449 | + BITS_PER_LONG); | |
2450 | + lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate, | |
2451 | + BITS_PER_LONG); | |
2452 | + lq_sta->max_mimo2_rate_idx = find_last_bit(&lq_sta->active_mimo2_rate, | |
2453 | + BITS_PER_LONG); | |
2454 | + | |
2455 | + IWL_DEBUG_RATE(mvm, "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d\n", | |
2456 | + lq_sta->active_legacy_rate, | |
2393 | 2457 | lq_sta->active_siso_rate, |
2394 | 2458 | lq_sta->active_mimo2_rate, |
2395 | 2459 | lq_sta->is_vht); |
2460 | + IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n", | |
2461 | + lq_sta->max_legacy_rate_idx, | |
2462 | + lq_sta->max_siso_rate_idx, | |
2463 | + lq_sta->max_mimo2_rate_idx); | |
2396 | 2464 | |
2397 | 2465 | /* These values will be overridden later */ |
2398 | 2466 | lq_sta->lq.single_stream_ant_msk = |
... | ... | @@ -2547,6 +2615,7 @@ |
2547 | 2615 | if (is_siso(&rate)) { |
2548 | 2616 | num_rates = RS_SECONDARY_SISO_NUM_RATES; |
2549 | 2617 | num_retries = RS_SECONDARY_SISO_RETRIES; |
2618 | + lq_cmd->mimo_delim = index; | |
2550 | 2619 | } else if (is_legacy(&rate)) { |
2551 | 2620 | num_rates = RS_SECONDARY_LEGACY_NUM_RATES; |
2552 | 2621 | num_retries = RS_LEGACY_RETRIES_PER_RATE; |
... | ... | @@ -2749,7 +2818,7 @@ |
2749 | 2818 | return -ENOMEM; |
2750 | 2819 | |
2751 | 2820 | desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id); |
2752 | - desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n", | |
2821 | + desc += sprintf(buff+desc, "failed=%d success=%d rate=0%lX\n", | |
2753 | 2822 | lq_sta->total_failed, lq_sta->total_success, |
2754 | 2823 | lq_sta->active_legacy_rate); |
2755 | 2824 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", |
drivers/net/wireless/iwlwifi/mvm/rs.h
... | ... | @@ -156,6 +156,7 @@ |
156 | 156 | #define IWL_RATE_HIGH_TH 10880 /* 85% */ |
157 | 157 | #define IWL_RATE_INCREASE_TH 6400 /* 50% */ |
158 | 158 | #define RS_SR_FORCE_DECREASE 1920 /* 15% */ |
159 | +#define RS_SR_NO_DECREASE 10880 /* 85% */ | |
159 | 160 | |
160 | 161 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ |
161 | 162 | #define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000) |
162 | 163 | |
... | ... | @@ -310,13 +311,20 @@ |
310 | 311 | u32 visited_columns; /* Bitmask marking which Tx columns were |
311 | 312 | * explored during a search cycle |
312 | 313 | */ |
314 | + u64 last_tx; | |
313 | 315 | bool is_vht; |
314 | 316 | enum ieee80211_band band; |
315 | 317 | |
316 | 318 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ |
317 | - u16 active_legacy_rate; | |
318 | - u16 active_siso_rate; | |
319 | - u16 active_mimo2_rate; | |
319 | + unsigned long active_legacy_rate; | |
320 | + unsigned long active_siso_rate; | |
321 | + unsigned long active_mimo2_rate; | |
322 | + | |
323 | + /* Highest rate per Tx mode */ | |
324 | + u8 max_legacy_rate_idx; | |
325 | + u8 max_siso_rate_idx; | |
326 | + u8 max_mimo2_rate_idx; | |
327 | + | |
320 | 328 | s8 max_rate_idx; /* Max rate set by user */ |
321 | 329 | u8 missed_rate_counter; |
322 | 330 |
drivers/net/wireless/iwlwifi/mvm/sf.c
... | ... | @@ -274,7 +274,8 @@ |
274 | 274 | return -EINVAL; |
275 | 275 | if (changed_vif->type != NL80211_IFTYPE_STATION) { |
276 | 276 | new_state = SF_UNINIT; |
277 | - } else if (changed_vif->bss_conf.assoc) { | |
277 | + } else if (changed_vif->bss_conf.assoc && | |
278 | + changed_vif->bss_conf.dtim_period) { | |
278 | 279 | mvmvif = iwl_mvm_vif_from_mac80211(changed_vif); |
279 | 280 | sta_id = mvmvif->ap_sta_id; |
280 | 281 | new_state = SF_FULL_ON; |
drivers/net/wireless/iwlwifi/pcie/drv.c
... | ... | @@ -373,12 +373,14 @@ |
373 | 373 | {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2n_cfg)}, |
374 | 374 | {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)}, |
375 | 375 | {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)}, |
376 | + {IWL_PCI_DEVICE(0x095A, 0x5102, iwl7265_n_cfg)}, | |
376 | 377 | {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)}, |
377 | 378 | {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)}, |
378 | 379 | {IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)}, |
379 | 380 | {IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)}, |
380 | 381 | {IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)}, |
381 | 382 | {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)}, |
383 | + {IWL_PCI_DEVICE(0x095A, 0x9200, iwl7265_2ac_cfg)}, | |
382 | 384 | {IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)}, |
383 | 385 | {IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)}, |
384 | 386 | {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)}, |
drivers/net/wireless/mwifiex/main.c
... | ... | @@ -292,6 +292,12 @@ |
292 | 292 | while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) |
293 | 293 | mwifiex_handle_rx_packet(adapter, skb); |
294 | 294 | |
295 | + /* Check for event */ | |
296 | + if (adapter->event_received) { | |
297 | + adapter->event_received = false; | |
298 | + mwifiex_process_event(adapter); | |
299 | + } | |
300 | + | |
295 | 301 | /* Check for Cmd Resp */ |
296 | 302 | if (adapter->cmd_resp_received) { |
297 | 303 | adapter->cmd_resp_received = false; |
... | ... | @@ -302,12 +308,6 @@ |
302 | 308 | adapter->hw_status = MWIFIEX_HW_STATUS_READY; |
303 | 309 | mwifiex_init_fw_complete(adapter); |
304 | 310 | } |
305 | - } | |
306 | - | |
307 | - /* Check for event */ | |
308 | - if (adapter->event_received) { | |
309 | - adapter->event_received = false; | |
310 | - mwifiex_process_event(adapter); | |
311 | 311 | } |
312 | 312 | |
313 | 313 | /* Check if we need to confirm Sleep Request |
drivers/net/wireless/mwifiex/sta_ioctl.c
... | ... | @@ -60,9 +60,10 @@ |
60 | 60 | int status; |
61 | 61 | |
62 | 62 | /* Wait for completion */ |
63 | - status = wait_event_interruptible(adapter->cmd_wait_q.wait, | |
64 | - *(cmd_queued->condition)); | |
65 | - if (status) { | |
63 | + status = wait_event_interruptible_timeout(adapter->cmd_wait_q.wait, | |
64 | + *(cmd_queued->condition), | |
65 | + (12 * HZ)); | |
66 | + if (status <= 0) { | |
66 | 67 | dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); |
67 | 68 | mwifiex_cancel_all_pending_cmd(adapter); |
68 | 69 | return status; |
drivers/net/wireless/rsi/rsi_91x_core.c
drivers/net/wireless/rsi/rsi_91x_mgmt.c
... | ... | @@ -841,16 +841,6 @@ |
841 | 841 | rsi_dbg(MGMT_TX_ZONE, |
842 | 842 | "%s: Sending scan req frame\n", __func__); |
843 | 843 | |
844 | - skb = dev_alloc_skb(FRAME_DESC_SZ); | |
845 | - if (!skb) { | |
846 | - rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | |
847 | - __func__); | |
848 | - return -ENOMEM; | |
849 | - } | |
850 | - | |
851 | - memset(skb->data, 0, FRAME_DESC_SZ); | |
852 | - mgmt_frame = (struct rsi_mac_frame *)skb->data; | |
853 | - | |
854 | 844 | if (common->band == IEEE80211_BAND_5GHZ) { |
855 | 845 | if ((channel >= 36) && (channel <= 64)) |
856 | 846 | channel = ((channel - 32) / 4); |
... | ... | @@ -868,6 +858,16 @@ |
868 | 858 | } |
869 | 859 | } |
870 | 860 | |
861 | + skb = dev_alloc_skb(FRAME_DESC_SZ); | |
862 | + if (!skb) { | |
863 | + rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", | |
864 | + __func__); | |
865 | + return -ENOMEM; | |
866 | + } | |
867 | + | |
868 | + memset(skb->data, 0, FRAME_DESC_SZ); | |
869 | + mgmt_frame = (struct rsi_mac_frame *)skb->data; | |
870 | + | |
871 | 871 | mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); |
872 | 872 | mgmt_frame->desc_word[1] = cpu_to_le16(SCAN_REQUEST); |
873 | 873 | mgmt_frame->desc_word[4] = cpu_to_le16(channel); |
... | ... | @@ -966,6 +966,7 @@ |
966 | 966 | if (!selected_rates) { |
967 | 967 | rsi_dbg(ERR_ZONE, "%s: Failed in allocation of mem\n", |
968 | 968 | __func__); |
969 | + dev_kfree_skb(skb); | |
969 | 970 | return -ENOMEM; |
970 | 971 | } |
971 | 972 |
drivers/net/wireless/ti/wl18xx/event.h
... | ... | @@ -68,6 +68,26 @@ |
68 | 68 | |
69 | 69 | /* bitmap of inactive stations (by HLID) */ |
70 | 70 | __le32 inactive_sta_bitmap; |
71 | + | |
72 | + /* rx BA win size indicated by RX_BA_WIN_SIZE_CHANGE_EVENT_ID */ | |
73 | + u8 rx_ba_role_id; | |
74 | + u8 rx_ba_link_id; | |
75 | + u8 rx_ba_win_size; | |
76 | + u8 padding; | |
77 | + | |
78 | + /* smart config */ | |
79 | + u8 sc_ssid_len; | |
80 | + u8 sc_pwd_len; | |
81 | + u8 sc_token_len; | |
82 | + u8 padding1; | |
83 | + u8 sc_ssid[32]; | |
84 | + u8 sc_pwd[32]; | |
85 | + u8 sc_token[32]; | |
86 | + | |
87 | + /* smart config sync channel */ | |
88 | + u8 sc_sync_channel; | |
89 | + u8 sc_sync_band; | |
90 | + u8 padding2[2]; | |
71 | 91 | } __packed; |
72 | 92 | |
73 | 93 | int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, |
drivers/net/wireless/ti/wlcore/event.c
... | ... | @@ -158,6 +158,11 @@ |
158 | 158 | |
159 | 159 | void wlcore_event_dummy_packet(struct wl1271 *wl) |
160 | 160 | { |
161 | + if (wl->plt) { | |
162 | + wl1271_info("Got DUMMY_PACKET event in PLT mode. FW bug, ignoring."); | |
163 | + return; | |
164 | + } | |
165 | + | |
161 | 166 | wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); |
162 | 167 | wl1271_tx_dummy_packet(wl); |
163 | 168 | } |
net/mac80211/chan.c
... | ... | @@ -249,7 +249,7 @@ |
249 | 249 | |
250 | 250 | if (!local->use_chanctx) { |
251 | 251 | local->_oper_chandef = *chandef; |
252 | - ieee80211_hw_config(local, 0); | |
252 | + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | |
253 | 253 | } else { |
254 | 254 | err = drv_add_chanctx(local, ctx); |
255 | 255 | if (err) { |
... | ... | @@ -286,7 +286,7 @@ |
286 | 286 | check_single_channel = true; |
287 | 287 | local->hw.conf.radar_enabled = false; |
288 | 288 | |
289 | - ieee80211_hw_config(local, 0); | |
289 | + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | |
290 | 290 | } else { |
291 | 291 | drv_remove_chanctx(local, ctx); |
292 | 292 | } |
... | ... | @@ -492,6 +492,13 @@ |
492 | 492 | rx_chains_static = max(rx_chains_static, needed_static); |
493 | 493 | rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic); |
494 | 494 | } |
495 | + | |
496 | + /* Disable SMPS for the monitor interface */ | |
497 | + sdata = rcu_dereference(local->monitor_sdata); | |
498 | + if (sdata && | |
499 | + rcu_access_pointer(sdata->vif.chanctx_conf) == &chanctx->conf) | |
500 | + rx_chains_dynamic = rx_chains_static = local->rx_chains; | |
501 | + | |
495 | 502 | rcu_read_unlock(); |
496 | 503 | |
497 | 504 | if (!local->use_chanctx) { |
net/mac80211/main.c
... | ... | @@ -148,6 +148,8 @@ |
148 | 148 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
149 | 149 | if (!rcu_access_pointer(sdata->vif.chanctx_conf)) |
150 | 150 | continue; |
151 | + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | |
152 | + continue; | |
151 | 153 | power = min(power, sdata->vif.bss_conf.txpower); |
152 | 154 | } |
153 | 155 | rcu_read_unlock(); |
... | ... | @@ -199,7 +201,7 @@ |
199 | 201 | { |
200 | 202 | struct ieee80211_local *local = sdata->local; |
201 | 203 | |
202 | - if (!changed) | |
204 | + if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | |
203 | 205 | return; |
204 | 206 | |
205 | 207 | drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); |
net/mac80211/offchannel.c
net/mac80211/status.c