Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb Fix some bugs introduced by the nick-nhusb merge...



details:   https://anonhg.NetBSD.org/src/rev/30429d104f01
branches:  trunk
changeset: 819619:30429d104f01
user:      skrll <skrll%NetBSD.org@localhost>
date:      Sun Dec 11 15:01:37 2016 +0000

description:
Fix some bugs introduced by the nick-nhusb merge and related to the
Tx Interrupt pipe transfer handling

While I'm here make some other changes moving towards MPification

PR/51151: athn panic on attach
PR/51458: usb athn panic

diffstat:

 sys/dev/usb/if_athn_usb.c |  319 ++++++++++++++++++++++++++++++++-------------
 sys/dev/usb/if_athn_usb.h |   11 +-
 2 files changed, 236 insertions(+), 94 deletions(-)

diffs (truncated from 634 to 300 lines):

diff -r a882c1db6f7f -r 30429d104f01 sys/dev/usb/if_athn_usb.c
--- a/sys/dev/usb/if_athn_usb.c Sun Dec 11 12:51:09 2016 +0000
+++ b/sys/dev/usb/if_athn_usb.c Sun Dec 11 15:01:37 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_athn_usb.c,v 1.17 2016/12/11 08:30:39 skrll Exp $   */
+/*     $NetBSD: if_athn_usb.c,v 1.18 2016/12/11 15:01:37 skrll Exp $   */
 /*     $OpenBSD: if_athn_usb.c,v 1.12 2013/01/14 09:50:31 jsing Exp $  */
 
 /*-
@@ -22,7 +22,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_athn_usb.c,v 1.17 2016/12/11 08:30:39 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_athn_usb.c,v 1.18 2016/12/11 15:01:37 skrll Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -94,6 +94,7 @@
 
 Static int     athn_usb_alloc_rx_list(struct athn_usb_softc *);
 Static int     athn_usb_alloc_tx_cmd(struct athn_usb_softc *);
+Static int     athn_usb_alloc_tx_msg(struct athn_usb_softc *);
 Static int     athn_usb_alloc_tx_list(struct athn_usb_softc *);
 Static void    athn_usb_attachhook(device_t);
 Static void    athn_usb_bcneof(struct usbd_xfer *, void *,
@@ -108,6 +109,7 @@
                    void (*)(struct athn_usb_softc *, void *), void *, int);
 Static void    athn_usb_free_rx_list(struct athn_usb_softc *);
 Static void    athn_usb_free_tx_cmd(struct athn_usb_softc *);
+Static void    athn_usb_free_tx_msg(struct athn_usb_softc *);
 Static void    athn_usb_free_tx_list(struct athn_usb_softc *);
 Static int     athn_usb_htc_connect_svc(struct athn_usb_softc *, uint16_t,
                    uint8_t, uint8_t, uint8_t *);
@@ -115,6 +117,7 @@
                    int);
 Static int     athn_usb_htc_setup(struct athn_usb_softc *);
 Static int     athn_usb_init(struct ifnet *);
+Static int     athn_usb_init_locked(struct ifnet *);
 Static void    athn_usb_intr(struct usbd_xfer *, void *,
                    usbd_status);
 Static int     athn_usb_ioctl(struct ifnet *, u_long, void *);
@@ -140,7 +143,9 @@
 Static void    athn_usb_rxeof(struct usbd_xfer *, void *,
                    usbd_status);
 Static void    athn_usb_start(struct ifnet *);
+//Static void  athn_usb_start_locked(struct ifnet *);
 Static void    athn_usb_stop(struct ifnet *);
+Static void    athn_usb_stop_locked(struct ifnet *);
 Static void    athn_usb_swba(struct athn_usb_softc *);
 Static int     athn_usb_switch_chan(struct athn_softc *,
                    struct ieee80211_channel *, struct ieee80211_channel *);
@@ -152,9 +157,8 @@
 Static void    athn_usb_updateslot(struct ifnet *);
 Static void    athn_usb_updateslot_cb(struct athn_usb_softc *, void *);
 Static void    athn_usb_wait_async(struct athn_usb_softc *);
-Static void    athn_usb_wait_cmd(struct athn_usb_softc *);
-Static void    athn_usb_wait_msg(struct athn_usb_softc *);
-Static void    athn_usb_wait_wmi(struct athn_usb_softc *);
+Static int     athn_usb_wait_cmd(struct athn_usb_softc *);
+Static int     athn_usb_wait_msg(struct athn_usb_softc *);
 Static void    athn_usb_watchdog(struct ifnet *);
 Static int     athn_usb_wmi_xcmd(struct athn_usb_softc *, uint16_t, void *,
                    int, void *);
@@ -268,6 +272,13 @@
        sc->sc_ops.write = athn_usb_write;
        sc->sc_ops.write_barrier = athn_usb_write_barrier;
 
+       mutex_init(&usc->usc_lock, MUTEX_DEFAULT, IPL_NONE);
+       
+       cv_init(&usc->usc_cmd_cv, "athncmd");
+       mutex_init(&usc->usc_cmd_mtx, MUTEX_DEFAULT, IPL_SOFTUSB);
+       cv_init(&usc->usc_msg_cv, "athnmsg");
+       mutex_init(&usc->usc_msg_mtx, MUTEX_DEFAULT, IPL_SOFTUSB);
+
        cv_init(&usc->usc_task_cv, "athntsk");
        mutex_init(&usc->usc_task_mtx, MUTEX_DEFAULT, IPL_NET);
        mutex_init(&usc->usc_tx_mtx, MUTEX_DEFAULT, IPL_NONE);
@@ -295,6 +306,10 @@
        if (athn_usb_alloc_tx_cmd(usc) != 0)
                goto fail;
 
+       /* Allocate xfer for firmware commands. */
+       if (athn_usb_alloc_tx_msg(usc) != 0)
+               goto fail;
+
        /* Allocate Tx/Rx buffers. */
        error = athn_usb_alloc_rx_list(usc);
        if (error != 0)
