net/ethtool/mse.c

Source file repositories/reference/linux-study-clean/net/ethtool/mse.c

File Facts

System
Linux kernel
Corpus path
net/ethtool/mse.c
Extension
.c
Size
8313 bytes
Lines
329
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mse_req_info {
	struct ethnl_req_info base;
};

struct mse_snapshot_entry {
	struct phy_mse_snapshot snapshot;
	int channel;
};

struct mse_reply_data {
	struct ethnl_reply_data base;
	struct phy_mse_capability capability;
	struct mse_snapshot_entry *snapshots;
	unsigned int num_snapshots;
};

static struct mse_reply_data *
mse_repdata(const struct ethnl_reply_data *reply_base)
{
	return container_of(reply_base, struct mse_reply_data, base);
}

const struct nla_policy ethnl_mse_get_policy[] = {
	[ETHTOOL_A_MSE_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy_phy),
};

static int get_snapshot_if_supported(struct phy_device *phydev,
				     struct mse_reply_data *data,
				     unsigned int *idx, u32 cap_bit,
				     enum phy_mse_channel channel)
{
	int ret;

	if (data->capability.supported_caps & cap_bit) {
		ret = phydev->drv->get_mse_snapshot(phydev, channel,
					&data->snapshots[*idx].snapshot);
		if (ret)
			return ret;
		data->snapshots[*idx].channel = channel;
		(*idx)++;
	}

	return 0;
}

static int mse_get_channels(struct phy_device *phydev,
			    struct mse_reply_data *data)
{
	unsigned int i = 0;
	int ret;

	if (!data->capability.supported_caps)
		return 0;

	data->snapshots = kzalloc_objs(*data->snapshots, PHY_MSE_CHANNEL_COUNT);
	if (!data->snapshots)
		return -ENOMEM;

	/* Priority 1: Individual channels */
	ret = get_snapshot_if_supported(phydev, data, &i, PHY_MSE_CAP_CHANNEL_A,
					PHY_MSE_CHANNEL_A);
	if (ret)
		return ret;
	ret = get_snapshot_if_supported(phydev, data, &i, PHY_MSE_CAP_CHANNEL_B,
					PHY_MSE_CHANNEL_B);
	if (ret)
		return ret;
	ret = get_snapshot_if_supported(phydev, data, &i, PHY_MSE_CAP_CHANNEL_C,
					PHY_MSE_CHANNEL_C);
	if (ret)
		return ret;
	ret = get_snapshot_if_supported(phydev, data, &i, PHY_MSE_CAP_CHANNEL_D,
					PHY_MSE_CHANNEL_D);
	if (ret)
		return ret;

	/* If any individual channels were found, we are done. */
	if (i > 0) {
		data->num_snapshots = i;
		return 0;
	}

	/* Priority 2: Worst channel, if no individual channels supported. */
	ret = get_snapshot_if_supported(phydev, data, &i,
					PHY_MSE_CAP_WORST_CHANNEL,
					PHY_MSE_CHANNEL_WORST);
	if (ret)
		return ret;

	/* If worst channel was found, we are done. */

Annotation

Implementation Notes