// SPDX-License-Identifier: GPL-2.0-only
/*
 * mac80211 ethtool hooks for cfg80211
 *
 * Copied from cfg.c - originally
 * Copyright 2006-2010	Johannes Berg <johannes@sipsolutions.net>
 * Copyright 2014	Intel Corporation (Author: Johannes Berg)
 * Copyright (C) 2018, 2022 Intel Corporation
 */
#include <linux/types.h>
#include <net/cfg80211.h>
#include "ieee80211_i.h"
#include "sta_info.h"
#include "driver-ops.h"

static int ieee80211_set_ringparam(struct net_device *dev,
				   struct ethtool_ringparam *rp,
				   struct kernel_ethtool_ringparam *kernel_rp,
				   struct netlink_ext_ack *extack)
{
	struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy);

	if (rp->rx_mini_pending != 0 || rp->rx_jumbo_pending != 0)
		return -EINVAL;

	return drv_set_ringparam(local, rp->tx_pending, rp->rx_pending);
}

static void ieee80211_get_ringparam(struct net_device *dev,
				    struct ethtool_ringparam *rp,
				    struct kernel_ethtool_ringparam *kernel_rp,
				    struct netlink_ext_ack *extack)
{
	struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy);

	memset(rp, 0, sizeof(*rp));

	drv_get_ringparam(local, &rp->tx_pending, &rp->tx_max_pending,
			  &rp->rx_pending, &rp->rx_max_pending);
}

static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
	"rx_packets", "rx_bytes",
	"rx_duplicates", "rx_fragments", "rx_dropped",
	"tx_packets", "tx_bytes",
	"tx_filtered", "tx_retry_failed", "tx_retries",
	"sta_state", "txrate", "rxrate", "signal",
	"channel", "noise", "ch_time", "ch_time_busy",
	"ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
};
#define STA_STATS_LEN	ARRAY_SIZE(ieee80211_gstrings_sta_stats)

static int ieee80211_get_sset_count(struct net_device *dev, int sset)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	int rv = 0;

	if (sset == ETH_SS_STATS)
		rv += STA_STATS_LEN;

	rv += drv_get_et_sset_count(sdata, sset);

	if (rv == 0)
		return -EOPNOTSUPP;
	return rv;
}

static void ieee80211_get_stats(struct net_device *dev,
				struct ethtool_stats *stats,
				u64 *data)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_chanctx_conf *chanctx_conf;
	struct ieee80211_channel *channel;
	struct sta_info *sta;
	struct ieee80211_local *local = sdata->local;
	struct station_info sinfo;
	struct survey_info survey;
	int i, q;
#define STA_STATS_SURVEY_LEN 7

	memset(data, 0, sizeof(u64) * STA_STATS_LEN);

#define ADD_STA_STATS(sta)					\
	do {							\
		data[i++] += sinfo.rx_packets;			\
		data[i++] += sinfo.rx_bytes;			\
		data[i++] += (sta)->rx_stats.num_duplicates;	\
		data[i++] += (sta)->rx_stats.fragments;		\
		data[i++] += sinfo.rx_dropped_misc;		\
								\
		data[i++] += sinfo.tx_packets;			\
		data[i++] += sinfo.tx_bytes;			\
		data[i++] += (sta)->status_stats.filtered;	\
		data[i++] += sinfo.tx_failed;			\
		data[i++] += sinfo.tx_retries;			\
	} while (0)

	/* For Managed stations, find the single station based on BSSID
	 * and use that.  For interface types, iterate through all available
	 * stations and add stats for any station that is assigned to this
	 * network device.
	 */

	mutex_lock(&local->sta_mtx);

	if (sdata->vif.type == NL80211_IFTYPE_STATION) {
		sta = sta_info_get_bss(sdata, sdata->deflink.u.mgd.bssid);

		if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
			goto do_survey;

		memset(&sinfo, 0, sizeof(sinfo));
		sta_set_sinfo(sta, &sinfo, false);

		i = 0;
		ADD_STA_STATS(&sta->deflink);

		data[i++] = sta->sta_state;


		if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE))
			data[i] = 100000ULL *
				cfg80211_calculate_bitrate(&sinfo.txrate);
		i++;
		if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE))
			data[i] = 100000ULL *
				cfg80211_calculate_bitrate(&sinfo.rxrate);
		i++;

		if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG))
			data[i] = (u8)sinfo.signal_avg;
		i++;
	} else {
		list_for_each_entry(sta, &local->sta_list, list) {
			/* Make sure this station belongs to the proper dev */
			if (sta->sdata->dev != dev)
				continue;

			memset(&sinfo, 0, sizeof(sinfo));
			sta_set_sinfo(sta, &sinfo, false);
			i = 0;
			ADD_STA_STATS(&sta->deflink);
		}
	}

do_survey:
	i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
	/* Get survey stats for current channel */
	survey.filled = 0;

	rcu_read_lock();
	chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
	if (chanctx_conf)
		channel = chanctx_conf->def.chan;
	else
		channel = NULL;
	rcu_read_unlock();

	if (channel) {
		q = 0;
		do {
			survey.filled = 0;
			if (drv_get_survey(local, q, &survey) != 0) {
				survey.filled = 0;
				break;
			}
			q++;
		} while (channel != survey.channel);
	}

	if (survey.filled)
		data[i++] = survey.channel->center_freq;
	else
		data[i++] = 0;
	if (survey.filled & SURVEY_INFO_NOISE_DBM)
		data[i++] = (u8)survey.noise;
	else
		data[i++] = -1LL;
	if (survey.filled & SURVEY_INFO_TIME)
		data[i++] = survey.time;
	else
		data[i++] = -1LL;
	if (survey.filled & SURVEY_INFO_TIME_BUSY)
		data[i++] = survey.time_busy;
	else
		data[i++] = -1LL;
	if (survey.filled & SURVEY_INFO_TIME_EXT_BUSY)
		data[i++] = survey.time_ext_busy;
	else
		data[i++] = -1LL;
	if (survey.filled & SURVEY_INFO_TIME_RX)
		data[i++] = survey.time_rx;
	else
		data[i++] = -1LL;
	if (survey.filled & SURVEY_INFO_TIME_TX)
		data[i++] = survey.time_tx;
	else
		data[i++] = -1LL;

	mutex_unlock(&local->sta_mtx);

	if (WARN_ON(i != STA_STATS_LEN))
		return;

	drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
}

static void ieee80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	int sz_sta_stats = 0;

	if (sset == ETH_SS_STATS) {
		sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
		memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats);
	}
	drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));
}

static int ieee80211_get_regs_len(struct net_device *dev)
{
	return 0;
}

static void ieee80211_get_regs(struct net_device *dev,
			       struct ethtool_regs *regs,
			       void *data)
{
	struct wireless_dev *wdev = dev->ieee80211_ptr;

	regs->version = wdev->wiphy->hw_version;
	regs->len = 0;
}

const struct ethtool_ops ieee80211_ethtool_ops = {
	.get_drvinfo = cfg80211_get_drvinfo,
	.get_regs_len = ieee80211_get_regs_len,
	.get_regs = ieee80211_get_regs,
	.get_link = ethtool_op_get_link,
	.get_ringparam = ieee80211_get_ringparam,
	.set_ringparam = ieee80211_set_ringparam,
	.get_strings = ieee80211_get_strings,
	.get_ethtool_stats = ieee80211_get_stats,
	.get_sset_count = ieee80211_get_sset_count,
};
