diff options
Diffstat (limited to 'net/mac80211/driver-ops.h')
| -rw-r--r-- | net/mac80211/driver-ops.h | 243 | 
1 files changed, 190 insertions, 53 deletions
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index b3ea11f3d52..bd782dcffcc 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -5,11 +5,11 @@  #include "ieee80211_i.h"  #include "trace.h" -static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) +static inline bool check_sdata_in_driver(struct ieee80211_sub_if_data *sdata)  { -	WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), -	     "%s:  Failed check-sdata-in-driver check, flags: 0x%x\n", -	     sdata->dev ? sdata->dev->name : sdata->name, sdata->flags); +	return !WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), +		     "%s:  Failed check-sdata-in-driver check, flags: 0x%x\n", +		     sdata->dev ? sdata->dev->name : sdata->name, sdata->flags);  }  static inline struct ieee80211_sub_if_data * @@ -168,7 +168,8 @@ static inline int drv_change_interface(struct ieee80211_local *local,  	might_sleep(); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return -EIO;  	trace_drv_change_interface(local, sdata, type, p2p);  	ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); @@ -181,7 +182,8 @@ static inline void drv_remove_interface(struct ieee80211_local *local,  {  	might_sleep(); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	trace_drv_remove_interface(local, sdata);  	local->ops->remove_interface(&local->hw, &sdata->vif); @@ -219,7 +221,8 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,  			 sdata->vif.type == NL80211_IFTYPE_MONITOR))  		return; -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	trace_drv_bss_info_changed(local, sdata, info, changed);  	if (local->ops->bss_info_changed) @@ -242,22 +245,6 @@ static inline u64 drv_prepare_multicast(struct ieee80211_local *local,  	return ret;  } -static inline void drv_set_multicast_list(struct ieee80211_local *local, -					  struct ieee80211_sub_if_data *sdata, -					  struct netdev_hw_addr_list *mc_list) -{ -	bool allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI; - -	trace_drv_set_multicast_list(local, sdata, mc_list->count); - -	check_sdata_in_driver(sdata); - -	if (local->ops->set_multicast_list) -		local->ops->set_multicast_list(&local->hw, &sdata->vif, -					       allmulti, mc_list); -	trace_drv_return_void(local); -} -  static inline void drv_configure_filter(struct ieee80211_local *local,  					unsigned int changed_flags,  					unsigned int *total_flags, @@ -294,7 +281,8 @@ static inline int drv_set_key(struct ieee80211_local *local,  	might_sleep();  	sdata = get_bss_sdata(sdata); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return -EIO;  	trace_drv_set_key(local, cmd, sdata, sta, key);  	ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); @@ -314,7 +302,8 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local,  		ista = &sta->sta;  	sdata = get_bss_sdata(sdata); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	trace_drv_update_tkip_key(local, sdata, conf, ista, iv32);  	if (local->ops->update_tkip_key) @@ -331,7 +320,8 @@ static inline int drv_hw_scan(struct ieee80211_local *local,  	might_sleep(); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return -EIO;  	trace_drv_hw_scan(local, sdata);  	ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); @@ -344,7 +334,8 @@ static inline void drv_cancel_hw_scan(struct ieee80211_local *local,  {  	might_sleep(); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	trace_drv_cancel_hw_scan(local, sdata);  	local->ops->cancel_hw_scan(&local->hw, &sdata->vif); @@ -361,7 +352,8 @@ drv_sched_scan_start(struct ieee80211_local *local,  	might_sleep(); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return -EIO;  	trace_drv_sched_scan_start(local, sdata);  	ret = local->ops->sched_scan_start(&local->hw, &sdata->vif, @@ -370,16 +362,21 @@ drv_sched_scan_start(struct ieee80211_local *local,  	return ret;  } -static inline void drv_sched_scan_stop(struct ieee80211_local *local, -				       struct ieee80211_sub_if_data *sdata) +static inline int drv_sched_scan_stop(struct ieee80211_local *local, +				      struct ieee80211_sub_if_data *sdata)  { +	int ret; +  	might_sleep(); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return -EIO;  	trace_drv_sched_scan_stop(local, sdata); -	local->ops->sched_scan_stop(&local->hw, &sdata->vif); -	trace_drv_return_void(local); +	ret = local->ops->sched_scan_stop(&local->hw, &sdata->vif); +	trace_drv_return_int(local, ret); + +	return ret;  }  static inline void drv_sw_scan_start(struct ieee80211_local *local) @@ -474,7 +471,8 @@ static inline void drv_sta_notify(struct ieee80211_local *local,  				  struct ieee80211_sta *sta)  {  	sdata = get_bss_sdata(sdata); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	trace_drv_sta_notify(local, sdata, cmd, sta);  	if (local->ops->sta_notify) @@ -491,7 +489,8 @@ static inline int drv_sta_add(struct ieee80211_local *local,  	might_sleep();  	sdata = get_bss_sdata(sdata); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return -EIO;  	trace_drv_sta_add(local, sdata, sta);  	if (local->ops->sta_add) @@ -509,7 +508,8 @@ static inline void drv_sta_remove(struct ieee80211_local *local,  	might_sleep();  	sdata = get_bss_sdata(sdata); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	trace_drv_sta_remove(local, sdata, sta);  	if (local->ops->sta_remove) @@ -527,7 +527,8 @@ static inline void drv_sta_add_debugfs(struct ieee80211_local *local,  	might_sleep();  	sdata = get_bss_sdata(sdata); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	if (local->ops->sta_add_debugfs)  		local->ops->sta_add_debugfs(&local->hw, &sdata->vif, @@ -550,6 +551,23 @@ static inline void drv_sta_remove_debugfs(struct ieee80211_local *local,  }  #endif +static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local, +					  struct ieee80211_sub_if_data *sdata, +					  struct sta_info *sta) +{ +	might_sleep(); + +	sdata = get_bss_sdata(sdata); +	if (!check_sdata_in_driver(sdata)) +		return; + +	trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta); +	if (local->ops->sta_pre_rcu_remove) +		local->ops->sta_pre_rcu_remove(&local->hw, &sdata->vif, +					       &sta->sta); +	trace_drv_return_void(local); +} +  static inline __must_check  int drv_sta_state(struct ieee80211_local *local,  		  struct ieee80211_sub_if_data *sdata, @@ -562,7 +580,8 @@ int drv_sta_state(struct ieee80211_local *local,  	might_sleep();  	sdata = get_bss_sdata(sdata); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return -EIO;  	trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state);  	if (local->ops->sta_state) { @@ -586,7 +605,8 @@ static inline void drv_sta_rc_update(struct ieee80211_local *local,  				     struct ieee80211_sta *sta, u32 changed)  {  	sdata = get_bss_sdata(sdata); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED &&  		(sdata->vif.type != NL80211_IFTYPE_ADHOC && @@ -608,7 +628,8 @@ static inline int drv_conf_tx(struct ieee80211_local *local,  	might_sleep(); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return -EIO;  	trace_drv_conf_tx(local, sdata, ac, params);  	if (local->ops->conf_tx) @@ -625,7 +646,8 @@ static inline u64 drv_get_tsf(struct ieee80211_local *local,  	might_sleep(); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return ret;  	trace_drv_get_tsf(local, sdata);  	if (local->ops->get_tsf) @@ -640,7 +662,8 @@ static inline void drv_set_tsf(struct ieee80211_local *local,  {  	might_sleep(); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	trace_drv_set_tsf(local, sdata, tsf);  	if (local->ops->set_tsf) @@ -653,7 +676,8 @@ static inline void drv_reset_tsf(struct ieee80211_local *local,  {  	might_sleep(); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	trace_drv_reset_tsf(local, sdata);  	if (local->ops->reset_tsf) @@ -685,7 +709,8 @@ static inline int drv_ampdu_action(struct ieee80211_local *local,  	might_sleep();  	sdata = get_bss_sdata(sdata); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return -EIO;  	trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); @@ -722,13 +747,19 @@ static inline void drv_rfkill_poll(struct ieee80211_local *local)  }  static inline void drv_flush(struct ieee80211_local *local, +			     struct ieee80211_sub_if_data *sdata,  			     u32 queues, bool drop)  { +	struct ieee80211_vif *vif = sdata ? &sdata->vif : NULL; +  	might_sleep(); +	if (sdata && !check_sdata_in_driver(sdata)) +		return; +  	trace_drv_flush(local, queues, drop);  	if (local->ops->flush) -		local->ops->flush(&local->hw, queues, drop); +		local->ops->flush(&local->hw, vif, queues, drop);  	trace_drv_return_void(local);  } @@ -844,7 +875,8 @@ static inline int drv_set_bitrate_mask(struct ieee80211_local *local,  	might_sleep(); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return -EIO;  	trace_drv_set_bitrate_mask(local, sdata, mask);  	if (local->ops->set_bitrate_mask) @@ -859,7 +891,8 @@ static inline void drv_set_rekey_data(struct ieee80211_local *local,  				      struct ieee80211_sub_if_data *sdata,  				      struct cfg80211_gtk_rekey_data *data)  { -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	trace_drv_set_rekey_data(local, sdata, data);  	if (local->ops->set_rekey_data) @@ -927,7 +960,8 @@ static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,  {  	might_sleep(); -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);  	trace_drv_mgd_prepare_tx(local, sdata); @@ -954,6 +988,9 @@ static inline int drv_add_chanctx(struct ieee80211_local *local,  static inline void drv_remove_chanctx(struct ieee80211_local *local,  				      struct ieee80211_chanctx *ctx)  { +	if (WARN_ON(!ctx->driver_present)) +		return; +  	trace_drv_remove_chanctx(local, ctx);  	if (local->ops->remove_chanctx)  		local->ops->remove_chanctx(&local->hw, &ctx->conf); @@ -979,7 +1016,8 @@ static inline int drv_assign_vif_chanctx(struct ieee80211_local *local,  {  	int ret = 0; -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return -EIO;  	trace_drv_assign_vif_chanctx(local, sdata, ctx);  	if (local->ops->assign_vif_chanctx) { @@ -997,7 +1035,8 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,  					    struct ieee80211_sub_if_data *sdata,  					    struct ieee80211_chanctx *ctx)  { -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	trace_drv_unassign_vif_chanctx(local, sdata, ctx);  	if (local->ops->unassign_vif_chanctx) { @@ -1009,12 +1048,66 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,  	trace_drv_return_void(local);  } +static inline int +drv_switch_vif_chanctx(struct ieee80211_local *local, +		       struct ieee80211_vif_chanctx_switch *vifs, +		       int n_vifs, +		       enum ieee80211_chanctx_switch_mode mode) +{ +	int ret = 0; +	int i; + +	if (!local->ops->switch_vif_chanctx) +		return -EOPNOTSUPP; + +	for (i = 0; i < n_vifs; i++) { +		struct ieee80211_chanctx *new_ctx = +			container_of(vifs[i].new_ctx, +				     struct ieee80211_chanctx, +				     conf); +		struct ieee80211_chanctx *old_ctx = +			container_of(vifs[i].old_ctx, +				     struct ieee80211_chanctx, +				     conf); + +		WARN_ON_ONCE(!old_ctx->driver_present); +		WARN_ON_ONCE((mode == CHANCTX_SWMODE_SWAP_CONTEXTS && +			      new_ctx->driver_present) || +			     (mode == CHANCTX_SWMODE_REASSIGN_VIF && +			      !new_ctx->driver_present)); +	} + +	trace_drv_switch_vif_chanctx(local, vifs, n_vifs, mode); +	ret = local->ops->switch_vif_chanctx(&local->hw, +					     vifs, n_vifs, mode); +	trace_drv_return_int(local, ret); + +	if (!ret && mode == CHANCTX_SWMODE_SWAP_CONTEXTS) { +		for (i = 0; i < n_vifs; i++) { +			struct ieee80211_chanctx *new_ctx = +				container_of(vifs[i].new_ctx, +					     struct ieee80211_chanctx, +					     conf); +			struct ieee80211_chanctx *old_ctx = +				container_of(vifs[i].old_ctx, +					     struct ieee80211_chanctx, +					     conf); + +			new_ctx->driver_present = true; +			old_ctx->driver_present = false; +		} +	} + +	return ret; +} +  static inline int drv_start_ap(struct ieee80211_local *local,  			       struct ieee80211_sub_if_data *sdata)  {  	int ret = 0; -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return -EIO;  	trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf);  	if (local->ops->start_ap) @@ -1026,7 +1119,8 @@ static inline int drv_start_ap(struct ieee80211_local *local,  static inline void drv_stop_ap(struct ieee80211_local *local,  			       struct ieee80211_sub_if_data *sdata)  { -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	trace_drv_stop_ap(local, sdata);  	if (local->ops->stop_ap) @@ -1049,7 +1143,8 @@ drv_set_default_unicast_key(struct ieee80211_local *local,  			    struct ieee80211_sub_if_data *sdata,  			    int key_idx)  { -	check_sdata_in_driver(sdata); +	if (!check_sdata_in_driver(sdata)) +		return;  	WARN_ON_ONCE(key_idx < -1 || key_idx > 3); @@ -1085,4 +1180,46 @@ drv_channel_switch_beacon(struct ieee80211_sub_if_data *sdata,  	}  } +static inline int drv_join_ibss(struct ieee80211_local *local, +				struct ieee80211_sub_if_data *sdata) +{ +	int ret = 0; + +	might_sleep(); +	if (!check_sdata_in_driver(sdata)) +		return -EIO; + +	trace_drv_join_ibss(local, sdata, &sdata->vif.bss_conf); +	if (local->ops->join_ibss) +		ret = local->ops->join_ibss(&local->hw, &sdata->vif); +	trace_drv_return_int(local, ret); +	return ret; +} + +static inline void drv_leave_ibss(struct ieee80211_local *local, +				  struct ieee80211_sub_if_data *sdata) +{ +	might_sleep(); +	if (!check_sdata_in_driver(sdata)) +		return; + +	trace_drv_leave_ibss(local, sdata); +	if (local->ops->leave_ibss) +		local->ops->leave_ibss(&local->hw, &sdata->vif); +	trace_drv_return_void(local); +} + +static inline u32 drv_get_expected_throughput(struct ieee80211_local *local, +					      struct ieee80211_sta *sta) +{ +	u32 ret = 0; + +	trace_drv_get_expected_throughput(sta); +	if (local->ops->get_expected_throughput) +		ret = local->ops->get_expected_throughput(sta); +	trace_drv_return_u32(local, ret); + +	return ret; +} +  #endif /* __MAC80211_DRIVER_OPS */  | 
