All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Alvaro Karsz <alvaro.karsz@solid-run.com>
Cc: xuanzhuo@linux.alibaba.com, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	virtualization@lists.linux-foundation.org, edumazet@google.com,
	kuba@kernel.org, pabeni@redhat.com, davem@davemloft.net
Subject: Re: [RFC PATCH net 1/3] virtio: re-negotiate features if probe fails and features are blocked
Date: Sun, 30 Apr 2023 09:27:22 -0400	[thread overview]
Message-ID: <20230430092142-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <20230430131518.2708471-2-alvaro.karsz@solid-run.com>

On Sun, Apr 30, 2023 at 04:15:16PM +0300, Alvaro Karsz wrote:
> This patch exports a new virtio core function: virtio_block_feature.
> The function should be called during a virtio driver probe.
> 
> If a virtio driver blocks features during probe and fails probe, virtio
> core will reset the device, try to re-negotiate the new features and
> probe again.
> 
> Signed-off-by: Alvaro Karsz <alvaro.karsz@solid-run.com>
> ---
>  drivers/virtio/virtio.c | 73 ++++++++++++++++++++++++++++++-----------
>  include/linux/virtio.h  |  3 ++
>  2 files changed, 56 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
> index 3893dc29eb2..eaad5b6a7a9 100644
> --- a/drivers/virtio/virtio.c
> +++ b/drivers/virtio/virtio.c
> @@ -167,6 +167,13 @@ void virtio_add_status(struct virtio_device *dev, unsigned int status)
>  }
>  EXPORT_SYMBOL_GPL(virtio_add_status);
>  
> +void virtio_block_feature(struct virtio_device *dev, unsigned int f)
> +{
> +	BUG_ON(f >= 64);
> +	dev->blocked_features |= (1ULL << f);
> +}
> +EXPORT_SYMBOL_GPL(virtio_block_feature);
> +

Let's add documentation please. Also pls call it __virtio_block_feature
since it has to be used in a special way - specifically only during
probe.

