o Switch to use non-mergeable RX buffers to avoid mbuf adjustment needs

o Operate with copy of iov as we expect later it was not modified
This commit is contained in:
Ruslan Bukin 2015-01-05 16:43:22 +00:00
parent 02b08c9092
commit 1aac28e753
4 changed files with 38 additions and 26 deletions

View File

@ -138,17 +138,16 @@ static int pio_enable_irq(struct vtbe_softc *sc, int enable);
static void
vtbe_txstart_locked(struct vtbe_softc *sc)
{
struct virtio_net_hdr_mrg_rxbuf *vnh;
struct iovec iov[DESC_COUNT];
struct virtio_net_hdr *vnh;
struct vqueue_info *vq;
struct iovec *riov;
struct iovec *tiov;
struct ifnet *ifp;
struct mbuf *m;
struct uio uio;
int enqueued;
int iolen;
int error;
int *addr;
int reg;
int len;
int n;
@ -186,24 +185,16 @@ vtbe_txstart_locked(struct vtbe_softc *sc)
n = vq_getchain(sc->beri_mem_offset, vq, iov,
DESC_COUNT, NULL);
KASSERT(n == 2,
("Unexpected amount of descriptors (%d)", n));
KASSERT(n >= 1 && n <= DESC_COUNT,
("wrong descriptors num %d", n));
addr = iov[0].iov_base;
len = iov[0].iov_len;
tiov = getcopy(iov, n);
vnh = iov[0].iov_base;
memset(vnh, 0, sc->hdrsize);
vnh->num_buffers = htobe16(1);
iov[0].iov_len -= sc->hdrsize;
iov[0].iov_base = (void *)((uintptr_t)iov[0].iov_base +
sc->hdrsize);
riov = &iov[0];
uio.uio_resid = iov[0].iov_len;
uio.uio_iov = riov;
len = iov[1].iov_len;
uio.uio_resid = len;
uio.uio_iov = &tiov[1];
uio.uio_segflg = UIO_SYSSPACE;
uio.uio_iovcnt = 1;
uio.uio_offset = 0;
@ -213,9 +204,10 @@ vtbe_txstart_locked(struct vtbe_softc *sc)
if (error)
panic("m_mbuftouio failed\n");
iolen = (len - iov[0].iov_len - sc->hdrsize);
vq_relchain(vq, iov, 0, iolen + sc->hdrsize);
paddr_unmap((void *)addr, len);
iolen = (len - uio.uio_resid + sc->hdrsize);
free(tiov, M_DEVBUF);
vq_relchain(vq, iov, n, iolen);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
@ -391,6 +383,7 @@ static void
vtbe_proc_rx(struct vtbe_softc *sc, struct vqueue_info *vq)
{
struct iovec iov[DESC_COUNT];
struct iovec *tiov;
struct ifnet *ifp;
struct uio uio;
struct mbuf *m;
@ -406,13 +399,15 @@ vtbe_proc_rx(struct vtbe_softc *sc, struct vqueue_info *vq)
KASSERT(n >= 1 && n <= DESC_COUNT,
("wrong n %d", n));
tiov = getcopy(iov, n);
iolen = 0;
for (i = 1; i < n; i++) {
iolen += iov[i].iov_len;
}
uio.uio_resid = iolen;
uio.uio_iov = &iov[1];
uio.uio_iov = &tiov[1];
uio.uio_segflg = UIO_SYSSPACE;
uio.uio_iovcnt = (n - 1);
uio.uio_rw = UIO_WRITE;
@ -434,6 +429,7 @@ vtbe_proc_rx(struct vtbe_softc *sc, struct vqueue_info *vq)
CURVNET_RESTORE();
done:
free(tiov, M_DEVBUF);
vq_relchain(vq, iov, n, iolen + sc->hdrsize);
}
@ -569,7 +565,7 @@ vtbe_attach(device_t dev)
sc = device_get_softc(dev);
sc->dev = dev;
sc->hdrsize = sizeof(struct virtio_net_hdr_mrg_rxbuf);
sc->hdrsize = sizeof(struct virtio_net_hdr);
if (bus_alloc_resources(dev, vtbe_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
@ -602,7 +598,6 @@ vtbe_attach(device_t dev)
/* Our features */
reg = htobe32(VIRTIO_NET_F_MAC |
VIRTIO_NET_F_MRG_RXBUF |
VIRTIO_F_NOTIFY_ON_EMPTY);
WRITE4(sc, VIRTIO_MMIO_HOST_FEATURES, reg);

View File

@ -186,7 +186,7 @@ vq_relchain(struct vqueue_info *vq, struct iovec *iov, int n, uint32_t iolen)
vu->idx = htobe16(uidx);
/* Clean up */
for (i = 1; i < (n-1); i++) {
for (i = 0; i < n; i++) {
paddr_unmap((void *)iov[i].iov_base, iov[i].iov_len);
}
}
@ -244,3 +244,17 @@ setup_offset(device_t dev, uint32_t *offset)
return (0);
}
struct iovec *
getcopy(struct iovec *iov, int n)
{
struct iovec *tiov;
int i;
tiov = malloc(n * sizeof(struct iovec), M_DEVBUF, M_NOWAIT);
for (i = 0; i < n; i++) {
tiov[i].iov_base = iov[i].iov_base;
tiov[i].iov_len = iov[i].iov_len;
}
return (tiov);
}

View File

@ -65,6 +65,7 @@ void paddr_unmap(void *phys, uint32_t size);
int vq_getchain(uint32_t beri_mem_offset, struct vqueue_info *vq,
struct iovec *iov, int n_iov, uint16_t *flags);
void vq_relchain(struct vqueue_info *vq, struct iovec *iov, int n, uint32_t iolen);
struct iovec * getcopy(struct iovec *iov, int n);
int setup_pio(device_t dev, char *name, device_t *pio_dev);
int setup_offset(device_t dev, uint32_t *offset);

View File

@ -151,6 +151,7 @@ vtblk_proc(struct beri_vtblk_softc *sc, struct vqueue_info *vq)
struct iovec iov[VTBLK_MAXSEGS + 2];
uint16_t flags[VTBLK_MAXSEGS + 2];
struct virtio_blk_outhdr *vbh;
struct iovec *tiov;
uint8_t *status;
off_t offset;
int iolen;
@ -160,10 +161,10 @@ vtblk_proc(struct beri_vtblk_softc *sc, struct vqueue_info *vq)
n = vq_getchain(sc->beri_mem_offset, vq, iov,
VTBLK_MAXSEGS + 2, flags);
KASSERT(n >= 2 && n <= VTBLK_MAXSEGS + 2,
("wrong n value %d", n));
tiov = getcopy(iov, n);
vbh = iov[0].iov_base;
status = iov[n-1].iov_base;
@ -181,7 +182,7 @@ vtblk_proc(struct beri_vtblk_softc *sc, struct vqueue_info *vq)
switch (type) {
case VIRTIO_BLK_T_OUT:
case VIRTIO_BLK_T_IN:
err = vtblk_rdwr(sc, iov + 1, i - 1,
err = vtblk_rdwr(sc, tiov + 1, i - 1,
offset, type, iolen);
break;
case VIRTIO_BLK_T_GET_ID:
@ -205,6 +206,7 @@ vtblk_proc(struct beri_vtblk_softc *sc, struct vqueue_info *vq)
} else
*status = VIRTIO_BLK_S_OK;
free(tiov, M_DEVBUF);
vq_relchain(vq, iov, n, 1);
}