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

binding.c (3945B)


      1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
      2/*
      3 * Copyright (C) 2012-2014, 2020 Intel Corporation
      4 * Copyright (C) 2016 Intel Deutschland GmbH
      5 */
      6#include <net/mac80211.h>
      7#include "fw-api.h"
      8#include "mvm.h"
      9
     10struct iwl_mvm_iface_iterator_data {
     11	struct ieee80211_vif *ignore_vif;
     12	int idx;
     13
     14	struct iwl_mvm_phy_ctxt *phyctxt;
     15
     16	u16 ids[MAX_MACS_IN_BINDING];
     17	u16 colors[MAX_MACS_IN_BINDING];
     18};
     19
     20static int iwl_mvm_binding_cmd(struct iwl_mvm *mvm, u32 action,
     21			       struct iwl_mvm_iface_iterator_data *data)
     22{
     23	struct iwl_binding_cmd cmd;
     24	struct iwl_mvm_phy_ctxt *phyctxt = data->phyctxt;
     25	int i, ret;
     26	u32 status;
     27	int size;
     28
     29	memset(&cmd, 0, sizeof(cmd));
     30
     31	if (fw_has_capa(&mvm->fw->ucode_capa,
     32			IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT)) {
     33		size = sizeof(cmd);
     34		cmd.lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm->fw,
     35							      phyctxt->channel->band));
     36	} else {
     37		size = IWL_BINDING_CMD_SIZE_V1;
     38	}
     39
     40	cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(phyctxt->id,
     41							   phyctxt->color));
     42	cmd.action = cpu_to_le32(action);
     43	cmd.phy = cpu_to_le32(FW_CMD_ID_AND_COLOR(phyctxt->id,
     44						  phyctxt->color));
     45
     46	for (i = 0; i < MAX_MACS_IN_BINDING; i++)
     47		cmd.macs[i] = cpu_to_le32(FW_CTXT_INVALID);
     48	for (i = 0; i < data->idx; i++)
     49		cmd.macs[i] = cpu_to_le32(FW_CMD_ID_AND_COLOR(data->ids[i],
     50							      data->colors[i]));
     51
     52	status = 0;
     53	ret = iwl_mvm_send_cmd_pdu_status(mvm, BINDING_CONTEXT_CMD,
     54					  size, &cmd, &status);
     55	if (ret) {
     56		IWL_ERR(mvm, "Failed to send binding (action:%d): %d\n",
     57			action, ret);
     58		return ret;
     59	}
     60
     61	if (status) {
     62		IWL_ERR(mvm, "Binding command failed: %u\n", status);
     63		ret = -EIO;
     64	}
     65
     66	return ret;
     67}
     68
     69static void iwl_mvm_iface_iterator(void *_data, u8 *mac,
     70				   struct ieee80211_vif *vif)
     71{
     72	struct iwl_mvm_iface_iterator_data *data = _data;
     73	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
     74
     75	if (vif == data->ignore_vif)
     76		return;
     77
     78	if (mvmvif->phy_ctxt != data->phyctxt)
     79		return;
     80
     81	if (WARN_ON_ONCE(data->idx >= MAX_MACS_IN_BINDING))
     82		return;
     83
     84	data->ids[data->idx] = mvmvif->id;
     85	data->colors[data->idx] = mvmvif->color;
     86	data->idx++;
     87}
     88
     89static int iwl_mvm_binding_update(struct iwl_mvm *mvm,
     90				  struct ieee80211_vif *vif,
     91				  struct iwl_mvm_phy_ctxt *phyctxt,
     92				  bool add)
     93{
     94	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
     95	struct iwl_mvm_iface_iterator_data data = {
     96		.ignore_vif = vif,
     97		.phyctxt = phyctxt,
     98	};
     99	u32 action = FW_CTXT_ACTION_MODIFY;
    100
    101	lockdep_assert_held(&mvm->mutex);
    102
    103	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
    104						   IEEE80211_IFACE_ITER_NORMAL,
    105						   iwl_mvm_iface_iterator,
    106						   &data);
    107
    108	/*
    109	 * If there are no other interfaces yet we
    110	 * need to create a new binding.
    111	 */
    112	if (data.idx == 0) {
    113		if (add)
    114			action = FW_CTXT_ACTION_ADD;
    115		else
    116			action = FW_CTXT_ACTION_REMOVE;
    117	}
    118
    119	if (add) {
    120		if (WARN_ON_ONCE(data.idx >= MAX_MACS_IN_BINDING))
    121			return -EINVAL;
    122
    123		data.ids[data.idx] = mvmvif->id;
    124		data.colors[data.idx] = mvmvif->color;
    125		data.idx++;
    126	}
    127
    128	return iwl_mvm_binding_cmd(mvm, action, &data);
    129}
    130
    131int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
    132{
    133	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    134
    135	if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
    136		return -EINVAL;
    137
    138	/*
    139	 * Update SF - Disable if needed. if this fails, SF might still be on
    140	 * while many macs are bound, which is forbidden - so fail the binding.
    141	 */
    142	if (iwl_mvm_sf_update(mvm, vif, false))
    143		return -EINVAL;
    144
    145	return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, true);
    146}
    147
    148int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
    149{
    150	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
    151	int ret;
    152
    153	if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
    154		return -EINVAL;
    155
    156	ret = iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, false);
    157
    158	if (!ret)
    159		if (iwl_mvm_sf_update(mvm, vif, true))
    160			IWL_ERR(mvm, "Failed to update SF state\n");
    161
    162	return ret;
    163}