static int gve_set_priv_flags()

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;
}