Module Name: src Committed By: riastradh Date: Sun Mar 13 11:29:21 UTC 2022
Modified Files: src/sys/dev/pci: ehci_pci.c src/sys/dev/usb: ehci.c ehcivar.h Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.73 -r1.74 src/sys/dev/pci/ehci_pci.c cvs rdiff -u -r1.308 -r1.309 src/sys/dev/usb/ehci.c cvs rdiff -u -r1.50 -r1.51 src/sys/dev/usb/ehcivar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/ehci_pci.c diff -u src/sys/dev/pci/ehci_pci.c:1.73 src/sys/dev/pci/ehci_pci.c:1.74 --- src/sys/dev/pci/ehci_pci.c:1.73 Wed Dec 22 21:45:02 2021 +++ src/sys/dev/pci/ehci_pci.c Sun Mar 13 11:29:21 2022 @@ -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); Index: src/sys/dev/usb/ehci.c diff -u src/sys/dev/usb/ehci.c:1.308 src/sys/dev/usb/ehci.c:1.309 --- src/sys/dev/usb/ehci.c:1.308 Sun Mar 13 11:29:10 2022 +++ src/sys/dev/usb/ehci.c Sun Mar 13 11:29:21 2022 @@ -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 f /* 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 * * 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 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 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_ 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_ 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, s /***********/ -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, 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, 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. * Index: src/sys/dev/usb/ehcivar.h diff -u src/sys/dev/usb/ehcivar.h:1.50 src/sys/dev/usb/ehcivar.h:1.51 --- src/sys/dev/usb/ehcivar.h:1.50 Sun Mar 13 11:29:10 2022 +++ src/sys/dev/usb/ehcivar.h Sun Mar 13 11:29:21 2022 @@ -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;