Revision efeea6d0 hw/virtio.c
b/hw/virtio.c | ||
---|---|---|
293 | 293 |
|
294 | 294 |
int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) |
295 | 295 |
{ |
296 |
target_phys_addr_t desc_pa = vq->vring.desc; |
|
297 |
unsigned int idx, max; |
|
298 |
int num_bufs, in_total, out_total; |
|
296 |
unsigned int idx; |
|
297 |
int total_bufs, in_total, out_total; |
|
299 | 298 |
|
300 | 299 |
idx = vq->last_avail_idx; |
301 |
max = vq->vring.num; |
|
302 | 300 |
|
303 |
num_bufs = in_total = out_total = 0;
|
|
301 |
total_bufs = in_total = out_total = 0;
|
|
304 | 302 |
while (virtqueue_num_heads(vq, idx)) { |
303 |
unsigned int max, num_bufs, indirect = 0; |
|
304 |
target_phys_addr_t desc_pa; |
|
305 | 305 |
int i; |
306 | 306 |
|
307 |
max = vq->vring.num; |
|
308 |
num_bufs = total_bufs; |
|
307 | 309 |
i = virtqueue_get_head(vq, idx++); |
310 |
desc_pa = vq->vring.desc; |
|
311 |
|
|
312 |
if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_INDIRECT) { |
|
313 |
if (vring_desc_len(desc_pa, i) % sizeof(VRingDesc)) { |
|
314 |
fprintf(stderr, "Invalid size for indirect buffer table\n"); |
|
315 |
exit(1); |
|
316 |
} |
|
317 |
|
|
318 |
/* If we've got too many, that implies a descriptor loop. */ |
|
319 |
if (num_bufs >= max) { |
|
320 |
fprintf(stderr, "Looped descriptor"); |
|
321 |
exit(1); |
|
322 |
} |
|
323 |
|
|
324 |
/* loop over the indirect descriptor table */ |
|
325 |
indirect = 1; |
|
326 |
max = vring_desc_len(desc_pa, i) / sizeof(VRingDesc); |
|
327 |
num_bufs = i = 0; |
|
328 |
desc_pa = vring_desc_addr(desc_pa, i); |
|
329 |
} |
|
330 |
|
|
308 | 331 |
do { |
309 | 332 |
/* If we've got too many, that implies a descriptor loop. */ |
310 | 333 |
if (++num_bufs > max) { |
... | ... | |
322 | 345 |
return 1; |
323 | 346 |
} |
324 | 347 |
} while ((i = virtqueue_next_desc(desc_pa, i, max)) != max); |
348 |
|
|
349 |
if (!indirect) |
|
350 |
total_bufs = num_bufs; |
|
351 |
else |
|
352 |
total_bufs++; |
|
325 | 353 |
} |
326 | 354 |
|
327 | 355 |
return 0; |
... | ... | |
342 | 370 |
max = vq->vring.num; |
343 | 371 |
|
344 | 372 |
i = head = virtqueue_get_head(vq, vq->last_avail_idx++); |
373 |
|
|
374 |
if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_INDIRECT) { |
|
375 |
if (vring_desc_len(desc_pa, i) % sizeof(VRingDesc)) { |
|
376 |
fprintf(stderr, "Invalid size for indirect buffer table\n"); |
|
377 |
exit(1); |
|
378 |
} |
|
379 |
|
|
380 |
/* loop over the indirect descriptor table */ |
|
381 |
max = vring_desc_len(desc_pa, i) / sizeof(VRingDesc); |
|
382 |
desc_pa = vring_desc_addr(desc_pa, i); |
|
383 |
i = 0; |
|
384 |
} |
|
385 |
|
|
345 | 386 |
do { |
346 | 387 |
struct iovec *sg; |
347 | 388 |
int is_write = 0; |
Also available in: Unified diff