dm: core: Create a new header file for 'compat' features
[oweals/u-boot.git] / drivers / virtio / virtio-uclass.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
4  * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
5  *
6  * VirtIO is a virtualization standard for network and disk device drivers
7  * where just the guest's device driver "knows" it is running in a virtual
8  * environment, and cooperates with the hypervisor. This enables guests to
9  * get high performance network and disk operations, and gives most of the
10  * performance benefits of paravirtualization. In the U-Boot case, the guest
11  * is U-Boot itself, while the virtual environment are normally QEMU targets
12  * like ARM, RISC-V and x86.
13  *
14  * See http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf for
15  * the VirtIO specification v1.0.
16  */
17
18 #include <common.h>
19 #include <dm.h>
20 #include <malloc.h>
21 #include <virtio_types.h>
22 #include <virtio.h>
23 #include <dm/lists.h>
24
25 static const char *const virtio_drv_name[VIRTIO_ID_MAX_NUM] = {
26         [VIRTIO_ID_NET]         = VIRTIO_NET_DRV_NAME,
27         [VIRTIO_ID_BLOCK]       = VIRTIO_BLK_DRV_NAME,
28         [VIRTIO_ID_RNG]         = VIRTIO_RNG_DRV_NAME,
29 };
30
31 int virtio_get_config(struct udevice *vdev, unsigned int offset,
32                       void *buf, unsigned int len)
33 {
34         struct dm_virtio_ops *ops;
35
36         ops = virtio_get_ops(vdev->parent);
37
38         return ops->get_config(vdev->parent, offset, buf, len);
39 }
40
41 int virtio_set_config(struct udevice *vdev, unsigned int offset,
42                       void *buf, unsigned int len)
43 {
44         struct dm_virtio_ops *ops;
45
46         ops = virtio_get_ops(vdev->parent);
47
48         return ops->set_config(vdev->parent, offset, buf, len);
49 }
50
51 int virtio_generation(struct udevice *vdev, u32 *counter)
52 {
53         struct dm_virtio_ops *ops;
54
55         ops = virtio_get_ops(vdev->parent);
56         if (!ops->generation)
57                 return -ENOSYS;
58
59         return ops->generation(vdev->parent, counter);
60 }
61
62 int virtio_get_status(struct udevice *vdev, u8 *status)
63 {
64         struct dm_virtio_ops *ops;
65
66         ops = virtio_get_ops(vdev->parent);
67
68         return ops->get_status(vdev->parent, status);
69 }
70
71 int virtio_set_status(struct udevice *vdev, u8 status)
72 {
73         struct dm_virtio_ops *ops;
74
75         ops = virtio_get_ops(vdev->parent);
76
77         return ops->set_status(vdev->parent, status);
78 }
79
80 int virtio_reset(struct udevice *vdev)
81 {
82         struct dm_virtio_ops *ops;
83
84         ops = virtio_get_ops(vdev->parent);
85
86         return ops->reset(vdev->parent);
87 }
88
89 int virtio_get_features(struct udevice *vdev, u64 *features)
90 {
91         struct dm_virtio_ops *ops;
92
93         ops = virtio_get_ops(vdev->parent);
94
95         return ops->get_features(vdev->parent, features);
96 }
97
98 int virtio_set_features(struct udevice *vdev)
99 {
100         struct dm_virtio_ops *ops;
101
102         ops = virtio_get_ops(vdev->parent);
103
104         return ops->set_features(vdev->parent);
105 }
106
107 int virtio_find_vqs(struct udevice *vdev, unsigned int nvqs,
108                     struct virtqueue *vqs[])
109 {
110         struct dm_virtio_ops *ops;
111
112         ops = virtio_get_ops(vdev->parent);
113
114         return ops->find_vqs(vdev->parent, nvqs, vqs);
115 }
116
117 int virtio_del_vqs(struct udevice *vdev)
118 {
119         struct dm_virtio_ops *ops;
120
121         ops = virtio_get_ops(vdev->parent);
122
123         return ops->del_vqs(vdev->parent);
124 }
125
126 int virtio_notify(struct udevice *vdev, struct virtqueue *vq)
127 {
128         struct dm_virtio_ops *ops;
129
130         ops = virtio_get_ops(vdev->parent);
131
132         return ops->notify(vdev->parent, vq);
133 }
134
135 void virtio_add_status(struct udevice *vdev, u8 status)
136 {
137         u8 old;
138
139         if (!virtio_get_status(vdev, &old))
140                 virtio_set_status(vdev, old | status);
141 }
142
143 int virtio_finalize_features(struct udevice *vdev)
144 {
145         struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(vdev->parent);
146         u8 status;
147         int ret;
148
149         ret = virtio_set_features(vdev);
150         if (ret)
151                 return ret;
152
153         if (uc_priv->legacy)
154                 return 0;
155
156         virtio_add_status(vdev, VIRTIO_CONFIG_S_FEATURES_OK);
157         ret = virtio_get_status(vdev, &status);
158         if (ret)
159                 return ret;
160         if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) {
161                 debug("(%s): device refuses features %x\n", vdev->name, status);
162                 return -ENODEV;
163         }
164
165         return 0;
166 }
167
168 void virtio_driver_features_init(struct virtio_dev_priv *priv,
169                                  const u32 *feature,
170                                  u32 feature_size,
171                                  const u32 *feature_legacy,
172                                  u32 feature_legacy_size)
173 {
174         priv->feature_table = feature;
175         priv->feature_table_size = feature_size;
176         priv->feature_table_legacy = feature_legacy;
177         priv->feature_table_size_legacy = feature_legacy_size;
178 }
179
180 int virtio_init(void)
181 {
182         struct udevice *bus;
183         int ret;
184
185         /* Enumerate all known virtio devices */
186         ret = uclass_first_device(UCLASS_VIRTIO, &bus);
187         if (ret)
188                 return ret;
189
190         while (bus) {
191                 ret = uclass_next_device(&bus);
192                 if (ret)
193                         break;
194         }
195
196         return ret;
197 }
198
199 static int virtio_uclass_pre_probe(struct udevice *udev)
200 {
201         struct dm_virtio_ops *ops;
202
203         ops = (struct dm_virtio_ops *)(udev->driver->ops);
204
205         /*
206          * Check virtio transport driver ops here so that we don't need
207          * check these ops each time when the virtio_xxx APIs are called.
208          *
209          * Only generation op is optional. All other ops are must-have.
210          */
211         if (!ops->get_config || !ops->set_config ||
212             !ops->get_status || !ops->set_status ||
213             !ops->get_features || !ops->set_features ||
214             !ops->find_vqs || !ops->del_vqs ||
215             !ops->reset || !ops->notify)
216                 return -ENOENT;
217
218         return 0;
219 }
220
221 static int virtio_uclass_post_probe(struct udevice *udev)
222 {
223         struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
224         char dev_name[30], *str;
225         struct udevice *vdev;
226         int ret;
227
228         if (uc_priv->device > VIRTIO_ID_MAX_NUM) {
229                 debug("(%s): virtio device ID %d exceeds maximum num\n",
230                       udev->name, uc_priv->device);
231                 return 0;
232         }
233
234         if (!virtio_drv_name[uc_priv->device]) {
235                 debug("(%s): underlying virtio device driver unavailable\n",
236                       udev->name);
237                 return 0;
238         }
239
240         snprintf(dev_name, sizeof(dev_name), "%s#%d",
241                  virtio_drv_name[uc_priv->device], udev->seq);
242         str = strdup(dev_name);
243         if (!str)
244                 return -ENOMEM;
245
246         ret = device_bind_driver(udev, virtio_drv_name[uc_priv->device],
247                                  str, &vdev);
248         if (ret == -ENOENT) {
249                 debug("(%s): no driver configured\n", udev->name);
250                 return 0;
251         }
252         if (ret) {
253                 free(str);
254                 return ret;
255         }
256         device_set_name_alloced(vdev);
257
258         INIT_LIST_HEAD(&uc_priv->vqs);
259
260         return 0;
261 }
262
263 static int virtio_uclass_child_post_bind(struct udevice *vdev)
264 {
265         /* Acknowledge that we've seen the device */
266         virtio_add_status(vdev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
267
268         return 0;
269 }
270
271 static int virtio_uclass_child_pre_probe(struct udevice *vdev)
272 {
273         struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(vdev->parent);
274         u64 device_features;
275         u64 driver_features;
276         u64 driver_features_legacy;
277         int i;
278         int ret;
279
280         /*
281          * Save the real virtio device (eg: virtio-net, virtio-blk) to
282          * the transport (parent) device's uclass priv for future use.
283          */
284         uc_priv->vdev = vdev;
285
286         /*
287          * We always start by resetting the device, in case a previous driver
288          * messed it up. This also tests that code path a little.
289          */
290         ret = virtio_reset(vdev);
291         if (ret)
292                 goto err;
293
294         /* We have a driver! */
295         virtio_add_status(vdev, VIRTIO_CONFIG_S_DRIVER);
296
297         /* Figure out what features the device supports */
298         virtio_get_features(vdev, &device_features);
299         debug("(%s) plain device features supported %016llx\n",
300               vdev->name, device_features);
301         if (!(device_features & (1ULL << VIRTIO_F_VERSION_1)))
302                 uc_priv->legacy = true;
303
304         /* Figure out what features the driver supports */
305         driver_features = 0;
306         for (i = 0; i < uc_priv->feature_table_size; i++) {
307                 unsigned int f = uc_priv->feature_table[i];
308
309                 WARN_ON(f >= 64);
310                 driver_features |= (1ULL << f);
311         }
312
313         /* Some drivers have a separate feature table for virtio v1.0 */
314         if (uc_priv->feature_table_legacy) {
315                 driver_features_legacy = 0;
316                 for (i = 0; i < uc_priv->feature_table_size_legacy; i++) {
317                         unsigned int f = uc_priv->feature_table_legacy[i];
318
319                         WARN_ON(f >= 64);
320                         driver_features_legacy |= (1ULL << f);
321                 }
322         } else {
323                 driver_features_legacy = driver_features;
324         }
325
326         if (uc_priv->legacy) {
327                 debug("(%s): legacy virtio device\n", vdev->name);
328                 uc_priv->features = driver_features_legacy & device_features;
329         } else {
330                 debug("(%s): v1.0 complaint virtio device\n", vdev->name);
331                 uc_priv->features = driver_features & device_features;
332         }
333
334         /* Transport features always preserved to pass to finalize_features */
335         for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++)
336                 if ((device_features & (1ULL << i)) &&
337                     (i == VIRTIO_F_VERSION_1))
338                         __virtio_set_bit(vdev->parent, i);
339
340         debug("(%s) final negotiated features supported %016llx\n",
341               vdev->name, uc_priv->features);
342         ret = virtio_finalize_features(vdev);
343         if (ret)
344                 goto err;
345
346         return 0;
347
348 err:
349         virtio_add_status(vdev, VIRTIO_CONFIG_S_FAILED);
350         return ret;
351 }
352
353 static int virtio_uclass_child_post_probe(struct udevice *vdev)
354 {
355         /* Indicates that the driver is set up and ready to drive the device */
356         virtio_add_status(vdev, VIRTIO_CONFIG_S_DRIVER_OK);
357
358         return 0;
359 }
360
361 UCLASS_DRIVER(virtio) = {
362         .name   = "virtio",
363         .id     = UCLASS_VIRTIO,
364         .flags  = DM_UC_FLAG_SEQ_ALIAS,
365         .pre_probe = virtio_uclass_pre_probe,
366         .post_probe = virtio_uclass_post_probe,
367         .child_post_bind = virtio_uclass_child_post_bind,
368         .child_pre_probe = virtio_uclass_child_pre_probe,
369         .child_post_probe = virtio_uclass_child_post_probe,
370         .per_device_auto_alloc_size = sizeof(struct virtio_dev_priv),
371 };