summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2006-06-16 18:54:10 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2006-06-16 18:54:10 +0000
commited56fec0efca32c4b1ddbb86885419e6dc009121 (patch)
tree6a332a3a319b361efdbb7ef1ad9ec2d7bf21e0bf /sys/dev
parent505cede9df8fa68e16114b3c65f2722f0abfe851 (diff)
- fix reassociations (the firmware was crashing because the configuration
was not properly reset) -- tested by Jean-Baptiste Campesato - load the firmware block by block to avoid allocating a large amount of contiguous memory, which may not be possible at the time the interface is turned up. - rename WPI_CONFIG_ASSOCIATED into WPI_STATE_ASSOCIATED
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/if_wpi.c138
-rw-r--r--sys/dev/pci/if_wpireg.h4
2 files changed, 72 insertions, 70 deletions
diff --git a/sys/dev/pci/if_wpi.c b/sys/dev/pci/if_wpi.c
index 2004d8a51bb..5b251ef1d92 100644
--- a/sys/dev/pci/if_wpi.c
+++ b/sys/dev/pci/if_wpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_wpi.c,v 1.18 2006/06/14 19:31:47 damien Exp $ */
+/* $OpenBSD: if_wpi.c,v 1.19 2006/06/16 18:54:09 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -115,6 +115,8 @@ void wpi_mem_write_region_4(struct wpi_softc *, uint16_t,
const uint32_t *, int);
uint16_t wpi_read_prom_word(struct wpi_softc *, uint32_t);
int wpi_load_microcode(struct wpi_softc *, const char *, int);
+int wpi_load_firmware_block(struct wpi_softc *, uint32_t,
+ bus_dma_segment_t *);
int wpi_load_firmware(struct wpi_softc *, uint32_t, const char *,
int);
void wpi_rx_intr(struct wpi_softc *, struct wpi_rx_desc *,
@@ -795,6 +797,10 @@ wpi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
return 0;
case IEEE80211_S_AUTH:
+ /* reset state to handle reassociations correctly */
+ sc->config.state = 0;
+ sc->config.filter &= ~htole32(WPI_FILTER_BSS);
+
if ((error = wpi_auth(sc)) != 0) {
printf("%s: could not send authentication request\n",
sc->sc_dev.dv_xname);
@@ -812,7 +818,7 @@ wpi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
wpi_enable_tsf(sc, ic->ic_bss);
/* update adapter's configuration */
- sc->config.state = htole16(WPI_CONFIG_ASSOCIATED);
+ sc->config.state = htole16(WPI_STATE_ASSOCIATED);
/* short preamble/slot time are negotiated when associating */
sc->config.flags &= ~htole32(WPI_CONFIG_SHPREAMBLE |
WPI_CONFIG_SHSLOT);
@@ -961,78 +967,27 @@ wpi_load_microcode(struct wpi_softc *sc, const char *ucode, int size)
return 0;
}
-/*
- * The firmware text and data segments are transferred to the NIC using DMA.
- * The driver just copies the firmware into DMA-safe memory and tells the NIC
- * where to find it. Once the NIC has copied the firmware into its internal
- * memory, we can free our local copy in the driver.
- */
int
-wpi_load_firmware(struct wpi_softc *sc, uint32_t target, const char *fw,
- int size)
+wpi_load_firmware_block(struct wpi_softc *sc, uint32_t target,
+ bus_dma_segment_t *seg)
{
- bus_dmamap_t map;
- bus_dma_segment_t seg;
- caddr_t virtaddr;
struct wpi_tx_desc desc;
- int i, ntries, nsegs, error;
-
- /*
- * Allocate DMA-safe memory to store the firmware.
- */
- error = bus_dmamap_create(sc->sc_dmat, size, WPI_MAX_SCATTER,
- WPI_MAX_SEG_LEN, 0, BUS_DMA_NOWAIT, &map);
- if (error != 0) {
- printf("%s: could not create firmware DMA map\n",
- sc->sc_dev.dv_xname);
- goto fail1;
- }
+ int ntries, error = 0;
- error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &seg, 1,
- &nsegs, BUS_DMA_NOWAIT);
- if (error != 0) {
- printf("%s: could not allocate firmware DMA memory\n",
- sc->sc_dev.dv_xname);
- goto fail2;
- }
-
- error = bus_dmamem_map(sc->sc_dmat, &seg, nsegs, size, &virtaddr,
- BUS_DMA_NOWAIT);
- if (error != 0) {
- printf("%s: could not map firmware DMA memory\n",
- sc->sc_dev.dv_xname);
- goto fail3;
- }
-
- error = bus_dmamap_load(sc->sc_dmat, map, virtaddr, size, NULL,
- BUS_DMA_NOWAIT | BUS_DMA_WRITE);
- if (error != 0) {
- printf("%s: could not load firmware DMA map\n",
- sc->sc_dev.dv_xname);
- goto fail4;
- }
-
- /* copy firmware image to DMA-safe memory */
- bcopy(fw, virtaddr, size);
-
- /* make sure the adapter will get up-to-date values */
- bus_dmamap_sync(sc->sc_dmat, map, 0, size, BUS_DMASYNC_PREWRITE);
+ DPRINTFN(2, ("loading firmware block target=%x addr=%x len=%d\n",
+ target, seg->ds_addr, seg->ds_len));
bzero(&desc, sizeof desc);
- desc.flags = htole32(WPI_PAD32(size) << 28 | map->dm_nsegs << 24);
- for (i = 0; i < map->dm_nsegs; i++) {
- desc.segs[i].addr = htole32(map->dm_segs[i].ds_addr);
- desc.segs[i].len = htole32(map->dm_segs[i].ds_len);
- }
+ desc.flags = htole32(WPI_PAD32(seg->ds_len) << 28 | 1 << 24);
+ desc.segs[0].addr = htole32(seg->ds_addr);
+ desc.segs[0].len = htole32(seg->ds_len);
- wpi_mem_lock(sc);
-
- /* tell adapter where to copy image in its internal memory */
+ /* tell adapter where to copy firmware block in its internal memory */
WPI_WRITE(sc, WPI_FW_TARGET, target);
WPI_WRITE(sc, WPI_TX_CONFIG(6), 0);
- /* copy firmware descriptor into NIC memory */
+ /* copy firmware block descriptor into NIC memory */
WPI_WRITE_REGION_4(sc, WPI_TX_DESC(6), (uint32_t *)&desc,
sizeof desc / sizeof (uint32_t));
@@ -1040,26 +995,72 @@ wpi_load_firmware(struct wpi_softc *sc, uint32_t target, const char *fw,
WPI_WRITE(sc, WPI_TX_STATE(6), 0x4001);
WPI_WRITE(sc, WPI_TX_CONFIG(6), 0x80000001);
- /* wait while the adapter is busy copying the firmware */
+ /* wait while the adapter is busy copying the firmware block */
for (ntries = 0; ntries < 100; ntries++) {
if (WPI_READ(sc, WPI_TX_STATUS) & WPI_TX_IDLE(6))
break;
DELAY(1000);
}
if (ntries == 100) {
- printf("%s: timeout transferring firmware\n",
+ printf("%s: timeout transferring firmware block\n",
sc->sc_dev.dv_xname);
error = ETIMEDOUT;
}
WPI_WRITE(sc, WPI_TX_CREDIT(6), 0);
+ return error;
+}
+
+/*
+ * The firmware text and data segments are transferred to the NIC using DMA.
+ * The driver just DMA-maps the firmware and tells the NIC where to find it.
+ * Once the NIC has copied the firmware into its internal memory, we can free
+ * our local copy in the driver.
+ */
+int
+wpi_load_firmware(struct wpi_softc *sc, uint32_t target, const char *fw,
+ int size)
+{
+ bus_dmamap_t map;
+ int i, nsegs, error;
+
+ nsegs = 1 + ((size + PAGE_SIZE - 1) / PAGE_SIZE);
+
+ error = bus_dmamap_create(sc->sc_dmat, size, nsegs, WPI_MAX_SEG_LEN,
+ 0, BUS_DMA_NOWAIT, &map);
+ if (error != 0) {
+ printf("%s: could not create firmware DMA map (error=%d)\n",
+ sc->sc_dev.dv_xname, error);
+ goto fail1;
+ }
+
+ /* XXX: we're discarding a const qualifier here! */
+ error = bus_dmamap_load(sc->sc_dmat, map, (void *)fw, size, NULL,
+ BUS_DMA_NOWAIT | BUS_DMA_WRITE);
+ if (error != 0) {
+ printf("%s: could not load firmware DMA map (error=%d)\n",
+ sc->sc_dev.dv_xname, error);
+ goto fail2;
+ }
+
+ DPRINTF(("load firmware target=%x size=%d nsegs=%d\n", target, size,
+ map->dm_nsegs));
+
+ /* make sure the adapter will get up-to-date values */
+ bus_dmamap_sync(sc->sc_dmat, map, 0, size, BUS_DMASYNC_PREWRITE);
+
+ wpi_mem_lock(sc);
+ for (i = 0; i < map->dm_nsegs; i++) {
+ error = wpi_load_firmware_block(sc, target, &map->dm_segs[i]);
+ if (error != 0)
+ break;
+ target += map->dm_segs[i].ds_len;
+ }
wpi_mem_unlock(sc);
bus_dmamap_sync(sc->sc_dmat, map, 0, size, BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->sc_dmat, map);
-fail4: bus_dmamem_unmap(sc->sc_dmat, virtaddr, size);
-fail3: bus_dmamem_free(sc->sc_dmat, &seg, 1);
fail2: bus_dmamap_destroy(sc->sc_dmat, map);
fail1: return error;
}
@@ -1101,7 +1102,8 @@ wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc,
* to radiotap in monitor mode).
*/
if ((letoh32(tail->flags) & WPI_RX_NOERROR) != WPI_RX_NOERROR) {
- DPRINTF(("rx tail flags error %x\n", letoh32(tail->flags)));
+ DPRINTFN(2, ("rx tail flags error %x\n",
+ letoh32(tail->flags)));
ifp->if_ierrors++;
return;
}
diff --git a/sys/dev/pci/if_wpireg.h b/sys/dev/pci/if_wpireg.h
index e2126f2982d..29a40f534e2 100644
--- a/sys/dev/pci/if_wpireg.h
+++ b/sys/dev/pci/if_wpireg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_wpireg.h,v 1.7 2006/06/05 16:42:21 damien Exp $ */
+/* $OpenBSD: if_wpireg.h,v 1.8 2006/06/16 18:54:09 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -273,7 +273,7 @@ struct wpi_config {
uint8_t ofdm_mask;
uint8_t cck_mask;
uint16_t state;
-#define WPI_CONFIG_ASSOCIATED 4
+#define WPI_STATE_ASSOCIATED 4
uint32_t flags;
#define WPI_CONFIG_24GHZ (1 << 0)