#include <sys/param.h>
#include <net/cfg80211.h>
#include "rs.h"
#include "mvm.h"
#ifdef CONFIG_IWLWIFI_DEBUGFS
void
iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)
{
uint8_t nss;
spin_lock_bh(&mvm->drv_stats_lock);
mvm->drv_rx_stats.success_frames++;
if (rate & RATE_MCS_HT_MSK_V1) {
mvm->drv_rx_stats.ht_frames++;
nss = 1 + ((rate & RATE_HT_MCS_NSS_MSK_V1) >> RATE_HT_MCS_NSS_POS_V1);
} else if (rate & RATE_MCS_VHT_MSK_V1) {
mvm->drv_rx_stats.vht_frames++;
nss = 1 + FIELD_GET(RATE_MCS_NSS_MSK, rate);
} else {
mvm->drv_rx_stats.legacy_frames++;
nss = 0;
}
switch (rate & RATE_MCS_CHAN_WIDTH_MSK_V1) {
case RATE_MCS_CHAN_WIDTH_20:
mvm->drv_rx_stats.bw_20_frames++;
break;
case RATE_MCS_CHAN_WIDTH_40:
mvm->drv_rx_stats.bw_40_frames++;
break;
case RATE_MCS_CHAN_WIDTH_80:
mvm->drv_rx_stats.bw_80_frames++;
break;
case RATE_MCS_CHAN_WIDTH_160:
mvm->drv_rx_stats.bw_160_frames++;
break;
}
if ((rate & RATE_MCS_CCK_MSK_V1) == 0 &&
(rate & RATE_MCS_SGI_MSK_V1) != 0)
mvm->drv_rx_stats.sgi_frames++;
else
mvm->drv_rx_stats.ngi_frames++;
switch (nss) {
case 1:
mvm->drv_rx_stats.siso_frames++;
break;
case 2:
mvm->drv_rx_stats.mimo2_frames++;
break;
}
if (agg)
mvm->drv_rx_stats.agg_frames++;
mvm->drv_rx_stats.last_rates[mvm->drv_rx_stats.last_frame_idx] = rate;
mvm->drv_rx_stats.last_frame_idx++;
mvm->drv_rx_stats.last_frame_idx %=
ARRAY_SIZE(mvm->drv_rx_stats.last_rates);
spin_unlock_bh(&mvm->drv_stats_lock);
}
void
iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm)
{
spin_lock_bh(&mvm->drv_stats_lock);
memset(&mvm->drv_rx_stats, 0, sizeof(mvm->drv_rx_stats));
spin_unlock_bh(&mvm->drv_stats_lock);
}
#endif
int
iwl_mvm_rate_control_register(void)
{
TODO("This likely has to call into net80211 unless we gain compat code in LinuxKPI");
return (0);
}
void
iwl_mvm_rate_control_unregister(void)
{
TODO("This likely has to call into net80211 unless we gain compat code in LinuxKPI");
}
int
iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, bool enable)
{
if (iwl_mvm_has_tlc_offload(mvm))
return (rs_fw_tx_protection(mvm, mvmsta, enable));
else {
TODO();
return (0);
}
}
static void
iwl_mvm_rs_sw_rate_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_bss_conf *link_conf, struct ieee80211_link_sta *link_sta,
enum nl80211_band band)
{
TODO();
}
void
iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_bss_conf *link_conf, struct ieee80211_link_sta *link_sta,
enum nl80211_band band)
{
if (iwl_mvm_has_tlc_offload(mvm))
iwl_mvm_rs_fw_rate_init(mvm, vif, sta, link_conf, link_sta, band);
else
iwl_mvm_rs_sw_rate_init(mvm, vif, sta, link_conf, link_sta, band);
}
void
iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, int tid,
struct ieee80211_tx_info *ba_info, bool t)
{
TODO();
}
void
rs_update_last_rssi(struct iwl_mvm *mvm __unused, struct iwl_mvm_sta *mvmsta,
struct ieee80211_rx_status *rx_status)
{
struct iwl_lq_sta *lq_sta;
int i;
if (mvmsta == NULL || rx_status == NULL)
return;
lq_sta = &mvmsta->deflink.lq_sta.rs_drv;
lq_sta->pers.last_rssi = S8_MIN;
lq_sta->pers.chains = rx_status->chains;
for (i = 0; i < nitems(lq_sta->pers.chain_signal); i++) {
if ((rx_status->chains & BIT(i)) == 0)
continue;
lq_sta->pers.chain_signal[i] = rx_status->chain_signal[i];
if (rx_status->chain_signal[i] > lq_sta->pers.last_rssi)
lq_sta->pers.last_rssi = rx_status->chain_signal[i];
}
}
int
rs_pretty_print_rate_v1(char *buf, int bufsz, const u32 rate)
{
TODO();
return (0);
}