Merge tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull virtio update from Rusty Russell: "Some nice cleanups, and even a patch my wife did as a "live" demo for Latinoware 2012. There's a slightly non-trivial merge in virtio-net, as we cleaned up the virtio add_buf interface while DaveM accepted the mq virtio-net patches." * tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux: (27 commits) virtio_console: Add support for remoteproc serial virtio_console: Merge struct buffer_token into struct port_buffer virtio: add drv_to_virtio to make code clearly virtio: use dev_to_virtio wrapper in virtio virtio-mmio: Fix irq parsing in command line parameter virtio_console: Free buffers from out-queue upon close virtio: Convert dev_printk(KERN_<LEVEL> to dev_<level>( virtio_console: Use kmalloc instead of kzalloc virtio_console: Free buffer if splice fails virtio: tools: make it clear that virtqueue_add_buf() no longer returns > 0 virtio: scsi: make it clear that virtqueue_add_buf() no longer returns > 0 virtio: rpmsg: make it clear that virtqueue_add_buf() no longer returns > 0 virtio: net: make it clear that virtqueue_add_buf() no longer returns > 0 virtio: console: make it clear that virtqueue_add_buf() no longer returns > 0 virtio: make virtqueue_add_buf() returning 0 on success, not capacity. virtio: console: don't rely on virtqueue_add_buf() returning capacity. virtio_net: don't rely on virtqueue_add_buf() returning capacity. virtio-net: remove unused skb_vnet_hdr->num_sg field virtio-net: correct capacity math on ring full virtio: move queue_index and num_free fields into core struct virtqueue. ...
This commit is contained in:
@@ -10,33 +10,32 @@ static DEFINE_IDA(virtio_index_ida);
|
||||
static ssize_t device_show(struct device *_d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
||||
struct virtio_device *dev = dev_to_virtio(_d);
|
||||
return sprintf(buf, "0x%04x\n", dev->id.device);
|
||||
}
|
||||
static ssize_t vendor_show(struct device *_d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
||||
struct virtio_device *dev = dev_to_virtio(_d);
|
||||
return sprintf(buf, "0x%04x\n", dev->id.vendor);
|
||||
}
|
||||
static ssize_t status_show(struct device *_d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
||||
struct virtio_device *dev = dev_to_virtio(_d);
|
||||
return sprintf(buf, "0x%08x\n", dev->config->get_status(dev));
|
||||
}
|
||||
static ssize_t modalias_show(struct device *_d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
||||
|
||||
struct virtio_device *dev = dev_to_virtio(_d);
|
||||
return sprintf(buf, "virtio:d%08Xv%08X\n",
|
||||
dev->id.device, dev->id.vendor);
|
||||
}
|
||||
static ssize_t features_show(struct device *_d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct virtio_device *dev = container_of(_d, struct virtio_device, dev);
|
||||
struct virtio_device *dev = dev_to_virtio(_d);
|
||||
unsigned int i;
|
||||
ssize_t len = 0;
|
||||
|
||||
@@ -71,10 +70,10 @@ static inline int virtio_id_match(const struct virtio_device *dev,
|
||||
static int virtio_dev_match(struct device *_dv, struct device_driver *_dr)
|
||||
{
|
||||
unsigned int i;
|
||||
struct virtio_device *dev = container_of(_dv,struct virtio_device,dev);
|
||||
struct virtio_device *dev = dev_to_virtio(_dv);
|
||||
const struct virtio_device_id *ids;
|
||||
|
||||
ids = container_of(_dr, struct virtio_driver, driver)->id_table;
|
||||
ids = drv_to_virtio(_dr)->id_table;
|
||||
for (i = 0; ids[i].device; i++)
|
||||
if (virtio_id_match(dev, &ids[i]))
|
||||
return 1;
|
||||
@@ -83,7 +82,7 @@ static int virtio_dev_match(struct device *_dv, struct device_driver *_dr)
|
||||
|
||||
static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env)
|
||||
{
|
||||
struct virtio_device *dev = container_of(_dv,struct virtio_device,dev);
|
||||
struct virtio_device *dev = dev_to_virtio(_dv);
|
||||
|
||||
return add_uevent_var(env, "MODALIAS=virtio:d%08Xv%08X",
|
||||
dev->id.device, dev->id.vendor);
|
||||
@@ -98,8 +97,7 @@ void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
|
||||
unsigned int fbit)
|
||||
{
|
||||
unsigned int i;
|
||||
struct virtio_driver *drv = container_of(vdev->dev.driver,
|
||||
struct virtio_driver, driver);
|
||||
struct virtio_driver *drv = drv_to_virtio(vdev->dev.driver);
|
||||
|
||||
for (i = 0; i < drv->feature_table_size; i++)
|
||||
if (drv->feature_table[i] == fbit)
|
||||
@@ -111,9 +109,8 @@ EXPORT_SYMBOL_GPL(virtio_check_driver_offered_feature);
|
||||
static int virtio_dev_probe(struct device *_d)
|
||||
{
|
||||
int err, i;
|
||||
struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
||||
struct virtio_driver *drv = container_of(dev->dev.driver,
|
||||
struct virtio_driver, driver);
|
||||
struct virtio_device *dev = dev_to_virtio(_d);
|
||||
struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
|
||||
u32 device_features;
|
||||
|
||||
/* We have a driver! */
|
||||
@@ -152,9 +149,8 @@ static int virtio_dev_probe(struct device *_d)
|
||||
|
||||
static int virtio_dev_remove(struct device *_d)
|
||||
{
|
||||
struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
||||
struct virtio_driver *drv = container_of(dev->dev.driver,
|
||||
struct virtio_driver, driver);
|
||||
struct virtio_device *dev = dev_to_virtio(_d);
|
||||
struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
|
||||
|
||||
drv->remove(dev);
|
||||
|
||||
|
@@ -139,10 +139,9 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num)
|
||||
struct page *page = balloon_page_enqueue(vb_dev_info);
|
||||
|
||||
if (!page) {
|
||||
if (printk_ratelimit())
|
||||
dev_printk(KERN_INFO, &vb->vdev->dev,
|
||||
"Out of puff! Can't get %u pages\n",
|
||||
VIRTIO_BALLOON_PAGES_PER_PAGE);
|
||||
dev_info_ratelimited(&vb->vdev->dev,
|
||||
"Out of puff! Can't get %u pages\n",
|
||||
VIRTIO_BALLOON_PAGES_PER_PAGE);
|
||||
/* Sleep for at least 1/5 of a second before retry. */
|
||||
msleep(200);
|
||||
break;
|
||||
|
@@ -225,7 +225,7 @@ static void vm_notify(struct virtqueue *vq)
|
||||
|
||||
/* We write the queue's selector into the notification register to
|
||||
* signal the other end */
|
||||
writel(virtqueue_get_queue_index(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
|
||||
writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
|
||||
}
|
||||
|
||||
/* Notify all virtqueues on an interrupt. */
|
||||
@@ -266,7 +266,7 @@ static void vm_del_vq(struct virtqueue *vq)
|
||||
struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
|
||||
struct virtio_mmio_vq_info *info = vq->priv;
|
||||
unsigned long flags, size;
|
||||
unsigned int index = virtqueue_get_queue_index(vq);
|
||||
unsigned int index = vq->index;
|
||||
|
||||
spin_lock_irqsave(&vm_dev->lock, flags);
|
||||
list_del(&info->node);
|
||||
@@ -521,25 +521,33 @@ static int vm_cmdline_set(const char *device,
|
||||
int err;
|
||||
struct resource resources[2] = {};
|
||||
char *str;
|
||||
long long int base;
|
||||
long long int base, size;
|
||||
unsigned int irq;
|
||||
int processed, consumed = 0;
|
||||
struct platform_device *pdev;
|
||||
|
||||
resources[0].flags = IORESOURCE_MEM;
|
||||
resources[1].flags = IORESOURCE_IRQ;
|
||||
|
||||
resources[0].end = memparse(device, &str) - 1;
|
||||
/* Consume "size" part of the command line parameter */
|
||||
size = memparse(device, &str);
|
||||
|
||||
/* Get "@<base>:<irq>[:<id>]" chunks */
|
||||
processed = sscanf(str, "@%lli:%u%n:%d%n",
|
||||
&base, &resources[1].start, &consumed,
|
||||
&base, &irq, &consumed,
|
||||
&vm_cmdline_id, &consumed);
|
||||
|
||||
if (processed < 2 || processed > 3 || str[consumed])
|
||||
/*
|
||||
* sscanf() must processes at least 2 chunks; also there
|
||||
* must be no extra characters after the last chunk, so
|
||||
* str[consumed] must be '\0'
|
||||
*/
|
||||
if (processed < 2 || str[consumed])
|
||||
return -EINVAL;
|
||||
|
||||
resources[0].flags = IORESOURCE_MEM;
|
||||
resources[0].start = base;
|
||||
resources[0].end += base;
|
||||
resources[1].end = resources[1].start;
|
||||
resources[0].end = base + size - 1;
|
||||
|
||||
resources[1].flags = IORESOURCE_IRQ;
|
||||
resources[1].start = resources[1].end = irq;
|
||||
|
||||
if (!vm_cmdline_parent_registered) {
|
||||
err = device_register(&vm_cmdline_parent);
|
||||
|
@@ -203,8 +203,7 @@ static void vp_notify(struct virtqueue *vq)
|
||||
|
||||
/* we write the queue's selector into the notification register to
|
||||
* signal the other end */
|
||||
iowrite16(virtqueue_get_queue_index(vq),
|
||||
vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
|
||||
iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
|
||||
}
|
||||
|
||||
/* Handle a configuration change: Tell driver if it wants to know. */
|
||||
@@ -479,8 +478,7 @@ static void vp_del_vq(struct virtqueue *vq)
|
||||
list_del(&info->node);
|
||||
spin_unlock_irqrestore(&vp_dev->lock, flags);
|
||||
|
||||
iowrite16(virtqueue_get_queue_index(vq),
|
||||
vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
|
||||
iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
|
||||
|
||||
if (vp_dev->msix_enabled) {
|
||||
iowrite16(VIRTIO_MSI_NO_VECTOR,
|
||||
@@ -830,16 +828,4 @@ static struct pci_driver virtio_pci_driver = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init virtio_pci_init(void)
|
||||
{
|
||||
return pci_register_driver(&virtio_pci_driver);
|
||||
}
|
||||
|
||||
module_init(virtio_pci_init);
|
||||
|
||||
static void __exit virtio_pci_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&virtio_pci_driver);
|
||||
}
|
||||
|
||||
module_exit(virtio_pci_exit);
|
||||
module_pci_driver(virtio_pci_driver);
|
||||
|
@@ -93,8 +93,6 @@ struct vring_virtqueue
|
||||
/* Host publishes avail event idx */
|
||||
bool event;
|
||||
|
||||
/* Number of free buffers */
|
||||
unsigned int num_free;
|
||||
/* Head of free buffer list. */
|
||||
unsigned int free_head;
|
||||
/* Number we've added since last sync. */
|
||||
@@ -106,9 +104,6 @@ struct vring_virtqueue
|
||||
/* How to notify other side. FIXME: commonalize hcalls! */
|
||||
void (*notify)(struct virtqueue *vq);
|
||||
|
||||
/* Index of the queue */
|
||||
int queue_index;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* They're supposed to lock for us. */
|
||||
unsigned int in_use;
|
||||
@@ -135,6 +130,13 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
|
||||
unsigned head;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* We require lowmem mappings for the descriptors because
|
||||
* otherwise virt_to_phys will give us bogus addresses in the
|
||||
* virtqueue.
|
||||
*/
|
||||
gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH);
|
||||
|
||||
desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp);
|
||||
if (!desc)
|
||||
return -ENOMEM;
|
||||
@@ -160,7 +162,7 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
|
||||
desc[i-1].next = 0;
|
||||
|
||||
/* We're about to use a buffer */
|
||||
vq->num_free--;
|
||||
vq->vq.num_free--;
|
||||
|
||||
/* Use a single buffer which doesn't continue */
|
||||
head = vq->free_head;
|
||||
@@ -174,13 +176,6 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
|
||||
return head;
|
||||
}
|
||||
|
||||
int virtqueue_get_queue_index(struct virtqueue *_vq)
|
||||
{
|
||||
struct vring_virtqueue *vq = to_vvq(_vq);
|
||||
return vq->queue_index;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(virtqueue_get_queue_index);
|
||||
|
||||
/**
|
||||
* virtqueue_add_buf - expose buffer to other end
|
||||
* @vq: the struct virtqueue we're talking about.
|
||||
@@ -193,10 +188,7 @@ EXPORT_SYMBOL_GPL(virtqueue_get_queue_index);
|
||||
* Caller must ensure we don't call this with other virtqueue operations
|
||||
* at the same time (except where noted).
|
||||
*
|
||||
* Returns remaining capacity of queue or a negative error
|
||||
* (ie. ENOSPC). Note that it only really makes sense to treat all
|
||||
* positive return values as "available": indirect buffers mean that
|
||||
* we can put an entire sg[] array inside a single queue entry.
|
||||
* Returns zero or a negative error (ie. ENOSPC, ENOMEM).
|
||||
*/
|
||||
int virtqueue_add_buf(struct virtqueue *_vq,
|
||||
struct scatterlist sg[],
|
||||
@@ -228,7 +220,7 @@ int virtqueue_add_buf(struct virtqueue *_vq,
|
||||
|
||||
/* If the host supports indirect descriptor tables, and we have multiple
|
||||
* buffers, then go indirect. FIXME: tune this threshold */
|
||||
if (vq->indirect && (out + in) > 1 && vq->num_free) {
|
||||
if (vq->indirect && (out + in) > 1 && vq->vq.num_free) {
|
||||
head = vring_add_indirect(vq, sg, out, in, gfp);
|
||||
if (likely(head >= 0))
|
||||
goto add_head;
|
||||
@@ -237,9 +229,9 @@ int virtqueue_add_buf(struct virtqueue *_vq,
|
||||
BUG_ON(out + in > vq->vring.num);
|
||||
BUG_ON(out + in == 0);
|
||||
|
||||
if (vq->num_free < out + in) {
|
||||
if (vq->vq.num_free < out + in) {
|
||||
pr_debug("Can't add buf len %i - avail = %i\n",
|
||||
out + in, vq->num_free);
|
||||
out + in, vq->vq.num_free);
|
||||
/* FIXME: for historical reasons, we force a notify here if
|
||||
* there are outgoing parts to the buffer. Presumably the
|
||||
* host should service the ring ASAP. */
|
||||
@@ -250,7 +242,7 @@ int virtqueue_add_buf(struct virtqueue *_vq,
|
||||
}
|
||||
|
||||
/* We're about to use some buffers from the free list. */
|
||||
vq->num_free -= out + in;
|
||||
vq->vq.num_free -= out + in;
|
||||
|
||||
head = vq->free_head;
|
||||
for (i = vq->free_head; out; i = vq->vring.desc[i].next, out--) {
|
||||
@@ -296,7 +288,7 @@ add_head:
|
||||
pr_debug("Added buffer head %i to %p\n", head, vq);
|
||||
END_USE(vq);
|
||||
|
||||
return vq->num_free;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(virtqueue_add_buf);
|
||||
|
||||
@@ -393,13 +385,13 @@ static void detach_buf(struct vring_virtqueue *vq, unsigned int head)
|
||||
|
||||
while (vq->vring.desc[i].flags & VRING_DESC_F_NEXT) {
|
||||
i = vq->vring.desc[i].next;
|
||||
vq->num_free++;
|
||||
vq->vq.num_free++;
|
||||
}
|
||||
|
||||
vq->vring.desc[i].next = vq->free_head;
|
||||
vq->free_head = head;
|
||||
/* Plus final descriptor */
|
||||
vq->num_free++;
|
||||
vq->vq.num_free++;
|
||||
}
|
||||
|
||||
static inline bool more_used(const struct vring_virtqueue *vq)
|
||||
@@ -599,7 +591,7 @@ void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
|
||||
return buf;
|
||||
}
|
||||
/* That should have freed everything. */
|
||||
BUG_ON(vq->num_free != vq->vring.num);
|
||||
BUG_ON(vq->vq.num_free != vq->vring.num);
|
||||
|
||||
END_USE(vq);
|
||||
return NULL;
|
||||
@@ -653,12 +645,13 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
|
||||
vq->vq.callback = callback;
|
||||
vq->vq.vdev = vdev;
|
||||
vq->vq.name = name;
|
||||
vq->vq.num_free = num;
|
||||
vq->vq.index = index;
|
||||
vq->notify = notify;
|
||||
vq->weak_barriers = weak_barriers;
|
||||
vq->broken = false;
|
||||
vq->last_used_idx = 0;
|
||||
vq->num_added = 0;
|
||||
vq->queue_index = index;
|
||||
list_add_tail(&vq->vq.list, &vdev->vqs);
|
||||
#ifdef DEBUG
|
||||
vq->in_use = false;
|
||||
@@ -673,7 +666,6 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
|
||||
vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
|
||||
|
||||
/* Put everything in free lists. */
|
||||
vq->num_free = num;
|
||||
vq->free_head = 0;
|
||||
for (i = 0; i < num-1; i++) {
|
||||
vq->vring.desc[i].next = i+1;
|
||||
|
Reference in New Issue
Block a user