diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 12:23:45 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 12:23:45 -0400 |
| commit | 1f0918d03ff4b5c94540c71ce889672abdbc2f4a (patch) | |
| tree | ecee710444fb3405da55933501e339e10e4ac880 /drivers | |
| parent | 4266c97a3ef4604561a22212eb0eab8a3c338971 (diff) | |
| parent | ca60a42c9be41c07ebcc2ec8c43dd1be53f147bf (diff) | |
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: don't force VIRTIO_F_NOTIFY_ON_EMPTY
lguest: cleanup for map_switcher()
lguest: use PGDIR_SHIFT for PAE code to allow different PAGE_OFFSET
lguest: use set_pte/set_pmd uniformly for real page table entries
lguest: move panic notifier registration to its expected place.
virtio_blk: add support for cache flush
virtio: add virtio IDs file
virtio: get rid of redundant VIRTIO_ID_9P definition
virtio: make add_buf return capacity remaining
virtio_pci: minor MSI-X cleanups
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/block/virtio_blk.c | 33 | ||||
| -rw-r--r-- | drivers/char/hw_random/virtio-rng.c | 3 | ||||
| -rw-r--r-- | drivers/char/virtio_console.c | 5 | ||||
| -rw-r--r-- | drivers/lguest/core.c | 5 | ||||
| -rw-r--r-- | drivers/lguest/page_tables.c | 45 | ||||
| -rw-r--r-- | drivers/net/virtio_net.c | 15 | ||||
| -rw-r--r-- | drivers/virtio/virtio_balloon.c | 3 | ||||
| -rw-r--r-- | drivers/virtio/virtio_pci.c | 125 | ||||
| -rw-r--r-- | drivers/virtio/virtio_ring.c | 6 |
9 files changed, 138 insertions, 102 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index aa89fe45237d..43f19389647a 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | #include <linux/blkdev.h> | 3 | #include <linux/blkdev.h> |
| 4 | #include <linux/hdreg.h> | 4 | #include <linux/hdreg.h> |
| 5 | #include <linux/virtio.h> | 5 | #include <linux/virtio.h> |
| 6 | #include <linux/virtio_ids.h> | ||
| 6 | #include <linux/virtio_blk.h> | 7 | #include <linux/virtio_blk.h> |
| 7 | #include <linux/scatterlist.h> | 8 | #include <linux/scatterlist.h> |
| 8 | 9 | ||
| @@ -91,15 +92,26 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
| 91 | return false; | 92 | return false; |
| 92 | 93 | ||
| 93 | vbr->req = req; | 94 | vbr->req = req; |
| 94 | if (blk_fs_request(vbr->req)) { | 95 | switch (req->cmd_type) { |
| 96 | case REQ_TYPE_FS: | ||
| 95 | vbr->out_hdr.type = 0; | 97 | vbr->out_hdr.type = 0; |
| 96 | vbr->out_hdr.sector = blk_rq_pos(vbr->req); | 98 | vbr->out_hdr.sector = blk_rq_pos(vbr->req); |
| 97 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | 99 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); |
| 98 | } else if (blk_pc_request(vbr->req)) { | 100 | break; |
| 101 | case REQ_TYPE_BLOCK_PC: | ||
| 99 | vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; | 102 | vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; |
| 100 | vbr->out_hdr.sector = 0; | 103 | vbr->out_hdr.sector = 0; |
| 101 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | 104 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); |
| 102 | } else { | 105 | break; |
| 106 | case REQ_TYPE_LINUX_BLOCK: | ||
| 107 | if (req->cmd[0] == REQ_LB_OP_FLUSH) { | ||
| 108 | vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH; | ||
| 109 | vbr->out_hdr.sector = 0; | ||
| 110 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | ||
| 111 | break; | ||
| 112 | } | ||
| 113 | /*FALLTHRU*/ | ||
| 114 | default: | ||
| 103 | /* We don't put anything else in the queue. */ | 115 | /* We don't put anything else in the queue. */ |
| 104 | BUG(); | 116 | BUG(); |
| 105 | } | 117 | } |
| @@ -139,7 +151,7 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
| 139 | } | 151 | } |
| 140 | } | 152 | } |
| 141 | 153 | ||
| 142 | if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr)) { | 154 | if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr) < 0) { |
| 143 | mempool_free(vbr, vblk->pool); | 155 | mempool_free(vbr, vblk->pool); |
| 144 | return false; | 156 | return false; |
| 145 | } | 157 | } |
| @@ -199,6 +211,12 @@ out: | |||
| 199 | return err; | 211 | return err; |
| 200 | } | 212 | } |
| 201 | 213 | ||
| 214 | static void virtblk_prepare_flush(struct request_queue *q, struct request *req) | ||
| 215 | { | ||
| 216 | req->cmd_type = REQ_TYPE_LINUX_BLOCK; | ||
| 217 | req->cmd[0] = REQ_LB_OP_FLUSH; | ||
| 218 | } | ||
| 219 | |||
| 202 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, | 220 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, |
| 203 | unsigned cmd, unsigned long data) | 221 | unsigned cmd, unsigned long data) |
| 204 | { | 222 | { |
| @@ -337,7 +355,10 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
| 337 | index++; | 355 | index++; |
| 338 | 356 | ||
| 339 | /* If barriers are supported, tell block layer that queue is ordered */ | 357 | /* If barriers are supported, tell block layer that queue is ordered */ |
| 340 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) | 358 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) |
| 359 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_DRAIN_FLUSH, | ||
| 360 | virtblk_prepare_flush); | ||
| 361 | else if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) | ||
| 341 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); | 362 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); |
| 342 | 363 | ||
| 343 | /* If disk is read-only in the host, the guest should obey */ | 364 | /* If disk is read-only in the host, the guest should obey */ |
| @@ -424,7 +445,7 @@ static struct virtio_device_id id_table[] = { | |||
| 424 | static unsigned int features[] = { | 445 | static unsigned int features[] = { |
| 425 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, | 446 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, |
| 426 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, | 447 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, |
| 427 | VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY | 448 | VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY, VIRTIO_BLK_F_FLUSH |
| 428 | }; | 449 | }; |
| 429 | 450 | ||
| 430 | /* | 451 | /* |
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 32216b623248..962968f05b94 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/scatterlist.h> | 21 | #include <linux/scatterlist.h> |
| 22 | #include <linux/spinlock.h> | 22 | #include <linux/spinlock.h> |
| 23 | #include <linux/virtio.h> | 23 | #include <linux/virtio.h> |
| 24 | #include <linux/virtio_ids.h> | ||
| 24 | #include <linux/virtio_rng.h> | 25 | #include <linux/virtio_rng.h> |
| 25 | 26 | ||
| 26 | /* The host will fill any buffer we give it with sweet, sweet randomness. We | 27 | /* The host will fill any buffer we give it with sweet, sweet randomness. We |
| @@ -51,7 +52,7 @@ static void register_buffer(void) | |||
| 51 | 52 | ||
| 52 | sg_init_one(&sg, random_data+data_left, RANDOM_DATA_SIZE-data_left); | 53 | sg_init_one(&sg, random_data+data_left, RANDOM_DATA_SIZE-data_left); |
| 53 | /* There should always be room for one buffer. */ | 54 | /* There should always be room for one buffer. */ |
| 54 | if (vq->vq_ops->add_buf(vq, &sg, 0, 1, random_data) != 0) | 55 | if (vq->vq_ops->add_buf(vq, &sg, 0, 1, random_data) < 0) |
| 55 | BUG(); | 56 | BUG(); |
| 56 | vq->vq_ops->kick(vq); | 57 | vq->vq_ops->kick(vq); |
| 57 | } | 58 | } |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index c74dacfa6795..0d328b59568d 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/err.h> | 31 | #include <linux/err.h> |
| 32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
| 33 | #include <linux/virtio.h> | 33 | #include <linux/virtio.h> |
| 34 | #include <linux/virtio_ids.h> | ||
| 34 | #include <linux/virtio_console.h> | 35 | #include <linux/virtio_console.h> |
| 35 | #include "hvc_console.h" | 36 | #include "hvc_console.h" |
| 36 | 37 | ||
| @@ -65,7 +66,7 @@ static int put_chars(u32 vtermno, const char *buf, int count) | |||
| 65 | 66 | ||
| 66 | /* add_buf wants a token to identify this buffer: we hand it any | 67 | /* add_buf wants a token to identify this buffer: we hand it any |
| 67 | * non-NULL pointer, since there's only ever one buffer. */ | 68 | * non-NULL pointer, since there's only ever one buffer. */ |
| 68 | if (out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, (void *)1) == 0) { | 69 | if (out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, (void *)1) >= 0) { |
| 69 | /* Tell Host to go! */ | 70 | /* Tell Host to go! */ |
| 70 | out_vq->vq_ops->kick(out_vq); | 71 | out_vq->vq_ops->kick(out_vq); |
| 71 | /* Chill out until it's done with the buffer. */ | 72 | /* Chill out until it's done with the buffer. */ |
| @@ -85,7 +86,7 @@ static void add_inbuf(void) | |||
| 85 | sg_init_one(sg, inbuf, PAGE_SIZE); | 86 | sg_init_one(sg, inbuf, PAGE_SIZE); |
| 86 | 87 | ||
| 87 | /* We should always be able to add one buffer to an empty queue. */ | 88 | /* We should always be able to add one buffer to an empty queue. */ |
| 88 | if (in_vq->vq_ops->add_buf(in_vq, sg, 0, 1, inbuf) != 0) | 89 | if (in_vq->vq_ops->add_buf(in_vq, sg, 0, 1, inbuf) < 0) |
| 89 | BUG(); | 90 | BUG(); |
| 90 | in_vq->vq_ops->kick(in_vq); | 91 | in_vq->vq_ops->kick(in_vq); |
| 91 | } | 92 | } |
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c index 1e2cb846b3c9..8744d24ac6e6 100644 --- a/drivers/lguest/core.c +++ b/drivers/lguest/core.c | |||
| @@ -67,12 +67,11 @@ static __init int map_switcher(void) | |||
| 67 | * so we make sure they're zeroed. | 67 | * so we make sure they're zeroed. |
| 68 | */ | 68 | */ |
| 69 | for (i = 0; i < TOTAL_SWITCHER_PAGES; i++) { | 69 | for (i = 0; i < TOTAL_SWITCHER_PAGES; i++) { |
| 70 | unsigned long addr = get_zeroed_page(GFP_KERNEL); | 70 | switcher_page[i] = alloc_page(GFP_KERNEL|__GFP_ZERO); |
| 71 | if (!addr) { | 71 | if (!switcher_page[i]) { |
| 72 | err = -ENOMEM; | 72 | err = -ENOMEM; |
| 73 | goto free_some_pages; | 73 | goto free_some_pages; |
| 74 | } | 74 | } |
| 75 | switcher_page[i] = virt_to_page(addr); | ||
| 76 | } | 75 | } |
| 77 | 76 | ||
| 78 | /* | 77 | /* |
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index 8aaad65c3bb5..cf94326f1b59 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c | |||
| @@ -380,7 +380,7 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode) | |||
| 380 | * And we copy the flags to the shadow PMD entry. The page | 380 | * And we copy the flags to the shadow PMD entry. The page |
| 381 | * number in the shadow PMD is the page we just allocated. | 381 | * number in the shadow PMD is the page we just allocated. |
| 382 | */ | 382 | */ |
| 383 | native_set_pmd(spmd, __pmd(__pa(ptepage) | pmd_flags(gpmd))); | 383 | set_pmd(spmd, __pmd(__pa(ptepage) | pmd_flags(gpmd))); |
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | /* | 386 | /* |
| @@ -447,7 +447,7 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode) | |||
| 447 | * we will come back here when a write does actually occur, so | 447 | * we will come back here when a write does actually occur, so |
| 448 | * we can update the Guest's _PAGE_DIRTY flag. | 448 | * we can update the Guest's _PAGE_DIRTY flag. |
| 449 | */ | 449 | */ |
| 450 | native_set_pte(spte, gpte_to_spte(cpu, pte_wrprotect(gpte), 0)); | 450 | set_pte(spte, gpte_to_spte(cpu, pte_wrprotect(gpte), 0)); |
| 451 | 451 | ||
| 452 | /* | 452 | /* |
| 453 | * Finally, we write the Guest PTE entry back: we've set the | 453 | * Finally, we write the Guest PTE entry back: we've set the |
| @@ -528,7 +528,7 @@ static void release_pmd(pmd_t *spmd) | |||
| 528 | /* Now we can free the page of PTEs */ | 528 | /* Now we can free the page of PTEs */ |
| 529 | free_page((long)ptepage); | 529 | free_page((long)ptepage); |
| 530 | /* And zero out the PMD entry so we never release it twice. */ | 530 | /* And zero out the PMD entry so we never release it twice. */ |
| 531 | native_set_pmd(spmd, __pmd(0)); | 531 | set_pmd(spmd, __pmd(0)); |
| 532 | } | 532 | } |
| 533 | } | 533 | } |
| 534 | 534 | ||
| @@ -833,15 +833,15 @@ static void do_set_pte(struct lg_cpu *cpu, int idx, | |||
| 833 | */ | 833 | */ |
| 834 | if (pte_flags(gpte) & (_PAGE_DIRTY | _PAGE_ACCESSED)) { | 834 | if (pte_flags(gpte) & (_PAGE_DIRTY | _PAGE_ACCESSED)) { |
| 835 | check_gpte(cpu, gpte); | 835 | check_gpte(cpu, gpte); |
| 836 | native_set_pte(spte, | 836 | set_pte(spte, |
| 837 | gpte_to_spte(cpu, gpte, | 837 | gpte_to_spte(cpu, gpte, |
| 838 | pte_flags(gpte) & _PAGE_DIRTY)); | 838 | pte_flags(gpte) & _PAGE_DIRTY)); |
| 839 | } else { | 839 | } else { |
| 840 | /* | 840 | /* |
| 841 | * Otherwise kill it and we can demand_page() | 841 | * Otherwise kill it and we can demand_page() |
| 842 | * it in later. | 842 | * it in later. |
| 843 | */ | 843 | */ |
| 844 | native_set_pte(spte, __pte(0)); | 844 | set_pte(spte, __pte(0)); |
| 845 | } | 845 | } |
| 846 | #ifdef CONFIG_X86_PAE | 846 | #ifdef CONFIG_X86_PAE |
| 847 | } | 847 | } |
| @@ -983,25 +983,22 @@ static unsigned long setup_pagetables(struct lguest *lg, | |||
| 983 | */ | 983 | */ |
| 984 | for (i = j = 0; i < mapped_pages && j < PTRS_PER_PMD; | 984 | for (i = j = 0; i < mapped_pages && j < PTRS_PER_PMD; |
| 985 | i += PTRS_PER_PTE, j++) { | 985 | i += PTRS_PER_PTE, j++) { |
| 986 | /* FIXME: native_set_pmd is overkill here. */ | 986 | pmd = pfn_pmd(((unsigned long)&linear[i] - mem_base)/PAGE_SIZE, |
| 987 | native_set_pmd(&pmd, __pmd(((unsigned long)(linear + i) | 987 | __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER)); |
| 988 | - mem_base) | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER)); | ||
| 989 | 988 | ||
| 990 | if (copy_to_user(&pmds[j], &pmd, sizeof(pmd)) != 0) | 989 | if (copy_to_user(&pmds[j], &pmd, sizeof(pmd)) != 0) |
| 991 | return -EFAULT; | 990 | return -EFAULT; |
| 992 | } | 991 | } |
| 993 | 992 | ||
| 994 | /* One PGD entry, pointing to that PMD page. */ | 993 | /* One PGD entry, pointing to that PMD page. */ |
| 995 | set_pgd(&pgd, __pgd(((u32)pmds - mem_base) | _PAGE_PRESENT)); | 994 | pgd = __pgd(((unsigned long)pmds - mem_base) | _PAGE_PRESENT); |
| 996 | /* Copy it in as the first PGD entry (ie. addresses 0-1G). */ | 995 | /* Copy it in as the first PGD entry (ie. addresses 0-1G). */ |
| 997 | if (copy_to_user(&pgdir[0], &pgd, sizeof(pgd)) != 0) | 996 | if (copy_to_user(&pgdir[0], &pgd, sizeof(pgd)) != 0) |
| 998 | return -EFAULT; | 997 | return -EFAULT; |
| 999 | /* | 998 | /* |
| 1000 | * And the third PGD entry (ie. addresses 3G-4G). | 999 | * And the other PGD entry to make the linear mapping at PAGE_OFFSET |
| 1001 | * | ||
| 1002 | * FIXME: This assumes that PAGE_OFFSET for the Guest is 0xC0000000. | ||
| 1003 | */ | 1000 | */ |
| 1004 | if (copy_to_user(&pgdir[3], &pgd, sizeof(pgd)) != 0) | 1001 | if (copy_to_user(&pgdir[KERNEL_PGD_BOUNDARY], &pgd, sizeof(pgd))) |
| 1005 | return -EFAULT; | 1002 | return -EFAULT; |
| 1006 | #else | 1003 | #else |
| 1007 | /* | 1004 | /* |
| @@ -1141,15 +1138,13 @@ void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages) | |||
| 1141 | { | 1138 | { |
| 1142 | pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages); | 1139 | pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages); |
| 1143 | pte_t regs_pte; | 1140 | pte_t regs_pte; |
| 1144 | unsigned long pfn; | ||
| 1145 | 1141 | ||
| 1146 | #ifdef CONFIG_X86_PAE | 1142 | #ifdef CONFIG_X86_PAE |
| 1147 | pmd_t switcher_pmd; | 1143 | pmd_t switcher_pmd; |
| 1148 | pmd_t *pmd_table; | 1144 | pmd_t *pmd_table; |
| 1149 | 1145 | ||
| 1150 | /* FIXME: native_set_pmd is overkill here. */ | 1146 | switcher_pmd = pfn_pmd(__pa(switcher_pte_page) >> PAGE_SHIFT, |
| 1151 | native_set_pmd(&switcher_pmd, pfn_pmd(__pa(switcher_pte_page) >> | 1147 | PAGE_KERNEL_EXEC); |
| 1152 | PAGE_SHIFT, PAGE_KERNEL_EXEC)); | ||
| 1153 | 1148 | ||
| 1154 | /* Figure out where the pmd page is, by reading the PGD, and converting | 1149 | /* Figure out where the pmd page is, by reading the PGD, and converting |
| 1155 | * it to a virtual address. */ | 1150 | * it to a virtual address. */ |
| @@ -1157,7 +1152,7 @@ void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages) | |||
| 1157 | pgdirs[cpu->cpu_pgd].pgdir[SWITCHER_PGD_INDEX]) | 1152 | pgdirs[cpu->cpu_pgd].pgdir[SWITCHER_PGD_INDEX]) |
| 1158 | << PAGE_SHIFT); | 1153 | << PAGE_SHIFT); |
| 1159 | /* Now write it into the shadow page table. */ | 1154 | /* Now write it into the shadow page table. */ |
| 1160 | native_set_pmd(&pmd_table[SWITCHER_PMD_INDEX], switcher_pmd); | 1155 | set_pmd(&pmd_table[SWITCHER_PMD_INDEX], switcher_pmd); |
| 1161 | #else | 1156 | #else |
| 1162 | pgd_t switcher_pgd; | 1157 | pgd_t switcher_pgd; |
| 1163 | 1158 | ||
| @@ -1179,10 +1174,8 @@ void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages) | |||
| 1179 | * page is already mapped there, we don't have to copy them out | 1174 | * page is already mapped there, we don't have to copy them out |
| 1180 | * again. | 1175 | * again. |
| 1181 | */ | 1176 | */ |
| 1182 | pfn = __pa(cpu->regs_page) >> PAGE_SHIFT; | 1177 | regs_pte = pfn_pte(__pa(cpu->regs_page) >> PAGE_SHIFT, PAGE_KERNEL); |
| 1183 | native_set_pte(®s_pte, pfn_pte(pfn, PAGE_KERNEL)); | 1178 | set_pte(&switcher_pte_page[pte_index((unsigned long)pages)], regs_pte); |
| 1184 | native_set_pte(&switcher_pte_page[pte_index((unsigned long)pages)], | ||
| 1185 | regs_pte); | ||
| 1186 | } | 1179 | } |
| 1187 | /*:*/ | 1180 | /*:*/ |
| 1188 | 1181 | ||
| @@ -1209,7 +1202,7 @@ static __init void populate_switcher_pte_page(unsigned int cpu, | |||
| 1209 | 1202 | ||
| 1210 | /* The first entries are easy: they map the Switcher code. */ | 1203 | /* The first entries are easy: they map the Switcher code. */ |
| 1211 | for (i = 0; i < pages; i++) { | 1204 | for (i = 0; i < pages; i++) { |
| 1212 | native_set_pte(&pte[i], mk_pte(switcher_page[i], | 1205 | set_pte(&pte[i], mk_pte(switcher_page[i], |
| 1213 | __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED))); | 1206 | __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED))); |
| 1214 | } | 1207 | } |
| 1215 | 1208 | ||
| @@ -1217,14 +1210,14 @@ static __init void populate_switcher_pte_page(unsigned int cpu, | |||
| 1217 | i = pages + cpu*2; | 1210 | i = pages + cpu*2; |
| 1218 | 1211 | ||
| 1219 | /* First page (Guest registers) is writable from the Guest */ | 1212 | /* First page (Guest registers) is writable from the Guest */ |
| 1220 | native_set_pte(&pte[i], pfn_pte(page_to_pfn(switcher_page[i]), | 1213 | set_pte(&pte[i], pfn_pte(page_to_pfn(switcher_page[i]), |
| 1221 | __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_RW))); | 1214 | __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_RW))); |
| 1222 | 1215 | ||
| 1223 | /* | 1216 | /* |
| 1224 | * The second page contains the "struct lguest_ro_state", and is | 1217 | * The second page contains the "struct lguest_ro_state", and is |
| 1225 | * read-only. | 1218 | * read-only. |
| 1226 | */ | 1219 | */ |
| 1227 | native_set_pte(&pte[i+1], pfn_pte(page_to_pfn(switcher_page[i+1]), | 1220 | set_pte(&pte[i+1], pfn_pte(page_to_pfn(switcher_page[i+1]), |
| 1228 | __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED))); | 1221 | __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED))); |
| 1229 | } | 1222 | } |
| 1230 | 1223 | ||
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 32266fb89c20..5c498d2b043f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/ethtool.h> | 22 | #include <linux/ethtool.h> |
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/virtio.h> | 24 | #include <linux/virtio.h> |
| 25 | #include <linux/virtio_ids.h> | ||
| 25 | #include <linux/virtio_net.h> | 26 | #include <linux/virtio_net.h> |
| 26 | #include <linux/scatterlist.h> | 27 | #include <linux/scatterlist.h> |
| 27 | #include <linux/if_vlan.h> | 28 | #include <linux/if_vlan.h> |
| @@ -320,7 +321,7 @@ static bool try_fill_recv_maxbufs(struct virtnet_info *vi, gfp_t gfp) | |||
| 320 | skb_queue_head(&vi->recv, skb); | 321 | skb_queue_head(&vi->recv, skb); |
| 321 | 322 | ||
| 322 | err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, num, skb); | 323 | err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, num, skb); |
| 323 | if (err) { | 324 | if (err < 0) { |
| 324 | skb_unlink(skb, &vi->recv); | 325 | skb_unlink(skb, &vi->recv); |
| 325 | trim_pages(vi, skb); | 326 | trim_pages(vi, skb); |
| 326 | kfree_skb(skb); | 327 | kfree_skb(skb); |
| @@ -373,7 +374,7 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp) | |||
| 373 | skb_queue_head(&vi->recv, skb); | 374 | skb_queue_head(&vi->recv, skb); |
| 374 | 375 | ||
| 375 | err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, 1, skb); | 376 | err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, 1, skb); |
| 376 | if (err) { | 377 | if (err < 0) { |
| 377 | skb_unlink(skb, &vi->recv); | 378 | skb_unlink(skb, &vi->recv); |
| 378 | kfree_skb(skb); | 379 | kfree_skb(skb); |
| 379 | break; | 380 | break; |
| @@ -527,7 +528,7 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) | |||
| 527 | num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; | 528 | num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; |
| 528 | 529 | ||
| 529 | err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); | 530 | err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); |
| 530 | if (!err && !vi->free_in_tasklet) | 531 | if (err >= 0 && !vi->free_in_tasklet) |
| 531 | mod_timer(&vi->xmit_free_timer, jiffies + (HZ/10)); | 532 | mod_timer(&vi->xmit_free_timer, jiffies + (HZ/10)); |
| 532 | 533 | ||
| 533 | return err; | 534 | return err; |
| @@ -538,7 +539,7 @@ static void xmit_tasklet(unsigned long data) | |||
| 538 | struct virtnet_info *vi = (void *)data; | 539 | struct virtnet_info *vi = (void *)data; |
| 539 | 540 | ||
| 540 | netif_tx_lock_bh(vi->dev); | 541 | netif_tx_lock_bh(vi->dev); |
| 541 | if (vi->last_xmit_skb && xmit_skb(vi, vi->last_xmit_skb) == 0) { | 542 | if (vi->last_xmit_skb && xmit_skb(vi, vi->last_xmit_skb) >= 0) { |
| 542 | vi->svq->vq_ops->kick(vi->svq); | 543 | vi->svq->vq_ops->kick(vi->svq); |
| 543 | vi->last_xmit_skb = NULL; | 544 | vi->last_xmit_skb = NULL; |
| 544 | } | 545 | } |
| @@ -557,7 +558,7 @@ again: | |||
| 557 | 558 | ||
| 558 | /* If we has a buffer left over from last time, send it now. */ | 559 | /* If we has a buffer left over from last time, send it now. */ |
| 559 | if (unlikely(vi->last_xmit_skb) && | 560 | if (unlikely(vi->last_xmit_skb) && |
| 560 | xmit_skb(vi, vi->last_xmit_skb) != 0) | 561 | xmit_skb(vi, vi->last_xmit_skb) < 0) |
| 561 | goto stop_queue; | 562 | goto stop_queue; |
| 562 | 563 | ||
| 563 | vi->last_xmit_skb = NULL; | 564 | vi->last_xmit_skb = NULL; |
| @@ -565,7 +566,7 @@ again: | |||
| 565 | /* Put new one in send queue and do transmit */ | 566 | /* Put new one in send queue and do transmit */ |
| 566 | if (likely(skb)) { | 567 | if (likely(skb)) { |
| 567 | __skb_queue_head(&vi->send, skb); | 568 | __skb_queue_head(&vi->send, skb); |
| 568 | if (xmit_skb(vi, skb) != 0) { | 569 | if (xmit_skb(vi, skb) < 0) { |
| 569 | vi->last_xmit_skb = skb; | 570 | vi->last_xmit_skb = skb; |
| 570 | skb = NULL; | 571 | skb = NULL; |
| 571 | goto stop_queue; | 572 | goto stop_queue; |
| @@ -668,7 +669,7 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, | |||
| 668 | sg_set_buf(&sg[i + 1], sg_virt(s), s->length); | 669 | sg_set_buf(&sg[i + 1], sg_virt(s), s->length); |
| 669 | sg_set_buf(&sg[out + in - 1], &status, sizeof(status)); | 670 | sg_set_buf(&sg[out + in - 1], &status, sizeof(status)); |
| 670 | 671 | ||
| 671 | BUG_ON(vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi)); | 672 | BUG_ON(vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi) < 0); |
| 672 | 673 | ||
| 673 | vi->cvq->vq_ops->kick(vi->cvq); | 674 | vi->cvq->vq_ops->kick(vi->cvq); |
| 674 | 675 | ||
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 26b278264796..200c22f55130 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | */ | 19 | */ |
| 20 | //#define DEBUG | 20 | //#define DEBUG |
| 21 | #include <linux/virtio.h> | 21 | #include <linux/virtio.h> |
| 22 | #include <linux/virtio_ids.h> | ||
| 22 | #include <linux/virtio_balloon.h> | 23 | #include <linux/virtio_balloon.h> |
| 23 | #include <linux/swap.h> | 24 | #include <linux/swap.h> |
| 24 | #include <linux/kthread.h> | 25 | #include <linux/kthread.h> |
| @@ -84,7 +85,7 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq) | |||
| 84 | init_completion(&vb->acked); | 85 | init_completion(&vb->acked); |
| 85 | 86 | ||
| 86 | /* We should always be able to add one buffer to an empty queue. */ | 87 | /* We should always be able to add one buffer to an empty queue. */ |
| 87 | if (vq->vq_ops->add_buf(vq, &sg, 1, 0, vb) != 0) | 88 | if (vq->vq_ops->add_buf(vq, &sg, 1, 0, vb) < 0) |
| 88 | BUG(); | 89 | BUG(); |
| 89 | vq->vq_ops->kick(vq); | 90 | vq->vq_ops->kick(vq); |
| 90 | 91 | ||
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 248e00ec4dc1..4a1f1ebff7bf 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
| @@ -84,7 +84,7 @@ struct virtio_pci_vq_info | |||
| 84 | struct list_head node; | 84 | struct list_head node; |
| 85 | 85 | ||
| 86 | /* MSI-X vector (or none) */ | 86 | /* MSI-X vector (or none) */ |
| 87 | unsigned vector; | 87 | unsigned msix_vector; |
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| 90 | /* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */ | 90 | /* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */ |
| @@ -280,25 +280,14 @@ static void vp_free_vectors(struct virtio_device *vdev) | |||
| 280 | vp_dev->msix_entries = NULL; | 280 | vp_dev->msix_entries = NULL; |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | static int vp_request_vectors(struct virtio_device *vdev, int nvectors, | 283 | static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, |
| 284 | bool per_vq_vectors) | 284 | bool per_vq_vectors) |
| 285 | { | 285 | { |
| 286 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 286 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
| 287 | const char *name = dev_name(&vp_dev->vdev.dev); | 287 | const char *name = dev_name(&vp_dev->vdev.dev); |
| 288 | unsigned i, v; | 288 | unsigned i, v; |
| 289 | int err = -ENOMEM; | 289 | int err = -ENOMEM; |
| 290 | 290 | ||
| 291 | if (!nvectors) { | ||
| 292 | /* Can't allocate MSI-X vectors, use regular interrupt */ | ||
| 293 | vp_dev->msix_vectors = 0; | ||
| 294 | err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, | ||
| 295 | IRQF_SHARED, name, vp_dev); | ||
| 296 | if (err) | ||
| 297 | return err; | ||
| 298 | vp_dev->intx_enabled = 1; | ||
| 299 | return 0; | ||
| 300 | } | ||
| 301 | |||
| 302 | vp_dev->msix_entries = kmalloc(nvectors * sizeof *vp_dev->msix_entries, | 291 | vp_dev->msix_entries = kmalloc(nvectors * sizeof *vp_dev->msix_entries, |
| 303 | GFP_KERNEL); | 292 | GFP_KERNEL); |
| 304 | if (!vp_dev->msix_entries) | 293 | if (!vp_dev->msix_entries) |
| @@ -311,6 +300,7 @@ static int vp_request_vectors(struct virtio_device *vdev, int nvectors, | |||
| 311 | for (i = 0; i < nvectors; ++i) | 300 | for (i = 0; i < nvectors; ++i) |
| 312 | vp_dev->msix_entries[i].entry = i; | 301 | vp_dev->msix_entries[i].entry = i; |
| 313 | 302 | ||
| 303 | /* pci_enable_msix returns positive if we can't get this many. */ | ||
| 314 | err = pci_enable_msix(vp_dev->pci_dev, vp_dev->msix_entries, nvectors); | 304 | err = pci_enable_msix(vp_dev->pci_dev, vp_dev->msix_entries, nvectors); |
| 315 | if (err > 0) | 305 | if (err > 0) |
| 316 | err = -ENOSPC; | 306 | err = -ENOSPC; |
| @@ -356,10 +346,22 @@ error: | |||
| 356 | return err; | 346 | return err; |
| 357 | } | 347 | } |
| 358 | 348 | ||
| 359 | static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, | 349 | static int vp_request_intx(struct virtio_device *vdev) |
| 360 | void (*callback)(struct virtqueue *vq), | 350 | { |
| 361 | const char *name, | 351 | int err; |
| 362 | u16 vector) | 352 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
| 353 | |||
| 354 | err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, | ||
| 355 | IRQF_SHARED, dev_name(&vdev->dev), vp_dev); | ||
| 356 | if (!err) | ||
| 357 | vp_dev->intx_enabled = 1; | ||
| 358 | return err; | ||
| 359 | } | ||
| 360 | |||
| 361 | static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, | ||
| 362 | void (*callback)(struct virtqueue *vq), | ||
| 363 | const char *name, | ||
| 364 | u16 msix_vec) | ||
| 363 | { | 365 | { |
| 364 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 366 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
| 365 | struct virtio_pci_vq_info *info; | 367 | struct virtio_pci_vq_info *info; |
| @@ -384,7 +386,7 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, | |||
| 384 | 386 | ||
| 385 | info->queue_index = index; | 387 | info->queue_index = index; |
| 386 | info->num = num; | 388 | info->num = num; |
| 387 | info->vector = vector; | 389 | info->msix_vector = msix_vec; |
| 388 | 390 | ||
| 389 | size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN)); | 391 | size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN)); |
| 390 | info->queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO); | 392 | info->queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO); |
| @@ -408,10 +410,10 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, | |||
| 408 | vq->priv = info; | 410 | vq->priv = info; |
| 409 | info->vq = vq; | 411 | info->vq = vq; |
| 410 | 412 | ||
| 411 | if (vector != VIRTIO_MSI_NO_VECTOR) { | 413 | if (msix_vec != VIRTIO_MSI_NO_VECTOR) { |
| 412 | iowrite16(vector, vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); | 414 | iowrite16(msix_vec, vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); |
| 413 | vector = ioread16(vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); | 415 | msix_vec = ioread16(vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); |
| 414 | if (vector == VIRTIO_MSI_NO_VECTOR) { | 416 | if (msix_vec == VIRTIO_MSI_NO_VECTOR) { |
| 415 | err = -EBUSY; | 417 | err = -EBUSY; |
| 416 | goto out_assign; | 418 | goto out_assign; |
| 417 | } | 419 | } |
| @@ -472,7 +474,8 @@ static void vp_del_vqs(struct virtio_device *vdev) | |||
| 472 | list_for_each_entry_safe(vq, n, &vdev->vqs, list) { | 474 | list_for_each_entry_safe(vq, n, &vdev->vqs, list) { |
| 473 | info = vq->priv; | 475 | info = vq->priv; |
| 474 | if (vp_dev->per_vq_vectors) | 476 | if (vp_dev->per_vq_vectors) |
| 475 | free_irq(vp_dev->msix_entries[info->vector].vector, vq); | 477 | free_irq(vp_dev->msix_entries[info->msix_vector].vector, |
| 478 | vq); | ||
| 476 | vp_del_vq(vq); | 479 | vp_del_vq(vq); |
| 477 | } | 480 | } |
| 478 | vp_dev->per_vq_vectors = false; | 481 | vp_dev->per_vq_vectors = false; |
| @@ -484,38 +487,58 @@ static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
| 484 | struct virtqueue *vqs[], | 487 | struct virtqueue *vqs[], |
| 485 | vq_callback_t *callbacks[], | 488 | vq_callback_t *callbacks[], |
| 486 | const char *names[], | 489 | const char *names[], |
| 487 | int nvectors, | 490 | bool use_msix, |
| 488 | bool per_vq_vectors) | 491 | bool per_vq_vectors) |
| 489 | { | 492 | { |
| 490 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 493 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
| 491 | u16 vector; | 494 | u16 msix_vec; |
| 492 | int i, err, allocated_vectors; | 495 | int i, err, nvectors, allocated_vectors; |
| 493 | 496 | ||
| 494 | err = vp_request_vectors(vdev, nvectors, per_vq_vectors); | 497 | if (!use_msix) { |
| 495 | if (err) | 498 | /* Old style: one normal interrupt for change and all vqs. */ |
| 496 | goto error_request; | 499 | err = vp_request_intx(vdev); |
| 500 | if (err) | ||
| 501 | goto error_request; | ||
| 502 | } else { | ||
| 503 | if (per_vq_vectors) { | ||
| 504 | /* Best option: one for change interrupt, one per vq. */ | ||
| 505 | nvectors = 1; | ||
| 506 | for (i = 0; i < nvqs; ++i) | ||
| 507 | if (callbacks[i]) | ||
| 508 | ++nvectors; | ||
| 509 | } else { | ||
| 510 | /* Second best: one for change, shared for all vqs. */ | ||
| 511 | nvectors = 2; | ||
| 512 | } | ||
| 513 | |||
| 514 | err = vp_request_msix_vectors(vdev, nvectors, per_vq_vectors); | ||
| 515 | if (err) | ||
| 516 | goto error_request; | ||
| 517 | } | ||
| 497 | 518 | ||
| 498 | vp_dev->per_vq_vectors = per_vq_vectors; | 519 | vp_dev->per_vq_vectors = per_vq_vectors; |
| 499 | allocated_vectors = vp_dev->msix_used_vectors; | 520 | allocated_vectors = vp_dev->msix_used_vectors; |
| 500 | for (i = 0; i < nvqs; ++i) { | 521 | for (i = 0; i < nvqs; ++i) { |
| 501 | if (!callbacks[i] || !vp_dev->msix_enabled) | 522 | if (!callbacks[i] || !vp_dev->msix_enabled) |
| 502 | vector = VIRTIO_MSI_NO_VECTOR; | 523 | msix_vec = VIRTIO_MSI_NO_VECTOR; |
| 503 | else if (vp_dev->per_vq_vectors) | 524 | else if (vp_dev->per_vq_vectors) |
| 504 | vector = allocated_vectors++; | 525 | msix_vec = allocated_vectors++; |
| 505 | else | 526 | else |
| 506 | vector = VP_MSIX_VQ_VECTOR; | 527 | msix_vec = VP_MSIX_VQ_VECTOR; |
| 507 | vqs[i] = vp_find_vq(vdev, i, callbacks[i], names[i], vector); | 528 | vqs[i] = setup_vq(vdev, i, callbacks[i], names[i], msix_vec); |
| 508 | if (IS_ERR(vqs[i])) { | 529 | if (IS_ERR(vqs[i])) { |
| 509 | err = PTR_ERR(vqs[i]); | 530 | err = PTR_ERR(vqs[i]); |
| 510 | goto error_find; | 531 | goto error_find; |
| 511 | } | 532 | } |
| 512 | /* allocate per-vq irq if available and necessary */ | 533 | /* allocate per-vq irq if available and necessary */ |
| 513 | if (vp_dev->per_vq_vectors && vector != VIRTIO_MSI_NO_VECTOR) { | 534 | if (vp_dev->per_vq_vectors) { |
| 514 | snprintf(vp_dev->msix_names[vector], sizeof *vp_dev->msix_names, | 535 | snprintf(vp_dev->msix_names[msix_vec], |
| 515 | "%s-%s", dev_name(&vp_dev->vdev.dev), names[i]); | 536 | sizeof *vp_dev->msix_names, |
| 516 | err = request_irq(vp_dev->msix_entries[vector].vector, | 537 | "%s-%s", |
| 517 | vring_interrupt, 0, | 538 | dev_name(&vp_dev->vdev.dev), names[i]); |
| 518 | vp_dev->msix_names[vector], vqs[i]); | 539 | err = request_irq(msix_vec, vring_interrupt, 0, |
| 540 | vp_dev->msix_names[msix_vec], | ||
| 541 | vqs[i]); | ||
| 519 | if (err) { | 542 | if (err) { |
| 520 | vp_del_vq(vqs[i]); | 543 | vp_del_vq(vqs[i]); |
| 521 | goto error_find; | 544 | goto error_find; |
| @@ -537,28 +560,20 @@ static int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
| 537 | vq_callback_t *callbacks[], | 560 | vq_callback_t *callbacks[], |
| 538 | const char *names[]) | 561 | const char *names[]) |
| 539 | { | 562 | { |
| 540 | int vectors = 0; | 563 | int err; |
| 541 | int i, uninitialized_var(err); | ||
| 542 | |||
| 543 | /* How many vectors would we like? */ | ||
| 544 | for (i = 0; i < nvqs; ++i) | ||
| 545 | if (callbacks[i]) | ||
| 546 | ++vectors; | ||
| 547 | 564 | ||
| 548 | /* We want at most one vector per queue and one for config changes. */ | 565 | /* Try MSI-X with one vector per queue. */ |
| 549 | err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, | 566 | err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, true, true); |
| 550 | vectors + 1, true); | ||
| 551 | if (!err) | 567 | if (!err) |
| 552 | return 0; | 568 | return 0; |
| 553 | /* Fallback to separate vectors for config and a shared for queues. */ | 569 | /* Fallback: MSI-X with one vector for config, one shared for queues. */ |
| 554 | err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, | 570 | err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, |
| 555 | 2, false); | 571 | true, false); |
| 556 | if (!err) | 572 | if (!err) |
| 557 | return 0; | 573 | return 0; |
| 558 | /* Finally fall back to regular interrupts. */ | 574 | /* Finally fall back to regular interrupts. */ |
| 559 | err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, | 575 | return vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, |
| 560 | 0, false); | 576 | false, false); |
| 561 | return err; | ||
| 562 | } | 577 | } |
| 563 | 578 | ||
| 564 | static struct virtio_config_ops virtio_pci_config_ops = { | 579 | static struct virtio_config_ops virtio_pci_config_ops = { |
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index a882f2606515..f53600580726 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
| @@ -208,7 +208,11 @@ add_head: | |||
| 208 | 208 | ||
| 209 | pr_debug("Added buffer head %i to %p\n", head, vq); | 209 | pr_debug("Added buffer head %i to %p\n", head, vq); |
| 210 | END_USE(vq); | 210 | END_USE(vq); |
| 211 | return 0; | 211 | |
| 212 | /* If we're indirect, we can fit many (assuming not OOM). */ | ||
| 213 | if (vq->indirect) | ||
| 214 | return vq->num_free ? vq->vring.num : 0; | ||
| 215 | return vq->num_free; | ||
| 212 | } | 216 | } |
| 213 | 217 | ||
| 214 | static void vring_kick(struct virtqueue *_vq) | 218 | static void vring_kick(struct virtqueue *_vq) |
