// SPDX-License-Identifier: GPL-2.0-only

#include "netlink.h"
#include "common.h"
#include "bitset.h"

struct eee_req_info {
	struct ethnl_req_info		base;
};

struct eee_reply_data {
	struct ethnl_reply_data		base;
	struct ethtool_keee		eee;
};

#define EEE_REPDATA(__reply_base) \
	container_of(__reply_base, struct eee_reply_data, base)

const struct nla_policy ethnl_eee_get_policy[] = {
	[ETHTOOL_A_EEE_HEADER]		=
		NLA_POLICY_NESTED(ethnl_header_policy),
};

static int eee_prepare_data(const struct ethnl_req_info *req_base,
			    struct ethnl_reply_data *reply_base,
			    const struct genl_info *info)
{
	struct eee_reply_data *data = EEE_REPDATA(reply_base);
	struct net_device *dev = reply_base->dev;
	struct ethtool_keee *eee = &data->eee;
	int ret;

	if (!dev->ethtool_ops->get_eee)
		return -EOPNOTSUPP;
	ret = ethnl_ops_begin(dev);
	if (ret < 0)
		return ret;
	ret = dev->ethtool_ops->get_eee(dev, eee);
	ethnl_ops_complete(dev);

	return ret;
}

static int eee_reply_size(const struct ethnl_req_info *req_base,
			  const struct ethnl_reply_data *reply_base)
{
	bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
	const struct eee_reply_data *data = EEE_REPDATA(reply_base);
	const struct ethtool_keee *eee = &data->eee;
	int len = 0;
	int ret;

	/* MODES_OURS */
	ret = ethnl_bitset_size(eee->advertised, eee->supported,
				__ETHTOOL_LINK_MODE_MASK_NBITS,
				link_mode_names, compact);
	if (ret < 0)
		return ret;
	len += ret;
	/* MODES_PEERS */
	ret = ethnl_bitset_size(eee->lp_advertised, NULL,
				__ETHTOOL_LINK_MODE_MASK_NBITS,
				link_mode_names, compact);
	if (ret < 0)
		return ret;
	len += ret;

	len += nla_total_size(sizeof(u8)) +	/* _EEE_ACTIVE */
	       nla_total_size(sizeof(u8)) +	/* _EEE_ENABLED */
	       nla_total_size(sizeof(u8)) +	/* _EEE_TX_LPI_ENABLED */
	       nla_total_size(sizeof(u32));	/* _EEE_TX_LPI_TIMER */

	return len;
}

static int eee_fill_reply(struct sk_buff *skb,
			  const struct ethnl_req_info *req_base,
			  const struct ethnl_reply_data *reply_base)
{
	bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
	const struct eee_reply_data *data = EEE_REPDATA(reply_base);
	const struct ethtool_keee *eee = &data->eee;
	int ret;

	ret = ethnl_put_bitset(skb, ETHTOOL_A_EEE_MODES_OURS,
			       eee->advertised, eee->supported,
			       __ETHTOOL_LINK_MODE_MASK_NBITS,
			       link_mode_names, compact);
	if (ret < 0)
		return ret;
	ret = ethnl_put_bitset(skb, ETHTOOL_A_EEE_MODES_PEER,
			       eee->lp_advertised, NULL,
			       __ETHTOOL_LINK_MODE_MASK_NBITS,
			       link_mode_names, compact);
	if (ret < 0)
		return ret;

	if (nla_put_u8(skb, ETHTOOL_A_EEE_ACTIVE, eee->eee_active) ||
	    nla_put_u8(skb, ETHTOOL_A_EEE_ENABLED, eee->eee_enabled) ||
	    nla_put_u8(skb, ETHTOOL_A_EEE_TX_LPI_ENABLED,
		       eee->tx_lpi_enabled) ||
	    nla_put_u32(skb, ETHTOOL_A_EEE_TX_LPI_TIMER, eee->tx_lpi_timer))
		return -EMSGSIZE;

	return 0;
}

/* EEE_SET */

const struct nla_policy ethnl_eee_set_policy[] = {
	[ETHTOOL_A_EEE_HEADER]		=
		NLA_POLICY_NESTED(ethnl_header_policy),
	[ETHTOOL_A_EEE_MODES_OURS]	= { .type = NLA_NESTED },
	[ETHTOOL_A_EEE_ENABLED]		= { .type = NLA_U8 },
	[ETHTOOL_A_EEE_TX_LPI_ENABLED]	= { .type = NLA_U8 },
	[ETHTOOL_A_EEE_TX_LPI_TIMER]	= { .type = NLA_U32 },
};

static int
ethnl_set_eee_validate(struct ethnl_req_info *req_info, struct genl_info *info)
{
	const struct ethtool_ops *ops = req_info->dev->ethtool_ops;

	return ops->get_eee && ops->set_eee ? 1 : -EOPNOTSUPP;
}

static int
ethnl_set_eee(struct ethnl_req_info *req_info, struct genl_info *info)
{
	struct net_device *dev = req_info->dev;
	struct nlattr **tb = info->attrs;
	struct ethtool_keee eee = {};
	bool mod = false;
	int ret;

	ret = dev->ethtool_ops->get_eee(dev, &eee);
	if (ret < 0)
		return ret;

	ret = ethnl_update_bitset(eee.advertised,
				  __ETHTOOL_LINK_MODE_MASK_NBITS,
				  tb[ETHTOOL_A_EEE_MODES_OURS],
				  link_mode_names, info->extack, &mod);
	if (ret < 0)
		return ret;
	ethnl_update_bool(&eee.eee_enabled, tb[ETHTOOL_A_EEE_ENABLED], &mod);
	ethnl_update_bool(&eee.tx_lpi_enabled, tb[ETHTOOL_A_EEE_TX_LPI_ENABLED],
			  &mod);
	ethnl_update_u32(&eee.tx_lpi_timer, tb[ETHTOOL_A_EEE_TX_LPI_TIMER],
			 &mod);
	if (!mod)
		return 0;

	ret = dev->ethtool_ops->set_eee(dev, &eee);
	return ret < 0 ? ret : 1;
}

const struct ethnl_request_ops ethnl_eee_request_ops = {
	.request_cmd		= ETHTOOL_MSG_EEE_GET,
	.reply_cmd		= ETHTOOL_MSG_EEE_GET_REPLY,
	.hdr_attr		= ETHTOOL_A_EEE_HEADER,
	.req_info_size		= sizeof(struct eee_req_info),
	.reply_data_size	= sizeof(struct eee_reply_data),

	.prepare_data		= eee_prepare_data,
	.reply_size		= eee_reply_size,
	.fill_reply		= eee_fill_reply,

	.set_validate		= ethnl_set_eee_validate,
	.set			= ethnl_set_eee,
	.set_ntf_cmd		= ETHTOOL_MSG_EEE_NTF,
};
