mirror of https://gitee.com/openkylin/linux.git
gve: Enable Link Speed Reporting in the driver.
This change allows the driver to report the device link speed when the ethtool command: ethtool <nic name> is run. Getting the link speed is done via a new admin queue command: ReportLinkSpeed. Reviewed-by: Yangchun Fu <yangchun@google.com> Signed-off-by: David Awogbemila <awogbemila@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
3b7cc73628
commit
7e074d5a76
|
@ -232,6 +232,7 @@ struct gve_priv {
|
|||
u32 adminq_dcfg_device_resources_cnt;
|
||||
u32 adminq_set_driver_parameter_cnt;
|
||||
u32 adminq_report_stats_cnt;
|
||||
u32 adminq_report_link_speed_cnt;
|
||||
|
||||
/* Global stats */
|
||||
u32 interface_up_cnt; /* count of times interface turned up since last reset */
|
||||
|
@ -254,6 +255,8 @@ struct gve_priv {
|
|||
unsigned long stats_report_timer_period;
|
||||
struct timer_list stats_report_timer;
|
||||
|
||||
/* Gvnic device link speed from hypervisor. */
|
||||
u64 link_speed;
|
||||
};
|
||||
|
||||
enum gve_service_task_flags_bit {
|
||||
|
|
|
@ -36,6 +36,7 @@ int gve_adminq_alloc(struct device *dev, struct gve_priv *priv)
|
|||
priv->adminq_dcfg_device_resources_cnt = 0;
|
||||
priv->adminq_set_driver_parameter_cnt = 0;
|
||||
priv->adminq_report_stats_cnt = 0;
|
||||
priv->adminq_report_link_speed_cnt = 0;
|
||||
|
||||
/* Setup Admin queue with the device */
|
||||
iowrite32be(priv->adminq_bus_addr / PAGE_SIZE,
|
||||
|
@ -238,6 +239,9 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv,
|
|||
case GVE_ADMINQ_REPORT_STATS:
|
||||
priv->adminq_report_stats_cnt++;
|
||||
break;
|
||||
case GVE_ADMINQ_REPORT_LINK_SPEED:
|
||||
priv->adminq_report_link_speed_cnt++;
|
||||
break;
|
||||
default:
|
||||
dev_err(&priv->pdev->dev, "unknown AQ command opcode %d\n", opcode);
|
||||
}
|
||||
|
@ -595,3 +599,30 @@ int gve_adminq_report_stats(struct gve_priv *priv, u64 stats_report_len,
|
|||
|
||||
return gve_adminq_execute_cmd(priv, &cmd);
|
||||
}
|
||||
|
||||
int gve_adminq_report_link_speed(struct gve_priv *priv)
|
||||
{
|
||||
union gve_adminq_command gvnic_cmd;
|
||||
dma_addr_t link_speed_region_bus;
|
||||
__be64 *link_speed_region;
|
||||
int err;
|
||||
|
||||
link_speed_region =
|
||||
dma_alloc_coherent(&priv->pdev->dev, sizeof(*link_speed_region),
|
||||
&link_speed_region_bus, GFP_KERNEL);
|
||||
|
||||
if (!link_speed_region)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(&gvnic_cmd, 0, sizeof(gvnic_cmd));
|
||||
gvnic_cmd.opcode = cpu_to_be32(GVE_ADMINQ_REPORT_LINK_SPEED);
|
||||
gvnic_cmd.report_link_speed.link_speed_address =
|
||||
cpu_to_be64(link_speed_region_bus);
|
||||
|
||||
err = gve_adminq_execute_cmd(priv, &gvnic_cmd);
|
||||
|
||||
priv->link_speed = be64_to_cpu(*link_speed_region);
|
||||
dma_free_coherent(&priv->pdev->dev, sizeof(*link_speed_region), link_speed_region,
|
||||
link_speed_region_bus);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ enum gve_adminq_opcodes {
|
|||
GVE_ADMINQ_DECONFIGURE_DEVICE_RESOURCES = 0x9,
|
||||
GVE_ADMINQ_SET_DRIVER_PARAMETER = 0xB,
|
||||
GVE_ADMINQ_REPORT_STATS = 0xC,
|
||||
GVE_ADMINQ_REPORT_LINK_SPEED = 0xD
|
||||
};
|
||||
|
||||
/* Admin queue status codes */
|
||||
|
@ -181,6 +182,12 @@ struct gve_adminq_report_stats {
|
|||
|
||||
static_assert(sizeof(struct gve_adminq_report_stats) == 24);
|
||||
|
||||
struct gve_adminq_report_link_speed {
|
||||
__be64 link_speed_address;
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct gve_adminq_report_link_speed) == 8);
|
||||
|
||||
struct stats {
|
||||
__be32 stat_name;
|
||||
__be32 queue_id;
|
||||
|
@ -228,6 +235,7 @@ union gve_adminq_command {
|
|||
struct gve_adminq_unregister_page_list unreg_page_list;
|
||||
struct gve_adminq_set_driver_parameter set_driver_param;
|
||||
struct gve_adminq_report_stats report_stats;
|
||||
struct gve_adminq_report_link_speed report_link_speed;
|
||||
};
|
||||
};
|
||||
u8 reserved[64];
|
||||
|
@ -255,4 +263,5 @@ int gve_adminq_unregister_page_list(struct gve_priv *priv, u32 page_list_id);
|
|||
int gve_adminq_set_mtu(struct gve_priv *priv, u64 mtu);
|
||||
int gve_adminq_report_stats(struct gve_priv *priv, u64 stats_report_len,
|
||||
dma_addr_t stats_report_addr, u64 interval);
|
||||
int gve_adminq_report_link_speed(struct gve_priv *priv);
|
||||
#endif /* _GVE_ADMINQ_H */
|
||||
|
|
|
@ -59,7 +59,7 @@ static const char gve_gstrings_adminq_stats[][ETH_GSTRING_LEN] = {
|
|||
"adminq_create_tx_queue_cnt", "adminq_create_rx_queue_cnt",
|
||||
"adminq_destroy_tx_queue_cnt", "adminq_destroy_rx_queue_cnt",
|
||||
"adminq_dcfg_device_resources_cnt", "adminq_set_driver_parameter_cnt",
|
||||
"adminq_report_stats_cnt",
|
||||
"adminq_report_stats_cnt", "adminq_report_link_speed_cnt"
|
||||
};
|
||||
|
||||
static const char gve_gstrings_priv_flags[][ETH_GSTRING_LEN] = {
|
||||
|
@ -355,6 +355,7 @@ gve_get_ethtool_stats(struct net_device *netdev,
|
|||
data[i++] = priv->adminq_dcfg_device_resources_cnt;
|
||||
data[i++] = priv->adminq_set_driver_parameter_cnt;
|
||||
data[i++] = priv->adminq_report_stats_cnt;
|
||||
data[i++] = priv->adminq_report_link_speed_cnt;
|
||||
}
|
||||
|
||||
static void gve_get_channels(struct net_device *netdev,
|
||||
|
@ -505,6 +506,16 @@ static int gve_set_priv_flags(struct net_device *netdev, u32 flags)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int gve_get_link_ksettings(struct net_device *netdev,
|
||||
struct ethtool_link_ksettings *cmd)
|
||||
{
|
||||
struct gve_priv *priv = netdev_priv(netdev);
|
||||
int err = gve_adminq_report_link_speed(priv);
|
||||
|
||||
cmd->base.speed = priv->link_speed;
|
||||
return err;
|
||||
}
|
||||
|
||||
const struct ethtool_ops gve_ethtool_ops = {
|
||||
.get_drvinfo = gve_get_drvinfo,
|
||||
.get_strings = gve_get_strings,
|
||||
|
@ -521,4 +532,5 @@ const struct ethtool_ops gve_ethtool_ops = {
|
|||
.set_tunable = gve_set_tunable,
|
||||
.get_priv_flags = gve_get_priv_flags,
|
||||
.set_priv_flags = gve_set_priv_flags,
|
||||
.get_link_ksettings = gve_get_link_ksettings
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue