~ubuntu-branches/ubuntu/precise/seabios/precise-updates

« back to all changes in this revision

Viewing changes to .pc/0029-virtio-remove-NO_NOTIFY-optimization.patch/src/virtio-ring.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2010-10-22 11:04:31 UTC
  • Revision ID: james.westby@ubuntu.com-20101022110431-fnfj73ra6xkq623n
Tags: 0.6.0-0ubuntu2
Add all patches which were included in qemu-0.13.0-rc2 (per
commit on Jul 13, 2010).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* virtio-pci.c - virtio ring management
 
2
 *
 
3
 * (c) Copyright 2008 Bull S.A.S.
 
4
 *
 
5
 *  Author: Laurent Vivier <Laurent.Vivier@bull.net>
 
6
 *
 
7
 *  some parts from Linux Virtio Ring
 
8
 *
 
9
 *  Copyright Rusty Russell IBM Corporation 2007
 
10
 *
 
11
 *  Adopted for Seabios: Gleb Natapov <gleb@redhat.com>
 
12
 *
 
13
 * This work is licensed under the terms of the GNU LGPLv3
 
14
 * See the COPYING file in the top-level directory.
 
15
 *
 
16
 *
 
17
 */
 
18
 
 
19
#include "virtio-ring.h"
 
20
#include "virtio-pci.h"
 
21
#include "biosvar.h" // GET_GLOBAL
 
22
#include "util.h" // dprintf
 
23
 
 
24
#define BUG() do {                                      \
 
25
        dprintf(1, "BUG: failure at %s:%d/%s()!\n",     \
 
26
                __FILE__, __LINE__, __func__);          \
 
27
                while(1);                               \
 
28
        } while (0)
 
29
#define BUG_ON(condition) do { if (condition) BUG(); } while (0)
 
30
 
 
31
/*
 
32
 * vring_more_used
 
33
 *
 
34
 * is there some used buffers ?
 
35
 *
 
36
 */
 
37
 
 
38
int vring_more_used(struct vring_virtqueue *vq)
 
39
{
 
40
    struct vring_used *used = GET_FLATPTR(vq->vring.used);
 
41
    wmb();
 
42
    return GET_FLATPTR(vq->last_used_idx) != GET_FLATPTR(used->idx);
 
43
}
 
44
 
 
45
/*
 
46
 * vring_free
 
47
 *
 
48
 * put at the begin of the free list the current desc[head]
 
49
 */
 
50
 
 
51
void vring_detach(struct vring_virtqueue *vq, unsigned int head)
 
52
{
 
53
    struct vring *vr = &vq->vring;
 
54
    struct vring_desc *desc = GET_FLATPTR(vr->desc);
 
55
    unsigned int i;
 
56
 
 
57
    /* find end of given descriptor */
 
58
 
 
59
    i = head;
 
60
    while (GET_FLATPTR(desc[i].flags) & VRING_DESC_F_NEXT)
 
61
        i = GET_FLATPTR(desc[i].next);
 
62
 
 
63
    /* link it with free list and point to it */
 
64
 
 
65
    SET_FLATPTR(desc[i].next, GET_FLATPTR(vq->free_head));
 
66
    wmb();
 
67
    SET_FLATPTR(vq->free_head, head);
 
68
}
 
69
 
 
70
/*
 
71
 * vring_get_buf
 
72
 *
 
73
 * get a buffer from the used list
 
74
 *
 
75
 */
 
76
 
 
77
int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len)
 
78
{
 
79
    struct vring *vr = &vq->vring;
 
80
    struct vring_used_elem *elem;
 
81
    struct vring_used *used = GET_FLATPTR(vq->vring.used);
 
82
    u32 id;
 
83
    int ret;
 
84
 
 
85
//    BUG_ON(!vring_more_used(vq));
 
86
 
 
87
    elem = &used->ring[GET_FLATPTR(vq->last_used_idx) % GET_FLATPTR(vr->num)];
 
88
    wmb();
 
89
    id = GET_FLATPTR(elem->id);
 
90
    if (len != NULL)
 
91
        *len = GET_FLATPTR(elem->len);
 
92
 
 
93
    ret = GET_FLATPTR(vq->vdata[id]);
 
94
 
 
95
    vring_detach(vq, id);
 
96
 
 
97
    SET_FLATPTR(vq->last_used_idx, GET_FLATPTR(vq->last_used_idx) + 1);
 
98
 
 
99
    return ret;
 
100
}
 
101
 
 
102
void vring_add_buf(struct vring_virtqueue *vq,
 
103
                   struct vring_list list[],
 
104
                   unsigned int out, unsigned int in,
 
105
                   int index, int num_added)
 
106
{
 
107
    struct vring *vr = &vq->vring;
 
108
    int i, av, head, prev;
 
109
    struct vring_desc *desc = GET_FLATPTR(vr->desc);
 
110
    struct vring_avail *avail = GET_FLATPTR(vr->avail);
 
111
 
 
112
    BUG_ON(out + in == 0);
 
113
 
 
114
    prev = 0;
 
115
    head = GET_FLATPTR(vq->free_head);
 
116
    for (i = head; out; i = GET_FLATPTR(desc[i].next), out--) {
 
117
        SET_FLATPTR(desc[i].flags, VRING_DESC_F_NEXT);
 
118
        SET_FLATPTR(desc[i].addr, (u64)virt_to_phys(list->addr));
 
119
        SET_FLATPTR(desc[i].len, list->length);
 
120
        prev = i;
 
121
        list++;
 
122
    }
 
123
    for ( ; in; i = GET_FLATPTR(desc[i].next), in--) {
 
124
        SET_FLATPTR(desc[i].flags, VRING_DESC_F_NEXT|VRING_DESC_F_WRITE);
 
125
        SET_FLATPTR(desc[i].addr, (u64)virt_to_phys(list->addr));
 
126
        SET_FLATPTR(desc[i].len, list->length);
 
127
        prev = i;
 
128
        list++;
 
129
    }
 
130
    SET_FLATPTR(desc[prev].flags,
 
131
                GET_FLATPTR(desc[prev].flags) & ~VRING_DESC_F_NEXT);
 
132
 
 
133
    SET_FLATPTR(vq->free_head, i);
 
134
 
 
135
    SET_FLATPTR(vq->vdata[head], index);
 
136
 
 
137
    av = (GET_FLATPTR(avail->idx) + num_added) % GET_FLATPTR(vr->num);
 
138
    SET_FLATPTR(avail->ring[av], head);
 
139
    wmb();
 
140
}
 
141
 
 
142
void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added)
 
143
{
 
144
    struct vring *vr = &vq->vring;
 
145
    struct vring_avail *avail = GET_FLATPTR(vr->avail);
 
146
    struct vring_used *used = GET_FLATPTR(vq->vring.used);
 
147
 
 
148
    wmb();
 
149
    SET_FLATPTR(avail->idx, GET_FLATPTR(avail->idx) + num_added);
 
150
 
 
151
    mb();
 
152
    if (!(GET_FLATPTR(used->flags) & VRING_USED_F_NO_NOTIFY))
 
153
        vp_notify(ioaddr, GET_FLATPTR(vq->queue_index));
 
154
}