usb: Hold pipe lock across upm_transfer and upm_start. This simplifies the code and fixes races with abort. Access to the pipe's queue is now done exclusively while the pipe is locked.diff -r1.29 -r1.30 src/sys/arch/mips/adm5120/dev/ahci.c
(riastradh)
--- src/sys/arch/mips/adm5120/dev/ahci.c 2022/03/03 06:04:31 1.29
+++ src/sys/arch/mips/adm5120/dev/ahci.c 2022/03/03 06:12:11 1.30
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ahci.c,v 1.29 2022/03/03 06:04:31 riastradh Exp $ */ | 1 | /* $NetBSD: ahci.c,v 1.30 2022/03/03 06:12:11 riastradh Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2007 Ruslan Ermilov and Vsevolod Lobko. | 4 | * Copyright (c) 2007 Ruslan Ermilov and Vsevolod Lobko. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or | 7 | * Redistribution and use in source and binary forms, with or | |
8 | * without modification, are permitted provided that the following | 8 | * without modification, are permitted provided that the following | |
9 | * conditions are met: | 9 | * conditions are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above | 12 | * 2. Redistributions in binary form must reproduce the above | |
13 | * copyright notice, this list of conditions and the following | 13 | * copyright notice, this list of conditions and the following | |
14 | * disclaimer in the documentation and/or other materials provided | 14 | * disclaimer in the documentation and/or other materials provided | |
@@ -54,27 +54,27 @@ | @@ -54,27 +54,27 @@ | |||
54 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 54 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
55 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 55 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
56 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 56 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
57 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 57 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
58 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 58 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
59 | * POSSIBILITY OF SUCH DAMAGE. | 59 | * POSSIBILITY OF SUCH DAMAGE. | |
60 | */ | 60 | */ | |
61 | 61 | |||
62 | /* | 62 | /* | |
63 | * !! HIGHLY EXPERIMENTAL CODE !! | 63 | * !! HIGHLY EXPERIMENTAL CODE !! | |
64 | */ | 64 | */ | |
65 | 65 | |||
66 | #include <sys/cdefs.h> | 66 | #include <sys/cdefs.h> | |
67 | __KERNEL_RCSID(0, "$NetBSD: ahci.c,v 1.29 2022/03/03 06:04:31 riastradh Exp $"); | 67 | __KERNEL_RCSID(0, "$NetBSD: ahci.c,v 1.30 2022/03/03 06:12:11 riastradh Exp $"); | |
68 | 68 | |||
69 | #include <sys/param.h> | 69 | #include <sys/param.h> | |
70 | #include <sys/systm.h> | 70 | #include <sys/systm.h> | |
71 | #include <sys/kernel.h> | 71 | #include <sys/kernel.h> | |
72 | #include <sys/proc.h> | 72 | #include <sys/proc.h> | |
73 | #include <sys/device.h> | 73 | #include <sys/device.h> | |
74 | #include <sys/kmem.h> | 74 | #include <sys/kmem.h> | |
75 | 75 | |||
76 | #include <sys/bus.h> | 76 | #include <sys/bus.h> | |
77 | #include <machine/cpu.h> | 77 | #include <machine/cpu.h> | |
78 | 78 | |||
79 | #include <dev/usb/usb.h> | 79 | #include <dev/usb/usb.h> | |
80 | #include <dev/usb/usbdi.h> | 80 | #include <dev/usb/usbdi.h> | |
@@ -559,26 +559,28 @@ ahci_noop(struct usbd_pipe *pipe) | @@ -559,26 +559,28 @@ ahci_noop(struct usbd_pipe *pipe) | |||
559 | 559 | |||
560 | static int | 560 | static int | |
561 | ahci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, | 561 | ahci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, | |
562 | void *buf, int buflen) | 562 | void *buf, int buflen) | |
563 | { | 563 | { | |
564 | struct ahci_softc *sc = AHCI_BUS2SC(bus); | 564 | struct ahci_softc *sc = AHCI_BUS2SC(bus); | |
565 | uint16_t len, value, index; | 565 | uint16_t len, value, index; | |
566 | usb_port_status_t ps; | 566 | usb_port_status_t ps; | |
567 | int totlen = 0; | 567 | int totlen = 0; | |
568 | int status; | 568 | int status; | |
569 | 569 | |||
570 | DPRINTF(D_TRACE, ("SLRCstart ")); | 570 | DPRINTF(D_TRACE, ("SLRCstart ")); | |
571 | 571 | |||
572 | KASSERT(bus->ub_polling || mutex_owned(bus->ub_lock)); | |||
573 | ||||
572 | len = UGETW(req->wLength); | 574 | len = UGETW(req->wLength); | |
573 | value = UGETW(req->wValue); | 575 | value = UGETW(req->wValue); | |
574 | index = UGETW(req->wIndex); | 576 | index = UGETW(req->wIndex); | |
575 | 577 | |||
576 | #define C(x,y) ((x) | ((y) << 8)) | 578 | #define C(x,y) ((x) | ((y) << 8)) | |
577 | switch (C(req->bRequest, req->bmRequestType)) { | 579 | switch (C(req->bRequest, req->bmRequestType)) { | |
578 | case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): | 580 | case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): | |
579 | switch (value) { | 581 | switch (value) { | |
580 | #define sd ((usb_string_descriptor_t *)buf) | 582 | #define sd ((usb_string_descriptor_t *)buf) | |
581 | case C(2, UDESC_STRING): | 583 | case C(2, UDESC_STRING): | |
582 | /* Product */ | 584 | /* Product */ | |
583 | totlen = usb_makestrdesc(sd, len, "ADM5120 root hub"); | 585 | totlen = usb_makestrdesc(sd, len, "ADM5120 root hub"); | |
584 | break; | 586 | break; | |
@@ -733,33 +735,33 @@ ahci_root_intr_transfer(struct usbd_xfer | @@ -733,33 +735,33 @@ ahci_root_intr_transfer(struct usbd_xfer | |||
733 | DPRINTF(D_TRACE, ("SLRItransfer ")); | 735 | DPRINTF(D_TRACE, ("SLRItransfer ")); | |
734 | 736 | |||
735 | /* Pipe isn't running, start first. */ | 737 | /* Pipe isn't running, start first. */ | |
736 | return ahci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 738 | return ahci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
737 | } | 739 | } | |
738 | 740 | |||
739 | static usbd_status | 741 | static usbd_status | |
740 | ahci_root_intr_start(struct usbd_xfer *xfer) | 742 | ahci_root_intr_start(struct usbd_xfer *xfer) | |
741 | { | 743 | { | |
742 | struct ahci_softc *sc = AHCI_XFER2SC(xfer); | 744 | struct ahci_softc *sc = AHCI_XFER2SC(xfer); | |
743 | 745 | |||
744 | DPRINTF(D_TRACE, ("SLRIstart ")); | 746 | DPRINTF(D_TRACE, ("SLRIstart ")); | |
745 | 747 | |||
746 | mutex_enter(&sc->sc_lock); | 748 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock); | |
749 | ||||
747 | KASSERT(sc->sc_intr_xfer == NULL); | 750 | KASSERT(sc->sc_intr_xfer == NULL); | |
748 | sc->sc_interval = MS_TO_TICKS(xfer->ux_pipe->up_endpoint->ue_edesc->bInterval); | 751 | sc->sc_interval = MS_TO_TICKS(xfer->ux_pipe->up_endpoint->ue_edesc->bInterval); | |
749 | callout_schedule(&sc->sc_poll_handle, sc->sc_interval); | 752 | callout_schedule(&sc->sc_poll_handle, sc->sc_interval); | |
750 | sc->sc_intr_xfer = xfer; | 753 | sc->sc_intr_xfer = xfer; | |
751 | xfer->ux_status = USBD_IN_PROGRESS; | 754 | xfer->ux_status = USBD_IN_PROGRESS; | |
752 | mutex_exit(&sc->sc_lock); | |||
753 | 755 | |||
754 | return USBD_IN_PROGRESS; | 756 | return USBD_IN_PROGRESS; | |
755 | } | 757 | } | |
756 | 758 | |||
757 | static void | 759 | static void | |
758 | ahci_root_intr_abort(struct usbd_xfer *xfer) | 760 | ahci_root_intr_abort(struct usbd_xfer *xfer) | |
759 | { | 761 | { | |
760 | struct ahci_softc *sc = AHCI_XFER2SC(xfer); | 762 | struct ahci_softc *sc = AHCI_XFER2SC(xfer); | |
761 | 763 | |||
762 | DPRINTF(D_TRACE, ("SLRIabort ")); | 764 | DPRINTF(D_TRACE, ("SLRIabort ")); | |
763 | 765 | |||
764 | KASSERT(mutex_owned(&sc->sc_lock)); | 766 | KASSERT(mutex_owned(&sc->sc_lock)); | |
765 | KASSERT(xfer->ux_pipe->up_intrxfer == xfer); | 767 | KASSERT(xfer->ux_pipe->up_intrxfer == xfer); | |
@@ -824,31 +826,31 @@ ahci_device_ctrl_transfer(struct usbd_xf | @@ -824,31 +826,31 @@ ahci_device_ctrl_transfer(struct usbd_xf | |||
824 | static usbd_status | 826 | static usbd_status | |
825 | ahci_device_ctrl_start(struct usbd_xfer *xfer) | 827 | ahci_device_ctrl_start(struct usbd_xfer *xfer) | |
826 | { | 828 | { | |
827 | usbd_status status = USBD_NORMAL_COMPLETION; | 829 | usbd_status status = USBD_NORMAL_COMPLETION; | |
828 | int s, err; | 830 | int s, err; | |
829 | static struct admhcd_ed ep_v __attribute__((aligned(16))), *ep; | 831 | static struct admhcd_ed ep_v __attribute__((aligned(16))), *ep; | |
830 | static struct admhcd_td td_v[4] __attribute__((aligned(16))), *td, *td1, *td2, *td3; | 832 | static struct admhcd_td td_v[4] __attribute__((aligned(16))), *td, *td1, *td2, *td3; | |
831 | static usb_dma_t reqdma; | 833 | static usb_dma_t reqdma; | |
832 | struct usbd_pipe *pipe = xfer->ux_pipe; | 834 | struct usbd_pipe *pipe = xfer->ux_pipe; | |
833 | usb_device_request_t *req = &xfer->ux_request; | 835 | usb_device_request_t *req = &xfer->ux_request; | |
834 | struct ahci_softc *sc = AHCI_XFER2SC(xfer); | 836 | struct ahci_softc *sc = AHCI_XFER2SC(xfer); | |
835 | int len, isread; | 837 | int len, isread; | |
836 | 838 | |||
839 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock); | |||
837 | 840 | |||
838 | #if 0 | 841 | #if 0 | |
839 | struct ahci_pipe *apipe = (struct ahci_pipe *)xfer->ux_pipe; | 842 | struct ahci_pipe *apipe = (struct ahci_pipe *)xfer->ux_pipe; | |
840 | #endif | 843 | #endif | |
841 | mutex_enter(&sc->sc_lock); | |||
842 | /* printf("ctrl_start>>>\n"); */ | 844 | /* printf("ctrl_start>>>\n"); */ | |
843 | 845 | |||
844 | #ifdef DIAGNOSTIC | 846 | #ifdef DIAGNOSTIC | |
845 | if (!(xfer->ux_rqflags & URQ_REQUEST)) { | 847 | if (!(xfer->ux_rqflags & URQ_REQUEST)) { | |
846 | /* XXX panic */ | 848 | /* XXX panic */ | |
847 | printf("ahci_device_ctrl_transfer: not a request\n"); | 849 | printf("ahci_device_ctrl_transfer: not a request\n"); | |
848 | return USBD_INVAL; | 850 | return USBD_INVAL; | |
849 | } | 851 | } | |
850 | #endif | 852 | #endif | |
851 | 853 | |||
852 | #define KSEG1ADDR(x) (0xa0000000 | (((uint32_t)x) & 0x1fffffff)) | 854 | #define KSEG1ADDR(x) (0xa0000000 | (((uint32_t)x) & 0x1fffffff)) | |
853 | DPRINTF(D_TRACE, ("st ")); | 855 | DPRINTF(D_TRACE, ("st ")); | |
854 | if (!ep) { | 856 | if (!ep) { | |
@@ -958,27 +960,26 @@ ahci_device_ctrl_start(struct usbd_xfer | @@ -958,27 +960,26 @@ ahci_device_ctrl_start(struct usbd_xfer | |||
958 | }; | 960 | }; | |
959 | status = USBD_NORMAL_COMPLETION; | 961 | status = USBD_NORMAL_COMPLETION; | |
960 | break; | 962 | break; | |
961 | 963 | |||
962 | }; | 964 | }; | |
963 | REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP); | 965 | REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP); | |
964 | 966 | |||
965 | xfer->ux_actlen = len; | 967 | xfer->ux_actlen = len; | |
966 | xfer->ux_status = status; | 968 | xfer->ux_status = status; | |
967 | 969 | |||
968 | /* printf("ctrl_start<<<\n"); */ | 970 | /* printf("ctrl_start<<<\n"); */ | |
969 | 971 | |||
970 | usb_transfer_complete(xfer); | 972 | usb_transfer_complete(xfer); | |
971 | mutex_exit(&sc->sc_lock); | |||
972 | 973 | |||
973 | usb_freemem(&reqdma); | 974 | usb_freemem(&reqdma); | |
974 | 975 | |||
975 | return USBD_NORMAL_COMPLETION; | 976 | return USBD_NORMAL_COMPLETION; | |
976 | } | 977 | } | |
977 | 978 | |||
978 | static void | 979 | static void | |
979 | ahci_device_ctrl_abort(struct usbd_xfer *xfer) | 980 | ahci_device_ctrl_abort(struct usbd_xfer *xfer) | |
980 | { | 981 | { | |
981 | DPRINTF(D_TRACE, ("Cab ")); | 982 | DPRINTF(D_TRACE, ("Cab ")); | |
982 | usbd_xfer_abort(xfer); | 983 | usbd_xfer_abort(xfer); | |
983 | } | 984 | } | |
984 | 985 | |||
@@ -996,31 +997,34 @@ ahci_device_ctrl_done(struct usbd_xfer * | @@ -996,31 +997,34 @@ ahci_device_ctrl_done(struct usbd_xfer * | |||
996 | 997 | |||
997 | static usbd_status | 998 | static usbd_status | |
998 | ahci_device_intr_transfer(struct usbd_xfer *xfer) | 999 | ahci_device_intr_transfer(struct usbd_xfer *xfer) | |
999 | { | 1000 | { | |
1000 | 1001 | |||
1001 | DPRINTF(D_TRACE, ("INTRtrans ")); | 1002 | DPRINTF(D_TRACE, ("INTRtrans ")); | |
1002 | 1003 | |||
1003 | return ahci_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 1004 | return ahci_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
1004 | } | 1005 | } | |
1005 | 1006 | |||
1006 | static usbd_status | 1007 | static usbd_status | |
1007 | ahci_device_intr_start(struct usbd_xfer *xfer) | 1008 | ahci_device_intr_start(struct usbd_xfer *xfer) | |
1008 | { | 1009 | { | |
1010 | struct ahci_softc *sc = AHCI_XFER2SC(xfer); | |||
1009 | struct usbd_pipe *pipe = xfer->ux_pipe; | 1011 | struct usbd_pipe *pipe = xfer->ux_pipe; | |
1010 | struct ahci_xfer *sx; | 1012 | struct ahci_xfer *sx; | |
1011 | 1013 | |||
1012 | DPRINTF(D_TRACE, ("INTRstart ")); | 1014 | DPRINTF(D_TRACE, ("INTRstart ")); | |
1013 | 1015 | |||
1016 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock); | |||
1017 | ||||
1014 | sx = kmem_intr_alloc(sizeof(*sx), KM_NOSLEEP); | 1018 | sx = kmem_intr_alloc(sizeof(*sx), KM_NOSLEEP); | |
1015 | if (sx == NULL) | 1019 | if (sx == NULL) | |
1016 | goto reterr; | 1020 | goto reterr; | |
1017 | memset(sx, 0, sizeof(*sx)); | 1021 | memset(sx, 0, sizeof(*sx)); | |
1018 | sx->sx_xfer = xfer; | 1022 | sx->sx_xfer = xfer; | |
1019 | xfer->ux_hcpriv = sx; | 1023 | xfer->ux_hcpriv = sx; | |
1020 | 1024 | |||
1021 | /* initialize callout */ | 1025 | /* initialize callout */ | |
1022 | callout_init(&sx->sx_callout_t, 0); | 1026 | callout_init(&sx->sx_callout_t, 0); | |
1023 | callout_reset(&sx->sx_callout_t, | 1027 | callout_reset(&sx->sx_callout_t, | |
1024 | MS_TO_TICKS(pipe->up_endpoint->ue_edesc->bInterval), | 1028 | MS_TO_TICKS(pipe->up_endpoint->ue_edesc->bInterval), | |
1025 | ahci_poll_device, sx); | 1029 | ahci_poll_device, sx); | |
1026 | 1030 | |||
@@ -1146,35 +1150,36 @@ ahci_device_bulk_start(struct usbd_xfer | @@ -1146,35 +1150,36 @@ ahci_device_bulk_start(struct usbd_xfer | |||
1146 | static volatile int level = 0; | 1150 | static volatile int level = 0; | |
1147 | usbd_status status = USBD_NORMAL_COMPLETION; | 1151 | usbd_status status = USBD_NORMAL_COMPLETION; | |
1148 | int s, err; | 1152 | int s, err; | |
1149 | static struct admhcd_ed ep_v __attribute__((aligned(16))), *ep; | 1153 | static struct admhcd_ed ep_v __attribute__((aligned(16))), *ep; | |
1150 | static struct admhcd_td td_v[NBULK_TDS] __attribute__((aligned(16))), *td[NBULK_TDS]; | 1154 | static struct admhcd_td td_v[NBULK_TDS] __attribute__((aligned(16))), *td[NBULK_TDS]; | |
1151 | struct usbd_pipe *pipe = xfer->ux_pipe; | 1155 | struct usbd_pipe *pipe = xfer->ux_pipe; | |
1152 | struct ahci_softc *sc = AHCI_XFER2SC(xfer); | 1156 | struct ahci_softc *sc = AHCI_XFER2SC(xfer); | |
1153 | int endpt, i, len, tlen, segs, offset, isread, toggle, short_ok; | 1157 | int endpt, i, len, tlen, segs, offset, isread, toggle, short_ok; | |
1154 | struct ahci_pipe *apipe = (struct ahci_pipe *)xfer->ux_pipe; | 1158 | struct ahci_pipe *apipe = (struct ahci_pipe *)xfer->ux_pipe; | |
1155 | 1159 | |||
1156 | #define KSEG1ADDR(x) (0xa0000000 | (((uint32_t)x) & 0x1fffffff)) | 1160 | #define KSEG1ADDR(x) (0xa0000000 | (((uint32_t)x) & 0x1fffffff)) | |
1157 | DPRINTF(D_TRACE, ("st ")); | 1161 | DPRINTF(D_TRACE, ("st ")); | |
1158 | 1162 | |||
1163 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock); | |||
1164 | ||||
1159 | #ifdef DIAGNOSTIC | 1165 | #ifdef DIAGNOSTIC | |
1160 | if (xfer->ux_rqflags & URQ_REQUEST) { | 1166 | if (xfer->ux_rqflags & URQ_REQUEST) { | |
1161 | /* XXX panic */ | 1167 | /* XXX panic */ | |
1162 | printf("ohci_device_bulk_start: a request\n"); | 1168 | printf("ohci_device_bulk_start: a request\n"); | |
1163 | return USBD_INVAL; | 1169 | return USBD_INVAL; | |
1164 | } | 1170 | } | |
1165 | #endif | 1171 | #endif | |
1166 | 1172 | |||
1167 | mutex_enter(&sc->sc_lock); | |||
1168 | level++; | 1173 | level++; | |
1169 | /* printf("bulk_start>>>\n"); */ | 1174 | /* printf("bulk_start>>>\n"); */ | |
1170 | 1175 | |||
1171 | if (!ep) { | 1176 | if (!ep) { | |
1172 | ep = (struct admhcd_ed *)KSEG1ADDR(&ep_v); | 1177 | ep = (struct admhcd_ed *)KSEG1ADDR(&ep_v); | |
1173 | for (i=0; i<NBULK_TDS; i++) { | 1178 | for (i=0; i<NBULK_TDS; i++) { | |
1174 | td[i] = (struct admhcd_td *)KSEG1ADDR(&td_v[i]); | 1179 | td[i] = (struct admhcd_td *)KSEG1ADDR(&td_v[i]); | |
1175 | }; | 1180 | }; | |
1176 | /* printf("ep: %p\n",ep);*/ | 1181 | /* printf("ep: %p\n",ep);*/ | |
1177 | }; | 1182 | }; | |
1178 | if (apipe->toggle == 0) { | 1183 | if (apipe->toggle == 0) { | |
1179 | toggle = ADMHCD_TD_DATA0; | 1184 | toggle = ADMHCD_TD_DATA0; | |
1180 | } else { | 1185 | } else { | |
@@ -1281,27 +1286,26 @@ ahci_device_bulk_start(struct usbd_xfer | @@ -1281,27 +1286,26 @@ ahci_device_bulk_start(struct usbd_xfer | |||
1281 | status = USBD_NORMAL_COMPLETION; | 1286 | status = USBD_NORMAL_COMPLETION; | |
1282 | }; | 1287 | }; | |
1283 | xfer->ux_actlen = len; | 1288 | xfer->ux_actlen = len; | |
1284 | xfer->ux_status = status; | 1289 | xfer->ux_status = status; | |
1285 | 1290 | |||
1286 | level--; | 1291 | level--; | |
1287 | /* printf("bulk_start<<<\n"); */ | 1292 | /* printf("bulk_start<<<\n"); */ | |
1288 | 1293 | |||
1289 | if (xfer->ux_length) | 1294 | if (xfer->ux_length) | |
1290 | usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, | 1295 | usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, | |
1291 | isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); | 1296 | isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); | |
1292 | 1297 | |||
1293 | usb_transfer_complete(xfer); | 1298 | usb_transfer_complete(xfer); | |
1294 | mutex_exit(&sc->sc_lock); | |||
1295 | 1299 | |||
1296 | return USBD_NORMAL_COMPLETION; | 1300 | return USBD_NORMAL_COMPLETION; | |
1297 | } | 1301 | } | |
1298 | 1302 | |||
1299 | static void | 1303 | static void | |
1300 | ahci_device_bulk_abort(struct usbd_xfer *xfer) | 1304 | ahci_device_bulk_abort(struct usbd_xfer *xfer) | |
1301 | { | 1305 | { | |
1302 | DPRINTF(D_TRACE, ("Bab ")); | 1306 | DPRINTF(D_TRACE, ("Bab ")); | |
1303 | usbd_xfer_abort(xfer); | 1307 | usbd_xfer_abort(xfer); | |
1304 | } | 1308 | } | |
1305 | 1309 | |||
1306 | static void | 1310 | static void | |
1307 | ahci_device_bulk_close(struct usbd_pipe *pipe) | 1311 | ahci_device_bulk_close(struct usbd_pipe *pipe) |
--- src/sys/dev/ic/sl811hs.c 2022/03/03 06:04:31 1.109
+++ src/sys/dev/ic/sl811hs.c 2022/03/03 06:12:11 1.110
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: sl811hs.c,v 1.109 2022/03/03 06:04:31 riastradh Exp $ */ | 1 | /* $NetBSD: sl811hs.c,v 1.110 2022/03/03 06:12:11 riastradh Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Not (c) 2007 Matthew Orgass | 4 | * Not (c) 2007 Matthew Orgass | |
5 | * This file is public domain, meaning anyone can make any use of part or all | 5 | * This file is public domain, meaning anyone can make any use of part or all | |
6 | * of this file including copying into other works without credit. Any use, | 6 | * of this file including copying into other works without credit. Any use, | |
7 | * modified or not, is solely the responsibility of the user. If this file is | 7 | * modified or not, is solely the responsibility of the user. If this file is | |
8 | * part of a collection then use in the collection is governed by the terms of | 8 | * part of a collection then use in the collection is governed by the terms of | |
9 | * the collection. | 9 | * the collection. | |
10 | */ | 10 | */ | |
11 | 11 | |||
12 | /* | 12 | /* | |
13 | * Cypress/ScanLogic SL811HS/T USB Host Controller | 13 | * Cypress/ScanLogic SL811HS/T USB Host Controller | |
14 | * Datasheet, Errata, and App Note available at www.cypress.com | 14 | * Datasheet, Errata, and App Note available at www.cypress.com | |
@@ -58,27 +58,27 @@ | @@ -58,27 +58,27 @@ | |||
58 | */ | 58 | */ | |
59 | 59 | |||
60 | /* | 60 | /* | |
61 | * XXX TODO: | 61 | * XXX TODO: | |
62 | * copy next output packet while transfering | 62 | * copy next output packet while transfering | |
63 | * usb suspend | 63 | * usb suspend | |
64 | * could keep track of known values of all buffer space? | 64 | * could keep track of known values of all buffer space? | |
65 | * combined print/log function for errors | 65 | * combined print/log function for errors | |
66 | * | 66 | * | |
67 | * ub_usepolling support is untested and may not work | 67 | * ub_usepolling support is untested and may not work | |
68 | */ | 68 | */ | |
69 | 69 | |||
70 | #include <sys/cdefs.h> | 70 | #include <sys/cdefs.h> | |
71 | __KERNEL_RCSID(0, "$NetBSD: sl811hs.c,v 1.109 2022/03/03 06:04:31 riastradh Exp $"); | 71 | __KERNEL_RCSID(0, "$NetBSD: sl811hs.c,v 1.110 2022/03/03 06:12:11 riastradh Exp $"); | |
72 | 72 | |||
73 | #ifdef _KERNEL_OPT | 73 | #ifdef _KERNEL_OPT | |
74 | #include "opt_slhci.h" | 74 | #include "opt_slhci.h" | |
75 | #include "opt_usb.h" | 75 | #include "opt_usb.h" | |
76 | #endif | 76 | #endif | |
77 | 77 | |||
78 | #include <sys/param.h> | 78 | #include <sys/param.h> | |
79 | 79 | |||
80 | #include <sys/bus.h> | 80 | #include <sys/bus.h> | |
81 | #include <sys/cpu.h> | 81 | #include <sys/cpu.h> | |
82 | #include <sys/device.h> | 82 | #include <sys/device.h> | |
83 | #include <sys/gcq.h> | 83 | #include <sys/gcq.h> | |
84 | #include <sys/intr.h> | 84 | #include <sys/intr.h> | |
@@ -836,48 +836,44 @@ slhci_get_lock(struct usbd_bus *bus, kmu | @@ -836,48 +836,44 @@ slhci_get_lock(struct usbd_bus *bus, kmu | |||
836 | } | 836 | } | |
837 | 837 | |||
838 | usbd_status | 838 | usbd_status | |
839 | slhci_transfer(struct usbd_xfer *xfer) | 839 | slhci_transfer(struct usbd_xfer *xfer) | |
840 | { | 840 | { | |
841 | SLHCIHIST_FUNC(); SLHCIHIST_CALLED(); | 841 | SLHCIHIST_FUNC(); SLHCIHIST_CALLED(); | |
842 | usbd_status error; | 842 | usbd_status error; | |
843 | 843 | |||
844 | DLOG(D_TRACE, "transfer type %jd xfer %#jx spipe %#jx ", | 844 | DLOG(D_TRACE, "transfer type %jd xfer %#jx spipe %#jx ", | |
845 | SLHCI_XFER_TYPE(xfer), (uintptr_t)xfer, (uintptr_t)xfer->ux_pipe, | 845 | SLHCI_XFER_TYPE(xfer), (uintptr_t)xfer, (uintptr_t)xfer->ux_pipe, | |
846 | 0); | 846 | 0); | |
847 | 847 | |||
848 | /* Pipe isn't running, so start it first. */ | 848 | /* Pipe isn't running, so start it first. */ | |
849 | ||||
850 | /* | |||
851 | * Start will take the lock. | |||
852 | */ | |||
853 | error = xfer->ux_pipe->up_methods->upm_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 849 | error = xfer->ux_pipe->up_methods->upm_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
854 | 850 | |||
855 | return error; | 851 | return error; | |
856 | } | 852 | } | |
857 | 853 | |||
858 | /* It is not safe for start to return anything other than USBD_INPROG. */ | 854 | /* It is not safe for start to return anything other than USBD_INPROG. */ | |
859 | usbd_status | 855 | usbd_status | |
860 | slhci_start(struct usbd_xfer *xfer) | 856 | slhci_start(struct usbd_xfer *xfer) | |
861 | { | 857 | { | |
862 | SLHCIHIST_FUNC(); SLHCIHIST_CALLED(); | 858 | SLHCIHIST_FUNC(); SLHCIHIST_CALLED(); | |
863 | struct slhci_softc *sc = SLHCI_XFER2SC(xfer); | 859 | struct slhci_softc *sc = SLHCI_XFER2SC(xfer); | |
864 | struct usbd_pipe *pipe = xfer->ux_pipe; | 860 | struct usbd_pipe *pipe = xfer->ux_pipe; | |
865 | struct slhci_pipe *spipe = SLHCI_PIPE2SPIPE(pipe); | 861 | struct slhci_pipe *spipe = SLHCI_PIPE2SPIPE(pipe); | |
866 | struct slhci_transfers *t = &sc->sc_transfers; | 862 | struct slhci_transfers *t = &sc->sc_transfers; | |
867 | usb_endpoint_descriptor_t *ed = pipe->up_endpoint->ue_edesc; | 863 | usb_endpoint_descriptor_t *ed = pipe->up_endpoint->ue_edesc; | |
868 | unsigned int max_packet; | 864 | unsigned int max_packet; | |
869 | 865 | |||
870 | mutex_enter(&sc->sc_lock); | 866 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |
871 | 867 | |||
872 | max_packet = UGETW(ed->wMaxPacketSize); | 868 | max_packet = UGETW(ed->wMaxPacketSize); | |
873 | 869 | |||
874 | DLOG(D_TRACE, "transfer type %jd start xfer %#jx spipe %#jx length %jd", | 870 | DLOG(D_TRACE, "transfer type %jd start xfer %#jx spipe %#jx length %jd", | |
875 | spipe->ptype, (uintptr_t)xfer, (uintptr_t)spipe, xfer->ux_length); | 871 | spipe->ptype, (uintptr_t)xfer, (uintptr_t)spipe, xfer->ux_length); | |
876 | 872 | |||
877 | /* root transfers use slhci_root_start */ | 873 | /* root transfers use slhci_root_start */ | |
878 | 874 | |||
879 | KASSERT(spipe->xfer == NULL); /* not SLASSERT */ | 875 | KASSERT(spipe->xfer == NULL); /* not SLASSERT */ | |
880 | 876 | |||
881 | xfer->ux_actlen = 0; | 877 | xfer->ux_actlen = 0; | |
882 | xfer->ux_status = USBD_IN_PROGRESS; | 878 | xfer->ux_status = USBD_IN_PROGRESS; | |
883 | 879 | |||
@@ -979,56 +975,54 @@ slhci_start(struct usbd_xfer *xfer) | @@ -979,56 +975,54 @@ slhci_start(struct usbd_xfer *xfer) | |||
979 | xfer->ux_status = USBD_INVAL; | 975 | xfer->ux_status = USBD_INVAL; | |
980 | } | 976 | } | |
981 | 977 | |||
982 | /* | 978 | /* | |
983 | * The datasheet incorrectly indicates that DIRECTION is for | 979 | * The datasheet incorrectly indicates that DIRECTION is for | |
984 | * "transmit to host". It is for OUT and SETUP. The app note | 980 | * "transmit to host". It is for OUT and SETUP. The app note | |
985 | * describes its use correctly. | 981 | * describes its use correctly. | |
986 | */ | 982 | */ | |
987 | if ((spipe->tregs[PID] & SL11_PID_BITS) != SL11_PID_IN) | 983 | if ((spipe->tregs[PID] & SL11_PID_BITS) != SL11_PID_IN) | |
988 | spipe->control |= SL11_EPCTRL_DIRECTION; | 984 | spipe->control |= SL11_EPCTRL_DIRECTION; | |
989 | 985 | |||
990 | slhci_start_entry(sc, spipe); | 986 | slhci_start_entry(sc, spipe); | |
991 | 987 | |||
992 | mutex_exit(&sc->sc_lock); | |||
993 | ||||
994 | return USBD_IN_PROGRESS; | 988 | return USBD_IN_PROGRESS; | |
995 | } | 989 | } | |
996 | 990 | |||
997 | usbd_status | 991 | usbd_status | |
998 | slhci_root_start(struct usbd_xfer *xfer) | 992 | slhci_root_start(struct usbd_xfer *xfer) | |
999 | { | 993 | { | |
1000 | SLHCIHIST_FUNC(); SLHCIHIST_CALLED(); | 994 | SLHCIHIST_FUNC(); SLHCIHIST_CALLED(); | |
1001 | struct slhci_softc *sc; | 995 | struct slhci_softc *sc; | |
1002 | struct slhci_pipe *spipe __diagused; | 996 | struct slhci_pipe *spipe __diagused; | |
1003 | 997 | |||
1004 | spipe = SLHCI_PIPE2SPIPE(xfer->ux_pipe); | 998 | spipe = SLHCI_PIPE2SPIPE(xfer->ux_pipe); | |
1005 | sc = SLHCI_XFER2SC(xfer); | 999 | sc = SLHCI_XFER2SC(xfer); | |
1006 | 1000 | |||
1007 | struct slhci_transfers *t = &sc->sc_transfers; | 1001 | struct slhci_transfers *t = &sc->sc_transfers; | |
1008 | 1002 | |||
1009 | LK_SLASSERT(spipe != NULL && xfer != NULL, sc, spipe, xfer, return | 1003 | LK_SLASSERT(spipe != NULL && xfer != NULL, sc, spipe, xfer, return | |
1010 | USBD_CANCELLED); | 1004 | USBD_CANCELLED); | |
1011 | 1005 | |||
1012 | DLOG(D_TRACE, "transfer type %jd start", | 1006 | DLOG(D_TRACE, "transfer type %jd start", | |
1013 | SLHCI_XFER_TYPE(xfer), 0, 0, 0); | 1007 | SLHCI_XFER_TYPE(xfer), 0, 0, 0); | |
1014 | 1008 | |||
1009 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
1010 | ||||
1015 | KASSERT(spipe->ptype == PT_ROOT_INTR); | 1011 | KASSERT(spipe->ptype == PT_ROOT_INTR); | |
1016 | 1012 | |||
1017 | mutex_enter(&sc->sc_intr_lock); | |||
1018 | KASSERT(t->rootintr == NULL); | 1013 | KASSERT(t->rootintr == NULL); | |
1019 | t->rootintr = xfer; | 1014 | t->rootintr = xfer; | |
1020 | xfer->ux_status = USBD_IN_PROGRESS; | 1015 | xfer->ux_status = USBD_IN_PROGRESS; | |
1021 | mutex_exit(&sc->sc_intr_lock); | |||
1022 | 1016 | |||
1023 | return USBD_IN_PROGRESS; | 1017 | return USBD_IN_PROGRESS; | |
1024 | } | 1018 | } | |
1025 | 1019 | |||
1026 | usbd_status | 1020 | usbd_status | |
1027 | slhci_open(struct usbd_pipe *pipe) | 1021 | slhci_open(struct usbd_pipe *pipe) | |
1028 | { | 1022 | { | |
1029 | SLHCIHIST_FUNC(); SLHCIHIST_CALLED(); | 1023 | SLHCIHIST_FUNC(); SLHCIHIST_CALLED(); | |
1030 | struct usbd_device *dev; | 1024 | struct usbd_device *dev; | |
1031 | struct slhci_softc *sc; | 1025 | struct slhci_softc *sc; | |
1032 | struct slhci_pipe *spipe; | 1026 | struct slhci_pipe *spipe; | |
1033 | usb_endpoint_descriptor_t *ed; | 1027 | usb_endpoint_descriptor_t *ed; | |
1034 | unsigned int max_packet, pmaxpkt; | 1028 | unsigned int max_packet, pmaxpkt; | |
@@ -3191,26 +3185,28 @@ slhci_get_status(struct slhci_softc *sc, | @@ -3191,26 +3185,28 @@ slhci_get_status(struct slhci_softc *sc, | |||
3191 | 3185 | |||
3192 | static int | 3186 | static int | |
3193 | slhci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, | 3187 | slhci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, | |
3194 | void *buf, int buflen) | 3188 | void *buf, int buflen) | |
3195 | { | 3189 | { | |
3196 | SLHCIHIST_FUNC(); SLHCIHIST_CALLED(); | 3190 | SLHCIHIST_FUNC(); SLHCIHIST_CALLED(); | |
3197 | struct slhci_softc *sc = SLHCI_BUS2SC(bus); | 3191 | struct slhci_softc *sc = SLHCI_BUS2SC(bus); | |
3198 | struct slhci_transfers *t = &sc->sc_transfers; | 3192 | struct slhci_transfers *t = &sc->sc_transfers; | |
3199 | usbd_status error = USBD_IOERROR; /* XXX should be STALL */ | 3193 | usbd_status error = USBD_IOERROR; /* XXX should be STALL */ | |
3200 | uint16_t len, value, index; | 3194 | uint16_t len, value, index; | |
3201 | uint8_t type; | 3195 | uint8_t type; | |
3202 | int actlen = 0; | 3196 | int actlen = 0; | |
3203 | 3197 | |||
3198 | KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock)); | |||
3199 | ||||
3204 | len = UGETW(req->wLength); | 3200 | len = UGETW(req->wLength); | |
3205 | value = UGETW(req->wValue); | 3201 | value = UGETW(req->wValue); | |
3206 | index = UGETW(req->wIndex); | 3202 | index = UGETW(req->wIndex); | |
3207 | 3203 | |||
3208 | type = req->bmRequestType; | 3204 | type = req->bmRequestType; | |
3209 | 3205 | |||
3210 | SLHCI_DEXEC(D_TRACE, slhci_log_req(req)); | 3206 | SLHCI_DEXEC(D_TRACE, slhci_log_req(req)); | |
3211 | 3207 | |||
3212 | /* | 3208 | /* | |
3213 | * USB requests for hubs have two basic types, standard and class. | 3209 | * USB requests for hubs have two basic types, standard and class. | |
3214 | * Each could potentially have recipients of device, interface, | 3210 | * Each could potentially have recipients of device, interface, | |
3215 | * endpoint, or other. For the hub class, CLASS_OTHER means the port | 3211 | * endpoint, or other. For the hub class, CLASS_OTHER means the port | |
3216 | * and CLASS_DEVICE means the hub. For standard requests, OTHER | 3212 | * and CLASS_DEVICE means the hub. For standard requests, OTHER |
--- src/sys/dev/usb/ehci.c 2022/03/03 06:08:50 1.304
+++ src/sys/dev/usb/ehci.c 2022/03/03 06:12:11 1.305
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ehci.c,v 1.304 2022/03/03 06:08:50 riastradh Exp $ */ | 1 | /* $NetBSD: ehci.c,v 1.305 2022/03/03 06:12:11 riastradh Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2004-2012,2016,2020 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2004-2012,2016,2020 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Lennart Augustsson (lennart@augustsson.net), Charles M. Hannum, | 8 | * by Lennart Augustsson (lennart@augustsson.net), Charles M. Hannum, | |
9 | * Jeremy Morse (jeremy.morse@gmail.com), Jared D. McNeill | 9 | * Jeremy Morse (jeremy.morse@gmail.com), Jared D. McNeill | |
10 | * (jmcneill@invisible.ca). Matthew R. Green (mrg@eterna.com.au), and | 10 | * (jmcneill@invisible.ca). Matthew R. Green (mrg@eterna.com.au), and | |
11 | * Nick Hudson . | 11 | * Nick Hudson . | |
12 | * | 12 | * | |
13 | * Redistribution and use in source and binary forms, with or without | 13 | * Redistribution and use in source and binary forms, with or without | |
14 | * modification, are permitted provided that the following conditions | 14 | * modification, are permitted provided that the following conditions | |
@@ -44,27 +44,27 @@ | @@ -44,27 +44,27 @@ | |||
44 | 44 | |||
45 | /* | 45 | /* | |
46 | * TODO: | 46 | * TODO: | |
47 | * 1) hold off explorations by companion controllers until ehci has started. | 47 | * 1) hold off explorations by companion controllers until ehci has started. | |
48 | * | 48 | * | |
49 | * 2) The hub driver needs to handle and schedule the transaction translator, | 49 | * 2) The hub driver needs to handle and schedule the transaction translator, | |
50 | * to assign place in frame where different devices get to go. See chapter | 50 | * to assign place in frame where different devices get to go. See chapter | |
51 | * on hubs in USB 2.0 for details. | 51 | * on hubs in USB 2.0 for details. | |
52 | * | 52 | * | |
53 | * 3) Command failures are not recovered correctly. | 53 | * 3) Command failures are not recovered correctly. | |
54 | */ | 54 | */ | |
55 | 55 | |||
56 | #include <sys/cdefs.h> | 56 | #include <sys/cdefs.h> | |
57 | __KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.304 2022/03/03 06:08:50 riastradh Exp $"); | 57 | __KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.305 2022/03/03 06:12:11 riastradh Exp $"); | |
58 | 58 | |||
59 | #include "ohci.h" | 59 | #include "ohci.h" | |
60 | #include "uhci.h" | 60 | #include "uhci.h" | |
61 | 61 | |||
62 | #ifdef _KERNEL_OPT | 62 | #ifdef _KERNEL_OPT | |
63 | #include "opt_usb.h" | 63 | #include "opt_usb.h" | |
64 | #endif | 64 | #endif | |
65 | 65 | |||
66 | #include <sys/param.h> | 66 | #include <sys/param.h> | |
67 | 67 | |||
68 | #include <sys/bus.h> | 68 | #include <sys/bus.h> | |
69 | #include <sys/cpu.h> | 69 | #include <sys/cpu.h> | |
70 | #include <sys/device.h> | 70 | #include <sys/device.h> | |
@@ -2359,26 +2359,28 @@ Static int | @@ -2359,26 +2359,28 @@ Static int | |||
2359 | ehci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, | 2359 | ehci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, | |
2360 | void *buf, int buflen) | 2360 | void *buf, int buflen) | |
2361 | { | 2361 | { | |
2362 | ehci_softc_t *sc = EHCI_BUS2SC(bus); | 2362 | ehci_softc_t *sc = EHCI_BUS2SC(bus); | |
2363 | usb_hub_descriptor_t hubd; | 2363 | usb_hub_descriptor_t hubd; | |
2364 | usb_port_status_t ps; | 2364 | usb_port_status_t ps; | |
2365 | uint16_t len, value, index; | 2365 | uint16_t len, value, index; | |
2366 | int l, totlen = 0; | 2366 | int l, totlen = 0; | |
2367 | int port, i; | 2367 | int port, i; | |
2368 | uint32_t v; | 2368 | uint32_t v; | |
2369 | 2369 | |||
2370 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | 2370 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | |
2371 | 2371 | |||
2372 | KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock)); | |||
2373 | ||||
2372 | if (sc->sc_dying) | 2374 | if (sc->sc_dying) | |
2373 | return -1; | 2375 | return -1; | |
2374 | 2376 | |||
2375 | DPRINTF("type=0x%02jx request=%02jx", req->bmRequestType, req->bRequest, | 2377 | DPRINTF("type=0x%02jx request=%02jx", req->bmRequestType, req->bRequest, | |
2376 | 0, 0); | 2378 | 0, 0); | |
2377 | 2379 | |||
2378 | len = UGETW(req->wLength); | 2380 | len = UGETW(req->wLength); | |
2379 | value = UGETW(req->wValue); | 2381 | value = UGETW(req->wValue); | |
2380 | index = UGETW(req->wIndex); | 2382 | index = UGETW(req->wIndex); | |
2381 | 2383 | |||
2382 | #define C(x,y) ((x) | ((y) << 8)) | 2384 | #define C(x,y) ((x) | ((y) << 8)) | |
2383 | switch (C(req->bRequest, req->bmRequestType)) { | 2385 | switch (C(req->bRequest, req->bmRequestType)) { | |
2384 | case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): | 2386 | case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): | |
@@ -2747,38 +2749,35 @@ ehci_disown(ehci_softc_t *sc, int index, | @@ -2747,38 +2749,35 @@ ehci_disown(ehci_softc_t *sc, int index, | |||
2747 | 2749 | |||
2748 | Static usbd_status | 2750 | Static usbd_status | |
2749 | ehci_root_intr_transfer(struct usbd_xfer *xfer) | 2751 | ehci_root_intr_transfer(struct usbd_xfer *xfer) | |
2750 | { | 2752 | { | |
2751 | 2753 | |||
2752 | /* Pipe isn't running, start first */ | 2754 | /* Pipe isn't running, start first */ | |
2753 | return ehci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 2755 | return ehci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
2754 | } | 2756 | } | |
2755 | 2757 | |||
2756 | Static usbd_status | 2758 | Static usbd_status | |
2757 | ehci_root_intr_start(struct usbd_xfer *xfer) | 2759 | ehci_root_intr_start(struct usbd_xfer *xfer) | |
2758 | { | 2760 | { | |
2759 | ehci_softc_t *sc = EHCI_XFER2SC(xfer); | 2761 | ehci_softc_t *sc = EHCI_XFER2SC(xfer); | |
2760 | const bool polling = sc->sc_bus.ub_usepolling; | 2762 | ||
2763 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
2761 | 2764 | |||
2762 | if (sc->sc_dying) | 2765 | if (sc->sc_dying) | |
2763 | return USBD_IOERROR; | 2766 | return USBD_IOERROR; | |
2764 | 2767 | |||
2765 | if (!polling) | |||
2766 | mutex_enter(&sc->sc_lock); | |||
2767 | KASSERT(sc->sc_intrxfer == NULL); | 2768 | KASSERT(sc->sc_intrxfer == NULL); | |
2768 | sc->sc_intrxfer = xfer; | 2769 | sc->sc_intrxfer = xfer; | |
2769 | xfer->ux_status = USBD_IN_PROGRESS; | 2770 | xfer->ux_status = USBD_IN_PROGRESS; | |
2770 | if (!polling) | |||
2771 | mutex_exit(&sc->sc_lock); | |||
2772 | 2771 | |||
2773 | return USBD_IN_PROGRESS; | 2772 | return USBD_IN_PROGRESS; | |
2774 | } | 2773 | } | |
2775 | 2774 | |||
2776 | /* Abort a root interrupt request. */ | 2775 | /* Abort a root interrupt request. */ | |
2777 | Static void | 2776 | Static void | |
2778 | ehci_root_intr_abort(struct usbd_xfer *xfer) | 2777 | ehci_root_intr_abort(struct usbd_xfer *xfer) | |
2779 | { | 2778 | { | |
2780 | ehci_softc_t *sc = EHCI_XFER2SC(xfer); | 2779 | ehci_softc_t *sc = EHCI_XFER2SC(xfer); | |
2781 | 2780 | |||
2782 | KASSERT(mutex_owned(&sc->sc_lock)); | 2781 | KASSERT(mutex_owned(&sc->sc_lock)); | |
2783 | KASSERT(xfer->ux_pipe->up_intrxfer == xfer); | 2782 | KASSERT(xfer->ux_pipe->up_intrxfer == xfer); | |
2784 | 2783 | |||
@@ -3597,30 +3596,30 @@ ehci_device_ctrl_transfer(struct usbd_xf | @@ -3597,30 +3596,30 @@ ehci_device_ctrl_transfer(struct usbd_xf | |||
3597 | /* Pipe isn't running, start first */ | 3596 | /* Pipe isn't running, start first */ | |
3598 | return ehci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 3597 | return ehci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
3599 | } | 3598 | } | |
3600 | 3599 | |||
3601 | Static usbd_status | 3600 | Static usbd_status | |
3602 | ehci_device_ctrl_start(struct usbd_xfer *xfer) | 3601 | ehci_device_ctrl_start(struct usbd_xfer *xfer) | |
3603 | { | 3602 | { | |
3604 | struct ehci_pipe *epipe = EHCI_XFER2EPIPE(xfer); | 3603 | struct ehci_pipe *epipe = EHCI_XFER2EPIPE(xfer); | |
3605 | struct ehci_xfer *exfer = EHCI_XFER2EXFER(xfer); | 3604 | struct ehci_xfer *exfer = EHCI_XFER2EXFER(xfer); | |
3606 | usb_device_request_t *req = &xfer->ux_request; | 3605 | usb_device_request_t *req = &xfer->ux_request; | |
3607 | ehci_softc_t *sc = EHCI_XFER2SC(xfer); | 3606 | ehci_softc_t *sc = EHCI_XFER2SC(xfer); | |
3608 | ehci_soft_qtd_t *setup, *status, *next; | 3607 | ehci_soft_qtd_t *setup, *status, *next; | |
3609 | ehci_soft_qh_t *sqh; | 3608 | ehci_soft_qh_t *sqh; | |
3610 | const bool polling = sc->sc_bus.ub_usepolling; | |||
3611 | 3609 | |||
3612 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | 3610 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | |
3613 | 3611 | |||
3612 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
3614 | KASSERT(xfer->ux_rqflags & URQ_REQUEST); | 3613 | KASSERT(xfer->ux_rqflags & URQ_REQUEST); | |
3615 | 3614 | |||
3616 | if (sc->sc_dying) | 3615 | if (sc->sc_dying) | |
3617 | return USBD_IOERROR; | 3616 | return USBD_IOERROR; | |
3618 | 3617 | |||
3619 | const int isread = req->bmRequestType & UT_READ; | 3618 | const int isread = req->bmRequestType & UT_READ; | |
3620 | const int len = UGETW(req->wLength); | 3619 | const int len = UGETW(req->wLength); | |
3621 | 3620 | |||
3622 | DPRINTF("type=0x%02jx, request=0x%02jx, wValue=0x%04jx, wIndex=0x%04jx", | 3621 | DPRINTF("type=0x%02jx, request=0x%02jx, wValue=0x%04jx, wIndex=0x%04jx", | |
3623 | req->bmRequestType, req->bRequest, UGETW(req->wValue), | 3622 | req->bmRequestType, req->bRequest, UGETW(req->wValue), | |
3624 | UGETW(req->wIndex)); | 3623 | UGETW(req->wIndex)); | |
3625 | DPRINTF("len=%jd, addr=%jd, endpt=%jd", | 3624 | DPRINTF("len=%jd, addr=%jd, endpt=%jd", | |
3626 | len, epipe->pipe.up_dev->ud_addr, | 3625 | len, epipe->pipe.up_dev->ud_addr, | |
@@ -3719,36 +3718,31 @@ ehci_device_ctrl_start(struct usbd_xfer | @@ -3719,36 +3718,31 @@ ehci_device_ctrl_start(struct usbd_xfer | |||
3719 | 3718 | |||
3720 | usb_syncmem(&status->dma, status->offs, sizeof(status->qtd), | 3719 | usb_syncmem(&status->dma, status->offs, sizeof(status->qtd), | |
3721 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 3720 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
3722 | 3721 | |||
3723 | KASSERT(status->qtd.qtd_status & htole32(EHCI_QTD_TOGGLE_MASK)); | 3722 | KASSERT(status->qtd.qtd_status & htole32(EHCI_QTD_TOGGLE_MASK)); | |
3724 | 3723 | |||
3725 | #ifdef EHCI_DEBUG | 3724 | #ifdef EHCI_DEBUG | |
3726 | DPRINTFN(5, "--- dump start ---", 0, 0, 0, 0); | 3725 | DPRINTFN(5, "--- dump start ---", 0, 0, 0, 0); | |
3727 | ehci_dump_sqh(sqh); | 3726 | ehci_dump_sqh(sqh); | |
3728 | ehci_dump_sqtds(setup); | 3727 | ehci_dump_sqtds(setup); | |
3729 | DPRINTFN(5, "--- dump end ---", 0, 0, 0, 0); | 3728 | DPRINTFN(5, "--- dump end ---", 0, 0, 0, 0); | |
3730 | #endif | 3729 | #endif | |
3731 | 3730 | |||
3732 | if (!polling) | |||
3733 | mutex_enter(&sc->sc_lock); | |||
3734 | ||||
3735 | /* Insert qTD in QH list - also does usb_syncmem(sqh) */ | 3731 | /* Insert qTD in QH list - also does usb_syncmem(sqh) */ | |
3736 | ehci_set_qh_qtd(sqh, setup); | 3732 | ehci_set_qh_qtd(sqh, setup); | |
3737 | usbd_xfer_schedule_timeout(xfer); | 3733 | usbd_xfer_schedule_timeout(xfer); | |
3738 | ehci_add_intr_list(sc, exfer); | 3734 | ehci_add_intr_list(sc, exfer); | |
3739 | xfer->ux_status = USBD_IN_PROGRESS; | 3735 | xfer->ux_status = USBD_IN_PROGRESS; | |
3740 | if (!polling) | |||
3741 | mutex_exit(&sc->sc_lock); | |||
3742 | 3736 | |||
3743 | #if 0 | 3737 | #if 0 | |
3744 | #ifdef EHCI_DEBUG | 3738 | #ifdef EHCI_DEBUG | |
3745 | DPRINTFN(10, "status=%jx, dump:", EOREAD4(sc, EHCI_USBSTS), 0, 0, 0); | 3739 | DPRINTFN(10, "status=%jx, dump:", EOREAD4(sc, EHCI_USBSTS), 0, 0, 0); | |
3746 | // delay(10000); | 3740 | // delay(10000); | |
3747 | ehci_dump_regs(sc); | 3741 | ehci_dump_regs(sc); | |
3748 | ehci_dump_sqh(sc->sc_async_head); | 3742 | ehci_dump_sqh(sc->sc_async_head); | |
3749 | ehci_dump_sqh(sqh); | 3743 | ehci_dump_sqh(sqh); | |
3750 | ehci_dump_sqtds(setup); | 3744 | ehci_dump_sqtds(setup); | |
3751 | #endif | 3745 | #endif | |
3752 | #endif | 3746 | #endif | |
3753 | 3747 | |||
3754 | return USBD_IN_PROGRESS; | 3748 | return USBD_IN_PROGRESS; | |
@@ -3868,78 +3862,73 @@ ehci_device_bulk_transfer(struct usbd_xf | @@ -3868,78 +3862,73 @@ ehci_device_bulk_transfer(struct usbd_xf | |||
3868 | /* Pipe isn't running, start first */ | 3862 | /* Pipe isn't running, start first */ | |
3869 | return ehci_device_bulk_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 3863 | return ehci_device_bulk_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
3870 | } | 3864 | } | |
3871 | 3865 | |||
3872 | Static usbd_status | 3866 | Static usbd_status | |
3873 | ehci_device_bulk_start(struct usbd_xfer *xfer) | 3867 | ehci_device_bulk_start(struct usbd_xfer *xfer) | |
3874 | { | 3868 | { | |
3875 | struct ehci_pipe *epipe = EHCI_XFER2EPIPE(xfer); | 3869 | struct ehci_pipe *epipe = EHCI_XFER2EPIPE(xfer); | |
3876 | struct ehci_xfer *exfer = EHCI_XFER2EXFER(xfer); | 3870 | struct ehci_xfer *exfer = EHCI_XFER2EXFER(xfer); | |
3877 | ehci_softc_t *sc = EHCI_XFER2SC(xfer); | 3871 | ehci_softc_t *sc = EHCI_XFER2SC(xfer); | |
3878 | ehci_soft_qh_t *sqh; | 3872 | ehci_soft_qh_t *sqh; | |
3879 | ehci_soft_qtd_t *end; | 3873 | ehci_soft_qtd_t *end; | |
3880 | int len, isread, endpt; | 3874 | int len, isread, endpt; | |
3881 | const bool polling = sc->sc_bus.ub_usepolling; | |||
3882 | 3875 | |||
3883 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | 3876 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | |
3884 | 3877 | |||
3885 | DPRINTF("xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, xfer->ux_length, | 3878 | DPRINTF("xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, xfer->ux_length, | |
3886 | xfer->ux_flags, 0); | 3879 | xfer->ux_flags, 0); | |
3887 | 3880 | |||
3881 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
3882 | ||||
3888 | if (sc->sc_dying) | 3883 | if (sc->sc_dying) | |
3889 | return USBD_IOERROR; | 3884 | return USBD_IOERROR; | |
3890 | 3885 | |||
3891 | KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); | 3886 | KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); | |
3892 | KASSERT(xfer->ux_length <= xfer->ux_bufsize); | 3887 | KASSERT(xfer->ux_length <= xfer->ux_bufsize); | |
3893 | 3888 | |||
3894 | len = xfer->ux_length; | 3889 | len = xfer->ux_length; | |
3895 | endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; | 3890 | endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; | |
3896 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | 3891 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | |
3897 | sqh = epipe->sqh; | 3892 | sqh = epipe->sqh; | |
3898 | 3893 | |||
3899 | KASSERT(exfer->ex_isdone); | 3894 | KASSERT(exfer->ex_isdone); | |
3900 | #ifdef DIAGNOSTIC | 3895 | #ifdef DIAGNOSTIC | |
3901 | exfer->ex_isdone = false; | 3896 | exfer->ex_isdone = false; | |
3902 | #endif | 3897 | #endif | |
3903 | 3898 | |||
3904 | /* Take lock here to protect nexttoggle */ | |||
3905 | if (!polling) | |||
3906 | mutex_enter(&sc->sc_lock); | |||
3907 | ||||
3908 | ehci_reset_sqtd_chain(sc, xfer, len, isread, &epipe->nexttoggle, &end); | 3899 | ehci_reset_sqtd_chain(sc, xfer, len, isread, &epipe->nexttoggle, &end); | |
3909 | 3900 | |||
3910 | exfer->ex_sqtdend = end; | 3901 | exfer->ex_sqtdend = end; | |
3911 | end->qtd.qtd_status |= htole32(EHCI_QTD_IOC); | 3902 | end->qtd.qtd_status |= htole32(EHCI_QTD_IOC); | |
3912 | usb_syncmem(&end->dma, end->offs, sizeof(end->qtd), | 3903 | usb_syncmem(&end->dma, end->offs, sizeof(end->qtd), | |
3913 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 3904 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
3914 | 3905 | |||
3915 | #ifdef EHCI_DEBUG | 3906 | #ifdef EHCI_DEBUG | |
3916 | DPRINTFN(5, "--- dump start ---", 0, 0, 0, 0); | 3907 | DPRINTFN(5, "--- dump start ---", 0, 0, 0, 0); | |
3917 | ehci_dump_sqh(sqh); | 3908 | ehci_dump_sqh(sqh); | |
3918 | ehci_dump_sqtds(exfer->ex_sqtdstart); | 3909 | ehci_dump_sqtds(exfer->ex_sqtdstart); | |
3919 | DPRINTFN(5, "--- dump end ---", 0, 0, 0, 0); | 3910 | DPRINTFN(5, "--- dump end ---", 0, 0, 0, 0); | |
3920 | #endif | 3911 | #endif | |
3921 | 3912 | |||
3922 | if (xfer->ux_length) | 3913 | if (xfer->ux_length) | |
3923 | usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, | 3914 | usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, | |
3924 | isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | 3915 | isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | |
3925 | 3916 | |||
3926 | /* also does usb_syncmem(sqh) */ | 3917 | /* also does usb_syncmem(sqh) */ | |
3927 | ehci_set_qh_qtd(sqh, exfer->ex_sqtdstart); | 3918 | ehci_set_qh_qtd(sqh, exfer->ex_sqtdstart); | |
3928 | usbd_xfer_schedule_timeout(xfer); | 3919 | usbd_xfer_schedule_timeout(xfer); | |
3929 | ehci_add_intr_list(sc, exfer); | 3920 | ehci_add_intr_list(sc, exfer); | |
3930 | xfer->ux_status = USBD_IN_PROGRESS; | 3921 | xfer->ux_status = USBD_IN_PROGRESS; | |
3931 | if (!polling) | |||
3932 | mutex_exit(&sc->sc_lock); | |||
3933 | 3922 | |||
3934 | #if 0 | 3923 | #if 0 | |
3935 | #ifdef EHCI_DEBUG | 3924 | #ifdef EHCI_DEBUG | |
3936 | DPRINTFN(5, "data(2)", 0, 0, 0, 0); | 3925 | DPRINTFN(5, "data(2)", 0, 0, 0, 0); | |
3937 | // delay(10000); | 3926 | // delay(10000); | |
3938 | DPRINTFN(5, "data(3)", 0, 0, 0, 0); | 3927 | DPRINTFN(5, "data(3)", 0, 0, 0, 0); | |
3939 | ehci_dump_regs(sc); | 3928 | ehci_dump_regs(sc); | |
3940 | #if 0 | 3929 | #if 0 | |
3941 | printf("async_head:\n"); | 3930 | printf("async_head:\n"); | |
3942 | ehci_dump_sqh(sc->sc_async_head); | 3931 | ehci_dump_sqh(sc->sc_async_head); | |
3943 | #endif | 3932 | #endif | |
3944 | DPRINTF("sqh:", 0, 0, 0, 0); | 3933 | DPRINTF("sqh:", 0, 0, 0, 0); | |
3945 | ehci_dump_sqh(sqh); | 3934 | ehci_dump_sqh(sqh); | |
@@ -4072,78 +4061,73 @@ ehci_device_intr_transfer(struct usbd_xf | @@ -4072,78 +4061,73 @@ ehci_device_intr_transfer(struct usbd_xf | |||
4072 | /* Pipe isn't running, so start it first. */ | 4061 | /* Pipe isn't running, so start it first. */ | |
4073 | return ehci_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 4062 | return ehci_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
4074 | } | 4063 | } | |
4075 | 4064 | |||
4076 | Static usbd_status | 4065 | Static usbd_status | |
4077 | ehci_device_intr_start(struct usbd_xfer *xfer) | 4066 | ehci_device_intr_start(struct usbd_xfer *xfer) | |
4078 | { | 4067 | { | |
4079 | struct ehci_pipe *epipe = EHCI_XFER2EPIPE(xfer); | 4068 | struct ehci_pipe *epipe = EHCI_XFER2EPIPE(xfer); | |
4080 | struct ehci_xfer *exfer = EHCI_XFER2EXFER(xfer); | 4069 | struct ehci_xfer *exfer = EHCI_XFER2EXFER(xfer); | |
4081 | ehci_softc_t *sc = EHCI_XFER2SC(xfer); | 4070 | ehci_softc_t *sc = EHCI_XFER2SC(xfer); | |
4082 | ehci_soft_qtd_t *end; | 4071 | ehci_soft_qtd_t *end; | |
4083 | ehci_soft_qh_t *sqh; | 4072 | ehci_soft_qh_t *sqh; | |
4084 | int len, isread, endpt; | 4073 | int len, isread, endpt; | |
4085 | const bool polling = sc->sc_bus.ub_usepolling; | |||
4086 | 4074 | |||
4087 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | 4075 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | |
4088 | 4076 | |||
4089 | DPRINTF("xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, xfer->ux_length, | 4077 | DPRINTF("xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, xfer->ux_length, | |
4090 | xfer->ux_flags, 0); | 4078 | xfer->ux_flags, 0); | |
4091 | 4079 | |||
4080 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
4081 | ||||
4092 | if (sc->sc_dying) | 4082 | if (sc->sc_dying) | |
4093 | return USBD_IOERROR; | 4083 | return USBD_IOERROR; | |
4094 | 4084 | |||
4095 | KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); | 4085 | KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); | |
4096 | KASSERT(xfer->ux_length <= xfer->ux_bufsize); | 4086 | KASSERT(xfer->ux_length <= xfer->ux_bufsize); | |
4097 | 4087 | |||
4098 | len = xfer->ux_length; | 4088 | len = xfer->ux_length; | |
4099 | endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; | 4089 | endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; | |
4100 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | 4090 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | |
4101 | sqh = epipe->sqh; | 4091 | sqh = epipe->sqh; | |
4102 | 4092 | |||
4103 | KASSERT(exfer->ex_isdone); | 4093 | KASSERT(exfer->ex_isdone); | |
4104 | #ifdef DIAGNOSTIC | 4094 | #ifdef DIAGNOSTIC | |
4105 | exfer->ex_isdone = false; | 4095 | exfer->ex_isdone = false; | |
4106 | #endif | 4096 | #endif | |
4107 | 4097 | |||
4108 | /* Take lock to protect nexttoggle */ | |||
4109 | if (!polling) | |||
4110 | mutex_enter(&sc->sc_lock); | |||
4111 | ||||
4112 | ehci_reset_sqtd_chain(sc, xfer, len, isread, &epipe->nexttoggle, &end); | 4098 | ehci_reset_sqtd_chain(sc, xfer, len, isread, &epipe->nexttoggle, &end); | |
4113 | 4099 | |||
4114 | end->qtd.qtd_status |= htole32(EHCI_QTD_IOC); | 4100 | end->qtd.qtd_status |= htole32(EHCI_QTD_IOC); | |
4115 | usb_syncmem(&end->dma, end->offs, sizeof(end->qtd), | 4101 | usb_syncmem(&end->dma, end->offs, sizeof(end->qtd), | |
4116 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 4102 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
4117 | exfer->ex_sqtdend = end; | 4103 | exfer->ex_sqtdend = end; | |
4118 | 4104 | |||
4119 | #ifdef EHCI_DEBUG | 4105 | #ifdef EHCI_DEBUG | |
4120 | DPRINTFN(5, "--- dump start ---", 0, 0, 0, 0); | 4106 | DPRINTFN(5, "--- dump start ---", 0, 0, 0, 0); | |
4121 | ehci_dump_sqh(sqh); | 4107 | ehci_dump_sqh(sqh); | |
4122 | ehci_dump_sqtds(exfer->ex_sqtdstart); | 4108 | ehci_dump_sqtds(exfer->ex_sqtdstart); | |
4123 | DPRINTFN(5, "--- dump end ---", 0, 0, 0, 0); | 4109 | DPRINTFN(5, "--- dump end ---", 0, 0, 0, 0); | |
4124 | #endif | 4110 | #endif | |
4125 | 4111 | |||
4126 | if (xfer->ux_length) | 4112 | if (xfer->ux_length) | |
4127 | usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, | 4113 | usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, | |
4128 | isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | 4114 | isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | |
4129 | 4115 | |||
4130 | /* also does usb_syncmem(sqh) */ | 4116 | /* also does usb_syncmem(sqh) */ | |
4131 | ehci_set_qh_qtd(sqh, exfer->ex_sqtdstart); | 4117 | ehci_set_qh_qtd(sqh, exfer->ex_sqtdstart); | |
4132 | usbd_xfer_schedule_timeout(xfer); | 4118 | usbd_xfer_schedule_timeout(xfer); | |
4133 | ehci_add_intr_list(sc, exfer); | 4119 | ehci_add_intr_list(sc, exfer); | |
4134 | xfer->ux_status = USBD_IN_PROGRESS; | 4120 | xfer->ux_status = USBD_IN_PROGRESS; | |
4135 | if (!polling) | |||
4136 | mutex_exit(&sc->sc_lock); | |||
4137 | 4121 | |||
4138 | #if 0 | 4122 | #if 0 | |
4139 | #ifdef EHCI_DEBUG | 4123 | #ifdef EHCI_DEBUG | |
4140 | DPRINTFN(5, "data(2)", 0, 0, 0, 0); | 4124 | DPRINTFN(5, "data(2)", 0, 0, 0, 0); | |
4141 | // delay(10000); | 4125 | // delay(10000); | |
4142 | DPRINTFN(5, "data(3)", 0, 0, 0, 0); | 4126 | DPRINTFN(5, "data(3)", 0, 0, 0, 0); | |
4143 | ehci_dump_regs(sc); | 4127 | ehci_dump_regs(sc); | |
4144 | DPRINTFN(5, "sqh:", 0, 0, 0, 0); | 4128 | DPRINTFN(5, "sqh:", 0, 0, 0, 0); | |
4145 | ehci_dump_sqh(sqh); | 4129 | ehci_dump_sqh(sqh); | |
4146 | ehci_dump_sqtds(exfer->ex_sqtdstart); | 4130 | ehci_dump_sqtds(exfer->ex_sqtdstart); | |
4147 | #endif | 4131 | #endif | |
4148 | #endif | 4132 | #endif | |
4149 | 4133 | |||
@@ -4315,26 +4299,28 @@ ehci_device_fs_isoc_transfer(struct usbd | @@ -4315,26 +4299,28 @@ ehci_device_fs_isoc_transfer(struct usbd | |||
4315 | usb_dma_t *dma_buf; | 4299 | usb_dma_t *dma_buf; | |
4316 | int i, j, k, frames; | 4300 | int i, j, k, frames; | |
4317 | int offs; | 4301 | int offs; | |
4318 | int frindex; | 4302 | int frindex; | |
4319 | u_int dir; | 4303 | u_int dir; | |
4320 | 4304 | |||
4321 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | 4305 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | |
4322 | 4306 | |||
4323 | sitd = NULL; | 4307 | sitd = NULL; | |
4324 | 4308 | |||
4325 | DPRINTF("xfer %#jx len %jd flags %jd", (uintptr_t)xfer, xfer->ux_length, | 4309 | DPRINTF("xfer %#jx len %jd flags %jd", (uintptr_t)xfer, xfer->ux_length, | |
4326 | xfer->ux_flags, 0); | 4310 | xfer->ux_flags, 0); | |
4327 | 4311 | |||
4312 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
4313 | ||||
4328 | if (sc->sc_dying) | 4314 | if (sc->sc_dying) | |
4329 | return USBD_IOERROR; | 4315 | return USBD_IOERROR; | |
4330 | 4316 | |||
4331 | /* | 4317 | /* | |
4332 | * To avoid complication, don't allow a request right now that'll span | 4318 | * To avoid complication, don't allow a request right now that'll span | |
4333 | * the entire frame table. To within 4 frames, to allow some leeway | 4319 | * the entire frame table. To within 4 frames, to allow some leeway | |
4334 | * on either side of where the hc currently is. | 4320 | * on either side of where the hc currently is. | |
4335 | */ | 4321 | */ | |
4336 | if (epipe->pipe.up_endpoint->ue_edesc->bInterval * | 4322 | if (epipe->pipe.up_endpoint->ue_edesc->bInterval * | |
4337 | xfer->ux_nframes >= sc->sc_flsize - 4) { | 4323 | xfer->ux_nframes >= sc->sc_flsize - 4) { | |
4338 | printf("ehci: isoc descriptor requested that spans the entire" | 4324 | printf("ehci: isoc descriptor requested that spans the entire" | |
4339 | "frametable, too many frames\n"); | 4325 | "frametable, too many frames\n"); | |
4340 | return USBD_INVAL; | 4326 | return USBD_INVAL; | |
@@ -4448,28 +4434,26 @@ ehci_device_fs_isoc_transfer(struct usbd | @@ -4448,28 +4434,26 @@ ehci_device_fs_isoc_transfer(struct usbd | |||
4448 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 4434 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
4449 | 4435 | |||
4450 | if (xfer->ux_length) | 4436 | if (xfer->ux_length) | |
4451 | usb_syncmem(&exfer->ex_xfer.ux_dmabuf, 0, xfer->ux_length, | 4437 | usb_syncmem(&exfer->ex_xfer.ux_dmabuf, 0, xfer->ux_length, | |
4452 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | 4438 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | |
4453 | 4439 | |||
4454 | /* | 4440 | /* | |
4455 | * Part 2: Transfer descriptors have now been set up, now they must | 4441 | * Part 2: Transfer descriptors have now been set up, now they must | |
4456 | * be scheduled into the periodic frame list. Erk. Not wanting to | 4442 | * be scheduled into the periodic frame list. Erk. Not wanting to | |
4457 | * complicate matters, transfer is denied if the transfer spans | 4443 | * complicate matters, transfer is denied if the transfer spans | |
4458 | * more than the period frame list. | 4444 | * more than the period frame list. | |
4459 | */ | 4445 | */ | |
4460 | 4446 | |||
4461 | mutex_enter(&sc->sc_lock); | |||
4462 | ||||
4463 | /* Start inserting frames */ | 4447 | /* Start inserting frames */ | |
4464 | if (epipe->isoc.cur_xfers > 0) { | 4448 | if (epipe->isoc.cur_xfers > 0) { | |
4465 | frindex = epipe->isoc.next_frame; | 4449 | frindex = epipe->isoc.next_frame; | |
4466 | } else { | 4450 | } else { | |
4467 | frindex = EOREAD4(sc, EHCI_FRINDEX); | 4451 | frindex = EOREAD4(sc, EHCI_FRINDEX); | |
4468 | frindex = frindex >> 3; /* Erase microframe index */ | 4452 | frindex = frindex >> 3; /* Erase microframe index */ | |
4469 | frindex += 2; | 4453 | frindex += 2; | |
4470 | } | 4454 | } | |
4471 | 4455 | |||
4472 | if (frindex >= sc->sc_flsize) | 4456 | if (frindex >= sc->sc_flsize) | |
4473 | frindex &= (sc->sc_flsize - 1); | 4457 | frindex &= (sc->sc_flsize - 1); | |
4474 | 4458 | |||
4475 | /* Whats the frame interval? */ | 4459 | /* Whats the frame interval? */ | |
@@ -4512,27 +4496,26 @@ ehci_device_fs_isoc_transfer(struct usbd | @@ -4512,27 +4496,26 @@ ehci_device_fs_isoc_transfer(struct usbd | |||
4512 | sitd->slot = frindex; | 4496 | sitd->slot = frindex; | |
4513 | sitd->frame_list.prev = NULL; | 4497 | sitd->frame_list.prev = NULL; | |
4514 | 4498 | |||
4515 | frindex += i; | 4499 | frindex += i; | |
4516 | if (frindex >= sc->sc_flsize) | 4500 | if (frindex >= sc->sc_flsize) | |
4517 | frindex -= sc->sc_flsize; | 4501 | frindex -= sc->sc_flsize; | |
4518 | } | 4502 | } | |
4519 | 4503 | |||
4520 | epipe->isoc.cur_xfers++; | 4504 | epipe->isoc.cur_xfers++; | |
4521 | epipe->isoc.next_frame = frindex; | 4505 | epipe->isoc.next_frame = frindex; | |
4522 | 4506 | |||
4523 | ehci_add_intr_list(sc, exfer); | 4507 | ehci_add_intr_list(sc, exfer); | |
4524 | xfer->ux_status = USBD_IN_PROGRESS; | 4508 | xfer->ux_status = USBD_IN_PROGRESS; | |
4525 | mutex_exit(&sc->sc_lock); | |||
4526 | 4509 | |||
4527 | return USBD_IN_PROGRESS; | 4510 | return USBD_IN_PROGRESS; | |
4528 | } | 4511 | } | |
4529 | 4512 | |||
4530 | Static void | 4513 | Static void | |
4531 | ehci_device_fs_isoc_abort(struct usbd_xfer *xfer) | 4514 | ehci_device_fs_isoc_abort(struct usbd_xfer *xfer) | |
4532 | { | 4515 | { | |
4533 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | 4516 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | |
4534 | 4517 | |||
4535 | DPRINTF("xfer = %#jx", (uintptr_t)xfer, 0, 0, 0); | 4518 | DPRINTF("xfer = %#jx", (uintptr_t)xfer, 0, 0, 0); | |
4536 | ehci_abort_isoc_xfer(xfer, USBD_CANCELLED); | 4519 | ehci_abort_isoc_xfer(xfer, USBD_CANCELLED); | |
4537 | } | 4520 | } | |
4538 | 4521 | |||
@@ -4680,26 +4663,28 @@ ehci_device_isoc_transfer(struct usbd_xf | @@ -4680,26 +4663,28 @@ ehci_device_isoc_transfer(struct usbd_xf | |||
4680 | int i, j; | 4663 | int i, j; | |
4681 | int frames, uframes, ufrperframe; | 4664 | int frames, uframes, ufrperframe; | |
4682 | int trans_count, offs; | 4665 | int trans_count, offs; | |
4683 | int frindex; | 4666 | int frindex; | |
4684 | 4667 | |||
4685 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | 4668 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | |
4686 | 4669 | |||
4687 | prev = NULL; | 4670 | prev = NULL; | |
4688 | itd = NULL; | 4671 | itd = NULL; | |
4689 | trans_count = 0; | 4672 | trans_count = 0; | |
4690 | 4673 | |||
4691 | DPRINTF("xfer %#jx flags %jd", (uintptr_t)xfer, xfer->ux_flags, 0, 0); | 4674 | DPRINTF("xfer %#jx flags %jd", (uintptr_t)xfer, xfer->ux_flags, 0, 0); | |
4692 | 4675 | |||
4676 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
4677 | ||||
4693 | if (sc->sc_dying) | 4678 | if (sc->sc_dying) | |
4694 | return USBD_IOERROR; | 4679 | return USBD_IOERROR; | |
4695 | 4680 | |||
4696 | /* | 4681 | /* | |
4697 | * To avoid complication, don't allow a request right now that'll span | 4682 | * To avoid complication, don't allow a request right now that'll span | |
4698 | * the entire frame table. To within 4 frames, to allow some leeway | 4683 | * the entire frame table. To within 4 frames, to allow some leeway | |
4699 | * on either side of where the hc currently is. | 4684 | * on either side of where the hc currently is. | |
4700 | */ | 4685 | */ | |
4701 | if ((1 << (epipe->pipe.up_endpoint->ue_edesc->bInterval)) * | 4686 | if ((1 << (epipe->pipe.up_endpoint->ue_edesc->bInterval)) * | |
4702 | xfer->ux_nframes >= (sc->sc_flsize - 4) * 8) { | 4687 | xfer->ux_nframes >= (sc->sc_flsize - 4) * 8) { | |
4703 | DPRINTF( | 4688 | DPRINTF( | |
4704 | "isoc descriptor spans entire frametable", 0, 0, 0, 0); | 4689 | "isoc descriptor spans entire frametable", 0, 0, 0, 0); | |
4705 | printf("ehci: isoc descriptor requested that spans the entire frametable, too many frames\n"); | 4690 | printf("ehci: isoc descriptor requested that spans the entire frametable, too many frames\n"); | |
@@ -4826,28 +4811,26 @@ ehci_device_isoc_transfer(struct usbd_xf | @@ -4826,28 +4811,26 @@ ehci_device_isoc_transfer(struct usbd_xf | |||
4826 | } /* End of frame */ | 4811 | } /* End of frame */ | |
4827 | 4812 | |||
4828 | if (xfer->ux_length) | 4813 | if (xfer->ux_length) | |
4829 | usb_syncmem(&exfer->ex_xfer.ux_dmabuf, 0, xfer->ux_length, | 4814 | usb_syncmem(&exfer->ex_xfer.ux_dmabuf, 0, xfer->ux_length, | |
4830 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | 4815 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | |
4831 | 4816 | |||
4832 | /* | 4817 | /* | |
4833 | * Part 2: Transfer descriptors have now been set up, now they must | 4818 | * Part 2: Transfer descriptors have now been set up, now they must | |
4834 | * be scheduled into the period frame list. Erk. Not wanting to | 4819 | * be scheduled into the period frame list. Erk. Not wanting to | |
4835 | * complicate matters, transfer is denied if the transfer spans | 4820 | * complicate matters, transfer is denied if the transfer spans | |
4836 | * more than the period frame list. | 4821 | * more than the period frame list. | |
4837 | */ | 4822 | */ | |
4838 | 4823 | |||
4839 | mutex_enter(&sc->sc_lock); | |||
4840 | ||||
4841 | /* Start inserting frames */ | 4824 | /* Start inserting frames */ | |
4842 | if (epipe->isoc.cur_xfers > 0) { | 4825 | if (epipe->isoc.cur_xfers > 0) { | |
4843 | frindex = epipe->isoc.next_frame; | 4826 | frindex = epipe->isoc.next_frame; | |
4844 | } else { | 4827 | } else { | |
4845 | frindex = EOREAD4(sc, EHCI_FRINDEX); | 4828 | frindex = EOREAD4(sc, EHCI_FRINDEX); | |
4846 | frindex = frindex >> 3; /* Erase microframe index */ | 4829 | frindex = frindex >> 3; /* Erase microframe index */ | |
4847 | frindex += 2; | 4830 | frindex += 2; | |
4848 | } | 4831 | } | |
4849 | 4832 | |||
4850 | if (frindex >= sc->sc_flsize) | 4833 | if (frindex >= sc->sc_flsize) | |
4851 | frindex &= (sc->sc_flsize - 1); | 4834 | frindex &= (sc->sc_flsize - 1); | |
4852 | 4835 | |||
4853 | /* What's the frame interval? */ | 4836 | /* What's the frame interval? */ | |
@@ -4895,27 +4878,26 @@ ehci_device_isoc_transfer(struct usbd_xf | @@ -4895,27 +4878,26 @@ ehci_device_isoc_transfer(struct usbd_xf | |||
4895 | 4878 | |||
4896 | frindex += i; | 4879 | frindex += i; | |
4897 | if (frindex >= sc->sc_flsize) | 4880 | if (frindex >= sc->sc_flsize) | |
4898 | frindex -= sc->sc_flsize; | 4881 | frindex -= sc->sc_flsize; | |
4899 | 4882 | |||
4900 | itd = itd->xfer_next; | 4883 | itd = itd->xfer_next; | |
4901 | } | 4884 | } | |
4902 | 4885 | |||
4903 | epipe->isoc.cur_xfers++; | 4886 | epipe->isoc.cur_xfers++; | |
4904 | epipe->isoc.next_frame = frindex; | 4887 | epipe->isoc.next_frame = frindex; | |
4905 | 4888 | |||
4906 | ehci_add_intr_list(sc, exfer); | 4889 | ehci_add_intr_list(sc, exfer); | |
4907 | xfer->ux_status = USBD_IN_PROGRESS; | 4890 | xfer->ux_status = USBD_IN_PROGRESS; | |
4908 | mutex_exit(&sc->sc_lock); | |||
4909 | 4891 | |||
4910 | return USBD_IN_PROGRESS; | 4892 | return USBD_IN_PROGRESS; | |
4911 | } | 4893 | } | |
4912 | 4894 | |||
4913 | Static void | 4895 | Static void | |
4914 | ehci_device_isoc_abort(struct usbd_xfer *xfer) | 4896 | ehci_device_isoc_abort(struct usbd_xfer *xfer) | |
4915 | { | 4897 | { | |
4916 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | 4898 | EHCIHIST_FUNC(); EHCIHIST_CALLED(); | |
4917 | 4899 | |||
4918 | DPRINTF("xfer = %#jx", (uintptr_t)xfer, 0, 0, 0); | 4900 | DPRINTF("xfer = %#jx", (uintptr_t)xfer, 0, 0, 0); | |
4919 | ehci_abort_isoc_xfer(xfer, USBD_CANCELLED); | 4901 | ehci_abort_isoc_xfer(xfer, USBD_CANCELLED); | |
4920 | } | 4902 | } | |
4921 | 4903 |
--- src/sys/dev/usb/motg.c 2022/03/03 06:08:50 1.39
+++ src/sys/dev/usb/motg.c 2022/03/03 06:12:11 1.40
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: motg.c,v 1.39 2022/03/03 06:08:50 riastradh Exp $ */ | 1 | /* $NetBSD: motg.c,v 1.40 2022/03/03 06:12:11 riastradh Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2004, 2011, 2012, 2014 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 2004, 2011, 2012, 2014 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Lennart Augustsson (lennart@augustsson.net) at | 8 | * by Lennart Augustsson (lennart@augustsson.net) at | |
9 | * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca), | 9 | * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca), | |
10 | * Matthew R. Green (mrg@eterna.com.au), and Manuel Bouyer (bouyer@netbsd.org). | 10 | * Matthew R. Green (mrg@eterna.com.au), and Manuel Bouyer (bouyer@netbsd.org). | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
@@ -30,27 +30,27 @@ | @@ -30,27 +30,27 @@ | |||
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
31 | * POSSIBILITY OF SUCH DAMAGE. | 31 | * POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | 34 | |||
35 | /* | 35 | /* | |
36 | * This file contains the driver for the Mentor Graphics Inventra USB | 36 | * This file contains the driver for the Mentor Graphics Inventra USB | |
37 | * 2.0 High Speed Dual-Role controller. | 37 | * 2.0 High Speed Dual-Role controller. | |
38 | * | 38 | * | |
39 | * NOTE: The current implementation only supports Device Side Mode! | 39 | * NOTE: The current implementation only supports Device Side Mode! | |
40 | */ | 40 | */ | |
41 | 41 | |||
42 | #include <sys/cdefs.h> | 42 | #include <sys/cdefs.h> | |
43 | __KERNEL_RCSID(0, "$NetBSD: motg.c,v 1.39 2022/03/03 06:08:50 riastradh Exp $"); | 43 | __KERNEL_RCSID(0, "$NetBSD: motg.c,v 1.40 2022/03/03 06:12:11 riastradh Exp $"); | |
44 | 44 | |||
45 | #ifdef _KERNEL_OPT | 45 | #ifdef _KERNEL_OPT | |
46 | #include "opt_usb.h" | 46 | #include "opt_usb.h" | |
47 | #endif | 47 | #endif | |
48 | 48 | |||
49 | #include <sys/param.h> | 49 | #include <sys/param.h> | |
50 | 50 | |||
51 | #include <sys/bus.h> | 51 | #include <sys/bus.h> | |
52 | #include <sys/cpu.h> | 52 | #include <sys/cpu.h> | |
53 | #include <sys/device.h> | 53 | #include <sys/device.h> | |
54 | #include <sys/kernel.h> | 54 | #include <sys/kernel.h> | |
55 | #include <sys/kmem.h> | 55 | #include <sys/kmem.h> | |
56 | #include <sys/proc.h> | 56 | #include <sys/proc.h> | |
@@ -796,26 +796,28 @@ motg_get_lock(struct usbd_bus *bus, kmut | @@ -796,26 +796,28 @@ motg_get_lock(struct usbd_bus *bus, kmut | |||
796 | Static int | 796 | Static int | |
797 | motg_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, | 797 | motg_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, | |
798 | void *buf, int buflen) | 798 | void *buf, int buflen) | |
799 | { | 799 | { | |
800 | struct motg_softc *sc = MOTG_BUS2SC(bus); | 800 | struct motg_softc *sc = MOTG_BUS2SC(bus); | |
801 | int status, change, totlen = 0; | 801 | int status, change, totlen = 0; | |
802 | uint16_t len, value, index; | 802 | uint16_t len, value, index; | |
803 | usb_port_status_t ps; | 803 | usb_port_status_t ps; | |
804 | usbd_status err; | 804 | usbd_status err; | |
805 | uint32_t val; | 805 | uint32_t val; | |
806 | 806 | |||
807 | MOTGHIST_FUNC(); MOTGHIST_CALLED(); | 807 | MOTGHIST_FUNC(); MOTGHIST_CALLED(); | |
808 | 808 | |||
809 | KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock)); | |||
810 | ||||
809 | if (sc->sc_dying) | 811 | if (sc->sc_dying) | |
810 | return -1; | 812 | return -1; | |
811 | 813 | |||
812 | DPRINTFN(MD_ROOT, "type=0x%02jx request=%02jx", req->bmRequestType, | 814 | DPRINTFN(MD_ROOT, "type=0x%02jx request=%02jx", req->bmRequestType, | |
813 | req->bRequest, 0, 0); | 815 | req->bRequest, 0, 0); | |
814 | 816 | |||
815 | len = UGETW(req->wLength); | 817 | len = UGETW(req->wLength); | |
816 | value = UGETW(req->wValue); | 818 | value = UGETW(req->wValue); | |
817 | index = UGETW(req->wIndex); | 819 | index = UGETW(req->wIndex); | |
818 | 820 | |||
819 | #define C(x,y) ((x) | ((y) << 8)) | 821 | #define C(x,y) ((x) | ((y) << 8)) | |
820 | switch (C(req->bRequest, req->bmRequestType)) { | 822 | switch (C(req->bRequest, req->bmRequestType)) { | |
821 | case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): | 823 | case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): | |
@@ -1010,43 +1012,40 @@ usbd_status | @@ -1010,43 +1012,40 @@ usbd_status | |||
1010 | motg_root_intr_transfer(struct usbd_xfer *xfer) | 1012 | motg_root_intr_transfer(struct usbd_xfer *xfer) | |
1011 | { | 1013 | { | |
1012 | 1014 | |||
1013 | /* Pipe isn't running, start first */ | 1015 | /* Pipe isn't running, start first */ | |
1014 | return motg_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 1016 | return motg_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
1015 | } | 1017 | } | |
1016 | 1018 | |||
1017 | /* Start a transfer on the root interrupt pipe */ | 1019 | /* Start a transfer on the root interrupt pipe */ | |
1018 | usbd_status | 1020 | usbd_status | |
1019 | motg_root_intr_start(struct usbd_xfer *xfer) | 1021 | motg_root_intr_start(struct usbd_xfer *xfer) | |
1020 | { | 1022 | { | |
1021 | struct usbd_pipe *pipe = xfer->ux_pipe; | 1023 | struct usbd_pipe *pipe = xfer->ux_pipe; | |
1022 | struct motg_softc *sc = MOTG_PIPE2SC(pipe); | 1024 | struct motg_softc *sc = MOTG_PIPE2SC(pipe); | |
1023 | const bool polling = sc->sc_bus.ub_usepolling; | |||
1024 | 1025 | |||
1025 | MOTGHIST_FUNC(); MOTGHIST_CALLED(); | 1026 | MOTGHIST_FUNC(); MOTGHIST_CALLED(); | |
1026 | 1027 | |||
1027 | DPRINTFN(MD_ROOT, "xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, | 1028 | DPRINTFN(MD_ROOT, "xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, | |
1028 | xfer->ux_length, xfer->ux_flags, 0); | 1029 | xfer->ux_length, xfer->ux_flags, 0); | |
1029 | 1030 | |||
1031 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
1032 | ||||
1030 | if (sc->sc_dying) | 1033 | if (sc->sc_dying) | |
1031 | return USBD_IOERROR; | 1034 | return USBD_IOERROR; | |
1032 | 1035 | |||
1033 | if (!polling) | |||
1034 | mutex_enter(&sc->sc_lock); | |||
1035 | KASSERT(sc->sc_intr_xfer == NULL); | 1036 | KASSERT(sc->sc_intr_xfer == NULL); | |
1036 | sc->sc_intr_xfer = xfer; | 1037 | sc->sc_intr_xfer = xfer; | |
1037 | xfer->ux_status = USBD_IN_PROGRESS; | 1038 | xfer->ux_status = USBD_IN_PROGRESS; | |
1038 | if (!polling) | |||
1039 | mutex_exit(&sc->sc_lock); | |||
1040 | 1039 | |||
1041 | return USBD_IN_PROGRESS; | 1040 | return USBD_IN_PROGRESS; | |
1042 | } | 1041 | } | |
1043 | 1042 | |||
1044 | /* Close the root interrupt pipe. */ | 1043 | /* Close the root interrupt pipe. */ | |
1045 | void | 1044 | void | |
1046 | motg_root_intr_close(struct usbd_pipe *pipe) | 1045 | motg_root_intr_close(struct usbd_pipe *pipe) | |
1047 | { | 1046 | { | |
1048 | struct motg_softc *sc __diagused = MOTG_PIPE2SC(pipe); | 1047 | struct motg_softc *sc __diagused = MOTG_PIPE2SC(pipe); | |
1049 | MOTGHIST_FUNC(); MOTGHIST_CALLED(); | 1048 | MOTGHIST_FUNC(); MOTGHIST_CALLED(); | |
1050 | 1049 | |||
1051 | KASSERT(mutex_owned(&sc->sc_lock)); | 1050 | KASSERT(mutex_owned(&sc->sc_lock)); | |
1052 | 1051 | |||
@@ -1266,31 +1265,30 @@ motg_setup_endpoint_rx(struct usbd_xfer | @@ -1266,31 +1265,30 @@ motg_setup_endpoint_rx(struct usbd_xfer | |||
1266 | 1265 | |||
1267 | static usbd_status | 1266 | static usbd_status | |
1268 | motg_device_ctrl_transfer(struct usbd_xfer *xfer) | 1267 | motg_device_ctrl_transfer(struct usbd_xfer *xfer) | |
1269 | { | 1268 | { | |
1270 | 1269 | |||
1271 | /* Pipe isn't running, so start it first. */ | 1270 | /* Pipe isn't running, so start it first. */ | |
1272 | return motg_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 1271 | return motg_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
1273 | } | 1272 | } | |
1274 | 1273 | |||
1275 | static usbd_status | 1274 | static usbd_status | |
1276 | motg_device_ctrl_start(struct usbd_xfer *xfer) | 1275 | motg_device_ctrl_start(struct usbd_xfer *xfer) | |
1277 | { | 1276 | { | |
1278 | struct motg_softc *sc = MOTG_XFER2SC(xfer); | 1277 | struct motg_softc *sc = MOTG_XFER2SC(xfer); | |
1279 | usbd_status err; | 1278 | ||
1280 | mutex_enter(&sc->sc_lock); | 1279 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |
1281 | err = motg_device_ctrl_start1(sc); | 1280 | ||
1282 | mutex_exit(&sc->sc_lock); | 1281 | return motg_device_ctrl_start1(sc); | |
1283 | return err; | |||
1284 | } | 1282 | } | |
1285 | 1283 | |||
1286 | static usbd_status | 1284 | static usbd_status | |
1287 | motg_device_ctrl_start1(struct motg_softc *sc) | 1285 | motg_device_ctrl_start1(struct motg_softc *sc) | |
1288 | { | 1286 | { | |
1289 | struct motg_hw_ep *ep = &sc->sc_in_ep[0]; | 1287 | struct motg_hw_ep *ep = &sc->sc_in_ep[0]; | |
1290 | struct usbd_xfer *xfer = NULL; | 1288 | struct usbd_xfer *xfer = NULL; | |
1291 | struct motg_pipe *otgpipe; | 1289 | struct motg_pipe *otgpipe; | |
1292 | usbd_status err = 0; | 1290 | usbd_status err = 0; | |
1293 | 1291 | |||
1294 | MOTGHIST_FUNC(); MOTGHIST_CALLED(); | 1292 | MOTGHIST_FUNC(); MOTGHIST_CALLED(); | |
1295 | 1293 | |||
1296 | KASSERT(mutex_owned(&sc->sc_lock)); | 1294 | KASSERT(mutex_owned(&sc->sc_lock)); | |
@@ -1707,35 +1705,34 @@ static usbd_status | @@ -1707,35 +1705,34 @@ static usbd_status | |||
1707 | motg_device_data_transfer(struct usbd_xfer *xfer) | 1705 | motg_device_data_transfer(struct usbd_xfer *xfer) | |
1708 | { | 1706 | { | |
1709 | MOTGHIST_FUNC(); MOTGHIST_CALLED(); | 1707 | MOTGHIST_FUNC(); MOTGHIST_CALLED(); | |
1710 | 1708 | |||
1711 | /* Pipe isn't running, so start it first. */ | 1709 | /* Pipe isn't running, so start it first. */ | |
1712 | return motg_device_data_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 1710 | return motg_device_data_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
1713 | } | 1711 | } | |
1714 | 1712 | |||
1715 | static usbd_status | 1713 | static usbd_status | |
1716 | motg_device_data_start(struct usbd_xfer *xfer) | 1714 | motg_device_data_start(struct usbd_xfer *xfer) | |
1717 | { | 1715 | { | |
1718 | struct motg_softc *sc = MOTG_XFER2SC(xfer); | 1716 | struct motg_softc *sc = MOTG_XFER2SC(xfer); | |
1719 | struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(xfer->ux_pipe); | 1717 | struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(xfer->ux_pipe); | |
1720 | usbd_status err; | |||
1721 | 1718 | |||
1722 | MOTGHIST_FUNC(); MOTGHIST_CALLED(); | 1719 | MOTGHIST_FUNC(); MOTGHIST_CALLED(); | |
1723 | 1720 | |||
1724 | mutex_enter(&sc->sc_lock); | |||
1725 | DPRINTF("xfer %#jx status %jd", (uintptr_t)xfer, xfer->ux_status, 0, 0); | 1721 | DPRINTF("xfer %#jx status %jd", (uintptr_t)xfer, xfer->ux_status, 0, 0); | |
1726 | err = motg_device_data_start1(sc, otgpipe->hw_ep); | 1722 | ||
1727 | mutex_exit(&sc->sc_lock); | 1723 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |
1728 | return err; | 1724 | ||
1725 | return motg_device_data_start1(sc, otgpipe->hw_ep); | |||
1729 | } | 1726 | } | |
1730 | 1727 | |||
1731 | static usbd_status | 1728 | static usbd_status | |
1732 | motg_device_data_start1(struct motg_softc *sc, struct motg_hw_ep *ep) | 1729 | motg_device_data_start1(struct motg_softc *sc, struct motg_hw_ep *ep) | |
1733 | { | 1730 | { | |
1734 | struct usbd_xfer *xfer = NULL; | 1731 | struct usbd_xfer *xfer = NULL; | |
1735 | struct motg_pipe *otgpipe; | 1732 | struct motg_pipe *otgpipe; | |
1736 | usbd_status err = 0; | 1733 | usbd_status err = 0; | |
1737 | uint32_t val __diagused; | 1734 | uint32_t val __diagused; | |
1738 | 1735 | |||
1739 | MOTGHIST_FUNC(); MOTGHIST_CALLED(); | 1736 | MOTGHIST_FUNC(); MOTGHIST_CALLED(); | |
1740 | 1737 | |||
1741 | KASSERT(mutex_owned(&sc->sc_lock)); | 1738 | KASSERT(mutex_owned(&sc->sc_lock)); |
--- src/sys/dev/usb/ohci.c 2022/03/03 06:08:50 1.320
+++ src/sys/dev/usb/ohci.c 2022/03/03 06:12:11 1.321
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ohci.c,v 1.320 2022/03/03 06:08:50 riastradh Exp $ */ | 1 | /* $NetBSD: ohci.c,v 1.321 2022/03/03 06:12:11 riastradh Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2004, 2005, 2012, 2016, 2020 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 2004, 2005, 2012, 2016, 2020 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Lennart Augustsson (lennart@augustsson.net) at | 8 | * by Lennart Augustsson (lennart@augustsson.net) at | |
9 | * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca), | 9 | * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca), | |
10 | * Matthew R. Green (mrg@eterna.com.au), and Nick Hudson. | 10 | * Matthew R. Green (mrg@eterna.com.au), and Nick Hudson. | |
11 | * | 11 | * | |
12 | * This code is derived from software contributed to The NetBSD Foundation | 12 | * This code is derived from software contributed to The NetBSD Foundation | |
13 | * by Charles M. Hannum. | 13 | * by Charles M. Hannum. | |
14 | * | 14 | * | |
@@ -32,27 +32,27 @@ | @@ -32,27 +32,27 @@ | |||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
34 | * POSSIBILITY OF SUCH DAMAGE. | 34 | * POSSIBILITY OF SUCH DAMAGE. | |
35 | */ | 35 | */ | |
36 | 36 | |||
37 | /* | 37 | /* | |
38 | * USB Open Host Controller driver. | 38 | * USB Open Host Controller driver. | |
39 | * | 39 | * | |
40 | * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html | 40 | * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html | |
41 | * USB spec: http://www.usb.org/developers/docs/ | 41 | * USB spec: http://www.usb.org/developers/docs/ | |
42 | */ | 42 | */ | |
43 | 43 | |||
44 | #include <sys/cdefs.h> | 44 | #include <sys/cdefs.h> | |
45 | __KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.320 2022/03/03 06:08:50 riastradh Exp $"); | 45 | __KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.321 2022/03/03 06:12:11 riastradh Exp $"); | |
46 | 46 | |||
47 | #ifdef _KERNEL_OPT | 47 | #ifdef _KERNEL_OPT | |
48 | #include "opt_usb.h" | 48 | #include "opt_usb.h" | |
49 | #endif | 49 | #endif | |
50 | 50 | |||
51 | #include <sys/param.h> | 51 | #include <sys/param.h> | |
52 | 52 | |||
53 | #include <sys/cpu.h> | 53 | #include <sys/cpu.h> | |
54 | #include <sys/device.h> | 54 | #include <sys/device.h> | |
55 | #include <sys/kernel.h> | 55 | #include <sys/kernel.h> | |
56 | #include <sys/kmem.h> | 56 | #include <sys/kmem.h> | |
57 | #include <sys/proc.h> | 57 | #include <sys/proc.h> | |
58 | #include <sys/queue.h> | 58 | #include <sys/queue.h> | |
@@ -2421,26 +2421,28 @@ dying: | @@ -2421,26 +2421,28 @@ dying: | |||
2421 | Static int | 2421 | Static int | |
2422 | ohci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, | 2422 | ohci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, | |
2423 | void *buf, int buflen) | 2423 | void *buf, int buflen) | |
2424 | { | 2424 | { | |
2425 | ohci_softc_t *sc = OHCI_BUS2SC(bus); | 2425 | ohci_softc_t *sc = OHCI_BUS2SC(bus); | |
2426 | usb_port_status_t ps; | 2426 | usb_port_status_t ps; | |
2427 | uint16_t len, value, index; | 2427 | uint16_t len, value, index; | |
2428 | int l, totlen = 0; | 2428 | int l, totlen = 0; | |
2429 | int port, i; | 2429 | int port, i; | |
2430 | uint32_t v; | 2430 | uint32_t v; | |
2431 | 2431 | |||
2432 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | 2432 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | |
2433 | 2433 | |||
2434 | KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock)); | |||
2435 | ||||
2434 | if (sc->sc_dying) | 2436 | if (sc->sc_dying) | |
2435 | return -1; | 2437 | return -1; | |
2436 | 2438 | |||
2437 | DPRINTFN(4, "type=0x%02jx request=%02jx", req->bmRequestType, | 2439 | DPRINTFN(4, "type=0x%02jx request=%02jx", req->bmRequestType, | |
2438 | req->bRequest, 0, 0); | 2440 | req->bRequest, 0, 0); | |
2439 | 2441 | |||
2440 | len = UGETW(req->wLength); | 2442 | len = UGETW(req->wLength); | |
2441 | value = UGETW(req->wValue); | 2443 | value = UGETW(req->wValue); | |
2442 | index = UGETW(req->wIndex); | 2444 | index = UGETW(req->wIndex); | |
2443 | 2445 | |||
2444 | #define C(x,y) ((x) | ((y) << 8)) | 2446 | #define C(x,y) ((x) | ((y) << 8)) | |
2445 | switch (C(req->bRequest, req->bmRequestType)) { | 2447 | switch (C(req->bRequest, req->bmRequestType)) { | |
2446 | case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): | 2448 | case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): | |
@@ -2610,38 +2612,35 @@ ohci_roothub_ctrl(struct usbd_bus *bus, | @@ -2610,38 +2612,35 @@ ohci_roothub_ctrl(struct usbd_bus *bus, | |||
2610 | 2612 | |||
2611 | Static usbd_status | 2613 | Static usbd_status | |
2612 | ohci_root_intr_transfer(struct usbd_xfer *xfer) | 2614 | ohci_root_intr_transfer(struct usbd_xfer *xfer) | |
2613 | { | 2615 | { | |
2614 | 2616 | |||
2615 | /* Pipe isn't running, start first */ | 2617 | /* Pipe isn't running, start first */ | |
2616 | return ohci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 2618 | return ohci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
2617 | } | 2619 | } | |
2618 | 2620 | |||
2619 | Static usbd_status | 2621 | Static usbd_status | |
2620 | ohci_root_intr_start(struct usbd_xfer *xfer) | 2622 | ohci_root_intr_start(struct usbd_xfer *xfer) | |
2621 | { | 2623 | { | |
2622 | ohci_softc_t *sc = OHCI_XFER2SC(xfer); | 2624 | ohci_softc_t *sc = OHCI_XFER2SC(xfer); | |
2623 | const bool polling = sc->sc_bus.ub_usepolling; | 2625 | ||
2626 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
2624 | 2627 | |||
2625 | if (sc->sc_dying) | 2628 | if (sc->sc_dying) | |
2626 | return USBD_IOERROR; | 2629 | return USBD_IOERROR; | |
2627 | 2630 | |||
2628 | if (!polling) | |||
2629 | mutex_enter(&sc->sc_lock); | |||
2630 | KASSERT(sc->sc_intrxfer == NULL); | 2631 | KASSERT(sc->sc_intrxfer == NULL); | |
2631 | sc->sc_intrxfer = xfer; | 2632 | sc->sc_intrxfer = xfer; | |
2632 | xfer->ux_status = USBD_IN_PROGRESS; | 2633 | xfer->ux_status = USBD_IN_PROGRESS; | |
2633 | if (!polling) | |||
2634 | mutex_exit(&sc->sc_lock); | |||
2635 | 2634 | |||
2636 | return USBD_IN_PROGRESS; | 2635 | return USBD_IN_PROGRESS; | |
2637 | } | 2636 | } | |
2638 | 2637 | |||
2639 | /* Abort a root interrupt request. */ | 2638 | /* Abort a root interrupt request. */ | |
2640 | Static void | 2639 | Static void | |
2641 | ohci_root_intr_abort(struct usbd_xfer *xfer) | 2640 | ohci_root_intr_abort(struct usbd_xfer *xfer) | |
2642 | { | 2641 | { | |
2643 | ohci_softc_t *sc = OHCI_XFER2SC(xfer); | 2642 | ohci_softc_t *sc = OHCI_XFER2SC(xfer); | |
2644 | 2643 | |||
2645 | KASSERT(mutex_owned(&sc->sc_lock)); | 2644 | KASSERT(mutex_owned(&sc->sc_lock)); | |
2646 | KASSERT(xfer->ux_pipe->up_intrxfer == xfer); | 2645 | KASSERT(xfer->ux_pipe->up_intrxfer == xfer); | |
2647 | 2646 | |||
@@ -2767,48 +2766,45 @@ ohci_device_ctrl_transfer(struct usbd_xf | @@ -2767,48 +2766,45 @@ ohci_device_ctrl_transfer(struct usbd_xf | |||
2767 | 2766 | |||
2768 | Static usbd_status | 2767 | Static usbd_status | |
2769 | ohci_device_ctrl_start(struct usbd_xfer *xfer) | 2768 | ohci_device_ctrl_start(struct usbd_xfer *xfer) | |
2770 | { | 2769 | { | |
2771 | ohci_softc_t *sc = OHCI_XFER2SC(xfer); | 2770 | ohci_softc_t *sc = OHCI_XFER2SC(xfer); | |
2772 | struct ohci_xfer *ox = OHCI_XFER2OXFER(xfer); | 2771 | struct ohci_xfer *ox = OHCI_XFER2OXFER(xfer); | |
2773 | struct ohci_pipe *opipe = OHCI_PIPE2OPIPE(xfer->ux_pipe); | 2772 | struct ohci_pipe *opipe = OHCI_PIPE2OPIPE(xfer->ux_pipe); | |
2774 | usb_device_request_t *req = &xfer->ux_request; | 2773 | usb_device_request_t *req = &xfer->ux_request; | |
2775 | struct usbd_device *dev __diagused = opipe->pipe.up_dev; | 2774 | struct usbd_device *dev __diagused = opipe->pipe.up_dev; | |
2776 | ohci_soft_td_t *setup, *stat, *next, *tail; | 2775 | ohci_soft_td_t *setup, *stat, *next, *tail; | |
2777 | ohci_soft_ed_t *sed; | 2776 | ohci_soft_ed_t *sed; | |
2778 | int isread; | 2777 | int isread; | |
2779 | int len; | 2778 | int len; | |
2780 | const bool polling = sc->sc_bus.ub_usepolling; | |||
2781 | 2779 | |||
2782 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | 2780 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | |
2783 | 2781 | |||
2782 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
2783 | ||||
2784 | if (sc->sc_dying) | 2784 | if (sc->sc_dying) | |
2785 | return USBD_IOERROR; | 2785 | return USBD_IOERROR; | |
2786 | 2786 | |||
2787 | KASSERT(xfer->ux_rqflags & URQ_REQUEST); | 2787 | KASSERT(xfer->ux_rqflags & URQ_REQUEST); | |
2788 | 2788 | |||
2789 | isread = req->bmRequestType & UT_READ; | 2789 | isread = req->bmRequestType & UT_READ; | |
2790 | len = UGETW(req->wLength); | 2790 | len = UGETW(req->wLength); | |
2791 | 2791 | |||
2792 | DPRINTF("xfer=%#jx len=%jd, addr=%jd, endpt=%jd", (uintptr_t)xfer, len, | 2792 | DPRINTF("xfer=%#jx len=%jd, addr=%jd, endpt=%jd", (uintptr_t)xfer, len, | |
2793 | dev->ud_addr, opipe->pipe.up_endpoint->ue_edesc->bEndpointAddress); | 2793 | dev->ud_addr, opipe->pipe.up_endpoint->ue_edesc->bEndpointAddress); | |
2794 | DPRINTF("type=0x%02jx, request=0x%02jx, wValue=0x%04jx, wIndex=0x%04jx", | 2794 | DPRINTF("type=0x%02jx, request=0x%02jx, wValue=0x%04jx, wIndex=0x%04jx", | |
2795 | req->bmRequestType, req->bRequest, UGETW(req->wValue), | 2795 | req->bmRequestType, req->bRequest, UGETW(req->wValue), | |
2796 | UGETW(req->wIndex)); | 2796 | UGETW(req->wIndex)); | |
2797 | 2797 | |||
2798 | /* Need to take lock here for pipe->tail.td */ | |||
2799 | if (!polling) | |||
2800 | mutex_enter(&sc->sc_lock); | |||
2801 | ||||
2802 | /* | 2798 | /* | |
2803 | * Use the pipe "tail" TD as our first and loan our first TD to the | 2799 | * Use the pipe "tail" TD as our first and loan our first TD to the | |
2804 | * next transfer | 2800 | * next transfer | |
2805 | */ | 2801 | */ | |
2806 | setup = opipe->tail.td; | 2802 | setup = opipe->tail.td; | |
2807 | opipe->tail.td = ox->ox_setup; | 2803 | opipe->tail.td = ox->ox_setup; | |
2808 | ox->ox_setup = setup; | 2804 | ox->ox_setup = setup; | |
2809 | setup->held = &ox->ox_setup; | 2805 | setup->held = &ox->ox_setup; | |
2810 | 2806 | |||
2811 | DPRINTFN(10, "xfer=%#jx new setup=%#jx held at %#jx", (uintptr_t)ox, | 2807 | DPRINTFN(10, "xfer=%#jx new setup=%#jx held at %#jx", (uintptr_t)ox, | |
2812 | (uintptr_t)setup, (uintptr_t)setup->held, 0); | 2808 | (uintptr_t)setup, (uintptr_t)setup->held, 0); | |
2813 | 2809 | |||
2814 | stat = ox->ox_stat; | 2810 | stat = ox->ox_stat; | |
@@ -2923,28 +2919,26 @@ ohci_device_ctrl_start(struct usbd_xfer | @@ -2923,28 +2919,26 @@ ohci_device_ctrl_start(struct usbd_xfer | |||
2923 | 2919 | |||
2924 | /* Insert ED in schedule */ | 2920 | /* Insert ED in schedule */ | |
2925 | sed->ed.ed_tailp = HTOO32(tail->physaddr); | 2921 | sed->ed.ed_tailp = HTOO32(tail->physaddr); | |
2926 | usb_syncmem(&sed->dma, | 2922 | usb_syncmem(&sed->dma, | |
2927 | sed->offs + offsetof(ohci_ed_t, ed_tailp), | 2923 | sed->offs + offsetof(ohci_ed_t, ed_tailp), | |
2928 | sizeof(sed->ed.ed_tailp), | 2924 | sizeof(sed->ed.ed_tailp), | |
2929 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 2925 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
2930 | OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); | 2926 | OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); | |
2931 | usbd_xfer_schedule_timeout(xfer); | 2927 | usbd_xfer_schedule_timeout(xfer); | |
2932 | 2928 | |||
2933 | DPRINTF("done", 0, 0, 0, 0); | 2929 | DPRINTF("done", 0, 0, 0, 0); | |
2934 | 2930 | |||
2935 | xfer->ux_status = USBD_IN_PROGRESS; | 2931 | xfer->ux_status = USBD_IN_PROGRESS; | |
2936 | if (!polling) | |||
2937 | mutex_exit(&sc->sc_lock); | |||
2938 | 2932 | |||
2939 | return USBD_IN_PROGRESS; | 2933 | return USBD_IN_PROGRESS; | |
2940 | } | 2934 | } | |
2941 | 2935 | |||
2942 | /* Abort a device control request. */ | 2936 | /* Abort a device control request. */ | |
2943 | Static void | 2937 | Static void | |
2944 | ohci_device_ctrl_abort(struct usbd_xfer *xfer) | 2938 | ohci_device_ctrl_abort(struct usbd_xfer *xfer) | |
2945 | { | 2939 | { | |
2946 | ohci_softc_t *sc __diagused = OHCI_XFER2SC(xfer); | 2940 | ohci_softc_t *sc __diagused = OHCI_XFER2SC(xfer); | |
2947 | 2941 | |||
2948 | KASSERT(mutex_owned(&sc->sc_lock)); | 2942 | KASSERT(mutex_owned(&sc->sc_lock)); | |
2949 | 2943 | |||
2950 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | 2944 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | |
@@ -3044,47 +3038,45 @@ ohci_device_bulk_transfer(struct usbd_xf | @@ -3044,47 +3038,45 @@ ohci_device_bulk_transfer(struct usbd_xf | |||
3044 | return ohci_device_bulk_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 3038 | return ohci_device_bulk_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
3045 | } | 3039 | } | |
3046 | 3040 | |||
3047 | Static usbd_status | 3041 | Static usbd_status | |
3048 | ohci_device_bulk_start(struct usbd_xfer *xfer) | 3042 | ohci_device_bulk_start(struct usbd_xfer *xfer) | |
3049 | { | 3043 | { | |
3050 | struct ohci_xfer *ox = OHCI_XFER2OXFER(xfer); | 3044 | struct ohci_xfer *ox = OHCI_XFER2OXFER(xfer); | |
3051 | struct ohci_pipe *opipe = OHCI_PIPE2OPIPE(xfer->ux_pipe); | 3045 | struct ohci_pipe *opipe = OHCI_PIPE2OPIPE(xfer->ux_pipe); | |
3052 | ohci_softc_t *sc = OHCI_XFER2SC(xfer); | 3046 | ohci_softc_t *sc = OHCI_XFER2SC(xfer); | |
3053 | ohci_soft_td_t *last; | 3047 | ohci_soft_td_t *last; | |
3054 | ohci_soft_td_t *data, *tail, *tdp; | 3048 | ohci_soft_td_t *data, *tail, *tdp; | |
3055 | ohci_soft_ed_t *sed; | 3049 | ohci_soft_ed_t *sed; | |
3056 | int len, isread, endpt; | 3050 | int len, isread, endpt; | |
3057 | const bool polling = sc->sc_bus.ub_usepolling; | |||
3058 | 3051 | |||
3059 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | 3052 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | |
3060 | 3053 | |||
3054 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
3055 | ||||
3061 | if (sc->sc_dying) | 3056 | if (sc->sc_dying) | |
3062 | return USBD_IOERROR; | 3057 | return USBD_IOERROR; | |
3063 | 3058 | |||
3064 | KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); | 3059 | KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); | |
3065 | 3060 | |||
3066 | len = xfer->ux_length; | 3061 | len = xfer->ux_length; | |
3067 | endpt = xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress; | 3062 | endpt = xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress; | |
3068 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | 3063 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | |
3069 | sed = opipe->sed; | 3064 | sed = opipe->sed; | |
3070 | 3065 | |||
3071 | DPRINTFN(4, "xfer=%#jx len=%jd isread=%jd flags=%jd", (uintptr_t)xfer, | 3066 | DPRINTFN(4, "xfer=%#jx len=%jd isread=%jd flags=%jd", (uintptr_t)xfer, | |
3072 | len, isread, xfer->ux_flags); | 3067 | len, isread, xfer->ux_flags); | |
3073 | DPRINTFN(4, "endpt=%jd", endpt, 0, 0, 0); | 3068 | DPRINTFN(4, "endpt=%jd", endpt, 0, 0, 0); | |
3074 | 3069 | |||
3075 | if (!polling) | |||
3076 | mutex_enter(&sc->sc_lock); | |||
3077 | ||||
3078 | /* | 3070 | /* | |
3079 | * Use the pipe "tail" TD as our first and loan our first TD to the | 3071 | * Use the pipe "tail" TD as our first and loan our first TD to the | |
3080 | * next transfer | 3072 | * next transfer | |
3081 | */ | 3073 | */ | |
3082 | data = opipe->tail.td; | 3074 | data = opipe->tail.td; | |
3083 | opipe->tail.td = ox->ox_stds[0]; | 3075 | opipe->tail.td = ox->ox_stds[0]; | |
3084 | ox->ox_stds[0] = data; | 3076 | ox->ox_stds[0] = data; | |
3085 | data->held = &ox->ox_stds[0]; | 3077 | data->held = &ox->ox_stds[0]; | |
3086 | ohci_reset_std_chain(sc, xfer, len, isread, data, &last); | 3078 | ohci_reset_std_chain(sc, xfer, len, isread, data, &last); | |
3087 | DPRINTFN(10, "xfer=%#jx new data=%#jx held at %#jx", | 3079 | DPRINTFN(10, "xfer=%#jx new data=%#jx held at %#jx", | |
3088 | (uintptr_t)ox, (uintptr_t)data, (uintptr_t)data->held, 0); | 3080 | (uintptr_t)ox, (uintptr_t)data, (uintptr_t)data->held, 0); | |
3089 | 3081 | |||
3090 | /* point at sentinel */ | 3082 | /* point at sentinel */ | |
@@ -3131,28 +3123,26 @@ ohci_device_bulk_start(struct usbd_xfer | @@ -3131,28 +3123,26 @@ ohci_device_bulk_start(struct usbd_xfer | |||
3131 | /* Insert ED in schedule */ | 3123 | /* Insert ED in schedule */ | |
3132 | for (tdp = data; tdp != tail; tdp = tdp->nexttd) { | 3124 | for (tdp = data; tdp != tail; tdp = tdp->nexttd) { | |
3133 | KASSERT(tdp->xfer == xfer); | 3125 | KASSERT(tdp->xfer == xfer); | |
3134 | } | 3126 | } | |
3135 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | 3127 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | |
3136 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | 3128 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | |
3137 | sed->ed.ed_tailp = HTOO32(tail->physaddr); | 3129 | sed->ed.ed_tailp = HTOO32(tail->physaddr); | |
3138 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); | 3130 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); | |
3139 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | 3131 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | |
3140 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 3132 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
3141 | OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF); | 3133 | OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF); | |
3142 | usbd_xfer_schedule_timeout(xfer); | 3134 | usbd_xfer_schedule_timeout(xfer); | |
3143 | xfer->ux_status = USBD_IN_PROGRESS; | 3135 | xfer->ux_status = USBD_IN_PROGRESS; | |
3144 | if (!polling) | |||
3145 | mutex_exit(&sc->sc_lock); | |||
3146 | 3136 | |||
3147 | return USBD_IN_PROGRESS; | 3137 | return USBD_IN_PROGRESS; | |
3148 | } | 3138 | } | |
3149 | 3139 | |||
3150 | Static void | 3140 | Static void | |
3151 | ohci_device_bulk_abort(struct usbd_xfer *xfer) | 3141 | ohci_device_bulk_abort(struct usbd_xfer *xfer) | |
3152 | { | 3142 | { | |
3153 | ohci_softc_t *sc __diagused = OHCI_XFER2SC(xfer); | 3143 | ohci_softc_t *sc __diagused = OHCI_XFER2SC(xfer); | |
3154 | 3144 | |||
3155 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | 3145 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | |
3156 | 3146 | |||
3157 | KASSERT(mutex_owned(&sc->sc_lock)); | 3147 | KASSERT(mutex_owned(&sc->sc_lock)); | |
3158 | 3148 | |||
@@ -3242,45 +3232,43 @@ ohci_device_intr_transfer(struct usbd_xf | @@ -3242,45 +3232,43 @@ ohci_device_intr_transfer(struct usbd_xf | |||
3242 | /* Pipe isn't running, start first */ | 3232 | /* Pipe isn't running, start first */ | |
3243 | return ohci_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 3233 | return ohci_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
3244 | } | 3234 | } | |
3245 | 3235 | |||
3246 | Static usbd_status | 3236 | Static usbd_status | |
3247 | ohci_device_intr_start(struct usbd_xfer *xfer) | 3237 | ohci_device_intr_start(struct usbd_xfer *xfer) | |
3248 | { | 3238 | { | |
3249 | struct ohci_xfer *ox = OHCI_XFER2OXFER(xfer); | 3239 | struct ohci_xfer *ox = OHCI_XFER2OXFER(xfer); | |
3250 | struct ohci_pipe *opipe = OHCI_PIPE2OPIPE(xfer->ux_pipe); | 3240 | struct ohci_pipe *opipe = OHCI_PIPE2OPIPE(xfer->ux_pipe); | |
3251 | ohci_softc_t *sc = OHCI_XFER2SC(xfer); | 3241 | ohci_softc_t *sc = OHCI_XFER2SC(xfer); | |
3252 | ohci_soft_ed_t *sed = opipe->sed; | 3242 | ohci_soft_ed_t *sed = opipe->sed; | |
3253 | ohci_soft_td_t *data, *last, *tail; | 3243 | ohci_soft_td_t *data, *last, *tail; | |
3254 | int len, isread, endpt; | 3244 | int len, isread, endpt; | |
3255 | const bool polling = sc->sc_bus.ub_usepolling; | |||
3256 | 3245 | |||
3257 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | 3246 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | |
3258 | 3247 | |||
3248 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
3249 | ||||
3259 | if (sc->sc_dying) | 3250 | if (sc->sc_dying) | |
3260 | return USBD_IOERROR; | 3251 | return USBD_IOERROR; | |
3261 | 3252 | |||
3262 | DPRINTFN(3, "xfer=%#jx len=%jd flags=%jd priv=%#jx", (uintptr_t)xfer, | 3253 | DPRINTFN(3, "xfer=%#jx len=%jd flags=%jd priv=%#jx", (uintptr_t)xfer, | |
3263 | xfer->ux_length, xfer->ux_flags, (uintptr_t)xfer->ux_priv); | 3254 | xfer->ux_length, xfer->ux_flags, (uintptr_t)xfer->ux_priv); | |
3264 | 3255 | |||
3265 | KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); | 3256 | KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); | |
3266 | 3257 | |||
3267 | len = xfer->ux_length; | 3258 | len = xfer->ux_length; | |
3268 | endpt = xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress; | 3259 | endpt = xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress; | |
3269 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | 3260 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | |
3270 | 3261 | |||
3271 | if (!polling) | |||
3272 | mutex_enter(&sc->sc_lock); | |||
3273 | ||||
3274 | /* | 3262 | /* | |
3275 | * Use the pipe "tail" TD as our first and loan our first TD to the | 3263 | * Use the pipe "tail" TD as our first and loan our first TD to the | |
3276 | * next transfer. | 3264 | * next transfer. | |
3277 | */ | 3265 | */ | |
3278 | data = opipe->tail.td; | 3266 | data = opipe->tail.td; | |
3279 | opipe->tail.td = ox->ox_stds[0]; | 3267 | opipe->tail.td = ox->ox_stds[0]; | |
3280 | ox->ox_stds[0] = data; | 3268 | ox->ox_stds[0] = data; | |
3281 | data->held = &ox->ox_stds[0]; | 3269 | data->held = &ox->ox_stds[0]; | |
3282 | ohci_reset_std_chain(sc, xfer, len, isread, data, &last); | 3270 | ohci_reset_std_chain(sc, xfer, len, isread, data, &last); | |
3283 | DPRINTFN(10, "xfer=%#jx new data=%#jx held at %#jx", | 3271 | DPRINTFN(10, "xfer=%#jx new data=%#jx held at %#jx", | |
3284 | (uintptr_t)ox, (uintptr_t)data, (uintptr_t)data->held, 0); | 3272 | (uintptr_t)ox, (uintptr_t)data, (uintptr_t)data->held, 0); | |
3285 | 3273 | |||
3286 | /* point at sentinel */ | 3274 | /* point at sentinel */ | |
@@ -3317,28 +3305,26 @@ ohci_device_intr_start(struct usbd_xfer | @@ -3317,28 +3305,26 @@ ohci_device_intr_start(struct usbd_xfer | |||
3317 | } | 3305 | } | |
3318 | DPRINTFN(5, "--- dump end ---", 0, 0, 0, 0); | 3306 | DPRINTFN(5, "--- dump end ---", 0, 0, 0, 0); | |
3319 | #endif | 3307 | #endif | |
3320 | 3308 | |||
3321 | /* Insert ED in schedule */ | 3309 | /* Insert ED in schedule */ | |
3322 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | 3310 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | |
3323 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | 3311 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | |
3324 | sed->ed.ed_tailp = HTOO32(tail->physaddr); | 3312 | sed->ed.ed_tailp = HTOO32(tail->physaddr); | |
3325 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); | 3313 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); | |
3326 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | 3314 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | |
3327 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 3315 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
3328 | 3316 | |||
3329 | xfer->ux_status = USBD_IN_PROGRESS; | 3317 | xfer->ux_status = USBD_IN_PROGRESS; | |
3330 | if (!polling) | |||
3331 | mutex_exit(&sc->sc_lock); | |||
3332 | 3318 | |||
3333 | return USBD_IN_PROGRESS; | 3319 | return USBD_IN_PROGRESS; | |
3334 | } | 3320 | } | |
3335 | 3321 | |||
3336 | /* Abort a device interrupt request. */ | 3322 | /* Abort a device interrupt request. */ | |
3337 | Static void | 3323 | Static void | |
3338 | ohci_device_intr_abort(struct usbd_xfer *xfer) | 3324 | ohci_device_intr_abort(struct usbd_xfer *xfer) | |
3339 | { | 3325 | { | |
3340 | ohci_softc_t *sc __diagused = OHCI_XFER2SC(xfer); | 3326 | ohci_softc_t *sc __diagused = OHCI_XFER2SC(xfer); | |
3341 | 3327 | |||
3342 | KASSERT(mutex_owned(&sc->sc_lock)); | 3328 | KASSERT(mutex_owned(&sc->sc_lock)); | |
3343 | 3329 | |||
3344 | usbd_xfer_abort(xfer); | 3330 | usbd_xfer_abort(xfer); | |
@@ -3549,32 +3535,30 @@ ohci_device_isoc_enter(struct usbd_xfer | @@ -3549,32 +3535,30 @@ ohci_device_isoc_enter(struct usbd_xfer | |||
3549 | { | 3535 | { | |
3550 | struct ohci_xfer *ox = OHCI_XFER2OXFER(xfer); | 3536 | struct ohci_xfer *ox = OHCI_XFER2OXFER(xfer); | |
3551 | struct ohci_pipe *opipe = OHCI_PIPE2OPIPE(xfer->ux_pipe); | 3537 | struct ohci_pipe *opipe = OHCI_PIPE2OPIPE(xfer->ux_pipe); | |
3552 | ohci_softc_t *sc = OHCI_XFER2SC(xfer); | 3538 | ohci_softc_t *sc = OHCI_XFER2SC(xfer); | |
3553 | ohci_soft_ed_t *sed = opipe->sed; | 3539 | ohci_soft_ed_t *sed = opipe->sed; | |
3554 | ohci_soft_itd_t *sitd, *nsitd, *tail; | 3540 | ohci_soft_itd_t *sitd, *nsitd, *tail; | |
3555 | ohci_physaddr_t buf, offs, bp0, bp1; | 3541 | ohci_physaddr_t buf, offs, bp0, bp1; | |
3556 | int i, ncur, nframes; | 3542 | int i, ncur, nframes; | |
3557 | size_t boff, frlen; | 3543 | size_t boff, frlen; | |
3558 | 3544 | |||
3559 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | 3545 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | |
3560 | DPRINTFN(5, "xfer=%#jx", (uintptr_t)xfer, 0, 0, 0); | 3546 | DPRINTFN(5, "xfer=%#jx", (uintptr_t)xfer, 0, 0, 0); | |
3561 | 3547 | |||
3562 | mutex_enter(&sc->sc_lock); | 3548 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |
3563 | 3549 | |||
3564 | if (sc->sc_dying) { | 3550 | if (sc->sc_dying) | |
3565 | mutex_exit(&sc->sc_lock); | |||
3566 | return; | 3551 | return; | |
3567 | } | |||
3568 | 3552 | |||
3569 | struct isoc *isoc = &opipe->isoc; | 3553 | struct isoc *isoc = &opipe->isoc; | |
3570 | 3554 | |||
3571 | DPRINTFN(1, "used=%jd next=%jd xfer=%#jx nframes=%jd", | 3555 | DPRINTFN(1, "used=%jd next=%jd xfer=%#jx nframes=%jd", | |
3572 | isoc->inuse, isoc->next, (uintptr_t)xfer, xfer->ux_nframes); | 3556 | isoc->inuse, isoc->next, (uintptr_t)xfer, xfer->ux_nframes); | |
3573 | 3557 | |||
3574 | int isread = | 3558 | int isread = | |
3575 | (UE_GET_DIR(xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress) == UE_DIR_IN); | 3559 | (UE_GET_DIR(xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress) == UE_DIR_IN); | |
3576 | 3560 | |||
3577 | if (xfer->ux_length) | 3561 | if (xfer->ux_length) | |
3578 | usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, | 3562 | usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, | |
3579 | isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | 3563 | isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | |
3580 | 3564 | |||
@@ -3713,27 +3697,26 @@ ohci_device_isoc_enter(struct usbd_xfer | @@ -3713,27 +3697,26 @@ ohci_device_isoc_enter(struct usbd_xfer | |||
3713 | 0, 0, 0); | 3697 | 0, 0, 0); | |
3714 | ohci_dump_itds(sc, xfer->ux_hcpriv); | 3698 | ohci_dump_itds(sc, xfer->ux_hcpriv); | |
3715 | ohci_dump_ed(sc, sed); | 3699 | ohci_dump_ed(sc, sed); | |
3716 | } | 3700 | } | |
3717 | #endif | 3701 | #endif | |
3718 | 3702 | |||
3719 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | 3703 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | |
3720 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | 3704 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | |
3721 | sed->ed.ed_tailp = HTOO32(tail->physaddr); | 3705 | sed->ed.ed_tailp = HTOO32(tail->physaddr); | |
3722 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); | 3706 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); | |
3723 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), | 3707 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), | |
3724 | sizeof(sed->ed.ed_flags), | 3708 | sizeof(sed->ed.ed_flags), | |
3725 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 3709 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
3726 | mutex_exit(&sc->sc_lock); | |||
3727 | } | 3710 | } | |
3728 | 3711 | |||
3729 | void | 3712 | void | |
3730 | ohci_device_isoc_abort(struct usbd_xfer *xfer) | 3713 | ohci_device_isoc_abort(struct usbd_xfer *xfer) | |
3731 | { | 3714 | { | |
3732 | struct ohci_pipe *opipe = OHCI_PIPE2OPIPE(xfer->ux_pipe); | 3715 | struct ohci_pipe *opipe = OHCI_PIPE2OPIPE(xfer->ux_pipe); | |
3733 | ohci_softc_t *sc = OHCI_XFER2SC(xfer); | 3716 | ohci_softc_t *sc = OHCI_XFER2SC(xfer); | |
3734 | ohci_soft_ed_t *sed; | 3717 | ohci_soft_ed_t *sed; | |
3735 | ohci_soft_itd_t *sitd; | 3718 | ohci_soft_itd_t *sitd; | |
3736 | 3719 | |||
3737 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | 3720 | OHCIHIST_FUNC(); OHCIHIST_CALLED(); | |
3738 | DPRINTFN(1, "xfer=%#jx", (uintptr_t)xfer, 0, 0, 0); | 3721 | DPRINTFN(1, "xfer=%#jx", (uintptr_t)xfer, 0, 0, 0); | |
3739 | 3722 |
--- src/sys/dev/usb/uhci.c 2022/03/03 06:08:50 1.310
+++ src/sys/dev/usb/uhci.c 2022/03/03 06:12:11 1.311
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: uhci.c,v 1.310 2022/03/03 06:08:50 riastradh Exp $ */ | 1 | /* $NetBSD: uhci.c,v 1.311 2022/03/03 06:12:11 riastradh Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2004, 2011, 2012, 2016, 2020 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 2004, 2011, 2012, 2016, 2020 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Lennart Augustsson (lennart@augustsson.net) at | 8 | * by Lennart Augustsson (lennart@augustsson.net) at | |
9 | * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca), | 9 | * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca), | |
10 | * Matthew R. Green (mrg@eterna.com.au) and Nick Hudson. | 10 | * Matthew R. Green (mrg@eterna.com.au) and Nick Hudson. | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
@@ -32,27 +32,27 @@ | @@ -32,27 +32,27 @@ | |||
32 | */ | 32 | */ | |
33 | 33 | |||
34 | /* | 34 | /* | |
35 | * USB Universal Host Controller driver. | 35 | * USB Universal Host Controller driver. | |
36 | * Handles e.g. PIIX3 and PIIX4. | 36 | * Handles e.g. PIIX3 and PIIX4. | |
37 | * | 37 | * | |
38 | * UHCI spec: http://www.intel.com/technology/usb/spec.htm | 38 | * UHCI spec: http://www.intel.com/technology/usb/spec.htm | |
39 | * USB spec: http://www.usb.org/developers/docs/ | 39 | * USB spec: http://www.usb.org/developers/docs/ | |
40 | * PIIXn spec: ftp://download.intel.com/design/intarch/datashts/29055002.pdf | 40 | * PIIXn spec: ftp://download.intel.com/design/intarch/datashts/29055002.pdf | |
41 | * ftp://download.intel.com/design/intarch/datashts/29056201.pdf | 41 | * ftp://download.intel.com/design/intarch/datashts/29056201.pdf | |
42 | */ | 42 | */ | |
43 | 43 | |||
44 | #include <sys/cdefs.h> | 44 | #include <sys/cdefs.h> | |
45 | __KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.310 2022/03/03 06:08:50 riastradh Exp $"); | 45 | __KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.311 2022/03/03 06:12:11 riastradh Exp $"); | |
46 | 46 | |||
47 | #ifdef _KERNEL_OPT | 47 | #ifdef _KERNEL_OPT | |
48 | #include "opt_usb.h" | 48 | #include "opt_usb.h" | |
49 | #endif | 49 | #endif | |
50 | 50 | |||
51 | #include <sys/param.h> | 51 | #include <sys/param.h> | |
52 | 52 | |||
53 | #include <sys/bus.h> | 53 | #include <sys/bus.h> | |
54 | #include <sys/cpu.h> | 54 | #include <sys/cpu.h> | |
55 | #include <sys/device.h> | 55 | #include <sys/device.h> | |
56 | #include <sys/kernel.h> | 56 | #include <sys/kernel.h> | |
57 | #include <sys/kmem.h> | 57 | #include <sys/kmem.h> | |
58 | #include <sys/mutex.h> | 58 | #include <sys/mutex.h> | |
@@ -2261,50 +2261,47 @@ uhci_device_bulk_transfer(struct usbd_xf | @@ -2261,50 +2261,47 @@ uhci_device_bulk_transfer(struct usbd_xf | |||
2261 | 2261 | |||
2262 | /* Pipe isn't running, so start it first. */ | 2262 | /* Pipe isn't running, so start it first. */ | |
2263 | return uhci_device_bulk_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 2263 | return uhci_device_bulk_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
2264 | } | 2264 | } | |
2265 | 2265 | |||
2266 | usbd_status | 2266 | usbd_status | |
2267 | uhci_device_bulk_start(struct usbd_xfer *xfer) | 2267 | uhci_device_bulk_start(struct usbd_xfer *xfer) | |
2268 | { | 2268 | { | |
2269 | struct uhci_pipe *upipe = UHCI_PIPE2UPIPE(xfer->ux_pipe); | 2269 | struct uhci_pipe *upipe = UHCI_PIPE2UPIPE(xfer->ux_pipe); | |
2270 | struct uhci_xfer *ux = UHCI_XFER2UXFER(xfer); | 2270 | struct uhci_xfer *ux = UHCI_XFER2UXFER(xfer); | |
2271 | uhci_softc_t *sc = UHCI_XFER2SC(xfer); | 2271 | uhci_softc_t *sc = UHCI_XFER2SC(xfer); | |
2272 | uhci_soft_td_t *data, *dataend; | 2272 | uhci_soft_td_t *data, *dataend; | |
2273 | uhci_soft_qh_t *sqh; | 2273 | uhci_soft_qh_t *sqh; | |
2274 | const bool polling = sc->sc_bus.ub_usepolling; | |||
2275 | int len; | 2274 | int len; | |
2276 | int endpt; | 2275 | int endpt; | |
2277 | int isread; | 2276 | int isread; | |
2278 | 2277 | |||
2279 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | 2278 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | |
2280 | DPRINTFN(3, "xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, | 2279 | DPRINTFN(3, "xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, | |
2281 | xfer->ux_length, xfer->ux_flags, 0); | 2280 | xfer->ux_length, xfer->ux_flags, 0); | |
2282 | 2281 | |||
2282 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
2283 | ||||
2283 | if (sc->sc_dying) | 2284 | if (sc->sc_dying) | |
2284 | return USBD_IOERROR; | 2285 | return USBD_IOERROR; | |
2285 | 2286 | |||
2286 | KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); | 2287 | KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); | |
2287 | KASSERT(xfer->ux_length <= xfer->ux_bufsize); | 2288 | KASSERT(xfer->ux_length <= xfer->ux_bufsize); | |
2288 | 2289 | |||
2289 | len = xfer->ux_length; | 2290 | len = xfer->ux_length; | |
2290 | endpt = upipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; | 2291 | endpt = upipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; | |
2291 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | 2292 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | |
2292 | sqh = upipe->bulk.sqh; | 2293 | sqh = upipe->bulk.sqh; | |
2293 | 2294 | |||
2294 | /* Take lock here to protect nexttoggle */ | |||
2295 | if (!polling) | |||
2296 | mutex_enter(&sc->sc_lock); | |||
2297 | ||||
2298 | uhci_reset_std_chain(sc, xfer, len, isread, &upipe->nexttoggle, | 2295 | uhci_reset_std_chain(sc, xfer, len, isread, &upipe->nexttoggle, | |
2299 | &dataend); | 2296 | &dataend); | |
2300 | 2297 | |||
2301 | data = ux->ux_stdstart; | 2298 | data = ux->ux_stdstart; | |
2302 | ux->ux_stdend = dataend; | 2299 | ux->ux_stdend = dataend; | |
2303 | dataend->td.td_status |= htole32(UHCI_TD_IOC); | 2300 | dataend->td.td_status |= htole32(UHCI_TD_IOC); | |
2304 | usb_syncmem(&dataend->dma, | 2301 | usb_syncmem(&dataend->dma, | |
2305 | dataend->offs + offsetof(uhci_td_t, td_status), | 2302 | dataend->offs + offsetof(uhci_td_t, td_status), | |
2306 | sizeof(dataend->td.td_status), | 2303 | sizeof(dataend->td.td_status), | |
2307 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 2304 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
2308 | 2305 | |||
2309 | #ifdef UHCI_DEBUG | 2306 | #ifdef UHCI_DEBUG | |
2310 | if (uhcidebug >= 10) { | 2307 | if (uhcidebug >= 10) { | |
@@ -2318,28 +2315,26 @@ uhci_device_bulk_start(struct usbd_xfer | @@ -2318,28 +2315,26 @@ uhci_device_bulk_start(struct usbd_xfer | |||
2318 | KASSERT(ux->ux_isdone); | 2315 | KASSERT(ux->ux_isdone); | |
2319 | #ifdef DIAGNOSTIC | 2316 | #ifdef DIAGNOSTIC | |
2320 | ux->ux_isdone = false; | 2317 | ux->ux_isdone = false; | |
2321 | #endif | 2318 | #endif | |
2322 | 2319 | |||
2323 | sqh->elink = data; | 2320 | sqh->elink = data; | |
2324 | sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD); | 2321 | sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD); | |
2325 | /* uhci_add_bulk() will do usb_syncmem(sqh) */ | 2322 | /* uhci_add_bulk() will do usb_syncmem(sqh) */ | |
2326 | 2323 | |||
2327 | uhci_add_bulk(sc, sqh); | 2324 | uhci_add_bulk(sc, sqh); | |
2328 | uhci_add_intr_list(sc, ux); | 2325 | uhci_add_intr_list(sc, ux); | |
2329 | usbd_xfer_schedule_timeout(xfer); | 2326 | usbd_xfer_schedule_timeout(xfer); | |
2330 | xfer->ux_status = USBD_IN_PROGRESS; | 2327 | xfer->ux_status = USBD_IN_PROGRESS; | |
2331 | if (!polling) | |||
2332 | mutex_exit(&sc->sc_lock); | |||
2333 | 2328 | |||
2334 | return USBD_IN_PROGRESS; | 2329 | return USBD_IN_PROGRESS; | |
2335 | } | 2330 | } | |
2336 | 2331 | |||
2337 | /* Abort a device bulk request. */ | 2332 | /* Abort a device bulk request. */ | |
2338 | void | 2333 | void | |
2339 | uhci_device_bulk_abort(struct usbd_xfer *xfer) | 2334 | uhci_device_bulk_abort(struct usbd_xfer *xfer) | |
2340 | { | 2335 | { | |
2341 | uhci_softc_t *sc __diagused = UHCI_XFER2SC(xfer); | 2336 | uhci_softc_t *sc __diagused = UHCI_XFER2SC(xfer); | |
2342 | 2337 | |||
2343 | KASSERT(mutex_owned(&sc->sc_lock)); | 2338 | KASSERT(mutex_owned(&sc->sc_lock)); | |
2344 | 2339 | |||
2345 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | 2340 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | |
@@ -2485,57 +2480,55 @@ uhci_device_ctrl_transfer(struct usbd_xf | @@ -2485,57 +2480,55 @@ uhci_device_ctrl_transfer(struct usbd_xf | |||
2485 | 2480 | |||
2486 | usbd_status | 2481 | usbd_status | |
2487 | uhci_device_ctrl_start(struct usbd_xfer *xfer) | 2482 | uhci_device_ctrl_start(struct usbd_xfer *xfer) | |
2488 | { | 2483 | { | |
2489 | uhci_softc_t *sc = UHCI_XFER2SC(xfer); | 2484 | uhci_softc_t *sc = UHCI_XFER2SC(xfer); | |
2490 | struct uhci_xfer *uxfer = UHCI_XFER2UXFER(xfer); | 2485 | struct uhci_xfer *uxfer = UHCI_XFER2UXFER(xfer); | |
2491 | struct uhci_pipe *upipe = UHCI_PIPE2UPIPE(xfer->ux_pipe); | 2486 | struct uhci_pipe *upipe = UHCI_PIPE2UPIPE(xfer->ux_pipe); | |
2492 | usb_device_request_t *req = &xfer->ux_request; | 2487 | usb_device_request_t *req = &xfer->ux_request; | |
2493 | struct usbd_device *dev = upipe->pipe.up_dev; | 2488 | struct usbd_device *dev = upipe->pipe.up_dev; | |
2494 | int addr = dev->ud_addr; | 2489 | int addr = dev->ud_addr; | |
2495 | int endpt = upipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; | 2490 | int endpt = upipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; | |
2496 | uhci_soft_td_t *setup, *stat, *next, *dataend; | 2491 | uhci_soft_td_t *setup, *stat, *next, *dataend; | |
2497 | uhci_soft_qh_t *sqh; | 2492 | uhci_soft_qh_t *sqh; | |
2498 | const bool polling = sc->sc_bus.ub_usepolling; | |||
2499 | int len; | 2493 | int len; | |
2500 | int isread; | 2494 | int isread; | |
2501 | 2495 | |||
2502 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | 2496 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | |
2503 | 2497 | |||
2498 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
2499 | ||||
2504 | if (sc->sc_dying) | 2500 | if (sc->sc_dying) | |
2505 | return USBD_IOERROR; | 2501 | return USBD_IOERROR; | |
2506 | 2502 | |||
2507 | KASSERT(xfer->ux_rqflags & URQ_REQUEST); | 2503 | KASSERT(xfer->ux_rqflags & URQ_REQUEST); | |
2508 | 2504 | |||
2509 | DPRINTFN(3, "type=0x%02jx, request=0x%02jx, " | 2505 | DPRINTFN(3, "type=0x%02jx, request=0x%02jx, " | |
2510 | "wValue=0x%04jx, wIndex=0x%04jx", | 2506 | "wValue=0x%04jx, wIndex=0x%04jx", | |
2511 | req->bmRequestType, req->bRequest, UGETW(req->wValue), | 2507 | req->bmRequestType, req->bRequest, UGETW(req->wValue), | |
2512 | UGETW(req->wIndex)); | 2508 | UGETW(req->wIndex)); | |
2513 | DPRINTFN(3, "len=%jd, addr=%jd, endpt=%jd", | 2509 | DPRINTFN(3, "len=%jd, addr=%jd, endpt=%jd", | |
2514 | UGETW(req->wLength), dev->ud_addr, endpt, 0); | 2510 | UGETW(req->wLength), dev->ud_addr, endpt, 0); | |
2515 | 2511 | |||
2516 | isread = req->bmRequestType & UT_READ; | 2512 | isread = req->bmRequestType & UT_READ; | |
2517 | len = UGETW(req->wLength); | 2513 | len = UGETW(req->wLength); | |
2518 | 2514 | |||
2519 | setup = upipe->ctrl.setup; | 2515 | setup = upipe->ctrl.setup; | |
2520 | stat = upipe->ctrl.stat; | 2516 | stat = upipe->ctrl.stat; | |
2521 | sqh = upipe->ctrl.sqh; | 2517 | sqh = upipe->ctrl.sqh; | |
2522 | 2518 | |||
2523 | memcpy(KERNADDR(&upipe->ctrl.reqdma, 0), req, sizeof(*req)); | 2519 | memcpy(KERNADDR(&upipe->ctrl.reqdma, 0), req, sizeof(*req)); | |
2524 | usb_syncmem(&upipe->ctrl.reqdma, 0, sizeof(*req), BUS_DMASYNC_PREWRITE); | 2520 | usb_syncmem(&upipe->ctrl.reqdma, 0, sizeof(*req), BUS_DMASYNC_PREWRITE); | |
2525 | 2521 | |||
2526 | if (!polling) | |||
2527 | mutex_enter(&sc->sc_lock); | |||
2528 | ||||
2529 | /* Set up data transaction */ | 2522 | /* Set up data transaction */ | |
2530 | if (len != 0) { | 2523 | if (len != 0) { | |
2531 | upipe->nexttoggle = 1; | 2524 | upipe->nexttoggle = 1; | |
2532 | next = uxfer->ux_data; | 2525 | next = uxfer->ux_data; | |
2533 | uhci_reset_std_chain(sc, xfer, len, isread, | 2526 | uhci_reset_std_chain(sc, xfer, len, isread, | |
2534 | &upipe->nexttoggle, &dataend); | 2527 | &upipe->nexttoggle, &dataend); | |
2535 | dataend->link.std = stat; | 2528 | dataend->link.std = stat; | |
2536 | dataend->td.td_link = htole32(stat->physaddr | UHCI_PTR_TD); | 2529 | dataend->td.td_link = htole32(stat->physaddr | UHCI_PTR_TD); | |
2537 | usb_syncmem(&dataend->dma, | 2530 | usb_syncmem(&dataend->dma, | |
2538 | dataend->offs + offsetof(uhci_td_t, td_link), | 2531 | dataend->offs + offsetof(uhci_td_t, td_link), | |
2539 | sizeof(dataend->td.td_link), | 2532 | sizeof(dataend->td.td_link), | |
2540 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 2533 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
2541 | } else { | 2534 | } else { | |
@@ -2613,28 +2606,26 @@ uhci_device_ctrl_start(struct usbd_xfer | @@ -2613,28 +2606,26 @@ uhci_device_ctrl_start(struct usbd_xfer | |||
2613 | xqh != NULL; | 2606 | xqh != NULL; | |
2614 | xqh = (maxqh++ == 5 || xqh->hlink == sxqh || | 2607 | xqh = (maxqh++ == 5 || xqh->hlink == sxqh || | |
2615 | xqh->hlink == xqh ? NULL : xqh->hlink)) { | 2608 | xqh->hlink == xqh ? NULL : xqh->hlink)) { | |
2616 | uhci_dump_qh(xqh); | 2609 | uhci_dump_qh(xqh); | |
2617 | } | 2610 | } | |
2618 | DPRINTFN(12, "Enqueued QH:", 0, 0, 0, 0); | 2611 | DPRINTFN(12, "Enqueued QH:", 0, 0, 0, 0); | |
2619 | uhci_dump_qh(sqh); | 2612 | uhci_dump_qh(sqh); | |
2620 | uhci_dump_tds(sqh->elink); | 2613 | uhci_dump_tds(sqh->elink); | |
2621 | DPRINTF("--- dump end ---", 0, 0, 0, 0); | 2614 | DPRINTF("--- dump end ---", 0, 0, 0, 0); | |
2622 | } | 2615 | } | |
2623 | #endif | 2616 | #endif | |
2624 | usbd_xfer_schedule_timeout(xfer); | 2617 | usbd_xfer_schedule_timeout(xfer); | |
2625 | xfer->ux_status = USBD_IN_PROGRESS; | 2618 | xfer->ux_status = USBD_IN_PROGRESS; | |
2626 | if (!polling) | |||
2627 | mutex_exit(&sc->sc_lock); | |||
2628 | 2619 | |||
2629 | return USBD_IN_PROGRESS; | 2620 | return USBD_IN_PROGRESS; | |
2630 | } | 2621 | } | |
2631 | 2622 | |||
2632 | int | 2623 | int | |
2633 | uhci_device_intr_init(struct usbd_xfer *xfer) | 2624 | uhci_device_intr_init(struct usbd_xfer *xfer) | |
2634 | { | 2625 | { | |
2635 | uhci_softc_t *sc = UHCI_XFER2SC(xfer); | 2626 | uhci_softc_t *sc = UHCI_XFER2SC(xfer); | |
2636 | struct uhci_xfer *ux = UHCI_XFER2UXFER(xfer); | 2627 | struct uhci_xfer *ux = UHCI_XFER2UXFER(xfer); | |
2637 | usb_endpoint_descriptor_t *ed = xfer->ux_pipe->up_endpoint->ue_edesc; | 2628 | usb_endpoint_descriptor_t *ed = xfer->ux_pipe->up_endpoint->ue_edesc; | |
2638 | int endpt = ed->bEndpointAddress; | 2629 | int endpt = ed->bEndpointAddress; | |
2639 | int isread = UE_GET_DIR(endpt) == UE_DIR_IN; | 2630 | int isread = UE_GET_DIR(endpt) == UE_DIR_IN; | |
2640 | int len = xfer->ux_bufsize; | 2631 | int len = xfer->ux_bufsize; | |
@@ -2675,54 +2666,53 @@ uhci_device_intr_transfer(struct usbd_xf | @@ -2675,54 +2666,53 @@ uhci_device_intr_transfer(struct usbd_xf | |||
2675 | 2666 | |||
2676 | /* Pipe isn't running, so start it first. */ | 2667 | /* Pipe isn't running, so start it first. */ | |
2677 | return uhci_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 2668 | return uhci_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
2678 | } | 2669 | } | |
2679 | 2670 | |||
2680 | usbd_status | 2671 | usbd_status | |
2681 | uhci_device_intr_start(struct usbd_xfer *xfer) | 2672 | uhci_device_intr_start(struct usbd_xfer *xfer) | |
2682 | { | 2673 | { | |
2683 | struct uhci_xfer *ux = UHCI_XFER2UXFER(xfer); | 2674 | struct uhci_xfer *ux = UHCI_XFER2UXFER(xfer); | |
2684 | struct uhci_pipe *upipe = UHCI_PIPE2UPIPE(xfer->ux_pipe); | 2675 | struct uhci_pipe *upipe = UHCI_PIPE2UPIPE(xfer->ux_pipe); | |
2685 | uhci_softc_t *sc = UHCI_XFER2SC(xfer); | 2676 | uhci_softc_t *sc = UHCI_XFER2SC(xfer); | |
2686 | uhci_soft_td_t *data, *dataend; | 2677 | uhci_soft_td_t *data, *dataend; | |
2687 | uhci_soft_qh_t *sqh; | 2678 | uhci_soft_qh_t *sqh; | |
2688 | const bool polling = sc->sc_bus.ub_usepolling; | |||
2689 | int isread, endpt; | 2679 | int isread, endpt; | |
2690 | int i; | 2680 | int i; | |
2691 | 2681 | |||
2692 | if (sc->sc_dying) | |||
2693 | return USBD_IOERROR; | |||
2694 | ||||
2695 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | 2682 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | |
2696 | 2683 | |||
2697 | DPRINTFN(3, "xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, | 2684 | DPRINTFN(3, "xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, | |
2698 | xfer->ux_length, xfer->ux_flags, 0); | 2685 | xfer->ux_length, xfer->ux_flags, 0); | |
2699 | 2686 | |||
2687 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
2688 | ||||
2689 | if (sc->sc_dying) | |||
2690 | return USBD_IOERROR; | |||
2691 | ||||
2700 | KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); | 2692 | KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); | |
2701 | KASSERT(xfer->ux_length <= xfer->ux_bufsize); | 2693 | KASSERT(xfer->ux_length <= xfer->ux_bufsize); | |
2702 | 2694 | |||
2703 | endpt = upipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; | 2695 | endpt = upipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; | |
2704 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | 2696 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | |
2705 | 2697 | |||
2706 | data = ux->ux_stdstart; | 2698 | data = ux->ux_stdstart; | |
2707 | 2699 | |||
2708 | KASSERT(ux->ux_isdone); | 2700 | KASSERT(ux->ux_isdone); | |
2709 | #ifdef DIAGNOSTIC | 2701 | #ifdef DIAGNOSTIC | |
2710 | ux->ux_isdone = false; | 2702 | ux->ux_isdone = false; | |
2711 | #endif | 2703 | #endif | |
2712 | 2704 | |||
2713 | /* Take lock to protect nexttoggle */ | 2705 | /* Take lock to protect nexttoggle */ | |
2714 | if (!polling) | |||
2715 | mutex_enter(&sc->sc_lock); | |||
2716 | uhci_reset_std_chain(sc, xfer, xfer->ux_length, isread, | 2706 | uhci_reset_std_chain(sc, xfer, xfer->ux_length, isread, | |
2717 | &upipe->nexttoggle, &dataend); | 2707 | &upipe->nexttoggle, &dataend); | |
2718 | 2708 | |||
2719 | dataend->td.td_status |= htole32(UHCI_TD_IOC); | 2709 | dataend->td.td_status |= htole32(UHCI_TD_IOC); | |
2720 | usb_syncmem(&dataend->dma, | 2710 | usb_syncmem(&dataend->dma, | |
2721 | dataend->offs + offsetof(uhci_td_t, td_status), | 2711 | dataend->offs + offsetof(uhci_td_t, td_status), | |
2722 | sizeof(dataend->td.td_status), | 2712 | sizeof(dataend->td.td_status), | |
2723 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 2713 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
2724 | ux->ux_stdend = dataend; | 2714 | ux->ux_stdend = dataend; | |
2725 | 2715 | |||
2726 | #ifdef UHCI_DEBUG | 2716 | #ifdef UHCI_DEBUG | |
2727 | if (uhcidebug >= 10) { | 2717 | if (uhcidebug >= 10) { | |
2728 | DPRINTF("--- dump start ---", 0, 0, 0, 0); | 2718 | DPRINTF("--- dump start ---", 0, 0, 0, 0); | |
@@ -2734,28 +2724,26 @@ uhci_device_intr_start(struct usbd_xfer | @@ -2734,28 +2724,26 @@ uhci_device_intr_start(struct usbd_xfer | |||
2734 | 2724 | |||
2735 | DPRINTFN(10, "qhs[0]=%#jx", (uintptr_t)upipe->intr.qhs[0], 0, 0, 0); | 2725 | DPRINTFN(10, "qhs[0]=%#jx", (uintptr_t)upipe->intr.qhs[0], 0, 0, 0); | |
2736 | for (i = 0; i < upipe->intr.npoll; i++) { | 2726 | for (i = 0; i < upipe->intr.npoll; i++) { | |
2737 | sqh = upipe->intr.qhs[i]; | 2727 | sqh = upipe->intr.qhs[i]; | |
2738 | sqh->elink = data; | 2728 | sqh->elink = data; | |
2739 | sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD); | 2729 | sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD); | |
2740 | usb_syncmem(&sqh->dma, | 2730 | usb_syncmem(&sqh->dma, | |
2741 | sqh->offs + offsetof(uhci_qh_t, qh_elink), | 2731 | sqh->offs + offsetof(uhci_qh_t, qh_elink), | |
2742 | sizeof(sqh->qh.qh_elink), | 2732 | sizeof(sqh->qh.qh_elink), | |
2743 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | 2733 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | |
2744 | } | 2734 | } | |
2745 | uhci_add_intr_list(sc, ux); | 2735 | uhci_add_intr_list(sc, ux); | |
2746 | xfer->ux_status = USBD_IN_PROGRESS; | 2736 | xfer->ux_status = USBD_IN_PROGRESS; | |
2747 | if (!polling) | |||
2748 | mutex_exit(&sc->sc_lock); | |||
2749 | 2737 | |||
2750 | #ifdef UHCI_DEBUG | 2738 | #ifdef UHCI_DEBUG | |
2751 | if (uhcidebug >= 10) { | 2739 | if (uhcidebug >= 10) { | |
2752 | DPRINTF("--- dump start ---", 0, 0, 0, 0); | 2740 | DPRINTF("--- dump start ---", 0, 0, 0, 0); | |
2753 | uhci_dump_tds(data); | 2741 | uhci_dump_tds(data); | |
2754 | uhci_dump_qh(upipe->intr.qhs[0]); | 2742 | uhci_dump_qh(upipe->intr.qhs[0]); | |
2755 | DPRINTF("--- dump end ---", 0, 0, 0, 0); | 2743 | DPRINTF("--- dump end ---", 0, 0, 0, 0); | |
2756 | } | 2744 | } | |
2757 | #endif | 2745 | #endif | |
2758 | 2746 | |||
2759 | return USBD_IN_PROGRESS; | 2747 | return USBD_IN_PROGRESS; | |
2760 | } | 2748 | } | |
2761 | 2749 | |||
@@ -2844,26 +2832,28 @@ uhci_device_isoc_fini(struct usbd_xfer * | @@ -2844,26 +2832,28 @@ uhci_device_isoc_fini(struct usbd_xfer * | |||
2844 | struct uhci_xfer *ux __diagused = UHCI_XFER2UXFER(xfer); | 2832 | struct uhci_xfer *ux __diagused = UHCI_XFER2UXFER(xfer); | |
2845 | 2833 | |||
2846 | KASSERT(ux->ux_type == UX_ISOC); | 2834 | KASSERT(ux->ux_type == UX_ISOC); | |
2847 | } | 2835 | } | |
2848 | 2836 | |||
2849 | usbd_status | 2837 | usbd_status | |
2850 | uhci_device_isoc_transfer(struct usbd_xfer *xfer) | 2838 | uhci_device_isoc_transfer(struct usbd_xfer *xfer) | |
2851 | { | 2839 | { | |
2852 | uhci_softc_t *sc = UHCI_XFER2SC(xfer); | 2840 | uhci_softc_t *sc = UHCI_XFER2SC(xfer); | |
2853 | 2841 | |||
2854 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | 2842 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | |
2855 | DPRINTFN(5, "xfer=%#jx", (uintptr_t)xfer, 0, 0, 0); | 2843 | DPRINTFN(5, "xfer=%#jx", (uintptr_t)xfer, 0, 0, 0); | |
2856 | 2844 | |||
2845 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
2846 | ||||
2857 | /* insert into schedule, */ | 2847 | /* insert into schedule, */ | |
2858 | 2848 | |||
2859 | struct uhci_pipe *upipe = UHCI_PIPE2UPIPE(xfer->ux_pipe); | 2849 | struct uhci_pipe *upipe = UHCI_PIPE2UPIPE(xfer->ux_pipe); | |
2860 | struct uhci_xfer *ux = UHCI_XFER2UXFER(xfer); | 2850 | struct uhci_xfer *ux = UHCI_XFER2UXFER(xfer); | |
2861 | struct isoc *isoc = &upipe->isoc; | 2851 | struct isoc *isoc = &upipe->isoc; | |
2862 | uhci_soft_td_t *std = NULL; | 2852 | uhci_soft_td_t *std = NULL; | |
2863 | uint32_t buf, len, status, offs; | 2853 | uint32_t buf, len, status, offs; | |
2864 | int i, next, nframes; | 2854 | int i, next, nframes; | |
2865 | int rd = UE_GET_DIR(upipe->pipe.up_endpoint->ue_edesc->bEndpointAddress) == UE_DIR_IN; | 2855 | int rd = UE_GET_DIR(upipe->pipe.up_endpoint->ue_edesc->bEndpointAddress) == UE_DIR_IN; | |
2866 | 2856 | |||
2867 | DPRINTFN(5, "used=%jd next=%jd xfer=%#jx nframes=%jd", | 2857 | DPRINTFN(5, "used=%jd next=%jd xfer=%#jx nframes=%jd", | |
2868 | isoc->inuse, isoc->next, (uintptr_t)xfer, xfer->ux_nframes); | 2858 | isoc->inuse, isoc->next, (uintptr_t)xfer, xfer->ux_nframes); | |
2869 | 2859 | |||
@@ -2877,27 +2867,26 @@ uhci_device_isoc_transfer(struct usbd_xf | @@ -2877,27 +2867,26 @@ uhci_device_isoc_transfer(struct usbd_xf | |||
2877 | } | 2867 | } | |
2878 | 2868 | |||
2879 | #ifdef DIAGNOSTIC | 2869 | #ifdef DIAGNOSTIC | |
2880 | if (isoc->inuse >= UHCI_VFRAMELIST_COUNT) | 2870 | if (isoc->inuse >= UHCI_VFRAMELIST_COUNT) | |
2881 | printf("%s: overflow!\n", __func__); | 2871 | printf("%s: overflow!\n", __func__); | |
2882 | #endif | 2872 | #endif | |
2883 | 2873 | |||
2884 | KASSERT(xfer->ux_nframes != 0); | 2874 | KASSERT(xfer->ux_nframes != 0); | |
2885 | 2875 | |||
2886 | if (xfer->ux_length) | 2876 | if (xfer->ux_length) | |
2887 | usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, | 2877 | usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, | |
2888 | rd ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | 2878 | rd ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | |
2889 | 2879 | |||
2890 | mutex_enter(&sc->sc_lock); | |||
2891 | next = isoc->next; | 2880 | next = isoc->next; | |
2892 | if (next == -1) { | 2881 | if (next == -1) { | |
2893 | /* Not in use yet, schedule it a few frames ahead. */ | 2882 | /* Not in use yet, schedule it a few frames ahead. */ | |
2894 | next = (UREAD2(sc, UHCI_FRNUM) + 3) % UHCI_VFRAMELIST_COUNT; | 2883 | next = (UREAD2(sc, UHCI_FRNUM) + 3) % UHCI_VFRAMELIST_COUNT; | |
2895 | DPRINTFN(2, "start next=%jd", next, 0, 0, 0); | 2884 | DPRINTFN(2, "start next=%jd", next, 0, 0, 0); | |
2896 | } | 2885 | } | |
2897 | 2886 | |||
2898 | xfer->ux_status = USBD_IN_PROGRESS; | 2887 | xfer->ux_status = USBD_IN_PROGRESS; | |
2899 | ux->ux_curframe = next; | 2888 | ux->ux_curframe = next; | |
2900 | 2889 | |||
2901 | offs = 0; | 2890 | offs = 0; | |
2902 | status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) | | 2891 | status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) | | |
2903 | UHCI_TD_ACTIVE | | 2892 | UHCI_TD_ACTIVE | | |
@@ -2939,28 +2928,26 @@ uhci_device_isoc_transfer(struct usbd_xf | @@ -2939,28 +2928,26 @@ uhci_device_isoc_transfer(struct usbd_xf | |||
2939 | isoc->next = next; | 2928 | isoc->next = next; | |
2940 | isoc->inuse += xfer->ux_nframes; | 2929 | isoc->inuse += xfer->ux_nframes; | |
2941 | 2930 | |||
2942 | /* Set up interrupt info. */ | 2931 | /* Set up interrupt info. */ | |
2943 | ux->ux_stdstart = std; | 2932 | ux->ux_stdstart = std; | |
2944 | ux->ux_stdend = std; | 2933 | ux->ux_stdend = std; | |
2945 | 2934 | |||
2946 | KASSERT(ux->ux_isdone); | 2935 | KASSERT(ux->ux_isdone); | |
2947 | #ifdef DIAGNOSTIC | 2936 | #ifdef DIAGNOSTIC | |
2948 | ux->ux_isdone = false; | 2937 | ux->ux_isdone = false; | |
2949 | #endif | 2938 | #endif | |
2950 | uhci_add_intr_list(sc, ux); | 2939 | uhci_add_intr_list(sc, ux); | |
2951 | 2940 | |||
2952 | mutex_exit(&sc->sc_lock); | |||
2953 | ||||
2954 | return USBD_IN_PROGRESS; | 2941 | return USBD_IN_PROGRESS; | |
2955 | } | 2942 | } | |
2956 | 2943 | |||
2957 | void | 2944 | void | |
2958 | uhci_device_isoc_abort(struct usbd_xfer *xfer) | 2945 | uhci_device_isoc_abort(struct usbd_xfer *xfer) | |
2959 | { | 2946 | { | |
2960 | uhci_softc_t *sc = UHCI_XFER2SC(xfer); | 2947 | uhci_softc_t *sc = UHCI_XFER2SC(xfer); | |
2961 | struct uhci_pipe *upipe = UHCI_PIPE2UPIPE(xfer->ux_pipe); | 2948 | struct uhci_pipe *upipe = UHCI_PIPE2UPIPE(xfer->ux_pipe); | |
2962 | struct uhci_xfer *ux = UHCI_XFER2UXFER(xfer); | 2949 | struct uhci_xfer *ux = UHCI_XFER2UXFER(xfer); | |
2963 | uhci_soft_td_t **stds = upipe->isoc.stds; | 2950 | uhci_soft_td_t **stds = upipe->isoc.stds; | |
2964 | uhci_soft_td_t *std; | 2951 | uhci_soft_td_t *std; | |
2965 | int i, n, nframes, maxlen, len; | 2952 | int i, n, nframes, maxlen, len; | |
2966 | 2953 | |||
@@ -3592,26 +3579,28 @@ uhci_portreset(uhci_softc_t *sc, int ind | @@ -3592,26 +3579,28 @@ uhci_portreset(uhci_softc_t *sc, int ind | |||
3592 | Static int | 3579 | Static int | |
3593 | uhci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, | 3580 | uhci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, | |
3594 | void *buf, int buflen) | 3581 | void *buf, int buflen) | |
3595 | { | 3582 | { | |
3596 | uhci_softc_t *sc = UHCI_BUS2SC(bus); | 3583 | uhci_softc_t *sc = UHCI_BUS2SC(bus); | |
3597 | int port, x; | 3584 | int port, x; | |
3598 | int status, change, totlen = 0; | 3585 | int status, change, totlen = 0; | |
3599 | uint16_t len, value, index; | 3586 | uint16_t len, value, index; | |
3600 | usb_port_status_t ps; | 3587 | usb_port_status_t ps; | |
3601 | usbd_status err; | 3588 | usbd_status err; | |
3602 | 3589 | |||
3603 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | 3590 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | |
3604 | 3591 | |||
3592 | KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock)); | |||
3593 | ||||
3605 | if (sc->sc_dying) | 3594 | if (sc->sc_dying) | |
3606 | return -1; | 3595 | return -1; | |
3607 | 3596 | |||
3608 | DPRINTF("type=0x%02jx request=%02jx", req->bmRequestType, | 3597 | DPRINTF("type=0x%02jx request=%02jx", req->bmRequestType, | |
3609 | req->bRequest, 0, 0); | 3598 | req->bRequest, 0, 0); | |
3610 | 3599 | |||
3611 | len = UGETW(req->wLength); | 3600 | len = UGETW(req->wLength); | |
3612 | value = UGETW(req->wValue); | 3601 | value = UGETW(req->wValue); | |
3613 | index = UGETW(req->wIndex); | 3602 | index = UGETW(req->wIndex); | |
3614 | 3603 | |||
3615 | #define C(x,y) ((x) | ((y) << 8)) | 3604 | #define C(x,y) ((x) | ((y) << 8)) | |
3616 | switch (C(req->bRequest, req->bmRequestType)) { | 3605 | switch (C(req->bRequest, req->bmRequestType)) { | |
3617 | case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): | 3606 | case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): | |
@@ -3843,50 +3832,45 @@ uhci_root_intr_transfer(struct usbd_xfer | @@ -3843,50 +3832,45 @@ uhci_root_intr_transfer(struct usbd_xfer | |||
3843 | { | 3832 | { | |
3844 | 3833 | |||
3845 | /* Pipe isn't running, start first */ | 3834 | /* Pipe isn't running, start first */ | |
3846 | return uhci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 3835 | return uhci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
3847 | } | 3836 | } | |
3848 | 3837 | |||
3849 | /* Start a transfer on the root interrupt pipe */ | 3838 | /* Start a transfer on the root interrupt pipe */ | |
3850 | usbd_status | 3839 | usbd_status | |
3851 | uhci_root_intr_start(struct usbd_xfer *xfer) | 3840 | uhci_root_intr_start(struct usbd_xfer *xfer) | |
3852 | { | 3841 | { | |
3853 | struct usbd_pipe *pipe = xfer->ux_pipe; | 3842 | struct usbd_pipe *pipe = xfer->ux_pipe; | |
3854 | uhci_softc_t *sc = UHCI_PIPE2SC(pipe); | 3843 | uhci_softc_t *sc = UHCI_PIPE2SC(pipe); | |
3855 | unsigned int ival; | 3844 | unsigned int ival; | |
3856 | const bool polling = sc->sc_bus.ub_usepolling; | |||
3857 | 3845 | |||
3858 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | 3846 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | |
3859 | DPRINTF("xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, xfer->ux_length, | 3847 | DPRINTF("xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer, xfer->ux_length, | |
3860 | xfer->ux_flags, 0); | 3848 | xfer->ux_flags, 0); | |
3861 | 3849 | |||
3850 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
3851 | ||||
3862 | if (sc->sc_dying) | 3852 | if (sc->sc_dying) | |
3863 | return USBD_IOERROR; | 3853 | return USBD_IOERROR; | |
3864 | 3854 | |||
3865 | if (!polling) | |||
3866 | mutex_enter(&sc->sc_lock); | |||
3867 | ||||
3868 | KASSERT(sc->sc_intr_xfer == NULL); | 3855 | KASSERT(sc->sc_intr_xfer == NULL); | |
3869 | 3856 | |||
3870 | /* XXX temporary variable needed to avoid gcc3 warning */ | 3857 | /* XXX temporary variable needed to avoid gcc3 warning */ | |
3871 | ival = xfer->ux_pipe->up_endpoint->ue_edesc->bInterval; | 3858 | ival = xfer->ux_pipe->up_endpoint->ue_edesc->bInterval; | |
3872 | sc->sc_ival = mstohz(ival); | 3859 | sc->sc_ival = mstohz(ival); | |
3873 | callout_schedule(&sc->sc_poll_handle, sc->sc_ival); | 3860 | callout_schedule(&sc->sc_poll_handle, sc->sc_ival); | |
3874 | sc->sc_intr_xfer = xfer; | 3861 | sc->sc_intr_xfer = xfer; | |
3875 | xfer->ux_status = USBD_IN_PROGRESS; | 3862 | xfer->ux_status = USBD_IN_PROGRESS; | |
3876 | 3863 | |||
3877 | if (!polling) | |||
3878 | mutex_exit(&sc->sc_lock); | |||
3879 | ||||
3880 | return USBD_IN_PROGRESS; | 3864 | return USBD_IN_PROGRESS; | |
3881 | } | 3865 | } | |
3882 | 3866 | |||
3883 | /* Close the root interrupt pipe. */ | 3867 | /* Close the root interrupt pipe. */ | |
3884 | void | 3868 | void | |
3885 | uhci_root_intr_close(struct usbd_pipe *pipe) | 3869 | uhci_root_intr_close(struct usbd_pipe *pipe) | |
3886 | { | 3870 | { | |
3887 | uhci_softc_t *sc __diagused = UHCI_PIPE2SC(pipe); | 3871 | uhci_softc_t *sc __diagused = UHCI_PIPE2SC(pipe); | |
3888 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | 3872 | UHCIHIST_FUNC(); UHCIHIST_CALLED(); | |
3889 | 3873 | |||
3890 | KASSERT(mutex_owned(&sc->sc_lock)); | 3874 | KASSERT(mutex_owned(&sc->sc_lock)); | |
3891 | 3875 | |||
3892 | /* | 3876 | /* |
--- src/sys/dev/usb/usbdi.c 2022/03/03 06:09:57 1.230
+++ src/sys/dev/usb/usbdi.c 2022/03/03 06:12:11 1.231
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: usbdi.c,v 1.230 2022/03/03 06:09:57 riastradh Exp $ */ | 1 | /* $NetBSD: usbdi.c,v 1.231 2022/03/03 06:12:11 riastradh Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2012, 2015 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 2012, 2015 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Lennart Augustsson (lennart@augustsson.net) at | 8 | * by Lennart Augustsson (lennart@augustsson.net) at | |
9 | * Carlstedt Research & Technology, Matthew R. Green (mrg@eterna.com.au), | 9 | * Carlstedt Research & Technology, Matthew R. Green (mrg@eterna.com.au), | |
10 | * and Nick Hudson. | 10 | * and Nick Hudson. | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
@@ -22,27 +22,27 @@ | @@ -22,27 +22,27 @@ | |||
22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
31 | * POSSIBILITY OF SUCH DAMAGE. | 31 | * POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | #include <sys/cdefs.h> | 34 | #include <sys/cdefs.h> | |
35 | __KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.230 2022/03/03 06:09:57 riastradh Exp $"); | 35 | __KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.231 2022/03/03 06:12:11 riastradh Exp $"); | |
36 | 36 | |||
37 | #ifdef _KERNEL_OPT | 37 | #ifdef _KERNEL_OPT | |
38 | #include "opt_usb.h" | 38 | #include "opt_usb.h" | |
39 | #include "opt_compat_netbsd.h" | 39 | #include "opt_compat_netbsd.h" | |
40 | #include "usb_dma.h" | 40 | #include "usb_dma.h" | |
41 | #endif | 41 | #endif | |
42 | 42 | |||
43 | #include <sys/param.h> | 43 | #include <sys/param.h> | |
44 | #include <sys/systm.h> | 44 | #include <sys/systm.h> | |
45 | #include <sys/kernel.h> | 45 | #include <sys/kernel.h> | |
46 | #include <sys/device.h> | 46 | #include <sys/device.h> | |
47 | #include <sys/kmem.h> | 47 | #include <sys/kmem.h> | |
48 | #include <sys/proc.h> | 48 | #include <sys/proc.h> | |
@@ -412,33 +412,34 @@ usbd_transfer(struct usbd_xfer *xfer) | @@ -412,33 +412,34 @@ usbd_transfer(struct usbd_xfer *xfer) | |||
412 | /* xfer is not valid after the transfer method unless synchronous */ | 412 | /* xfer is not valid after the transfer method unless synchronous */ | |
413 | SDT_PROBE2(usb, device, pipe, transfer__start, pipe, xfer); | 413 | SDT_PROBE2(usb, device, pipe, transfer__start, pipe, xfer); | |
414 | do { | 414 | do { | |
415 | #ifdef DIAGNOSTIC | 415 | #ifdef DIAGNOSTIC | |
416 | xfer->ux_state = XFER_ONQU; | 416 | xfer->ux_state = XFER_ONQU; | |
417 | #endif | 417 | #endif | |
418 | SIMPLEQ_INSERT_TAIL(&pipe->up_queue, xfer, ux_next); | 418 | SIMPLEQ_INSERT_TAIL(&pipe->up_queue, xfer, ux_next); | |
419 | if (pipe->up_running && pipe->up_serialise) { | 419 | if (pipe->up_running && pipe->up_serialise) { | |
420 | err = USBD_IN_PROGRESS; | 420 | err = USBD_IN_PROGRESS; | |
421 | } else { | 421 | } else { | |
422 | pipe->up_running = 1; | 422 | pipe->up_running = 1; | |
423 | err = USBD_NORMAL_COMPLETION; | 423 | err = USBD_NORMAL_COMPLETION; | |
424 | } | 424 | } | |
425 | usbd_unlock_pipe(pipe); | |||
426 | if (err) | 425 | if (err) | |
427 | break; | 426 | break; | |
428 | err = pipe->up_methods->upm_transfer(xfer); | 427 | err = pipe->up_methods->upm_transfer(xfer); | |
429 | } while (0); | 428 | } while (0); | |
430 | SDT_PROBE3(usb, device, pipe, transfer__done, pipe, xfer, err); | 429 | SDT_PROBE3(usb, device, pipe, transfer__done, pipe, xfer, err); | |
431 | 430 | |||
431 | usbd_unlock_pipe(pipe); | |||
432 | ||||
432 | if (err != USBD_IN_PROGRESS && err) { | 433 | if (err != USBD_IN_PROGRESS && err) { | |
433 | /* | 434 | /* | |
434 | * The transfer made it onto the pipe queue, but didn't get | 435 | * The transfer made it onto the pipe queue, but didn't get | |
435 | * accepted by the HCD for some reason. It needs removing | 436 | * accepted by the HCD for some reason. It needs removing | |
436 | * from the pipe queue. | 437 | * from the pipe queue. | |
437 | */ | 438 | */ | |
438 | USBHIST_LOG(usbdebug, "xfer failed: %jd, reinserting", | 439 | USBHIST_LOG(usbdebug, "xfer failed: %jd, reinserting", | |
439 | err, 0, 0, 0); | 440 | err, 0, 0, 0); | |
440 | usbd_lock_pipe(pipe); | 441 | usbd_lock_pipe(pipe); | |
441 | SDT_PROBE1(usb, device, xfer, preabort, xfer); | 442 | SDT_PROBE1(usb, device, xfer, preabort, xfer); | |
442 | #ifdef DIAGNOSTIC | 443 | #ifdef DIAGNOSTIC | |
443 | xfer->ux_state = XFER_BUSY; | 444 | xfer->ux_state = XFER_BUSY; | |
444 | #endif | 445 | #endif | |
@@ -1180,32 +1181,28 @@ usbd_start_next(struct usbd_pipe *pipe) | @@ -1180,32 +1181,28 @@ usbd_start_next(struct usbd_pipe *pipe) | |||
1180 | KASSERT(pipe->up_methods->upm_start != NULL); | 1181 | KASSERT(pipe->up_methods->upm_start != NULL); | |
1181 | KASSERT(pipe->up_serialise == true); | 1182 | KASSERT(pipe->up_serialise == true); | |
1182 | 1183 | |||
1183 | int polling = pipe->up_dev->ud_bus->ub_usepolling; | 1184 | int polling = pipe->up_dev->ud_bus->ub_usepolling; | |
1184 | KASSERT(polling || mutex_owned(pipe->up_dev->ud_bus->ub_lock)); | 1185 | KASSERT(polling || mutex_owned(pipe->up_dev->ud_bus->ub_lock)); | |
1185 | 1186 | |||
1186 | /* Get next request in queue. */ | 1187 | /* Get next request in queue. */ | |
1187 | xfer = SIMPLEQ_FIRST(&pipe->up_queue); | 1188 | xfer = SIMPLEQ_FIRST(&pipe->up_queue); | |
1188 | USBHIST_CALLARGS(usbdebug, "pipe = %#jx, xfer = %#jx", (uintptr_t)pipe, | 1189 | USBHIST_CALLARGS(usbdebug, "pipe = %#jx, xfer = %#jx", (uintptr_t)pipe, | |
1189 | (uintptr_t)xfer, 0, 0); | 1190 | (uintptr_t)xfer, 0, 0); | |
1190 | if (xfer == NULL) { | 1191 | if (xfer == NULL) { | |
1191 | pipe->up_running = 0; | 1192 | pipe->up_running = 0; | |
1192 | } else { | 1193 | } else { | |
1193 | if (!polling) | |||
1194 | mutex_exit(pipe->up_dev->ud_bus->ub_lock); | |||
1195 | SDT_PROBE2(usb, device, pipe, start, pipe, xfer); | 1194 | SDT_PROBE2(usb, device, pipe, start, pipe, xfer); | |
1196 | err = pipe->up_methods->upm_start(xfer); | 1195 | err = pipe->up_methods->upm_start(xfer); | |
1197 | if (!polling) | |||
1198 | mutex_enter(pipe->up_dev->ud_bus->ub_lock); | |||
1199 | 1196 | |||
1200 | if (err != USBD_IN_PROGRESS) { | 1197 | if (err != USBD_IN_PROGRESS) { | |
1201 | USBHIST_LOG(usbdebug, "error = %jd", err, 0, 0, 0); | 1198 | USBHIST_LOG(usbdebug, "error = %jd", err, 0, 0, 0); | |
1202 | pipe->up_running = 0; | 1199 | pipe->up_running = 0; | |
1203 | /* XXX do what? */ | 1200 | /* XXX do what? */ | |
1204 | } | 1201 | } | |
1205 | } | 1202 | } | |
1206 | 1203 | |||
1207 | KASSERT(polling || mutex_owned(pipe->up_dev->ud_bus->ub_lock)); | 1204 | KASSERT(polling || mutex_owned(pipe->up_dev->ud_bus->ub_lock)); | |
1208 | } | 1205 | } | |
1209 | 1206 | |||
1210 | usbd_status | 1207 | usbd_status | |
1211 | usbd_do_request(struct usbd_device *dev, usb_device_request_t *req, void *data) | 1208 | usbd_do_request(struct usbd_device *dev, usb_device_request_t *req, void *data) |
--- src/sys/dev/usb/usbdivar.h 2022/03/03 06:09:20 1.133
+++ src/sys/dev/usb/usbdivar.h 2022/03/03 06:12:11 1.134
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: usbdivar.h,v 1.133 2022/03/03 06:09:20 riastradh Exp $ */ | 1 | /* $NetBSD: usbdivar.h,v 1.134 2022/03/03 06:12:11 riastradh Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2012 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 2012 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Lennart Augustsson (lennart@augustsson.net) at | 8 | * by Lennart Augustsson (lennart@augustsson.net) at | |
9 | * Carlstedt Research & Technology and Matthew R. Green (mrg@eterna.com.au). | 9 | * Carlstedt Research & Technology and Matthew R. Green (mrg@eterna.com.au). | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -41,34 +41,34 @@ | @@ -41,34 +41,34 @@ | |||
41 | * List of hardware interface methods, and whether the lock is held | 41 | * List of hardware interface methods, and whether the lock is held | |
42 | * when each is called by this module: | 42 | * when each is called by this module: | |
43 | * | 43 | * | |
44 | * BUS METHOD LOCK NOTES | 44 | * BUS METHOD LOCK NOTES | |
45 | * ----------------------- ------- ------------------------- | 45 | * ----------------------- ------- ------------------------- | |
46 | * ubm_open - might want to take lock? | 46 | * ubm_open - might want to take lock? | |
47 | * ubm_softint x may release/reacquire lock | 47 | * ubm_softint x may release/reacquire lock | |
48 | * ubm_dopoll - might want to take lock? | 48 | * ubm_dopoll - might want to take lock? | |
49 | * ubm_allocx - | 49 | * ubm_allocx - | |
50 | * ubm_freex - | 50 | * ubm_freex - | |
51 | * ubm_abortx x must not release/reacquire lock | 51 | * ubm_abortx x must not release/reacquire lock | |
52 | * ubm_getlock - Called at attach time | 52 | * ubm_getlock - Called at attach time | |
53 | * ubm_newdev - Will take lock | 53 | * ubm_newdev - Will take lock | |
54 | * ubm_rhctrl | 54 | * ubm_rhctrl x | |
55 | * | 55 | * | |
56 | * PIPE METHOD LOCK NOTES | 56 | * PIPE METHOD LOCK NOTES | |
57 | * ----------------------- ------- ------------------------- | 57 | * ----------------------- ------- ------------------------- | |
58 | * upm_init - | 58 | * upm_init - | |
59 | * upm_fini - | 59 | * upm_fini - | |
60 | * upm_transfer - | 60 | * upm_transfer x | |
61 | * upm_start - might want to take lock? | 61 | * upm_start x | |
62 | * upm_abort x | 62 | * upm_abort x | |
63 | * upm_close x | 63 | * upm_close x | |
64 | * upm_cleartoggle - | 64 | * upm_cleartoggle - | |
65 | * upm_done x | 65 | * upm_done x | |
66 | * | 66 | * | |
67 | * The above semantics are likely to change. Little performance | 67 | * The above semantics are likely to change. Little performance | |
68 | * evaluation has been done on this code and the locking strategy. | 68 | * evaluation has been done on this code and the locking strategy. | |
69 | * | 69 | * | |
70 | * USB functions known to expect the lock taken include (this list is | 70 | * USB functions known to expect the lock taken include (this list is | |
71 | * probably not exhaustive): | 71 | * probably not exhaustive): | |
72 | * usb_transfer_complete() | 72 | * usb_transfer_complete() | |
73 | * usb_start_next() | 73 | * usb_start_next() | |
74 | * | 74 | * |
--- src/sys/dev/usb/usbroothub.c 2022/03/03 06:04:31 1.12
+++ src/sys/dev/usb/usbroothub.c 2022/03/03 06:12:11 1.13
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: usbroothub.c,v 1.12 2022/03/03 06:04:31 riastradh Exp $ */ | 1 | /* $NetBSD: usbroothub.c,v 1.13 2022/03/03 06:12:11 riastradh Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1998, 2004, 2011, 2012 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 2004, 2011, 2012 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Lennart Augustsson (lennart@augustsson.net) at | 8 | * by Lennart Augustsson (lennart@augustsson.net) at | |
9 | * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca), | 9 | * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca), | |
10 | * Matthew R. Green (mrg@eterna.com.au) and Nick Hudson. | 10 | * Matthew R. Green (mrg@eterna.com.au) and Nick Hudson. | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
@@ -48,27 +48,27 @@ | @@ -48,27 +48,27 @@ | |||
48 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 48 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
49 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 49 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
50 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 50 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
51 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 51 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
52 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 52 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
53 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 53 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
54 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 54 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
55 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 55 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
56 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 56 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
57 | * | 57 | * | |
58 | */ | 58 | */ | |
59 | 59 | |||
60 | #include <sys/cdefs.h> | 60 | #include <sys/cdefs.h> | |
61 | __KERNEL_RCSID(0, "$NetBSD: usbroothub.c,v 1.12 2022/03/03 06:04:31 riastradh Exp $"); | 61 | __KERNEL_RCSID(0, "$NetBSD: usbroothub.c,v 1.13 2022/03/03 06:12:11 riastradh Exp $"); | |
62 | 62 | |||
63 | #include <sys/param.h> | 63 | #include <sys/param.h> | |
64 | #include <sys/systm.h> /* for ostype */ | 64 | #include <sys/systm.h> /* for ostype */ | |
65 | 65 | |||
66 | #include <dev/usb/usb.h> | 66 | #include <dev/usb/usb.h> | |
67 | #include <dev/usb/usbdi.h> | 67 | #include <dev/usb/usbdi.h> | |
68 | #include <dev/usb/usbdivar.h> | 68 | #include <dev/usb/usbdivar.h> | |
69 | #include <dev/usb/usbroothub.h> | 69 | #include <dev/usb/usbroothub.h> | |
70 | #include <dev/usb/usbhist.h> | 70 | #include <dev/usb/usbhist.h> | |
71 | 71 | |||
72 | /* helper functions for USB root hub emulation */ | 72 | /* helper functions for USB root hub emulation */ | |
73 | 73 | |||
74 | static usbd_status roothub_ctrl_transfer(struct usbd_xfer *); | 74 | static usbd_status roothub_ctrl_transfer(struct usbd_xfer *); | |
@@ -351,26 +351,33 @@ roothub_ctrl_transfer(struct usbd_xfer * | @@ -351,26 +351,33 @@ roothub_ctrl_transfer(struct usbd_xfer * | |||
351 | static usbd_status | 351 | static usbd_status | |
352 | roothub_ctrl_start(struct usbd_xfer *xfer) | 352 | roothub_ctrl_start(struct usbd_xfer *xfer) | |
353 | { | 353 | { | |
354 | struct usbd_pipe *pipe = xfer->ux_pipe; | 354 | struct usbd_pipe *pipe = xfer->ux_pipe; | |
355 | struct usbd_bus *bus = pipe->up_dev->ud_bus; | 355 | struct usbd_bus *bus = pipe->up_dev->ud_bus; | |
356 | usb_device_request_t *req; | 356 | usb_device_request_t *req; | |
357 | usbd_status err = USBD_IOERROR; /* XXX STALL? */ | 357 | usbd_status err = USBD_IOERROR; /* XXX STALL? */ | |
358 | uint16_t len, value; | 358 | uint16_t len, value; | |
359 | int buflen, actlen = -1; | 359 | int buflen, actlen = -1; | |
360 | void *buf; | 360 | void *buf; | |
361 | 361 | |||
362 | USBHIST_FUNC(); | 362 | USBHIST_FUNC(); | |
363 | 363 | |||
364 | /* | |||
365 | * XXX Should really assert pipe lock, in case ever have | |||
366 | * per-pipe locking instead of using the bus lock for all | |||
367 | * pipes. | |||
368 | */ | |||
369 | KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock)); | |||
370 | ||||
364 | KASSERT(xfer->ux_rqflags & URQ_REQUEST); | 371 | KASSERT(xfer->ux_rqflags & URQ_REQUEST); | |
365 | req = &xfer->ux_request; | 372 | req = &xfer->ux_request; | |
366 | 373 | |||
367 | len = UGETW(req->wLength); | 374 | len = UGETW(req->wLength); | |
368 | value = UGETW(req->wValue); | 375 | value = UGETW(req->wValue); | |
369 | 376 | |||
370 | USBHIST_CALLARGS(usbdebug, "type=%#jx request=%#jx len=%#jx value=%#jx", | 377 | USBHIST_CALLARGS(usbdebug, "type=%#jx request=%#jx len=%#jx value=%#jx", | |
371 | req->bmRequestType, req->bRequest, len, value); | 378 | req->bmRequestType, req->bRequest, len, value); | |
372 | 379 | |||
373 | buf = len ? usbd_get_buffer(xfer) : NULL; | 380 | buf = len ? usbd_get_buffer(xfer) : NULL; | |
374 | buflen = 0; | 381 | buflen = 0; | |
375 | 382 | |||
376 | #define C(x,y) ((x) | ((y) << 8)) | 383 | #define C(x,y) ((x) | ((y) << 8)) | |
@@ -544,29 +551,27 @@ roothub_ctrl_start(struct usbd_xfer *xfe | @@ -544,29 +551,27 @@ roothub_ctrl_start(struct usbd_xfer *xfe | |||
544 | 551 | |||
545 | actlen = bus->ub_methods->ubm_rhctrl(bus, req, buf, buflen); | 552 | actlen = bus->ub_methods->ubm_rhctrl(bus, req, buf, buflen); | |
546 | if (actlen < 0) | 553 | if (actlen < 0) | |
547 | goto fail; | 554 | goto fail; | |
548 | 555 | |||
549 | xfer->ux_actlen = actlen; | 556 | xfer->ux_actlen = actlen; | |
550 | err = USBD_NORMAL_COMPLETION; | 557 | err = USBD_NORMAL_COMPLETION; | |
551 | 558 | |||
552 | fail: | 559 | fail: | |
553 | USBHIST_LOG(usbdebug, "xfer %#jx buflen %jd actlen %jd err %jd", | 560 | USBHIST_LOG(usbdebug, "xfer %#jx buflen %jd actlen %jd err %jd", | |
554 | (uintptr_t)xfer, buflen, actlen, err); | 561 | (uintptr_t)xfer, buflen, actlen, err); | |
555 | 562 | |||
556 | xfer->ux_status = err; | 563 | xfer->ux_status = err; | |
557 | mutex_enter(bus->ub_lock); | |||
558 | usb_transfer_complete(xfer); | 564 | usb_transfer_complete(xfer); | |
559 | mutex_exit(bus->ub_lock); | |||
560 | 565 | |||
561 | return USBD_NORMAL_COMPLETION; | 566 | return USBD_NORMAL_COMPLETION; | |
562 | } | 567 | } | |
563 | 568 | |||
564 | /* Abort a root control request. */ | 569 | /* Abort a root control request. */ | |
565 | Static void | 570 | Static void | |
566 | roothub_ctrl_abort(struct usbd_xfer *xfer) | 571 | roothub_ctrl_abort(struct usbd_xfer *xfer) | |
567 | { | 572 | { | |
568 | 573 | |||
569 | /* Nothing to do, all transfers are synchronous. */ | 574 | /* Nothing to do, all transfers are synchronous. */ | |
570 | } | 575 | } | |
571 | 576 | |||
572 | /* Close the root pipe. */ | 577 | /* Close the root pipe. */ |
--- src/sys/dev/usb/vhci.c 2022/03/03 06:04:31 1.24
+++ src/sys/dev/usb/vhci.c 2022/03/03 06:12:11 1.25
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: vhci.c,v 1.24 2022/03/03 06:04:31 riastradh Exp $ */ | 1 | /* $NetBSD: vhci.c,v 1.25 2022/03/03 06:12:11 riastradh Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2019-2020 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2019-2020 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Maxime Villard. | 8 | * by Maxime Villard. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -20,27 +20,27 @@ | @@ -20,27 +20,27 @@ | |||
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | __KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.24 2022/03/03 06:04:31 riastradh Exp $"); | 33 | __KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.25 2022/03/03 06:12:11 riastradh Exp $"); | |
34 | 34 | |||
35 | #ifdef _KERNEL_OPT | 35 | #ifdef _KERNEL_OPT | |
36 | #include "opt_usb.h" | 36 | #include "opt_usb.h" | |
37 | #endif | 37 | #endif | |
38 | 38 | |||
39 | #include <sys/param.h> | 39 | #include <sys/param.h> | |
40 | 40 | |||
41 | #include <sys/bus.h> | 41 | #include <sys/bus.h> | |
42 | #include <sys/cpu.h> | 42 | #include <sys/cpu.h> | |
43 | #include <sys/conf.h> | 43 | #include <sys/conf.h> | |
44 | #include <sys/device.h> | 44 | #include <sys/device.h> | |
45 | #include <sys/kernel.h> | 45 | #include <sys/kernel.h> | |
46 | #include <sys/kmem.h> | 46 | #include <sys/kmem.h> | |
@@ -595,60 +595,55 @@ vhci_device_ctrl_transfer(struct usbd_xf | @@ -595,60 +595,55 @@ vhci_device_ctrl_transfer(struct usbd_xf | |||
595 | 595 | |||
596 | /* Pipe isn't running, start first */ | 596 | /* Pipe isn't running, start first */ | |
597 | return vhci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 597 | return vhci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
598 | } | 598 | } | |
599 | 599 | |||
600 | static usbd_status | 600 | static usbd_status | |
601 | vhci_device_ctrl_start(struct usbd_xfer *xfer) | 601 | vhci_device_ctrl_start(struct usbd_xfer *xfer) | |
602 | { | 602 | { | |
603 | usb_endpoint_descriptor_t *ed = xfer->ux_pipe->up_endpoint->ue_edesc; | 603 | usb_endpoint_descriptor_t *ed = xfer->ux_pipe->up_endpoint->ue_edesc; | |
604 | usb_device_request_t *req = &xfer->ux_request; | 604 | usb_device_request_t *req = &xfer->ux_request; | |
605 | struct usbd_device *dev = xfer->ux_pipe->up_dev; | 605 | struct usbd_device *dev = xfer->ux_pipe->up_dev; | |
606 | vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv; | 606 | vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv; | |
607 | vhci_port_t *port; | 607 | vhci_port_t *port; | |
608 | bool polling = sc->sc_bus.ub_usepolling; | |||
609 | bool isread = (req->bmRequestType & UT_READ) != 0; | 608 | bool isread = (req->bmRequestType & UT_READ) != 0; | |
610 | uint8_t addr = UE_GET_ADDR(ed->bEndpointAddress); | 609 | uint8_t addr = UE_GET_ADDR(ed->bEndpointAddress); | |
611 | int portno, ret; | 610 | int portno, ret; | |
612 | 611 | |||
613 | KASSERT(addr == 0); | 612 | KASSERT(addr == 0); | |
614 | KASSERT(xfer->ux_rqflags & URQ_REQUEST); | 613 | KASSERT(xfer->ux_rqflags & URQ_REQUEST); | |
615 | KASSERT(dev->ud_myhsport != NULL); | 614 | KASSERT(dev->ud_myhsport != NULL); | |
616 | portno = dev->ud_myhsport->up_portno; | 615 | portno = dev->ud_myhsport->up_portno; | |
617 | 616 | |||
618 | DPRINTF("%s: type=0x%02x, len=%d, isread=%d, portno=%d\n", | 617 | DPRINTF("%s: type=0x%02x, len=%d, isread=%d, portno=%d\n", | |
619 | __func__, req->bmRequestType, UGETW(req->wLength), isread, portno); | 618 | __func__, req->bmRequestType, UGETW(req->wLength), isread, portno); | |
620 | 619 | |||
620 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
621 | ||||
621 | if (sc->sc_dying) | 622 | if (sc->sc_dying) | |
622 | return USBD_IOERROR; | 623 | return USBD_IOERROR; | |
623 | 624 | |||
624 | port = &sc->sc_port[portno]; | 625 | port = &sc->sc_port[portno]; | |
625 | 626 | |||
626 | if (!polling) | |||
627 | mutex_enter(&sc->sc_lock); | |||
628 | ||||
629 | mutex_enter(&port->lock); | 627 | mutex_enter(&port->lock); | |
630 | if (port->status & UPS_PORT_ENABLED) { | 628 | if (port->status & UPS_PORT_ENABLED) { | |
631 | xfer->ux_status = USBD_IN_PROGRESS; | 629 | xfer->ux_status = USBD_IN_PROGRESS; | |
632 | vhci_pkt_ctrl_create(port, xfer, isread, addr); | 630 | vhci_pkt_ctrl_create(port, xfer, isread, addr); | |
633 | ret = USBD_IN_PROGRESS; | 631 | ret = USBD_IN_PROGRESS; | |
634 | } else { | 632 | } else { | |
635 | ret = USBD_IOERROR; | 633 | ret = USBD_IOERROR; | |
636 | } | 634 | } | |
637 | mutex_exit(&port->lock); | 635 | mutex_exit(&port->lock); | |
638 | 636 | |||
639 | if (!polling) | |||
640 | mutex_exit(&sc->sc_lock); | |||
641 | ||||
642 | return ret; | 637 | return ret; | |
643 | } | 638 | } | |
644 | 639 | |||
645 | static void | 640 | static void | |
646 | vhci_device_ctrl_abort(struct usbd_xfer *xfer) | 641 | vhci_device_ctrl_abort(struct usbd_xfer *xfer) | |
647 | { | 642 | { | |
648 | vhci_xfer_t *vxfer = (vhci_xfer_t *)xfer; | 643 | vhci_xfer_t *vxfer = (vhci_xfer_t *)xfer; | |
649 | vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv; | 644 | vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv; | |
650 | vhci_port_t *port = vxfer->port; | 645 | vhci_port_t *port = vxfer->port; | |
651 | vhci_packet_t *pkt; | 646 | vhci_packet_t *pkt; | |
652 | 647 | |||
653 | DPRINTF("%s: called\n", __func__); | 648 | DPRINTF("%s: called\n", __func__); | |
654 | 649 | |||
@@ -699,40 +694,37 @@ static usbd_status | @@ -699,40 +694,37 @@ static usbd_status | |||
699 | vhci_root_intr_transfer(struct usbd_xfer *xfer) | 694 | vhci_root_intr_transfer(struct usbd_xfer *xfer) | |
700 | { | 695 | { | |
701 | 696 | |||
702 | DPRINTF("%s: called\n", __func__); | 697 | DPRINTF("%s: called\n", __func__); | |
703 | 698 | |||
704 | /* Pipe isn't running, start first */ | 699 | /* Pipe isn't running, start first */ | |
705 | return vhci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 700 | return vhci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
706 | } | 701 | } | |
707 | 702 | |||
708 | static usbd_status | 703 | static usbd_status | |
709 | vhci_root_intr_start(struct usbd_xfer *xfer) | 704 | vhci_root_intr_start(struct usbd_xfer *xfer) | |
710 | { | 705 | { | |
711 | vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv; | 706 | vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv; | |
712 | const bool polling = sc->sc_bus.ub_usepolling; | |||
713 | 707 | |||
714 | DPRINTF("%s: called, len=%zu\n", __func__, (size_t)xfer->ux_length); | 708 | DPRINTF("%s: called, len=%zu\n", __func__, (size_t)xfer->ux_length); | |
715 | 709 | |||
710 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
711 | ||||
716 | if (sc->sc_dying) | 712 | if (sc->sc_dying) | |
717 | return USBD_IOERROR; | 713 | return USBD_IOERROR; | |
718 | 714 | |||
719 | if (!polling) | |||
720 | mutex_enter(&sc->sc_lock); | |||
721 | KASSERT(sc->sc_intrxfer == NULL); | 715 | KASSERT(sc->sc_intrxfer == NULL); | |
722 | sc->sc_intrxfer = xfer; | 716 | sc->sc_intrxfer = xfer; | |
723 | xfer->ux_status = USBD_IN_PROGRESS; | 717 | xfer->ux_status = USBD_IN_PROGRESS; | |
724 | if (!polling) | |||
725 | mutex_exit(&sc->sc_lock); | |||
726 | 718 | |||
727 | return USBD_IN_PROGRESS; | 719 | return USBD_IN_PROGRESS; | |
728 | } | 720 | } | |
729 | 721 | |||
730 | static void | 722 | static void | |
731 | vhci_root_intr_abort(struct usbd_xfer *xfer) | 723 | vhci_root_intr_abort(struct usbd_xfer *xfer) | |
732 | { | 724 | { | |
733 | vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv; | 725 | vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv; | |
734 | 726 | |||
735 | DPRINTF("%s: called\n", __func__); | 727 | DPRINTF("%s: called\n", __func__); | |
736 | 728 | |||
737 | KASSERT(mutex_owned(&sc->sc_lock)); | 729 | KASSERT(mutex_owned(&sc->sc_lock)); | |
738 | KASSERT(xfer->ux_pipe->up_intrxfer == xfer); | 730 | KASSERT(xfer->ux_pipe->up_intrxfer == xfer); |
--- src/sys/dev/usb/xhci.c 2022/03/03 06:08:50 1.157
+++ src/sys/dev/usb/xhci.c 2022/03/03 06:12:11 1.158
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: xhci.c,v 1.157 2022/03/03 06:08:50 riastradh Exp $ */ | 1 | /* $NetBSD: xhci.c,v 1.158 2022/03/03 06:12:11 riastradh Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2013 Jonathan A. Kollasch | 4 | * Copyright (c) 2013 Jonathan A. Kollasch | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
@@ -24,27 +24,27 @@ | @@ -24,27 +24,27 @@ | |||
24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
25 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 25 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
26 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | 27 | */ | |
28 | 28 | |||
29 | /* | 29 | /* | |
30 | * USB rev 2.0 and rev 3.1 specification | 30 | * USB rev 2.0 and rev 3.1 specification | |
31 | * http://www.usb.org/developers/docs/ | 31 | * http://www.usb.org/developers/docs/ | |
32 | * xHCI rev 1.1 specification | 32 | * xHCI rev 1.1 specification | |
33 | * http://www.intel.com/technology/usb/spec.htm | 33 | * http://www.intel.com/technology/usb/spec.htm | |
34 | */ | 34 | */ | |
35 | 35 | |||
36 | #include <sys/cdefs.h> | 36 | #include <sys/cdefs.h> | |
37 | __KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.157 2022/03/03 06:08:50 riastradh Exp $"); | 37 | __KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.158 2022/03/03 06:12:11 riastradh Exp $"); | |
38 | 38 | |||
39 | #ifdef _KERNEL_OPT | 39 | #ifdef _KERNEL_OPT | |
40 | #include "opt_usb.h" | 40 | #include "opt_usb.h" | |
41 | #endif | 41 | #endif | |
42 | 42 | |||
43 | #include <sys/param.h> | 43 | #include <sys/param.h> | |
44 | #include <sys/systm.h> | 44 | #include <sys/systm.h> | |
45 | #include <sys/kernel.h> | 45 | #include <sys/kernel.h> | |
46 | #include <sys/kmem.h> | 46 | #include <sys/kmem.h> | |
47 | #include <sys/device.h> | 47 | #include <sys/device.h> | |
48 | #include <sys/select.h> | 48 | #include <sys/select.h> | |
49 | #include <sys/proc.h> | 49 | #include <sys/proc.h> | |
50 | #include <sys/queue.h> | 50 | #include <sys/queue.h> | |
@@ -2176,27 +2176,26 @@ xhci_host_dequeue(struct xhci_ring * con | @@ -2176,27 +2176,26 @@ xhci_host_dequeue(struct xhci_ring * con | |||
2176 | * Issue RESET_EP to recover halt condition and SET_TR_DEQUEUE to remove | 2176 | * Issue RESET_EP to recover halt condition and SET_TR_DEQUEUE to remove | |
2177 | * all transfers on transfer ring. | 2177 | * all transfers on transfer ring. | |
2178 | * These are done in thread context asynchronously. | 2178 | * These are done in thread context asynchronously. | |
2179 | */ | 2179 | */ | |
2180 | static void | 2180 | static void | |
2181 | xhci_pipe_async_task(void *cookie) | 2181 | xhci_pipe_async_task(void *cookie) | |
2182 | { | 2182 | { | |
2183 | struct xhci_pipe * const xp = cookie; | 2183 | struct xhci_pipe * const xp = cookie; | |
2184 | struct usbd_pipe * const pipe = &xp->xp_pipe; | 2184 | struct usbd_pipe * const pipe = &xp->xp_pipe; | |
2185 | struct xhci_softc * const sc = XHCI_PIPE2SC(pipe); | 2185 | struct xhci_softc * const sc = XHCI_PIPE2SC(pipe); | |
2186 | struct xhci_slot * const xs = pipe->up_dev->ud_hcpriv; | 2186 | struct xhci_slot * const xs = pipe->up_dev->ud_hcpriv; | |
2187 | const u_int dci = xhci_ep_get_dci(pipe->up_endpoint->ue_edesc); | 2187 | const u_int dci = xhci_ep_get_dci(pipe->up_endpoint->ue_edesc); | |
2188 | struct xhci_ring * const tr = xs->xs_xr[dci]; | 2188 | struct xhci_ring * const tr = xs->xs_xr[dci]; | |
2189 | bool restart = false; | |||
2190 | 2189 | |||
2191 | XHCIHIST_FUNC(); | 2190 | XHCIHIST_FUNC(); | |
2192 | XHCIHIST_CALLARGS("pipe %#jx slot %ju dci %ju", | 2191 | XHCIHIST_CALLARGS("pipe %#jx slot %ju dci %ju", | |
2193 | (uintptr_t)pipe, xs->xs_idx, dci, 0); | 2192 | (uintptr_t)pipe, xs->xs_idx, dci, 0); | |
2194 | 2193 | |||
2195 | mutex_enter(&sc->sc_lock); | 2194 | mutex_enter(&sc->sc_lock); | |
2196 | 2195 | |||
2197 | /* | 2196 | /* | |
2198 | * - If the endpoint is halted, indicating a stall, reset it. | 2197 | * - If the endpoint is halted, indicating a stall, reset it. | |
2199 | * - If the endpoint is stopped, we're already good. | 2198 | * - If the endpoint is stopped, we're already good. | |
2200 | * - Otherwise, someone wanted to abort the pipe, so stop the | 2199 | * - Otherwise, someone wanted to abort the pipe, so stop the | |
2201 | * endpoint. | 2200 | * endpoint. | |
2202 | * | 2201 | * | |
@@ -2217,51 +2216,38 @@ xhci_pipe_async_task(void *cookie) | @@ -2217,51 +2216,38 @@ xhci_pipe_async_task(void *cookie) | |||
2217 | break; | 2216 | break; | |
2218 | case XHCI_EPSTATE_ERROR: | 2217 | case XHCI_EPSTATE_ERROR: | |
2219 | device_printf(sc->sc_dev, "endpoint 0x%x error\n", | 2218 | device_printf(sc->sc_dev, "endpoint 0x%x error\n", | |
2220 | pipe->up_endpoint->ue_edesc->bEndpointAddress); | 2219 | pipe->up_endpoint->ue_edesc->bEndpointAddress); | |
2221 | break; | 2220 | break; | |
2222 | default: | 2221 | default: | |
2223 | device_printf(sc->sc_dev, "endpoint 0x%x failed to stop\n", | 2222 | device_printf(sc->sc_dev, "endpoint 0x%x failed to stop\n", | |
2224 | pipe->up_endpoint->ue_edesc->bEndpointAddress); | 2223 | pipe->up_endpoint->ue_edesc->bEndpointAddress); | |
2225 | } | 2224 | } | |
2226 | xhci_set_dequeue(pipe); | 2225 | xhci_set_dequeue(pipe); | |
2227 | 2226 | |||
2228 | /* | 2227 | /* | |
2229 | * If we halted our own queue because it stalled, mark it no | 2228 | * If we halted our own queue because it stalled, mark it no | |
2230 | * longer halted and arrange to start it up again. | 2229 | * longer halted and start issuing queued transfers again. | |
2231 | */ | 2230 | */ | |
2232 | if (tr->is_halted) { | 2231 | if (tr->is_halted) { | |
2232 | struct usbd_xfer *xfer = SIMPLEQ_FIRST(&pipe->up_queue); | |||
2233 | ||||
2233 | tr->is_halted = false; | 2234 | tr->is_halted = false; | |
2234 | if (!SIMPLEQ_EMPTY(&pipe->up_queue)) | 2235 | if (xfer) | |
2235 | restart = true; | 2236 | (*pipe->up_methods->upm_start)(xfer); | |
2236 | } | 2237 | } | |
2237 | 2238 | |||
2238 | mutex_exit(&sc->sc_lock); | 2239 | mutex_exit(&sc->sc_lock); | |
2239 | 2240 | |||
2240 | /* | |||
2241 | * If the endpoint was stalled, start issuing queued transfers | |||
2242 | * again. | |||
2243 | */ | |||
2244 | if (restart) { | |||
2245 | /* | |||
2246 | * XXX Shouldn't touch the queue unlocked -- upm_start | |||
2247 | * should be called with the lock held instead. The | |||
2248 | * pipe could be aborted at this point, and the xfer | |||
2249 | * freed. | |||
2250 | */ | |||
2251 | struct usbd_xfer *xfer = SIMPLEQ_FIRST(&pipe->up_queue); | |||
2252 | (*pipe->up_methods->upm_start)(xfer); | |||
2253 | } | |||
2254 | ||||
2255 | DPRINTFN(4, "ends", 0, 0, 0, 0); | 2241 | DPRINTFN(4, "ends", 0, 0, 0, 0); | |
2256 | } | 2242 | } | |
2257 | 2243 | |||
2258 | static void | 2244 | static void | |
2259 | xhci_pipe_restart(struct usbd_pipe *pipe) | 2245 | xhci_pipe_restart(struct usbd_pipe *pipe) | |
2260 | { | 2246 | { | |
2261 | struct xhci_pipe * const xp = | 2247 | struct xhci_pipe * const xp = | |
2262 | container_of(pipe, struct xhci_pipe, xp_pipe); | 2248 | container_of(pipe, struct xhci_pipe, xp_pipe); | |
2263 | 2249 | |||
2264 | XHCIHIST_FUNC(); | 2250 | XHCIHIST_FUNC(); | |
2265 | XHCIHIST_CALLARGS("pipe %#jx", (uintptr_t)pipe, 0, 0, 0); | 2251 | XHCIHIST_CALLARGS("pipe %#jx", (uintptr_t)pipe, 0, 0, 0); | |
2266 | 2252 | |||
2267 | usb_add_task(pipe->up_dev, &xp->xp_async_task, USB_TASKQ_HC); | 2253 | usb_add_task(pipe->up_dev, &xp->xp_async_task, USB_TASKQ_HC); | |
@@ -3860,26 +3846,28 @@ xhci_noop(struct usbd_pipe *pipe) | @@ -3860,26 +3846,28 @@ xhci_noop(struct usbd_pipe *pipe) | |||
3860 | static int | 3846 | static int | |
3861 | xhci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, | 3847 | xhci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, | |
3862 | void *buf, int buflen) | 3848 | void *buf, int buflen) | |
3863 | { | 3849 | { | |
3864 | struct xhci_softc * const sc = XHCI_BUS2SC(bus); | 3850 | struct xhci_softc * const sc = XHCI_BUS2SC(bus); | |
3865 | usb_port_status_t ps; | 3851 | usb_port_status_t ps; | |
3866 | int l, totlen = 0; | 3852 | int l, totlen = 0; | |
3867 | uint16_t len, value, index; | 3853 | uint16_t len, value, index; | |
3868 | int port, i; | 3854 | int port, i; | |
3869 | uint32_t v; | 3855 | uint32_t v; | |
3870 | 3856 | |||
3871 | XHCIHIST_FUNC(); | 3857 | XHCIHIST_FUNC(); | |
3872 | 3858 | |||
3859 | KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock)); | |||
3860 | ||||
3873 | if (sc->sc_dying) | 3861 | if (sc->sc_dying) | |
3874 | return -1; | 3862 | return -1; | |
3875 | 3863 | |||
3876 | size_t bn = bus == &sc->sc_bus ? 0 : 1; | 3864 | size_t bn = bus == &sc->sc_bus ? 0 : 1; | |
3877 | 3865 | |||
3878 | len = UGETW(req->wLength); | 3866 | len = UGETW(req->wLength); | |
3879 | value = UGETW(req->wValue); | 3867 | value = UGETW(req->wValue); | |
3880 | index = UGETW(req->wIndex); | 3868 | index = UGETW(req->wIndex); | |
3881 | 3869 | |||
3882 | XHCIHIST_CALLARGS("rhreq: %04jx %04jx %04jx %04jx", | 3870 | XHCIHIST_CALLARGS("rhreq: %04jx %04jx %04jx %04jx", | |
3883 | req->bmRequestType | (req->bRequest << 8), value, index, len); | 3871 | req->bmRequestType | (req->bRequest << 8), value, index, len); | |
3884 | 3872 | |||
3885 | #define C(x,y) ((x) | ((y) << 8)) | 3873 | #define C(x,y) ((x) | ((y) << 8)) | |
@@ -4129,40 +4117,37 @@ xhci_root_intr_transfer(struct usbd_xfer | @@ -4129,40 +4117,37 @@ xhci_root_intr_transfer(struct usbd_xfer | |||
4129 | { | 4117 | { | |
4130 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | 4118 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | |
4131 | 4119 | |||
4132 | /* Pipe isn't running, start first */ | 4120 | /* Pipe isn't running, start first */ | |
4133 | return xhci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 4121 | return xhci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
4134 | } | 4122 | } | |
4135 | 4123 | |||
4136 | /* Wait for roothub port status/change */ | 4124 | /* Wait for roothub port status/change */ | |
4137 | static usbd_status | 4125 | static usbd_status | |
4138 | xhci_root_intr_start(struct usbd_xfer *xfer) | 4126 | xhci_root_intr_start(struct usbd_xfer *xfer) | |
4139 | { | 4127 | { | |
4140 | struct xhci_softc * const sc = XHCI_XFER2SC(xfer); | 4128 | struct xhci_softc * const sc = XHCI_XFER2SC(xfer); | |
4141 | const size_t bn = XHCI_XFER2BUS(xfer) == &sc->sc_bus ? 0 : 1; | 4129 | const size_t bn = XHCI_XFER2BUS(xfer) == &sc->sc_bus ? 0 : 1; | |
4142 | const bool polling = xhci_polling_p(sc); | |||
4143 | 4130 | |||
4144 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | 4131 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | |
4145 | 4132 | |||
4133 | KASSERT(xhci_polling_p(sc) || mutex_owned(&sc->sc_lock)); | |||
4134 | ||||
4146 | if (sc->sc_dying) | 4135 | if (sc->sc_dying) | |
4147 | return USBD_IOERROR; | 4136 | return USBD_IOERROR; | |
4148 | 4137 | |||
4149 | if (!polling) | |||
4150 | mutex_enter(&sc->sc_lock); | |||
4151 | KASSERT(sc->sc_intrxfer[bn] == NULL); | 4138 | KASSERT(sc->sc_intrxfer[bn] == NULL); | |
4152 | sc->sc_intrxfer[bn] = xfer; | 4139 | sc->sc_intrxfer[bn] = xfer; | |
4153 | xfer->ux_status = USBD_IN_PROGRESS; | 4140 | xfer->ux_status = USBD_IN_PROGRESS; | |
4154 | if (!polling) | |||
4155 | mutex_exit(&sc->sc_lock); | |||
4156 | 4141 | |||
4157 | return USBD_IN_PROGRESS; | 4142 | return USBD_IN_PROGRESS; | |
4158 | } | 4143 | } | |
4159 | 4144 | |||
4160 | static void | 4145 | static void | |
4161 | xhci_root_intr_abort(struct usbd_xfer *xfer) | 4146 | xhci_root_intr_abort(struct usbd_xfer *xfer) | |
4162 | { | 4147 | { | |
4163 | struct xhci_softc * const sc = XHCI_XFER2SC(xfer); | 4148 | struct xhci_softc * const sc = XHCI_XFER2SC(xfer); | |
4164 | const size_t bn = XHCI_XFER2BUS(xfer) == &sc->sc_bus ? 0 : 1; | 4149 | const size_t bn = XHCI_XFER2BUS(xfer) == &sc->sc_bus ? 0 : 1; | |
4165 | 4150 | |||
4166 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | 4151 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | |
4167 | 4152 | |||
4168 | KASSERT(mutex_owned(&sc->sc_lock)); | 4153 | KASSERT(mutex_owned(&sc->sc_lock)); | |
@@ -4240,34 +4225,34 @@ xhci_device_ctrl_start(struct usbd_xfer | @@ -4240,34 +4225,34 @@ xhci_device_ctrl_start(struct usbd_xfer | |||
4240 | const uint32_t len = UGETW(req->wLength); | 4225 | const uint32_t len = UGETW(req->wLength); | |
4241 | usb_dma_t * const dma = &xfer->ux_dmabuf; | 4226 | usb_dma_t * const dma = &xfer->ux_dmabuf; | |
4242 | uint64_t parameter; | 4227 | uint64_t parameter; | |
4243 | uint32_t status; | 4228 | uint32_t status; | |
4244 | uint32_t control; | 4229 | uint32_t control; | |
4245 | u_int i; | 4230 | u_int i; | |
4246 | const bool polling = xhci_polling_p(sc); | 4231 | const bool polling = xhci_polling_p(sc); | |
4247 | 4232 | |||
4248 | XHCIHIST_FUNC(); | 4233 | XHCIHIST_FUNC(); | |
4249 | XHCIHIST_CALLARGS("req: %04jx %04jx %04jx %04jx", | 4234 | XHCIHIST_CALLARGS("req: %04jx %04jx %04jx %04jx", | |
4250 | req->bmRequestType | (req->bRequest << 8), UGETW(req->wValue), | 4235 | req->bmRequestType | (req->bRequest << 8), UGETW(req->wValue), | |
4251 | UGETW(req->wIndex), UGETW(req->wLength)); | 4236 | UGETW(req->wIndex), UGETW(req->wLength)); | |
4252 | 4237 | |||
4238 | KASSERT(polling || mutex_owned(&sc->sc_lock)); | |||
4239 | ||||
4253 | /* we rely on the bottom bits for extra info */ | 4240 | /* we rely on the bottom bits for extra info */ | |
4254 | KASSERTMSG(((uintptr_t)xfer & 0x3) == 0x0, "xfer %zx", | 4241 | KASSERTMSG(((uintptr_t)xfer & 0x3) == 0x0, "xfer %zx", | |
4255 | (uintptr_t) xfer); | 4242 | (uintptr_t) xfer); | |
4256 | 4243 | |||
4257 | KASSERT((xfer->ux_rqflags & URQ_REQUEST) != 0); | 4244 | KASSERT((xfer->ux_rqflags & URQ_REQUEST) != 0); | |
4258 | 4245 | |||
4259 | if (!polling) | |||
4260 | mutex_enter(&sc->sc_lock); | |||
4261 | if (tr->is_halted) | 4246 | if (tr->is_halted) | |
4262 | goto out; | 4247 | goto out; | |
4263 | 4248 | |||
4264 | i = 0; | 4249 | i = 0; | |
4265 | 4250 | |||
4266 | /* setup phase */ | 4251 | /* setup phase */ | |
4267 | parameter = le64dec(req); /* to keep USB endian after xhci_trb_put() */ | 4252 | parameter = le64dec(req); /* to keep USB endian after xhci_trb_put() */ | |
4268 | status = XHCI_TRB_2_IRQ_SET(0) | XHCI_TRB_2_BYTES_SET(sizeof(*req)); | 4253 | status = XHCI_TRB_2_IRQ_SET(0) | XHCI_TRB_2_BYTES_SET(sizeof(*req)); | |
4269 | control = ((len == 0) ? XHCI_TRB_3_TRT_NONE : | 4254 | control = ((len == 0) ? XHCI_TRB_3_TRT_NONE : | |
4270 | (isread ? XHCI_TRB_3_TRT_IN : XHCI_TRB_3_TRT_OUT)) | | 4255 | (isread ? XHCI_TRB_3_TRT_IN : XHCI_TRB_3_TRT_OUT)) | | |
4271 | XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_SETUP_STAGE) | | 4256 | XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_SETUP_STAGE) | | |
4272 | XHCI_TRB_3_IDT_BIT; | 4257 | XHCI_TRB_3_IDT_BIT; | |
4273 | xhci_xfer_put_trb(xx, i++, parameter, status, control); | 4258 | xhci_xfer_put_trb(xx, i++, parameter, status, control); | |
@@ -4305,28 +4290,26 @@ xhci_device_ctrl_start(struct usbd_xfer | @@ -4305,28 +4290,26 @@ xhci_device_ctrl_start(struct usbd_xfer | |||
4305 | 4290 | |||
4306 | xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci); | 4291 | xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci); | |
4307 | 4292 | |||
4308 | out: if (xfer->ux_status == USBD_NOT_STARTED) { | 4293 | out: if (xfer->ux_status == USBD_NOT_STARTED) { | |
4309 | usbd_xfer_schedule_timeout(xfer); | 4294 | usbd_xfer_schedule_timeout(xfer); | |
4310 | xfer->ux_status = USBD_IN_PROGRESS; | 4295 | xfer->ux_status = USBD_IN_PROGRESS; | |
4311 | } else { | 4296 | } else { | |
4312 | /* | 4297 | /* | |
4313 | * We must be coming from xhci_pipe_restart -- timeout | 4298 | * We must be coming from xhci_pipe_restart -- timeout | |
4314 | * already set up, nothing to do. | 4299 | * already set up, nothing to do. | |
4315 | */ | 4300 | */ | |
4316 | } | 4301 | } | |
4317 | KASSERT(xfer->ux_status == USBD_IN_PROGRESS); | 4302 | KASSERT(xfer->ux_status == USBD_IN_PROGRESS); | |
4318 | if (!polling) | |||
4319 | mutex_exit(&sc->sc_lock); | |||
4320 | 4303 | |||
4321 | return USBD_IN_PROGRESS; | 4304 | return USBD_IN_PROGRESS; | |
4322 | } | 4305 | } | |
4323 | 4306 | |||
4324 | static void | 4307 | static void | |
4325 | xhci_device_ctrl_done(struct usbd_xfer *xfer) | 4308 | xhci_device_ctrl_done(struct usbd_xfer *xfer) | |
4326 | { | 4309 | { | |
4327 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | 4310 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | |
4328 | usb_device_request_t *req = &xfer->ux_request; | 4311 | usb_device_request_t *req = &xfer->ux_request; | |
4329 | int len = UGETW(req->wLength); | 4312 | int len = UGETW(req->wLength); | |
4330 | int rd = req->bmRequestType & UT_READ; | 4313 | int rd = req->bmRequestType & UT_READ; | |
4331 | 4314 | |||
4332 | if (len) | 4315 | if (len) | |
@@ -4378,26 +4361,28 @@ xhci_device_isoc_enter(struct usbd_xfer | @@ -4378,26 +4361,28 @@ xhci_device_isoc_enter(struct usbd_xfer | |||
4378 | uint32_t mfindex; | 4361 | uint32_t mfindex; | |
4379 | uint32_t offs; | 4362 | uint32_t offs; | |
4380 | int i, ival; | 4363 | int i, ival; | |
4381 | const bool polling = xhci_polling_p(sc); | 4364 | const bool polling = xhci_polling_p(sc); | |
4382 | const uint16_t MPS = UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize); | 4365 | const uint16_t MPS = UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize); | |
4383 | const uint16_t mps = UE_GET_SIZE(MPS); | 4366 | const uint16_t mps = UE_GET_SIZE(MPS); | |
4384 | const uint8_t maxb = xpipe->xp_maxb; | 4367 | const uint8_t maxb = xpipe->xp_maxb; | |
4385 | u_int tdpc, tbc, tlbpc; | 4368 | u_int tdpc, tbc, tlbpc; | |
4386 | 4369 | |||
4387 | XHCIHIST_FUNC(); | 4370 | XHCIHIST_FUNC(); | |
4388 | XHCIHIST_CALLARGS("%#jx slot %ju dci %ju", | 4371 | XHCIHIST_CALLARGS("%#jx slot %ju dci %ju", | |
4389 | (uintptr_t)xfer, xs->xs_idx, dci, 0); | 4372 | (uintptr_t)xfer, xs->xs_idx, dci, 0); | |
4390 | 4373 | |||
4374 | KASSERT(polling || mutex_owned(&sc->sc_lock)); | |||
4375 | ||||
4391 | if (sc->sc_dying) | 4376 | if (sc->sc_dying) | |
4392 | return USBD_IOERROR; | 4377 | return USBD_IOERROR; | |
4393 | 4378 | |||
4394 | KASSERT(xfer->ux_nframes != 0 && xfer->ux_frlengths); | 4379 | KASSERT(xfer->ux_nframes != 0 && xfer->ux_frlengths); | |
4395 | KASSERT((xfer->ux_rqflags & URQ_REQUEST) == 0); | 4380 | KASSERT((xfer->ux_rqflags & URQ_REQUEST) == 0); | |
4396 | 4381 | |||
4397 | const bool isread = usbd_xfer_isread(xfer); | 4382 | const bool isread = usbd_xfer_isread(xfer); | |
4398 | if (xfer->ux_length) | 4383 | if (xfer->ux_length) | |
4399 | usb_syncmem(dma, 0, xfer->ux_length, | 4384 | usb_syncmem(dma, 0, xfer->ux_length, | |
4400 | isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | 4385 | isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | |
4401 | 4386 | |||
4402 | ival = xfer->ux_pipe->up_endpoint->ue_edesc->bInterval; | 4387 | ival = xfer->ux_pipe->up_endpoint->ue_edesc->bInterval; | |
4403 | if (ival >= 1 && ival <= 16) | 4388 | if (ival >= 1 && ival <= 16) | |
@@ -4450,33 +4435,29 @@ xhci_device_isoc_enter(struct usbd_xfer | @@ -4450,33 +4435,29 @@ xhci_device_isoc_enter(struct usbd_xfer | |||
4450 | 4435 | |||
4451 | xpipe->xp_isoc_next += ival; | 4436 | xpipe->xp_isoc_next += ival; | |
4452 | offs += len; | 4437 | offs += len; | |
4453 | } | 4438 | } | |
4454 | 4439 | |||
4455 | xx->xx_isoc_done = 0; | 4440 | xx->xx_isoc_done = 0; | |
4456 | 4441 | |||
4457 | if (!polling) | 4442 | if (!polling) | |
4458 | mutex_enter(&tr->xr_lock); | 4443 | mutex_enter(&tr->xr_lock); | |
4459 | xhci_ring_put_xfer(sc, tr, xx, i); | 4444 | xhci_ring_put_xfer(sc, tr, xx, i); | |
4460 | if (!polling) | 4445 | if (!polling) | |
4461 | mutex_exit(&tr->xr_lock); | 4446 | mutex_exit(&tr->xr_lock); | |
4462 | 4447 | |||
4463 | if (!polling) | |||
4464 | mutex_enter(&sc->sc_lock); | |||
4465 | xfer->ux_status = USBD_IN_PROGRESS; | 4448 | xfer->ux_status = USBD_IN_PROGRESS; | |
4466 | xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci); | 4449 | xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci); | |
4467 | usbd_xfer_schedule_timeout(xfer); | 4450 | usbd_xfer_schedule_timeout(xfer); | |
4468 | if (!polling) | |||
4469 | mutex_exit(&sc->sc_lock); | |||
4470 | 4451 | |||
4471 | return USBD_IN_PROGRESS; | 4452 | return USBD_IN_PROGRESS; | |
4472 | } | 4453 | } | |
4473 | 4454 | |||
4474 | static void | 4455 | static void | |
4475 | xhci_device_isoc_abort(struct usbd_xfer *xfer) | 4456 | xhci_device_isoc_abort(struct usbd_xfer *xfer) | |
4476 | { | 4457 | { | |
4477 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | 4458 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | |
4478 | 4459 | |||
4479 | usbd_xfer_abort(xfer); | 4460 | usbd_xfer_abort(xfer); | |
4480 | } | 4461 | } | |
4481 | 4462 | |||
4482 | static void | 4463 | static void | |
@@ -4526,33 +4507,33 @@ xhci_device_bulk_start(struct usbd_xfer | @@ -4526,33 +4507,33 @@ xhci_device_bulk_start(struct usbd_xfer | |||
4526 | struct xhci_xfer * const xx = XHCI_XFER2XXFER(xfer); | 4507 | struct xhci_xfer * const xx = XHCI_XFER2XXFER(xfer); | |
4527 | const uint32_t len = xfer->ux_length; | 4508 | const uint32_t len = xfer->ux_length; | |
4528 | usb_dma_t * const dma = &xfer->ux_dmabuf; | 4509 | usb_dma_t * const dma = &xfer->ux_dmabuf; | |
4529 | uint64_t parameter; | 4510 | uint64_t parameter; | |
4530 | uint32_t status; | 4511 | uint32_t status; | |
4531 | uint32_t control; | 4512 | uint32_t control; | |
4532 | u_int i = 0; | 4513 | u_int i = 0; | |
4533 | const bool polling = xhci_polling_p(sc); | 4514 | const bool polling = xhci_polling_p(sc); | |
4534 | 4515 | |||
4535 | XHCIHIST_FUNC(); | 4516 | XHCIHIST_FUNC(); | |
4536 | XHCIHIST_CALLARGS("%#jx slot %ju dci %ju", | 4517 | XHCIHIST_CALLARGS("%#jx slot %ju dci %ju", | |
4537 | (uintptr_t)xfer, xs->xs_idx, dci, 0); | 4518 | (uintptr_t)xfer, xs->xs_idx, dci, 0); | |
4538 | 4519 | |||
4520 | KASSERT(polling || mutex_owned(&sc->sc_lock)); | |||
4521 | ||||
4539 | if (sc->sc_dying) | 4522 | if (sc->sc_dying) | |
4540 | return USBD_IOERROR; | 4523 | return USBD_IOERROR; | |
4541 | 4524 | |||
4542 | KASSERT((xfer->ux_rqflags & URQ_REQUEST) == 0); | 4525 | KASSERT((xfer->ux_rqflags & URQ_REQUEST) == 0); | |
4543 | 4526 | |||
4544 | if (!polling) | |||
4545 | mutex_enter(&sc->sc_lock); | |||
4546 | if (tr->is_halted) | 4527 | if (tr->is_halted) | |
4547 | goto out; | 4528 | goto out; | |
4548 | 4529 | |||
4549 | parameter = DMAADDR(dma, 0); | 4530 | parameter = DMAADDR(dma, 0); | |
4550 | const bool isread = usbd_xfer_isread(xfer); | 4531 | const bool isread = usbd_xfer_isread(xfer); | |
4551 | if (len) | 4532 | if (len) | |
4552 | usb_syncmem(dma, 0, len, | 4533 | usb_syncmem(dma, 0, len, | |
4553 | isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | 4534 | isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | |
4554 | 4535 | |||
4555 | /* | 4536 | /* | |
4556 | * XXX: (dsl) The physical buffer must not cross a 64k boundary. | 4537 | * XXX: (dsl) The physical buffer must not cross a 64k boundary. | |
4557 | * If the user supplied buffer crosses such a boundary then 2 | 4538 | * If the user supplied buffer crosses such a boundary then 2 | |
4558 | * (or more) TRB should be used. | 4539 | * (or more) TRB should be used. | |
@@ -4580,28 +4561,26 @@ xhci_device_bulk_start(struct usbd_xfer | @@ -4580,28 +4561,26 @@ xhci_device_bulk_start(struct usbd_xfer | |||
4580 | 4561 | |||
4581 | xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci); | 4562 | xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci); | |
4582 | 4563 | |||
4583 | out: if (xfer->ux_status == USBD_NOT_STARTED) { | 4564 | out: if (xfer->ux_status == USBD_NOT_STARTED) { | |
4584 | xfer->ux_status = USBD_IN_PROGRESS; | 4565 | xfer->ux_status = USBD_IN_PROGRESS; | |
4585 | usbd_xfer_schedule_timeout(xfer); | 4566 | usbd_xfer_schedule_timeout(xfer); | |
4586 | } else { | 4567 | } else { | |
4587 | /* | 4568 | /* | |
4588 | * We must be coming from xhci_pipe_restart -- timeout | 4569 | * We must be coming from xhci_pipe_restart -- timeout | |
4589 | * already set up, nothing to do. | 4570 | * already set up, nothing to do. | |
4590 | */ | 4571 | */ | |
4591 | } | 4572 | } | |
4592 | KASSERT(xfer->ux_status == USBD_IN_PROGRESS); | 4573 | KASSERT(xfer->ux_status == USBD_IN_PROGRESS); | |
4593 | if (!polling) | |||
4594 | mutex_exit(&sc->sc_lock); | |||
4595 | 4574 | |||
4596 | return USBD_IN_PROGRESS; | 4575 | return USBD_IN_PROGRESS; | |
4597 | } | 4576 | } | |
4598 | 4577 | |||
4599 | static void | 4578 | static void | |
4600 | xhci_device_bulk_done(struct usbd_xfer *xfer) | 4579 | xhci_device_bulk_done(struct usbd_xfer *xfer) | |
4601 | { | 4580 | { | |
4602 | #ifdef USB_DEBUG | 4581 | #ifdef USB_DEBUG | |
4603 | struct xhci_slot * const xs = xfer->ux_pipe->up_dev->ud_hcpriv; | 4582 | struct xhci_slot * const xs = xfer->ux_pipe->up_dev->ud_hcpriv; | |
4604 | const u_int dci = xhci_ep_get_dci(xfer->ux_pipe->up_endpoint->ue_edesc); | 4583 | const u_int dci = xhci_ep_get_dci(xfer->ux_pipe->up_endpoint->ue_edesc); | |
4605 | #endif | 4584 | #endif | |
4606 | const bool isread = usbd_xfer_isread(xfer); | 4585 | const bool isread = usbd_xfer_isread(xfer); | |
4607 | 4586 | |||
@@ -4651,31 +4630,31 @@ xhci_device_intr_start(struct usbd_xfer | @@ -4651,31 +4630,31 @@ xhci_device_intr_start(struct usbd_xfer | |||
4651 | struct xhci_xfer * const xx = XHCI_XFER2XXFER(xfer); | 4630 | struct xhci_xfer * const xx = XHCI_XFER2XXFER(xfer); | |
4652 | const uint32_t len = xfer->ux_length; | 4631 | const uint32_t len = xfer->ux_length; | |
4653 | const bool polling = xhci_polling_p(sc); | 4632 | const bool polling = xhci_polling_p(sc); | |
4654 | usb_dma_t * const dma = &xfer->ux_dmabuf; | 4633 | usb_dma_t * const dma = &xfer->ux_dmabuf; | |
4655 | uint64_t parameter; | 4634 | uint64_t parameter; | |
4656 | uint32_t status; | 4635 | uint32_t status; | |
4657 | uint32_t control; | 4636 | uint32_t control; | |
4658 | u_int i = 0; | 4637 | u_int i = 0; | |
4659 | 4638 | |||
4660 | XHCIHIST_FUNC(); | 4639 | XHCIHIST_FUNC(); | |
4661 | XHCIHIST_CALLARGS("%#jx slot %ju dci %ju", | 4640 | XHCIHIST_CALLARGS("%#jx slot %ju dci %ju", | |
4662 | (uintptr_t)xfer, xs->xs_idx, dci, 0); | 4641 | (uintptr_t)xfer, xs->xs_idx, dci, 0); | |
4663 | 4642 | |||
4643 | KASSERT(polling || mutex_owned(&sc->sc_lock)); | |||
4644 | ||||
4664 | if (sc->sc_dying) | 4645 | if (sc->sc_dying) | |
4665 | return USBD_IOERROR; | 4646 | return USBD_IOERROR; | |
4666 | 4647 | |||
4667 | if (!polling) | |||
4668 | mutex_enter(&sc->sc_lock); | |||
4669 | if (tr->is_halted) | 4648 | if (tr->is_halted) | |
4670 | goto out; | 4649 | goto out; | |
4671 | 4650 | |||
4672 | KASSERT((xfer->ux_rqflags & URQ_REQUEST) == 0); | 4651 | KASSERT((xfer->ux_rqflags & URQ_REQUEST) == 0); | |
4673 | 4652 | |||
4674 | const bool isread = usbd_xfer_isread(xfer); | 4653 | const bool isread = usbd_xfer_isread(xfer); | |
4675 | if (len) | 4654 | if (len) | |
4676 | usb_syncmem(dma, 0, len, | 4655 | usb_syncmem(dma, 0, len, | |
4677 | isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | 4656 | isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | |
4678 | 4657 | |||
4679 | parameter = DMAADDR(dma, 0); | 4658 | parameter = DMAADDR(dma, 0); | |
4680 | KASSERTMSG(len <= 0x10000, "len %d", len); | 4659 | KASSERTMSG(len <= 0x10000, "len %d", len); | |
4681 | status = XHCI_TRB_2_IRQ_SET(0) | | 4660 | status = XHCI_TRB_2_IRQ_SET(0) | | |
@@ -4693,28 +4672,26 @@ xhci_device_intr_start(struct usbd_xfer | @@ -4693,28 +4672,26 @@ xhci_device_intr_start(struct usbd_xfer | |||
4693 | 4672 | |||
4694 | xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci); | 4673 | xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci); | |
4695 | 4674 | |||
4696 | out: if (xfer->ux_status == USBD_NOT_STARTED) { | 4675 | out: if (xfer->ux_status == USBD_NOT_STARTED) { | |
4697 | xfer->ux_status = USBD_IN_PROGRESS; | 4676 | xfer->ux_status = USBD_IN_PROGRESS; | |
4698 | usbd_xfer_schedule_timeout(xfer); | 4677 | usbd_xfer_schedule_timeout(xfer); | |
4699 | } else { | 4678 | } else { | |
4700 | /* | 4679 | /* | |
4701 | * We must be coming from xhci_pipe_restart -- timeout | 4680 | * We must be coming from xhci_pipe_restart -- timeout | |
4702 | * already set up, nothing to do. | 4681 | * already set up, nothing to do. | |
4703 | */ | 4682 | */ | |
4704 | } | 4683 | } | |
4705 | KASSERT(xfer->ux_status == USBD_IN_PROGRESS); | 4684 | KASSERT(xfer->ux_status == USBD_IN_PROGRESS); | |
4706 | if (!polling) | |||
4707 | mutex_exit(&sc->sc_lock); | |||
4708 | 4685 | |||
4709 | return USBD_IN_PROGRESS; | 4686 | return USBD_IN_PROGRESS; | |
4710 | } | 4687 | } | |
4711 | 4688 | |||
4712 | static void | 4689 | static void | |
4713 | xhci_device_intr_done(struct usbd_xfer *xfer) | 4690 | xhci_device_intr_done(struct usbd_xfer *xfer) | |
4714 | { | 4691 | { | |
4715 | struct xhci_softc * const sc __diagused = XHCI_XFER2SC(xfer); | 4692 | struct xhci_softc * const sc __diagused = XHCI_XFER2SC(xfer); | |
4716 | #ifdef USB_DEBUG | 4693 | #ifdef USB_DEBUG | |
4717 | struct xhci_slot * const xs = xfer->ux_pipe->up_dev->ud_hcpriv; | 4694 | struct xhci_slot * const xs = xfer->ux_pipe->up_dev->ud_hcpriv; | |
4718 | const u_int dci = xhci_ep_get_dci(xfer->ux_pipe->up_endpoint->ue_edesc); | 4695 | const u_int dci = xhci_ep_get_dci(xfer->ux_pipe->up_endpoint->ue_edesc); | |
4719 | #endif | 4696 | #endif | |
4720 | const bool isread = usbd_xfer_isread(xfer); | 4697 | const bool isread = usbd_xfer_isread(xfer); |
--- src/sys/external/bsd/dwc2/dwc2.c 2022/03/03 06:08:50 1.79
+++ src/sys/external/bsd/dwc2/dwc2.c 2022/03/03 06:12:11 1.80
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: dwc2.c,v 1.79 2022/03/03 06:08:50 riastradh Exp $ */ | 1 | /* $NetBSD: dwc2.c,v 1.80 2022/03/03 06:12:11 riastradh Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2013 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2013 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Nick Hudson | 8 | * by Nick Hudson | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -20,27 +20,27 @@ | @@ -20,27 +20,27 @@ | |||
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | __KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.79 2022/03/03 06:08:50 riastradh Exp $"); | 33 | __KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.80 2022/03/03 06:12:11 riastradh Exp $"); | |
34 | 34 | |||
35 | #include "opt_usb.h" | 35 | #include "opt_usb.h" | |
36 | 36 | |||
37 | #include <sys/param.h> | 37 | #include <sys/param.h> | |
38 | 38 | |||
39 | #include <sys/cpu.h> | 39 | #include <sys/cpu.h> | |
40 | #include <sys/device.h> | 40 | #include <sys/device.h> | |
41 | #include <sys/kernel.h> | 41 | #include <sys/kernel.h> | |
42 | #include <sys/kmem.h> | 42 | #include <sys/kmem.h> | |
43 | #include <sys/proc.h> | 43 | #include <sys/proc.h> | |
44 | #include <sys/queue.h> | 44 | #include <sys/queue.h> | |
45 | #include <sys/select.h> | 45 | #include <sys/select.h> | |
46 | #include <sys/sysctl.h> | 46 | #include <sys/sysctl.h> | |
@@ -610,40 +610,37 @@ Static usbd_status | @@ -610,40 +610,37 @@ Static usbd_status | |||
610 | dwc2_root_intr_transfer(struct usbd_xfer *xfer) | 610 | dwc2_root_intr_transfer(struct usbd_xfer *xfer) | |
611 | { | 611 | { | |
612 | 612 | |||
613 | DPRINTF("\n"); | 613 | DPRINTF("\n"); | |
614 | 614 | |||
615 | /* Pipe isn't running, start first */ | 615 | /* Pipe isn't running, start first */ | |
616 | return dwc2_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 616 | return dwc2_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
617 | } | 617 | } | |
618 | 618 | |||
619 | Static usbd_status | 619 | Static usbd_status | |
620 | dwc2_root_intr_start(struct usbd_xfer *xfer) | 620 | dwc2_root_intr_start(struct usbd_xfer *xfer) | |
621 | { | 621 | { | |
622 | struct dwc2_softc *sc = DWC2_XFER2SC(xfer); | 622 | struct dwc2_softc *sc = DWC2_XFER2SC(xfer); | |
623 | const bool polling = sc->sc_bus.ub_usepolling; | |||
624 | 623 | |||
625 | DPRINTF("\n"); | 624 | DPRINTF("\n"); | |
626 | 625 | |||
626 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
627 | ||||
627 | if (sc->sc_dying) | 628 | if (sc->sc_dying) | |
628 | return USBD_IOERROR; | 629 | return USBD_IOERROR; | |
629 | 630 | |||
630 | if (!polling) | |||
631 | mutex_enter(&sc->sc_lock); | |||
632 | KASSERT(sc->sc_intrxfer == NULL); | 631 | KASSERT(sc->sc_intrxfer == NULL); | |
633 | sc->sc_intrxfer = xfer; | 632 | sc->sc_intrxfer = xfer; | |
634 | xfer->ux_status = USBD_IN_PROGRESS; | 633 | xfer->ux_status = USBD_IN_PROGRESS; | |
635 | if (!polling) | |||
636 | mutex_exit(&sc->sc_lock); | |||
637 | 634 | |||
638 | return USBD_IN_PROGRESS; | 635 | return USBD_IN_PROGRESS; | |
639 | } | 636 | } | |
640 | 637 | |||
641 | /* Abort a root interrupt request. */ | 638 | /* Abort a root interrupt request. */ | |
642 | Static void | 639 | Static void | |
643 | dwc2_root_intr_abort(struct usbd_xfer *xfer) | 640 | dwc2_root_intr_abort(struct usbd_xfer *xfer) | |
644 | { | 641 | { | |
645 | struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); | 642 | struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); | |
646 | 643 | |||
647 | DPRINTF("xfer=%p\n", xfer); | 644 | DPRINTF("xfer=%p\n", xfer); | |
648 | 645 | |||
649 | KASSERT(mutex_owned(&sc->sc_lock)); | 646 | KASSERT(mutex_owned(&sc->sc_lock)); | |
@@ -699,37 +696,33 @@ dwc2_device_ctrl_transfer(struct usbd_xf | @@ -699,37 +696,33 @@ dwc2_device_ctrl_transfer(struct usbd_xf | |||
699 | { | 696 | { | |
700 | 697 | |||
701 | DPRINTF("\n"); | 698 | DPRINTF("\n"); | |
702 | 699 | |||
703 | /* Pipe isn't running, start first */ | 700 | /* Pipe isn't running, start first */ | |
704 | return dwc2_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 701 | return dwc2_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
705 | } | 702 | } | |
706 | 703 | |||
707 | Static usbd_status | 704 | Static usbd_status | |
708 | dwc2_device_ctrl_start(struct usbd_xfer *xfer) | 705 | dwc2_device_ctrl_start(struct usbd_xfer *xfer) | |
709 | { | 706 | { | |
710 | struct dwc2_softc *sc = DWC2_XFER2SC(xfer); | 707 | struct dwc2_softc *sc = DWC2_XFER2SC(xfer); | |
711 | usbd_status err; | 708 | usbd_status err; | |
712 | const bool polling = sc->sc_bus.ub_usepolling; | |||
713 | 709 | |||
714 | DPRINTF("\n"); | 710 | DPRINTF("\n"); | |
715 | 711 | |||
716 | if (!polling) | 712 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |
717 | mutex_enter(&sc->sc_lock); | 713 | ||
718 | xfer->ux_status = USBD_IN_PROGRESS; | 714 | xfer->ux_status = USBD_IN_PROGRESS; | |
719 | err = dwc2_device_start(xfer); | 715 | err = dwc2_device_start(xfer); | |
720 | if (!polling) | |||
721 | mutex_exit(&sc->sc_lock); | |||
722 | ||||
723 | if (err) | 716 | if (err) | |
724 | return err; | 717 | return err; | |
725 | 718 | |||
726 | return USBD_IN_PROGRESS; | 719 | return USBD_IN_PROGRESS; | |
727 | } | 720 | } | |
728 | 721 | |||
729 | Static void | 722 | Static void | |
730 | dwc2_device_ctrl_abort(struct usbd_xfer *xfer) | 723 | dwc2_device_ctrl_abort(struct usbd_xfer *xfer) | |
731 | { | 724 | { | |
732 | struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); | 725 | struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); | |
733 | 726 | |||
734 | KASSERT(mutex_owned(&sc->sc_lock)); | 727 | KASSERT(mutex_owned(&sc->sc_lock)); | |
735 | 728 | |||
@@ -750,38 +743,32 @@ dwc2_device_ctrl_close(struct usbd_pipe | @@ -750,38 +743,32 @@ dwc2_device_ctrl_close(struct usbd_pipe | |||
750 | 743 | |||
751 | Static void | 744 | Static void | |
752 | dwc2_device_ctrl_done(struct usbd_xfer *xfer) | 745 | dwc2_device_ctrl_done(struct usbd_xfer *xfer) | |
753 | { | 746 | { | |
754 | 747 | |||
755 | DPRINTF("xfer=%p\n", xfer); | 748 | DPRINTF("xfer=%p\n", xfer); | |
756 | } | 749 | } | |
757 | 750 | |||
758 | /***********************************************************************/ | 751 | /***********************************************************************/ | |
759 | 752 | |||
760 | Static usbd_status | 753 | Static usbd_status | |
761 | dwc2_device_bulk_transfer(struct usbd_xfer *xfer) | 754 | dwc2_device_bulk_transfer(struct usbd_xfer *xfer) | |
762 | { | 755 | { | |
763 | struct dwc2_softc *sc = DWC2_XFER2SC(xfer); | |||
764 | usbd_status err; | |||
765 | 756 | |||
766 | DPRINTF("xfer=%p\n", xfer); | 757 | DPRINTF("xfer=%p\n", xfer); | |
767 | 758 | |||
768 | mutex_enter(&sc->sc_lock); | |||
769 | KASSERT(xfer->ux_status == USBD_NOT_STARTED); | 759 | KASSERT(xfer->ux_status == USBD_NOT_STARTED); | |
770 | xfer->ux_status = USBD_IN_PROGRESS; | 760 | xfer->ux_status = USBD_IN_PROGRESS; | |
771 | err = dwc2_device_start(xfer); | 761 | return dwc2_device_start(xfer); | |
772 | mutex_exit(&sc->sc_lock); | |||
773 | ||||
774 | return err; | |||
775 | } | 762 | } | |
776 | 763 | |||
777 | Static void | 764 | Static void | |
778 | dwc2_device_bulk_abort(struct usbd_xfer *xfer) | 765 | dwc2_device_bulk_abort(struct usbd_xfer *xfer) | |
779 | { | 766 | { | |
780 | struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); | 767 | struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); | |
781 | 768 | |||
782 | KASSERT(mutex_owned(&sc->sc_lock)); | 769 | KASSERT(mutex_owned(&sc->sc_lock)); | |
783 | 770 | |||
784 | DPRINTF("xfer=%p\n", xfer); | 771 | DPRINTF("xfer=%p\n", xfer); | |
785 | usbd_xfer_abort(xfer); | 772 | usbd_xfer_abort(xfer); | |
786 | } | 773 | } | |
787 | 774 | |||
@@ -810,35 +797,31 @@ dwc2_device_intr_transfer(struct usbd_xf | @@ -810,35 +797,31 @@ dwc2_device_intr_transfer(struct usbd_xf | |||
810 | DPRINTF("xfer=%p\n", xfer); | 797 | DPRINTF("xfer=%p\n", xfer); | |
811 | 798 | |||
812 | /* Pipe isn't running, start first */ | 799 | /* Pipe isn't running, start first */ | |
813 | return dwc2_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 800 | return dwc2_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
814 | } | 801 | } | |
815 | 802 | |||
816 | Static usbd_status | 803 | Static usbd_status | |
817 | dwc2_device_intr_start(struct usbd_xfer *xfer) | 804 | dwc2_device_intr_start(struct usbd_xfer *xfer) | |
818 | { | 805 | { | |
819 | struct dwc2_pipe *dpipe = DWC2_XFER2DPIPE(xfer) | 806 | struct dwc2_pipe *dpipe = DWC2_XFER2DPIPE(xfer) | |
820 | struct usbd_device *dev = dpipe->pipe.up_dev; | 807 | struct usbd_device *dev = dpipe->pipe.up_dev; | |
821 | struct dwc2_softc *sc = dev->ud_bus->ub_hcpriv; | 808 | struct dwc2_softc *sc = dev->ud_bus->ub_hcpriv; | |
822 | usbd_status err; | 809 | usbd_status err; | |
823 | const bool polling = sc->sc_bus.ub_usepolling; | |||
824 | 810 | |||
825 | if (!polling) | 811 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |
826 | mutex_enter(&sc->sc_lock); | 812 | ||
827 | xfer->ux_status = USBD_IN_PROGRESS; | 813 | xfer->ux_status = USBD_IN_PROGRESS; | |
828 | err = dwc2_device_start(xfer); | 814 | err = dwc2_device_start(xfer); | |
829 | if (!polling) | |||
830 | mutex_exit(&sc->sc_lock); | |||
831 | ||||
832 | if (err) | 815 | if (err) | |
833 | return err; | 816 | return err; | |
834 | 817 | |||
835 | return USBD_IN_PROGRESS; | 818 | return USBD_IN_PROGRESS; | |
836 | } | 819 | } | |
837 | 820 | |||
838 | /* Abort a device interrupt request. */ | 821 | /* Abort a device interrupt request. */ | |
839 | Static void | 822 | Static void | |
840 | dwc2_device_intr_abort(struct usbd_xfer *xfer) | 823 | dwc2_device_intr_abort(struct usbd_xfer *xfer) | |
841 | { | 824 | { | |
842 | struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); | 825 | struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); | |
843 | 826 | |||
844 | KASSERT(mutex_owned(&sc->sc_lock)); | 827 | KASSERT(mutex_owned(&sc->sc_lock)); | |
@@ -858,38 +841,32 @@ dwc2_device_intr_close(struct usbd_pipe | @@ -858,38 +841,32 @@ dwc2_device_intr_close(struct usbd_pipe | |||
858 | 841 | |||
859 | Static void | 842 | Static void | |
860 | dwc2_device_intr_done(struct usbd_xfer *xfer) | 843 | dwc2_device_intr_done(struct usbd_xfer *xfer) | |
861 | { | 844 | { | |
862 | 845 | |||
863 | DPRINTF("\n"); | 846 | DPRINTF("\n"); | |
864 | } | 847 | } | |
865 | 848 | |||
866 | /***********************************************************************/ | 849 | /***********************************************************************/ | |
867 | 850 | |||
868 | usbd_status | 851 | usbd_status | |
869 | dwc2_device_isoc_transfer(struct usbd_xfer *xfer) | 852 | dwc2_device_isoc_transfer(struct usbd_xfer *xfer) | |
870 | { | 853 | { | |
871 | struct dwc2_softc *sc = DWC2_XFER2SC(xfer); | |||
872 | usbd_status err; | |||
873 | 854 | |||
874 | DPRINTF("xfer=%p\n", xfer); | 855 | DPRINTF("xfer=%p\n", xfer); | |
875 | 856 | |||
876 | mutex_enter(&sc->sc_lock); | |||
877 | KASSERT(xfer->ux_status == USBD_NOT_STARTED); | 857 | KASSERT(xfer->ux_status == USBD_NOT_STARTED); | |
878 | xfer->ux_status = USBD_IN_PROGRESS; | 858 | xfer->ux_status = USBD_IN_PROGRESS; | |
879 | err = dwc2_device_start(xfer); | 859 | return dwc2_device_start(xfer); | |
880 | mutex_exit(&sc->sc_lock); | |||
881 | ||||
882 | return err; | |||
883 | } | 860 | } | |
884 | 861 | |||
885 | void | 862 | void | |
886 | dwc2_device_isoc_abort(struct usbd_xfer *xfer) | 863 | dwc2_device_isoc_abort(struct usbd_xfer *xfer) | |
887 | { | 864 | { | |
888 | struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); | 865 | struct dwc2_softc *sc __diagused = DWC2_XFER2SC(xfer); | |
889 | KASSERT(mutex_owned(&sc->sc_lock)); | 866 | KASSERT(mutex_owned(&sc->sc_lock)); | |
890 | 867 | |||
891 | DPRINTF("xfer=%p\n", xfer); | 868 | DPRINTF("xfer=%p\n", xfer); | |
892 | usbd_xfer_abort(xfer); | 869 | usbd_xfer_abort(xfer); | |
893 | } | 870 | } | |
894 | 871 | |||
895 | void | 872 | void | |
@@ -923,26 +900,28 @@ dwc2_device_start(struct usbd_xfer *xfer | @@ -923,26 +900,28 @@ dwc2_device_start(struct usbd_xfer *xfer | |||
923 | uint8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes); | 900 | uint8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes); | |
924 | uint8_t epnum = UE_GET_ADDR(ed->bEndpointAddress); | 901 | uint8_t epnum = UE_GET_ADDR(ed->bEndpointAddress); | |
925 | uint8_t dir = UE_GET_DIR(ed->bEndpointAddress); | 902 | uint8_t dir = UE_GET_DIR(ed->bEndpointAddress); | |
926 | uint16_t mps = UE_GET_SIZE(UGETW(ed->wMaxPacketSize)); | 903 | uint16_t mps = UE_GET_SIZE(UGETW(ed->wMaxPacketSize)); | |
927 | uint32_t len; | 904 | uint32_t len; | |
928 | 905 | |||
929 | uint32_t flags = 0; | 906 | uint32_t flags = 0; | |
930 | uint32_t off = 0; | 907 | uint32_t off = 0; | |
931 | int retval, err; | 908 | int retval, err; | |
932 | int alloc_bandwidth = 0; | 909 | int alloc_bandwidth = 0; | |
933 | 910 | |||
934 | DPRINTFN(1, "xfer=%p pipe=%p\n", xfer, xfer->ux_pipe); | 911 | DPRINTFN(1, "xfer=%p pipe=%p\n", xfer, xfer->ux_pipe); | |
935 | 912 | |||
913 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
914 | ||||
936 | if (xfertype == UE_ISOCHRONOUS || | 915 | if (xfertype == UE_ISOCHRONOUS || | |
937 | xfertype == UE_INTERRUPT) { | 916 | xfertype == UE_INTERRUPT) { | |
938 | mutex_spin_enter(&hsotg->lock); | 917 | mutex_spin_enter(&hsotg->lock); | |
939 | if (!dwc2_hcd_is_bandwidth_allocated(hsotg, xfer)) | 918 | if (!dwc2_hcd_is_bandwidth_allocated(hsotg, xfer)) | |
940 | alloc_bandwidth = 1; | 919 | alloc_bandwidth = 1; | |
941 | mutex_spin_exit(&hsotg->lock); | 920 | mutex_spin_exit(&hsotg->lock); | |
942 | } | 921 | } | |
943 | 922 | |||
944 | /* | 923 | /* | |
945 | * For Control pipe the direction is from the request, all other | 924 | * For Control pipe the direction is from the request, all other | |
946 | * transfers have been set correctly at pipe open time. | 925 | * transfers have been set correctly at pipe open time. | |
947 | */ | 926 | */ | |
948 | if (xfertype == UE_CONTROL) { | 927 | if (xfertype == UE_CONTROL) { | |
@@ -1111,29 +1090,27 @@ dwc2_device_start(struct usbd_xfer *xfer | @@ -1111,29 +1090,27 @@ dwc2_device_start(struct usbd_xfer *xfer | |||
1111 | /* might need to check cpu_intr_p */ | 1090 | /* might need to check cpu_intr_p */ | |
1112 | mutex_spin_enter(&hsotg->lock); | 1091 | mutex_spin_enter(&hsotg->lock); | |
1113 | retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, qh, qtd); | 1092 | retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, qh, qtd); | |
1114 | if (retval) | 1093 | if (retval) | |
1115 | goto fail2; | 1094 | goto fail2; | |
1116 | usbd_xfer_schedule_timeout(xfer); | 1095 | usbd_xfer_schedule_timeout(xfer); | |
1117 | xfer->ux_status = USBD_IN_PROGRESS; | 1096 | xfer->ux_status = USBD_IN_PROGRESS; | |
1118 | 1097 | |||
1119 | if (alloc_bandwidth) { | 1098 | if (alloc_bandwidth) { | |
1120 | dwc2_allocate_bus_bandwidth(hsotg, | 1099 | dwc2_allocate_bus_bandwidth(hsotg, | |
1121 | dwc2_hcd_get_ep_bandwidth(hsotg, dpipe), | 1100 | dwc2_hcd_get_ep_bandwidth(hsotg, dpipe), | |
1122 | xfer); | 1101 | xfer); | |
1123 | } | 1102 | } | |
1124 | ||||
1125 | mutex_spin_exit(&hsotg->lock); | 1103 | mutex_spin_exit(&hsotg->lock); | |
1126 | // mutex_exit(&sc->sc_lock); | |||
1127 | 1104 | |||
1128 | return USBD_IN_PROGRESS; | 1105 | return USBD_IN_PROGRESS; | |
1129 | 1106 | |||
1130 | fail2: | 1107 | fail2: | |
1131 | dwc2_urb->priv = NULL; | 1108 | dwc2_urb->priv = NULL; | |
1132 | mutex_spin_exit(&hsotg->lock); | 1109 | mutex_spin_exit(&hsotg->lock); | |
1133 | pool_cache_put(sc->sc_qtdpool, qtd); | 1110 | pool_cache_put(sc->sc_qtdpool, qtd); | |
1134 | 1111 | |||
1135 | fail1: | 1112 | fail1: | |
1136 | if (qh_allocated) { | 1113 | if (qh_allocated) { | |
1137 | dpipe->priv = NULL; | 1114 | dpipe->priv = NULL; | |
1138 | dwc2_hcd_qh_free(hsotg, qh); | 1115 | dwc2_hcd_qh_free(hsotg, qh); | |
1139 | } | 1116 | } |
--- src/sys/rump/dev/lib/libugenhc/ugenhc.c 2022/03/03 06:04:31 1.30
+++ src/sys/rump/dev/lib/libugenhc/ugenhc.c 2022/03/03 06:12:11 1.31
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ugenhc.c,v 1.30 2022/03/03 06:04:31 riastradh Exp $ */ | 1 | /* $NetBSD: ugenhc.c,v 1.31 2022/03/03 06:12:11 riastradh Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2009, 2010 Antti Kantee. All Rights Reserved. | 4 | * Copyright (c) 2009, 2010 Antti Kantee. All Rights Reserved. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 13 | * documentation and/or other materials provided with the distribution. | |
14 | * | 14 | * | |
@@ -51,27 +51,27 @@ | @@ -51,27 +51,27 @@ | |||
51 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 51 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
52 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 52 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
53 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 53 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
54 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 54 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
55 | * POSSIBILITY OF SUCH DAMAGE. | 55 | * POSSIBILITY OF SUCH DAMAGE. | |
56 | */ | 56 | */ | |
57 | 57 | |||
58 | /* | 58 | /* | |
59 | * This rump driver attaches ugen as a kernel usb host controller. | 59 | * This rump driver attaches ugen as a kernel usb host controller. | |
60 | * It's still somewhat under the hammer .... | 60 | * It's still somewhat under the hammer .... | |
61 | */ | 61 | */ | |
62 | 62 | |||
63 | #include <sys/cdefs.h> | 63 | #include <sys/cdefs.h> | |
64 | __KERNEL_RCSID(0, "$NetBSD: ugenhc.c,v 1.30 2022/03/03 06:04:31 riastradh Exp $"); | 64 | __KERNEL_RCSID(0, "$NetBSD: ugenhc.c,v 1.31 2022/03/03 06:12:11 riastradh Exp $"); | |
65 | 65 | |||
66 | #include <sys/param.h> | 66 | #include <sys/param.h> | |
67 | #include <sys/bus.h> | 67 | #include <sys/bus.h> | |
68 | #include <sys/conf.h> | 68 | #include <sys/conf.h> | |
69 | #include <sys/device.h> | 69 | #include <sys/device.h> | |
70 | #include <sys/fcntl.h> | 70 | #include <sys/fcntl.h> | |
71 | #include <sys/kmem.h> | 71 | #include <sys/kmem.h> | |
72 | #include <sys/kernel.h> | 72 | #include <sys/kernel.h> | |
73 | #include <sys/kthread.h> | 73 | #include <sys/kthread.h> | |
74 | #include <sys/mutex.h> | 74 | #include <sys/mutex.h> | |
75 | 75 | |||
76 | #include <dev/usb/usb.h> | 76 | #include <dev/usb/usb.h> | |
77 | #include <dev/usb/usbdi.h> | 77 | #include <dev/usb/usbdi.h> | |
@@ -217,26 +217,28 @@ ugenhc_roothub_ctrl(struct usbd_bus *bus | @@ -217,26 +217,28 @@ ugenhc_roothub_ctrl(struct usbd_bus *bus | |||
217 | } | 217 | } | |
218 | 218 | |||
219 | static usbd_status | 219 | static usbd_status | |
220 | rumpusb_device_ctrl_start(struct usbd_xfer *xfer) | 220 | rumpusb_device_ctrl_start(struct usbd_xfer *xfer) | |
221 | { | 221 | { | |
222 | usb_device_request_t *req = &xfer->ux_request; | 222 | usb_device_request_t *req = &xfer->ux_request; | |
223 | struct ugenhc_softc *sc = UGENHC_XFER2SC(xfer); | 223 | struct ugenhc_softc *sc = UGENHC_XFER2SC(xfer); | |
224 | uint8_t *buf = NULL; | 224 | uint8_t *buf = NULL; | |
225 | int len, totlen; | 225 | int len, totlen; | |
226 | int value; | 226 | int value; | |
227 | int err = 0; | 227 | int err = 0; | |
228 | int ru_error, mightfail = 0; | 228 | int ru_error, mightfail = 0; | |
229 | 229 | |||
230 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
231 | ||||
230 | len = totlen = UGETW(req->wLength); | 232 | len = totlen = UGETW(req->wLength); | |
231 | if (len) | 233 | if (len) | |
232 | buf = xfer->ux_buf; | 234 | buf = xfer->ux_buf; | |
233 | value = UGETW(req->wValue); | 235 | value = UGETW(req->wValue); | |
234 | 236 | |||
235 | #define C(x,y) ((x) | ((y) << 8)) | 237 | #define C(x,y) ((x) | ((y) << 8)) | |
236 | switch(C(req->bRequest, req->bmRequestType)) { | 238 | switch(C(req->bRequest, req->bmRequestType)) { | |
237 | case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): | 239 | case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): | |
238 | switch (value>>8) { | 240 | switch (value>>8) { | |
239 | case UDESC_DEVICE: | 241 | case UDESC_DEVICE: | |
240 | { | 242 | { | |
241 | usb_device_descriptor_t uddesc; | 243 | usb_device_descriptor_t uddesc; | |
242 | totlen = uimin(len, USB_DEVICE_DESCRIPTOR_SIZE); | 244 | totlen = uimin(len, USB_DEVICE_DESCRIPTOR_SIZE); | |
@@ -381,29 +383,27 @@ rumpusb_device_ctrl_start(struct usbd_xf | @@ -381,29 +383,27 @@ rumpusb_device_ctrl_start(struct usbd_xf | |||
381 | } | 383 | } | |
382 | } | 384 | } | |
383 | break; | 385 | break; | |
384 | 386 | |||
385 | default: | 387 | default: | |
386 | panic("unhandled request"); | 388 | panic("unhandled request"); | |
387 | break; | 389 | break; | |
388 | } | 390 | } | |
389 | xfer->ux_actlen = totlen; | 391 | xfer->ux_actlen = totlen; | |
390 | err = USBD_NORMAL_COMPLETION; | 392 | err = USBD_NORMAL_COMPLETION; | |
391 | 393 | |||
392 | ret: | 394 | ret: | |
393 | xfer->ux_status = err; | 395 | xfer->ux_status = err; | |
394 | mutex_enter(&sc->sc_lock); | |||
395 | usb_transfer_complete(xfer); | 396 | usb_transfer_complete(xfer); | |
396 | mutex_exit(&sc->sc_lock); | |||
397 | 397 | |||
398 | return USBD_IN_PROGRESS; | 398 | return USBD_IN_PROGRESS; | |
399 | } | 399 | } | |
400 | 400 | |||
401 | static usbd_status | 401 | static usbd_status | |
402 | rumpusb_device_ctrl_transfer(struct usbd_xfer *xfer) | 402 | rumpusb_device_ctrl_transfer(struct usbd_xfer *xfer) | |
403 | { | 403 | { | |
404 | 404 | |||
405 | return rumpusb_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 405 | return rumpusb_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
406 | } | 406 | } | |
407 | 407 | |||
408 | static void | 408 | static void | |
409 | rumpusb_device_ctrl_abort(struct usbd_xfer *xfer) | 409 | rumpusb_device_ctrl_abort(struct usbd_xfer *xfer) | |
@@ -506,35 +506,35 @@ rhscintr(void *arg) | @@ -506,35 +506,35 @@ rhscintr(void *arg) | |||
506 | 506 | |||
507 | kpause("ugwait3", false, hz, NULL); | 507 | kpause("ugwait3", false, hz, NULL); | |
508 | } | 508 | } | |
509 | 509 | |||
510 | kthread_exit(0); | 510 | kthread_exit(0); | |
511 | } | 511 | } | |
512 | 512 | |||
513 | static usbd_status | 513 | static usbd_status | |
514 | rumpusb_root_intr_start(struct usbd_xfer *xfer) | 514 | rumpusb_root_intr_start(struct usbd_xfer *xfer) | |
515 | { | 515 | { | |
516 | struct ugenhc_softc *sc = UGENHC_XFER2SC(xfer); | 516 | struct ugenhc_softc *sc = UGENHC_XFER2SC(xfer); | |
517 | int error; | 517 | int error; | |
518 | 518 | |||
519 | mutex_enter(&sc->sc_lock); | 519 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |
520 | ||||
520 | sc->sc_intrxfer = xfer; | 521 | sc->sc_intrxfer = xfer; | |
521 | if (!sc->sc_rhintr) { | 522 | if (!sc->sc_rhintr) { | |
522 | error = kthread_create(PRI_NONE, 0, NULL, | 523 | error = kthread_create(PRI_NONE, 0, NULL, | |
523 | rhscintr, sc, &sc->sc_rhintr, "ugenrhi"); | 524 | rhscintr, sc, &sc->sc_rhintr, "ugenrhi"); | |
524 | if (error) | 525 | if (error) | |
525 | xfer->ux_status = USBD_IOERROR; | 526 | xfer->ux_status = USBD_IOERROR; | |
526 | } | 527 | } | |
527 | mutex_exit(&sc->sc_lock); | |||
528 | 528 | |||
529 | return USBD_IN_PROGRESS; | 529 | return USBD_IN_PROGRESS; | |
530 | } | 530 | } | |
531 | 531 | |||
532 | static usbd_status | 532 | static usbd_status | |
533 | rumpusb_root_intr_transfer(struct usbd_xfer *xfer) | 533 | rumpusb_root_intr_transfer(struct usbd_xfer *xfer) | |
534 | { | 534 | { | |
535 | 535 | |||
536 | return rumpusb_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | 536 | return rumpusb_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue)); | |
537 | } | 537 | } | |
538 | 538 | |||
539 | static void | 539 | static void | |
540 | rumpusb_root_intr_abort(struct usbd_xfer *xfer) | 540 | rumpusb_root_intr_abort(struct usbd_xfer *xfer) | |
@@ -571,26 +571,28 @@ static const struct usbd_pipe_methods ru | @@ -571,26 +571,28 @@ static const struct usbd_pipe_methods ru | |||
571 | 571 | |||
572 | static usbd_status | 572 | static usbd_status | |
573 | rumpusb_device_bulk_start(struct usbd_xfer *xfer) | 573 | rumpusb_device_bulk_start(struct usbd_xfer *xfer) | |
574 | { | 574 | { | |
575 | struct ugenhc_softc *sc = UGENHC_XFER2SC(xfer); | 575 | struct ugenhc_softc *sc = UGENHC_XFER2SC(xfer); | |
576 | usb_endpoint_descriptor_t *ed = xfer->ux_pipe->up_endpoint->ue_edesc; | 576 | usb_endpoint_descriptor_t *ed = xfer->ux_pipe->up_endpoint->ue_edesc; | |
577 | size_t n, done; | 577 | size_t n, done; | |
578 | bool isread; | 578 | bool isread; | |
579 | int len, error, endpt; | 579 | int len, error, endpt; | |
580 | uint8_t *buf; | 580 | uint8_t *buf; | |
581 | int xfererr = USBD_NORMAL_COMPLETION; | 581 | int xfererr = USBD_NORMAL_COMPLETION; | |
582 | int shortval, i; | 582 | int shortval, i; | |
583 | 583 | |||
584 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | |||
585 | ||||
584 | ed = xfer->ux_pipe->up_endpoint->ue_edesc; | 586 | ed = xfer->ux_pipe->up_endpoint->ue_edesc; | |
585 | endpt = ed->bEndpointAddress; | 587 | endpt = ed->bEndpointAddress; | |
586 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | 588 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | |
587 | endpt = UE_GET_ADDR(endpt); | 589 | endpt = UE_GET_ADDR(endpt); | |
588 | KASSERT(endpt < UGEN_NEPTS); | 590 | KASSERT(endpt < UGEN_NEPTS); | |
589 | 591 | |||
590 | buf = xfer->ux_buf; | 592 | buf = xfer->ux_buf; | |
591 | done = 0; | 593 | done = 0; | |
592 | if ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS) { | 594 | if ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS) { | |
593 | for (i = 0, len = 0; i < xfer->ux_nframes; i++) | 595 | for (i = 0, len = 0; i < xfer->ux_nframes; i++) | |
594 | len += xfer->ux_frlengths[i]; | 596 | len += xfer->ux_frlengths[i]; | |
595 | } else { | 597 | } else { | |
596 | KASSERT(xfer->ux_length); | 598 | KASSERT(xfer->ux_length); | |
@@ -657,44 +659,40 @@ rumpusb_device_bulk_start(struct usbd_xf | @@ -657,44 +659,40 @@ rumpusb_device_bulk_start(struct usbd_xf | |||
657 | } | 659 | } | |
658 | 660 | |||
659 | if (RUSB(xfer)->rusb_status == 0) { | 661 | if (RUSB(xfer)->rusb_status == 0) { | |
660 | xfer->ux_actlen = done; | 662 | xfer->ux_actlen = done; | |
661 | } else { | 663 | } else { | |
662 | xfererr = USBD_CANCELLED; | 664 | xfererr = USBD_CANCELLED; | |
663 | RUSB(xfer)->rusb_status = 2; | 665 | RUSB(xfer)->rusb_status = 2; | |
664 | } | 666 | } | |
665 | out: | 667 | out: | |
666 | if ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS) | 668 | if ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS) | |
667 | if (done != len) | 669 | if (done != len) | |
668 | panic("lazy bum"); | 670 | panic("lazy bum"); | |
669 | xfer->ux_status = xfererr; | 671 | xfer->ux_status = xfererr; | |
670 | mutex_enter(&sc->sc_lock); | |||
671 | usb_transfer_complete(xfer); | 672 | usb_transfer_complete(xfer); | |
672 | mutex_exit(&sc->sc_lock); | |||
673 | return USBD_IN_PROGRESS; | 673 | return USBD_IN_PROGRESS; | |
674 | } | 674 | } | |
675 | 675 | |||
676 | static void | 676 | static void | |
677 | doxfer_kth(void *arg) | 677 | doxfer_kth(void *arg) | |
678 | { | 678 | { | |
679 | struct usbd_pipe *pipe = arg; | 679 | struct usbd_pipe *pipe = arg; | |
680 | struct ugenhc_softc *sc = UGENHC_PIPE2SC(pipe); | 680 | struct ugenhc_softc *sc = UGENHC_PIPE2SC(pipe); | |
681 | 681 | |||
682 | mutex_enter(&sc->sc_lock); | 682 | mutex_enter(&sc->sc_lock); | |
683 | do { | 683 | do { | |
684 | struct usbd_xfer *xfer = SIMPLEQ_FIRST(&pipe->up_queue); | 684 | struct usbd_xfer *xfer = SIMPLEQ_FIRST(&pipe->up_queue); | |
685 | mutex_exit(&sc->sc_lock); | |||
686 | rumpusb_device_bulk_start(xfer); | 685 | rumpusb_device_bulk_start(xfer); | |
687 | mutex_enter(&sc->sc_lock); | |||
688 | } while (!SIMPLEQ_EMPTY(&pipe->up_queue)); | 686 | } while (!SIMPLEQ_EMPTY(&pipe->up_queue)); | |
689 | mutex_exit(&sc->sc_lock); | 687 | mutex_exit(&sc->sc_lock); | |
690 | kthread_exit(0); | 688 | kthread_exit(0); | |
691 | } | 689 | } | |
692 | 690 | |||
693 | static usbd_status | 691 | static usbd_status | |
694 | rumpusb_device_bulk_transfer(struct usbd_xfer *xfer) | 692 | rumpusb_device_bulk_transfer(struct usbd_xfer *xfer) | |
695 | { | 693 | { | |
696 | 694 | |||
697 | if (!rump_threads) { | 695 | if (!rump_threads) { | |
698 | /* XXX: lie about supporting async transfers */ | 696 | /* XXX: lie about supporting async transfers */ | |
699 | if ((xfer->ux_flags & USBD_SYNCHRONOUS) == 0) { | 697 | if ((xfer->ux_flags & USBD_SYNCHRONOUS) == 0) { | |
700 | printf("non-threaded rump does not support " | 698 | printf("non-threaded rump does not support " |