| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: xhci.c,v 1.28.2.64 2016/04/10 21:30:41 skrll Exp $ */ | | 1 | /* $NetBSD: xhci.c,v 1.28.2.65 2016/04/10 22:16:00 skrll 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. |
| @@ -26,27 +26,27 @@ | | | @@ -26,27 +26,27 @@ |
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 3.1 specification | | 30 | * USB rev 3.1 specification |
31 | * http://www.usb.org/developers/docs/usb_31_040315.zip | | 31 | * http://www.usb.org/developers/docs/usb_31_040315.zip |
32 | * USB rev 2.0 specification | | 32 | * USB rev 2.0 specification |
33 | * http://www.usb.org/developers/docs/usb20_docs/usb_20_031815.zip | | 33 | * http://www.usb.org/developers/docs/usb20_docs/usb_20_031815.zip |
34 | * xHCI rev 1.1 specification | | 34 | * xHCI rev 1.1 specification |
35 | * http://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf | | 35 | * http://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf |
36 | */ | | 36 | */ |
37 | | | 37 | |
38 | #include <sys/cdefs.h> | | 38 | #include <sys/cdefs.h> |
39 | __KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.64 2016/04/10 21:30:41 skrll Exp $"); | | 39 | __KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.65 2016/04/10 22:16:00 skrll Exp $"); |
40 | | | 40 | |
41 | #include "opt_usb.h" | | 41 | #include "opt_usb.h" |
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> |
51 | #include <sys/mutex.h> | | 51 | #include <sys/mutex.h> |
52 | #include <sys/condvar.h> | | 52 | #include <sys/condvar.h> |
| @@ -136,28 +136,26 @@ static usbd_status xhci_new_device(devic | | | @@ -136,28 +136,26 @@ static usbd_status xhci_new_device(devic |
136 | struct usbd_port *); | | 136 | struct usbd_port *); |
137 | static int xhci_roothub_ctrl(struct usbd_bus *, usb_device_request_t *, | | 137 | static int xhci_roothub_ctrl(struct usbd_bus *, usb_device_request_t *, |
138 | void *, int); | | 138 | void *, int); |
139 | | | 139 | |
140 | static usbd_status xhci_configure_endpoint(struct usbd_pipe *); | | 140 | static usbd_status xhci_configure_endpoint(struct usbd_pipe *); |
141 | //static usbd_status xhci_unconfigure_endpoint(struct usbd_pipe *); | | 141 | //static usbd_status xhci_unconfigure_endpoint(struct usbd_pipe *); |
142 | static usbd_status xhci_reset_endpoint(struct usbd_pipe *); | | 142 | static usbd_status xhci_reset_endpoint(struct usbd_pipe *); |
143 | static usbd_status xhci_stop_endpoint(struct usbd_pipe *); | | 143 | static usbd_status xhci_stop_endpoint(struct usbd_pipe *); |
144 | | | 144 | |
145 | static usbd_status xhci_set_dequeue(struct usbd_pipe *); | | 145 | static usbd_status xhci_set_dequeue(struct usbd_pipe *); |
146 | | | 146 | |
147 | static usbd_status xhci_do_command(struct xhci_softc * const, | | 147 | static usbd_status xhci_do_command(struct xhci_softc * const, |
148 | struct xhci_trb * const, int); | | 148 | struct xhci_trb * const, int); |
149 | static usbd_status xhci_do_command1(struct xhci_softc * const, | | | |
150 | struct xhci_trb * const, int, int); | | | |
151 | static usbd_status xhci_do_command_locked(struct xhci_softc * const, | | 149 | static usbd_status xhci_do_command_locked(struct xhci_softc * const, |
152 | struct xhci_trb * const, int); | | 150 | struct xhci_trb * const, int); |
153 | static usbd_status xhci_init_slot(struct usbd_device *, uint32_t, uint32_t, int); | | 151 | static usbd_status xhci_init_slot(struct usbd_device *, uint32_t, uint32_t, int); |
154 | static usbd_status xhci_enable_slot(struct xhci_softc * const, | | 152 | static usbd_status xhci_enable_slot(struct xhci_softc * const, |
155 | uint8_t * const); | | 153 | uint8_t * const); |
156 | static usbd_status xhci_disable_slot(struct xhci_softc * const, uint8_t); | | 154 | static usbd_status xhci_disable_slot(struct xhci_softc * const, uint8_t); |
157 | static usbd_status xhci_address_device(struct xhci_softc * const, | | 155 | static usbd_status xhci_address_device(struct xhci_softc * const, |
158 | uint64_t, uint8_t, bool); | | 156 | uint64_t, uint8_t, bool); |
159 | static void xhci_set_dcba(struct xhci_softc * const, uint64_t, int); | | 157 | static void xhci_set_dcba(struct xhci_softc * const, uint64_t, int); |
160 | static usbd_status xhci_update_ep0_mps(struct xhci_softc * const, | | 158 | static usbd_status xhci_update_ep0_mps(struct xhci_softc * const, |
161 | struct xhci_slot * const, u_int); | | 159 | struct xhci_slot * const, u_int); |
162 | static usbd_status xhci_ring_init(struct xhci_softc * const, | | 160 | static usbd_status xhci_ring_init(struct xhci_softc * const, |
163 | struct xhci_ring * const, size_t, size_t); | | 161 | struct xhci_ring * const, size_t, size_t); |
| @@ -2465,40 +2463,38 @@ xhci_ring_put(struct xhci_softc * const | | | @@ -2465,40 +2463,38 @@ xhci_ring_put(struct xhci_softc * const |
2465 | xr->xr_cs = cs; | | 2463 | xr->xr_cs = cs; |
2466 | | | 2464 | |
2467 | DPRINTFN(12, "%p xr_ep 0x%x xr_cs %u", xr, xr->xr_ep, xr->xr_cs, 0); | | 2465 | DPRINTFN(12, "%p xr_ep 0x%x xr_cs %u", xr, xr->xr_ep, xr->xr_cs, 0); |
2468 | } | | 2466 | } |
2469 | | | 2467 | |
2470 | /* | | 2468 | /* |
2471 | * Put a command on command ring, ring bell, set timer, and cv_timedwait. | | 2469 | * Put a command on command ring, ring bell, set timer, and cv_timedwait. |
2472 | * Command completion is notified by cv_signal from xhci_handle_event | | 2470 | * Command completion is notified by cv_signal from xhci_handle_event |
2473 | * (called from interrupt from xHCI), or timed-out. | | 2471 | * (called from interrupt from xHCI), or timed-out. |
2474 | * Command validation is performed in xhci_handle_event by checking if | | 2472 | * Command validation is performed in xhci_handle_event by checking if |
2475 | * trb_0 in CMD_COMPLETE TRB and sc->sc_command_addr are identical. | | 2473 | * trb_0 in CMD_COMPLETE TRB and sc->sc_command_addr are identical. |
2476 | */ | | 2474 | */ |
2477 | static usbd_status | | 2475 | static usbd_status |
2478 | xhci_do_command1(struct xhci_softc * const sc, struct xhci_trb * const trb, | | 2476 | xhci_do_command_locked(struct xhci_softc * const sc, struct xhci_trb * const trb, |
2479 | int timeout, int locked) | | 2477 | int timeout) |
2480 | { | | 2478 | { |
2481 | struct xhci_ring * const cr = &sc->sc_cr; | | 2479 | struct xhci_ring * const cr = &sc->sc_cr; |
2482 | usbd_status err; | | 2480 | usbd_status err; |
2483 | | | 2481 | |
2484 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | | 2482 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); |
2485 | DPRINTFN(12, "input: 0x%016"PRIx64" 0x%08"PRIx32" 0x%08"PRIx32, | | 2483 | DPRINTFN(12, "input: 0x%016"PRIx64" 0x%08"PRIx32" 0x%08"PRIx32, |
2486 | trb->trb_0, trb->trb_2, trb->trb_3, 0); | | 2484 | trb->trb_0, trb->trb_2, trb->trb_3, 0); |
2487 | | | 2485 | |
2488 | KASSERTMSG(!cpu_intr_p() && !cpu_softintr_p(), "called from intr ctx"); | | 2486 | KASSERTMSG(!cpu_intr_p() && !cpu_softintr_p(), "called from intr ctx"); |
2489 | | | 2487 | KASSERT(mutex_owned(&sc->sc_lock)); |
2490 | if (!locked) | | | |
2491 | mutex_enter(&sc->sc_lock); | | | |
2492 | | | 2488 | |
2493 | /* XXX KASSERT may fire when cv_timedwait unlocks sc_lock */ | | 2489 | /* XXX KASSERT may fire when cv_timedwait unlocks sc_lock */ |
2494 | KASSERT(sc->sc_command_addr == 0); | | 2490 | KASSERT(sc->sc_command_addr == 0); |
2495 | sc->sc_command_addr = xhci_ring_trbp(cr, cr->xr_ep); | | 2491 | sc->sc_command_addr = xhci_ring_trbp(cr, cr->xr_ep); |
2496 | | | 2492 | |
2497 | mutex_enter(&cr->xr_lock); | | 2493 | mutex_enter(&cr->xr_lock); |
2498 | xhci_ring_put(sc, cr, NULL, trb, 1); | | 2494 | xhci_ring_put(sc, cr, NULL, trb, 1); |
2499 | mutex_exit(&cr->xr_lock); | | 2495 | mutex_exit(&cr->xr_lock); |
2500 | | | 2496 | |
2501 | xhci_db_write_4(sc, XHCI_DOORBELL(0), 0); | | 2497 | xhci_db_write_4(sc, XHCI_DOORBELL(0), 0); |
2502 | | | 2498 | |
2503 | if (cv_timedwait(&sc->sc_command_cv, &sc->sc_lock, | | 2499 | if (cv_timedwait(&sc->sc_command_cv, &sc->sc_lock, |
2504 | MAX(1, mstohz(timeout))) == EWOULDBLOCK) { | | 2500 | MAX(1, mstohz(timeout))) == EWOULDBLOCK) { |
| @@ -2518,48 +2514,39 @@ xhci_do_command1(struct xhci_softc * con | | | @@ -2518,48 +2514,39 @@ xhci_do_command1(struct xhci_softc * con |
2518 | err = USBD_NORMAL_COMPLETION; | | 2514 | err = USBD_NORMAL_COMPLETION; |
2519 | break; | | 2515 | break; |
2520 | default: | | 2516 | default: |
2521 | case 192 ... 223: | | 2517 | case 192 ... 223: |
2522 | err = USBD_IOERROR; | | 2518 | err = USBD_IOERROR; |
2523 | break; | | 2519 | break; |
2524 | case 224 ... 255: | | 2520 | case 224 ... 255: |
2525 | err = USBD_NORMAL_COMPLETION; | | 2521 | err = USBD_NORMAL_COMPLETION; |
2526 | break; | | 2522 | break; |
2527 | } | | 2523 | } |
2528 | | | 2524 | |
2529 | timedout: | | 2525 | timedout: |
2530 | sc->sc_command_addr = 0; | | 2526 | sc->sc_command_addr = 0; |
2531 | if (!locked) | | | |
2532 | mutex_exit(&sc->sc_lock); | | | |
2533 | return err; | | 2527 | return err; |
2534 | } | | 2528 | } |
2535 | | | 2529 | |
2536 | static usbd_status | | 2530 | static usbd_status |
2537 | xhci_do_command(struct xhci_softc * const sc, struct xhci_trb * const trb, | | 2531 | xhci_do_command(struct xhci_softc * const sc, struct xhci_trb * const trb, |
2538 | int timeout) | | 2532 | int timeout) |
2539 | { | | 2533 | { |
2540 | return xhci_do_command1(sc, trb, timeout, 0); | | | |
2541 | } | | | |
2542 | | | 2534 | |
2543 | /* | | 2535 | mutex_enter(&sc->sc_lock); |
2544 | * This allows xhci_do_command with already sc_lock held. | | 2536 | int ret = xhci_do_command_locked(sc, trb, timeout); |
2545 | * This is needed as USB stack calls close methods with sc_lock_held. | | 2537 | mutex_exit(&sc->sc_lock); |
2546 | * (see usbdivar.h) | | 2538 | |
2547 | */ | | 2539 | return ret; |
2548 | static usbd_status | | | |
2549 | xhci_do_command_locked(struct xhci_softc * const sc, | | | |
2550 | struct xhci_trb * const trb, int timeout) | | | |
2551 | { | | | |
2552 | return xhci_do_command1(sc, trb, timeout, 1); | | | |
2553 | } | | 2540 | } |
2554 | | | 2541 | |
2555 | static usbd_status | | 2542 | static usbd_status |
2556 | xhci_enable_slot(struct xhci_softc * const sc, uint8_t * const slotp) | | 2543 | xhci_enable_slot(struct xhci_softc * const sc, uint8_t * const slotp) |
2557 | { | | 2544 | { |
2558 | struct xhci_trb trb; | | 2545 | struct xhci_trb trb; |
2559 | usbd_status err; | | 2546 | usbd_status err; |
2560 | | | 2547 | |
2561 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); | | 2548 | XHCIHIST_FUNC(); XHCIHIST_CALLED(); |
2562 | | | 2549 | |
2563 | trb.trb_0 = 0; | | 2550 | trb.trb_0 = 0; |
2564 | trb.trb_2 = 0; | | 2551 | trb.trb_2 = 0; |
2565 | trb.trb_3 = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_ENABLE_SLOT); | | 2552 | trb.trb_3 = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_ENABLE_SLOT); |