diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ic/bwfm.c | 112 | ||||
-rw-r--r-- | sys/dev/ic/bwfmvar.h | 7 | ||||
-rw-r--r-- | sys/dev/pci/if_bwfm_pci.c | 44 | ||||
-rw-r--r-- | sys/dev/sdmmc/if_bwfm_sdio.c | 43 | ||||
-rw-r--r-- | sys/dev/usb/if_bwfm_usb.c | 52 |
5 files changed, 167 insertions, 91 deletions
diff --git a/sys/dev/ic/bwfm.c b/sys/dev/ic/bwfm.c index 718d904b4f1..63af1755fc7 100644 --- a/sys/dev/ic/bwfm.c +++ b/sys/dev/ic/bwfm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bwfm.c,v 1.45 2018/05/17 06:53:45 patrick Exp $ */ +/* $OpenBSD: bwfm.c,v 1.46 2018/05/23 11:32:14 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> @@ -169,24 +169,10 @@ bwfm_attach(struct bwfm_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; - uint32_t bandlist[3], tmp; - int i, j, nbands, nmode, vhtmode; TAILQ_INIT(&sc->sc_bcdc_rxctlq); TAILQ_INIT(&sc->sc_bcdc_txctlq); - if (bwfm_fwvar_cmd_get_int(sc, BWFM_C_GET_VERSION, &tmp)) { - printf("%s: could not read io type\n", DEVNAME(sc)); - return; - } else - sc->sc_io_type = tmp; - if (bwfm_fwvar_var_get_data(sc, "cur_etheraddr", ic->ic_myaddr, - sizeof(ic->ic_myaddr))) { - printf("%s: could not read mac address\n", DEVNAME(sc)); - return; - } - printf("%s: address %s\n", DEVNAME(sc), ether_sprintf(ic->ic_myaddr)); - /* Init host async commands ring. */ sc->sc_cmdq.cur = sc->sc_cmdq.next = sc->sc_cmdq.queued = 0; sc->sc_taskq = taskq_create(DEVNAME(sc), 1, IPL_SOFTNET, 0); @@ -204,6 +190,63 @@ bwfm_attach(struct bwfm_softc *sc) IEEE80211_C_SCANALL | /* device scans all channels at once */ IEEE80211_C_SCANALLBAND; /* device scans all bands at once */ + /* IBSS channel undefined for now. */ + ic->ic_ibss_chan = &ic->ic_channels[0]; + + ifp->if_softc = sc; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_ioctl = bwfm_ioctl; + ifp->if_start = bwfm_start; + ifp->if_watchdog = bwfm_watchdog; + memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); + + if_attach(ifp); + ieee80211_ifattach(ifp); + + sc->sc_newstate = ic->ic_newstate; + ic->ic_newstate = bwfm_newstate; + ic->ic_send_mgmt = bwfm_send_mgmt; + ic->ic_set_key = bwfm_set_key; + ic->ic_delete_key = bwfm_delete_key; + + ieee80211_media_init(ifp, bwfm_media_change, ieee80211_media_status); +} + +void +bwfm_attachhook(struct device *self) +{ + struct bwfm_softc *sc = (struct bwfm_softc *)self; + + if (sc->sc_bus_ops->bs_preinit != NULL && + sc->sc_bus_ops->bs_preinit(sc)) + return; + if (bwfm_preinit(sc)) + return; + sc->sc_initialized = 1; +} + +int +bwfm_preinit(struct bwfm_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = &ic->ic_if; + int i, j, nbands, nmode, vhtmode; + uint32_t bandlist[3], tmp; + + if (sc->sc_initialized) + return 0; + + if (bwfm_fwvar_cmd_get_int(sc, BWFM_C_GET_VERSION, &tmp)) { + printf("%s: could not read io type\n", DEVNAME(sc)); + return 1; + } else + sc->sc_io_type = tmp; + if (bwfm_fwvar_var_get_data(sc, "cur_etheraddr", ic->ic_myaddr, + sizeof(ic->ic_myaddr))) { + printf("%s: could not read mac address\n", DEVNAME(sc)); + return 1; + } + if (bwfm_fwvar_var_get_int(sc, "nmode", &nmode)) nmode = 0; if (bwfm_fwvar_var_get_int(sc, "vhtmode", &vhtmode)) @@ -211,7 +254,7 @@ bwfm_attach(struct bwfm_softc *sc) if (bwfm_fwvar_cmd_get_data(sc, BWFM_C_GET_BANDLIST, bandlist, sizeof(bandlist))) { printf("%s: couldn't get supported band list\n", DEVNAME(sc)); - return; + return 1; } nbands = letoh32(bandlist[0]); for (i = 1; i <= nbands && i < nitems(bandlist); i++) { @@ -260,26 +303,15 @@ bwfm_attach(struct bwfm_softc *sc) } } - /* IBSS channel undefined for now. */ - ic->ic_ibss_chan = &ic->ic_channels[0]; + /* Configure channel information obtained from firmware. */ + ieee80211_channel_init(ifp); - ifp->if_softc = sc; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = bwfm_ioctl; - ifp->if_start = bwfm_start; - ifp->if_watchdog = bwfm_watchdog; - memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); - - if_attach(ifp); - ieee80211_ifattach(ifp); - - sc->sc_newstate = ic->ic_newstate; - ic->ic_newstate = bwfm_newstate; - ic->ic_send_mgmt = bwfm_send_mgmt; - ic->ic_set_key = bwfm_set_key; - ic->ic_delete_key = bwfm_delete_key; + /* Configure MAC address. */ + if (if_setlladdr(ifp, ic->ic_myaddr)) + printf("%s: could not set MAC address\n", DEVNAME(sc)); ieee80211_media_init(ifp, bwfm_media_change, ieee80211_media_status); + return 0; } int @@ -341,8 +373,18 @@ bwfm_init(struct ifnet *ifp) struct bwfm_join_pref_params join_pref[2]; int pm; - if (sc->sc_bus_ops->bs_init) - sc->sc_bus_ops->bs_init(sc); + if (!sc->sc_initialized) { + if (sc->sc_bus_ops->bs_preinit != NULL && + sc->sc_bus_ops->bs_preinit(sc)) { + printf("%s: could not init bus\n", DEVNAME(sc)); + return; + } + if (bwfm_preinit(sc)) { + printf("%s: could not init\n", DEVNAME(sc)); + return; + } + sc->sc_initialized = 1; + } if (bwfm_fwvar_var_set_int(sc, "mpc", 1)) { printf("%s: could not set mpc\n", DEVNAME(sc)); diff --git a/sys/dev/ic/bwfmvar.h b/sys/dev/ic/bwfmvar.h index e473c43b773..250aba20bc4 100644 --- a/sys/dev/ic/bwfmvar.h +++ b/sys/dev/ic/bwfmvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bwfmvar.h,v 1.13 2018/05/16 08:20:00 patrick Exp $ */ +/* $OpenBSD: bwfmvar.h,v 1.14 2018/05/23 11:32:14 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> @@ -85,7 +85,7 @@ struct bwfm_chip { }; struct bwfm_bus_ops { - void (*bs_init)(struct bwfm_softc *); + int (*bs_preinit)(struct bwfm_softc *); void (*bs_stop)(struct bwfm_softc *); int (*bs_txcheck)(struct bwfm_softc *); int (*bs_txdata)(struct bwfm_softc *, struct mbuf *); @@ -159,6 +159,7 @@ struct bwfm_softc { #define BWFM_IO_TYPE_D11N 1 #define BWFM_IO_TYPE_D11AC 2 + int sc_initialized; int sc_tx_timer; int (*sc_newstate)(struct ieee80211com *, @@ -173,6 +174,8 @@ struct bwfm_softc { }; void bwfm_attach(struct bwfm_softc *); +void bwfm_attachhook(struct device *); +int bwfm_preinit(struct bwfm_softc *); int bwfm_detach(struct bwfm_softc *, int); int bwfm_chip_attach(struct bwfm_softc *); int bwfm_chip_set_active(struct bwfm_softc *, uint32_t); diff --git a/sys/dev/pci/if_bwfm_pci.c b/sys/dev/pci/if_bwfm_pci.c index 96ef2c2e2df..2b5f918f030 100644 --- a/sys/dev/pci/if_bwfm_pci.c +++ b/sys/dev/pci/if_bwfm_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bwfm_pci.c,v 1.20 2018/05/23 08:36:15 patrick Exp $ */ +/* $OpenBSD: if_bwfm_pci.c,v 1.21 2018/05/23 11:32:14 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation * Copyright (c) 2017 Patrick Wildt <patrick@blueri.se> @@ -113,6 +113,8 @@ struct bwfm_pci_softc { pcireg_t sc_id; void *sc_ih; + int sc_initialized; + bus_space_tag_t sc_reg_iot; bus_space_handle_t sc_reg_ioh; bus_size_t sc_reg_ios; @@ -185,7 +187,6 @@ struct bwfm_pci_dmamem { #define BWFM_PCI_DMA_KVA(_bdm) ((void *)(_bdm)->bdm_kva) int bwfm_pci_match(struct device *, void *, void *); -void bwfm_pci_attachhook(struct device *); void bwfm_pci_attach(struct device *, struct device *, void *); int bwfm_pci_detach(struct device *, int); @@ -257,6 +258,7 @@ void bwfm_pci_flowring_create(struct bwfm_pci_softc *, void bwfm_pci_flowring_create_cb(struct bwfm_softc *, void *); void bwfm_pci_flowring_delete(struct bwfm_pci_softc *, int); +int bwfm_pci_preinit(struct bwfm_softc *); void bwfm_pci_stop(struct bwfm_softc *); int bwfm_pci_txcheck(struct bwfm_softc *); int bwfm_pci_txdata(struct bwfm_softc *, struct mbuf *); @@ -280,7 +282,7 @@ struct bwfm_buscore_ops bwfm_pci_buscore_ops = { }; struct bwfm_bus_ops bwfm_pci_bus_ops = { - .bs_init = NULL, + .bs_preinit = bwfm_pci_preinit, .bs_stop = bwfm_pci_stop, .bs_txcheck = bwfm_pci_txcheck, .bs_txdata = bwfm_pci_txdata, @@ -358,7 +360,10 @@ bwfm_pci_attach(struct device *parent, struct device *self, void *aux) } printf(": %s\n", intrstr); - config_mountroot(self, bwfm_pci_attachhook); + sc->sc_sc.sc_bus_ops = &bwfm_pci_bus_ops; + sc->sc_sc.sc_proto_ops = &bwfm_pci_msgbuf_ops; + bwfm_attach(&sc->sc_sc); + config_mountroot(self, bwfm_attachhook); return; bar0: @@ -367,11 +372,10 @@ bar1: bus_space_unmap(sc->sc_tcm_iot, sc->sc_tcm_ioh, sc->sc_tcm_ios); } -void -bwfm_pci_attachhook(struct device *self) +int +bwfm_pci_preinit(struct bwfm_softc *bwfm) { - struct bwfm_pci_softc *sc = (struct bwfm_pci_softc *)self; - struct bwfm_softc *bwfm = (void *)sc; + struct bwfm_pci_softc *sc = (void *)bwfm; struct bwfm_pci_ringinfo ringinfo; const char *name = NULL; u_char *ucode; size_t size; @@ -380,10 +384,13 @@ bwfm_pci_attachhook(struct device *self) uint32_t idx_offset, reg; int i; + if (sc->sc_initialized) + return 0; + sc->sc_sc.sc_buscore_ops = &bwfm_pci_buscore_ops; if (bwfm_chip_attach(&sc->sc_sc) != 0) { printf("%s: cannot attach chip\n", DEVNAME(sc)); - return; + return 1; } bwfm_pci_select_core(sc, BWFM_AGENT_CORE_PCIE2); @@ -408,13 +415,13 @@ bwfm_pci_attachhook(struct device *self) default: printf("%s: unknown firmware for chip %s\n", DEVNAME(sc), bwfm->sc_chip.ch_name); - return; + return 1; } if (loadfirmware(name, &ucode, &size) != 0) { printf("%s: failed loadfirmware of file %s\n", DEVNAME(sc), name); - return; + return 1; } /* Retrieve RAM size from firmware. */ @@ -428,7 +435,7 @@ bwfm_pci_attachhook(struct device *self) printf("%s: could not load microcode\n", DEVNAME(sc)); free(ucode, M_DEVBUF, size); - return; + return 1; } free(ucode, M_DEVBUF, size); @@ -439,7 +446,7 @@ bwfm_pci_attachhook(struct device *self) sc->sc_shared_version < BWFM_SHARED_INFO_MIN_VERSION) { printf("%s: PCIe version %d unsupported\n", DEVNAME(sc), sc->sc_shared_version); - return; + return 1; } if (sc->sc_shared_flags & BWFM_SHARED_INFO_DMA_INDEX) { @@ -510,7 +517,7 @@ bwfm_pci_attachhook(struct device *self) /* XXX: Fallback to TCM? */ printf("%s: cannot allocate idx buf\n", DEVNAME(sc)); - return; + return 1; } idx_offset = sc->sc_dma_idx_sz; @@ -651,12 +658,8 @@ bwfm_pci_attachhook(struct device *self) bwfm_pci_debug_console(sc); #endif - sc->sc_ioctl_poll = 1; - sc->sc_sc.sc_bus_ops = &bwfm_pci_bus_ops; - sc->sc_sc.sc_proto_ops = &bwfm_pci_msgbuf_ops; - bwfm_attach(&sc->sc_sc); - sc->sc_ioctl_poll = 0; - return; + sc->sc_initialized = 1; + return 0; cleanup: if (sc->sc_ioctl_buf) @@ -677,6 +680,7 @@ cleanup: bwfm_pci_dmamem_free(sc, sc->sc_ctrl_submit.ring); if (sc->sc_dma_idx_buf) bwfm_pci_dmamem_free(sc, sc->sc_dma_idx_buf); + return 1; } int diff --git a/sys/dev/sdmmc/if_bwfm_sdio.c b/sys/dev/sdmmc/if_bwfm_sdio.c index 5334b087f1d..42752a9b776 100644 --- a/sys/dev/sdmmc/if_bwfm_sdio.c +++ b/sys/dev/sdmmc/if_bwfm_sdio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bwfm_sdio.c,v 1.14 2018/05/23 09:08:18 patrick Exp $ */ +/* $OpenBSD: if_bwfm_sdio.c,v 1.15 2018/05/23 11:32:14 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> @@ -79,6 +79,8 @@ struct bwfm_sdio_softc { struct rwlock *sc_lock; void *sc_ih; + int sc_initialized; + uint32_t sc_bar0; int sc_clkstate; int sc_alp_only; @@ -101,7 +103,7 @@ struct bwfm_sdio_softc { int bwfm_sdio_match(struct device *, void *, void *); void bwfm_sdio_attach(struct device *, struct device *, void *); -void bwfm_sdio_attachhook(struct device *); +int bwfm_sdio_preinit(struct bwfm_softc *); int bwfm_sdio_detach(struct device *, int); int bwfm_sdio_intr(void *); @@ -157,7 +159,7 @@ void bwfm_sdio_debug_console(struct bwfm_sdio_softc *); #endif struct bwfm_bus_ops bwfm_sdio_bus_ops = { - .bs_init = NULL, + .bs_preinit = bwfm_sdio_preinit, .bs_stop = NULL, .bs_txcheck = bwfm_sdio_txcheck, .bs_txdata = bwfm_sdio_txdata, @@ -312,24 +314,29 @@ bwfm_sdio_attach(struct device *parent, struct device *self, void *aux) bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, 0); sc->sc_clkstate = CLK_SDONLY; - config_mountroot(self, bwfm_sdio_attachhook); + sc->sc_sc.sc_bus_ops = &bwfm_sdio_bus_ops; + sc->sc_sc.sc_proto_ops = &bwfm_proto_bcdc_ops; + bwfm_attach(&sc->sc_sc); + config_mountroot(self, bwfm_attachhook); return; err: free(sc->sc_sf, M_DEVBUF, 0); } -void -bwfm_sdio_attachhook(struct device *self) +int +bwfm_sdio_preinit(struct bwfm_softc *bwfm) { - struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self; - struct bwfm_softc *bwfm = (void *)sc; + struct bwfm_sdio_softc *sc = (void *)bwfm; const char *name = NULL; const char *nvname = NULL; uint32_t clk, reg; u_char *ucode, *nvram; size_t size, nvlen; + if (sc->sc_initialized) + return 0; + rw_enter_write(sc->sc_lock); switch (bwfm->sc_chip.ch_chip) @@ -349,20 +356,20 @@ bwfm_sdio_attachhook(struct device *self) default: printf("%s: unknown firmware for chip %s\n", DEVNAME(sc), bwfm->sc_chip.ch_name); - return; + return 1; } if (loadfirmware(name, &ucode, &size) != 0) { printf("%s: failed loadfirmware of file %s\n", DEVNAME(sc), name); - return; + return 1; } if (loadfirmware(nvname, &nvram, &nvlen) != 0) { printf("%s: failed loadfirmware of file %s\n", DEVNAME(sc), nvname); free(ucode, M_DEVBUF, size); - return; + return 1; } sc->sc_alp_only = 1; @@ -372,7 +379,7 @@ bwfm_sdio_attachhook(struct device *self) DEVNAME(sc)); free(ucode, M_DEVBUF, size); free(nvram, M_DEVBUF, nvlen); - return; + return 1; } sc->sc_alp_only = 0; free(ucode, M_DEVBUF, size); @@ -380,7 +387,7 @@ bwfm_sdio_attachhook(struct device *self) bwfm_sdio_clkctl(sc, CLK_AVAIL, 0); if (sc->sc_clkstate != CLK_AVAIL) - return; + return 1; clk = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR); bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, @@ -390,7 +397,7 @@ bwfm_sdio_attachhook(struct device *self) SDPCM_PROT_VERSION << SDPCM_PROT_VERSION_SHIFT); if (sdmmc_io_function_enable(sc->sc_sf[2]) != 0) { printf("%s: cannot enable function 2\n", DEVNAME(sc)); - return; + return 1; } bwfm_sdio_dev_write(sc, SDPCMD_HOSTINTMASK, @@ -411,20 +418,18 @@ bwfm_sdio_attachhook(struct device *self) bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clk); } - /* if interrupt establish fails */ sc->sc_ih = sdmmc_intr_establish(bwfm->sc_dev.dv_parent, bwfm_sdio_intr, sc, DEVNAME(sc)); if (sc->sc_ih == NULL) { printf("%s: can't establish interrupt\n", DEVNAME(sc)); bwfm_sdio_clkctl(sc, CLK_NONE, 0); - return; + return 1; } sdmmc_intr_enable(sc->sc_sf[1]); rw_exit(sc->sc_lock); - sc->sc_sc.sc_bus_ops = &bwfm_sdio_bus_ops; - sc->sc_sc.sc_proto_ops = &bwfm_proto_bcdc_ops; - bwfm_attach(&sc->sc_sc); + sc->sc_initialized = 1; + return 0; } int diff --git a/sys/dev/usb/if_bwfm_usb.c b/sys/dev/usb/if_bwfm_usb.c index 54c990daba0..202d34d492f 100644 --- a/sys/dev/usb/if_bwfm_usb.c +++ b/sys/dev/usb/if_bwfm_usb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bwfm_usb.c,v 1.13 2018/05/16 13:14:23 patrick Exp $ */ +/* $OpenBSD: if_bwfm_usb.c,v 1.14 2018/05/23 11:32:14 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> @@ -166,6 +166,8 @@ struct bwfm_usb_softc { struct usbd_interface *sc_iface; uint8_t sc_ifaceno; + int sc_initialized; + uint16_t sc_vendor; uint16_t sc_product; @@ -184,7 +186,6 @@ struct bwfm_usb_softc { }; int bwfm_usb_match(struct device *, void *, void *); -void bwfm_usb_attachhook(struct device *); void bwfm_usb_attach(struct device *, struct device *, void *); int bwfm_usb_detach(struct device *, int); @@ -197,6 +198,7 @@ void bwfm_usb_free_rx_list(struct bwfm_usb_softc *); int bwfm_usb_alloc_tx_list(struct bwfm_usb_softc *); void bwfm_usb_free_tx_list(struct bwfm_usb_softc *); +int bwfm_usb_preinit(struct bwfm_softc *); int bwfm_usb_txcheck(struct bwfm_softc *); int bwfm_usb_txdata(struct bwfm_softc *, struct mbuf *); int bwfm_usb_txctl(struct bwfm_softc *); @@ -207,7 +209,7 @@ void bwfm_usb_rxeof(struct usbd_xfer *, void *, usbd_status); void bwfm_usb_txeof(struct usbd_xfer *, void *, usbd_status); struct bwfm_bus_ops bwfm_usb_bus_ops = { - .bs_init = NULL, + .bs_preinit = bwfm_usb_preinit, .bs_stop = NULL, .bs_txcheck = bwfm_usb_txcheck, .bs_txdata = bwfm_usb_txdata, @@ -285,13 +287,14 @@ bwfm_usb_attach(struct device *parent, struct device *self, void *aux) return; } - config_mountroot(self, bwfm_usb_attachhook); + bwfm_attach(&sc->sc_sc); + config_mountroot(self, bwfm_attachhook); } -void -bwfm_usb_attachhook(struct device *self) +int +bwfm_usb_preinit(struct bwfm_softc *bwfm) { - struct bwfm_usb_softc *sc = (struct bwfm_usb_softc *)self; + struct bwfm_usb_softc *sc = (void *)bwfm; struct bwfm_usb_rx_data *data; const char *name = NULL; struct bootrom_id brom; @@ -300,6 +303,9 @@ bwfm_usb_attachhook(struct device *self) size_t size; int i; + if (sc->sc_initialized) + return 0; + /* Read chip id and chip rev to check the firmware. */ memset(&brom, 0, sizeof(brom)); bwfm_usb_dl_cmd(sc, DL_GETVER, &brom, sizeof(brom)); @@ -312,14 +318,14 @@ bwfm_usb_attachhook(struct device *self) if (error != 0) { printf("%s: could not open rx pipe: %s\n", DEVNAME(sc), usbd_errstr(error)); - return; + return 1; } error = usbd_open_pipe(sc->sc_iface, sc->sc_tx_no, USBD_EXCLUSIVE_USE, &sc->sc_tx_pipeh); if (error != 0) { printf("%s: could not open tx pipe: %s\n", DEVNAME(sc), usbd_errstr(error)); - return; + return 1; } /* Firmware not yet loaded? */ @@ -348,20 +354,20 @@ bwfm_usb_attachhook(struct device *self) if (name == NULL) { printf("%s: unknown firmware\n", DEVNAME(sc)); - return; + goto cleanup; } if (loadfirmware(name, &ucode, &size) != 0) { printf("%s: failed loadfirmware of file %s\n", DEVNAME(sc), name); - return; + goto cleanup; } if (bwfm_usb_load_microcode(sc, ucode, size) != 0) { printf("%s: could not load microcode\n", DEVNAME(sc)); free(ucode, M_DEVBUF, size); - return; + goto cleanup; } free(ucode, M_DEVBUF, size); @@ -377,7 +383,7 @@ bwfm_usb_attachhook(struct device *self) if (letoh32(brom.chip) != BRCMF_POSTBOOT_ID) { printf("%s: firmware did not start up\n", DEVNAME(sc)); - return; + goto cleanup; } sc->sc_chip = letoh32(brom.chip); @@ -388,7 +394,7 @@ bwfm_usb_attachhook(struct device *self) if (bwfm_usb_alloc_rx_list(sc) || bwfm_usb_alloc_tx_list(sc)) { printf("%s: cannot allocate rx/tx lists\n", DEVNAME(sc)); - return; + goto cleanup; } for (i = 0; i < BWFM_RX_LIST_COUNT; i++) { @@ -403,7 +409,23 @@ bwfm_usb_attachhook(struct device *self) DEVNAME(sc), usbd_errstr(error)); } - bwfm_attach(&sc->sc_sc); + sc->sc_initialized = 1; + return 0; + +cleanup: + if (sc->sc_rx_pipeh) { + usbd_abort_pipe(sc->sc_rx_pipeh); + usbd_close_pipe(sc->sc_rx_pipeh); + sc->sc_rx_pipeh = NULL; + } + if (sc->sc_tx_pipeh) { + usbd_abort_pipe(sc->sc_tx_pipeh); + usbd_close_pipe(sc->sc_tx_pipeh); + sc->sc_tx_pipeh = NULL; + } + bwfm_usb_free_rx_list(sc); + bwfm_usb_free_tx_list(sc); + return 1; } struct mbuf * |