Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus: lguest: notify on empty virtio: force callback on empty. virtio_blk: fix endianess annotations virtio_config: fix len calculation of config elements virtio_net: another race with virtio_net and enable_cb virtio: An entropy device, as suggested by hpa. virtio_blk: allow read-only disks lguest: fix ugly <NULL> in /proc/interrupts virtio: set device index in common code. virtio: virtio_pci should not set bus_id. virtio: bus_id for devices should contain 'virtio' Fix crash in virtio_blk during modprobe ; rmmod ; modprobe lguest: use ioremap_cache, not ioremap
This commit is contained in:
commit
ab8cd81830
14 changed files with 225 additions and 53 deletions
|
@ -157,6 +157,9 @@ struct virtqueue
|
|||
|
||||
/* The routine to call when the Guest pings us. */
|
||||
void (*handle_output)(int fd, struct virtqueue *me);
|
||||
|
||||
/* Outstanding buffers */
|
||||
unsigned int inflight;
|
||||
};
|
||||
|
||||
/* Remember the arguments to the program so we can "reboot" */
|
||||
|
@ -702,6 +705,7 @@ static unsigned get_vq_desc(struct virtqueue *vq,
|
|||
errx(1, "Looped descriptor");
|
||||
} while ((i = next_desc(vq, i)) != vq->vring.num);
|
||||
|
||||
vq->inflight++;
|
||||
return head;
|
||||
}
|
||||
|
||||
|
@ -719,6 +723,7 @@ static void add_used(struct virtqueue *vq, unsigned int head, int len)
|
|||
/* Make sure buffer is written before we update index. */
|
||||
wmb();
|
||||
vq->vring.used->idx++;
|
||||
vq->inflight--;
|
||||
}
|
||||
|
||||
/* This actually sends the interrupt for this virtqueue */
|
||||
|
@ -726,8 +731,9 @@ static void trigger_irq(int fd, struct virtqueue *vq)
|
|||
{
|
||||
unsigned long buf[] = { LHREQ_IRQ, vq->config.irq };
|
||||
|
||||
/* If they don't want an interrupt, don't send one. */
|
||||
if (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
|
||||
/* If they don't want an interrupt, don't send one, unless empty. */
|
||||
if ((vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
|
||||
&& vq->inflight)
|
||||
return;
|
||||
|
||||
/* Send the Guest an interrupt tell them we used something up. */
|
||||
|
@ -1107,6 +1113,7 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs,
|
|||
vq->next = NULL;
|
||||
vq->last_avail_idx = 0;
|
||||
vq->dev = dev;
|
||||
vq->inflight = 0;
|
||||
|
||||
/* Initialize the configuration. */
|
||||
vq->config.num = num_descs;
|
||||
|
@ -1368,6 +1375,7 @@ static void setup_tun_net(const char *arg)
|
|||
|
||||
/* Tell Guest what MAC address to use. */
|
||||
add_feature(dev, VIRTIO_NET_F_MAC);
|
||||
add_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY);
|
||||
set_config(dev, sizeof(conf), &conf);
|
||||
|
||||
/* We don't need the socket any more; setup is done. */
|
||||
|
|
|
@ -582,8 +582,9 @@ static void __init lguest_init_IRQ(void)
|
|||
int vector = FIRST_EXTERNAL_VECTOR + i;
|
||||
if (vector != SYSCALL_VECTOR) {
|
||||
set_intr_gate(vector, interrupt[i]);
|
||||
set_irq_chip_and_handler(i, &lguest_irq_controller,
|
||||
handle_level_irq);
|
||||
set_irq_chip_and_handler_name(i, &lguest_irq_controller,
|
||||
handle_level_irq,
|
||||
"level");
|
||||
}
|
||||
}
|
||||
/* This call is required to set up for 4k stacks, where we have
|
||||
|
|
|
@ -260,6 +260,10 @@ static int virtblk_probe(struct virtio_device *vdev)
|
|||
if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER))
|
||||
blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL);
|
||||
|
||||
/* If disk is read-only in the host, the guest should obey */
|
||||
if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO))
|
||||
set_disk_ro(vblk->disk, 1);
|
||||
|
||||
/* Host must always specify the capacity. */
|
||||
vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity),
|
||||
&cap, sizeof(cap));
|
||||
|
@ -311,6 +315,7 @@ static void virtblk_remove(struct virtio_device *vdev)
|
|||
/* Stop all the virtqueues. */
|
||||
vdev->config->reset(vdev);
|
||||
|
||||
del_gendisk(vblk->disk);
|
||||
blk_cleanup_queue(vblk->disk->queue);
|
||||
put_disk(vblk->disk);
|
||||
mempool_destroy(vblk->pool);
|
||||
|
@ -325,7 +330,7 @@ static struct virtio_device_id id_table[] = {
|
|||
|
||||
static unsigned int features[] = {
|
||||
VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
|
||||
VIRTIO_BLK_F_GEOMETRY,
|
||||
VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO,
|
||||
};
|
||||
|
||||
static struct virtio_driver virtio_blk = {
|
||||
|
|
|
@ -112,3 +112,12 @@ config HW_RANDOM_PASEMI
|
|||
|
||||
If unsure, say Y.
|
||||
|
||||
config HW_RANDOM_VIRTIO
|
||||
tristate "VirtIO Random Number Generator support"
|
||||
depends on HW_RANDOM && VIRTIO
|
||||
---help---
|
||||
This driver provides kernel-side support for the virtual Random Number
|
||||
Generator hardware.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called virtio-rng. If unsure, say N.
|
||||
|
|
|
@ -11,3 +11,4 @@ obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
|
|||
obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
|
||||
|
|
155
drivers/char/hw_random/virtio-rng.c
Normal file
155
drivers/char/hw_random/virtio-rng.c
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Randomness driver for virtio
|
||||
* Copyright (C) 2007, 2008 Rusty Russell IBM Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <linux/err.h>
|
||||
#include <linux/hw_random.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/virtio.h>
|
||||
#include <linux/virtio_rng.h>
|
||||
|
||||
/* The host will fill any buffer we give it with sweet, sweet randomness. We
|
||||
* give it 64 bytes at a time, and the hwrng framework takes it 4 bytes at a
|
||||
* time. */
|
||||
#define RANDOM_DATA_SIZE 64
|
||||
|
||||
static struct virtqueue *vq;
|
||||
static u32 *random_data;
|
||||
static unsigned int data_left;
|
||||
static DECLARE_COMPLETION(have_data);
|
||||
|
||||
static void random_recv_done(struct virtqueue *vq)
|
||||
{
|
||||
int len;
|
||||
|
||||
/* We never get spurious callbacks. */
|
||||
if (!vq->vq_ops->get_buf(vq, &len))
|
||||
BUG();
|
||||
|
||||
data_left = len / sizeof(random_data[0]);
|
||||
complete(&have_data);
|
||||
}
|
||||
|
||||
static void register_buffer(void)
|
||||
{
|
||||
struct scatterlist sg;
|
||||
|
||||
sg_init_one(&sg, random_data, RANDOM_DATA_SIZE);
|
||||
/* There should always be room for one buffer. */
|
||||
if (vq->vq_ops->add_buf(vq, &sg, 0, 1, random_data) != 0)
|
||||
BUG();
|
||||
vq->vq_ops->kick(vq);
|
||||
}
|
||||
|
||||
/* At least we don't udelay() in a loop like some other drivers. */
|
||||
static int virtio_data_present(struct hwrng *rng, int wait)
|
||||
{
|
||||
if (data_left)
|
||||
return 1;
|
||||
|
||||
if (!wait)
|
||||
return 0;
|
||||
|
||||
wait_for_completion(&have_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* virtio_data_present() must have succeeded before this is called. */
|
||||
static int virtio_data_read(struct hwrng *rng, u32 *data)
|
||||
{
|
||||
BUG_ON(!data_left);
|
||||
|
||||
*data = random_data[--data_left];
|
||||
|
||||
if (!data_left) {
|
||||
init_completion(&have_data);
|
||||
register_buffer();
|
||||
}
|
||||
return sizeof(*data);
|
||||
}
|
||||
|
||||
static struct hwrng virtio_hwrng = {
|
||||
.name = "virtio",
|
||||
.data_present = virtio_data_present,
|
||||
.data_read = virtio_data_read,
|
||||
};
|
||||
|
||||
static int virtrng_probe(struct virtio_device *vdev)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* We expect a single virtqueue. */
|
||||
vq = vdev->config->find_vq(vdev, 0, random_recv_done);
|
||||
if (IS_ERR(vq))
|
||||
return PTR_ERR(vq);
|
||||
|
||||
err = hwrng_register(&virtio_hwrng);
|
||||
if (err) {
|
||||
vdev->config->del_vq(vq);
|
||||
return err;
|
||||
}
|
||||
|
||||
register_buffer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void virtrng_remove(struct virtio_device *vdev)
|
||||
{
|
||||
vdev->config->reset(vdev);
|
||||
hwrng_unregister(&virtio_hwrng);
|
||||
vdev->config->del_vq(vq);
|
||||
}
|
||||
|
||||
static struct virtio_device_id id_table[] = {
|
||||
{ VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static struct virtio_driver virtio_rng = {
|
||||
.driver.name = KBUILD_MODNAME,
|
||||
.driver.owner = THIS_MODULE,
|
||||
.id_table = id_table,
|
||||
.probe = virtrng_probe,
|
||||
.remove = __devexit_p(virtrng_remove),
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
random_data = kmalloc(RANDOM_DATA_SIZE, GFP_KERNEL);
|
||||
if (!random_data)
|
||||
return -ENOMEM;
|
||||
|
||||
err = register_virtio_driver(&virtio_rng);
|
||||
if (err)
|
||||
kfree(random_data);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
kfree(random_data);
|
||||
unregister_virtio_driver(&virtio_rng);
|
||||
}
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
|
||||
MODULE_DEVICE_TABLE(virtio, id_table);
|
||||
MODULE_DESCRIPTION("Virtio random number driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -20,14 +20,11 @@
|
|||
/* The pointer to our (page) of device descriptions. */
|
||||
static void *lguest_devices;
|
||||
|
||||
/* Unique numbering for lguest devices. */
|
||||
static unsigned int dev_index;
|
||||
|
||||
/* For Guests, device memory can be used as normal memory, so we cast away the
|
||||
* __iomem to quieten sparse. */
|
||||
static inline void *lguest_map(unsigned long phys_addr, unsigned long pages)
|
||||
{
|
||||
return (__force void *)ioremap(phys_addr, PAGE_SIZE*pages);
|
||||
return (__force void *)ioremap_cache(phys_addr, PAGE_SIZE*pages);
|
||||
}
|
||||
|
||||
static inline void lguest_unmap(void *addr)
|
||||
|
@ -325,8 +322,10 @@ static struct device lguest_root = {
|
|||
* As Andrew Tridgell says, "Untested code is buggy code".
|
||||
*
|
||||
* It's worth reading this carefully: we start with a pointer to the new device
|
||||
* descriptor in the "lguest_devices" page. */
|
||||
static void add_lguest_device(struct lguest_device_desc *d)
|
||||
* descriptor in the "lguest_devices" page, and the offset into the device
|
||||
* descriptor page so we can uniquely identify it if things go badly wrong. */
|
||||
static void add_lguest_device(struct lguest_device_desc *d,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct lguest_device *ldev;
|
||||
|
||||
|
@ -334,18 +333,14 @@ static void add_lguest_device(struct lguest_device_desc *d)
|
|||
* it. */
|
||||
ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
|
||||
if (!ldev) {
|
||||
printk(KERN_EMERG "Cannot allocate lguest dev %u\n",
|
||||
dev_index++);
|
||||
printk(KERN_EMERG "Cannot allocate lguest dev %u type %u\n",
|
||||
offset, d->type);
|
||||
return;
|
||||
}
|
||||
|
||||
/* This devices' parent is the lguest/ dir. */
|
||||
ldev->vdev.dev.parent = &lguest_root;
|
||||
/* We have a unique device index thanks to the dev_index counter. */
|
||||
ldev->vdev.index = dev_index++;
|
||||
/* The device type comes straight from the descriptor. There's also a
|
||||
* device vendor field in the virtio_device struct, which we leave as
|
||||
* 0. */
|
||||
ldev->vdev.id.device = d->type;
|
||||
/* We have a simple set of routines for querying the device's
|
||||
* configuration information and setting its status. */
|
||||
|
@ -357,8 +352,8 @@ static void add_lguest_device(struct lguest_device_desc *d)
|
|||
* virtio_device and calls device_register(). This makes the bus
|
||||
* infrastructure look for a matching driver. */
|
||||
if (register_virtio_device(&ldev->vdev) != 0) {
|
||||
printk(KERN_ERR "Failed to register lguest device %u\n",
|
||||
ldev->vdev.index);
|
||||
printk(KERN_ERR "Failed to register lguest dev %u type %u\n",
|
||||
offset, d->type);
|
||||
kfree(ldev);
|
||||
}
|
||||
}
|
||||
|
@ -379,7 +374,7 @@ static void scan_devices(void)
|
|||
break;
|
||||
|
||||
printk("Device at %i has size %u\n", i, desc_size(d));
|
||||
add_lguest_device(d);
|
||||
add_lguest_device(d, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,11 +31,6 @@
|
|||
*/
|
||||
static void *kvm_devices;
|
||||
|
||||
/*
|
||||
* Unique numbering for kvm devices.
|
||||
*/
|
||||
static unsigned int dev_index;
|
||||
|
||||
struct kvm_device {
|
||||
struct virtio_device vdev;
|
||||
struct kvm_device_desc *desc;
|
||||
|
@ -250,26 +245,25 @@ static struct device kvm_root = {
|
|||
* adds a new device and register it with virtio
|
||||
* appropriate drivers are loaded by the device model
|
||||
*/
|
||||
static void add_kvm_device(struct kvm_device_desc *d)
|
||||
static void add_kvm_device(struct kvm_device_desc *d, unsigned int offset)
|
||||
{
|
||||
struct kvm_device *kdev;
|
||||
|
||||
kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
|
||||
if (!kdev) {
|
||||
printk(KERN_EMERG "Cannot allocate kvm dev %u\n",
|
||||
dev_index++);
|
||||
printk(KERN_EMERG "Cannot allocate kvm dev %u type %u\n",
|
||||
offset, d->type);
|
||||
return;
|
||||
}
|
||||
|
||||
kdev->vdev.dev.parent = &kvm_root;
|
||||
kdev->vdev.index = dev_index++;
|
||||
kdev->vdev.id.device = d->type;
|
||||
kdev->vdev.config = &kvm_vq_configspace_ops;
|
||||
kdev->desc = d;
|
||||
|
||||
if (register_virtio_device(&kdev->vdev) != 0) {
|
||||
printk(KERN_ERR "Failed to register kvm device %u\n",
|
||||
kdev->vdev.index);
|
||||
printk(KERN_ERR "Failed to register kvm device %u type %u\n",
|
||||
offset, d->type);
|
||||
kfree(kdev);
|
||||
}
|
||||
}
|
||||
|
@ -289,7 +283,7 @@ static void scan_devices(void)
|
|||
if (d->type == 0)
|
||||
break;
|
||||
|
||||
add_kvm_device(d);
|
||||
add_kvm_device(d, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/virtio_config.h>
|
||||
|
||||
/* Unique numbering for virtio devices. */
|
||||
static unsigned int dev_index;
|
||||
|
||||
static ssize_t device_show(struct device *_d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
@ -166,7 +169,10 @@ int register_virtio_device(struct virtio_device *dev)
|
|||
int err;
|
||||
|
||||
dev->dev.bus = &virtio_bus;
|
||||
sprintf(dev->dev.bus_id, "%u", dev->index);
|
||||
|
||||
/* Assign a unique device index and hence name. */
|
||||
dev->index = dev_index++;
|
||||
sprintf(dev->dev.bus_id, "virtio%u", dev->index);
|
||||
|
||||
/* We always start by resetting the device, in case a previous
|
||||
* driver messed it up. This also tests that code path a little. */
|
||||
|
|
|
@ -78,9 +78,6 @@ static struct device virtio_pci_root = {
|
|||
.bus_id = "virtio-pci",
|
||||
};
|
||||
|
||||
/* Unique numbering for devices under the kvm root */
|
||||
static unsigned int dev_index;
|
||||
|
||||
/* Convert a generic virtio device to our structure */
|
||||
static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev)
|
||||
{
|
||||
|
@ -325,10 +322,6 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
|
|||
if (vp_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
snprintf(vp_dev->vdev.dev.bus_id, BUS_ID_SIZE, "virtio%d", dev_index);
|
||||
vp_dev->vdev.index = dev_index;
|
||||
dev_index++;
|
||||
|
||||
vp_dev->vdev.dev.parent = &virtio_pci_root;
|
||||
vp_dev->vdev.config = &virtio_pci_config_ops;
|
||||
vp_dev->pci_dev = pci_dev;
|
||||
|
|
|
@ -227,7 +227,6 @@ static bool vring_enable_cb(struct virtqueue *_vq)
|
|||
struct vring_virtqueue *vq = to_vvq(_vq);
|
||||
|
||||
START_USE(vq);
|
||||
BUG_ON(!(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT));
|
||||
|
||||
/* We optimistically turn back on interrupts, then check if there was
|
||||
* more to do. */
|
||||
|
@ -254,13 +253,6 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
|
|||
if (unlikely(vq->broken))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/* Other side may have missed us turning off the interrupt,
|
||||
* but we should preserve disable semantic for virtio users. */
|
||||
if (unlikely(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) {
|
||||
pr_debug("virtqueue interrupt after disable for %p\n", vq);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback);
|
||||
if (vq->vq.callback)
|
||||
vq->vq.callback(&vq->vq);
|
||||
|
|
|
@ -10,18 +10,19 @@
|
|||
#define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */
|
||||
#define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */
|
||||
#define VIRTIO_BLK_F_GEOMETRY 4 /* Legacy geometry available */
|
||||
#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */
|
||||
|
||||
struct virtio_blk_config
|
||||
{
|
||||
/* The capacity (in 512-byte sectors). */
|
||||
__le64 capacity;
|
||||
__u64 capacity;
|
||||
/* The maximum segment size (if VIRTIO_BLK_F_SIZE_MAX) */
|
||||
__le32 size_max;
|
||||
__u32 size_max;
|
||||
/* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */
|
||||
__le32 seg_max;
|
||||
__u32 seg_max;
|
||||
/* geometry the device (if VIRTIO_BLK_F_GEOMETRY) */
|
||||
struct virtio_blk_geometry {
|
||||
__le16 cylinders;
|
||||
__u16 cylinders;
|
||||
__u8 heads;
|
||||
__u8 sectors;
|
||||
} geometry;
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
/* We've given up on this device. */
|
||||
#define VIRTIO_CONFIG_S_FAILED 0x80
|
||||
|
||||
/* Do we get callbacks when the ring is completely used, even if we've
|
||||
* suppressed them? */
|
||||
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/virtio.h>
|
||||
|
||||
|
@ -99,7 +103,7 @@ static inline bool virtio_has_feature(const struct virtio_device *vdev,
|
|||
* The return value is -ENOENT if the feature doesn't exist. Otherwise
|
||||
* the config value is copied into whatever is pointed to by v. */
|
||||
#define virtio_config_val(vdev, fbit, offset, v) \
|
||||
virtio_config_buf((vdev), (fbit), (offset), (v), sizeof(v))
|
||||
virtio_config_buf((vdev), (fbit), (offset), (v), sizeof(*v))
|
||||
|
||||
static inline int virtio_config_buf(struct virtio_device *vdev,
|
||||
unsigned int fbit,
|
||||
|
|
8
include/linux/virtio_rng.h
Normal file
8
include/linux/virtio_rng.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef _LINUX_VIRTIO_RNG_H
|
||||
#define _LINUX_VIRTIO_RNG_H
|
||||
#include <linux/virtio_config.h>
|
||||
|
||||
/* The ID for virtio_rng */
|
||||
#define VIRTIO_ID_RNG 4
|
||||
|
||||
#endif /* _LINUX_VIRTIO_RNG_H */
|
Loading…
Reference in a new issue