aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h10
-rw-r--r--net/mac80211/cfg.c11
-rw-r--r--net/mac80211/driver-ops.h25
-rw-r--r--net/mac80211/pm.c4
-rw-r--r--net/mac80211/trace.h37
-rw-r--r--net/mac80211/util.c6
6 files changed, 92 insertions, 1 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 00b7204708bd..5f5327452c9a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2381,6 +2381,13 @@ enum ieee80211_rate_control_changed {
2381 * to vif. Possible use is for hw queue remapping. 2381 * to vif. Possible use is for hw queue remapping.
2382 * @unassign_vif_chanctx: Notifies device driver about channel context being 2382 * @unassign_vif_chanctx: Notifies device driver about channel context being
2383 * unbound from vif. 2383 * unbound from vif.
2384 * @start_ap: Start operation on the AP interface, this is called after all the
2385 * information in bss_conf is set and beacon can be retrieved. A channel
2386 * context is bound before this is called. Note that if the driver uses
2387 * software scan or ROC, this (and @stop_ap) isn't called when the AP is
2388 * just "paused" for scanning/ROC, which is indicated by the beacon being
2389 * disabled/enabled via @bss_info_changed.
2390 * @stop_ap: Stop operation on the AP interface.
2384 */ 2391 */
2385struct ieee80211_ops { 2392struct ieee80211_ops {
2386 void (*tx)(struct ieee80211_hw *hw, 2393 void (*tx)(struct ieee80211_hw *hw,
@@ -2406,6 +2413,9 @@ struct ieee80211_ops {
2406 struct ieee80211_bss_conf *info, 2413 struct ieee80211_bss_conf *info,
2407 u32 changed); 2414 u32 changed);
2408 2415
2416 int (*start_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
2417 void (*stop_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
2418
2409 u64 (*prepare_multicast)(struct ieee80211_hw *hw, 2419 u64 (*prepare_multicast)(struct ieee80211_hw *hw,
2410 struct netdev_hw_addr_list *mc_list); 2420 struct netdev_hw_addr_list *mc_list);
2411 void (*configure_filter)(struct ieee80211_hw *hw, 2421 void (*configure_filter)(struct ieee80211_hw *hw,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 95bf3d5d009f..34fd3eba3090 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -922,6 +922,15 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
922 return err; 922 return err;
923 changed |= err; 923 changed |= err;
924 924
925 err = drv_start_ap(sdata->local, sdata);
926 if (err) {
927 old = rtnl_dereference(sdata->u.ap.beacon);
928 if (old)
929 kfree_rcu(old, rcu_head);
930 RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
931 return err;
932 }
933
925 ieee80211_bss_info_change_notify(sdata, changed); 934 ieee80211_bss_info_change_notify(sdata, changed);
926 935
927 netif_carrier_on(dev); 936 netif_carrier_on(dev);
@@ -979,6 +988,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
979 sta_info_flush(local, sdata); 988 sta_info_flush(local, sdata);
980 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); 989 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
981 990
991 drv_stop_ap(sdata->local, sdata);
992
982 /* free all potentially still buffered bcast frames */ 993 /* free all potentially still buffered bcast frames */
983 local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf); 994 local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf);
984 skb_queue_purge(&sdata->u.ap.ps.bc_buf); 995 skb_queue_purge(&sdata->u.ap.ps.bc_buf);
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 77407b31e1ff..1701ad7013a4 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -936,4 +936,29 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,
936 trace_drv_return_void(local); 936 trace_drv_return_void(local);
937} 937}
938 938
939static inline int drv_start_ap(struct ieee80211_local *local,
940 struct ieee80211_sub_if_data *sdata)
941{
942 int ret = 0;
943
944 check_sdata_in_driver(sdata);
945
946 trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf);
947 if (local->ops->start_ap)
948 ret = local->ops->start_ap(&local->hw, &sdata->vif);
949 trace_drv_return_int(local, ret);
950 return ret;
951}
952
953static inline void drv_stop_ap(struct ieee80211_local *local,
954 struct ieee80211_sub_if_data *sdata)
955{
956 check_sdata_in_driver(sdata);
957
958 trace_drv_stop_ap(local, sdata);
959 if (local->ops->stop_ap)
960 local->ops->stop_ap(&local->hw, &sdata->vif);
961 trace_drv_return_void(local);
962}
963
939#endif /* __MAC80211_DRIVER_OPS */ 964#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 9f404ac901ab..0f1c434638bc 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -135,6 +135,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
135 ieee80211_bss_info_change_notify(sdata, 135 ieee80211_bss_info_change_notify(sdata,
136 BSS_CHANGED_BEACON_ENABLED); 136 BSS_CHANGED_BEACON_ENABLED);
137 137
138 if (sdata->vif.type == NL80211_IFTYPE_AP &&
139 rcu_access_pointer(sdata->u.ap.beacon))
140 drv_stop_ap(local, sdata);
141
138 /* the interface is leaving the channel and is removed */ 142 /* the interface is leaving the channel and is removed */
139 ieee80211_vif_release_channel(sdata); 143 ieee80211_vif_release_channel(sdata);
140 drv_remove_interface(local, sdata); 144 drv_remove_interface(local, sdata);
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 0638541b625f..5e74e77cba9a 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1396,6 +1396,43 @@ DEFINE_EVENT(local_sdata_chanctx, drv_unassign_vif_chanctx,
1396 TP_ARGS(local, sdata, ctx) 1396 TP_ARGS(local, sdata, ctx)
1397); 1397);
1398 1398
1399TRACE_EVENT(drv_start_ap,
1400 TP_PROTO(struct ieee80211_local *local,
1401 struct ieee80211_sub_if_data *sdata,
1402 struct ieee80211_bss_conf *info),
1403
1404 TP_ARGS(local, sdata, info),
1405
1406 TP_STRUCT__entry(
1407 LOCAL_ENTRY
1408 VIF_ENTRY
1409 __field(u8, dtimper)
1410 __field(u16, bcnint)
1411 __dynamic_array(u8, ssid, info->ssid_len);
1412 __field(bool, hidden_ssid);
1413 ),
1414
1415 TP_fast_assign(
1416 LOCAL_ASSIGN;
1417 VIF_ASSIGN;
1418 __entry->dtimper = info->dtim_period;
1419 __entry->bcnint = info->beacon_int;
1420 memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len);
1421 __entry->hidden_ssid = info->hidden_ssid;
1422 ),
1423
1424 TP_printk(
1425 LOCAL_PR_FMT VIF_PR_FMT,
1426 LOCAL_PR_ARG, VIF_PR_ARG
1427 )
1428);
1429
1430DEFINE_EVENT(local_sdata_evt, drv_stop_ap,
1431 TP_PROTO(struct ieee80211_local *local,
1432 struct ieee80211_sub_if_data *sdata),
1433 TP_ARGS(local, sdata)
1434);
1435
1399/* 1436/*
1400 * Tracing for API calls that drivers call. 1437 * Tracing for API calls that drivers call.
1401 */ 1438 */
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index ea8a6744a9db..dd0e6f20fc51 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1467,9 +1467,13 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1467 case NL80211_IFTYPE_AP: 1467 case NL80211_IFTYPE_AP:
1468 changed |= BSS_CHANGED_SSID; 1468 changed |= BSS_CHANGED_SSID;
1469 1469
1470 if (sdata->vif.type == NL80211_IFTYPE_AP) 1470 if (sdata->vif.type == NL80211_IFTYPE_AP) {
1471 changed |= BSS_CHANGED_AP_PROBE_RESP; 1471 changed |= BSS_CHANGED_AP_PROBE_RESP;
1472 1472
1473 if (rcu_access_pointer(sdata->u.ap.beacon))
1474 drv_start_ap(local, sdata);
1475 }
1476
1473 /* fall through */ 1477 /* fall through */
1474 case NL80211_IFTYPE_MESH_POINT: 1478 case NL80211_IFTYPE_MESH_POINT:
1475 changed |= BSS_CHANGED_BEACON | 1479 changed |= BSS_CHANGED_BEACON |