#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,
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,
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
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;
};
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)
{
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;
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 {
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
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)
}
}
-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)
{
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,
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,
.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)
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)
{
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);
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:
ena_com_delete_host_info(ena_dev);
+ ena_extra_properties_strings_destroy(netdev);
+
ena_release_bars(ena_dev, pdev);
pci_disable_device(pdev);
u32 last_monitored_tx_qid;
enum ena_regs_reset_reason_types reset_reason;
+
+ u8 ena_extra_properties_count;
};
void ena_set_ethtool_ops(struct net_device *netdev);