// SPDX-License-Identifier: GPL-2.0 #include "softmac_core.h" void rpu_vif_add(struct umac_vif *uvif) { unsigned int type; struct ieee80211_conf *conf = &uvif->priv->hw->conf; int ret = 0; RPU_DEBUG_VIF("%s-UMAC: Add VIF %d Type = %d\n", uvif->priv->name, uvif->vif_index, uvif->vif->type); uvif->config.atim_window = uvif->config.bcn_lost_cnt = uvif->config.aid = 0; uvif->noa_active = 0; spin_lock_bh_init(&uvif->noa_que_lock); switch (uvif->vif->type) { case NL80211_IFTYPE_STATION: type = IF_MODE_STA_BSS; skb_queue_head_init(&uvif->noa_que); break; case NL80211_IFTYPE_ADHOC: type = IF_MODE_STA_IBSS; init_beacon(uvif); break; case NL80211_IFTYPE_AP: type = IF_MODE_AP; init_beacon(uvif); break; default: WARN_ON(1); return; } CALL_RPU(rpu_prog_vif_ctrl, uvif->vif_index, uvif->vif->addr, type, IF_ADD); /* Reprogram retry counts */ CALL_RPU(rpu_prog_short_retry, uvif->vif_index, uvif->vif->addr, conf->short_frame_max_tx_count); CALL_RPU(rpu_prog_long_retry, uvif->vif_index, uvif->vif->addr, conf->long_frame_max_tx_count); if (uvif->vif->type == NL80211_IFTYPE_AP) { /* Program the EDCA params */ unsigned int queue; unsigned int aifs; unsigned int txop; unsigned int cwmin; unsigned int cwmax; unsigned int uapsd; for (queue = 0; queue < 4; queue++) { aifs = uvif->config.edca_params[queue].aifs; txop = uvif->config.edca_params[queue].txop; cwmin = uvif->config.edca_params[queue].cwmin; cwmax = uvif->config.edca_params[queue].cwmax; uapsd = uvif->config.edca_params[queue].uapsd; CALL_RPU(rpu_prog_txq_params, uvif->vif_index, uvif->vif->addr, queue, aifs, txop, cwmin, cwmax, uapsd); } } prog_rpu_fail: return; } void rpu_vif_remove(struct umac_vif *uvif) { struct sk_buff *skb; unsigned int type; int ret = 0; RPU_DEBUG_VIF("%s-UMAC: Remove VIF %d called\n", uvif->priv->name, uvif->vif_index); switch (uvif->vif->type) { case NL80211_IFTYPE_STATION: type = IF_MODE_STA_BSS; break; case NL80211_IFTYPE_ADHOC: type = IF_MODE_STA_IBSS; deinit_beacon(uvif); break; case NL80211_IFTYPE_AP: type = IF_MODE_AP; deinit_beacon(uvif); break; default: WARN_ON(1); return; } if (type == IF_MODE_STA_BSS) { spin_lock_bh(&uvif->noa_que_lock); while ((skb = __skb_dequeue(&uvif->noa_que))) dev_kfree_skb(skb); spin_unlock_bh(&uvif->noa_que_lock); } CALL_RPU(rpu_prog_vif_ctrl, uvif->vif_index, uvif->vif->addr, type, IF_REM); prog_rpu_fail: return; } void rpu_vif_set_edca_params(unsigned short queue, struct umac_vif *uvif, struct edca_params *params, unsigned int vif_active) { int ret = 0; switch (queue) { case 0: queue = 3; /* Voice */ break; case 1: queue = 2; /* Video */ break; case 2: queue = 1; /* Best effort */ break; case 3: queue = 0; /* Back groud */ break; } RPU_DEBUG_VIF("%s-UMAC:Set EDCA params for VIF %d,", uvif->priv ? uvif->priv->name : 0, uvif->vif_index); RPU_DEBUG_VIF(" Values: %d, %d, %d, %d, %d\n", queue, params->aifs, params->txop, params->cwmin, params->cwmax); if (uvif->priv->params->production_test == 0) { /* arbitration interframe space [0..255] */ uvif->config.edca_params[queue].aifs = params->aifs; /* maximum burst time in units of 32 usecs, 0 meaning disabled*/ uvif->config.edca_params[queue].txop = params->txop; /* minimum contention window in units of 2^n-1 */ uvif->config.edca_params[queue].cwmin = params->cwmin; /* maximum contention window in units of 2^n-1 */ uvif->config.edca_params[queue].cwmax = params->cwmax; uvif->config.edca_params[queue].uapsd = params->uapsd; } else { uvif->config.edca_params[queue].aifs = 3; uvif->config.edca_params[queue].txop = 0; uvif->config.edca_params[queue].cwmin = 0; uvif->config.edca_params[queue].cwmax = 0; uvif->config.edca_params[queue].uapsd = 0; } /* For the AP case, EDCA params are set before ADD interface is called. * Since this is not supported, we simply store the params and program * them to the LMAC after the interface is added */ if (!vif_active) return; /* Program the txq parameters into the LMAC */ CALL_RPU(rpu_prog_txq_params, uvif->vif_index, uvif->vif->addr, queue, params->aifs, params->txop, params->cwmin, params->cwmax, params->uapsd); prog_rpu_fail: return; } void rpu_vif_bss_info_changed(struct umac_vif *uvif, struct ieee80211_bss_conf *bss_conf, unsigned int changed) { unsigned int caps = 0; int center_freq = 0; int chan = 0; int ret = 0; RPU_DEBUG_VIF("%s-CORE: BSS INFO changed %d, %d, %d\n", uvif->priv->name, uvif->vif_index, uvif->vif->type, changed); if (changed & BSS_CHANGED_BSSID) { CALL_RPU(rpu_prog_vif_bssid, uvif->vif_index, uvif->vif->addr, (unsigned char *)bss_conf->bssid, bss_conf->mbssid); } if (changed & BSS_CHANGED_BASIC_RATES) { if (bss_conf->basic_rates) CALL_RPU(rpu_prog_vif_basic_rates, uvif->vif_index, uvif->vif->addr, bss_conf->basic_rates); else CALL_RPU(rpu_prog_vif_basic_rates, uvif->vif_index, uvif->vif->addr, 0x153); } if (changed & BSS_CHANGED_ERP_SLOT) { unsigned int queue = 0; unsigned int aifs = 0; unsigned int txop = 0; unsigned int cwmin = 0; unsigned int cwmax = 0; unsigned int uapsd = 0; CALL_RPU(rpu_prog_vif_short_slot, uvif->vif_index, uvif->vif->addr, bss_conf->use_short_slot); for (queue = 0; queue < LMAC_AC_MAX_CNT; queue++) { aifs = uvif->config.edca_params[queue].aifs; txop = uvif->config.edca_params[queue].txop; cwmin = uvif->config.edca_params[queue].cwmin; cwmax = uvif->config.edca_params[queue].cwmax; uapsd = uvif->config.edca_params[queue].uapsd; if (uvif->config.edca_params[queue].cwmin != 0) CALL_RPU(rpu_prog_txq_params, uvif->vif_index, uvif->vif->addr, queue, aifs, txop, cwmin, cwmax, uapsd); } } switch (uvif->vif->type) { case NL80211_IFTYPE_STATION: if (changed & BSS_CHANGED_ASSOC) { center_freq = bss_conf->chandef.chan->center_freq; chan = ieee80211_frequency_to_channel(center_freq); if (bss_conf->assoc) { RPU_DEBUG_VIF("%s-CORE: AID %d,", uvif->priv->name, bss_conf->aid); RPU_DEBUG_VIF(" CAPS 0x%04x\n", bss_conf->assoc_capability | (bss_conf->qos << 9)); CALL_RPU(rpu_prog_vif_conn_state, uvif->vif_index, uvif->vif->addr, STA_CONN); CALL_RPU(rpu_prog_vif_aid, uvif->vif_index, uvif->vif->addr, bss_conf->aid); CALL_RPU(rpu_prog_vif_op_channel, uvif->vif_index, uvif->vif->addr, chan); caps = (bss_conf->assoc_capability | (bss_conf->qos << 9)); CALL_RPU(rpu_prog_vif_assoc_cap, uvif->vif_index, uvif->vif->addr, caps); CALL_RPU(rpu_prog_srg, uvif, bss_conf->he_obss_pd, bss_conf->he_operation); CALL_RPU(rpu_prog_mac_params, uvif->vif_index, bss_conf); uvif->noa_active = 0; uvif->priv->params->is_associated = 1; } else { uvif->priv->params->is_associated = 0; CALL_RPU(rpu_prog_vif_conn_state, uvif->vif_index, uvif->vif->addr, STA_DISCONN); #ifdef BEACON_TIME_STAMP uvif->priv->params-> sync[uvif->vif_index].status = 0; #endif /* BEACON_TIME_STAMP */ } } if (changed & BSS_CHANGED_BEACON_INT) { CALL_RPU(rpu_prog_vif_beacon_int, uvif->vif_index, uvif->vif->addr, bss_conf->beacon_int); } if (changed & BSS_CHANGED_BEACON_INFO) { CALL_RPU(rpu_prog_vif_dtim_period, uvif->vif_index, uvif->vif->addr, bss_conf->dtim_period); } break; case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_AP: if ((changed & BSS_CHANGED_BEACON_ENABLED) || (changed & BSS_CHANGED_BEACON_INT)){ IMG_AP_DBG_PARAM_INCR(ap_bss_info_changed, 1); modify_beacon_params(uvif, bss_conf); } break; default: WARN_ON(1); return; } prog_rpu_fail: return; }