Skip to content

Commit 694a111

Browse files
vireshkmstsirkin
authored andcommitted
virtio: Bind virtio device to device-tree node
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 <[email protected]> Signed-off-by: Viresh Kumar <[email protected]> Link: https://lore.kernel.org/r/94c12705602929968477aaf27e02439eb7a7f253.1627362340.git.viresh.kumar@linaro.org Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent d5a8680 commit 694a111

File tree

1 file changed

+54
-3
lines changed

1 file changed

+54
-3
lines changed

drivers/virtio/virtio.c

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <linux/virtio_config.h>
55
#include <linux/module.h>
66
#include <linux/idr.h>
7+
#include <linux/of.h>
78
#include <uapi/linux/virtio_ids.h>
89

910
/* Unique numbering for virtio devices. */
@@ -292,6 +293,9 @@ static int virtio_dev_remove(struct device *_d)
292293

293294
/* Acknowledge the device's existence again. */
294295
virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
296+
297+
of_node_put(dev->dev.of_node);
298+
295299
return 0;
296300
}
297301

@@ -319,6 +323,43 @@ void unregister_virtio_driver(struct virtio_driver *driver)
319323
}
320324
EXPORT_SYMBOL_GPL(unregister_virtio_driver);
321325

326+
static int virtio_device_of_init(struct virtio_device *dev)
327+
{
328+
struct device_node *np, *pnode = dev_of_node(dev->dev.parent);
329+
char compat[] = "virtio,deviceXXXXXXXX";
330+
int ret, count;
331+
332+
if (!pnode)
333+
return 0;
334+
335+
count = of_get_available_child_count(pnode);
336+
if (!count)
337+
return 0;
338+
339+
/* There can be only 1 child node */
340+
if (WARN_ON(count > 1))
341+
return -EINVAL;
342+
343+
np = of_get_next_available_child(pnode, NULL);
344+
if (WARN_ON(!np))
345+
return -ENODEV;
346+
347+
ret = snprintf(compat, sizeof(compat), "virtio,device%x", dev->id.device);
348+
BUG_ON(ret >= sizeof(compat));
349+
350+
if (!of_device_is_compatible(np, compat)) {
351+
ret = -EINVAL;
352+
goto out;
353+
}
354+
355+
dev->dev.of_node = np;
356+
return 0;
357+
358+
out:
359+
of_node_put(np);
360+
return ret;
361+
}
362+
322363
/**
323364
* register_virtio_device - register virtio device
324365
* @dev : virtio device to be registered
@@ -343,6 +384,10 @@ int register_virtio_device(struct virtio_device *dev)
343384
dev->index = err;
344385
dev_set_name(&dev->dev, "virtio%u", dev->index);
345386

387+
err = virtio_device_of_init(dev);
388+
if (err)
389+
goto out_ida_remove;
390+
346391
spin_lock_init(&dev->config_lock);
347392
dev->config_enabled = false;
348393
dev->config_change_pending = false;
@@ -363,10 +408,16 @@ int register_virtio_device(struct virtio_device *dev)
363408
*/
364409
err = device_add(&dev->dev);
365410
if (err)
366-
ida_simple_remove(&virtio_index_ida, dev->index);
411+
goto out_of_node_put;
412+
413+
return 0;
414+
415+
out_of_node_put:
416+
of_node_put(dev->dev.of_node);
417+
out_ida_remove:
418+
ida_simple_remove(&virtio_index_ida, dev->index);
367419
out:
368-
if (err)
369-
virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED);
420+
virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED);
370421
return err;
371422
}
372423
EXPORT_SYMBOL_GPL(register_virtio_device);

0 commit comments

Comments
 (0)