summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/bwfm.c112
-rw-r--r--sys/dev/ic/bwfmvar.h7
-rw-r--r--sys/dev/pci/if_bwfm_pci.c44
-rw-r--r--sys/dev/sdmmc/if_bwfm_sdio.c43
-rw-r--r--sys/dev/usb/if_bwfm_usb.c52
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 *