@@ -309,13 +324,23 @@
        return;
 
  fail:
+ 
        /* Free Tx/Rx buffers. */
        athn_usb_abort_pipes(usc);
        athn_usb_free_tx_list(usc);
        athn_usb_free_rx_list(usc);
        athn_usb_free_tx_cmd(usc);
+       athn_usb_free_tx_msg(usc);
        athn_usb_close_pipes(usc);
        usb_rem_task(usc->usc_udev, &usc->usc_task);
+
+       cv_destroy(&usc->usc_cmd_cv);
+       cv_destroy(&usc->usc_msg_cv);
+
+       mutex_destroy(&usc->usc_lock);
+
+       mutex_destroy(&usc->usc_cmd_mtx);
+       mutex_destroy(&usc->usc_msg_mtx);
        mutex_destroy(&usc->usc_tx_mtx);
        mutex_destroy(&usc->usc_task_mtx);
 }
@@ -447,9 +472,12 @@
        s = splusb();
        usc->usc_dying = 1;
 
-       athn_usb_wait_wmi(usc);
+       mutex_enter(&usc->usc_cmd_mtx);
        athn_usb_wait_cmd(usc);
+       mutex_exit(&usc->usc_cmd_mtx);
+       mutex_enter(&usc->usc_msg_mtx);
        athn_usb_wait_msg(usc);
+       mutex_exit(&usc->usc_msg_mtx);
        athn_usb_wait_async(usc);
 
        usb_rem_task(usc->usc_udev, &usc->usc_task);
@@ -734,6 +762,40 @@
                usbd_destroy_xfer(xfer);
 }
 
+Static int
+athn_usb_alloc_tx_msg(struct athn_usb_softc *usc)
+{
+       struct athn_usb_tx_data *data = &usc->usc_tx_msg;
+
+       DPRINTFN(DBG_FN, usc, "\n");
+
+       data->sc = usc; /* Backpointer for callbacks. */
+
+       int err = usbd_create_xfer(usc->usc_tx_intr_pipe, ATHN_USB_TXCMDSZ,
+           0, 0, &data->xfer);
+       if (err) {
+               aprint_error_dev(usc->usc_dev,
+                   "could not allocate command xfer\n");
+               return err;
+       }
+       data->buf = usbd_get_buffer(data->xfer);
+
+       return 0;
+}
+
+Static void
+athn_usb_free_tx_msg(struct athn_usb_softc *usc)
+{
+       struct usbd_xfer *xfer;
+
+       DPRINTFN(DBG_FN, usc, "\n");
+
+       CTASSERT(sizeof(xfer) == sizeof(void *));
+       xfer = atomic_swap_ptr(&usc->usc_tx_msg.xfer, NULL);
+       if (xfer != NULL)
+               usbd_destroy_xfer(xfer);
+}
+
 Static void
 athn_usb_task(void *arg)
 {
@@ -811,7 +873,7 @@
        u_char *fw, *ptr;
        size_t size, remain;
        uint32_t addr;
-       int s, mlen, error;
+       int mlen, error;
 
        DPRINTFN(DBG_FN, sc, "\n");
 
@@ -882,14 +944,24 @@
        USETW(req.wValue, addr);
        USETW(req.wLength, 0);
 
-       s = splusb();
+       mutex_enter(&usc->usc_msg_mtx);
+       error = athn_usb_wait_msg(usc);
+       if (error) {
+               mutex_exit(&usc->usc_msg_mtx);
+               return error;
+       }
+
        usc->usc_wait_msg_id = AR_HTC_MSG_READY;
        error = usbd_do_request(usc->usc_udev, &req, NULL);
+
        /* Wait at most 1 second for firmware to boot. */
-       if (error == 0 && usc->usc_wait_msg_id != 0)
-               error = tsleep(&usc->usc_wait_msg_id, 0, "athnfw", hz);
-       usc->usc_wait_msg_id = 0;
-       splx(s);
+       if (error == 0)
+               error = athn_usb_wait_msg(usc);
+
+       mutex_exit(&usc->usc_msg_mtx);
+
+       DPRINTFN(DBG_FN, sc, "return %d\n", error);
+
        return error;
 }
 
