From owner-svn-src-all@freebsd.org Thu Dec 3 14:38:56 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id C28DEA3F07F; Thu, 3 Dec 2015 14:38:56 +0000 (UTC) (envelope-from avos@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 8A3ED1B41; Thu, 3 Dec 2015 14:38:56 +0000 (UTC) (envelope-from avos@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tB3EctFG025254; Thu, 3 Dec 2015 14:38:55 GMT (envelope-from avos@FreeBSD.org) Received: (from avos@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tB3EctBu025253; Thu, 3 Dec 2015 14:38:55 GMT (envelope-from avos@FreeBSD.org) Message-Id: <201512031438.tB3EctBu025253@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: avos set sender to avos@FreeBSD.org using -f From: Andriy Voskoboinyk Date: Thu, 3 Dec 2015 14:38:55 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r291698 - head/sys/dev/usb/wlan X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 03 Dec 2015 14:38:57 -0000 Author: avos Date: Thu Dec 3 14:38:55 2015 New Revision: 291698 URL: https://svnweb.freebsd.org/changeset/base/291698 Log: urtwn(4): add error handling for urtwn_write_X() functions. - Call ieee80211_stop() when urtwn_init() fails (i.e., stop vap explicitly) - Return an error when urtwn_write_() fails. - Handle errors from them in: * urtwn_fw_cmd(); * urtwn_llt_write(); * urtwn_efuse_*(); * urtwn_*_power_on(); * urtwn_*_dma_init(); * urtwn_mac_init(); * urtwn_init(); Tested with RTL8188EU, STA mode Reviewed by: kevlo Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D4291 Modified: head/sys/dev/usb/wlan/if_urtwn.c Modified: head/sys/dev/usb/wlan/if_urtwn.c ============================================================================== --- head/sys/dev/usb/wlan/if_urtwn.c Thu Dec 3 14:32:54 2015 (r291697) +++ head/sys/dev/usb/wlan/if_urtwn.c Thu Dec 3 14:38:55 2015 (r291698) @@ -195,12 +195,12 @@ static void urtwn_free_rx_list(struct u static void urtwn_free_tx_list(struct urtwn_softc *); static struct urtwn_data * _urtwn_getbuf(struct urtwn_softc *); static struct urtwn_data * urtwn_getbuf(struct urtwn_softc *); -static int urtwn_write_region_1(struct urtwn_softc *, uint16_t, +static usb_error_t urtwn_write_region_1(struct urtwn_softc *, uint16_t, uint8_t *, int); -static void urtwn_write_1(struct urtwn_softc *, uint16_t, uint8_t); -static void urtwn_write_2(struct urtwn_softc *, uint16_t, uint16_t); -static void urtwn_write_4(struct urtwn_softc *, uint16_t, uint32_t); -static int urtwn_read_region_1(struct urtwn_softc *, uint16_t, +static usb_error_t urtwn_write_1(struct urtwn_softc *, uint16_t, uint8_t); +static usb_error_t urtwn_write_2(struct urtwn_softc *, uint16_t, uint16_t); +static usb_error_t urtwn_write_4(struct urtwn_softc *, uint16_t, uint32_t); +static usb_error_t urtwn_read_region_1(struct urtwn_softc *, uint16_t, uint8_t *, int); static uint8_t urtwn_read_1(struct urtwn_softc *, uint16_t); static uint16_t urtwn_read_2(struct urtwn_softc *, uint16_t); @@ -223,7 +223,7 @@ static void urtwn_dump_rom_contents(str #endif static int urtwn_efuse_read(struct urtwn_softc *, uint8_t *, uint16_t); -static void urtwn_efuse_switch_power(struct urtwn_softc *); +static int urtwn_efuse_switch_power(struct urtwn_softc *); static int urtwn_read_chipid(struct urtwn_softc *); static int urtwn_read_rom(struct urtwn_softc *); static int urtwn_r88e_read_rom(struct urtwn_softc *); @@ -267,7 +267,7 @@ static int urtwn_fw_loadpage(struct urt static int urtwn_load_firmware(struct urtwn_softc *); static int urtwn_r92c_dma_init(struct urtwn_softc *); static int urtwn_r88e_dma_init(struct urtwn_softc *); -static void urtwn_mac_init(struct urtwn_softc *); +static int urtwn_mac_init(struct urtwn_softc *); static void urtwn_bb_init(struct urtwn_softc *); static void urtwn_rf_init(struct urtwn_softc *); static void urtwn_cam_init(struct urtwn_softc *); @@ -298,7 +298,7 @@ static void urtwn_set_chan(struct urtwn struct ieee80211_channel *); static void urtwn_iq_calib(struct urtwn_softc *); static void urtwn_lc_calib(struct urtwn_softc *); -static void urtwn_init(struct urtwn_softc *); +static int urtwn_init(struct urtwn_softc *); static void urtwn_stop(struct urtwn_softc *); static void urtwn_abort_xfers(struct urtwn_softc *); static int urtwn_raw_xmit(struct ieee80211_node *, struct mbuf *, @@ -516,9 +516,10 @@ urtwn_detach(device_t self) /* Prevent further ioctls. */ URTWN_LOCK(sc); sc->sc_flags |= URTWN_DETACHED; - urtwn_stop(sc); URTWN_UNLOCK(sc); + urtwn_stop(sc); + callout_drain(&sc->sc_watchdog_ch); /* stop all USB transfers */ @@ -1051,7 +1052,7 @@ urtwn_getbuf(struct urtwn_softc *sc) return (bf); } -static int +static usb_error_t urtwn_write_region_1(struct urtwn_softc *sc, uint16_t addr, uint8_t *buf, int len) { @@ -1065,28 +1066,27 @@ urtwn_write_region_1(struct urtwn_softc return (urtwn_do_request(sc, &req, buf)); } -static void +static usb_error_t urtwn_write_1(struct urtwn_softc *sc, uint16_t addr, uint8_t val) { - urtwn_write_region_1(sc, addr, &val, 1); + return (urtwn_write_region_1(sc, addr, &val, sizeof(val))); } - -static void +static usb_error_t urtwn_write_2(struct urtwn_softc *sc, uint16_t addr, uint16_t val) { val = htole16(val); - urtwn_write_region_1(sc, addr, (uint8_t *)&val, 2); + return (urtwn_write_region_1(sc, addr, (uint8_t *)&val, sizeof(val))); } -static void +static usb_error_t urtwn_write_4(struct urtwn_softc *sc, uint16_t addr, uint32_t val) { val = htole32(val); - urtwn_write_region_1(sc, addr, (uint8_t *)&val, 4); + return (urtwn_write_region_1(sc, addr, (uint8_t *)&val, sizeof(val))); } -static int +static usb_error_t urtwn_read_region_1(struct urtwn_softc *sc, uint16_t addr, uint8_t *buf, int len) { @@ -1134,6 +1134,7 @@ static int urtwn_fw_cmd(struct urtwn_softc *sc, uint8_t id, const void *buf, int len) { struct r92c_fw_cmd cmd; + usb_error_t error; int ntries; /* Wait for current FW box to be empty. */ @@ -1155,10 +1156,14 @@ urtwn_fw_cmd(struct urtwn_softc *sc, uin memcpy(cmd.msg, buf, len); /* Write the first word last since that will trigger the FW. */ - urtwn_write_region_1(sc, R92C_HMEBOX_EXT(sc->fwcur), + error = urtwn_write_region_1(sc, R92C_HMEBOX_EXT(sc->fwcur), (uint8_t *)&cmd + 4, 2); - urtwn_write_region_1(sc, R92C_HMEBOX(sc->fwcur), + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); + error = urtwn_write_region_1(sc, R92C_HMEBOX(sc->fwcur), (uint8_t *)&cmd + 0, 4); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX; return (0); @@ -1221,12 +1226,15 @@ urtwn_rf_read(struct urtwn_softc *sc, in static int urtwn_llt_write(struct urtwn_softc *sc, uint32_t addr, uint32_t data) { + usb_error_t error; int ntries; - urtwn_write_4(sc, R92C_LLT_INIT, + error = urtwn_write_4(sc, R92C_LLT_INIT, SM(R92C_LLT_INIT_OP, R92C_LLT_INIT_OP_WRITE) | SM(R92C_LLT_INIT_ADDR, addr) | SM(R92C_LLT_INIT_DATA, data)); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); /* Wait for write operation to complete. */ for (ntries = 0; ntries < 20; ntries++) { if (MS(urtwn_read_4(sc, R92C_LLT_INIT), R92C_LLT_INIT_OP) == @@ -1241,6 +1249,7 @@ static int urtwn_efuse_read_next(struct urtwn_softc *sc, uint8_t *val) { uint32_t reg; + usb_error_t error; int ntries; if (sc->last_rom_addr >= URTWN_EFUSE_MAX_LEN) @@ -1250,7 +1259,9 @@ urtwn_efuse_read_next(struct urtwn_softc reg = RW(reg, R92C_EFUSE_CTRL_ADDR, sc->last_rom_addr); reg &= ~R92C_EFUSE_CTRL_VALID; - urtwn_write_4(sc, R92C_EFUSE_CTRL, reg); + error = urtwn_write_4(sc, R92C_EFUSE_CTRL, reg); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); /* Wait for read operation to complete. */ for (ntries = 0; ntries < 100; ntries++) { reg = urtwn_read_4(sc, R92C_EFUSE_CTRL); @@ -1327,7 +1338,7 @@ urtwn_efuse_read(struct urtwn_softc *sc, uint8_t msk, off, reg; int error; - urtwn_efuse_switch_power(sc); + URTWN_CHK(urtwn_efuse_switch_power(sc)); /* Read full ROM image. */ sc->last_rom_addr = 0; @@ -1370,29 +1381,40 @@ end: #undef URTWN_CHK } -static void +static int urtwn_efuse_switch_power(struct urtwn_softc *sc) { + usb_error_t error; uint32_t reg; - urtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_ON); + error = urtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_ON); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); reg = urtwn_read_2(sc, R92C_SYS_ISO_CTRL); if (!(reg & R92C_SYS_ISO_CTRL_PWC_EV12V)) { - urtwn_write_2(sc, R92C_SYS_ISO_CTRL, + error = urtwn_write_2(sc, R92C_SYS_ISO_CTRL, reg | R92C_SYS_ISO_CTRL_PWC_EV12V); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); } reg = urtwn_read_2(sc, R92C_SYS_FUNC_EN); if (!(reg & R92C_SYS_FUNC_EN_ELDR)) { - urtwn_write_2(sc, R92C_SYS_FUNC_EN, + error = urtwn_write_2(sc, R92C_SYS_FUNC_EN, reg | R92C_SYS_FUNC_EN_ELDR); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); } reg = urtwn_read_2(sc, R92C_SYS_CLKR); if ((reg & (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) != (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) { - urtwn_write_2(sc, R92C_SYS_CLKR, + error = urtwn_write_2(sc, R92C_SYS_CLKR, reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); } + + return (0); } static int @@ -2360,24 +2382,23 @@ static void urtwn_parent(struct ieee80211com *ic) { struct urtwn_softc *sc = ic->ic_softc; - int startall = 0; URTWN_LOCK(sc); if (sc->sc_flags & URTWN_DETACHED) { URTWN_UNLOCK(sc); return; } - if (ic->ic_nrunning > 0) { - if ((sc->sc_flags & URTWN_RUNNING) == 0) { - urtwn_init(sc); - startall = 1; - } - } else if (sc->sc_flags & URTWN_RUNNING) - urtwn_stop(sc); URTWN_UNLOCK(sc); - if (startall) - ieee80211_start_all(ic); + if (ic->ic_nrunning > 0) { + if (urtwn_init(sc) != 0) { + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + if (vap != NULL) + ieee80211_stop(vap); + } else + ieee80211_start_all(ic); + } else + urtwn_stop(sc); } static __inline int @@ -2391,6 +2412,7 @@ static int urtwn_r92c_power_on(struct urtwn_softc *sc) { uint32_t reg; + usb_error_t error; int ntries; /* Wait for autoload done bit. */ @@ -2406,24 +2428,34 @@ urtwn_r92c_power_on(struct urtwn_softc * } /* Unlock ISO/CLK/Power control register. */ - urtwn_write_1(sc, R92C_RSV_CTRL, 0); + error = urtwn_write_1(sc, R92C_RSV_CTRL, 0); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); /* Move SPS into PWM mode. */ - urtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b); + error = urtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); urtwn_ms_delay(sc); reg = urtwn_read_1(sc, R92C_LDOV12D_CTRL); if (!(reg & R92C_LDOV12D_CTRL_LDV12_EN)) { - urtwn_write_1(sc, R92C_LDOV12D_CTRL, + error = urtwn_write_1(sc, R92C_LDOV12D_CTRL, reg | R92C_LDOV12D_CTRL_LDV12_EN); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); urtwn_ms_delay(sc); - urtwn_write_1(sc, R92C_SYS_ISO_CTRL, + error = urtwn_write_1(sc, R92C_SYS_ISO_CTRL, urtwn_read_1(sc, R92C_SYS_ISO_CTRL) & ~R92C_SYS_ISO_CTRL_MD2PP); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); } /* Auto enable WLAN. */ - urtwn_write_2(sc, R92C_APS_FSMCO, + error = urtwn_write_2(sc, R92C_APS_FSMCO, urtwn_read_2(sc, R92C_APS_FSMCO) | R92C_APS_FSMCO_APFM_ONMAC); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); for (ntries = 0; ntries < 1000; ntries++) { if (!(urtwn_read_2(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_APFM_ONMAC)) @@ -2437,17 +2469,23 @@ urtwn_r92c_power_on(struct urtwn_softc * } /* Enable radio, GPIO and LED functions. */ - urtwn_write_2(sc, R92C_APS_FSMCO, + error = urtwn_write_2(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_PDN_EN | R92C_APS_FSMCO_PFM_ALDN); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); /* Release RF digital isolation. */ - urtwn_write_2(sc, R92C_SYS_ISO_CTRL, + error = urtwn_write_2(sc, R92C_SYS_ISO_CTRL, urtwn_read_2(sc, R92C_SYS_ISO_CTRL) & ~R92C_SYS_ISO_CTRL_DIOR); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); /* Initialize MAC. */ - urtwn_write_1(sc, R92C_APSD_CTRL, + error = urtwn_write_1(sc, R92C_APSD_CTRL, urtwn_read_1(sc, R92C_APSD_CTRL) & ~R92C_APSD_CTRL_OFF); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); for (ntries = 0; ntries < 200; ntries++) { if (!(urtwn_read_1(sc, R92C_APSD_CTRL) & R92C_APSD_CTRL_OFF_STATUS)) @@ -2466,9 +2504,13 @@ urtwn_r92c_power_on(struct urtwn_softc * R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN | R92C_CR_ENSEC; - urtwn_write_2(sc, R92C_CR, reg); + error = urtwn_write_2(sc, R92C_CR, reg); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); - urtwn_write_1(sc, 0xfe10, 0x19); + error = urtwn_write_1(sc, 0xfe10, 0x19); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); return (0); } @@ -2476,6 +2518,7 @@ static int urtwn_r88e_power_on(struct urtwn_softc *sc) { uint32_t reg; + usb_error_t error; int ntries; /* Wait for power ready bit. */ @@ -2491,24 +2534,34 @@ urtwn_r88e_power_on(struct urtwn_softc * } /* Reset BB. */ - urtwn_write_1(sc, R92C_SYS_FUNC_EN, + error = urtwn_write_1(sc, R92C_SYS_FUNC_EN, urtwn_read_1(sc, R92C_SYS_FUNC_EN) & ~(R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST)); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); - urtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 2, + error = urtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 2, urtwn_read_1(sc, R92C_AFE_XTAL_CTRL + 2) | 0x80); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); /* Disable HWPDN. */ - urtwn_write_2(sc, R92C_APS_FSMCO, + error = urtwn_write_2(sc, R92C_APS_FSMCO, urtwn_read_2(sc, R92C_APS_FSMCO) & ~R92C_APS_FSMCO_APDM_HPDN); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); /* Disable WL suspend. */ - urtwn_write_2(sc, R92C_APS_FSMCO, + error = urtwn_write_2(sc, R92C_APS_FSMCO, urtwn_read_2(sc, R92C_APS_FSMCO) & ~(R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE)); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); - urtwn_write_2(sc, R92C_APS_FSMCO, + error = urtwn_write_2(sc, R92C_APS_FSMCO, urtwn_read_2(sc, R92C_APS_FSMCO) | R92C_APS_FSMCO_APFM_ONMAC); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); for (ntries = 0; ntries < 5000; ntries++) { if (!(urtwn_read_2(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_APFM_ONMAC)) @@ -2519,16 +2572,22 @@ urtwn_r88e_power_on(struct urtwn_softc * return (ETIMEDOUT); /* Enable LDO normal mode. */ - urtwn_write_1(sc, R92C_LPLDO_CTRL, + error = urtwn_write_1(sc, R92C_LPLDO_CTRL, urtwn_read_1(sc, R92C_LPLDO_CTRL) & ~0x10); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ - urtwn_write_2(sc, R92C_CR, 0); + error = urtwn_write_2(sc, R92C_CR, 0); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); reg = urtwn_read_2(sc, R92C_CR); reg |= R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN | R92C_CR_ENSEC | R92C_CR_CALTMR_EN; - urtwn_write_2(sc, R92C_CR, reg); + error = urtwn_write_2(sc, R92C_CR, reg); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); return (0); } @@ -2598,7 +2657,8 @@ static int urtwn_fw_loadpage(struct urtwn_softc *sc, int page, const uint8_t *buf, int len) { uint32_t reg; - int off, mlen, error = 0; + usb_error_t error = USB_ERR_NORMAL_COMPLETION; + int off, mlen; reg = urtwn_read_4(sc, R92C_MCUFWDL); reg = RW(reg, R92C_MCUFWDL_PAGE, page); @@ -2615,7 +2675,7 @@ urtwn_fw_loadpage(struct urtwn_softc *sc /* XXX fix this deconst */ error = urtwn_write_region_1(sc, off, __DECONST(uint8_t *, buf), mlen); - if (error != 0) + if (error != USB_ERR_NORMAL_COMPLETION) break; off += mlen; buf += mlen; @@ -2748,6 +2808,7 @@ fail: static __inline int urtwn_dma_init(struct urtwn_softc *sc) { + usb_error_t usb_err; int error; /* Initialize LLT table. */ @@ -2760,9 +2821,11 @@ urtwn_dma_init(struct urtwn_softc *sc) return (error); /* Set Tx/Rx transfer page size. */ - urtwn_write_1(sc, R92C_PBP, + usb_err = urtwn_write_1(sc, R92C_PBP, SM(R92C_PBP_PSRX, R92C_PBP_128) | SM(R92C_PBP_PSTX, R92C_PBP_128)); + if (usb_err != USB_ERR_NORMAL_COMPLETION) + return (EIO); return (0); } @@ -2771,6 +2834,7 @@ static int urtwn_r92c_dma_init(struct urtwn_softc *sc) { int hashq, hasnq, haslq, nqueues, nqpages, nrempages; + usb_error_t error; uint32_t reg; /* Get Tx queues to USB endpoints mapping. */ @@ -2792,8 +2856,10 @@ urtwn_r92c_dma_init(struct urtwn_softc * nrempages = (R92C_TX_PAGE_COUNT - R92C_PUBQ_NPAGES) % nqueues; /* Set number of pages for normal priority queue. */ - urtwn_write_1(sc, R92C_RQPN_NPQ, hasnq ? nqpages : 0); - urtwn_write_4(sc, R92C_RQPN, + error = urtwn_write_1(sc, R92C_RQPN_NPQ, hasnq ? nqpages : 0); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); + error = urtwn_write_4(sc, R92C_RQPN, /* Set number of pages for public queue. */ SM(R92C_RQPN_PUBQ, R92C_PUBQ_NPAGES) | /* Set number of pages for high priority queue. */ @@ -2802,12 +2868,24 @@ urtwn_r92c_dma_init(struct urtwn_softc * SM(R92C_RQPN_LPQ, haslq ? nqpages : 0) | /* Load values. */ R92C_RQPN_LD); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); - urtwn_write_1(sc, R92C_TXPKTBUF_BCNQ_BDNY, R92C_TX_PAGE_BOUNDARY); - urtwn_write_1(sc, R92C_TXPKTBUF_MGQ_BDNY, R92C_TX_PAGE_BOUNDARY); - urtwn_write_1(sc, R92C_TXPKTBUF_WMAC_LBK_BF_HD, R92C_TX_PAGE_BOUNDARY); - urtwn_write_1(sc, R92C_TRXFF_BNDY, R92C_TX_PAGE_BOUNDARY); - urtwn_write_1(sc, R92C_TDECTRL + 1, R92C_TX_PAGE_BOUNDARY); + error = urtwn_write_1(sc, R92C_TXPKTBUF_BCNQ_BDNY, R92C_TX_PAGE_BOUNDARY); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); + error = urtwn_write_1(sc, R92C_TXPKTBUF_MGQ_BDNY, R92C_TX_PAGE_BOUNDARY); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); + error = urtwn_write_1(sc, R92C_TXPKTBUF_WMAC_LBK_BF_HD, R92C_TX_PAGE_BOUNDARY); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); + error = urtwn_write_1(sc, R92C_TRXFF_BNDY, R92C_TX_PAGE_BOUNDARY); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); + error = urtwn_write_1(sc, R92C_TDECTRL + 1, R92C_TX_PAGE_BOUNDARY); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); /* Set queue to USB pipe mapping. */ reg = urtwn_read_2(sc, R92C_TRXDMA_CTRL); @@ -2829,10 +2907,14 @@ urtwn_r92c_dma_init(struct urtwn_softc * reg |= R92C_TRXDMA_CTRL_QMAP_HQ_LQ; } else reg |= R92C_TRXDMA_CTRL_QMAP_3EP; - urtwn_write_2(sc, R92C_TRXDMA_CTRL, reg); + error = urtwn_write_2(sc, R92C_TRXDMA_CTRL, reg); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); /* Set Tx/Rx transfer page boundary. */ - urtwn_write_2(sc, R92C_TRXFF_BNDY + 2, 0x27ff); + error = urtwn_write_2(sc, R92C_TRXFF_BNDY + 2, 0x27ff); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); return (0); } @@ -2842,6 +2924,7 @@ urtwn_r88e_dma_init(struct urtwn_softc * { struct usb_interface *iface; uint32_t reg; + usb_error_t error; int nqueues; /* Get Tx queues to USB endpoints mapping. */ @@ -2851,14 +2934,28 @@ urtwn_r88e_dma_init(struct urtwn_softc * return (EIO); /* Set number of pages for normal priority queue. */ - urtwn_write_2(sc, R92C_RQPN_NPQ, 0x000d); - urtwn_write_4(sc, R92C_RQPN, 0x808e000d); + error = urtwn_write_2(sc, R92C_RQPN_NPQ, 0x000d); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); + error = urtwn_write_4(sc, R92C_RQPN, 0x808e000d); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); - urtwn_write_1(sc, R92C_TXPKTBUF_BCNQ_BDNY, R88E_TX_PAGE_BOUNDARY); - urtwn_write_1(sc, R92C_TXPKTBUF_MGQ_BDNY, R88E_TX_PAGE_BOUNDARY); - urtwn_write_1(sc, R92C_TXPKTBUF_WMAC_LBK_BF_HD, R88E_TX_PAGE_BOUNDARY); - urtwn_write_1(sc, R92C_TRXFF_BNDY, R88E_TX_PAGE_BOUNDARY); - urtwn_write_1(sc, R92C_TDECTRL + 1, R88E_TX_PAGE_BOUNDARY); + error = urtwn_write_1(sc, R92C_TXPKTBUF_BCNQ_BDNY, R88E_TX_PAGE_BOUNDARY); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); + error = urtwn_write_1(sc, R92C_TXPKTBUF_MGQ_BDNY, R88E_TX_PAGE_BOUNDARY); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); + error = urtwn_write_1(sc, R92C_TXPKTBUF_WMAC_LBK_BF_HD, R88E_TX_PAGE_BOUNDARY); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); + error = urtwn_write_1(sc, R92C_TRXFF_BNDY, R88E_TX_PAGE_BOUNDARY); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); + error = urtwn_write_1(sc, R92C_TDECTRL + 1, R88E_TX_PAGE_BOUNDARY); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); /* Set queue to USB pipe mapping. */ reg = urtwn_read_2(sc, R92C_TRXDMA_CTRL); @@ -2869,31 +2966,42 @@ urtwn_r88e_dma_init(struct urtwn_softc * reg |= R92C_TRXDMA_CTRL_QMAP_HQ_NQ; else reg |= R92C_TRXDMA_CTRL_QMAP_3EP; - urtwn_write_2(sc, R92C_TRXDMA_CTRL, reg); + error = urtwn_write_2(sc, R92C_TRXDMA_CTRL, reg); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); /* Set Tx/Rx transfer page boundary. */ - urtwn_write_2(sc, R92C_TRXFF_BNDY + 2, 0x23ff); + error = urtwn_write_2(sc, R92C_TRXFF_BNDY + 2, 0x23ff); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); return (0); } -static void +static int urtwn_mac_init(struct urtwn_softc *sc) { + usb_error_t error; int i; /* Write MAC initialization values. */ if (sc->chip & URTWN_CHIP_88E) { for (i = 0; i < nitems(rtl8188eu_mac); i++) { - urtwn_write_1(sc, rtl8188eu_mac[i].reg, + error = urtwn_write_1(sc, rtl8188eu_mac[i].reg, rtl8188eu_mac[i].val); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); } urtwn_write_1(sc, R92C_MAX_AGGR_NUM, 0x07); } else { for (i = 0; i < nitems(rtl8192cu_mac); i++) - urtwn_write_1(sc, rtl8192cu_mac[i].reg, + error = urtwn_write_1(sc, rtl8192cu_mac[i].reg, rtl8192cu_mac[i].val); + if (error != USB_ERR_NORMAL_COMPLETION) + return (EIO); } + + return (0); } static void @@ -3711,19 +3819,21 @@ urtwn_lc_calib(struct urtwn_softc *sc) } } -static void +static int urtwn_init(struct urtwn_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint8_t macaddr[IEEE80211_ADDR_LEN]; uint32_t reg; + usb_error_t usb_err = USB_ERR_NORMAL_COMPLETION; int error; - URTWN_ASSERT_LOCKED(sc); - - if (sc->sc_flags & URTWN_RUNNING) - urtwn_stop(sc); + URTWN_LOCK(sc); + if (sc->sc_flags & URTWN_RUNNING) { + URTWN_UNLOCK(sc); + return (0); + } /* Init firmware commands ring. */ sc->fwcur = 0; @@ -3752,22 +3862,36 @@ urtwn_init(struct urtwn_softc *sc) /* Init interrupts. */ if (sc->chip & URTWN_CHIP_88E) { - urtwn_write_4(sc, R88E_HISR, 0xffffffff); - urtwn_write_4(sc, R88E_HIMR, R88E_HIMR_CPWM | R88E_HIMR_CPWM2 | + usb_err = urtwn_write_4(sc, R88E_HISR, 0xffffffff); + if (usb_err != USB_ERR_NORMAL_COMPLETION) + goto fail; + usb_err = urtwn_write_4(sc, R88E_HIMR, R88E_HIMR_CPWM | R88E_HIMR_CPWM2 | R88E_HIMR_TBDER | R88E_HIMR_PSTIMEOUT); - urtwn_write_4(sc, R88E_HIMRE, R88E_HIMRE_RXFOVW | + if (usb_err != USB_ERR_NORMAL_COMPLETION) + goto fail; + usb_err = urtwn_write_4(sc, R88E_HIMRE, R88E_HIMRE_RXFOVW | R88E_HIMRE_TXFOVW | R88E_HIMRE_RXERR | R88E_HIMRE_TXERR); - urtwn_write_1(sc, R92C_USB_SPECIAL_OPTION, + if (usb_err != USB_ERR_NORMAL_COMPLETION) + goto fail; + usb_err = urtwn_write_1(sc, R92C_USB_SPECIAL_OPTION, urtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) | R92C_USB_SPECIAL_OPTION_INT_BULK_SEL); + if (usb_err != USB_ERR_NORMAL_COMPLETION) + goto fail; } else { - urtwn_write_4(sc, R92C_HISR, 0xffffffff); - urtwn_write_4(sc, R92C_HIMR, 0xffffffff); + usb_err = urtwn_write_4(sc, R92C_HISR, 0xffffffff); + if (usb_err != USB_ERR_NORMAL_COMPLETION) + goto fail; + usb_err = urtwn_write_4(sc, R92C_HIMR, 0xffffffff); + if (usb_err != USB_ERR_NORMAL_COMPLETION) + goto fail; } /* Set MAC address. */ IEEE80211_ADDR_COPY(macaddr, vap ? vap->iv_myaddr : ic->ic_macaddr); - urtwn_write_region_1(sc, R92C_MACID, macaddr, IEEE80211_ADDR_LEN); + usb_err = urtwn_write_region_1(sc, R92C_MACID, macaddr, IEEE80211_ADDR_LEN); + if (usb_err != USB_ERR_NORMAL_COMPLETION) + goto fail; /* Set initial network type. */ urtwn_set_mode(sc, R92C_MSR_INFRA); @@ -3842,7 +3966,12 @@ urtwn_init(struct urtwn_softc *sc) goto fail; /* Initialize MAC/BB/RF blocks. */ - urtwn_mac_init(sc); + error = urtwn_mac_init(sc); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: error while initializing MAC block\n", __func__); + goto fail; + } urtwn_bb_init(sc); urtwn_rf_init(sc); @@ -3858,10 +3987,14 @@ urtwn_init(struct urtwn_softc *sc) /* Turn CCK and OFDM blocks on. */ reg = urtwn_bb_read(sc, R92C_FPGA0_RFMOD); reg |= R92C_RFMOD_CCK_EN; - urtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg); + usb_err = urtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg); + if (usb_err != USB_ERR_NORMAL_COMPLETION) + goto fail; reg = urtwn_bb_read(sc, R92C_FPGA0_RFMOD); reg |= R92C_RFMOD_OFDM_EN; - urtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg); + usb_err = urtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg); + if (usb_err != USB_ERR_NORMAL_COMPLETION) + goto fail; /* Clear per-station keys table. */ urtwn_cam_init(sc); @@ -3897,19 +4030,30 @@ urtwn_init(struct urtwn_softc *sc) callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc); fail: - return; + if (usb_err != USB_ERR_NORMAL_COMPLETION) + error = EIO; + + URTWN_UNLOCK(sc); + + return (error); } static void urtwn_stop(struct urtwn_softc *sc) { - URTWN_ASSERT_LOCKED(sc); + URTWN_LOCK(sc); + if (!(sc->sc_flags & URTWN_RUNNING)) { + URTWN_UNLOCK(sc); + return; + } + sc->sc_flags &= ~URTWN_RUNNING; callout_stop(&sc->sc_watchdog_ch); urtwn_abort_xfers(sc); urtwn_drain_mbufq(sc); + URTWN_UNLOCK(sc); } static void