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: Arthur Kiyanovski <akiyano@amazon.com> Signed-off-by: Sameeh Jubran <sameehj@amazon.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
05d62ca218
commit
315c28d2b7
@ -32,6 +32,8 @@
|
|||||||
#ifndef _ENA_ADMIN_H_
|
#ifndef _ENA_ADMIN_H_
|
||||||
#define _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 {
|
enum ena_admin_aq_opcode {
|
||||||
ENA_ADMIN_CREATE_SQ = 1,
|
ENA_ADMIN_CREATE_SQ = 1,
|
||||||
@ -60,6 +62,8 @@ enum ena_admin_aq_feature_id {
|
|||||||
ENA_ADMIN_MAX_QUEUES_NUM = 2,
|
ENA_ADMIN_MAX_QUEUES_NUM = 2,
|
||||||
ENA_ADMIN_HW_HINTS = 3,
|
ENA_ADMIN_HW_HINTS = 3,
|
||||||
ENA_ADMIN_LLQ = 4,
|
ENA_ADMIN_LLQ = 4,
|
||||||
|
ENA_ADMIN_EXTRA_PROPERTIES_STRINGS = 5,
|
||||||
|
ENA_ADMIN_EXTRA_PROPERTIES_FLAGS = 6,
|
||||||
ENA_ADMIN_RSS_HASH_FUNCTION = 10,
|
ENA_ADMIN_RSS_HASH_FUNCTION = 10,
|
||||||
ENA_ADMIN_STATELESS_OFFLOAD_CONFIG = 11,
|
ENA_ADMIN_STATELESS_OFFLOAD_CONFIG = 11,
|
||||||
ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG = 12,
|
ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG = 12,
|
||||||
@ -560,6 +564,14 @@ struct ena_admin_set_feature_mtu_desc {
|
|||||||
u32 mtu;
|
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 {
|
struct ena_admin_set_feature_host_attr_desc {
|
||||||
/* host OS info base address in OS memory. host info is 4KB of
|
/* host OS info base address in OS memory. host info is 4KB of
|
||||||
* physically contiguous
|
* physically contiguous
|
||||||
@ -864,6 +876,10 @@ struct ena_admin_get_feat_resp {
|
|||||||
struct ena_admin_feature_intr_moder_desc intr_moderation;
|
struct ena_admin_feature_intr_moder_desc intr_moderation;
|
||||||
|
|
||||||
struct ena_admin_ena_hw_hints hw_hints;
|
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;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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);
|
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,
|
int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev,
|
||||||
struct ena_com_dev_get_features_ctx *get_feat_ctx)
|
struct ena_com_dev_get_features_ctx *get_feat_ctx)
|
||||||
{
|
{
|
||||||
|
@ -347,6 +347,12 @@ struct ena_host_attribute {
|
|||||||
dma_addr_t host_info_dma_addr;
|
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. */
|
/* Each ena_dev is a PCI function. */
|
||||||
struct ena_com_dev {
|
struct ena_com_dev {
|
||||||
struct ena_com_admin_queue admin_queue;
|
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_intr_moder_entry *intr_moder_tbl;
|
||||||
|
|
||||||
struct ena_com_llq_info llq_info;
|
struct ena_com_llq_info llq_info;
|
||||||
|
struct ena_extra_properties_strings extra_properties_strings;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ena_com_dev_get_features_ctx {
|
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,
|
int ena_com_get_link_params(struct ena_com_dev *ena_dev,
|
||||||
struct ena_admin_get_feat_resp *resp);
|
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
|
/* ena_com_get_dma_width - Retrieve physical dma address width the device
|
||||||
* supports.
|
* supports.
|
||||||
* @ena_dev: ENA communication layer struct
|
* @ena_dev: ENA communication layer struct
|
||||||
|
@ -197,15 +197,24 @@ static void ena_get_ethtool_stats(struct net_device *netdev,
|
|||||||
ena_dev_admin_queue_stats(adapter, &data);
|
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)
|
int ena_get_sset_count(struct net_device *netdev, int sset)
|
||||||
{
|
{
|
||||||
struct ena_adapter *adapter = netdev_priv(netdev);
|
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 -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)
|
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;
|
const struct ena_stats *ena_stats;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (sset != ETH_SS_STATS)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < ENA_STATS_ARRAY_GLOBAL; i++) {
|
for (i = 0; i < ENA_STATS_ARRAY_GLOBAL; i++) {
|
||||||
ena_stats = &ena_stats_global_strings[i];
|
ena_stats = &ena_stats_global_strings[i];
|
||||||
|
|
||||||
memcpy(data, ena_stats->name, ETH_GSTRING_LEN);
|
memcpy(data, ena_stats->name, ETH_GSTRING_LEN);
|
||||||
data += ETH_GSTRING_LEN;
|
data += ETH_GSTRING_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
ena_queue_strings(adapter, &data);
|
ena_queue_strings(adapter, &data);
|
||||||
ena_com_dev_strings(&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,
|
static int ena_get_link_ksettings(struct net_device *netdev,
|
||||||
struct ethtool_link_ksettings *link_ksettings)
|
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->version, DRV_MODULE_VERSION, sizeof(info->version));
|
||||||
strlcpy(info->bus_info, pci_name(adapter->pdev),
|
strlcpy(info->bus_info, pci_name(adapter->pdev),
|
||||||
sizeof(info->bus_info));
|
sizeof(info->bus_info));
|
||||||
|
info->n_priv_flags = adapter->ena_extra_properties_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ena_get_ringparam(struct net_device *netdev,
|
static void ena_get_ringparam(struct net_device *netdev,
|
||||||
@ -798,6 +836,20 @@ static int ena_set_tunable(struct net_device *netdev,
|
|||||||
return ret;
|
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 = {
|
static const struct ethtool_ops ena_ethtool_ops = {
|
||||||
.get_link_ksettings = ena_get_link_ksettings,
|
.get_link_ksettings = ena_get_link_ksettings,
|
||||||
.get_drvinfo = ena_get_drvinfo,
|
.get_drvinfo = ena_get_drvinfo,
|
||||||
@ -819,6 +871,7 @@ static const struct ethtool_ops ena_ethtool_ops = {
|
|||||||
.get_channels = ena_get_channels,
|
.get_channels = ena_get_channels,
|
||||||
.get_tunable = ena_get_tunable,
|
.get_tunable = ena_get_tunable,
|
||||||
.set_tunable = ena_set_tunable,
|
.set_tunable = ena_set_tunable,
|
||||||
|
.get_priv_flags = ena_get_priv_flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
void ena_set_ethtool_ops(struct net_device *netdev)
|
void ena_set_ethtool_ops(struct net_device *netdev)
|
||||||
|
@ -2369,6 +2369,14 @@ err:
|
|||||||
ena_com_delete_debug_area(adapter->ena_dev);
|
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,
|
static void ena_get_stats64(struct net_device *netdev,
|
||||||
struct rtnl_link_stats64 *stats)
|
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);
|
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);
|
memcpy(adapter->netdev->perm_addr, adapter->mac_addr, netdev->addr_len);
|
||||||
|
|
||||||
netif_carrier_off(netdev);
|
netif_carrier_off(netdev);
|
||||||
@ -3463,6 +3474,7 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_rss:
|
err_rss:
|
||||||
|
ena_extra_properties_strings_destroy(netdev);
|
||||||
ena_com_delete_debug_area(ena_dev);
|
ena_com_delete_debug_area(ena_dev);
|
||||||
ena_com_rss_destroy(ena_dev);
|
ena_com_rss_destroy(ena_dev);
|
||||||
err_free_msix:
|
err_free_msix:
|
||||||
@ -3529,6 +3541,8 @@ static void ena_remove(struct pci_dev *pdev)
|
|||||||
|
|
||||||
ena_com_delete_host_info(ena_dev);
|
ena_com_delete_host_info(ena_dev);
|
||||||
|
|
||||||
|
ena_extra_properties_strings_destroy(netdev);
|
||||||
|
|
||||||
ena_release_bars(ena_dev, pdev);
|
ena_release_bars(ena_dev, pdev);
|
||||||
|
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
|
@ -364,6 +364,8 @@ struct ena_adapter {
|
|||||||
u32 last_monitored_tx_qid;
|
u32 last_monitored_tx_qid;
|
||||||
|
|
||||||
enum ena_regs_reset_reason_types reset_reason;
|
enum ena_regs_reset_reason_types reset_reason;
|
||||||
|
|
||||||
|
u8 ena_extra_properties_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ena_set_ethtool_ops(struct net_device *netdev);
|
void ena_set_ethtool_ops(struct net_device *netdev);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user