cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

driver-ops.c (8179B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright 2015 Intel Deutschland GmbH
      4 */
      5#include <net/mac80211.h>
      6#include "ieee80211_i.h"
      7#include "trace.h"
      8#include "driver-ops.h"
      9
     10int drv_start(struct ieee80211_local *local)
     11{
     12	int ret;
     13
     14	might_sleep();
     15
     16	if (WARN_ON(local->started))
     17		return -EALREADY;
     18
     19	trace_drv_start(local);
     20	local->started = true;
     21	/* allow rx frames */
     22	smp_mb();
     23	ret = local->ops->start(&local->hw);
     24	trace_drv_return_int(local, ret);
     25
     26	if (ret)
     27		local->started = false;
     28
     29	return ret;
     30}
     31
     32void drv_stop(struct ieee80211_local *local)
     33{
     34	might_sleep();
     35
     36	if (WARN_ON(!local->started))
     37		return;
     38
     39	trace_drv_stop(local);
     40	local->ops->stop(&local->hw);
     41	trace_drv_return_void(local);
     42
     43	/* sync away all work on the tasklet before clearing started */
     44	tasklet_disable(&local->tasklet);
     45	tasklet_enable(&local->tasklet);
     46
     47	barrier();
     48
     49	local->started = false;
     50}
     51
     52int drv_add_interface(struct ieee80211_local *local,
     53		      struct ieee80211_sub_if_data *sdata)
     54{
     55	int ret;
     56
     57	might_sleep();
     58
     59	if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
     60		    (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
     61		     !ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) &&
     62		     !(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))))
     63		return -EINVAL;
     64
     65	trace_drv_add_interface(local, sdata);
     66	ret = local->ops->add_interface(&local->hw, &sdata->vif);
     67	trace_drv_return_int(local, ret);
     68
     69	if (ret == 0)
     70		sdata->flags |= IEEE80211_SDATA_IN_DRIVER;
     71
     72	return ret;
     73}
     74
     75int drv_change_interface(struct ieee80211_local *local,
     76			 struct ieee80211_sub_if_data *sdata,
     77			 enum nl80211_iftype type, bool p2p)
     78{
     79	int ret;
     80
     81	might_sleep();
     82
     83	if (!check_sdata_in_driver(sdata))
     84		return -EIO;
     85
     86	trace_drv_change_interface(local, sdata, type, p2p);
     87	ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p);
     88	trace_drv_return_int(local, ret);
     89	return ret;
     90}
     91
     92void drv_remove_interface(struct ieee80211_local *local,
     93			  struct ieee80211_sub_if_data *sdata)
     94{
     95	might_sleep();
     96
     97	if (!check_sdata_in_driver(sdata))
     98		return;
     99
    100	trace_drv_remove_interface(local, sdata);
    101	local->ops->remove_interface(&local->hw, &sdata->vif);
    102	sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER;
    103	trace_drv_return_void(local);
    104}
    105
    106__must_check
    107int drv_sta_state(struct ieee80211_local *local,
    108		  struct ieee80211_sub_if_data *sdata,
    109		  struct sta_info *sta,
    110		  enum ieee80211_sta_state old_state,
    111		  enum ieee80211_sta_state new_state)
    112{
    113	int ret = 0;
    114
    115	might_sleep();
    116
    117	sdata = get_bss_sdata(sdata);
    118	if (!check_sdata_in_driver(sdata))
    119		return -EIO;
    120
    121	trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state);
    122	if (local->ops->sta_state) {
    123		ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta,
    124					    old_state, new_state);
    125	} else if (old_state == IEEE80211_STA_AUTH &&
    126		   new_state == IEEE80211_STA_ASSOC) {
    127		ret = drv_sta_add(local, sdata, &sta->sta);
    128		if (ret == 0) {
    129			sta->uploaded = true;
    130			if (rcu_access_pointer(sta->sta.rates))
    131				drv_sta_rate_tbl_update(local, sdata, &sta->sta);
    132		}
    133	} else if (old_state == IEEE80211_STA_ASSOC &&
    134		   new_state == IEEE80211_STA_AUTH) {
    135		drv_sta_remove(local, sdata, &sta->sta);
    136	}
    137	trace_drv_return_int(local, ret);
    138	return ret;
    139}
    140
    141__must_check
    142int drv_sta_set_txpwr(struct ieee80211_local *local,
    143		      struct ieee80211_sub_if_data *sdata,
    144		      struct sta_info *sta)
    145{
    146	int ret = -EOPNOTSUPP;
    147
    148	might_sleep();
    149
    150	sdata = get_bss_sdata(sdata);
    151	if (!check_sdata_in_driver(sdata))
    152		return -EIO;
    153
    154	trace_drv_sta_set_txpwr(local, sdata, &sta->sta);
    155	if (local->ops->sta_set_txpwr)
    156		ret = local->ops->sta_set_txpwr(&local->hw, &sdata->vif,
    157						&sta->sta);
    158	trace_drv_return_int(local, ret);
    159	return ret;
    160}
    161
    162void drv_sta_rc_update(struct ieee80211_local *local,
    163		       struct ieee80211_sub_if_data *sdata,
    164		       struct ieee80211_sta *sta, u32 changed)
    165{
    166	sdata = get_bss_sdata(sdata);
    167	if (!check_sdata_in_driver(sdata))
    168		return;
    169
    170	WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED &&
    171		(sdata->vif.type != NL80211_IFTYPE_ADHOC &&
    172		 sdata->vif.type != NL80211_IFTYPE_MESH_POINT));
    173
    174	trace_drv_sta_rc_update(local, sdata, sta, changed);
    175	if (local->ops->sta_rc_update)
    176		local->ops->sta_rc_update(&local->hw, &sdata->vif,
    177					  sta, changed);
    178
    179	trace_drv_return_void(local);
    180}
    181
    182int drv_conf_tx(struct ieee80211_local *local,
    183		struct ieee80211_sub_if_data *sdata, u16 ac,
    184		const struct ieee80211_tx_queue_params *params)
    185{
    186	int ret = -EOPNOTSUPP;
    187
    188	might_sleep();
    189
    190	if (!check_sdata_in_driver(sdata))
    191		return -EIO;
    192
    193	if (params->cw_min == 0 || params->cw_min > params->cw_max) {
    194		/*
    195		 * If we can't configure hardware anyway, don't warn. We may
    196		 * never have initialized the CW parameters.
    197		 */
    198		WARN_ONCE(local->ops->conf_tx,
    199			  "%s: invalid CW_min/CW_max: %d/%d\n",
    200			  sdata->name, params->cw_min, params->cw_max);
    201		return -EINVAL;
    202	}
    203
    204	trace_drv_conf_tx(local, sdata, ac, params);
    205	if (local->ops->conf_tx)
    206		ret = local->ops->conf_tx(&local->hw, &sdata->vif,
    207					  ac, params);
    208	trace_drv_return_int(local, ret);
    209	return ret;
    210}
    211
    212u64 drv_get_tsf(struct ieee80211_local *local,
    213		struct ieee80211_sub_if_data *sdata)
    214{
    215	u64 ret = -1ULL;
    216
    217	might_sleep();
    218
    219	if (!check_sdata_in_driver(sdata))
    220		return ret;
    221
    222	trace_drv_get_tsf(local, sdata);
    223	if (local->ops->get_tsf)
    224		ret = local->ops->get_tsf(&local->hw, &sdata->vif);
    225	trace_drv_return_u64(local, ret);
    226	return ret;
    227}
    228
    229void drv_set_tsf(struct ieee80211_local *local,
    230		 struct ieee80211_sub_if_data *sdata,
    231		 u64 tsf)
    232{
    233	might_sleep();
    234
    235	if (!check_sdata_in_driver(sdata))
    236		return;
    237
    238	trace_drv_set_tsf(local, sdata, tsf);
    239	if (local->ops->set_tsf)
    240		local->ops->set_tsf(&local->hw, &sdata->vif, tsf);
    241	trace_drv_return_void(local);
    242}
    243
    244void drv_offset_tsf(struct ieee80211_local *local,
    245		    struct ieee80211_sub_if_data *sdata,
    246		    s64 offset)
    247{
    248	might_sleep();
    249
    250	if (!check_sdata_in_driver(sdata))
    251		return;
    252
    253	trace_drv_offset_tsf(local, sdata, offset);
    254	if (local->ops->offset_tsf)
    255		local->ops->offset_tsf(&local->hw, &sdata->vif, offset);
    256	trace_drv_return_void(local);
    257}
    258
    259void drv_reset_tsf(struct ieee80211_local *local,
    260		   struct ieee80211_sub_if_data *sdata)
    261{
    262	might_sleep();
    263
    264	if (!check_sdata_in_driver(sdata))
    265		return;
    266
    267	trace_drv_reset_tsf(local, sdata);
    268	if (local->ops->reset_tsf)
    269		local->ops->reset_tsf(&local->hw, &sdata->vif);
    270	trace_drv_return_void(local);
    271}
    272
    273int drv_switch_vif_chanctx(struct ieee80211_local *local,
    274			   struct ieee80211_vif_chanctx_switch *vifs,
    275			   int n_vifs, enum ieee80211_chanctx_switch_mode mode)
    276{
    277	int ret = 0;
    278	int i;
    279
    280	might_sleep();
    281
    282	if (!local->ops->switch_vif_chanctx)
    283		return -EOPNOTSUPP;
    284
    285	for (i = 0; i < n_vifs; i++) {
    286		struct ieee80211_chanctx *new_ctx =
    287			container_of(vifs[i].new_ctx,
    288				     struct ieee80211_chanctx,
    289				     conf);
    290		struct ieee80211_chanctx *old_ctx =
    291			container_of(vifs[i].old_ctx,
    292				     struct ieee80211_chanctx,
    293				     conf);
    294
    295		WARN_ON_ONCE(!old_ctx->driver_present);
    296		WARN_ON_ONCE((mode == CHANCTX_SWMODE_SWAP_CONTEXTS &&
    297			      new_ctx->driver_present) ||
    298			     (mode == CHANCTX_SWMODE_REASSIGN_VIF &&
    299			      !new_ctx->driver_present));
    300	}
    301
    302	trace_drv_switch_vif_chanctx(local, vifs, n_vifs, mode);
    303	ret = local->ops->switch_vif_chanctx(&local->hw,
    304					     vifs, n_vifs, mode);
    305	trace_drv_return_int(local, ret);
    306
    307	if (!ret && mode == CHANCTX_SWMODE_SWAP_CONTEXTS) {
    308		for (i = 0; i < n_vifs; i++) {
    309			struct ieee80211_chanctx *new_ctx =
    310				container_of(vifs[i].new_ctx,
    311					     struct ieee80211_chanctx,
    312					     conf);
    313			struct ieee80211_chanctx *old_ctx =
    314				container_of(vifs[i].old_ctx,
    315					     struct ieee80211_chanctx,
    316					     conf);
    317
    318			new_ctx->driver_present = true;
    319			old_ctx->driver_present = false;
    320		}
    321	}
    322
    323	return ret;
    324}
    325
    326int drv_ampdu_action(struct ieee80211_local *local,
    327		     struct ieee80211_sub_if_data *sdata,
    328		     struct ieee80211_ampdu_params *params)
    329{
    330	int ret = -EOPNOTSUPP;
    331
    332	might_sleep();
    333
    334	sdata = get_bss_sdata(sdata);
    335	if (!check_sdata_in_driver(sdata))
    336		return -EIO;
    337
    338	trace_drv_ampdu_action(local, sdata, params);
    339
    340	if (local->ops->ampdu_action)
    341		ret = local->ops->ampdu_action(&local->hw, &sdata->vif, params);
    342
    343	trace_drv_return_int(local, ret);
    344
    345	return ret;
    346}