@@ -897,7 +969,7 @@
 athn_usb_htc_msg(struct athn_usb_softc *usc, uint16_t msg_id, void *buf,
     int len)
 {
-       struct athn_usb_tx_data *data = &usc->usc_tx_cmd;
+       struct athn_usb_tx_data *data = &usc->usc_tx_msg;
        struct ar_htc_frame_hdr *htc;
        struct ar_htc_msg_hdr *msg;
 
@@ -906,6 +978,8 @@
 
        DPRINTFN(DBG_FN, usc, "\n");
 
+       KASSERT(mutex_owned(&usc->usc_msg_mtx));
+
        htc = (struct ar_htc_frame_hdr *)data->buf;
        memset(htc, 0, sizeof(*htc));
        htc->endpoint_id = 0;
@@ -920,13 +994,15 @@
            sizeof(*htc) + sizeof(*msg) + len,
            USBD_SHORT_XFER_OK, ATHN_USB_CMD_TIMEOUT, NULL);
        return usbd_sync_transfer(data->xfer);
+
+
 }
 
 Static int
 athn_usb_htc_setup(struct athn_usb_softc *usc)
 {
        struct ar_htc_msg_config_pipe cfg;
-       int s, error;
+       int error;
 
        /*
         * Connect WMI services to USB pipes.
@@ -973,26 +1049,41 @@
        cfg.pipe_id = UE_GET_ADDR(AR_PIPE_TX_DATA);
        cfg.credits = (usc->usc_flags & ATHN_USB_FLAG_AR7010) ? 45 : 33;
 
-       s = splusb();
+       mutex_enter(&usc->usc_msg_mtx);
+       error = athn_usb_wait_msg(usc);
+       if (error) {
+               mutex_exit(&usc->usc_msg_mtx);
+               return error;
+       }
 
        usc->usc_wait_msg_id = AR_HTC_MSG_CONF_PIPE_RSP;
        error = athn_usb_htc_msg(usc, AR_HTC_MSG_CONF_PIPE, &cfg, sizeof(cfg));
-       if (error == 0 && usc->usc_wait_msg_id != 0)
-               error = tsleep(&usc->usc_wait_msg_id, 0, "athnhtc", hz);
-       usc->usc_wait_msg_id = 0;
-
-       splx(s);
 
        if (error != 0) {
-               aprint_error_dev(usc->usc_dev, "could not configure pipe\n");
+               aprint_error_dev(usc->usc_dev, "could not request pipe configurations\n");
+               mutex_exit(&usc->usc_msg_mtx);
+               return error;
+       }
+       error = athn_usb_wait_msg(usc);
+       if (error) {
+               mutex_exit(&usc->usc_msg_mtx);
                return error;
        }
 
        error = athn_usb_htc_msg(usc, AR_HTC_MSG_SETUP_COMPLETE, NULL, 0);
        if (error != 0) {
-               aprint_error_dev(usc->usc_dev, "could not complete setup\n");
+               aprint_error_dev(usc->usc_dev, "could not request complete setup\n");
+               mutex_exit(&usc->usc_msg_mtx);
                return error;
        }
+       error = athn_usb_wait_msg(usc);
+       if (error) {
+               mutex_exit(&usc->usc_msg_mtx);
+               return error;
+       }
+
+       mutex_exit(&usc->usc_msg_mtx);
+
        return 0;
 }
 
@@ -1002,7 +1093,7 @@
 {
        struct ar_htc_msg_conn_svc msg;
        struct ar_htc_msg_conn_svc_rsp rsp;
-       int s, error;
+       int error;
 
        DPRINTFN(DBG_FN, usc, "\n");



Home | Main Index | Thread Index | Old Index