| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: xhci.c,v 1.139 2021/05/23 11:49:45 riastradh Exp $ */ | | 1 | /* $NetBSD: xhci.c,v 1.140 2021/05/23 21:12: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.139 2021/05/23 11:49:45 riastradh Exp $"); | | 37 | __KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.140 2021/05/23 21:12: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> |
| @@ -147,26 +147,28 @@ static void xhci_poll(struct usbd_bus *) | | | @@ -147,26 +147,28 @@ static void xhci_poll(struct usbd_bus *) |
147 | static struct usbd_xfer *xhci_allocx(struct usbd_bus *, unsigned int); | | 147 | static struct usbd_xfer *xhci_allocx(struct usbd_bus *, unsigned int); |
148 | static void xhci_freex(struct usbd_bus *, struct usbd_xfer *); | | 148 | static void xhci_freex(struct usbd_bus *, struct usbd_xfer *); |
149 | static void xhci_abortx(struct usbd_xfer *); | | 149 | static void xhci_abortx(struct usbd_xfer *); |
150 | static bool xhci_dying(struct usbd_bus *); | | 150 | static bool xhci_dying(struct usbd_bus *); |
151 | static void xhci_get_lock(struct usbd_bus *, kmutex_t **); | | 151 | static void xhci_get_lock(struct usbd_bus *, kmutex_t **); |
152 | static usbd_status xhci_new_device(device_t, struct usbd_bus *, int, int, int, | | 152 | static usbd_status xhci_new_device(device_t, struct usbd_bus *, int, int, int, |
153 | struct usbd_port *); | | 153 | struct usbd_port *); |
154 | static int xhci_roothub_ctrl(struct usbd_bus *, usb_device_request_t *, | | 154 | static int xhci_roothub_ctrl(struct usbd_bus *, usb_device_request_t *, |
155 | void *, int); | | 155 | void *, int); |
156 | | | 156 | |
157 | static usbd_status xhci_configure_endpoint(struct usbd_pipe *); | | 157 | static usbd_status xhci_configure_endpoint(struct usbd_pipe *); |
158 | //static usbd_status xhci_unconfigure_endpoint(struct usbd_pipe *); | | 158 | //static usbd_status xhci_unconfigure_endpoint(struct usbd_pipe *); |
159 | static usbd_status xhci_reset_endpoint(struct usbd_pipe *); | | 159 | static usbd_status xhci_reset_endpoint(struct usbd_pipe *); |
| | | 160 | static usbd_status xhci_stop_endpoint_cmd(struct xhci_softc *, |
| | | 161 | struct xhci_slot *, u_int, uint32_t); |
160 | static usbd_status xhci_stop_endpoint(struct usbd_pipe *); | | 162 | static usbd_status xhci_stop_endpoint(struct usbd_pipe *); |
161 | | | 163 | |
162 | static void xhci_host_dequeue(struct xhci_ring * const); | | 164 | static void xhci_host_dequeue(struct xhci_ring * const); |
163 | static usbd_status xhci_set_dequeue(struct usbd_pipe *); | | 165 | static usbd_status xhci_set_dequeue(struct usbd_pipe *); |
164 | | | 166 | |
165 | static usbd_status xhci_do_command(struct xhci_softc * const, | | 167 | static usbd_status xhci_do_command(struct xhci_softc * const, |
166 | struct xhci_soft_trb * const, int); | | 168 | struct xhci_soft_trb * const, int); |
167 | static usbd_status xhci_do_command_locked(struct xhci_softc * const, | | 169 | static usbd_status xhci_do_command_locked(struct xhci_softc * const, |
168 | struct xhci_soft_trb * const, int); | | 170 | struct xhci_soft_trb * const, int); |
169 | static usbd_status xhci_init_slot(struct usbd_device *, uint32_t); | | 171 | static usbd_status xhci_init_slot(struct usbd_device *, uint32_t); |
170 | static void xhci_free_slot(struct xhci_softc *, struct xhci_slot *); | | 172 | static void xhci_free_slot(struct xhci_softc *, struct xhci_slot *); |
171 | static usbd_status xhci_set_address(struct usbd_device *, uint32_t, bool); | | 173 | static usbd_status xhci_set_address(struct usbd_device *, uint32_t, bool); |
172 | static usbd_status xhci_enable_slot(struct xhci_softc * const, | | 174 | static usbd_status xhci_enable_slot(struct xhci_softc * const, |
| @@ -689,34 +691,90 @@ xhci_activate(device_t self, enum devact | | | @@ -689,34 +691,90 @@ xhci_activate(device_t self, enum devact |
689 | switch (act) { | | 691 | switch (act) { |
690 | case DVACT_DEACTIVATE: | | 692 | case DVACT_DEACTIVATE: |
691 | sc->sc_dying = true; | | 693 | sc->sc_dying = true; |
692 | return 0; | | 694 | return 0; |
693 | default: | | 695 | default: |
694 | return EOPNOTSUPP; | | 696 | return EOPNOTSUPP; |
695 | } | | 697 | } |
696 | } | | 698 | } |
697 | | | 699 | |
698 | bool | | 700 | bool |
699 | xhci_suspend(device_t self, const pmf_qual_t *qual) | | 701 | xhci_suspend(device_t self, const pmf_qual_t *qual) |
700 | { | | 702 | { |
701 | struct xhci_softc * const sc = device_private(self); | | 703 | struct xhci_softc * const sc = device_private(self); |
702 | size_t i, j, bn; | | 704 | size_t i, j, bn, dci; |
703 | int port; | | 705 | int port; |
704 | uint32_t v; | | 706 | uint32_t v; |
| | | 707 | usbd_status err; |
| | | 708 | bool ok = false; |
705 | | | 709 | |
706 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | | 710 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); |
707 | | | 711 | |
| | | 712 | mutex_enter(&sc->sc_lock); |
| | | 713 | |
| | | 714 | /* |
| | | 715 | * Block issuance of new commands, and wait for all pending |
| | | 716 | * commands to complete. |
| | | 717 | */ |
| | | 718 | KASSERT(sc->sc_suspender == NULL); |
| | | 719 | sc->sc_suspender = curlwp; |
| | | 720 | while (sc->sc_command_addr != 0) |
| | | 721 | cv_wait(&sc->sc_cmdbusy_cv, &sc->sc_lock); |
| | | 722 | |
| | | 723 | /* |
| | | 724 | * xHCI Requirements Specification 1.2, May 2019, Sec. 4.23.2: |
| | | 725 | * xHCI Power Management, p. 342 |
| | | 726 | * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf#page=342 |
| | | 727 | */ |
| | | 728 | |
| | | 729 | /* |
| | | 730 | * `1. Stop all USB activity by issuing Stop Endpoint Commands |
| | | 731 | * for Busy endpoints in the Running state. If the Force |
| | | 732 | * Save Context Capability (FSC = ``0'') is not supported, |
| | | 733 | * then Stop Endpoint Commands shall be issued for all idle |
| | | 734 | * endpoints in the Running state as well. The Stop |
| | | 735 | * Endpoint Command causes the xHC to update the respective |
| | | 736 | * Endpoint or Stream Contexts in system memory, e.g. the |
| | | 737 | * TR Dequeue Pointer, DCS, etc. fields. Refer to |
| | | 738 | * Implementation Note "0".' |
| | | 739 | */ |
| | | 740 | for (i = 0; i < sc->sc_maxslots; i++) { |
| | | 741 | struct xhci_slot *xs = &sc->sc_slots[i]; |
| | | 742 | |
| | | 743 | /* Skip if the slot is not in use. */ |
| | | 744 | if (xs->xs_idx == 0) |
| | | 745 | continue; |
| | | 746 | |
| | | 747 | for (dci = XHCI_DCI_SLOT; dci <= XHCI_MAX_DCI; dci++) { |
| | | 748 | /* Skip if the endpoint is not Running. */ |
| | | 749 | /* XXX What about Busy? */ |
| | | 750 | if (xhci_get_epstate(sc, xs, dci) != |
| | | 751 | XHCI_EPSTATE_RUNNING) |
| | | 752 | continue; |
| | | 753 | |
| | | 754 | /* Stop endpoint. */ |
| | | 755 | err = xhci_stop_endpoint_cmd(sc, xs, dci, |
| | | 756 | XHCI_TRB_3_SUSP_EP_BIT); |
| | | 757 | if (err) { |
| | | 758 | device_printf(self, "failed to stop endpoint" |
| | | 759 | " slot %zu dci %zu err %d\n", |
| | | 760 | i, dci, err); |
| | | 761 | goto out; |
| | | 762 | } |
| | | 763 | } |
| | | 764 | } |
| | | 765 | |
708 | /* | | 766 | /* |
709 | * First, suspend all the ports: | | 767 | * Next, suspend all the ports: |
710 | * | | 768 | * |
711 | * xHCI Requirements Specification 1.2, May 2019, Sec. 4.15: | | 769 | * xHCI Requirements Specification 1.2, May 2019, Sec. 4.15: |
712 | * Suspend-Resume, pp. 276-283 | | 770 | * Suspend-Resume, pp. 276-283 |
713 | * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf#page=276 | | 771 | * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf#page=276 |
714 | */ | | 772 | */ |
715 | for (bn = 0; bn < 2; bn++) { | | 773 | for (bn = 0; bn < 2; bn++) { |
716 | for (i = 1; i <= sc->sc_rhportcount[bn]; i++) { | | 774 | for (i = 1; i <= sc->sc_rhportcount[bn]; i++) { |
717 | /* 4.15.1: Port Suspend. */ | | 775 | /* 4.15.1: Port Suspend. */ |
718 | port = XHCI_PORTSC(xhci_rhport2ctlrport(sc, bn, i)); | | 776 | port = XHCI_PORTSC(xhci_rhport2ctlrport(sc, bn, i)); |
719 | | | 777 | |
720 | /* | | 778 | /* |
721 | * `System software places individual ports | | 779 | * `System software places individual ports |
722 | * into suspend mode by writing a ``3'' into | | 780 | * into suspend mode by writing a ``3'' into |
| @@ -757,53 +815,32 @@ xhci_suspend(device_t self, const pmf_qu | | | @@ -757,53 +815,32 @@ xhci_suspend(device_t self, const pmf_qu |
757 | * reduce polling on host controllers that | | 815 | * reduce polling on host controllers that |
758 | * support the U3C capability. | | 816 | * support the U3C capability. |
759 | */ | | 817 | */ |
760 | for (j = 0; j < XHCI_WAIT_PLS_U3; j++) { | | 818 | for (j = 0; j < XHCI_WAIT_PLS_U3; j++) { |
761 | v = xhci_op_read_4(sc, port); | | 819 | v = xhci_op_read_4(sc, port); |
762 | if (XHCI_PS_PLS_GET(v) == XHCI_PS_PLS_U3) | | 820 | if (XHCI_PS_PLS_GET(v) == XHCI_PS_PLS_U3) |
763 | break; | | 821 | break; |
764 | usb_delay_ms(&sc->sc_bus, 1); | | 822 | usb_delay_ms(&sc->sc_bus, 1); |
765 | } | | 823 | } |
766 | if (j == XHCI_WAIT_PLS_U3) { | | 824 | if (j == XHCI_WAIT_PLS_U3) { |
767 | device_printf(self, | | 825 | device_printf(self, |
768 | "suspend timeout on bus %zu port %zu\n", | | 826 | "suspend timeout on bus %zu port %zu\n", |
769 | bn, i); | | 827 | bn, i); |
770 | return false; | | 828 | goto out; |
771 | } | | 829 | } |
772 | } | | 830 | } |
773 | } | | 831 | } |
774 | | | 832 | |
775 | /* | | 833 | /* |
776 | * xHCI Requirements Specification 1.2, May 2019, Sec. 4.23.2: | | | |
777 | * xHCI Power Management, p. 342 | | | |
778 | * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf#page=342 | | | |
779 | */ | | | |
780 | | | | |
781 | /* | | | |
782 | * `1. Stop all USB activity by issuing Stop Endpoint Commands | | | |
783 | * for Busy endpoints in the Running state. If the Force | | | |
784 | * Save Context Capability (FSC = ``0'') is not supported, | | | |
785 | * then Stop Endpoint Commands shall be issued for all Idle | | | |
786 | * endpoints in the Running state as well. The Stop | | | |
787 | * Endpoint Command causes the xHC to update the respective | | | |
788 | * Endpoint or Stream Contexts in system memory, e.g. the | | | |
789 | * TR Dequeue Pointer, DCS, etc. fields. Refer to | | | |
790 | * Implementation Note "0".' | | | |
791 | * | | | |
792 | * XXX Not entirely sure if this is necessary for us; also it | | | |
793 | * probably has to happen before suspending the ports. | | | |
794 | */ | | | |
795 | | | | |
796 | /* | | | |
797 | * `2. Ensure that the Command Ring is in the Stopped state | | 834 | * `2. Ensure that the Command Ring is in the Stopped state |
798 | * (CRR = ``0'') or Idle (i.e. the Command Transfer Ring is | | 835 | * (CRR = ``0'') or Idle (i.e. the Command Transfer Ring is |
799 | * empty), and all Command Completion Events associated | | 836 | * empty), and all Command Completion Events associated |
800 | * with them have been received.' | | 837 | * with them have been received.' |
801 | * | | 838 | * |
802 | * XXX | | 839 | * XXX |
803 | */ | | 840 | */ |
804 | | | 841 | |
805 | /* `3. Stop the controller by setting Run/Stop (R/S) = ``0''.' */ | | 842 | /* `3. Stop the controller by setting Run/Stop (R/S) = ``0''.' */ |
806 | xhci_op_write_4(sc, XHCI_USBCMD, | | 843 | xhci_op_write_4(sc, XHCI_USBCMD, |
807 | xhci_op_read_4(sc, XHCI_USBCMD) & ~XHCI_CMD_RS); | | 844 | xhci_op_read_4(sc, XHCI_USBCMD) & ~XHCI_CMD_RS); |
808 | | | 845 | |
809 | /* | | 846 | /* |
| @@ -846,42 +883,50 @@ xhci_suspend(device_t self, const pmf_qu | | | @@ -846,42 +883,50 @@ xhci_suspend(device_t self, const pmf_qu |
846 | * Just optimistically go on and check SRE anyway -- | | 883 | * Just optimistically go on and check SRE anyway -- |
847 | * what's the worst that could happen? | | 884 | * what's the worst that could happen? |
848 | */ | | 885 | */ |
849 | } | | 886 | } |
850 | | | 887 | |
851 | /* | | 888 | /* |
852 | * `Note: After a Save or Restore operation completes, the | | 889 | * `Note: After a Save or Restore operation completes, the |
853 | * Save/Restore Error (SRE) flag in the USBSTS register should | | 890 | * Save/Restore Error (SRE) flag in the USBSTS register should |
854 | * be checked to ensure that the operation completed | | 891 | * be checked to ensure that the operation completed |
855 | * successfully.' | | 892 | * successfully.' |
856 | */ | | 893 | */ |
857 | if (xhci_op_read_4(sc, XHCI_USBSTS) & XHCI_STS_SRE) { | | 894 | if (xhci_op_read_4(sc, XHCI_USBSTS) & XHCI_STS_SRE) { |
858 | device_printf(self, "suspend error, USBSTS.SRE\n"); | | 895 | device_printf(self, "suspend error, USBSTS.SRE\n"); |
859 | return false; | | 896 | goto out; |
860 | } | | 897 | } |
861 | | | 898 | |
862 | return true; | | 899 | /* Success! */ |
| | | 900 | ok = true; |
| | | 901 | |
| | | 902 | out: mutex_exit(&sc->sc_lock); |
| | | 903 | return ok; |
863 | } | | 904 | } |
864 | | | 905 | |
865 | bool | | 906 | bool |
866 | xhci_resume(device_t self, const pmf_qual_t *qual) | | 907 | xhci_resume(device_t self, const pmf_qual_t *qual) |
867 | { | | 908 | { |
868 | struct xhci_softc * const sc = device_private(self); | | 909 | struct xhci_softc * const sc = device_private(self); |
869 | size_t i, j, bn, dci; | | 910 | size_t i, j, bn, dci; |
870 | int port; | | 911 | int port; |
871 | uint32_t v; | | 912 | uint32_t v; |
| | | 913 | bool ok = false; |
872 | | | 914 | |
873 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | | 915 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); |
874 | | | 916 | |
| | | 917 | mutex_enter(&sc->sc_lock); |
| | | 918 | KASSERT(sc->sc_suspender); |
| | | 919 | |
875 | /* | | 920 | /* |
876 | * xHCI Requirements Specification 1.2, May 2019, Sec. 4.23.2: | | 921 | * xHCI Requirements Specification 1.2, May 2019, Sec. 4.23.2: |
877 | * xHCI Power Management, p. 343 | | 922 | * xHCI Power Management, p. 343 |
878 | * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf#page=343 | | 923 | * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf#page=343 |
879 | */ | | 924 | */ |
880 | | | 925 | |
881 | /* | | 926 | /* |
882 | * `4. Restore the Operational Runtime, and VTIO registers with | | 927 | * `4. Restore the Operational Runtime, and VTIO registers with |
883 | * their previously saved state in the following order: | | 928 | * their previously saved state in the following order: |
884 | * DNCTRL, DCBAAP, CONFIG, ERSTSZ, ERSTBA, ERDP, IMAN, | | 929 | * DNCTRL, DCBAAP, CONFIG, ERSTSZ, ERSTBA, ERDP, IMAN, |
885 | * IMOD, and VTIO.' | | 930 | * IMOD, and VTIO.' |
886 | * | | 931 | * |
887 | * (We don't use VTIO here (for now?).) | | 932 | * (We don't use VTIO here (for now?).) |
| @@ -906,27 +951,27 @@ xhci_resume(device_t self, const pmf_qua | | | @@ -906,27 +951,27 @@ xhci_resume(device_t self, const pmf_qua |
906 | xhci_op_read_4(sc, XHCI_USBCMD) | XHCI_CMD_CRS); | | 951 | xhci_op_read_4(sc, XHCI_USBCMD) | XHCI_CMD_CRS); |
907 | | | 952 | |
908 | /* | | 953 | /* |
909 | * `...and wait for the Restore State Status (RSS) in the | | 954 | * `...and wait for the Restore State Status (RSS) in the |
910 | * USBSTS register (5.4.2) to transition to ``0''.' | | 955 | * USBSTS register (5.4.2) to transition to ``0''.' |
911 | */ | | 956 | */ |
912 | for (i = 0; i < XHCI_WAIT_RSS; i++) { | | 957 | for (i = 0; i < XHCI_WAIT_RSS; i++) { |
913 | if ((xhci_op_read_4(sc, XHCI_USBSTS) & XHCI_STS_RSS) == 0) | | 958 | if ((xhci_op_read_4(sc, XHCI_USBSTS) & XHCI_STS_RSS) == 0) |
914 | break; | | 959 | break; |
915 | usb_delay_ms(&sc->sc_bus, 1); | | 960 | usb_delay_ms(&sc->sc_bus, 1); |
916 | } | | 961 | } |
917 | if (i >= XHCI_WAIT_RSS) { | | 962 | if (i >= XHCI_WAIT_RSS) { |
918 | device_printf(self, "suspend timeout, USBSTS.RSS\n"); | | 963 | device_printf(self, "suspend timeout, USBSTS.RSS\n"); |
919 | return false; | | 964 | goto out; |
920 | } | | 965 | } |
921 | | | 966 | |
922 | /* | | 967 | /* |
923 | * `6. Reinitialize the Command Ring, i.e. so its Cycle bits | | 968 | * `6. Reinitialize the Command Ring, i.e. so its Cycle bits |
924 | * are consistent with the RCS values to be written to the | | 969 | * are consistent with the RCS values to be written to the |
925 | * CRCR.' | | 970 | * CRCR.' |
926 | * | | 971 | * |
927 | * XXX Hope just zeroing it is good enough! | | 972 | * XXX Hope just zeroing it is good enough! |
928 | */ | | 973 | */ |
929 | xhci_host_dequeue(sc->sc_cr); | | 974 | xhci_host_dequeue(sc->sc_cr); |
930 | | | 975 | |
931 | /* | | 976 | /* |
932 | * `7. Write the CRCR with the address and RCS value of the | | 977 | * `7. Write the CRCR with the address and RCS value of the |
| @@ -998,27 +1043,27 @@ xhci_resume(device_t self, const pmf_qua | | | @@ -998,27 +1043,27 @@ xhci_resume(device_t self, const pmf_qua |
998 | v |= XHCI_PS_LWS | XHCI_PS_PLS_SET(XHCI_PS_PLS_SETU0); | | 1043 | v |= XHCI_PS_LWS | XHCI_PS_PLS_SET(XHCI_PS_PLS_SETU0); |
999 | xhci_op_write_4(sc, port, v); | | 1044 | xhci_op_write_4(sc, port, v); |
1000 | | | 1045 | |
1001 | for (j = 0; j < XHCI_WAIT_PLS_U0; j++) { | | 1046 | for (j = 0; j < XHCI_WAIT_PLS_U0; j++) { |
1002 | v = xhci_op_read_4(sc, port); | | 1047 | v = xhci_op_read_4(sc, port); |
1003 | if (XHCI_PS_PLS_GET(v) == XHCI_PS_PLS_U0) | | 1048 | if (XHCI_PS_PLS_GET(v) == XHCI_PS_PLS_U0) |
1004 | break; | | 1049 | break; |
1005 | usb_delay_ms(&sc->sc_bus, 1); | | 1050 | usb_delay_ms(&sc->sc_bus, 1); |
1006 | } | | 1051 | } |
1007 | if (j == XHCI_WAIT_PLS_U0) { | | 1052 | if (j == XHCI_WAIT_PLS_U0) { |
1008 | device_printf(self, | | 1053 | device_printf(self, |
1009 | "resume timeout on bus %zu port %zu\n", | | 1054 | "resume timeout on bus %zu port %zu\n", |
1010 | bn, i); | | 1055 | bn, i); |
1011 | return false; | | 1056 | goto out; |
1012 | } | | 1057 | } |
1013 | } | | 1058 | } |
1014 | } | | 1059 | } |
1015 | | | 1060 | |
1016 | /* | | 1061 | /* |
1017 | * `10. Restart each of the previously Running endpoints by | | 1062 | * `10. Restart each of the previously Running endpoints by |
1018 | * ringing their doorbells.' | | 1063 | * ringing their doorbells.' |
1019 | */ | | 1064 | */ |
1020 | for (i = 0; i < sc->sc_maxslots; i++) { | | 1065 | for (i = 0; i < sc->sc_maxslots; i++) { |
1021 | struct xhci_slot *xs = &sc->sc_slots[i]; | | 1066 | struct xhci_slot *xs = &sc->sc_slots[i]; |
1022 | | | 1067 | |
1023 | /* Skip if the slot is not in use. */ | | 1068 | /* Skip if the slot is not in use. */ |
1024 | if (xs->xs_idx == 0) | | 1069 | if (xs->xs_idx == 0) |
| @@ -1033,30 +1078,38 @@ xhci_resume(device_t self, const pmf_qua | | | @@ -1033,30 +1078,38 @@ xhci_resume(device_t self, const pmf_qua |
1033 | /* Ring the doorbell. */ | | 1078 | /* Ring the doorbell. */ |
1034 | xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci); | | 1079 | xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci); |
1035 | } | | 1080 | } |
1036 | } | | 1081 | } |
1037 | | | 1082 | |
1038 | /* | | 1083 | /* |
1039 | * `Note: After a Save or Restore operation completes, the | | 1084 | * `Note: After a Save or Restore operation completes, the |
1040 | * Save/Restore Error (SRE) flag in the USBSTS register should | | 1085 | * Save/Restore Error (SRE) flag in the USBSTS register should |
1041 | * be checked to ensure that the operation completed | | 1086 | * be checked to ensure that the operation completed |
1042 | * successfully.' | | 1087 | * successfully.' |
1043 | */ | | 1088 | */ |
1044 | if (xhci_op_read_4(sc, XHCI_USBSTS) & XHCI_STS_SRE) { | | 1089 | if (xhci_op_read_4(sc, XHCI_USBSTS) & XHCI_STS_SRE) { |
1045 | device_printf(self, "resume error, USBSTS.SRE\n"); | | 1090 | device_printf(self, "resume error, USBSTS.SRE\n"); |
1046 | return false; | | 1091 | goto out; |
1047 | } | | 1092 | } |
1048 | | | 1093 | |
1049 | return true; | | 1094 | /* Resume command issuance. */ |
| | | 1095 | sc->sc_suspender = NULL; |
| | | 1096 | cv_broadcast(&sc->sc_cmdbusy_cv); |
| | | 1097 | |
| | | 1098 | /* Success! */ |
| | | 1099 | ok = true; |
| | | 1100 | |
| | | 1101 | out: mutex_exit(&sc->sc_lock); |
| | | 1102 | return ok; |
1050 | } | | 1103 | } |
1051 | | | 1104 | |
1052 | bool | | 1105 | bool |
1053 | xhci_shutdown(device_t self, int flags) | | 1106 | xhci_shutdown(device_t self, int flags) |
1054 | { | | 1107 | { |
1055 | return false; | | 1108 | return false; |
1056 | } | | 1109 | } |
1057 | | | 1110 | |
1058 | static int | | 1111 | static int |
1059 | xhci_hc_reset(struct xhci_softc * const sc) | | 1112 | xhci_hc_reset(struct xhci_softc * const sc) |
1060 | { | | 1113 | { |
1061 | uint32_t usbcmd, usbsts; | | 1114 | uint32_t usbcmd, usbsts; |
1062 | int i; | | 1115 | int i; |
| @@ -1853,50 +1906,64 @@ xhci_reset_endpoint(struct usbd_pipe *pi | | | @@ -1853,50 +1906,64 @@ xhci_reset_endpoint(struct usbd_pipe *pi |
1853 | mutex_enter(&sc->sc_lock); | | 1906 | mutex_enter(&sc->sc_lock); |
1854 | usbd_status ret = xhci_reset_endpoint_locked(pipe); | | 1907 | usbd_status ret = xhci_reset_endpoint_locked(pipe); |
1855 | mutex_exit(&sc->sc_lock); | | 1908 | mutex_exit(&sc->sc_lock); |
1856 | | | 1909 | |
1857 | return ret; | | 1910 | return ret; |
1858 | } | | 1911 | } |
1859 | | | 1912 | |
1860 | /* | | 1913 | /* |
1861 | * 4.6.9, 6.4.3.8 | | 1914 | * 4.6.9, 6.4.3.8 |
1862 | * Stop execution of TDs on xfer ring. | | 1915 | * Stop execution of TDs on xfer ring. |
1863 | * Should be called with sc_lock held. | | 1916 | * Should be called with sc_lock held. |
1864 | */ | | 1917 | */ |
1865 | static usbd_status | | 1918 | static usbd_status |
1866 | xhci_stop_endpoint(struct usbd_pipe *pipe) | | 1919 | xhci_stop_endpoint_cmd(struct xhci_softc *sc, struct xhci_slot *xs, u_int dci, |
| | | 1920 | uint32_t trb3flags) |
1867 | { | | 1921 | { |
1868 | struct xhci_softc * const sc = XHCI_PIPE2SC(pipe); | | | |
1869 | struct xhci_slot * const xs = pipe->up_dev->ud_hcpriv; | | | |
1870 | struct xhci_soft_trb trb; | | 1922 | struct xhci_soft_trb trb; |
1871 | usbd_status err; | | 1923 | usbd_status err; |
1872 | const u_int dci = xhci_ep_get_dci(pipe->up_endpoint->ue_edesc); | | | |
1873 | | | 1924 | |
1874 | XHCIHIST_FUNC(); | | 1925 | XHCIHIST_FUNC(); |
1875 | XHCIHIST_CALLARGS("slot %ju dci %ju", xs->xs_idx, dci, 0, 0); | | 1926 | XHCIHIST_CALLARGS("slot %ju dci %ju", xs->xs_idx, dci, 0, 0); |
1876 | | | 1927 | |
1877 | KASSERT(mutex_owned(&sc->sc_lock)); | | 1928 | KASSERT(mutex_owned(&sc->sc_lock)); |
1878 | | | 1929 | |
1879 | trb.trb_0 = 0; | | 1930 | trb.trb_0 = 0; |
1880 | trb.trb_2 = 0; | | 1931 | trb.trb_2 = 0; |
1881 | trb.trb_3 = XHCI_TRB_3_SLOT_SET(xs->xs_idx) | | | 1932 | trb.trb_3 = XHCI_TRB_3_SLOT_SET(xs->xs_idx) | |
1882 | XHCI_TRB_3_EP_SET(dci) | | | 1933 | XHCI_TRB_3_EP_SET(dci) | |
1883 | XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_STOP_EP); | | 1934 | XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_STOP_EP) | |
| | | 1935 | trb3flags; |
1884 | | | 1936 | |
1885 | err = xhci_do_command_locked(sc, &trb, USBD_DEFAULT_TIMEOUT); | | 1937 | err = xhci_do_command_locked(sc, &trb, USBD_DEFAULT_TIMEOUT); |
1886 | | | 1938 | |
1887 | return err; | | 1939 | return err; |
1888 | } | | 1940 | } |
1889 | | | 1941 | |
| | | 1942 | static usbd_status |
| | | 1943 | xhci_stop_endpoint(struct usbd_pipe *pipe) |
| | | 1944 | { |
| | | 1945 | struct xhci_softc * const sc = XHCI_PIPE2SC(pipe); |
| | | 1946 | struct xhci_slot * const xs = pipe->up_dev->ud_hcpriv; |
| | | 1947 | const u_int dci = xhci_ep_get_dci(pipe->up_endpoint->ue_edesc); |
| | | 1948 | |
| | | 1949 | XHCIHIST_FUNC(); |
| | | 1950 | XHCIHIST_CALLARGS("slot %ju dci %ju", xs->xs_idx, dci, 0, 0); |
| | | 1951 | |
| | | 1952 | KASSERT(mutex_owned(&sc->sc_lock)); |
| | | 1953 | |
| | | 1954 | return xhci_stop_endpoint_cmd(sc, xs, dci, 0); |
| | | 1955 | } |
| | | 1956 | |
1890 | /* | | 1957 | /* |
1891 | * Set TR Dequeue Pointer. | | 1958 | * Set TR Dequeue Pointer. |
1892 | * xHCI 1.1 4.6.10 6.4.3.9 | | 1959 | * xHCI 1.1 4.6.10 6.4.3.9 |
1893 | * Purge all of the TRBs on ring and reinitialize ring. | | 1960 | * Purge all of the TRBs on ring and reinitialize ring. |
1894 | * Set TR dequeue Pointr to 0 and Cycle State to 1. | | 1961 | * Set TR dequeue Pointr to 0 and Cycle State to 1. |
1895 | * EPSTATE of endpoint must be ERROR or STOPPED, otherwise CONTEXT_STATE | | 1962 | * EPSTATE of endpoint must be ERROR or STOPPED, otherwise CONTEXT_STATE |
1896 | * error will be generated. | | 1963 | * error will be generated. |
1897 | */ | | 1964 | */ |
1898 | static usbd_status | | 1965 | static usbd_status |
1899 | xhci_set_dequeue_locked(struct usbd_pipe *pipe) | | 1966 | xhci_set_dequeue_locked(struct usbd_pipe *pipe) |
1900 | { | | 1967 | { |
1901 | struct xhci_softc * const sc = XHCI_PIPE2SC(pipe); | | 1968 | struct xhci_softc * const sc = XHCI_PIPE2SC(pipe); |
1902 | struct xhci_slot * const xs = pipe->up_dev->ud_hcpriv; | | 1969 | struct xhci_slot * const xs = pipe->up_dev->ud_hcpriv; |
| @@ -3117,27 +3184,29 @@ static usbd_status | | | @@ -3117,27 +3184,29 @@ static usbd_status |
3117 | xhci_do_command_locked(struct xhci_softc * const sc, | | 3184 | xhci_do_command_locked(struct xhci_softc * const sc, |
3118 | struct xhci_soft_trb * const trb, int timeout) | | 3185 | struct xhci_soft_trb * const trb, int timeout) |
3119 | { | | 3186 | { |
3120 | struct xhci_ring * const cr = sc->sc_cr; | | 3187 | struct xhci_ring * const cr = sc->sc_cr; |
3121 | usbd_status err; | | 3188 | usbd_status err; |
3122 | | | 3189 | |
3123 | XHCIHIST_FUNC(); | | 3190 | XHCIHIST_FUNC(); |
3124 | XHCIHIST_CALLARGS("input: 0x%016jx 0x%08jx 0x%08jx", | | 3191 | XHCIHIST_CALLARGS("input: 0x%016jx 0x%08jx 0x%08jx", |
3125 | trb->trb_0, trb->trb_2, trb->trb_3, 0); | | 3192 | trb->trb_0, trb->trb_2, trb->trb_3, 0); |
3126 | | | 3193 | |
3127 | KASSERTMSG(!cpu_intr_p() && !cpu_softintr_p(), "called from intr ctx"); | | 3194 | KASSERTMSG(!cpu_intr_p() && !cpu_softintr_p(), "called from intr ctx"); |
3128 | KASSERT(mutex_owned(&sc->sc_lock)); | | 3195 | KASSERT(mutex_owned(&sc->sc_lock)); |
3129 | | | 3196 | |
3130 | while (sc->sc_command_addr != 0) | | 3197 | while (sc->sc_command_addr != 0 && |
| | | 3198 | sc->sc_suspender != NULL && |
| | | 3199 | sc->sc_suspender != curlwp) |
3131 | cv_wait(&sc->sc_cmdbusy_cv, &sc->sc_lock); | | 3200 | cv_wait(&sc->sc_cmdbusy_cv, &sc->sc_lock); |
3132 | | | 3201 | |
3133 | /* | | 3202 | /* |
3134 | * If enqueue pointer points at last of ring, it's Link TRB, | | 3203 | * If enqueue pointer points at last of ring, it's Link TRB, |
3135 | * command TRB will be stored in 0th TRB. | | 3204 | * command TRB will be stored in 0th TRB. |
3136 | */ | | 3205 | */ |
3137 | if (cr->xr_ep == cr->xr_ntrb - 1) | | 3206 | if (cr->xr_ep == cr->xr_ntrb - 1) |
3138 | sc->sc_command_addr = xhci_ring_trbp(cr, 0); | | 3207 | sc->sc_command_addr = xhci_ring_trbp(cr, 0); |
3139 | else | | 3208 | else |
3140 | sc->sc_command_addr = xhci_ring_trbp(cr, cr->xr_ep); | | 3209 | sc->sc_command_addr = xhci_ring_trbp(cr, cr->xr_ep); |
3141 | | | 3210 | |
3142 | sc->sc_resultpending = true; | | 3211 | sc->sc_resultpending = true; |
3143 | | | 3212 | |