2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
15 #ifndef __VIRTIO_INLINE_H__
16 #define __VIRTIO_INLINE_H__
18 #define foreach_virtio_input_error \
19 _ (BUFFER_ALLOC, "buffer alloc error") \
20 _ (UNKNOWN, "unknown")
24 #define _(f, s) VIRTIO_INPUT_ERROR_##f,
25 foreach_virtio_input_error
28 } virtio_input_error_t;
30 static_always_inline void
31 virtio_refill_vring_split (vlib_main_t *vm, virtio_if_t *vif,
32 virtio_if_type_t type, virtio_vring_t *vring,
33 const int hdr_sz, u32 node_index)
35 u16 used, next, avail, n_slots, n_refill;
40 used = vring->desc_in_use;
42 if (sz - used < sz / 8)
45 /* deliver free buffers in chunks of 64 */
46 n_refill = clib_min (sz - used, 64);
48 next = vring->desc_next;
49 avail = vring->avail->idx;
50 n_slots = vlib_buffer_alloc_to_ring_from_pool (
51 vm, vring->buffers, next, vring->size, n_refill, vring->buffer_pool_index);
53 if (PREDICT_FALSE (n_slots != n_refill))
55 vlib_error_count (vm, node_index, VIRTIO_INPUT_ERROR_BUFFER_ALLOC,
63 vring_desc_t *d = &vring->desc[next];
65 vlib_buffer_t *b = vlib_get_buffer (vm, vring->buffers[next]);
67 * current_data may not be initialized with 0 and may contain
68 * previous offset. Here we want to make sure, it should be 0
71 b->current_data = -hdr_sz;
72 clib_memset (vlib_buffer_get_current (b), 0, hdr_sz);
73 d->addr = ((type == VIRTIO_IF_TYPE_PCI) ?
74 vlib_buffer_get_current_pa (vm, b) :
75 pointer_to_uword (vlib_buffer_get_current (b)));
76 d->len = vlib_buffer_get_default_data_size (vm) + hdr_sz;
77 d->flags = VRING_DESC_F_WRITE;
78 vring->avail->ring[avail & mask] = next;
80 next = (next + 1) & mask;
84 clib_atomic_store_seq_cst (&vring->avail->idx, avail);
85 vring->desc_next = next;
86 vring->desc_in_use = used;
87 if ((clib_atomic_load_seq_cst (&vring->used->flags) &
88 VRING_USED_F_NO_NOTIFY) == 0)
90 virtio_kick (vm, vring, vif);
95 static_always_inline void
96 virtio_refill_vring_packed (vlib_main_t *vm, virtio_if_t *vif,
97 virtio_if_type_t type, virtio_vring_t *vring,
98 const int hdr_sz, u32 node_index)
100 u16 used, next, n_slots, n_refill, flags = 0, first_desc_flags;
101 u16 sz = vring->size;
104 used = vring->desc_in_use;
109 /* deliver free buffers in chunks of 64 */
110 n_refill = clib_min (sz - used, 64);
112 next = vring->desc_next;
113 first_desc_flags = vring->packed_desc[next].flags;
114 n_slots = vlib_buffer_alloc_to_ring_from_pool (
115 vm, vring->buffers, next, sz, n_refill, vring->buffer_pool_index);
117 if (PREDICT_FALSE (n_slots != n_refill))
119 vlib_error_count (vm, node_index, VIRTIO_INPUT_ERROR_BUFFER_ALLOC,
127 vring_packed_desc_t *d = &vring->packed_desc[next];
128 vlib_buffer_t *b = vlib_get_buffer (vm, vring->buffers[next]);
130 * current_data may not be initialized with 0 and may contain
131 * previous offset. Here we want to make sure, it should be 0
134 b->current_data = -hdr_sz;
135 clib_memset (vlib_buffer_get_current (b), 0, hdr_sz);
136 d->addr = ((type == VIRTIO_IF_TYPE_PCI) ?
137 vlib_buffer_get_current_pa (vm, b) :
138 pointer_to_uword (vlib_buffer_get_current (b)));
139 d->len = vlib_buffer_get_default_data_size (vm) + hdr_sz;
141 if (vring->avail_wrap_counter)
142 flags = (VRING_DESC_F_AVAIL | VRING_DESC_F_WRITE);
144 flags = (VRING_DESC_F_USED | VRING_DESC_F_WRITE);
147 if (vring->desc_next == next)
148 first_desc_flags = flags;
156 vring->avail_wrap_counter ^= 1;
161 CLIB_MEMORY_STORE_BARRIER ();
162 vring->packed_desc[vring->desc_next].flags = first_desc_flags;
163 vring->desc_next = next;
164 vring->desc_in_use = used;
165 CLIB_MEMORY_BARRIER ();
166 if (vring->device_event->flags != VRING_EVENT_F_DISABLE)
168 virtio_kick (vm, vring, vif);
177 * fd.io coding-style-patch-verification: ON
180 * eval: (c-set-style "gnu")