Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 315c28d2 authored by Arthur Kiyanovski's avatar Arthur Kiyanovski Committed by David S. Miller
Browse files

net: ena: ethtool: add extra properties retrieval via get_priv_flags



This commit adds a mechanism for exposing different device
properties via ethtool's priv_flags. The strings are provided
by the device and copied to user space through the driver.

In this commit we:

Add commands, structs and defines necessary for handling
extra properties

Add functions for:
Allocation/destruction of a buffer for extra properties strings.
Retreival of extra properties strings and flags from the network device.

Handle the allocation of a buffer for extra properties strings.

* Initialize buffer with extra properties strings from the
  network device at driver startup.

Use ethtool's get_priv_flags to expose extra properties of
the ENA device

Signed-off-by: default avatarArthur Kiyanovski <akiyano@amazon.com>
Signed-off-by: default avatarSameeh Jubran <sameehj@amazon.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 05d62ca2
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@
#ifndef _ENA_ADMIN_H_
#define _ENA_ADMIN_H_

#define ENA_ADMIN_EXTRA_PROPERTIES_STRING_LEN 32
#define ENA_ADMIN_EXTRA_PROPERTIES_COUNT     32

enum ena_admin_aq_opcode {
	ENA_ADMIN_CREATE_SQ                         = 1,
@@ -60,6 +62,8 @@ enum ena_admin_aq_feature_id {
	ENA_ADMIN_MAX_QUEUES_NUM                    = 2,
	ENA_ADMIN_HW_HINTS                          = 3,
	ENA_ADMIN_LLQ                               = 4,
	ENA_ADMIN_EXTRA_PROPERTIES_STRINGS          = 5,
	ENA_ADMIN_EXTRA_PROPERTIES_FLAGS            = 6,
	ENA_ADMIN_RSS_HASH_FUNCTION                 = 10,
	ENA_ADMIN_STATELESS_OFFLOAD_CONFIG          = 11,
	ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG      = 12,
@@ -560,6 +564,14 @@ struct ena_admin_set_feature_mtu_desc {
	u32 mtu;
};

struct ena_admin_get_extra_properties_strings_desc {
	u32 count;
};

struct ena_admin_get_extra_properties_flags_desc {
	u32 flags;
};

struct ena_admin_set_feature_host_attr_desc {
	/* host OS info base address in OS memory. host info is 4KB of
	 * physically contiguous
@@ -864,6 +876,10 @@ struct ena_admin_get_feat_resp {
		struct ena_admin_feature_intr_moder_desc intr_moderation;

		struct ena_admin_ena_hw_hints hw_hints;

		struct ena_admin_get_extra_properties_strings_desc extra_properties_strings;

		struct ena_admin_get_extra_properties_flags_desc extra_properties_flags;
	} u;
};

+56 −0
Original line number Diff line number Diff line
@@ -1877,6 +1877,62 @@ int ena_com_get_link_params(struct ena_com_dev *ena_dev,
	return ena_com_get_feature(ena_dev, resp, ENA_ADMIN_LINK_CONFIG);
}

int ena_com_extra_properties_strings_init(struct ena_com_dev *ena_dev)
{
	struct ena_admin_get_feat_resp resp;
	struct ena_extra_properties_strings *extra_properties_strings =
			&ena_dev->extra_properties_strings;
	u32 rc;

	extra_properties_strings->size = ENA_ADMIN_EXTRA_PROPERTIES_COUNT *
		ENA_ADMIN_EXTRA_PROPERTIES_STRING_LEN;

	extra_properties_strings->virt_addr =
		dma_alloc_coherent(ena_dev->dmadev,
				   extra_properties_strings->size,
				   &extra_properties_strings->dma_addr,
				   GFP_KERNEL);
	if (unlikely(!extra_properties_strings->virt_addr)) {
		pr_err("Failed to allocate extra properties strings\n");
		return 0;
	}

	rc = ena_com_get_feature_ex(ena_dev, &resp,
				    ENA_ADMIN_EXTRA_PROPERTIES_STRINGS,
				    extra_properties_strings->dma_addr,
				    extra_properties_strings->size);
	if (rc) {
		pr_debug("Failed to get extra properties strings\n");
		goto err;
	}

	return resp.u.extra_properties_strings.count;
err:
	ena_com_delete_extra_properties_strings(ena_dev);
	return 0;
}

void ena_com_delete_extra_properties_strings(struct ena_com_dev *ena_dev)
{
	struct ena_extra_properties_strings *extra_properties_strings =
				&ena_dev->extra_properties_strings;

	if (extra_properties_strings->virt_addr) {
		dma_free_coherent(ena_dev->dmadev,
				  extra_properties_strings->size,
				  extra_properties_strings->virt_addr,
				  extra_properties_strings->dma_addr);
		extra_properties_strings->virt_addr = NULL;
	}
}

int ena_com_get_extra_properties_flags(struct ena_com_dev *ena_dev,
				       struct ena_admin_get_feat_resp *resp)
{
	return ena_com_get_feature(ena_dev, resp,
				   ENA_ADMIN_EXTRA_PROPERTIES_FLAGS);
}

int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev,
			      struct ena_com_dev_get_features_ctx *get_feat_ctx)
{
+32 −0
Original line number Diff line number Diff line
@@ -347,6 +347,12 @@ struct ena_host_attribute {
	dma_addr_t host_info_dma_addr;
};

struct ena_extra_properties_strings {
	u8 *virt_addr;
	dma_addr_t dma_addr;
	u32 size;
};

/* Each ena_dev is a PCI function. */
struct ena_com_dev {
	struct ena_com_admin_queue admin_queue;
@@ -375,6 +381,7 @@ struct ena_com_dev {
	struct ena_intr_moder_entry *intr_moder_tbl;

	struct ena_com_llq_info llq_info;
	struct ena_extra_properties_strings extra_properties_strings;
};

struct ena_com_dev_get_features_ctx {
@@ -596,6 +603,31 @@ int ena_com_validate_version(struct ena_com_dev *ena_dev);
int ena_com_get_link_params(struct ena_com_dev *ena_dev,
			    struct ena_admin_get_feat_resp *resp);

/* ena_com_extra_properties_strings_init - Initialize the extra properties strings buffer.
 * @ena_dev: ENA communication layer struct
 *
 * Initialize the extra properties strings buffer.
 */
int ena_com_extra_properties_strings_init(struct ena_com_dev *ena_dev);

/* ena_com_delete_extra_properties_strings - Free the extra properties strings buffer.
 * @ena_dev: ENA communication layer struct
 *
 * Free the allocated extra properties strings buffer.
 */
void ena_com_delete_extra_properties_strings(struct ena_com_dev *ena_dev);

/* ena_com_get_extra_properties_flags - Retrieve extra properties flags.
 * @ena_dev: ENA communication layer struct
 * @resp: Extra properties flags.
 *
 * Retrieve the extra properties flags.
 *
 * @return - 0 on Success negative value otherwise.
 */
int ena_com_get_extra_properties_flags(struct ena_com_dev *ena_dev,
				       struct ena_admin_get_feat_resp *resp);

/* ena_com_get_dma_width - Retrieve physical dma address width the device
 * supports.
 * @ena_dev: ENA communication layer struct
+64 −11
Original line number Diff line number Diff line
@@ -197,15 +197,24 @@ static void ena_get_ethtool_stats(struct net_device *netdev,
	ena_dev_admin_queue_stats(adapter, &data);
}

static int get_stats_sset_count(struct ena_adapter *adapter)
{
	return  adapter->num_queues * (ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_RX)
		+ ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENA_COM;
}

int ena_get_sset_count(struct net_device *netdev, int sset)
{
	struct ena_adapter *adapter = netdev_priv(netdev);

	if (sset != ETH_SS_STATS)
	switch (sset) {
	case ETH_SS_STATS:
		return get_stats_sset_count(adapter);
	case ETH_SS_PRIV_FLAGS:
		return adapter->ena_extra_properties_count;
	default:
		return -EOPNOTSUPP;

	return  adapter->num_queues * (ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_RX)
		+ ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENA_COM;
	}
}

static void ena_queue_strings(struct ena_adapter *adapter, u8 **data)
@@ -247,26 +256,54 @@ static void ena_com_dev_strings(u8 **data)
	}
}

static void ena_get_strings(struct net_device *netdev, u32 sset, u8 *data)
static void get_stats_strings(struct ena_adapter *adapter, u8 *data)
{
	struct ena_adapter *adapter = netdev_priv(netdev);
	const struct ena_stats *ena_stats;
	int i;

	if (sset != ETH_SS_STATS)
		return;

	for (i = 0; i < ENA_STATS_ARRAY_GLOBAL; i++) {
		ena_stats = &ena_stats_global_strings[i];

		memcpy(data, ena_stats->name, ETH_GSTRING_LEN);
		data += ETH_GSTRING_LEN;
	}

	ena_queue_strings(adapter, &data);
	ena_com_dev_strings(&data);
}

static void get_private_flags_strings(struct ena_adapter *adapter, u8 *data)
{
	struct ena_com_dev *ena_dev = adapter->ena_dev;
	u8 *strings = ena_dev->extra_properties_strings.virt_addr;
	int i;

	if (unlikely(!strings)) {
		adapter->ena_extra_properties_count = 0;
		return;
	}

	for (i = 0; i < adapter->ena_extra_properties_count; i++) {
		strlcpy(data, strings + ENA_ADMIN_EXTRA_PROPERTIES_STRING_LEN * i,
			ETH_GSTRING_LEN);
		data += ETH_GSTRING_LEN;
	}
}

static void ena_get_strings(struct net_device *netdev, u32 sset, u8 *data)
{
	struct ena_adapter *adapter = netdev_priv(netdev);

	switch (sset) {
	case ETH_SS_STATS:
		get_stats_strings(adapter, data);
		break;
	case ETH_SS_PRIV_FLAGS:
		get_private_flags_strings(adapter, data);
		break;
	default:
		break;
	}
}

static int ena_get_link_ksettings(struct net_device *netdev,
				  struct ethtool_link_ksettings *link_ksettings)
{
@@ -441,6 +478,7 @@ static void ena_get_drvinfo(struct net_device *dev,
	strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
	strlcpy(info->bus_info, pci_name(adapter->pdev),
		sizeof(info->bus_info));
	info->n_priv_flags = adapter->ena_extra_properties_count;
}

static void ena_get_ringparam(struct net_device *netdev,
@@ -798,6 +836,20 @@ static int ena_set_tunable(struct net_device *netdev,
	return ret;
}

static u32 ena_get_priv_flags(struct net_device *netdev)
{
	struct ena_adapter *adapter = netdev_priv(netdev);
	struct ena_com_dev *ena_dev = adapter->ena_dev;
	struct ena_admin_get_feat_resp get_resp;
	u32 rc;

	rc = ena_com_get_extra_properties_flags(ena_dev, &get_resp);
	if (!rc)
		return get_resp.u.extra_properties_flags.flags;

	return 0;
}

static const struct ethtool_ops ena_ethtool_ops = {
	.get_link_ksettings	= ena_get_link_ksettings,
	.get_drvinfo		= ena_get_drvinfo,
@@ -819,6 +871,7 @@ static const struct ethtool_ops ena_ethtool_ops = {
	.get_channels		= ena_get_channels,
	.get_tunable		= ena_get_tunable,
	.set_tunable		= ena_set_tunable,
	.get_priv_flags		= ena_get_priv_flags,
};

void ena_set_ethtool_ops(struct net_device *netdev)
+14 −0
Original line number Diff line number Diff line
@@ -2369,6 +2369,14 @@ static void ena_config_debug_area(struct ena_adapter *adapter)
	ena_com_delete_debug_area(adapter->ena_dev);
}

static void ena_extra_properties_strings_destroy(struct net_device *netdev)
{
	struct ena_adapter *adapter = netdev_priv(netdev);

	ena_com_delete_extra_properties_strings(adapter->ena_dev);
	adapter->ena_extra_properties_count = 0;
}

static void ena_get_stats64(struct net_device *netdev,
			    struct rtnl_link_stats64 *stats)
{
@@ -3424,6 +3432,9 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)

	ena_config_debug_area(adapter);

	adapter->ena_extra_properties_count =
		ena_com_extra_properties_strings_init(ena_dev);

	memcpy(adapter->netdev->perm_addr, adapter->mac_addr, netdev->addr_len);

	netif_carrier_off(netdev);
@@ -3463,6 +3474,7 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	return 0;

err_rss:
	ena_extra_properties_strings_destroy(netdev);
	ena_com_delete_debug_area(ena_dev);
	ena_com_rss_destroy(ena_dev);
err_free_msix:
@@ -3529,6 +3541,8 @@ static void ena_remove(struct pci_dev *pdev)

	ena_com_delete_host_info(ena_dev);

	ena_extra_properties_strings_destroy(netdev);

	ena_release_bars(ena_dev, pdev);

	pci_disable_device(pdev);
Loading