in build/gve_ethtool.c [738:835]
static int gve_set_priv_flags(struct net_device *netdev, u32 flags)
{
struct gve_priv *priv = netdev_priv(netdev);
u64 ori_flags, new_flags;
int num_tx_queues;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6,8,0))
u64 flag_diff;
int new_packet_buffer_size;
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6,8,0) */
num_tx_queues = gve_num_tx_queues(priv);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0))
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,20,0)
ori_flags = READ_ONCE(priv->ethtool_flags);
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3,20,0) */
ori_flags = ACCESS_ONCE(priv->ethtool_flags);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,20,0) */
new_flags = ori_flags;
/* Only one priv flag exists: report-stats (BIT(0))*/
if (flags & BIT(0))
new_flags |= BIT(0);
else
new_flags &= ~(BIT(0));
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) */
/* If turning off header split, strict header split will be turned off too*/
if (gve_get_enable_header_split(priv) && !(flags & BIT(GVE_PRIV_FLAGS_ENABLE_HEADER_SPLIT))) {
flags &= ~BIT(GVE_PRIV_FLAGS_ENABLE_HEADER_SPLIT);
flags &= ~BIT(GVE_PRIV_FLAGS_ENABLE_STRICT_HEADER_SPLIT);
}
/* If strict header-split is requested, turn on regular header-split */
if (flags & BIT(GVE_PRIV_FLAGS_ENABLE_STRICT_HEADER_SPLIT))
flags |= BIT(GVE_PRIV_FLAGS_ENABLE_HEADER_SPLIT);
/* Make sure header-split is available */
if ((flags & BIT(GVE_PRIV_FLAGS_ENABLE_HEADER_SPLIT)) && !(priv->header_buf_size)) {
dev_err(&priv->pdev->dev, "Header-split not available\n");
return -EINVAL;
}
if ((flags & BIT(GVE_PRIV_FLAGS_ENABLE_MAX_RX_BUFFER_SIZE)) && priv->max_rx_buffer_size <= GVE_DEFAULT_RX_BUFFER_SIZE) {
dev_err(&priv->pdev->dev,
"Max-rx-buffer-size not available\n");
return -EINVAL;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,20,0)
ori_flags = READ_ONCE(priv->ethtool_flags);
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3,20,0) */
ori_flags = ACCESS_ONCE(priv->ethtool_flags);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,20,0) */
new_flags = flags & GVE_PRIV_FLAGS_MASK;
flag_diff = new_flags ^ ori_flags;
if ((flag_diff & BIT(GVE_PRIV_FLAGS_ENABLE_HEADER_SPLIT)) || (flag_diff & BIT(GVE_PRIV_FLAGS_ENABLE_MAX_RX_BUFFER_SIZE))) {
bool enable_hdr_split = new_flags & BIT(GVE_PRIV_FLAGS_ENABLE_HEADER_SPLIT);
bool enable_max_buffer_size = new_flags & BIT(GVE_PRIV_FLAGS_ENABLE_MAX_RX_BUFFER_SIZE);
int err;
if (enable_max_buffer_size)
new_packet_buffer_size = priv->max_rx_buffer_size;
else
new_packet_buffer_size = GVE_DEFAULT_RX_BUFFER_SIZE;
err = gve_set_buffer_size_config(priv, enable_hdr_split,
new_packet_buffer_size);
if (err)
return err;
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) */
priv->ethtool_flags = new_flags;
/* start report-stats timer when user turns report stats on. */
if (flags & BIT(0)) {
mod_timer(&priv->stats_report_timer,
round_jiffies(jiffies +
msecs_to_jiffies(priv->stats_report_timer_period)));
}
/* Zero off gve stats when report-stats turned off and */
/* delete report stats timer. */
if (!(flags & BIT(0)) && (ori_flags & BIT(0))) {
int tx_stats_num = GVE_TX_STATS_REPORT_NUM *
num_tx_queues;
int rx_stats_num = GVE_RX_STATS_REPORT_NUM *
priv->rx_cfg.num_queues;
memset(priv->stats_report->stats, 0, (tx_stats_num + rx_stats_num) *
sizeof(struct stats));
del_timer_sync(&priv->stats_report_timer);
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6,8,0))
priv->header_split_strict = (priv->ethtool_flags & BIT(GVE_PRIV_FLAGS_ENABLE_STRICT_HEADER_SPLIT)) ? true : false;
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6,8,0) */
return 0;
}