Re: [PATCH V3 5/5] virtio: Bind virtio device to device-tree node
From: Alexey Kardashevskiy <hidden>
Date: 2021-09-13 10:27:30
Also in:
lkml, virtualization
On 13/09/2021 19:45, Michael S. Tsirkin wrote:
On Mon, Sep 13, 2021 at 07:19:17PM +1000, Alexey Kardashevskiy wrote:quoted
On 26/07/2021 14:51, Viresh Kumar wrote:quoted
Bind the virtio devices with their of_node. This will help users of the virtio devices to mention their dependencies on the device in the DT itself. Like GPIO pin users can use the phandle of the device node, or the node may contain more subnodes to add i2c or spi eeproms and other users. Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> --- drivers/virtio/virtio.c | 57 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 3 deletions(-)diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 4b15c00c0a0a..d001e84a5b23 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c@@ -4,6 +4,7 @@ #include <linux/virtio_config.h> #include <linux/module.h> #include <linux/idr.h> +#include <linux/of.h> #include <uapi/linux/virtio_ids.h> /* Unique numbering for virtio devices. */@@ -292,6 +293,9 @@ static int virtio_dev_remove(struct device *_d) /* Acknowledge the device's existence again. */ virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); + + of_node_put(dev->dev.of_node); + return 0; }@@ -319,6 +323,43 @@ void unregister_virtio_driver(struct virtio_driver *driver) } EXPORT_SYMBOL_GPL(unregister_virtio_driver); +static int virtio_device_of_init(struct virtio_device *dev) +{ + struct device_node *np, *pnode = dev_of_node(dev->dev.parent); + char compat[] = "virtio,XXXXXXXX"; /* Reserve enough space 32-bit id */ + int ret, count; + + if (!pnode) + return 0; + + count = of_get_available_child_count(pnode); + if (!count) + return 0; + + /* There can be only 1 child node */ + if (WARN_ON(count > 1)) + return -EINVAL; + + np = of_get_next_available_child(pnode, NULL); + if (WARN_ON(!np)) + return -ENODEV; + + BUG_ON(snprintf(compat, sizeof(compat), "virtio,%x", dev->id.device) >= + sizeof(compat)); + + if (!of_device_is_compatible(np, compat)) {This broke powerpc/pseries as there these virtio devices are PCI so there is no "compat" - PCI vendor id/device ids play role of "compat". Thanks,Hmm now that you say this I wonder why do we bother with this check, too. When can this be invoked for something that is not a virtio device? And is it enough to just skip of_node initialization then?
I am not following here, the problem device is virtio-scsi which is virtio-derived, or you meant that virtio which hosts virtio-bus?
quoted
quoted
+ ret = -EINVAL;So basically ret = 0 above?
Yup, this does fix it. Thanks,
quoted
quoted
+ goto out; + } + + dev->dev.of_node = np; + return 0; + +out: + of_node_put(np); + return ret; +} + /** * register_virtio_device - register virtio device * @dev : virtio device to be registered@@ -343,6 +384,10 @@ int register_virtio_device(struct virtio_device *dev) dev->index = err; dev_set_name(&dev->dev, "virtio%u", dev->index); + err = virtio_device_of_init(dev); + if (err) + goto out_ida_remove; + spin_lock_init(&dev->config_lock); dev->config_enabled = false; dev->config_change_pending = false;@@ -362,10 +407,16 @@ int register_virtio_device(struct virtio_device *dev) */ err = device_add(&dev->dev); if (err) - ida_simple_remove(&virtio_index_ida, dev->index); + goto out_of_node_put; + + return 0; + +out_of_node_put: + of_node_put(dev->dev.of_node); +out_ida_remove: + ida_simple_remove(&virtio_index_ida, dev->index); out: - if (err) - virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); + virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED); return err; } EXPORT_SYMBOL_GPL(register_virtio_device);-- Alexey
-- Alexey