diff options
| author | riastradh <riastradh@NetBSD.org> | 2022-03-13 11:29:21 +0000 |
|---|---|---|
| committer | riastradh <riastradh@NetBSD.org> | 2022-03-13 11:29:21 +0000 |
| commit | 08ccf0ed57f5c3d9a7aeb840745f9845b944d2eb (patch) | |
| tree | bb219249c20bab6339fc14f242f8eda596d5ca2a /sys/dev | |
| parent | cb61661b8da1ed32f63c9b6cc627d0d160ba8838 (diff) | |
ehci(4): Serialize access to portsc registers.
Both ehci_roothub_ctrl and ehci_suspend/resume do r/m/w on them, so
use a mutex to serialize access to avoid stomping on each other.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/pci/ehci_pci.c | 5 | ||||
| -rw-r--r-- | sys/dev/usb/ehci.c | 41 | ||||
| -rw-r--r-- | sys/dev/usb/ehcivar.h | 3 |
3 files changed, 35 insertions, 14 deletions
diff --git a/sys/dev/pci/ehci_pci.c b/sys/dev/pci/ehci_pci.c index b69a93b7085..f494b906293 100644 --- a/sys/dev/pci/ehci_pci.c +++ b/sys/dev/pci/ehci_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ehci_pci.c,v 1.73 2021/12/22 21:45:02 skrll Exp $ */ +/* $NetBSD: ehci_pci.c,v 1.74 2022/03/13 11:29:21 riastradh Exp $ */ /* * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.73 2021/12/22 21:45:02 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.74 2022/03/13 11:29:21 riastradh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -325,6 +325,7 @@ ehci_pci_detach(device_t self, int flags) #if 1 /* XXX created in ehci.c */ if (sc->sc_init_state >= EHCI_INIT_INITED) { + mutex_destroy(&sc->sc.sc_rhlock); mutex_destroy(&sc->sc.sc_lock); mutex_destroy(&sc->sc.sc_intr_lock); softint_disestablish(sc->sc.sc_doorbell_si); diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c index eb57efebd2f..39728d75e03 100644 --- a/sys/dev/usb/ehci.c +++ b/sys/dev/usb/ehci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ehci.c,v 1.308 2022/03/13 11:29:10 riastradh Exp $ */ +/* $NetBSD: ehci.c,v 1.309 2022/03/13 11:29:21 riastradh Exp $ */ /* * Copyright (c) 2004-2012,2016,2020 The NetBSD Foundation, Inc. @@ -54,7 +54,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.308 2022/03/13 11:29:10 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.309 2022/03/13 11:29:21 riastradh Exp $"); #include "ohci.h" #include "uhci.h" @@ -412,6 +412,7 @@ ehci_init(ehci_softc_t *sc) theehci = sc; #endif + mutex_init(&sc->sc_rhlock, MUTEX_DEFAULT, IPL_NONE); mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_USB); cv_init(&sc->sc_doorbell, "ehcidb"); @@ -703,6 +704,7 @@ fail2: fail1: softint_disestablish(sc->sc_doorbell_si); softint_disestablish(sc->sc_pcd_si); + mutex_destroy(&sc->sc_rhlock); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); @@ -1411,6 +1413,7 @@ ehci_detach(struct ehci_softc *sc, int flags) /* XXX destroyed in ehci_pci.c as it controls ehci_intr access */ softint_disestablish(sc->sc_doorbell_si); softint_disestablish(sc->sc_pcd_si); + mutex_destroy(&sc->sc_rhlock); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); #endif @@ -1441,9 +1444,6 @@ ehci_activate(device_t self, enum devact act) * * Note that this power handler isn't to be registered directly; the * bus glue needs to call out to it. - * - * XXX This should be serialized with ehci_roothub_ctrl's access to the - * portsc registers. */ bool ehci_suspend(device_t dv, const pmf_qual_t *qual) @@ -1454,6 +1454,8 @@ ehci_suspend(device_t dv, const pmf_qual_t *qual) EHCIHIST_FUNC(); EHCIHIST_CALLED(); + mutex_enter(&sc->sc_rhlock); + for (i = 1; i <= sc->sc_noport; i++) { cmd = EOREAD4(sc, EHCI_PORTSC(i)) & ~EHCI_PS_CLEAR; if ((cmd & EHCI_PS_PO) == 0 && (cmd & EHCI_PS_PE) == EHCI_PS_PE) @@ -1488,6 +1490,8 @@ ehci_suspend(device_t dv, const pmf_qual_t *qual) if (hcr != EHCI_STS_HCH) printf("%s: config timeout\n", device_xname(dv)); + mutex_exit(&sc->sc_rhlock); + return true; } @@ -1500,6 +1504,8 @@ ehci_resume(device_t dv, const pmf_qual_t *qual) EHCIHIST_FUNC(); EHCIHIST_CALLED(); + mutex_enter(&sc->sc_rhlock); + /* restore things in case the bios sucks */ EOWRITE4(sc, EHCI_CTRLDSSEGMENT, 0); EOWRITE4(sc, EHCI_PERIODICLISTBASE, DMAADDR(&sc->sc_fldma, 0)); @@ -1545,6 +1551,8 @@ ehci_resume(device_t dv, const pmf_qual_t *qual) if (hcr == EHCI_STS_HCH) printf("%s: config timeout\n", device_xname(dv)); + mutex_exit(&sc->sc_rhlock); + return true; } @@ -2375,8 +2383,8 @@ ehci_free_sitd_chain(ehci_softc_t *sc, struct ehci_soft_sitd *sitd) /***********/ -Static int -ehci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, +static int +ehci_roothub_ctrl_locked(struct usbd_bus *bus, usb_device_request_t *req, void *buf, int buflen) { ehci_softc_t *sc = EHCI_BUS2SC(bus); @@ -2389,10 +2397,7 @@ ehci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, EHCIHIST_FUNC(); EHCIHIST_CALLED(); - /* - * XXX This should be serialized with ehci_suspend/resume's - * access to the portsc registers. - */ + KASSERT(mutex_owned(&sc->sc_rhlock)); if (sc->sc_dying) return -1; @@ -2667,6 +2672,20 @@ ehci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, return totlen; } +Static int +ehci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req, + void *buf, int buflen) +{ + struct ehci_softc *sc = EHCI_BUS2SC(bus); + int actlen; + + mutex_enter(&sc->sc_rhlock); + actlen = ehci_roothub_ctrl_locked(bus, req, buf, buflen); + mutex_exit(&sc->sc_rhlock); + + return actlen; +} + /* * Handle ehci hand-off in early boot vs RB_ASKNAME/RB_SINGLE. * diff --git a/sys/dev/usb/ehcivar.h b/sys/dev/usb/ehcivar.h index b37640fa3ac..e3050ca1490 100644 --- a/sys/dev/usb/ehcivar.h +++ b/sys/dev/usb/ehcivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: ehcivar.h,v 1.50 2022/03/13 11:29:10 riastradh Exp $ */ +/* $NetBSD: ehcivar.h,v 1.51 2022/03/13 11:29:21 riastradh Exp $ */ /* * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -162,6 +162,7 @@ struct ehci_soft_islot { typedef struct ehci_softc { device_t sc_dev; + kmutex_t sc_rhlock; kmutex_t sc_lock; kmutex_t sc_intr_lock; kcondvar_t sc_doorbell; |
