History

vdpa: add driver_override support

`driver_override` allows to control which of the vDPA bus drivers binds to a vDPA device. If `driver_override` is not set, the previous behaviour is followed: devices use the first vDPA bus driver loaded (unless auto binding is disabled). Tested on Fedora 34 with driverctl(8): $ modprobe virtio-vdpa $ modprobe vhost-vdpa $ modprobe vdpa-sim-net $ vdpa dev add mgmtdev vdpasim_net name dev1 # dev1 is attached to the first vDPA bus driver loaded $ driverctl -b vdpa list-devices dev1 virtio_vdpa $ driverctl -b vdpa set-override dev1 vhost_vdpa $ driverctl -b vdpa list-devices dev1 vhost_vdpa [*] Note: driverctl(8) integrates with udev so the binding is preserved.

Stefano Garzarella committed 4 years ago

Commit 539fec71 parent 9c25cde3 files · +96 −0Browse files

Unified · Split

3 files
  1. Documentation/ABI/testing/sysfs-bus-vdpa +20 −0
  2. drivers/vdpa/vdpa.c +74 −0
  3. include/linux/vdpa.h +2 −0
Documentation/ABI/testing/sysfs-bus-vdpa+20−0
@@ -35,3 +35,23 @@ Description: · 34 unmodified lines
35 Writing a device name to this file will cause the driver to35 Writing a device name to this file will cause the driver to
36 attempt to unbind from the device. This may be useful when36 attempt to unbind from the device. This may be useful when
37 overriding default bindings.37 overriding default bindings.
38
39What: /sys/bus/vdpa/devices/.../driver_override
40Date: November 2021
41Contact: virtualization@lists.linux-foundation.org
42Description:
43 This file allows the driver for a device to be specified.
44 When specified, only a driver with a name matching the value
45 written to driver_override will have an opportunity to bind to
46 the device. The override is specified by writing a string to the
47 driver_override file (echo vhost-vdpa > driver_override) and may
48 be cleared with an empty string (echo > driver_override).
49 This returns the device to standard matching rules binding.
50 Writing to driver_override does not automatically unbind the
51 device from its current driver or make any attempt to
52 automatically load the specified driver. If no driver with a
53 matching name is currently loaded in the kernel, the device will
54 not bind to any driver. This also allows devices to opt-out of
55 driver binding using a driver_override name such as "none".
56 Only a single driver may be specified in the override, there is
57 no support for parsing delimiters.
drivers/vdpa/vdpa.c+74−0
@@ -52,8 +52,81 @@ static void vdpa_dev_remove(struct device *d) · 51 unmodified lines
52 drv->remove(vdev);52 drv->remove(vdev);
53}53}
54 54
55static int vdpa_dev_match(struct device *dev, struct device_driver *drv)
56{
57 struct vdpa_device *vdev = dev_to_vdpa(dev);
58
59 /* Check override first, and if set, only use the named driver */
60 if (vdev->driver_override)
61 return strcmp(vdev->driver_override, drv->name) == 0;
62
63 /* Currently devices must be supported by all vDPA bus drivers */
64 return 1;
65}
66
67static ssize_t driver_override_store(struct device *dev,
68 struct device_attribute *attr,
69 const char *buf, size_t count)
70{
71 struct vdpa_device *vdev = dev_to_vdpa(dev);
72 const char *driver_override, *old;
73 char *cp;
74
75 /* We need to keep extra room for a newline */
76 if (count >= (PAGE_SIZE - 1))
77 return -EINVAL;
78
79 driver_override = kstrndup(buf, count, GFP_KERNEL);
80 if (!driver_override)
81 return -ENOMEM;
82
83 cp = strchr(driver_override, '\n');
84 if (cp)
85 *cp = '\0';
86
87 device_lock(dev);
88 old = vdev->driver_override;
89 if (strlen(driver_override)) {
90 vdev->driver_override = driver_override;
91 } else {
92 kfree(driver_override);
93 vdev->driver_override = NULL;
94 }
95 device_unlock(dev);
96
97 kfree(old);
98
99 return count;
100}
101
102static ssize_t driver_override_show(struct device *dev,
103 struct device_attribute *attr, char *buf)
104{
105 struct vdpa_device *vdev = dev_to_vdpa(dev);
106 ssize_t len;
107
108 device_lock(dev);
109 len = snprintf(buf, PAGE_SIZE, "%s\n", vdev->driver_override);
110 device_unlock(dev);
111
112 return len;
113}
114static DEVICE_ATTR_RW(driver_override);
115
116static struct attribute *vdpa_dev_attrs[] = {
117 &dev_attr_driver_override.attr,
118 NULL,
119};
120
121static const struct attribute_group vdpa_dev_group = {
122 .attrs = vdpa_dev_attrs,
123};
124__ATTRIBUTE_GROUPS(vdpa_dev);
125
55static struct bus_type vdpa_bus = {126static struct bus_type vdpa_bus = {
56 .name = "vdpa",127 .name = "vdpa",
128 .dev_groups = vdpa_dev_groups,
129 .match = vdpa_dev_match,
57 .probe = vdpa_dev_probe,130 .probe = vdpa_dev_probe,
58 .remove = vdpa_dev_remove,131 .remove = vdpa_dev_remove,
59};132};
@@ -68,6 +141,7 @@ static void vdpa_release_dev(struct device *d) · 8 unmodified lines
68 141
69 ida_simple_remove(&vdpa_index_ida, vdev->index);142 ida_simple_remove(&vdpa_index_ida, vdev->index);
70 mutex_destroy(&vdev->cf_mutex);143 mutex_destroy(&vdev->cf_mutex);
144 kfree(vdev->driver_override);
71 kfree(vdev);145 kfree(vdev);
72}146}
73 147
include/linux/vdpa.h+2−0
@@ -64,6 +64,7 @@ struct vdpa_mgmt_dev; · 63 unmodified lines
64 * struct vdpa_device - representation of a vDPA device64 * struct vdpa_device - representation of a vDPA device
65 * @dev: underlying device65 * @dev: underlying device
66 * @dma_dev: the actual device that is performing DMA66 * @dma_dev: the actual device that is performing DMA
67 * @driver_override: driver name to force a match
67 * @config: the configuration ops for this device.68 * @config: the configuration ops for this device.
68 * @cf_mutex: Protects get and set access to configuration layout.69 * @cf_mutex: Protects get and set access to configuration layout.
69 * @index: device index70 * @index: device index
@@ -76,6 +77,7 @@ struct vdpa_mgmt_dev; · 6 unmodified lines
76struct vdpa_device {77struct vdpa_device {
77 struct device dev;78 struct device dev;
78 struct device *dma_dev;79 struct device *dma_dev;
80 const char *driver_override;
79 const struct vdpa_config_ops *config;81 const struct vdpa_config_ops *config;
80 struct mutex cf_mutex; /* Protects get/set config */82 struct mutex cf_mutex; /* Protects get/set config */
81 unsigned int index;83 unsigned int index;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t