From bef976591be8739534d2f3f6a760bba91b4a6a46 Mon Sep 17 00:00:00 2001 From: dlg Date: Fri, 23 Jan 2015 12:41:23 +0000 Subject: [PATCH] move from deferring vd requests with a task per message to a ring of pointers to vd requests, and a single task to notify the taskq that there's work on the ring. the ring is modelled on what you usually get with network cards, which is an array with a producer and consumer index. the interrupt handler fills an entry in the ring at the producers index and increments it. the task reads entries at the consumer index and increments it until it reaches the same value as the producer. tested and slightly tweaked by kettenis@ ok kettenis@ --- sys/arch/sparc64/dev/vdsp.c | 98 ++++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 39 deletions(-) diff --git a/sys/arch/sparc64/dev/vdsp.c b/sys/arch/sparc64/dev/vdsp.c index 4cc7513d99a..6e7eae16228 100644 --- a/sys/arch/sparc64/dev/vdsp.c +++ b/sys/arch/sparc64/dev/vdsp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vdsp.c,v 1.34 2014/12/17 19:39:01 tedu Exp $ */ +/* $OpenBSD: vdsp.c,v 1.35 2015/01/23 12:41:23 dlg Exp $ */ /* * Copyright (c) 2009, 2011, 2014 Mark Kettenis * @@ -247,7 +247,10 @@ struct vdsp_softc { struct task sc_read_task; caddr_t sc_vd; - struct task *sc_vd_task; + struct task sc_vd_task; + struct vd_desc **sc_vd_ring; + u_int sc_vd_prod; + u_int sc_vd_cons; uint32_t sc_vdisk_block_size; uint64_t sc_vdisk_size; @@ -299,6 +302,7 @@ int vdsp_writelabel(struct vdsp_softc *); int vdsp_is_iso(struct vdsp_softc *); void vdsp_read(void *, void *); void vdsp_read_desc(struct vdsp_softc *, struct vdsk_desc_msg *); +void vdsp_vd_task(void *, void *); void vdsp_read_dring(void *, void *); void vdsp_write_dring(void *, void *); void vdsp_flush_dring(void *, void *); @@ -716,7 +720,6 @@ vdsp_rx_vio_dring_data(struct vdsp_softc *sc, struct vio_msg_tag *tag) { struct vio_dring_msg *dm = (struct vio_dring_msg *)tag; struct vd_desc *vd; - struct task *task; vaddr_t va; paddr_t pa; uint64_t size, off; @@ -752,29 +755,58 @@ vdsp_rx_vio_dring_data(struct vdsp_softc *sc, struct vio_msg_tag *tag) size -= nbytes; off += nbytes; } - task = &sc->sc_vd_task[dm->start_idx]; - DPRINTF(("%s: start_idx %d, end_idx %d, operation %x\n", - sc->sc_dv.dv_xname, dm->start_idx, dm->end_idx, + sc->sc_vd_ring[sc->sc_vd_prod % sc->sc_num_descriptors] = vd; + membar_producer(); + sc->sc_vd_prod++; + task_add(systq, &sc->sc_vd_task); + + break; + + case VIO_SUBTYPE_ACK: + DPRINTF(("DATA/ACK/DRING_DATA\n")); + break; + + case VIO_SUBTYPE_NACK: + DPRINTF(("DATA/NACK/DRING_DATA\n")); + break; + + default: + DPRINTF(("DATA/0x%02x/DRING_DATA\n", tag->stype)); + break; + } +} + +void +vdsp_vd_task(void *xsc, void *null) +{ + struct vdsp_softc *sc = xsc; + struct vd_desc *vd; + + while (sc->sc_vd_cons != sc->sc_vd_prod) { + membar_consumer(); + vd = sc->sc_vd_ring[sc->sc_vd_cons++ % sc->sc_num_descriptors]; + + DPRINTF(("%s: operation %x\n", sc->sc_dv.dv_xname, vd->operation)); switch (vd->operation) { case VD_OP_BREAD: - task_set(task, vdsp_read_dring, sc, vd); + vdsp_read_dring(sc, vd); break; case VD_OP_BWRITE: - task_set(task, vdsp_write_dring, sc, vd); + vdsp_write_dring(sc, vd); break; case VD_OP_FLUSH: - task_set(task, vdsp_flush_dring, sc, vd); + vdsp_flush_dring(sc, vd); break; case VD_OP_GET_VTOC: - task_set(task, vdsp_get_vtoc, sc, vd); + vdsp_get_vtoc(sc, vd); break; case VD_OP_SET_VTOC: - task_set(task, vdsp_set_vtoc, sc, vd); + vdsp_set_vtoc(sc, vd); break; case VD_OP_GET_DISKGEOM: - task_set(task, vdsp_get_diskgeom, sc, vd); + vdsp_get_diskgeom(sc, vd); break; case VD_OP_GET_WCE: case VD_OP_SET_WCE: @@ -785,28 +817,14 @@ vdsp_rx_vio_dring_data(struct vdsp_softc *sc, struct vio_msg_tag *tag) * to be able to handle failure just fine, so * we silently ignore it. */ - task_set(task, vdsp_unimp, sc, vd); + vdsp_unimp(sc, vd); break; default: printf("%s: unsupported operation 0x%02x\n", sc->sc_dv.dv_xname, vd->operation); - task_set(task, vdsp_unimp, sc, vd); + vdsp_unimp(sc, vd); break; } - task_add(systq, task); - break; - - case VIO_SUBTYPE_ACK: - DPRINTF(("DATA/ACK/DRING_DATA\n")); - break; - - case VIO_SUBTYPE_NACK: - DPRINTF(("DATA/NACK/DRING_DATA\n")); - break; - - default: - DPRINTF(("DATA/0x%02x/DRING_DATA\n", tag->stype)); - break; } } @@ -885,7 +903,7 @@ vdsp_sendmsg(struct vdsp_softc *sc, void *msg, size_t len, int dowait) } void -vdsp_open(void *arg1, void *arg2) +vdsp_open(void *arg1, void *null) { struct vdsp_softc *sc = arg1; struct proc *p = curproc; @@ -953,7 +971,7 @@ vdsp_open(void *arg1, void *arg2) } void -vdsp_close(void *arg1, void *arg2) +vdsp_close(void *arg1, void *null) { struct vdsp_softc *sc = arg1; struct proc *p = curproc; @@ -964,9 +982,10 @@ vdsp_close(void *arg1, void *arg2) free(sc->sc_vd, M_DEVBUF, 0); sc->sc_vd = NULL; } - if (sc->sc_vd_task) { - free(sc->sc_vd_task, M_DEVBUF, 0); - sc->sc_vd_task = NULL; + if (sc->sc_vd_ring != NULL) { + free(sc->sc_vd_ring, M_DEVBUF, + sc->sc_num_descriptors * sizeof(*sc->sc_vd_ring)); + sc->sc_vd_ring = NULL; } if (sc->sc_label) { free(sc->sc_label, M_DEVBUF, 0); @@ -1074,17 +1093,18 @@ vdsp_is_iso(struct vdsp_softc *sc) } void -vdsp_alloc(void *arg1, void *arg2) +vdsp_alloc(void *arg1, void *null) { struct vdsp_softc *sc = arg1; struct vio_dring_reg dr; KASSERT(sc->sc_num_descriptors <= VDSK_MAX_DESCRIPTORS); KASSERT(sc->sc_descriptor_size <= VDSK_MAX_DESCRIPTOR_SIZE); - sc->sc_vd = mallocarray(sc->sc_num_descriptors, sc->sc_descriptor_size, - M_DEVBUF, M_WAITOK); - sc->sc_vd_task = mallocarray(sc->sc_num_descriptors, - sizeof(struct task), M_DEVBUF, M_WAITOK); + sc->sc_vd = mallocarray(sc->sc_num_descriptors, + sc->sc_descriptor_size, M_DEVBUF, M_WAITOK); + sc->sc_vd_ring = mallocarray(sc->sc_num_descriptors, + sizeof(*sc->sc_vd_ring), M_DEVBUF, M_WAITOK); + task_set(&sc->sc_vd_task, vdsp_vd_task, sc, NULL); bzero(&dr, sizeof(dr)); dr.tag.type = VIO_TYPE_CTRL; @@ -1096,7 +1116,7 @@ vdsp_alloc(void *arg1, void *arg2) } void -vdsp_read(void *arg1, void *arg2) +vdsp_read(void *arg1, void *null) { struct vdsp_softc *sc = arg1; -- 2.20.1