Re: [PATCHv4 2/2] virtio: refactor find_vqs
On Tue, 25 Aug 2009 09:34:34 pm Michael S. Tsirkin wrote: That's because we didn't do the request_irq's for the per_vector case, because we don't have the names. This is what prevented me from doing a nice encapsulation. Yes. But let's split free_vectors out into free_msix_vectors and free_intx as well? Perhaps. Patch welcome :) Yes, I agree, this is good cleanup, structure field names should be desriptive. Are you sure we want to make all local variables named vector renamed to msix_vector though? CodingStyle says local var names should be short ... A couple of ideas below. msix_vec would work. But vector for something which isn't always the vector is misleading, IMHO. - if (vector != VIRTIO_MSI_NO_VECTOR) { - iowrite16(vector, vp_dev-ioaddr + VIRTIO_MSI_QUEUE_VECTOR); - vector = ioread16(vp_dev-ioaddr + VIRTIO_MSI_QUEUE_VECTOR); - if (vector == VIRTIO_MSI_NO_VECTOR) { + if (msix_vector != VIRTIO_MSI_NO_VECTOR) { + iowrite16(msix_vector, vp_dev-ioaddr+VIRTIO_MSI_QUEUE_VECTOR); + msix_vector = ioread16(vp_dev-ioaddr+VIRTIO_MSI_QUEUE_VECTOR); checkpatch will complain that space is lacking around +. We won't have a problem if we keep it named vector. Yeah, but OTOH ignoring checkpatch warnings is good for the soul. if (!use_msix) { /* Old style: one normal interrupt for change and all vqs. */ vp_dev-msix_vectors = 0; - vp_dev-per_vq_vectors = false; I know it's enough to look at msix_vectors, but isn't it cleaner to have per_vq_vectors consistent as well? E.g. del_vqs seems to only look at per_vq_vectors. This should in fact be: if (!use_msix) { /* Old style: one normal interrupt for change and all vqs. */ - vp_dev-msix_vectors = 0; - vp_dev-per_vq_vectors = false; err = request_irq(vp_dev-pci_dev-irq, vp_interrupt, IRQF_SHARED, dev_name(vdev-dev), vp_dev); - if (!err) - vp_dev-intx_enabled = 1; - return err; + if (err) + return err; + vp_dev-intx_enabled = 1; The msix fields should all be ignored if msix_enabled is false. Think about running valgrind (or equiv) over the code: if you initialize something which shouldn't be accessed, valgrind won't spot it. For similar reasons, I dislike memseting structs to 0, or kzallocing them. err = request_irq(vp_dev-pci_dev-irq, vp_interrupt, IRQF_SHARED, dev_name(vdev-dev), vp_dev); - if (!err) - vp_dev-intx_enabled = 1; - return err; + if (err) + return err; Maybe move this part out into a separate function? This way vp_try_to_find_vqs does high-level processing. Nice. Moved this to vp_request_intx(). + } else { + if (per_vq_vectors) { + /* Best option: one for change interrupt, one per vq. */ + nvectors = 1; + for (i = 0; i nvqs; ++i) + if (callbacks[i]) + ++nvectors; + } else { + /* Second best: one for change, shared for all vqs. */ + nvectors = 2; Out of curiosity: why do you put {} here? They aren't strictly necessary ... Comment made it multiline, looked a bit neater? Here's the diff result: diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -346,10 +346,22 @@ error: return err; } +static int vp_request_intx(struct virtio_device *vdev) +{ + int err; + struct virtio_pci_device *vp_dev = to_vp_device(vdev); + + err = request_irq(vp_dev-pci_dev-irq, vp_interrupt, + IRQF_SHARED, dev_name(vdev-dev), vp_dev); + if (!err) + vp_dev-intx_enabled = 1; + return err; +} + static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, void (*callback)(struct virtqueue *vq), const char *name, - u16 msix_vector) + u16 msix_vec) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); struct virtio_pci_vq_info *info; @@ -374,7 +386,7 @@ static struct virtqueue *setup_vq(struct info-queue_index = index; info-num = num; - info-msix_vector = msix_vector; + info-msix_vector = msix_vec; size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN)); info-queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO); @@ -398,10 +410,10 @@ static struct virtqueue *setup_vq(struct vq-priv = info; info-vq = vq; - if
Re: [PATCHv4 2/2] virtio: refactor find_vqs
On Thu, Aug 27, 2009 at 07:00:34PM +0930, Rusty Russell wrote: On Tue, 25 Aug 2009 09:34:34 pm Michael S. Tsirkin wrote: That's because we didn't do the request_irq's for the per_vector case, because we don't have the names. This is what prevented me from doing a nice encapsulation. Yes. But let's split free_vectors out into free_msix_vectors and free_intx as well? Perhaps. Patch welcome :) Could you put the end result somewhere so I can work on top of it? Yes, I agree, this is good cleanup, structure field names should be desriptive. Are you sure we want to make all local variables named vector renamed to msix_vector though? CodingStyle says local var names should be short ... A couple of ideas below. msix_vec would work. Yes, ok. But vector for something which isn't always the vector is misleading, IMHO. I think you mean it's isn't always used? It's always a vector ... - if (vector != VIRTIO_MSI_NO_VECTOR) { - iowrite16(vector, vp_dev-ioaddr + VIRTIO_MSI_QUEUE_VECTOR); - vector = ioread16(vp_dev-ioaddr + VIRTIO_MSI_QUEUE_VECTOR); - if (vector == VIRTIO_MSI_NO_VECTOR) { + if (msix_vector != VIRTIO_MSI_NO_VECTOR) { + iowrite16(msix_vector, vp_dev-ioaddr+VIRTIO_MSI_QUEUE_VECTOR); + msix_vector = ioread16(vp_dev-ioaddr+VIRTIO_MSI_QUEUE_VECTOR); checkpatch will complain that space is lacking around +. We won't have a problem if we keep it named vector. Yeah, but OTOH ignoring checkpatch warnings is good for the soul. if (!use_msix) { /* Old style: one normal interrupt for change and all vqs. */ vp_dev-msix_vectors = 0; - vp_dev-per_vq_vectors = false; I know it's enough to look at msix_vectors, but isn't it cleaner to have per_vq_vectors consistent as well? E.g. del_vqs seems to only look at per_vq_vectors. This should in fact be: if (!use_msix) { /* Old style: one normal interrupt for change and all vqs. */ - vp_dev-msix_vectors = 0; - vp_dev-per_vq_vectors = false; err = request_irq(vp_dev-pci_dev-irq, vp_interrupt, IRQF_SHARED, dev_name(vdev-dev), vp_dev); - if (!err) - vp_dev-intx_enabled = 1; - return err; + if (err) + return err; + vp_dev-intx_enabled = 1; The msix fields should all be ignored if msix_enabled is false. Need to audit code to make sure it's so then. I actually think per_vq_vectors is kind of not directly tied to msix. Don't you think it's nicer like del_vqs does: if (vp_dev-per_vq_vectors) { } Than if (vp_dev-msix_enabled vp_dev-per_vq_vectors) { } BTW, let's get rid of msix_enabled completely? We can always use msix_vectors ... Think about running valgrind (or equiv) over the code: if you initialize something which shouldn't be accessed, valgrind won't spot it. For similar reasons, I dislike memseting structs to 0, or kzallocing them. Yes, I agree generally. err = request_irq(vp_dev-pci_dev-irq, vp_interrupt, IRQF_SHARED, dev_name(vdev-dev), vp_dev); - if (!err) - vp_dev-intx_enabled = 1; - return err; + if (err) + return err; Maybe move this part out into a separate function? This way vp_try_to_find_vqs does high-level processing. Nice. Moved this to vp_request_intx(). + } else { + if (per_vq_vectors) { + /* Best option: one for change interrupt, one per vq. */ + nvectors = 1; + for (i = 0; i nvqs; ++i) + if (callbacks[i]) + ++nvectors; + } else { + /* Second best: one for change, shared for all vqs. */ + nvectors = 2; Out of curiosity: why do you put {} here? They aren't strictly necessary ... Comment made it multiline, looked a bit neater? Here's the diff result: Looks good to me. When we are done with cleanups, need to remember to test this with all the possible combinations: no msix, 2 vectors, 1 vector. diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -346,10 +346,22 @@ error: return err; } +static int vp_request_intx(struct virtio_device *vdev) +{ + int err; + struct virtio_pci_device *vp_dev = to_vp_device(vdev); + + err = request_irq(vp_dev-pci_dev-irq, vp_interrupt, + IRQF_SHARED, dev_name(vdev-dev), vp_dev); + if (!err) + vp_dev-intx_enabled = 1; + return err; +} + static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, void (*callback)(struct
Re: [PATCHv4 2/2] virtio: refactor find_vqs
On Thu, 27 Aug 2009 07:19:26 pm Michael S. Tsirkin wrote: On Thu, Aug 27, 2009 at 07:00:34PM +0930, Rusty Russell wrote: On Tue, 25 Aug 2009 09:34:34 pm Michael S. Tsirkin wrote: That's because we didn't do the request_irq's for the per_vector case, because we don't have the names. This is what prevented me from doing a nice encapsulation. Yes. But let's split free_vectors out into free_msix_vectors and free_intx as well? Perhaps. Patch welcome :) Could you put the end result somewhere so I can work on top of it? Sure, it'll hit linux-next tomorrow, otherwise you can steal from http://ozlabs.org/~rusty/kernel/rr-latest (virtio:pci-minor-cleanups.patch and virtio:pci-minor-cleanups-fix.patch). But vector for something which isn't always the vector is misleading, IMHO. I think you mean it's isn't always used? It's always a vector ... The non-MSI case, it's set to VIRTIO_MSI_NO_VECTOR, and we use a normal interrupt vector. BTW, let's get rid of msix_enabled completely? We can always use msix_vectors ... That would be nice. But yes, requiring more audit. Ideally, if msix_vectors == 0, implies intx_enabled. Thanks, Rusty. -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv4 2/2] virtio: refactor find_vqs
On Thu, Aug 27, 2009 at 08:32:24PM +0930, Rusty Russell wrote: On Thu, 27 Aug 2009 07:19:26 pm Michael S. Tsirkin wrote: On Thu, Aug 27, 2009 at 07:00:34PM +0930, Rusty Russell wrote: On Tue, 25 Aug 2009 09:34:34 pm Michael S. Tsirkin wrote: That's because we didn't do the request_irq's for the per_vector case, because we don't have the names. This is what prevented me from doing a nice encapsulation. Yes. But let's split free_vectors out into free_msix_vectors and free_intx as well? Perhaps. Patch welcome :) Could you put the end result somewhere so I can work on top of it? Sure, it'll hit linux-next tomorrow, otherwise you can steal from http://ozlabs.org/~rusty/kernel/rr-latest (virtio:pci-minor-cleanups.patch and virtio:pci-minor-cleanups-fix.patch). But vector for something which isn't always the vector is misleading, IMHO. I think you mean it's isn't always used? It's always a vector ... The non-MSI case, it's set to VIRTIO_MSI_NO_VECTOR, and we use a normal interrupt vector. BTW, let's get rid of msix_enabled completely? We can always use msix_vectors ... That would be nice. But yes, requiring more audit. Ideally, if msix_vectors == 0, implies intx_enabled. It seems that since we *can* request both an intx and msix vectors, it's better to have them independent even if we currently don't do that. No? Thanks, Rusty. -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv4 2/2] virtio: refactor find_vqs
Sorry it took a bit to respond to this. I kept hoping I'll have time to test it but looks like I won't before I'm on vacation. I agree it's good cleanup, and maybe we can go even further, see below. On Mon, Aug 10, 2009 at 09:07:52AM +0930, Rusty Russell wrote: On Tue, 28 Jul 2009 06:03:08 pm Michael S. Tsirkin wrote: On Tue, Jul 28, 2009 at 12:44:31PM +0930, Rusty Russell wrote: On Mon, 27 Jul 2009 01:17:09 am Michael S. Tsirkin wrote: This refactors find_vqs, making it more readable and robust, and fixing two regressions from 2.6.30: - double free_irq causing BUG_ON on device removal - probe failure when vq can't be assigned to msi-x vector (reported on old host kernels) An older version of this patch was tested by Amit Shah. OK, I've applied both of these; I'd like to see a new test by Amit to make sure tho. I really like this cleanup! I looked harder at this code, and my best attempts to untangle it further came to very little. This is what I ended up with, but it's all cosmetic and can wait until next merge window. See what you think. Thanks! Rusty. virtio_pci: minor MSI-X cleanups 1) Rename vp_request_vectors to vp_request_msix_vectors, and take non-MSI-X case out to caller. I'm not sure this change was for the best: we still have a separate code path under if !use_msix, only in another place now. See below. And this seems to break the symmetry between request_ and free_vectors. Yes, but unfortunately request_vectors was never really symmetrical :( That's because we didn't do the request_irq's for the per_vector case, because we don't have the names. This is what prevented me from doing a nice encapsulation. Yes. But let's split free_vectors out into free_msix_vectors and free_intx as well? - err = vp_request_vectors(vdev, nvectors, per_vq_vectors); + if (!use_msix) { + /* Old style: one normal interrupt for change and all vqs. */ + vp_dev-msix_vectors = 0; + vp_dev-per_vq_vectors = false; + err = request_irq(vp_dev-pci_dev-irq, vp_interrupt, + IRQF_SHARED, dev_name(vdev-dev), vp_dev); + if (!err) + vp_dev-intx_enabled = 1; shorter as vp_dev-intx_enabled = !err + return err; Is that all? Don't we need to create the vqs? Oh, yeah :) This patch applies on top. Basically reverts that part, and renames vector to msix_vector, which I think makes the code more readable. Yes, I agree, this is good cleanup, structure field names should be desriptive. Are you sure we want to make all local variables named vector renamed to msix_vector though? CodingStyle says local var names should be short ... A couple of ideas below. virtio: more PCI minor cleanups Signed-off-by: Rusty Russell ru...@rustcorp.com.au --- drivers/virtio/virtio_pci.c | 73 +--- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -84,7 +84,7 @@ struct virtio_pci_vq_info struct list_head node; /* MSI-X vector (or none) */ - unsigned vector; + unsigned msix_vector; Good. And now we don't need the comment. }; /* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */ @@ -349,7 +349,7 @@ error: static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, void (*callback)(struct virtqueue *vq), const char *name, - u16 vector) + u16 msix_vector) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); struct virtio_pci_vq_info *info; @@ -374,7 +374,7 @@ static struct virtqueue *setup_vq(struct info-queue_index = index; info-num = num; - info-vector = vector; + info-msix_vector = msix_vector; size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN)); info-queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO); @@ -398,10 +398,10 @@ static struct virtqueue *setup_vq(struct vq-priv = info; info-vq = vq; - if (vector != VIRTIO_MSI_NO_VECTOR) { - iowrite16(vector, vp_dev-ioaddr + VIRTIO_MSI_QUEUE_VECTOR); - vector = ioread16(vp_dev-ioaddr + VIRTIO_MSI_QUEUE_VECTOR); - if (vector == VIRTIO_MSI_NO_VECTOR) { + if (msix_vector != VIRTIO_MSI_NO_VECTOR) { + iowrite16(msix_vector, vp_dev-ioaddr+VIRTIO_MSI_QUEUE_VECTOR); + msix_vector = ioread16(vp_dev-ioaddr+VIRTIO_MSI_QUEUE_VECTOR); checkpatch will complain that space is lacking around +. We won't have a problem if we keep it named vector. + if (msix_vector == VIRTIO_MSI_NO_VECTOR) {
Re: [PATCHv4 2/2] virtio: refactor find_vqs
On Tue, 28 Jul 2009 06:03:08 pm Michael S. Tsirkin wrote: On Tue, Jul 28, 2009 at 12:44:31PM +0930, Rusty Russell wrote: On Mon, 27 Jul 2009 01:17:09 am Michael S. Tsirkin wrote: This refactors find_vqs, making it more readable and robust, and fixing two regressions from 2.6.30: - double free_irq causing BUG_ON on device removal - probe failure when vq can't be assigned to msi-x vector (reported on old host kernels) An older version of this patch was tested by Amit Shah. OK, I've applied both of these; I'd like to see a new test by Amit to make sure tho. I really like this cleanup! I looked harder at this code, and my best attempts to untangle it further came to very little. This is what I ended up with, but it's all cosmetic and can wait until next merge window. See what you think. Thanks! Rusty. virtio_pci: minor MSI-X cleanups 1) Rename vp_request_vectors to vp_request_msix_vectors, and take non-MSI-X case out to caller. I'm not sure this change was for the best: we still have a separate code path under if !use_msix, only in another place now. See below. And this seems to break the symmetry between request_ and free_vectors. Yes, but unfortunately request_vectors was never really symmetrical :( That's because we didn't do the request_irq's for the per_vector case, because we don't have the names. This is what prevented me from doing a nice encapsulation. - err = vp_request_vectors(vdev, nvectors, per_vq_vectors); + if (!use_msix) { + /* Old style: one normal interrupt for change and all vqs. */ + vp_dev-msix_vectors = 0; + vp_dev-per_vq_vectors = false; + err = request_irq(vp_dev-pci_dev-irq, vp_interrupt, + IRQF_SHARED, dev_name(vdev-dev), vp_dev); + if (!err) + vp_dev-intx_enabled = 1; shorter as vp_dev-intx_enabled = !err + return err; Is that all? Don't we need to create the vqs? Oh, yeah :) This patch applies on top. Basically reverts that part, and renames vector to msix_vector, which I think makes the code more readable. virtio: more PCI minor cleanups Signed-off-by: Rusty Russell ru...@rustcorp.com.au --- drivers/virtio/virtio_pci.c | 73 +--- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -84,7 +84,7 @@ struct virtio_pci_vq_info struct list_head node; /* MSI-X vector (or none) */ - unsigned vector; + unsigned msix_vector; }; /* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */ @@ -349,7 +349,7 @@ error: static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, void (*callback)(struct virtqueue *vq), const char *name, - u16 vector) + u16 msix_vector) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); struct virtio_pci_vq_info *info; @@ -374,7 +374,7 @@ static struct virtqueue *setup_vq(struct info-queue_index = index; info-num = num; - info-vector = vector; + info-msix_vector = msix_vector; size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN)); info-queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO); @@ -398,10 +398,10 @@ static struct virtqueue *setup_vq(struct vq-priv = info; info-vq = vq; - if (vector != VIRTIO_MSI_NO_VECTOR) { - iowrite16(vector, vp_dev-ioaddr + VIRTIO_MSI_QUEUE_VECTOR); - vector = ioread16(vp_dev-ioaddr + VIRTIO_MSI_QUEUE_VECTOR); - if (vector == VIRTIO_MSI_NO_VECTOR) { + if (msix_vector != VIRTIO_MSI_NO_VECTOR) { + iowrite16(msix_vector, vp_dev-ioaddr+VIRTIO_MSI_QUEUE_VECTOR); + msix_vector = ioread16(vp_dev-ioaddr+VIRTIO_MSI_QUEUE_VECTOR); + if (msix_vector == VIRTIO_MSI_NO_VECTOR) { err = -EBUSY; goto out_assign; } @@ -462,7 +462,8 @@ static void vp_del_vqs(struct virtio_dev list_for_each_entry_safe(vq, n, vdev-vqs, list) { info = vq-priv; if (vp_dev-per_vq_vectors) - free_irq(vp_dev-msix_entries[info-vector].vector, vq); + free_irq(vp_dev-msix_entries[info-msix_vector].vector, +vq); vp_del_vq(vq); } vp_dev-per_vq_vectors = false; @@ -478,58 +479,56 @@ static int vp_try_to_find_vqs(struct vir bool per_vq_vectors) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); - u16 vector; + u16 msix_vector; int i,
Re: [PATCHv4 2/2] virtio: refactor find_vqs
On Tue, Jul 28, 2009 at 12:44:31PM +0930, Rusty Russell wrote: On Mon, 27 Jul 2009 01:17:09 am Michael S. Tsirkin wrote: This refactors find_vqs, making it more readable and robust, and fixing two regressions from 2.6.30: - double free_irq causing BUG_ON on device removal - probe failure when vq can't be assigned to msi-x vector (reported on old host kernels) An older version of this patch was tested by Amit Shah. OK, I've applied both of these; I'd like to see a new test by Amit to make sure tho. I really like this cleanup! I looked harder at this code, and my best attempts to untangle it further came to very little. This is what I ended up with, but it's all cosmetic and can wait until next merge window. See what you think. Thanks! Rusty. virtio_pci: minor MSI-X cleanups 1) Rename vp_request_vectors to vp_request_msix_vectors, and take non-MSI-X case out to caller. I'm not sure this change was for the best: we still have a separate code path under if !use_msix, only in another place now. See below. And this seems to break the symmetry between request_ and free_vectors. 2) Comment weird pci_enable_msix API 3) Rename vp_find_vq to setup_vq. 4) Fix spaces to tabs 5) Make nvectors calc internal to vp_try_to_find_vqs() The other changes look good to me. Signed-off-by: Rusty Russell ru...@rustcorp.com.au --- drivers/virtio/virtio_pci.c | 84 +++- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -280,25 +280,14 @@ static void vp_free_vectors(struct virti vp_dev-msix_entries = NULL; } -static int vp_request_vectors(struct virtio_device *vdev, int nvectors, - bool per_vq_vectors) +static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, +bool per_vq_vectors) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); const char *name = dev_name(vp_dev-vdev.dev); unsigned i, v; int err = -ENOMEM; - if (!nvectors) { - /* Can't allocate MSI-X vectors, use regular interrupt */ - vp_dev-msix_vectors = 0; - err = request_irq(vp_dev-pci_dev-irq, vp_interrupt, - IRQF_SHARED, name, vp_dev); - if (err) - return err; - vp_dev-intx_enabled = 1; - return 0; - } - vp_dev-msix_entries = kmalloc(nvectors * sizeof *vp_dev-msix_entries, GFP_KERNEL); if (!vp_dev-msix_entries) @@ -311,6 +300,7 @@ static int vp_request_vectors(struct vir for (i = 0; i nvectors; ++i) vp_dev-msix_entries[i].entry = i; + /* pci_enable_msix returns positive if we can't get this many. */ err = pci_enable_msix(vp_dev-pci_dev, vp_dev-msix_entries, nvectors); if (err 0) err = -ENOSPC; @@ -356,10 +346,10 @@ error: return err; } -static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, - void (*callback)(struct virtqueue *vq), - const char *name, - u16 vector) +static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, + void (*callback)(struct virtqueue *vq), + const char *name, + u16 vector) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); struct virtio_pci_vq_info *info; @@ -408,7 +398,7 @@ static struct virtqueue *vp_find_vq(stru vq-priv = info; info-vq = vq; - if (vector != VIRTIO_MSI_NO_VECTOR) { + if (vector != VIRTIO_MSI_NO_VECTOR) { iowrite16(vector, vp_dev-ioaddr + VIRTIO_MSI_QUEUE_VECTOR); vector = ioread16(vp_dev-ioaddr + VIRTIO_MSI_QUEUE_VECTOR); if (vector == VIRTIO_MSI_NO_VECTOR) { @@ -484,14 +474,36 @@ static int vp_try_to_find_vqs(struct vir struct virtqueue *vqs[], vq_callback_t *callbacks[], const char *names[], - int nvectors, + bool use_msix, bool per_vq_vectors) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); u16 vector; - int i, err, allocated_vectors; + int i, err, nvectors, allocated_vectors; - err = vp_request_vectors(vdev, nvectors, per_vq_vectors); + if (!use_msix) { + /* Old style: one normal interrupt for change and all vqs. */ + vp_dev-msix_vectors = 0; + vp_dev-per_vq_vectors = false; + err =
Re: [PATCHv4 2/2] virtio: refactor find_vqs
On (Tue) Jul 28 2009 [12:44:31], Rusty Russell wrote: On Mon, 27 Jul 2009 01:17:09 am Michael S. Tsirkin wrote: This refactors find_vqs, making it more readable and robust, and fixing two regressions from 2.6.30: - double free_irq causing BUG_ON on device removal - probe failure when vq can't be assigned to msi-x vector (reported on old host kernels) An older version of this patch was tested by Amit Shah. OK, I've applied both of these; I'd like to see a new test by Amit to make sure tho. Tested these patches as well. They work fine. Tested-by: Amit Shah amit.s...@redhat.com -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv4 2/2] virtio: refactor find_vqs
On Tue, Jul 28, 2009 at 08:00:52PM +0530, Amit Shah wrote: On (Tue) Jul 28 2009 [12:44:31], Rusty Russell wrote: On Mon, 27 Jul 2009 01:17:09 am Michael S. Tsirkin wrote: This refactors find_vqs, making it more readable and robust, and fixing two regressions from 2.6.30: - double free_irq causing BUG_ON on device removal - probe failure when vq can't be assigned to msi-x vector (reported on old host kernels) An older version of this patch was tested by Amit Shah. OK, I've applied both of these; I'd like to see a new test by Amit to make sure tho. Tested these patches as well. They work fine. Tested-by: Amit Shah amit.s...@redhat.com Amit, thanks very much for the testing. -- MST -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv4 2/2] virtio: refactor find_vqs
On Mon, 27 Jul 2009 01:17:09 am Michael S. Tsirkin wrote: This refactors find_vqs, making it more readable and robust, and fixing two regressions from 2.6.30: - double free_irq causing BUG_ON on device removal - probe failure when vq can't be assigned to msi-x vector (reported on old host kernels) An older version of this patch was tested by Amit Shah. OK, I've applied both of these; I'd like to see a new test by Amit to make sure tho. I really like this cleanup! I looked harder at this code, and my best attempts to untangle it further came to very little. This is what I ended up with, but it's all cosmetic and can wait until next merge window. See what you think. Thanks! Rusty. virtio_pci: minor MSI-X cleanups 1) Rename vp_request_vectors to vp_request_msix_vectors, and take non-MSI-X case out to caller. 2) Comment weird pci_enable_msix API 3) Rename vp_find_vq to setup_vq. 4) Fix spaces to tabs 5) Make nvectors calc internal to vp_try_to_find_vqs() Signed-off-by: Rusty Russell ru...@rustcorp.com.au --- drivers/virtio/virtio_pci.c | 84 +++- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -280,25 +280,14 @@ static void vp_free_vectors(struct virti vp_dev-msix_entries = NULL; } -static int vp_request_vectors(struct virtio_device *vdev, int nvectors, - bool per_vq_vectors) +static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, + bool per_vq_vectors) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); const char *name = dev_name(vp_dev-vdev.dev); unsigned i, v; int err = -ENOMEM; - if (!nvectors) { - /* Can't allocate MSI-X vectors, use regular interrupt */ - vp_dev-msix_vectors = 0; - err = request_irq(vp_dev-pci_dev-irq, vp_interrupt, - IRQF_SHARED, name, vp_dev); - if (err) - return err; - vp_dev-intx_enabled = 1; - return 0; - } - vp_dev-msix_entries = kmalloc(nvectors * sizeof *vp_dev-msix_entries, GFP_KERNEL); if (!vp_dev-msix_entries) @@ -311,6 +300,7 @@ static int vp_request_vectors(struct vir for (i = 0; i nvectors; ++i) vp_dev-msix_entries[i].entry = i; + /* pci_enable_msix returns positive if we can't get this many. */ err = pci_enable_msix(vp_dev-pci_dev, vp_dev-msix_entries, nvectors); if (err 0) err = -ENOSPC; @@ -356,10 +346,10 @@ error: return err; } -static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, - void (*callback)(struct virtqueue *vq), - const char *name, - u16 vector) +static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, + void (*callback)(struct virtqueue *vq), + const char *name, + u16 vector) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); struct virtio_pci_vq_info *info; @@ -408,7 +398,7 @@ static struct virtqueue *vp_find_vq(stru vq-priv = info; info-vq = vq; -if (vector != VIRTIO_MSI_NO_VECTOR) { + if (vector != VIRTIO_MSI_NO_VECTOR) { iowrite16(vector, vp_dev-ioaddr + VIRTIO_MSI_QUEUE_VECTOR); vector = ioread16(vp_dev-ioaddr + VIRTIO_MSI_QUEUE_VECTOR); if (vector == VIRTIO_MSI_NO_VECTOR) { @@ -484,14 +474,36 @@ static int vp_try_to_find_vqs(struct vir struct virtqueue *vqs[], vq_callback_t *callbacks[], const char *names[], - int nvectors, + bool use_msix, bool per_vq_vectors) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); u16 vector; - int i, err, allocated_vectors; + int i, err, nvectors, allocated_vectors; - err = vp_request_vectors(vdev, nvectors, per_vq_vectors); + if (!use_msix) { + /* Old style: one normal interrupt for change and all vqs. */ + vp_dev-msix_vectors = 0; + vp_dev-per_vq_vectors = false; + err = request_irq(vp_dev-pci_dev-irq, vp_interrupt, + IRQF_SHARED, dev_name(vdev-dev), vp_dev); + if (!err) + vp_dev-intx_enabled = 1; + return err; + } + + if (per_vq_vectors) { + /* Best option: one for change
[PATCHv4 2/2] virtio: refactor find_vqs
This refactors find_vqs, making it more readable and robust, and fixing two regressions from 2.6.30: - double free_irq causing BUG_ON on device removal - probe failure when vq can't be assigned to msi-x vector (reported on old host kernels) An older version of this patch was tested by Amit Shah. Reported-by: Amit Shah amit.s...@redhat.com Signed-off-by: Michael S. Tsirkin m...@redhat.com --- drivers/virtio/virtio_pci.c | 212 --- 1 files changed, 119 insertions(+), 93 deletions(-) diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 4c74c72..c17b830 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -52,8 +52,10 @@ struct virtio_pci_device char (*msix_names)[256]; /* Number of available vectors */ unsigned msix_vectors; - /* Vectors allocated */ + /* Vectors allocated, excluding per-vq vectors if any */ unsigned msix_used_vectors; + /* Whether we have vector per vq */ + bool per_vq_vectors; }; /* Constants for MSI-X */ @@ -278,27 +280,24 @@ static void vp_free_vectors(struct virtio_device *vdev) vp_dev-msix_entries = NULL; } -static int vp_enable_msix(struct pci_dev *dev, struct msix_entry *entries, - int *options, int noptions) -{ - int i; - for (i = 0; i noptions; ++i) - if (!pci_enable_msix(dev, entries, options[i])) - return options[i]; - return -EBUSY; -} - -static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs) +static int vp_request_vectors(struct virtio_device *vdev, int nvectors, + bool per_vq_vectors) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); const char *name = dev_name(vp_dev-vdev.dev); unsigned i, v; int err = -ENOMEM; - /* We want at most one vector per queue and one for config changes. -* Fallback to separate vectors for config and a shared for queues. -* Finally fall back to regular interrupts. */ - int options[] = { max_vqs + 1, 2 }; - int nvectors = max(options[0], options[1]); + + if (!nvectors) { + /* Can't allocate MSI-X vectors, use regular interrupt */ + vp_dev-msix_vectors = 0; + err = request_irq(vp_dev-pci_dev-irq, vp_interrupt, + IRQF_SHARED, name, vp_dev); + if (err) + return err; + vp_dev-intx_enabled = 1; + return 0; + } vp_dev-msix_entries = kmalloc(nvectors * sizeof *vp_dev-msix_entries, GFP_KERNEL); @@ -312,41 +311,34 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs) for (i = 0; i nvectors; ++i) vp_dev-msix_entries[i].entry = i; - err = vp_enable_msix(vp_dev-pci_dev, vp_dev-msix_entries, -options, ARRAY_SIZE(options)); - if (err 0) { - /* Can't allocate enough MSI-X vectors, use regular interrupt */ - vp_dev-msix_vectors = 0; - err = request_irq(vp_dev-pci_dev-irq, vp_interrupt, - IRQF_SHARED, name, vp_dev); - if (err) - goto error; - vp_dev-intx_enabled = 1; - } else { - vp_dev-msix_vectors = err; - vp_dev-msix_enabled = 1; - - /* Set the vector used for configuration */ - v = vp_dev-msix_used_vectors; - snprintf(vp_dev-msix_names[v], sizeof *vp_dev-msix_names, -%s-config, name); - err = request_irq(vp_dev-msix_entries[v].vector, - vp_config_changed, 0, vp_dev-msix_names[v], - vp_dev); - if (err) - goto error; - ++vp_dev-msix_used_vectors; + err = pci_enable_msix(vp_dev-pci_dev, vp_dev-msix_entries, nvectors); + if (err 0) + err = -ENOSPC; + if (err) + goto error; + vp_dev-msix_vectors = nvectors; + vp_dev-msix_enabled = 1; + + /* Set the vector used for configuration */ + v = vp_dev-msix_used_vectors; + snprintf(vp_dev-msix_names[v], sizeof *vp_dev-msix_names, +%s-config, name); + err = request_irq(vp_dev-msix_entries[v].vector, + vp_config_changed, 0, vp_dev-msix_names[v], + vp_dev); + if (err) + goto error; + ++vp_dev-msix_used_vectors; - iowrite16(v, vp_dev-ioaddr + VIRTIO_MSI_CONFIG_VECTOR); - /* Verify we had enough resources to assign the vector */ - v = ioread16(vp_dev-ioaddr + VIRTIO_MSI_CONFIG_VECTOR); - if (v ==