Browse Source

virtio-net: Fix kick/wait logic

The virtnet_transmit() logic for waiting the packet to be transmitted is
reversed: we can't wait the packet to be transmitted if we didn't kick()
the ring yet. The vring_more_used() while loop logic is reversed also,
that explains why the code works today.

The current code risks trying to free a buffer from the used ring
when none was available, that will happen most times because KVM
doesn't handle the packet immediately on kick(). Luckily it was working
because it was unlikely to have a buffer still queued for transmit when
virtnet_transmit() was called.

Also, adds a BUG_ON() to vring_get_buf(), to catch cases where we try
to free a buffer from the used ring when there was none available.

Patch for Etherboot. gPXE has the same problem on the code, but I hadn't
a chance to test gPXE using virtio-net yet.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
tags/v0.9.6
Eduardo Habkost 16 years ago
parent
commit
744b98d273
1 changed files with 5 additions and 3 deletions
  1. 5
    3
      src/drivers/net/virtio-net.c

+ 5
- 3
src/drivers/net/virtio-net.c View File

187
    u32 id;
187
    u32 id;
188
    int ret;
188
    int ret;
189
 
189
 
190
+   BUG_ON(!vring_more_used(queue_index));
191
+
190
    elem = &vr->used->ring[last_used_idx[queue_index] % vr->num];
192
    elem = &vr->used->ring[last_used_idx[queue_index] % vr->num];
191
    wmb();
193
    wmb();
192
    id = elem->id;
194
    id = elem->id;
365
 
367
 
366
    vring_add_buf(TX_INDEX, 0, 0);
368
    vring_add_buf(TX_INDEX, 0, 0);
367
 
369
 
370
+   vring_kick(nic, TX_INDEX, 1);
371
+
368
    /*
372
    /*
369
     * http://www.etherboot.org/wiki/dev/devmanual
373
     * http://www.etherboot.org/wiki/dev/devmanual
370
     *
374
     *
372
     *    before returning from this routine"
376
     *    before returning from this routine"
373
     */
377
     */
374
 
378
 
375
-   while (vring_more_used(TX_INDEX)) {
379
+   while (!vring_more_used(TX_INDEX)) {
376
            mb();
380
            mb();
377
            udelay(10);
381
            udelay(10);
378
    }
382
    }
379
 
383
 
380
-   vring_kick(nic, TX_INDEX, 1);
381
-
382
    /* free desc */
384
    /* free desc */
383
 
385
 
384
    (void)vring_get_buf(TX_INDEX, NULL);
386
    (void)vring_get_buf(TX_INDEX, NULL);

Loading…
Cancel
Save