From owner-p4-projects@FreeBSD.ORG Thu Feb 12 21:10:28 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id C6B8B1065672; Thu, 12 Feb 2009 21:10:27 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8682B106566C for ; Thu, 12 Feb 2009 21:10:27 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 731808FC19 for ; Thu, 12 Feb 2009 21:10:27 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n1CLAROi022992 for ; Thu, 12 Feb 2009 21:10:27 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n1CLARHT022990 for perforce@freebsd.org; Thu, 12 Feb 2009 21:10:27 GMT (envelope-from hselasky@FreeBSD.org) Date: Thu, 12 Feb 2009 21:10:27 GMT Message-Id: <200902122110.n1CLARHT022990@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 157611 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Feb 2009 21:10:28 -0000 http://perforce.freebsd.org/chv.cgi?CH=157611 Change 157611 by hselasky@hselasky_laptop001 on 2009/02/12 21:10:08 USB WLAN: Put more seatbelts on the drivers like in the original USB2 version. - Remove cmd request structure from the stack in ZYD driver. - Make drivers wait for transmit to complete and then halt transmit during any pending command operations. Probably not all command operations, like reading the status counters needs this halt (TODO). Affected files ... .. //depot/projects/usb/src/sys/dev/usb2/wlan/if_rum2.c#39 edit .. //depot/projects/usb/src/sys/dev/usb2/wlan/if_rumvar.h#9 edit .. //depot/projects/usb/src/sys/dev/usb2/wlan/if_ural2.c#38 edit .. //depot/projects/usb/src/sys/dev/usb2/wlan/if_uralvar.h#9 edit .. //depot/projects/usb/src/sys/dev/usb2/wlan/if_zyd2.c#39 edit .. //depot/projects/usb/src/sys/dev/usb2/wlan/if_zydreg.h#10 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_rum2.c#39 (text+ko) ==== @@ -116,6 +116,7 @@ static usb2_callback_t rum_bulk_read_callback; static usb2_callback_t rum_bulk_write_callback; +static usb2_proc_callback_t rum_command_wrapper; static usb2_proc_callback_t rum_attach_post; static usb2_proc_callback_t rum_task; static usb2_proc_callback_t rum_scantask; @@ -408,6 +409,8 @@ mtx_init(&sc->sc_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK, MTX_DEF); + cv_init(&sc->sc_cmd_cv, "wtxdone"); + iface_index = RT2573_IFACE_INDEX; error = usb2_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, rum_config, RUM_N_TRANSFER, sc, &sc->sc_mtx); @@ -573,6 +576,8 @@ if_free(ifp); } + cv_destroy(&sc->sc_cmd_cv); + mtx_destroy(&sc->sc_mtx); return (0); @@ -839,6 +844,10 @@ struct mbuf *m; unsigned int len; + /* wakeup waiting command, if any */ + if (sc->sc_last_task != NULL) + cv_signal(&sc->sc_cmd_cv); + switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: DPRINTFN(11, "transfer complete, %d bytes\n", xfer->actlen); @@ -853,6 +862,10 @@ /* FALLTHROUGH */ case USB_ST_SETUP: tr_setup: + /* wait for command to complete, if any */ + if (sc->sc_last_task != NULL) + break; + data = STAILQ_FIRST(&sc->tx_q); if (data) { STAILQ_REMOVE_HEAD(&sc->tx_q, next); @@ -2166,7 +2179,8 @@ err = rum_write(sc, reg, UGETDW(ucode)); if (err) { /* firmware already loaded ? */ - device_printf(sc->sc_dev, "Firmware load failed.\n"); + device_printf(sc->sc_dev, "Firmware load " + "failure! (ignored)\n"); break; } } @@ -2466,6 +2480,30 @@ } static void +rum_command_wrapper(struct usb2_proc_msg *pm) +{ + struct rum_task *task = (struct rum_task *)pm; + struct rum_softc *sc = task->sc; + struct ifnet *ifp; + + /* wait for pending transfer, if any */ + while (usb2_transfer_pending(sc->sc_xfer[RUM_BULK_WR])) + cv_wait(&sc->sc_cmd_cv, &sc->sc_mtx); + + /* execute task */ + task->func(pm); + + /* check if this is the last task executed */ + if (sc->sc_last_task == task) { + sc->sc_last_task = NULL; + ifp = sc->sc_ifp; + /* re-start TX, if any */ + if ((ifp != NULL) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) + usb2_transfer_start(sc->sc_xfer[RUM_BULK_WR]); + } +} + +static void rum_queue_command(struct rum_softc *sc, usb2_proc_callback_t *fn, struct usb2_proc_msg *t0, struct usb2_proc_msg *t1) { @@ -2482,15 +2520,19 @@ usb2_proc_msignal(&sc->sc_tq, t0, t1); /* Setup callback and softc pointers */ - task->hdr.pm_callback = fn; + task->hdr.pm_callback = rum_command_wrapper; + task->func = fn; task->sc = sc; - /* - * Init, stop and flush must be synchronous! - */ - if ((fn == rum_init_task) || (fn == rum_stop_task) || + /* Make sure that any TX operation will stop */ + sc->sc_last_task = task; + + /* + * Init, stop and flush must be synchronous! + */ + if ((fn == rum_init_task) || (fn == rum_stop_task) || (fn == rum_flush_task)) - usb2_proc_mwait(&sc->sc_tq, t0, t1); + usb2_proc_mwait(&sc->sc_tq, t0, t1); } static device_method_t rum_methods[] = { ==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_rumvar.h#9 (text+ko) ==== @@ -55,6 +55,7 @@ struct rum_task { struct usb2_proc_msg hdr; + usb2_proc_callback_t *func; struct rum_softc *sc; }; @@ -101,6 +102,7 @@ const struct ieee80211_rate_table *sc_rates; struct usb2_xfer *sc_xfer[RUM_N_TRANSFER]; + struct rum_task *sc_last_task; uint8_t rf_rev; uint8_t rffreq; @@ -121,6 +123,7 @@ rum_txdhead tx_free; struct rum_rx_desc sc_rx_desc; + struct cv sc_cmd_cv; struct mtx sc_mtx; uint32_t sta[6]; ==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_ural2.c#38 (text+ko) ==== @@ -95,6 +95,7 @@ static usb2_callback_t ural_bulk_read_callback; static usb2_callback_t ural_bulk_write_callback; +static usb2_proc_callback_t ural_command_wrapper; static usb2_proc_callback_t ural_attach_post; static usb2_proc_callback_t ural_task; static usb2_proc_callback_t ural_scantask; @@ -411,6 +412,8 @@ mtx_init(&sc->sc_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK, MTX_DEF); + cv_init(&sc->sc_cmd_cv, "wtxdone"); + iface_index = RAL_IFACE_INDEX; error = usb2_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, ural_config, @@ -564,6 +567,8 @@ if_free(ifp); } + cv_destroy(&sc->sc_cmd_cv); + mtx_destroy(&sc->sc_mtx); return (0); @@ -876,6 +881,10 @@ struct mbuf *m; unsigned int len; + /* wakeup waiting command, if any */ + if (sc->sc_last_task != NULL) + cv_signal(&sc->sc_cmd_cv); + switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: DPRINTFN(11, "transfer complete, %d bytes\n", xfer->actlen); @@ -890,6 +899,10 @@ /* FALLTHROUGH */ case USB_ST_SETUP: tr_setup: + /* wait for command to complete, if any */ + if (sc->sc_last_task != NULL) + break; + data = STAILQ_FIRST(&sc->tx_q); if (data) { STAILQ_REMOVE_HEAD(&sc->tx_q, next); @@ -2395,6 +2408,30 @@ } static void +ural_command_wrapper(struct usb2_proc_msg *pm) +{ + struct ural_task *task = (struct ural_task *)pm; + struct ural_softc *sc = task->sc; + struct ifnet *ifp; + + /* wait for pending transfer, if any */ + while (usb2_transfer_pending(sc->sc_xfer[URAL_BULK_WR])) + cv_wait(&sc->sc_cmd_cv, &sc->sc_mtx); + + /* execute task */ + task->func(pm); + + /* check if this is the last task executed */ + if (sc->sc_last_task == task) { + sc->sc_last_task = NULL; + ifp = sc->sc_ifp; + /* re-start TX, if any */ + if ((ifp != NULL) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) + usb2_transfer_start(sc->sc_xfer[URAL_BULK_WR]); + } +} + +static void ural_queue_command(struct ural_softc *sc, usb2_proc_callback_t *fn, struct usb2_proc_msg *t0, struct usb2_proc_msg *t1) { @@ -2411,9 +2448,13 @@ usb2_proc_msignal(&sc->sc_tq, t0, t1); /* Setup callback and softc pointers */ - task->hdr.pm_callback = fn; + task->hdr.pm_callback = ural_command_wrapper; + task->func = fn; task->sc = sc; + /* Make sure that any TX operation will stop */ + sc->sc_last_task = task; + /* * Init, stop and flush must be synchronous! */ ==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_uralvar.h#9 (text+ko) ==== @@ -60,6 +60,7 @@ struct ural_task { struct usb2_proc_msg hdr; + usb2_proc_callback_t *func; struct ural_softc *sc; }; @@ -110,6 +111,7 @@ uint8_t rf_rev; struct usb2_xfer *sc_xfer[URAL_N_TRANSFER]; + struct ural_task *sc_last_task; enum ieee80211_state sc_state; int sc_arg; @@ -125,6 +127,7 @@ struct ural_rx_desc sc_rx_desc; struct mtx sc_mtx; + struct cv sc_cmd_cv; uint16_t sta[11]; uint32_t rf_regs[4]; ==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_zyd2.c#39 (text+ko) ==== @@ -325,7 +325,8 @@ mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK, MTX_DEF); - STAILQ_INIT(&sc->sc_rqh); + cv_init(&sc->sc_cmd_cv, "wtxdone"); + cv_init(&sc->sc_intr_cv, "zydcmd"); iface_index = ZYD_IFACE_INDEX; error = usb2_transfer_setup(uaa->device, @@ -469,6 +470,9 @@ if_free(ifp); } + cv_destroy(&sc->sc_cmd_cv); + cv_destroy(&sc->sc_intr_cv); + mtx_destroy(&sc->sc_mtx); return (0); @@ -744,11 +748,13 @@ datalen = xfer->actlen - sizeof(cmd->code); datalen -= 2; /* XXX: padding? */ - STAILQ_FOREACH(rqp, &sc->sc_rqh, rq) { + rqp = sc->sc_curr_rq; + if (rqp != NULL) { int i, cnt; if (rqp->olen != datalen) - continue; + break; + cnt = rqp->olen / sizeof(struct zyd_pair); for (i = 0; i < cnt; i++) { if (*(((const uint16_t *)rqp->idata) + i) != @@ -756,16 +762,15 @@ break; } if (i != cnt) - continue; + break; /* copy answer into caller-supplied buffer */ bcopy(cmd->data, rqp->odata, rqp->olen); DPRINTF(sc, ZYD_DEBUG_CMD, "command %p complete, data = %*D \n", rqp, rqp->olen, rqp->odata, ":"); - wakeup(rqp); /* wakeup caller */ - break; - } - if (rqp == NULL) { + /* wakeup caller */ + cv_signal(&sc->sc_intr_cv); + } else { device_printf(sc->sc_dev, "unexpected IORD notification %*D\n", datalen, cmd->data, ":"); @@ -805,25 +810,26 @@ switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: - rqp = xfer->priv_fifo; + rqp = sc->sc_curr_rq; DPRINTF(sc, ZYD_DEBUG_CMD, "command %p transferred\n", rqp); - if ((rqp->flags & ZYD_CMD_FLAG_READ) == 0) - wakeup(rqp); /* wakeup caller */ + if (rqp != NULL) { + if ((rqp->flags & ZYD_CMD_FLAG_READ) == 0) + cv_signal(&sc->sc_intr_cv); /* wakeup caller */ + } /* FALLTHROUGH */ case USB_ST_SETUP: tr_setup: - STAILQ_FOREACH(rqp, &sc->sc_rqh, rq) { + rqp = sc->sc_curr_rq; + if (rqp != NULL) { if (rqp->flags & ZYD_CMD_FLAG_SENT) - continue; + break; usb2_copy_in(xfer->frbuffers, 0, rqp->cmd, rqp->ilen); xfer->frlengths[0] = rqp->ilen; - xfer->priv_fifo = rqp; rqp->flags |= ZYD_CMD_FLAG_SENT; usb2_start_hardware(xfer); - break; } break; @@ -844,38 +850,42 @@ zyd_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, int ilen, void *odata, int olen, unsigned int flags) { - struct zyd_cmd cmd; - struct zyd_rq rq; int error; - if (ilen > sizeof(cmd.data)) + if (ilen > sizeof(sc->sc_cmd.data)) return (EINVAL); if (usb2_proc_is_gone(&sc->sc_tq)) return (ENXIO); - cmd.code = htole16(code); - bcopy(idata, cmd.data, ilen); + sc->sc_cmd.code = htole16(code); + bcopy(idata, sc->sc_cmd.data, ilen); DPRINTF(sc, ZYD_DEBUG_CMD, "sending cmd %p = %*D\n", - &rq, ilen, idata, ":"); + &sc->sc_rq, ilen, idata, ":"); + + sc->sc_rq.cmd = &sc->sc_cmd; + sc->sc_rq.idata = idata; + sc->sc_rq.odata = odata; + sc->sc_rq.ilen = sizeof(uint16_t) + ilen; + sc->sc_rq.olen = olen; + sc->sc_rq.flags = flags; + + /* set our hint */ + sc->sc_curr_rq = &sc->sc_rq; - rq.cmd = &cmd; - rq.idata = idata; - rq.odata = odata; - rq.ilen = sizeof(uint16_t) + ilen; - rq.olen = olen; - rq.flags = flags; - STAILQ_INSERT_TAIL(&sc->sc_rqh, &rq, rq); usb2_transfer_start(sc->sc_xfer[ZYD_INTR_RD]); usb2_transfer_start(sc->sc_xfer[ZYD_INTR_WR]); /* wait at most one second for command reply */ - error = mtx_sleep(&rq, &sc->sc_mtx, 0 , "zydcmd", hz); + error = cv_timedwait(&sc->sc_intr_cv, &sc->sc_mtx, hz); if (error) device_printf(sc->sc_dev, "command timeout\n"); - STAILQ_REMOVE(&sc->sc_rqh, &rq, zyd_rq, rq); + + /* clear our hint */ + sc->sc_curr_rq = NULL; + DPRINTF(sc, ZYD_DEBUG_CMD, "finsihed cmd %p, error = %d \n", - &rq, error); + &sc->sc_rq, error); return (error); } @@ -2511,6 +2521,10 @@ struct zyd_tx_data *data; struct mbuf *m; + /* wakeup any waiting command, if any */ + if (sc->sc_last_task != NULL) + cv_signal(&sc->sc_cmd_cv); + switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: DPRINTF(sc, ZYD_DEBUG_ANY, "transfer complete, %u bytes\n", @@ -2526,6 +2540,10 @@ /* FALLTHROUGH */ case USB_ST_SETUP: tr_setup: + /* wait for command to complete, if any */ + if (sc->sc_last_task != NULL) + break; + data = STAILQ_FIRST(&sc->tx_q); if (data) { STAILQ_REMOVE_HEAD(&sc->tx_q, next); @@ -3099,6 +3117,30 @@ } static void +zyd_command_wrapper(struct usb2_proc_msg *pm) +{ + struct zyd_task *task = (struct zyd_task *)pm; + struct zyd_softc *sc = task->sc; + struct ifnet *ifp; + + /* wait for pending transfer, if any */ + while (usb2_transfer_pending(sc->sc_xfer[ZYD_BULK_WR])) + cv_wait(&sc->sc_cmd_cv, &sc->sc_mtx); + + /* execute task */ + task->func(pm); + + /* check if this is the last task executed */ + if (sc->sc_last_task == task) { + sc->sc_last_task = NULL; + ifp = sc->sc_ifp; + /* re-start TX, if any */ + if ((ifp != NULL) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) + usb2_transfer_start(sc->sc_xfer[ZYD_BULK_WR]); + } +} + +static void zyd_queue_command(struct zyd_softc *sc, usb2_proc_callback_t *fn, struct usb2_proc_msg *t0, struct usb2_proc_msg *t1) { @@ -3115,15 +3157,19 @@ usb2_proc_msignal(&sc->sc_tq, t0, t1); /* Setup callback and softc pointers */ - task->hdr.pm_callback = fn; + task->hdr.pm_callback = zyd_command_wrapper; + task->func = fn; task->sc = sc; - /* - * Init and stop must be synchronous! - */ - if ((fn == zyd_init_task) || (fn == zyd_stop_task) || + /* Make sure that any TX operation will stop */ + sc->sc_last_task = task; + + /* + * Init and stop must be synchronous! + */ + if ((fn == zyd_init_task) || (fn == zyd_stop_task) || (fn == zyd_flush_task)) - usb2_proc_mwait(&sc->sc_tq, t0, t1); + usb2_proc_mwait(&sc->sc_tq, t0, t1); } static device_method_t zyd_methods[] = { ==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_zydreg.h#10 (text+ko) ==== @@ -1165,6 +1165,7 @@ struct zyd_task { struct usb2_proc_msg hdr; + usb2_proc_callback_t *func; struct zyd_softc *sc; }; @@ -1267,6 +1268,8 @@ struct usb2_process sc_tq; struct usb2_xfer *sc_xfer[ZYD_N_TRANSFER]; + struct zyd_task *sc_last_task; + struct zyd_rq *sc_curr_rq; enum ieee80211_state sc_state; int sc_arg; @@ -1285,10 +1288,9 @@ struct zyd_task sc_task[2]; struct zyd_rf sc_rf; + struct zyd_cmd sc_cmd; + struct zyd_rq sc_rq; - STAILQ_HEAD(, zyd_rq) sc_rtx; - STAILQ_HEAD(, zyd_rq) sc_rqh; - uint8_t sc_bssid[IEEE80211_ADDR_LEN]; uint16_t sc_fwbase; uint8_t sc_regdomain; @@ -1315,6 +1317,7 @@ uint8_t sc_ofdm54_cal[14]; struct mtx sc_mtx; + struct cv sc_cmd_cv; struct cv sc_intr_cv; struct zyd_tx_data tx_data[ZYD_TX_LIST_CNT]; zyd_txdhead tx_q;