| @@ -1,41 +1,41 @@ | | | @@ -1,41 +1,41 @@ |
1 | /* $NetBSD: if_urtwn.c,v 1.34.4.15 2016/12/05 10:55:18 skrll Exp $ */ | | 1 | /* $NetBSD: if_urtwn.c,v 1.34.4.16 2017/01/28 12:04:17 skrll Exp $ */ |
2 | /* $OpenBSD: if_urtwn.c,v 1.42 2015/02/10 23:25:46 mpi Exp $ */ | | 2 | /* $OpenBSD: if_urtwn.c,v 1.42 2015/02/10 23:25:46 mpi Exp $ */ |
3 | | | 3 | |
4 | /*- | | 4 | /*- |
5 | * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> | | 5 | * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> |
6 | * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org> | | 6 | * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org> |
7 | * Copyright (c) 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au> | | 7 | * Copyright (c) 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au> |
8 | * | | 8 | * |
9 | * Permission to use, copy, modify, and distribute this software for any | | 9 | * Permission to use, copy, modify, and distribute this software for any |
10 | * purpose with or without fee is hereby granted, provided that the above | | 10 | * purpose with or without fee is hereby granted, provided that the above |
11 | * copyright notice and this permission notice appear in all copies. | | 11 | * copyright notice and this permission notice appear in all copies. |
12 | * | | 12 | * |
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | | 13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
14 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | | 14 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
15 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | | 15 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
16 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | | 16 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | | 17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
18 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | | 18 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
19 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | | 19 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
20 | */ | | 20 | */ |
21 | | | 21 | |
22 | /*- | | 22 | /*- |
23 | * Driver for Realtek RTL8188CE-VAU/RTL8188CUS/RTL8188EU/RTL8188RU/RTL8192CU | | 23 | * Driver for Realtek RTL8188CE-VAU/RTL8188CUS/RTL8188EU/RTL8188RU/RTL8192CU |
24 | * RTL8192EU. | | 24 | * RTL8192EU. |
25 | */ | | 25 | */ |
26 | | | 26 | |
27 | #include <sys/cdefs.h> | | 27 | #include <sys/cdefs.h> |
28 | __KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.34.4.15 2016/12/05 10:55:18 skrll Exp $"); | | 28 | __KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.34.4.16 2017/01/28 12:04:17 skrll Exp $"); |
29 | | | 29 | |
30 | #ifdef _KERNEL_OPT | | 30 | #ifdef _KERNEL_OPT |
31 | #include "opt_inet.h" | | 31 | #include "opt_inet.h" |
32 | #include "opt_usb.h" | | 32 | #include "opt_usb.h" |
33 | #endif | | 33 | #endif |
34 | | | 34 | |
35 | #include <sys/param.h> | | 35 | #include <sys/param.h> |
36 | #include <sys/sockio.h> | | 36 | #include <sys/sockio.h> |
37 | #include <sys/sysctl.h> | | 37 | #include <sys/sysctl.h> |
38 | #include <sys/mbuf.h> | | 38 | #include <sys/mbuf.h> |
39 | #include <sys/kernel.h> | | 39 | #include <sys/kernel.h> |
40 | #include <sys/socket.h> | | 40 | #include <sys/socket.h> |
41 | #include <sys/systm.h> | | 41 | #include <sys/systm.h> |
| @@ -362,26 +362,27 @@ urtwn_attach(device_t parent, device_t s | | | @@ -362,26 +362,27 @@ urtwn_attach(device_t parent, device_t s |
362 | | | 362 | |
363 | devinfop = usbd_devinfo_alloc(sc->sc_udev, 0); | | 363 | devinfop = usbd_devinfo_alloc(sc->sc_udev, 0); |
364 | aprint_normal_dev(self, "%s\n", devinfop); | | 364 | aprint_normal_dev(self, "%s\n", devinfop); |
365 | usbd_devinfo_free(devinfop); | | 365 | usbd_devinfo_free(devinfop); |
366 | | | 366 | |
367 | req.bmRequestType = UT_WRITE_DEVICE; | | 367 | req.bmRequestType = UT_WRITE_DEVICE; |
368 | req.bRequest = UR_SET_FEATURE; | | 368 | req.bRequest = UR_SET_FEATURE; |
369 | USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); | | 369 | USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); |
370 | USETW(req.wIndex, UHF_PORT_SUSPEND); | | 370 | USETW(req.wIndex, UHF_PORT_SUSPEND); |
371 | USETW(req.wLength, 0); | | 371 | USETW(req.wLength, 0); |
372 | | | 372 | |
373 | (void) usbd_do_request(sc->sc_udev, &req, 0); | | 373 | (void) usbd_do_request(sc->sc_udev, &req, 0); |
374 | | | 374 | |
| | | 375 | cv_init(&sc->sc_task_cv, "urtwntsk"); |
375 | mutex_init(&sc->sc_task_mtx, MUTEX_DEFAULT, IPL_NET); | | 376 | mutex_init(&sc->sc_task_mtx, MUTEX_DEFAULT, IPL_NET); |
376 | mutex_init(&sc->sc_tx_mtx, MUTEX_DEFAULT, IPL_NONE); | | 377 | mutex_init(&sc->sc_tx_mtx, MUTEX_DEFAULT, IPL_NONE); |
377 | mutex_init(&sc->sc_rx_mtx, MUTEX_DEFAULT, IPL_NONE); | | 378 | mutex_init(&sc->sc_rx_mtx, MUTEX_DEFAULT, IPL_NONE); |
378 | mutex_init(&sc->sc_fwcmd_mtx, MUTEX_DEFAULT, IPL_NONE); | | 379 | mutex_init(&sc->sc_fwcmd_mtx, MUTEX_DEFAULT, IPL_NONE); |
379 | mutex_init(&sc->sc_write_mtx, MUTEX_DEFAULT, IPL_NONE); | | 380 | mutex_init(&sc->sc_write_mtx, MUTEX_DEFAULT, IPL_NONE); |
380 | | | 381 | |
381 | usb_init_task(&sc->sc_task, urtwn_task, sc, 0); | | 382 | usb_init_task(&sc->sc_task, urtwn_task, sc, 0); |
382 | | | 383 | |
383 | callout_init(&sc->sc_scan_to, 0); | | 384 | callout_init(&sc->sc_scan_to, 0); |
384 | callout_setfunc(&sc->sc_scan_to, urtwn_next_scan, sc); | | 385 | callout_setfunc(&sc->sc_scan_to, urtwn_next_scan, sc); |
385 | callout_init(&sc->sc_calib_to, 0); | | 386 | callout_init(&sc->sc_calib_to, 0); |
386 | callout_setfunc(&sc->sc_calib_to, urtwn_calib_to, sc); | | 387 | callout_setfunc(&sc->sc_calib_to, urtwn_calib_to, sc); |
387 | | | 388 | |
| @@ -549,26 +550,27 @@ urtwn_detach(device_t self, int flags) | | | @@ -549,26 +550,27 @@ urtwn_detach(device_t self, int flags) |
549 | if_detach(ifp); | | 550 | if_detach(ifp); |
550 | | | 551 | |
551 | /* Close Tx/Rx pipes. Abort done by urtwn_stop. */ | | 552 | /* Close Tx/Rx pipes. Abort done by urtwn_stop. */ |
552 | urtwn_close_pipes(sc); | | 553 | urtwn_close_pipes(sc); |
553 | } | | 554 | } |
554 | | | 555 | |
555 | splx(s); | | 556 | splx(s); |
556 | | | 557 | |
557 | usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); | | 558 | usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); |
558 | | | 559 | |
559 | callout_destroy(&sc->sc_scan_to); | | 560 | callout_destroy(&sc->sc_scan_to); |
560 | callout_destroy(&sc->sc_calib_to); | | 561 | callout_destroy(&sc->sc_calib_to); |
561 | | | 562 | |
| | | 563 | cv_destroy(&sc->sc_task_cv); |
562 | mutex_destroy(&sc->sc_write_mtx); | | 564 | mutex_destroy(&sc->sc_write_mtx); |
563 | mutex_destroy(&sc->sc_fwcmd_mtx); | | 565 | mutex_destroy(&sc->sc_fwcmd_mtx); |
564 | mutex_destroy(&sc->sc_tx_mtx); | | 566 | mutex_destroy(&sc->sc_tx_mtx); |
565 | mutex_destroy(&sc->sc_rx_mtx); | | 567 | mutex_destroy(&sc->sc_rx_mtx); |
566 | mutex_destroy(&sc->sc_task_mtx); | | 568 | mutex_destroy(&sc->sc_task_mtx); |
567 | | | 569 | |
568 | return 0; | | 570 | return 0; |
569 | } | | 571 | } |
570 | | | 572 | |
571 | static int | | 573 | static int |
572 | urtwn_activate(device_t self, enum devact act) | | 574 | urtwn_activate(device_t self, enum devact act) |
573 | { | | 575 | { |
574 | struct urtwn_softc *sc = device_private(self); | | 576 | struct urtwn_softc *sc = device_private(self); |
| @@ -813,28 +815,28 @@ urtwn_task(void *arg) | | | @@ -813,28 +815,28 @@ urtwn_task(void *arg) |
813 | s = splusb(); | | 815 | s = splusb(); |
814 | mutex_spin_enter(&sc->sc_task_mtx); | | 816 | mutex_spin_enter(&sc->sc_task_mtx); |
815 | while (ring->next != ring->cur) { | | 817 | while (ring->next != ring->cur) { |
816 | cmd = &ring->cmd[ring->next]; | | 818 | cmd = &ring->cmd[ring->next]; |
817 | mutex_spin_exit(&sc->sc_task_mtx); | | 819 | mutex_spin_exit(&sc->sc_task_mtx); |
818 | splx(s); | | 820 | splx(s); |
819 | /* Invoke callback with kernel lock held. */ | | 821 | /* Invoke callback with kernel lock held. */ |
820 | cmd->cb(sc, cmd->data); | | 822 | cmd->cb(sc, cmd->data); |
821 | s = splusb(); | | 823 | s = splusb(); |
822 | mutex_spin_enter(&sc->sc_task_mtx); | | 824 | mutex_spin_enter(&sc->sc_task_mtx); |
823 | ring->queued--; | | 825 | ring->queued--; |
824 | ring->next = (ring->next + 1) % URTWN_HOST_CMD_RING_COUNT; | | 826 | ring->next = (ring->next + 1) % URTWN_HOST_CMD_RING_COUNT; |
825 | } | | 827 | } |
| | | 828 | cv_broadcast(&sc->sc_task_cv); |
826 | mutex_spin_exit(&sc->sc_task_mtx); | | 829 | mutex_spin_exit(&sc->sc_task_mtx); |
827 | wakeup(&sc->cmdq); | | | |
828 | splx(s); | | 830 | splx(s); |
829 | } | | 831 | } |
830 | | | 832 | |
831 | static void | | 833 | static void |
832 | urtwn_do_async(struct urtwn_softc *sc, void (*cb)(struct urtwn_softc *, void *), | | 834 | urtwn_do_async(struct urtwn_softc *sc, void (*cb)(struct urtwn_softc *, void *), |
833 | void *arg, int len) | | 835 | void *arg, int len) |
834 | { | | 836 | { |
835 | struct urtwn_host_cmd_ring *ring = &sc->cmdq; | | 837 | struct urtwn_host_cmd_ring *ring = &sc->cmdq; |
836 | struct urtwn_host_cmd *cmd; | | 838 | struct urtwn_host_cmd *cmd; |
837 | int s; | | 839 | int s; |
838 | | | 840 | |
839 | DPRINTFN(DBG_FN, ("%s: %s: cb=%p, arg=%p, len=%d\n", | | 841 | DPRINTFN(DBG_FN, ("%s: %s: cb=%p, arg=%p, len=%d\n", |
840 | device_xname(sc->sc_dev), __func__, cb, arg, len)); | | 842 | device_xname(sc->sc_dev), __func__, cb, arg, len)); |
| @@ -853,28 +855,30 @@ urtwn_do_async(struct urtwn_softc *sc, v | | | @@ -853,28 +855,30 @@ urtwn_do_async(struct urtwn_softc *sc, v |
853 | usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER); | | 855 | usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER); |
854 | } else | | 856 | } else |
855 | mutex_spin_exit(&sc->sc_task_mtx); | | 857 | mutex_spin_exit(&sc->sc_task_mtx); |
856 | splx(s); | | 858 | splx(s); |
857 | } | | 859 | } |
858 | | | 860 | |
859 | static void | | 861 | static void |
860 | urtwn_wait_async(struct urtwn_softc *sc) | | 862 | urtwn_wait_async(struct urtwn_softc *sc) |
861 | { | | 863 | { |
862 | | | 864 | |
863 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 865 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
864 | | | 866 | |
865 | /* Wait for all queued asynchronous commands to complete. */ | | 867 | /* Wait for all queued asynchronous commands to complete. */ |
| | | 868 | mutex_spin_enter(&sc->sc_task_mtx); |
866 | while (sc->cmdq.queued > 0) | | 869 | while (sc->cmdq.queued > 0) |
867 | tsleep(&sc->cmdq, 0, "endtask", 0); | | 870 | cv_wait(&sc->sc_task_cv, &sc->sc_task_mtx); |
| | | 871 | mutex_spin_exit(&sc->sc_task_mtx); |
868 | } | | 872 | } |
869 | | | 873 | |
870 | static int | | 874 | static int |
871 | urtwn_write_region_1(struct urtwn_softc *sc, uint16_t addr, uint8_t *buf, | | 875 | urtwn_write_region_1(struct urtwn_softc *sc, uint16_t addr, uint8_t *buf, |
872 | int len) | | 876 | int len) |
873 | { | | 877 | { |
874 | usb_device_request_t req; | | 878 | usb_device_request_t req; |
875 | usbd_status error; | | 879 | usbd_status error; |
876 | | | 880 | |
877 | KASSERT(mutex_owned(&sc->sc_write_mtx)); | | 881 | KASSERT(mutex_owned(&sc->sc_write_mtx)); |
878 | | | 882 | |
879 | req.bmRequestType = UT_WRITE_VENDOR_DEVICE; | | 883 | req.bmRequestType = UT_WRITE_VENDOR_DEVICE; |
880 | req.bRequest = R92C_REQ_REGS; | | 884 | req.bRequest = R92C_REQ_REGS; |