diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 11 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 25 | ||||
-rw-r--r-- | net/mac80211/pm.c | 4 | ||||
-rw-r--r-- | net/mac80211/trace.h | 37 | ||||
-rw-r--r-- | net/mac80211/util.c | 6 |
5 files changed, 82 insertions, 1 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 95bf3d5..34fd3eb 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, return err; changed |= err; + err = drv_start_ap(sdata->local, sdata); + if (err) { + old = rtnl_dereference(sdata->u.ap.beacon); + if (old) + kfree_rcu(old, rcu_head); + RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); + return err; + } + ieee80211_bss_info_change_notify(sdata, changed); netif_carrier_on(dev); @@ -979,6 +988,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) sta_info_flush(local, sdata); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); + drv_stop_ap(sdata->local, sdata); + /* free all potentially still buffered bcast frames */ local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf); skb_queue_purge(&sdata->u.ap.ps.bc_buf); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 77407b3..1701ad7 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, trace_drv_return_void(local); } +static inline int drv_start_ap(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata) +{ + int ret = 0; + + check_sdata_in_driver(sdata); + + trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf); + if (local->ops->start_ap) + ret = local->ops->start_ap(&local->hw, &sdata->vif); + trace_drv_return_int(local, ret); + return ret; +} + +static inline void drv_stop_ap(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata) +{ + check_sdata_in_driver(sdata); + + trace_drv_stop_ap(local, sdata); + if (local->ops->stop_ap) + local->ops->stop_ap(&local->hw, &sdata->vif); + trace_drv_return_void(local); +} + #endif /* __MAC80211_DRIVER_OPS */ diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 9f404ac..0f1c434 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) ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); + if (sdata->vif.type == NL80211_IFTYPE_AP && + rcu_access_pointer(sdata->u.ap.beacon)) + drv_stop_ap(local, sdata); + /* the interface is leaving the channel and is removed */ ieee80211_vif_release_channel(sdata); drv_remove_interface(local, sdata); diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 0638541..5e74e77 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -1396,6 +1396,43 @@ DEFINE_EVENT(local_sdata_chanctx, drv_unassign_vif_chanctx, TP_ARGS(local, sdata, ctx) ); +TRACE_EVENT(drv_start_ap, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_bss_conf *info), + + TP_ARGS(local, sdata, info), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + __field(u8, dtimper) + __field(u16, bcnint) + __dynamic_array(u8, ssid, info->ssid_len); + __field(bool, hidden_ssid); + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + __entry->dtimper = info->dtim_period; + __entry->bcnint = info->beacon_int; + memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len); + __entry->hidden_ssid = info->hidden_ssid; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT, + LOCAL_PR_ARG, VIF_PR_ARG + ) +); + +DEFINE_EVENT(local_sdata_evt, drv_stop_ap, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata) +); + /* * Tracing for API calls that drivers call. */ diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ea8a674..dd0e6f2 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1467,9 +1467,13 @@ int ieee80211_reconfig(struct ieee80211_local *local) case NL80211_IFTYPE_AP: changed |= BSS_CHANGED_SSID; - if (sdata->vif.type == NL80211_IFTYPE_AP) + if (sdata->vif.type == NL80211_IFTYPE_AP) { changed |= BSS_CHANGED_AP_PROBE_RESP; + if (rcu_access_pointer(sdata->u.ap.beacon)) + drv_start_ap(local, sdata); + } + /* fall through */ case NL80211_IFTYPE_MESH_POINT: changed |= BSS_CHANGED_BEACON | |