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_<smth>() 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
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to