aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c258
1 files changed, 123 insertions, 135 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 58c2ab3d483a..fbef7a1ada7a 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -43,6 +43,127 @@
43 */ 43 */
44 44
45 45
46static 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
56static 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
67static 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 if (local->scan_sdata &&
116 !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) {
117 scanning = true;
118 local->scan_sdata->vif.bss_conf.idle = false;
119 }
120
121 list_for_each_entry(sdata, &local->interfaces, list) {
122 if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
123 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
124 continue;
125 if (sdata->old_idle == sdata->vif.bss_conf.idle)
126 continue;
127 if (!ieee80211_sdata_running(sdata))
128 continue;
129 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
130 }
131
132 if (working || scanning)
133 led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK;
134 else
135 led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK;
136
137 if (count)
138 led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
139 else
140 led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
141
142 ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
143
144 if (working)
145 return ieee80211_idle_off(local, "working");
146 if (scanning)
147 return ieee80211_idle_off(local, "scanning");
148 if (!count)
149 return ieee80211_idle_on(local);
150 else
151 return ieee80211_idle_off(local, "in use");
152
153 return 0;
154}
155
156void ieee80211_recalc_idle(struct ieee80211_local *local)
157{
158 u32 chg;
159
160 mutex_lock(&local->iflist_mtx);
161 chg = __ieee80211_recalc_idle(local);
162 mutex_unlock(&local->iflist_mtx);
163 if (chg)
164 ieee80211_hw_config(local, chg);
165}
166
46static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) 167static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
47{ 168{
48 int meshhdrlen; 169 int meshhdrlen;
@@ -209,7 +330,7 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
209 sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; 330 sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
210} 331}
211 332
212static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) 333int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
213{ 334{
214 struct ieee80211_sub_if_data *sdata; 335 struct ieee80211_sub_if_data *sdata;
215 int ret; 336 int ret;
@@ -250,7 +371,7 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
250 return 0; 371 return 0;
251} 372}
252 373
253static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) 374void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
254{ 375{
255 struct ieee80211_sub_if_data *sdata; 376 struct ieee80211_sub_if_data *sdata;
256 377
@@ -366,12 +487,6 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
366 break; 487 break;
367 } 488 }
368 489
369 if (local->monitors == 0 && local->open_count == 0) {
370 res = ieee80211_add_virtual_monitor(local);
371 if (res)
372 goto err_stop;
373 }
374
375 /* must be before the call to ieee80211_configure_filter */ 490 /* must be before the call to ieee80211_configure_filter */
376 local->monitors++; 491 local->monitors++;
377 if (local->monitors == 1) { 492 if (local->monitors == 1) {
@@ -386,8 +501,6 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
386 break; 501 break;
387 default: 502 default:
388 if (coming_up) { 503 if (coming_up) {
389 ieee80211_del_virtual_monitor(local);
390
391 res = drv_add_interface(local, sdata); 504 res = drv_add_interface(local, sdata);
392 if (res) 505 if (res)
393 goto err_stop; 506 goto err_stop;
@@ -622,7 +735,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
622 if (local->monitors == 0) { 735 if (local->monitors == 0) {
623 local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; 736 local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;
624 hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; 737 hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
625 ieee80211_del_virtual_monitor(local);
626 } 738 }
627 739
628 ieee80211_adjust_monitor_flags(sdata, -1); 740 ieee80211_adjust_monitor_flags(sdata, -1);
@@ -696,9 +808,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
696 } 808 }
697 } 809 }
698 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 810 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
699
700 if (local->monitors == local->open_count && local->monitors > 0)
701 ieee80211_add_virtual_monitor(local);
702} 811}
703 812
704static int ieee80211_stop(struct net_device *dev) 813static int ieee80211_stop(struct net_device *dev)
@@ -1403,127 +1512,6 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
1403 list_del(&unreg_list); 1512 list_del(&unreg_list);
1404} 1513}
1405 1514
1406static u32 ieee80211_idle_off(struct ieee80211_local *local,
1407 const char *reason)
1408{
1409 if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
1410 return 0;
1411
1412 local->hw.conf.flags &= ~IEEE80211_CONF_IDLE;
1413 return IEEE80211_CONF_CHANGE_IDLE;
1414}
1415
1416static u32 ieee80211_idle_on(struct ieee80211_local *local)
1417{
1418 if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
1419 return 0;
1420
1421 drv_flush(local, false);
1422
1423 local->hw.conf.flags |= IEEE80211_CONF_IDLE;
1424 return IEEE80211_CONF_CHANGE_IDLE;
1425}
1426
1427u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
1428{
1429 struct ieee80211_sub_if_data *sdata;
1430 int count = 0;
1431 bool working = false, scanning = false;
1432 unsigned int led_trig_start = 0, led_trig_stop = 0;
1433 struct ieee80211_roc_work *roc;
1434
1435#ifdef CONFIG_PROVE_LOCKING
1436 WARN_ON(debug_locks && !lockdep_rtnl_is_held() &&
1437 !lockdep_is_held(&local->iflist_mtx));
1438#endif
1439 lockdep_assert_held(&local->mtx);
1440
1441 list_for_each_entry(sdata, &local->interfaces, list) {
1442 if (!ieee80211_sdata_running(sdata)) {
1443 sdata->vif.bss_conf.idle = true;
1444 continue;
1445 }
1446
1447 sdata->old_idle = sdata->vif.bss_conf.idle;
1448
1449 /* do not count disabled managed interfaces */
1450 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
1451 !sdata->u.mgd.associated &&
1452 !sdata->u.mgd.auth_data &&
1453 !sdata->u.mgd.assoc_data) {
1454 sdata->vif.bss_conf.idle = true;
1455 continue;
1456 }
1457 /* do not count unused IBSS interfaces */
1458 if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
1459 !sdata->u.ibss.ssid_len) {
1460 sdata->vif.bss_conf.idle = true;
1461 continue;
1462 }
1463 /* count everything else */
1464 sdata->vif.bss_conf.idle = false;
1465 count++;
1466 }
1467
1468 if (!local->ops->remain_on_channel) {
1469 list_for_each_entry(roc, &local->roc_list, list) {
1470 working = true;
1471 roc->sdata->vif.bss_conf.idle = false;
1472 }
1473 }
1474
1475 if (local->scan_sdata &&
1476 !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) {
1477 scanning = true;
1478 local->scan_sdata->vif.bss_conf.idle = false;
1479 }
1480
1481 list_for_each_entry(sdata, &local->interfaces, list) {
1482 if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
1483 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1484 continue;
1485 if (sdata->old_idle == sdata->vif.bss_conf.idle)
1486 continue;
1487 if (!ieee80211_sdata_running(sdata))
1488 continue;
1489 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
1490 }
1491
1492 if (working || scanning)
1493 led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK;
1494 else
1495 led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK;
1496
1497 if (count)
1498 led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
1499 else
1500 led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
1501
1502 ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
1503
1504 if (working)
1505 return ieee80211_idle_off(local, "working");
1506 if (scanning)
1507 return ieee80211_idle_off(local, "scanning");
1508 if (!count)
1509 return ieee80211_idle_on(local);
1510 else
1511 return ieee80211_idle_off(local, "in use");
1512
1513 return 0;
1514}
1515
1516void ieee80211_recalc_idle(struct ieee80211_local *local)
1517{
1518 u32 chg;
1519
1520 mutex_lock(&local->iflist_mtx);
1521 chg = __ieee80211_recalc_idle(local);
1522 mutex_unlock(&local->iflist_mtx);
1523 if (chg)
1524 ieee80211_hw_config(local, chg);
1525}
1526
1527static int netdev_notify(struct notifier_block *nb, 1515static int netdev_notify(struct notifier_block *nb,
1528 unsigned long state, 1516 unsigned long state,
1529 void *ndev) 1517 void *ndev)