diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 325 |
1 files changed, 153 insertions, 172 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 8664111d0566..bfb57dcc1538 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -43,6 +43,128 @@ | |||
43 | */ | 43 | */ |
44 | 44 | ||
45 | 45 | ||
46 | static u32 ieee80211_idle_off(struct ieee80211_local *local, | ||
47 | const char *reason) | ||
48 | { | ||
49 | if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) | ||
50 | return 0; | ||
51 | |||
52 | local->hw.conf.flags &= ~IEEE80211_CONF_IDLE; | ||
53 | return IEEE80211_CONF_CHANGE_IDLE; | ||
54 | } | ||
55 | |||
56 | static u32 ieee80211_idle_on(struct ieee80211_local *local) | ||
57 | { | ||
58 | if (local->hw.conf.flags & IEEE80211_CONF_IDLE) | ||
59 | return 0; | ||
60 | |||
61 | drv_flush(local, false); | ||
62 | |||
63 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; | ||
64 | return IEEE80211_CONF_CHANGE_IDLE; | ||
65 | } | ||
66 | |||
67 | static u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | ||
68 | { | ||
69 | struct ieee80211_sub_if_data *sdata; | ||
70 | int count = 0; | ||
71 | bool working = false, scanning = false; | ||
72 | unsigned int led_trig_start = 0, led_trig_stop = 0; | ||
73 | struct ieee80211_roc_work *roc; | ||
74 | |||
75 | #ifdef CONFIG_PROVE_LOCKING | ||
76 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && | ||
77 | !lockdep_is_held(&local->iflist_mtx)); | ||
78 | #endif | ||
79 | lockdep_assert_held(&local->mtx); | ||
80 | |||
81 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
82 | if (!ieee80211_sdata_running(sdata)) { | ||
83 | sdata->vif.bss_conf.idle = true; | ||
84 | continue; | ||
85 | } | ||
86 | |||
87 | sdata->old_idle = sdata->vif.bss_conf.idle; | ||
88 | |||
89 | /* do not count disabled managed interfaces */ | ||
90 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
91 | !sdata->u.mgd.associated && | ||
92 | !sdata->u.mgd.auth_data && | ||
93 | !sdata->u.mgd.assoc_data) { | ||
94 | sdata->vif.bss_conf.idle = true; | ||
95 | continue; | ||
96 | } | ||
97 | /* do not count unused IBSS interfaces */ | ||
98 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
99 | !sdata->u.ibss.ssid_len) { | ||
100 | sdata->vif.bss_conf.idle = true; | ||
101 | continue; | ||
102 | } | ||
103 | /* count everything else */ | ||
104 | sdata->vif.bss_conf.idle = false; | ||
105 | count++; | ||
106 | } | ||
107 | |||
108 | if (!local->ops->remain_on_channel) { | ||
109 | list_for_each_entry(roc, &local->roc_list, list) { | ||
110 | working = true; | ||
111 | roc->sdata->vif.bss_conf.idle = false; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | sdata = rcu_dereference_protected(local->scan_sdata, | ||
116 | lockdep_is_held(&local->mtx)); | ||
117 | if (sdata && !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { | ||
118 | scanning = true; | ||
119 | sdata->vif.bss_conf.idle = false; | ||
120 | } | ||
121 | |||
122 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
123 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | ||
124 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
125 | continue; | ||
126 | if (sdata->old_idle == sdata->vif.bss_conf.idle) | ||
127 | continue; | ||
128 | if (!ieee80211_sdata_running(sdata)) | ||
129 | continue; | ||
130 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | ||
131 | } | ||
132 | |||
133 | if (working || scanning) | ||
134 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; | ||
135 | else | ||
136 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; | ||
137 | |||
138 | if (count) | ||
139 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | ||
140 | else | ||
141 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | ||
142 | |||
143 | ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); | ||
144 | |||
145 | if (working) | ||
146 | return ieee80211_idle_off(local, "working"); | ||
147 | if (scanning) | ||
148 | return ieee80211_idle_off(local, "scanning"); | ||
149 | if (!count) | ||
150 | return ieee80211_idle_on(local); | ||
151 | else | ||
152 | return ieee80211_idle_off(local, "in use"); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | void ieee80211_recalc_idle(struct ieee80211_local *local) | ||
158 | { | ||
159 | u32 chg; | ||
160 | |||
161 | mutex_lock(&local->iflist_mtx); | ||
162 | chg = __ieee80211_recalc_idle(local); | ||
163 | mutex_unlock(&local->iflist_mtx); | ||
164 | if (chg) | ||
165 | ieee80211_hw_config(local, chg); | ||
166 | } | ||
167 | |||
46 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | 168 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) |
47 | { | 169 | { |
48 | int meshhdrlen; | 170 | int meshhdrlen; |
@@ -57,9 +179,6 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | |||
57 | return -EINVAL; | 179 | return -EINVAL; |
58 | } | 180 | } |
59 | 181 | ||
60 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
61 | printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu); | ||
62 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
63 | dev->mtu = new_mtu; | 182 | dev->mtu = new_mtu; |
64 | return 0; | 183 | return 0; |
65 | } | 184 | } |
@@ -100,15 +219,12 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata, | |||
100 | { | 219 | { |
101 | struct ieee80211_local *local = sdata->local; | 220 | struct ieee80211_local *local = sdata->local; |
102 | struct ieee80211_sub_if_data *nsdata; | 221 | struct ieee80211_sub_if_data *nsdata; |
103 | struct net_device *dev = sdata->dev; | ||
104 | 222 | ||
105 | ASSERT_RTNL(); | 223 | ASSERT_RTNL(); |
106 | 224 | ||
107 | /* we hold the RTNL here so can safely walk the list */ | 225 | /* we hold the RTNL here so can safely walk the list */ |
108 | list_for_each_entry(nsdata, &local->interfaces, list) { | 226 | list_for_each_entry(nsdata, &local->interfaces, list) { |
109 | struct net_device *ndev = nsdata->dev; | 227 | if (nsdata != sdata && ieee80211_sdata_running(nsdata)) { |
110 | |||
111 | if (ndev != dev && ieee80211_sdata_running(nsdata)) { | ||
112 | /* | 228 | /* |
113 | * Allow only a single IBSS interface to be up at any | 229 | * Allow only a single IBSS interface to be up at any |
114 | * time. This is restricted because beacon distribution | 230 | * time. This is restricted because beacon distribution |
@@ -127,7 +243,8 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata, | |||
127 | * The remaining checks are only performed for interfaces | 243 | * The remaining checks are only performed for interfaces |
128 | * with the same MAC address. | 244 | * with the same MAC address. |
129 | */ | 245 | */ |
130 | if (!ether_addr_equal(dev->dev_addr, ndev->dev_addr)) | 246 | if (!ether_addr_equal(sdata->vif.addr, |
247 | nsdata->vif.addr)) | ||
131 | continue; | 248 | continue; |
132 | 249 | ||
133 | /* | 250 | /* |
@@ -217,17 +334,21 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) | |||
217 | static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | 334 | static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) |
218 | { | 335 | { |
219 | struct ieee80211_sub_if_data *sdata; | 336 | struct ieee80211_sub_if_data *sdata; |
220 | int ret; | 337 | int ret = 0; |
221 | 338 | ||
222 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) | 339 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) |
223 | return 0; | 340 | return 0; |
224 | 341 | ||
342 | mutex_lock(&local->iflist_mtx); | ||
343 | |||
225 | if (local->monitor_sdata) | 344 | if (local->monitor_sdata) |
226 | return 0; | 345 | goto out_unlock; |
227 | 346 | ||
228 | sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); | 347 | sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); |
229 | if (!sdata) | 348 | if (!sdata) { |
230 | return -ENOMEM; | 349 | ret = -ENOMEM; |
350 | goto out_unlock; | ||
351 | } | ||
231 | 352 | ||
232 | /* set up data */ | 353 | /* set up data */ |
233 | sdata->local = local; | 354 | sdata->local = local; |
@@ -241,18 +362,19 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
241 | if (WARN_ON(ret)) { | 362 | if (WARN_ON(ret)) { |
242 | /* ok .. stupid driver, it asked for this! */ | 363 | /* ok .. stupid driver, it asked for this! */ |
243 | kfree(sdata); | 364 | kfree(sdata); |
244 | return ret; | 365 | goto out_unlock; |
245 | } | 366 | } |
246 | 367 | ||
247 | ret = ieee80211_check_queues(sdata); | 368 | ret = ieee80211_check_queues(sdata); |
248 | if (ret) { | 369 | if (ret) { |
249 | kfree(sdata); | 370 | kfree(sdata); |
250 | return ret; | 371 | goto out_unlock; |
251 | } | 372 | } |
252 | 373 | ||
253 | rcu_assign_pointer(local->monitor_sdata, sdata); | 374 | rcu_assign_pointer(local->monitor_sdata, sdata); |
254 | 375 | out_unlock: | |
255 | return 0; | 376 | mutex_unlock(&local->iflist_mtx); |
377 | return ret; | ||
256 | } | 378 | } |
257 | 379 | ||
258 | static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | 380 | static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) |
@@ -262,10 +384,12 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
262 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) | 384 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) |
263 | return; | 385 | return; |
264 | 386 | ||
265 | sdata = rtnl_dereference(local->monitor_sdata); | 387 | mutex_lock(&local->iflist_mtx); |
266 | 388 | ||
389 | sdata = rcu_dereference_protected(local->monitor_sdata, | ||
390 | lockdep_is_held(&local->iflist_mtx)); | ||
267 | if (!sdata) | 391 | if (!sdata) |
268 | return; | 392 | goto out_unlock; |
269 | 393 | ||
270 | rcu_assign_pointer(local->monitor_sdata, NULL); | 394 | rcu_assign_pointer(local->monitor_sdata, NULL); |
271 | synchronize_net(); | 395 | synchronize_net(); |
@@ -273,6 +397,8 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
273 | drv_remove_interface(local, sdata); | 397 | drv_remove_interface(local, sdata); |
274 | 398 | ||
275 | kfree(sdata); | 399 | kfree(sdata); |
400 | out_unlock: | ||
401 | mutex_unlock(&local->iflist_mtx); | ||
276 | } | 402 | } |
277 | 403 | ||
278 | /* | 404 | /* |
@@ -520,7 +646,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
520 | 646 | ||
521 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); | 647 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); |
522 | 648 | ||
523 | if (local->scan_sdata == sdata) | 649 | if (rcu_access_pointer(local->scan_sdata) == sdata) |
524 | ieee80211_scan_cancel(local); | 650 | ieee80211_scan_cancel(local); |
525 | 651 | ||
526 | /* | 652 | /* |
@@ -528,10 +654,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
528 | */ | 654 | */ |
529 | netif_tx_stop_all_queues(sdata->dev); | 655 | netif_tx_stop_all_queues(sdata->dev); |
530 | 656 | ||
531 | /* | 657 | ieee80211_roc_purge(sdata); |
532 | * Purge work for this interface. | ||
533 | */ | ||
534 | ieee80211_work_purge(sdata); | ||
535 | 658 | ||
536 | /* | 659 | /* |
537 | * Remove all stations associated with this interface. | 660 | * Remove all stations associated with this interface. |
@@ -637,18 +760,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
637 | ieee80211_configure_filter(local); | 760 | ieee80211_configure_filter(local); |
638 | break; | 761 | break; |
639 | default: | 762 | default: |
640 | mutex_lock(&local->mtx); | ||
641 | if (local->hw_roc_dev == sdata->dev && | ||
642 | local->hw_roc_channel) { | ||
643 | /* ignore return value since this is racy */ | ||
644 | drv_cancel_remain_on_channel(local); | ||
645 | ieee80211_queue_work(&local->hw, &local->hw_roc_done); | ||
646 | } | ||
647 | mutex_unlock(&local->mtx); | ||
648 | |||
649 | flush_work(&local->hw_roc_start); | ||
650 | flush_work(&local->hw_roc_done); | ||
651 | |||
652 | flush_work(&sdata->work); | 763 | flush_work(&sdata->work); |
653 | /* | 764 | /* |
654 | * When we get here, the interface is marked down. | 765 | * When we get here, the interface is marked down. |
@@ -823,7 +934,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, | |||
823 | 934 | ||
824 | hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); | 935 | hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); |
825 | 936 | ||
826 | return ieee80211_select_queue_80211(local, skb, hdr); | 937 | return ieee80211_select_queue_80211(sdata, skb, hdr); |
827 | } | 938 | } |
828 | 939 | ||
829 | static const struct net_device_ops ieee80211_monitorif_ops = { | 940 | static const struct net_device_ops ieee80211_monitorif_ops = { |
@@ -1238,7 +1349,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1238 | 1349 | ||
1239 | if (__ffs64(mask) + hweight64(mask) != fls64(mask)) { | 1350 | if (__ffs64(mask) + hweight64(mask) != fls64(mask)) { |
1240 | /* not a contiguous mask ... not handled now! */ | 1351 | /* not a contiguous mask ... not handled now! */ |
1241 | printk(KERN_DEBUG "not contiguous\n"); | 1352 | pr_info("not contiguous\n"); |
1242 | break; | 1353 | break; |
1243 | } | 1354 | } |
1244 | 1355 | ||
@@ -1284,7 +1395,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1284 | } | 1395 | } |
1285 | 1396 | ||
1286 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 1397 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
1287 | struct net_device **new_dev, enum nl80211_iftype type, | 1398 | struct wireless_dev **new_wdev, enum nl80211_iftype type, |
1288 | struct vif_params *params) | 1399 | struct vif_params *params) |
1289 | { | 1400 | { |
1290 | struct net_device *ndev; | 1401 | struct net_device *ndev; |
@@ -1364,6 +1475,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1364 | sdata->u.mgd.use_4addr = params->use_4addr; | 1475 | sdata->u.mgd.use_4addr = params->use_4addr; |
1365 | } | 1476 | } |
1366 | 1477 | ||
1478 | ndev->features |= local->hw.netdev_features; | ||
1479 | |||
1367 | ret = register_netdevice(ndev); | 1480 | ret = register_netdevice(ndev); |
1368 | if (ret) | 1481 | if (ret) |
1369 | goto fail; | 1482 | goto fail; |
@@ -1372,8 +1485,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1372 | list_add_tail_rcu(&sdata->list, &local->interfaces); | 1485 | list_add_tail_rcu(&sdata->list, &local->interfaces); |
1373 | mutex_unlock(&local->iflist_mtx); | 1486 | mutex_unlock(&local->iflist_mtx); |
1374 | 1487 | ||
1375 | if (new_dev) | 1488 | if (new_wdev) |
1376 | *new_dev = ndev; | 1489 | *new_wdev = &sdata->wdev; |
1377 | 1490 | ||
1378 | return 0; | 1491 | return 0; |
1379 | 1492 | ||
@@ -1421,138 +1534,6 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
1421 | list_del(&unreg_list); | 1534 | list_del(&unreg_list); |
1422 | } | 1535 | } |
1423 | 1536 | ||
1424 | static u32 ieee80211_idle_off(struct ieee80211_local *local, | ||
1425 | const char *reason) | ||
1426 | { | ||
1427 | if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) | ||
1428 | return 0; | ||
1429 | |||
1430 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1431 | wiphy_debug(local->hw.wiphy, "device no longer idle - %s\n", reason); | ||
1432 | #endif | ||
1433 | |||
1434 | local->hw.conf.flags &= ~IEEE80211_CONF_IDLE; | ||
1435 | return IEEE80211_CONF_CHANGE_IDLE; | ||
1436 | } | ||
1437 | |||
1438 | static u32 ieee80211_idle_on(struct ieee80211_local *local) | ||
1439 | { | ||
1440 | if (local->hw.conf.flags & IEEE80211_CONF_IDLE) | ||
1441 | return 0; | ||
1442 | |||
1443 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1444 | wiphy_debug(local->hw.wiphy, "device now idle\n"); | ||
1445 | #endif | ||
1446 | |||
1447 | drv_flush(local, false); | ||
1448 | |||
1449 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; | ||
1450 | return IEEE80211_CONF_CHANGE_IDLE; | ||
1451 | } | ||
1452 | |||
1453 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | ||
1454 | { | ||
1455 | struct ieee80211_sub_if_data *sdata; | ||
1456 | int count = 0; | ||
1457 | bool working = false, scanning = false, hw_roc = false; | ||
1458 | struct ieee80211_work *wk; | ||
1459 | unsigned int led_trig_start = 0, led_trig_stop = 0; | ||
1460 | |||
1461 | #ifdef CONFIG_PROVE_LOCKING | ||
1462 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && | ||
1463 | !lockdep_is_held(&local->iflist_mtx)); | ||
1464 | #endif | ||
1465 | lockdep_assert_held(&local->mtx); | ||
1466 | |||
1467 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1468 | if (!ieee80211_sdata_running(sdata)) { | ||
1469 | sdata->vif.bss_conf.idle = true; | ||
1470 | continue; | ||
1471 | } | ||
1472 | |||
1473 | sdata->old_idle = sdata->vif.bss_conf.idle; | ||
1474 | |||
1475 | /* do not count disabled managed interfaces */ | ||
1476 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
1477 | !sdata->u.mgd.associated && | ||
1478 | !sdata->u.mgd.auth_data && | ||
1479 | !sdata->u.mgd.assoc_data) { | ||
1480 | sdata->vif.bss_conf.idle = true; | ||
1481 | continue; | ||
1482 | } | ||
1483 | /* do not count unused IBSS interfaces */ | ||
1484 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
1485 | !sdata->u.ibss.ssid_len) { | ||
1486 | sdata->vif.bss_conf.idle = true; | ||
1487 | continue; | ||
1488 | } | ||
1489 | /* count everything else */ | ||
1490 | sdata->vif.bss_conf.idle = false; | ||
1491 | count++; | ||
1492 | } | ||
1493 | |||
1494 | list_for_each_entry(wk, &local->work_list, list) { | ||
1495 | working = true; | ||
1496 | wk->sdata->vif.bss_conf.idle = false; | ||
1497 | } | ||
1498 | |||
1499 | if (local->scan_sdata && | ||
1500 | !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { | ||
1501 | scanning = true; | ||
1502 | local->scan_sdata->vif.bss_conf.idle = false; | ||
1503 | } | ||
1504 | |||
1505 | if (local->hw_roc_channel) | ||
1506 | hw_roc = true; | ||
1507 | |||
1508 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1509 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | ||
1510 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
1511 | continue; | ||
1512 | if (sdata->old_idle == sdata->vif.bss_conf.idle) | ||
1513 | continue; | ||
1514 | if (!ieee80211_sdata_running(sdata)) | ||
1515 | continue; | ||
1516 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | ||
1517 | } | ||
1518 | |||
1519 | if (working || scanning || hw_roc) | ||
1520 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; | ||
1521 | else | ||
1522 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; | ||
1523 | |||
1524 | if (count) | ||
1525 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | ||
1526 | else | ||
1527 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | ||
1528 | |||
1529 | ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); | ||
1530 | |||
1531 | if (hw_roc) | ||
1532 | return ieee80211_idle_off(local, "hw remain-on-channel"); | ||
1533 | if (working) | ||
1534 | return ieee80211_idle_off(local, "working"); | ||
1535 | if (scanning) | ||
1536 | return ieee80211_idle_off(local, "scanning"); | ||
1537 | if (!count) | ||
1538 | return ieee80211_idle_on(local); | ||
1539 | else | ||
1540 | return ieee80211_idle_off(local, "in use"); | ||
1541 | |||
1542 | return 0; | ||
1543 | } | ||
1544 | |||
1545 | void ieee80211_recalc_idle(struct ieee80211_local *local) | ||
1546 | { | ||
1547 | u32 chg; | ||
1548 | |||
1549 | mutex_lock(&local->iflist_mtx); | ||
1550 | chg = __ieee80211_recalc_idle(local); | ||
1551 | mutex_unlock(&local->iflist_mtx); | ||
1552 | if (chg) | ||
1553 | ieee80211_hw_config(local, chg); | ||
1554 | } | ||
1555 | |||
1556 | static int netdev_notify(struct notifier_block *nb, | 1537 | static int netdev_notify(struct notifier_block *nb, |
1557 | unsigned long state, | 1538 | unsigned long state, |
1558 | void *ndev) | 1539 | void *ndev) |