|
4 | 4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 | 5 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
6 | 6 | * Copyright (C) 2015 - 2017 Intel Deutschland GmbH |
7 | | - * Copyright (C) 2018-2023 Intel Corporation |
| 7 | + * Copyright (C) 2018-2024 Intel Corporation |
8 | 8 | */ |
9 | 9 |
|
10 | 10 | #include <linux/module.h> |
@@ -1317,9 +1317,13 @@ static int _sta_info_move_state(struct sta_info *sta, |
1317 | 1317 | sta->sta.addr, new_state); |
1318 | 1318 |
|
1319 | 1319 | /* notify the driver before the actual changes so it can |
1320 | | - * fail the transition |
| 1320 | + * fail the transition if the state is increasing. |
| 1321 | + * The driver is required not to fail when the transition |
| 1322 | + * is decreasing the state, so first, do all the preparation |
| 1323 | + * work and only then, notify the driver. |
1321 | 1324 | */ |
1322 | | - if (test_sta_flag(sta, WLAN_STA_INSERTED)) { |
| 1325 | + if (new_state > sta->sta_state && |
| 1326 | + test_sta_flag(sta, WLAN_STA_INSERTED)) { |
1323 | 1327 | int err = drv_sta_state(sta->local, sta->sdata, sta, |
1324 | 1328 | sta->sta_state, new_state); |
1325 | 1329 | if (err) |
@@ -1395,6 +1399,16 @@ static int _sta_info_move_state(struct sta_info *sta, |
1395 | 1399 | break; |
1396 | 1400 | } |
1397 | 1401 |
|
| 1402 | + if (new_state < sta->sta_state && |
| 1403 | + test_sta_flag(sta, WLAN_STA_INSERTED)) { |
| 1404 | + int err = drv_sta_state(sta->local, sta->sdata, sta, |
| 1405 | + sta->sta_state, new_state); |
| 1406 | + |
| 1407 | + WARN_ONCE(err, |
| 1408 | + "Driver is not allowed to fail if the sta_state is transitioning down the list: %d\n", |
| 1409 | + err); |
| 1410 | + } |
| 1411 | + |
1398 | 1412 | sta->sta_state = new_state; |
1399 | 1413 |
|
1400 | 1414 | return 0; |
|
0 commit comments