>  /* Do some validation, then set FEATURES_OK */
>  static int virtio_features_ok(struct virtio_device *dev)
>  {
> @@ -234,17 +241,13 @@ void virtio_reset_device(struct virtio_device *dev)
>  }
>  EXPORT_SYMBOL_GPL(virtio_reset_device);
>  
> -static int virtio_dev_probe(struct device *_d)
> +static int virtio_negotiate_features(struct virtio_device *dev)
>  {
> -	int err, i;
> -	struct virtio_device *dev = dev_to_virtio(_d);
>  	struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
>  	u64 device_features;
>  	u64 driver_features;
>  	u64 driver_features_legacy;
> -
> -	/* We have a driver! */
> -	virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);
> +	int i, ret;
>  
>  	/* Figure out what features the device supports. */
>  	device_features = dev->config->get_features(dev);
> @@ -279,30 +282,61 @@ static int virtio_dev_probe(struct device *_d)
>  		if (device_features & (1ULL << i))
>  			__virtio_set_bit(dev, i);
>  
> -	err = dev->config->finalize_features(dev);
> -	if (err)
> -		goto err;
> +	/* Remove blocked features */
> +	dev->features &= ~dev->blocked_features;
> +
> +	ret = dev->config->finalize_features(dev);
> +	if (ret)
> +		goto exit;
>  
>  	if (drv->validate) {
>  		u64 features = dev->features;
>  
> -		err = drv->validate(dev);
> -		if (err)
> -			goto err;
> +		ret = drv->validate(dev);
> +		if (ret)
> +			goto exit;
>  
>  		/* Did validation change any features? Then write them again. */
>  		if (features != dev->features) {
> -			err = dev->config->finalize_features(dev);
> -			if (err)
> -				goto err;
> +			ret = dev->config->finalize_features(dev);
> +			if (ret)
> +				goto exit;
>  		}
>  	}
>  
> -	err = virtio_features_ok(dev);
> -	if (err)
> -		goto err;
> +	ret = virtio_features_ok(dev);
> +exit:
> +	return ret;
> +}
> +
> +static int virtio_dev_probe(struct device *_d)
> +{
> +	int err;
> +	struct virtio_device *dev = dev_to_virtio(_d);
> +	struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
> +	u64 blocked_features;
> +	bool renegotiate = true;
> +
> +	/* We have a driver! */
> +	virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);
> +
> +	/* Store blocked features and attempt to negotiate features & probe.
> +	 * If the probe fails, we check if the driver has blocked any new features.
> +	 * If it has, we reset the device and try again with the new features.
> +	 */
> +	while (renegotiate) {
> +		blocked_features = dev->blocked_features;
> +		err = virtio_negotiate_features(dev);
> +		if (err)
> +			break;
> +
> +		err = drv->probe(dev);


there's no way to driver to clear blocked features, but
just in case, I'd add BUG_ON to check.

> +		if (err && blocked_features != dev->blocked_features)
> +			virtio_reset_device(dev);
> +		else
> +			renegotiate = false;
> +	}
>  
> -	err = drv->probe(dev);
>  	if (err)
>  		goto err;
>  
> @@ -319,7 +353,6 @@ static int virtio_dev_probe(struct device *_d)
>  err:
>  	virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED);
>  	return err;
> -
>  }
>  
>  static void virtio_dev_remove(struct device *_d)
> diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> index b93238db94e..2de9b2d3ca4 100644
> --- a/include/linux/virtio.h
> +++ b/include/linux/virtio.h
> @@ -109,6 +109,7 @@ int virtqueue_resize(struct virtqueue *vq, u32 num,
>   * @vringh_config: configuration ops for host vrings.
>   * @vqs: the list of virtqueues for this device.
>   * @features: the features supported by both driver and device.
> + * @blocked_features: the features blocked by the driver that can't be negotiated.
>   * @priv: private pointer for the driver's use.
>   */
>  struct virtio_device {
> @@ -124,6 +125,7 @@ struct virtio_device {
>  	const struct vringh_config_ops *vringh_config;
>  	struct list_head vqs;
>  	u64 features;
> +	u64 blocked_features;

add comment here too, explain purpose and rules of use

>  	void *priv;
>  };
>  
> @@ -133,6 +135,7 @@ void virtio_add_status(struct virtio_device *dev, unsigned int status);
>  int register_virtio_device(struct virtio_device *dev);
>  void unregister_virtio_device(struct virtio_device *dev);
>  bool is_virtio_device(struct device *dev);
> +void virtio_block_feature(struct virtio_device *dev, unsigned int f);
>  
>  void virtio_break_device(struct virtio_device *dev);
>  void __virtio_unbreak_device(struct virtio_device *dev);
> -- 
> 2.34.1

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

WARNING: multiple messages have this Message-ID (diff)
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Alvaro Karsz <alvaro.karsz@solid-run.com>
Cc: jasowang@redhat.com, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, pabeni@redhat.com,
	virtualization@lists.linux-foundation.org,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	xuanzhuo@linux.alibaba.com
Subject: Re: [RFC PATCH net 1/3] virtio: re-negotiate features if probe fails and features are blocked
Date: Sun, 30 Apr 2023 09:27:22 -0400	[thread overview]
Message-ID: <20230430092142-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <20230430131518.2708471-2-alvaro.karsz@solid-run.com>

On Sun, Apr 30, 2023 at 04:15:16PM +0300, Alvaro Karsz wrote:
> This patch exports a new virtio core function: virtio_block_feature.
> The function should be called during a virtio driver probe.
> 
> If a virtio driver blocks features during probe and fails probe, virtio
> core will reset the device, try to re-negotiate the new features and
> probe again.
> 
> Signed-off-by: Alvaro Karsz <alvaro.karsz@solid-run.com>
> ---
>  drivers/virtio/virtio.c | 73 ++++++++++++++++++++++++++++++-----------
>  include/linux/virtio.h  |  3 ++
>  2 files changed, 56 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
> index 3893dc29eb2..eaad5b6a7a9 100644
> --- a/drivers/virtio/virtio.c
> +++ b/drivers/virtio/virtio.c
> @@ -167,6 +167,13 @@ void virtio_add_status(struct virtio_device *dev, unsigned int status)
>  }
>  EXPORT_SYMBOL_GPL(virtio_add_status);
>  
> +void virtio_block_feature(struct virtio_device *dev, unsigned int f)
> +{
> +	BUG_ON(f >= 64);
> +	dev->blocked_features |= (1ULL << f);
> +}
> +EXPORT_SYMBOL_GPL(virtio_block_feature);
> +

Let's add documentation please. Also pls call it __virtio_block_feature
since it has to be used in a special way - specifically only during
probe.

>  /* Do some validation, then set FEATURES_OK */
>  static int virtio_features_ok(struct virtio_device *dev)
>  {
> @@ -234,17 +241,13 @@ void virtio_reset_device(struct virtio_device *dev)
>  }
>  EXPORT_SYMBOL_GPL(virtio_reset_device);
>  
> -static int virtio_dev_probe(struct device *_d)
> +static int virtio_negotiate_features(struct virtio_device *dev)
>  {
> -	int err, i;
> -	struct virtio_device *dev = dev_to_virtio(_d);
>  	struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
>  	u64 device_features;
>  	u64 driver_features;
>  	u64 driver_features_legacy;
> -
> -	/* We have a driver! */
> -	virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);
> +	int i, ret;
>  
>  	/* Figure out what features the device supports. */
>  	device_features = dev->config->get_features(dev);
> @@ -279,30 +282,61 @@ static int virtio_dev_probe(struct device *_d)
>  		if (device_features & (1ULL << i))
>  			__virtio_set_bit(dev, i);
>  
> -	err = dev->config->finalize_features(dev);
> -	if (err)
> -		goto err;
> +	/* Remove blocked features */
> +	dev->features &= ~dev->blocked_features;
> +
> +	ret = dev->config->finalize_features(dev);
> +	if (ret)
> +		goto exit;
>  
>  	if (drv->validate) {
>  		u64 features = dev->features;
>  
> -		err = drv->validate(dev);
> -		if (err)
> -			goto err;
> +		ret = drv->validate(dev);
> +		if (ret)
> +			goto exit;
>  
>  		/* Did validation change any features? Then write them again. */
>  		if (features != dev->features) {
> -			err = dev->config->finalize_features(dev);
> -			if (err)
> -				goto err;
> +			ret = dev->config->finalize_features(dev);
> +			if (ret)
> +				goto exit;
>  		}
>  	}
>  
> -	err = virtio_features_ok(dev);
> -	if (err)
> -		goto err;
> +	ret = virtio_features_ok(dev);
> +exit:
> +	return ret;
> +}
> +
> +static int virtio_dev_probe(struct device *_d)
> +{
> +	int err;
> +	struct virtio_device *dev = dev_to_virtio(_d);
> +	struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
> +	u64 blocked_features;
> +	bool renegotiate = true;
> +
> +	/* We have a driver! */
> +	virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);
> +
> +	/* Store blocked features and attempt to negotiate features & probe.
> +	 * If the probe fails, we check if the driver has blocked any new features.
> +	 * If it has, we reset the device and try again with the new features.
> +	 */
> +	while (renegotiate) {
> +		blocked_features = dev->blocked_features;
> +		err = virtio_negotiate_features(dev);
> +		if (err)
> +			break;
> +
> +		err = drv->probe(dev);


there's no way to driver to clear blocked features, but
just in case, I'd add BUG_ON to check.

> +		if (err && blocked_features != dev->blocked_features)
> +			virtio_reset_device(dev);
> +		else
> +			renegotiate = false;
> +	}
>  
> -	err = drv->probe(dev);
>  	if (err)
>  		goto err;
>  
> @@ -319,7 +353,6 @@ static int virtio_dev_probe(struct device *_d)
>  err:
>  	virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED);
>  	return err;
> -
>  }
>  
>  static void virtio_dev_remove(struct device *_d)
> diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> index b93238db94e..2de9b2d3ca4 100644
> --- a/include/linux/virtio.h
> +++ b/include/linux/virtio.h
> @@ -109,6 +109,7 @@ int virtqueue_resize(struct virtqueue *vq, u32 num,
>   * @vringh_config: configuration ops for host vrings.
>   * @vqs: the list of virtqueues for this device.
>   * @features: the features supported by both driver and device.
> + * @blocked_features: the features blocked by the driver that can't be negotiated.
>   * @priv: private pointer for the driver's use.
>   */
>  struct virtio_device {
> @@ -124,6 +125,7 @@ struct virtio_device {
>  	const struct vringh_config_ops *vringh_config;
>  	struct list_head vqs;
>  	u64 features;
> +	u64 blocked_features;

add comment here too, explain purpose and rules of use

>  	void *priv;
>  };
>  
> @@ -133,6 +135,7 @@ void virtio_add_status(struct virtio_device *dev, unsigned int status);
>  int register_virtio_device(struct virtio_device *dev);
>  void unregister_virtio_device(struct virtio_device *dev);
>  bool is_virtio_device(struct device *dev);
> +void virtio_block_feature(struct virtio_device *dev, unsigned int f);
>  
>  void virtio_break_device(struct virtio_device *dev);
>  void __virtio_unbreak_device(struct virtio_device *dev);
> -- 
> 2.34.1


  reply	other threads:[~2023-04-30 13:27 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-30 13:15 [RFC PATCH net 0/3] virtio-net: allow usage of small vrings Alvaro Karsz
2023-04-30 13:15 ` Alvaro Karsz
2023-04-30 13:15 ` [RFC PATCH net 1/3] virtio: re-negotiate features if probe fails and features are blocked Alvaro Karsz
2023-04-30 13:15   ` Alvaro Karsz
2023-04-30 13:27   ` Michael S. Tsirkin [this message]
2023-04-30 13:27     ` Michael S. Tsirkin
2023-04-30 18:18     ` Alvaro Karsz
2023-04-30 18:18       ` Alvaro Karsz
2023-04-30 13:15 ` [RFC PATCH net 2/3] virtio-net: allow usage of vrings smaller than MAX_SKB_FRAGS + 2 Alvaro Karsz
2023-04-30 13:15   ` Alvaro Karsz
2023-04-30 14:05   ` Michael S. Tsirkin
2023-04-30 14:05     ` Michael S. Tsirkin
2023-04-30 18:54     ` Alvaro Karsz
2023-04-30 18:54       ` Alvaro Karsz
2023-05-01 10:20       ` Michael S. Tsirkin
2023-05-01 10:20         ` Michael S. Tsirkin
2023-05-01 11:59         ` Alvaro Karsz
2023-05-01 11:59           ` Alvaro Karsz
2023-06-02 11:30           ` Michael S. Tsirkin
2023-06-02 11:30             ` Michael S. Tsirkin
2023-04-30 13:15 ` [RFC PATCH net 3/3] virtio-net: block ethtool from converting a ring to a small ring Alvaro Karsz
2023-04-30 13:15   ` Alvaro Karsz
2023-04-30 14:06 ` [RFC PATCH net 0/3] virtio-net: allow usage of small vrings Michael S. Tsirkin
2023-04-30 14:06   ` Michael S. Tsirkin
2023-04-30 18:15   ` Alvaro Karsz
2023-04-30 18:15     ` Alvaro Karsz
2023-05-01 10:27     ` Michael S. Tsirkin
2023-05-01 10:27       ` Michael S. Tsirkin
2023-05-01 11:41       ` Alvaro Karsz
2023-05-01 11:41         ` Alvaro Karsz
2023-06-02 11:29         ` Michael S. Tsirkin
2023-06-02 11:29           ` Michael S. Tsirkin
2023-06-17  7:44 ` Michael S. Tsirkin
2023-06-17  7:44   ` Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230430092142-mutt-send-email-mst@kernel.org \
    --to=mst@redhat.com \
    --cc=alvaro.karsz@solid-run.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=virtualization@lists.linux-foundation.org \
    --cc=xuanzhuo@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.