| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: xhci.c,v 1.176 2023/04/07 09:39:48 riastradh Exp $ */ | | 1 | /* $NetBSD: xhci.c,v 1.177 2023/04/09 20:41:28 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.176 2023/04/07 09:39:48 riastradh Exp $"); | | 37 | __KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.177 2023/04/09 20:41:28 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> |
| @@ -690,26 +690,27 @@ xhci_suspend(device_t self, const pmf_qu | | | @@ -690,26 +690,27 @@ xhci_suspend(device_t self, const pmf_qu |
690 | int port; | | 690 | int port; |
691 | uint32_t v; | | 691 | uint32_t v; |
692 | usbd_status err; | | 692 | usbd_status err; |
693 | bool ok = false; | | 693 | bool ok = false; |
694 | | | 694 | |
695 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | | 695 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); |
696 | | | 696 | |
697 | /* | | 697 | /* |
698 | * Block issuance of new commands, and wait for all pending | | 698 | * Block issuance of new commands, and wait for all pending |
699 | * commands to complete. | | 699 | * commands to complete. |
700 | */ | | 700 | */ |
701 | mutex_enter(&sc->sc_lock); | | 701 | mutex_enter(&sc->sc_lock); |
702 | KASSERT(sc->sc_suspender == NULL); | | 702 | KASSERT(sc->sc_suspender == NULL); |
| | | 703 | KASSERT(!sc->sc_suspendresume_failed); |
703 | sc->sc_suspender = curlwp; | | 704 | sc->sc_suspender = curlwp; |
704 | while (sc->sc_command_addr != 0) | | 705 | while (sc->sc_command_addr != 0) |
705 | cv_wait(&sc->sc_cmdbusy_cv, &sc->sc_lock); | | 706 | cv_wait(&sc->sc_cmdbusy_cv, &sc->sc_lock); |
706 | mutex_exit(&sc->sc_lock); | | 707 | mutex_exit(&sc->sc_lock); |
707 | | | 708 | |
708 | /* | | 709 | /* |
709 | * Block roothub xfers which might touch portsc registers until | | 710 | * Block roothub xfers which might touch portsc registers until |
710 | * we're done suspending. | | 711 | * we're done suspending. |
711 | */ | | 712 | */ |
712 | mutex_enter(&sc->sc_rhlock); | | 713 | mutex_enter(&sc->sc_rhlock); |
713 | | | 714 | |
714 | /* | | 715 | /* |
715 | * xHCI Requirements Specification 1.2, May 2019, Sec. 4.23.2: | | 716 | * xHCI Requirements Specification 1.2, May 2019, Sec. 4.23.2: |
| @@ -885,49 +886,62 @@ xhci_suspend(device_t self, const pmf_qu | | | @@ -885,49 +886,62 @@ xhci_suspend(device_t self, const pmf_qu |
885 | * successfully.' | | 886 | * successfully.' |
886 | */ | | 887 | */ |
887 | if (xhci_op_read_4(sc, XHCI_USBSTS) & XHCI_STS_SRE) { | | 888 | if (xhci_op_read_4(sc, XHCI_USBSTS) & XHCI_STS_SRE) { |
888 | device_printf(self, "suspend error, USBSTS.SRE\n"); | | 889 | device_printf(self, "suspend error, USBSTS.SRE\n"); |
889 | goto out; | | 890 | goto out; |
890 | } | | 891 | } |
891 | | | 892 | |
892 | /* Success! */ | | 893 | /* Success! */ |
893 | ok = true; | | 894 | ok = true; |
894 | | | 895 | |
895 | out: mutex_exit(&sc->sc_rhlock); | | 896 | out: mutex_exit(&sc->sc_rhlock); |
896 | if (!ok) { | | 897 | if (!ok) { |
897 | /* | | 898 | /* |
898 | * If suspend failed, resume command issuance. | | 899 | * If suspend failed, stop holding up command issuance |
| | | 900 | * and make it fail instead. |
899 | */ | | 901 | */ |
900 | mutex_enter(&sc->sc_lock); | | 902 | mutex_enter(&sc->sc_lock); |
901 | KASSERT(sc->sc_suspender == curlwp); | | 903 | KASSERT(sc->sc_suspender == curlwp); |
902 | sc->sc_suspender = NULL; | | 904 | sc->sc_suspender = NULL; |
| | | 905 | sc->sc_suspendresume_failed = true; |
903 | cv_broadcast(&sc->sc_cmdbusy_cv); | | 906 | cv_broadcast(&sc->sc_cmdbusy_cv); |
904 | mutex_exit(&sc->sc_lock); | | 907 | mutex_exit(&sc->sc_lock); |
905 | } | | 908 | } |
906 | return ok; | | 909 | return ok; |
907 | } | | 910 | } |
908 | | | 911 | |
909 | bool | | 912 | bool |
910 | xhci_resume(device_t self, const pmf_qual_t *qual) | | 913 | xhci_resume(device_t self, const pmf_qual_t *qual) |
911 | { | | 914 | { |
912 | struct xhci_softc * const sc = device_private(self); | | 915 | struct xhci_softc * const sc = device_private(self); |
913 | size_t i, j, bn, dci; | | 916 | size_t i, j, bn, dci; |
914 | int port; | | 917 | int port; |
915 | uint32_t v; | | 918 | uint32_t v; |
916 | bool ok = false; | | 919 | bool ok = false; |
917 | | | 920 | |
918 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | | 921 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); |
919 | | | 922 | |
| | | 923 | /* |
| | | 924 | * If resume had previously failed, just try again. Can't make |
| | | 925 | * things worse, probably. |
| | | 926 | */ |
| | | 927 | mutex_enter(&sc->sc_lock); |
| | | 928 | if (sc->sc_suspendresume_failed) { |
| | | 929 | KASSERT(sc->sc_suspender == NULL); |
| | | 930 | sc->sc_suspender = curlwp; |
| | | 931 | sc->sc_suspendresume_failed = false; |
| | | 932 | } |
920 | KASSERT(sc->sc_suspender); | | 933 | KASSERT(sc->sc_suspender); |
| | | 934 | mutex_exit(&sc->sc_lock); |
921 | | | 935 | |
922 | /* | | 936 | /* |
923 | * Block roothub xfers which might touch portsc registers until | | 937 | * Block roothub xfers which might touch portsc registers until |
924 | * we're done resuming. | | 938 | * we're done resuming. |
925 | */ | | 939 | */ |
926 | mutex_enter(&sc->sc_rhlock); | | 940 | mutex_enter(&sc->sc_rhlock); |
927 | | | 941 | |
928 | /* | | 942 | /* |
929 | * xHCI Requirements Specification 1.2, May 2019, Sec. 4.23.2: | | 943 | * xHCI Requirements Specification 1.2, May 2019, Sec. 4.23.2: |
930 | * xHCI Power Management, p. 343 | | 944 | * xHCI Power Management, p. 343 |
931 | * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf#page=343 | | 945 | * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf#page=343 |
932 | */ | | 946 | */ |
933 | | | 947 | |
| @@ -1101,26 +1115,27 @@ xhci_resume(device_t self, const pmf_qua | | | @@ -1101,26 +1115,27 @@ xhci_resume(device_t self, const pmf_qua |
1101 | | | 1115 | |
1102 | /* Success! */ | | 1116 | /* Success! */ |
1103 | ok = true; | | 1117 | ok = true; |
1104 | | | 1118 | |
1105 | out: /* | | 1119 | out: /* |
1106 | * Resume command issuance. If the hardware failed to resume, | | 1120 | * Resume command issuance. If the hardware failed to resume, |
1107 | * well, tough -- deadlocking because everything is held up on | | 1121 | * well, tough -- deadlocking because everything is held up on |
1108 | * the suspension, with no opportunity to detach, isn't better | | 1122 | * the suspension, with no opportunity to detach, isn't better |
1109 | * than timing out waiting for dead hardware. | | 1123 | * than timing out waiting for dead hardware. |
1110 | */ | | 1124 | */ |
1111 | mutex_enter(&sc->sc_lock); | | 1125 | mutex_enter(&sc->sc_lock); |
1112 | KASSERT(sc->sc_suspender); | | 1126 | KASSERT(sc->sc_suspender); |
1113 | sc->sc_suspender = NULL; | | 1127 | sc->sc_suspender = NULL; |
| | | 1128 | sc->sc_suspendresume_failed = !ok; |
1114 | cv_broadcast(&sc->sc_cmdbusy_cv); | | 1129 | cv_broadcast(&sc->sc_cmdbusy_cv); |
1115 | mutex_exit(&sc->sc_lock); | | 1130 | mutex_exit(&sc->sc_lock); |
1116 | | | 1131 | |
1117 | mutex_exit(&sc->sc_rhlock); | | 1132 | mutex_exit(&sc->sc_rhlock); |
1118 | return ok; | | 1133 | return ok; |
1119 | } | | 1134 | } |
1120 | | | 1135 | |
1121 | bool | | 1136 | bool |
1122 | xhci_shutdown(device_t self, int flags) | | 1137 | xhci_shutdown(device_t self, int flags) |
1123 | { | | 1138 | { |
1124 | return false; | | 1139 | return false; |
1125 | } | | 1140 | } |
1126 | | | 1141 | |
| @@ -3207,26 +3222,28 @@ xhci_do_command_locked(struct xhci_softc | | | @@ -3207,26 +3222,28 @@ xhci_do_command_locked(struct xhci_softc |
3207 | struct xhci_ring * const cr = sc->sc_cr; | | 3222 | struct xhci_ring * const cr = sc->sc_cr; |
3208 | usbd_status err; | | 3223 | usbd_status err; |
3209 | | | 3224 | |
3210 | XHCIHIST_FUNC(); | | 3225 | XHCIHIST_FUNC(); |
3211 | XHCIHIST_CALLARGS("input: 0x%016jx 0x%08jx 0x%08jx", | | 3226 | XHCIHIST_CALLARGS("input: 0x%016jx 0x%08jx 0x%08jx", |
3212 | trb->trb_0, trb->trb_2, trb->trb_3, 0); | | 3227 | trb->trb_0, trb->trb_2, trb->trb_3, 0); |
3213 | | | 3228 | |
3214 | KASSERTMSG(!cpu_intr_p() && !cpu_softintr_p(), "called from intr ctx"); | | 3229 | KASSERTMSG(!cpu_intr_p() && !cpu_softintr_p(), "called from intr ctx"); |
3215 | KASSERT(mutex_owned(&sc->sc_lock)); | | 3230 | KASSERT(mutex_owned(&sc->sc_lock)); |
3216 | | | 3231 | |
3217 | while (sc->sc_command_addr != 0 || | | 3232 | while (sc->sc_command_addr != 0 || |
3218 | (sc->sc_suspender != NULL && sc->sc_suspender != curlwp)) | | 3233 | (sc->sc_suspender != NULL && sc->sc_suspender != curlwp)) |
3219 | cv_wait(&sc->sc_cmdbusy_cv, &sc->sc_lock); | | 3234 | cv_wait(&sc->sc_cmdbusy_cv, &sc->sc_lock); |
| | | 3235 | if (sc->sc_suspendresume_failed) |
| | | 3236 | return USBD_IOERROR; |
3220 | | | 3237 | |
3221 | /* | | 3238 | /* |
3222 | * If enqueue pointer points at last of ring, it's Link TRB, | | 3239 | * If enqueue pointer points at last of ring, it's Link TRB, |
3223 | * command TRB will be stored in 0th TRB. | | 3240 | * command TRB will be stored in 0th TRB. |
3224 | */ | | 3241 | */ |
3225 | if (cr->xr_ep == cr->xr_ntrb - 1) | | 3242 | if (cr->xr_ep == cr->xr_ntrb - 1) |
3226 | sc->sc_command_addr = xhci_ring_trbp(cr, 0); | | 3243 | sc->sc_command_addr = xhci_ring_trbp(cr, 0); |
3227 | else | | 3244 | else |
3228 | sc->sc_command_addr = xhci_ring_trbp(cr, cr->xr_ep); | | 3245 | sc->sc_command_addr = xhci_ring_trbp(cr, cr->xr_ep); |
3229 | | | 3246 | |
3230 | sc->sc_resultpending = true; | | 3247 | sc->sc_resultpending = true; |
3231 | | | 3248 | |
3232 | mutex_enter(&cr->xr_lock); | | 3249 | mutex_enter(&cr->xr_lock); |