net/ethtool/tsconfig.c

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

File Facts

System
Linux kernel
Corpus path
net/ethtool/tsconfig.c
Extension
.c
Size
11895 bytes
Lines
461
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: operation-table or driver-model contract
Status
pattern 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

const struct net_device_ops *ops = req_base->dev->netdev_ops;

	if (!ops->ndo_hwtstamp_set || !ops->ndo_hwtstamp_get)
		return -EOPNOTSUPP;

	return 1;
}

static struct hwtstamp_provider *
tsconfig_set_hwprov_from_desc(struct net_device *dev,
			      struct genl_info *info,
			      struct hwtstamp_provider_desc *hwprov_desc)
{
	struct kernel_ethtool_ts_info ts_info;
	struct hwtstamp_provider *hwprov;
	struct nlattr **tb = info->attrs;
	struct phy_device *phy = NULL;
	enum hwtstamp_source source;
	int ret;

	ret = ethtool_net_get_ts_info_by_phc(dev, &ts_info, hwprov_desc);
	if (!ret) {
		/* Found */
		source = HWTSTAMP_SOURCE_NETDEV;
	} else {
		phy = ethtool_phy_get_ts_info_by_phc(dev, &ts_info, hwprov_desc);
		if (IS_ERR(phy)) {
			if (PTR_ERR(phy) == -ENODEV)
				NL_SET_ERR_MSG_ATTR(info->extack,
						    tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER],
						    "phc not in this net device topology");
			return ERR_CAST(phy);
		}

		source = HWTSTAMP_SOURCE_PHYLIB;
	}

	hwprov = kzalloc_obj(*hwprov);
	if (!hwprov)
		return ERR_PTR(-ENOMEM);

	hwprov->desc.index = hwprov_desc->index;
	hwprov->desc.qualifier = hwprov_desc->qualifier;
	hwprov->source = source;
	hwprov->phydev = phy;

	return hwprov;
}

static int ethnl_set_tsconfig(struct ethnl_req_info *req_base,
			      struct genl_info *info)
{
	struct kernel_hwtstamp_config hwtst_config = {0};
	bool hwprov_mod = false, config_mod = false;
	struct hwtstamp_provider *hwprov = NULL;
	struct net_device *dev = req_base->dev;
	struct nlattr **tb = info->attrs;
	int ret;

	if (!netif_device_present(dev))
		return -ENODEV;

	if (tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER]) {
		struct hwtstamp_provider_desc __hwprov_desc = {.index = -1};
		struct hwtstamp_provider *__hwprov;

		__hwprov = netdev_ops_lock_dereference(dev->hwprov, dev);
		if (__hwprov) {
			__hwprov_desc.index = __hwprov->desc.index;
			__hwprov_desc.qualifier = __hwprov->desc.qualifier;
		}

		ret = ts_parse_hwtst_provider(tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER],
					      &__hwprov_desc, info->extack,
					      &hwprov_mod);
		if (ret < 0)
			return ret;

		if (hwprov_mod) {
			hwprov = tsconfig_set_hwprov_from_desc(dev, info,
							       &__hwprov_desc);
			if (IS_ERR(hwprov))
				return PTR_ERR(hwprov);
		}
	}

	/* Get current hwtstamp config if we are not changing the
	 * hwtstamp source. It will be zeroed in the other case.
	 */
	if (!hwprov_mod) {

Annotation

Implementation Notes