summaryrefslogtreecommitdiffstats
path: root/sys/dev/wpi
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2008-03-10 23:16:48 +0000
committerthompsa <thompsa@FreeBSD.org>2008-03-10 23:16:48 +0000
commit163aa57ba0984e7e74861db5880e32c2e038bd32 (patch)
treea3d1505e006eab727efde27028f7dcf0903488cc /sys/dev/wpi
parent540fa064d9cfc1fff7b06504893684dc0d934999 (diff)
downloadFreeBSD-src-163aa57ba0984e7e74861db5880e32c2e038bd32.zip
FreeBSD-src-163aa57ba0984e7e74861db5880e32c2e038bd32.tar.gz
Update wpi(4) with stability fixes
- remove second taskqueue - busdma 16k alignment workaround - use busdma instead of external mbuf storage on Rx - locking fixes - net80211 state change fixes - improve scanning reliability - improve radio hw switch interaction - consolidate callouts Parts obtained from: benjsc, sam Tested by: many
Diffstat (limited to 'sys/dev/wpi')
-rw-r--r--sys/dev/wpi/if_wpi.c1035
-rw-r--r--sys/dev/wpi/if_wpireg.h2
-rw-r--r--sys/dev/wpi/if_wpivar.h84
3 files changed, 514 insertions, 607 deletions
diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c
index 315a5c3..c4977d2 100644
--- a/sys/dev/wpi/if_wpi.c
+++ b/sys/dev/wpi/if_wpi.c
@@ -75,15 +75,8 @@ __FBSDID("$FreeBSD$");
#include <sys/linker.h>
#include <sys/firmware.h>
-#if (__FreeBSD_version > 700000)
-#define WPI_CURRENT
-#endif
-
#include <machine/bus.h>
#include <machine/resource.h>
-#ifndef WPI_CURRENT
-#include <machine/clock.h>
-#endif
#include <sys/rman.h>
#include <dev/pci/pcireg.h>
@@ -165,10 +158,6 @@ static void wpi_dma_contig_free(struct wpi_dma_info *);
static void wpi_dma_map_addr(void *, bus_dma_segment_t *, int, int);
static int wpi_alloc_shared(struct wpi_softc *);
static void wpi_free_shared(struct wpi_softc *);
-static struct wpi_rbuf *wpi_alloc_rbuf(struct wpi_softc *);
-static void wpi_free_rbuf(void *, void *);
-static int wpi_alloc_rpool(struct wpi_softc *);
-static void wpi_free_rpool(struct wpi_softc *);
static int wpi_alloc_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
static void wpi_reset_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
static void wpi_free_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
@@ -199,12 +188,8 @@ static void wpi_notif_intr(struct wpi_softc *);
static void wpi_intr(void *);
static void wpi_ops(void *, int);
static uint8_t wpi_plcp_signal(int);
-static int wpi_queue_cmd(struct wpi_softc *, int);
-static void wpi_tick(void *);
-#if 0
-static void wpi_radio_on(void *, int);
-static void wpi_radio_off(void *, int);
-#endif
+static int wpi_queue_cmd(struct wpi_softc *, int, int, int);
+static void wpi_watchdog(void *);
static int wpi_tx_data(struct wpi_softc *, struct mbuf *,
struct ieee80211_node *, int);
static void wpi_start(struct ifnet *);
@@ -213,9 +198,7 @@ static void wpi_scan_end(struct ieee80211com *);
static void wpi_set_channel(struct ieee80211com *);
static void wpi_scan_curchan(struct ieee80211com *, unsigned long);
static void wpi_scan_mindwell(struct ieee80211com *);
-static void wpi_watchdog(struct ifnet *);
static int wpi_ioctl(struct ifnet *, u_long, caddr_t);
-static void wpi_restart(void *, int);
static void wpi_read_eeprom(struct wpi_softc *);
static void wpi_read_eeprom_channels(struct wpi_softc *, int);
static void wpi_read_eeprom_group(struct wpi_softc *, int);
@@ -228,6 +211,7 @@ static void wpi_enable_tsf(struct wpi_softc *, struct ieee80211_node *);
static int wpi_setup_beacon(struct wpi_softc *, struct ieee80211_node *);
#endif
static int wpi_auth(struct wpi_softc *);
+static int wpi_run(struct wpi_softc *);
static int wpi_scan(struct wpi_softc *);
static int wpi_config(struct wpi_softc *);
static void wpi_stop_master(struct wpi_softc *);
@@ -235,6 +219,7 @@ static int wpi_power_up(struct wpi_softc *);
static int wpi_reset(struct wpi_softc *);
static void wpi_hw_config(struct wpi_softc *);
static void wpi_init(void *);
+static void wpi_init_locked(struct wpi_softc *, int);
static void wpi_stop(struct wpi_softc *);
static void wpi_stop_locked(struct wpi_softc *);
static void wpi_iter_func(void *, struct ieee80211_node *);
@@ -316,17 +301,12 @@ wpi_probe(device_t dev)
static int
wpi_load_firmware(struct wpi_softc *sc)
{
-#ifdef WPI_CURRENT
const struct firmware *fp ;
-#else
- struct firmware *fp;
-#endif
struct wpi_dma_info *dma = &sc->fw_dma;
const struct wpi_firmware_hdr *hdr;
const uint8_t *itext, *idata, *rtext, *rdata, *btext;
uint32_t itextsz, idatasz, rtextsz, rdatasz, btextsz;
int error;
- WPI_LOCK_DECL;
DPRINTFN(WPI_DEBUG_FIRMWARE,
("Attempting Loading Firmware from wpi_fw module\n"));
@@ -482,7 +462,6 @@ fail:
static void
wpi_unload_firmware(struct wpi_softc *sc)
{
- WPI_LOCK_DECL;
if (sc->fw_fp) {
WPI_UNLOCK(sc);
@@ -529,22 +508,12 @@ wpi_attach(device_t dev)
taskqueue_thread_enqueue, &sc->sc_tq);
taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
device_get_nameunit(dev));
-
- sc->sc_tq2 = taskqueue_create("wpi_taskq2", M_NOWAIT | M_ZERO,
- taskqueue_thread_enqueue, &sc->sc_tq2);
- taskqueue_start_threads(&sc->sc_tq2, 1, PI_NET, "%s taskq2",
- device_get_nameunit(dev));
#else
#error "Sorry, this driver is not yet ready for FreeBSD < 7.0"
#endif
/* Create the tasks that can be queued */
-#if 0
- TASK_INIT(&sc->sc_radioontask, 0, wpi_radio_on, sc);
- TASK_INIT(&sc->sc_radioofftask, 0, wpi_radio_off, sc);
-#endif
TASK_INIT(&sc->sc_opstask, 0, wpi_ops, sc);
- TASK_INIT(&sc->sc_restarttask, 0, wpi_restart, sc);
WPI_LOCK_INIT(sc);
WPI_CMD_LOCK_INIT(sc);
@@ -615,17 +584,6 @@ wpi_attach(device_t dev)
goto fail;
}
- /*
- * Allocate the receive buffer pool. The recieve buffers are
- * WPI_RBUF_SIZE in length (3k) this is bigger than MCLBYTES
- * hence we can't simply use a cluster and used mapped dma memory
- * instead.
- */
- if ((error = wpi_alloc_rpool(sc)) != 0) {
- device_printf(dev, "could not allocate Rx buffers\n");
- goto fail;
- }
-
/* tx data queues - 4 for QoS purposes */
for (ac = 0; ac < WME_NUM_AC; ac++) {
error = wpi_alloc_tx_ring(sc, &sc->txq[ac], WPI_TX_RING_COUNT, ac);
@@ -744,17 +702,15 @@ wpi_attach(device_t dev)
/*
* Hook our interrupt after all initialization is complete.
*/
- error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET |INTR_MPSAFE ,
-#ifdef WPI_CURRENT
- NULL,
-#endif
- wpi_intr, sc, &sc->sc_ih);
+ error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET |INTR_MPSAFE,
+ NULL, wpi_intr, sc, &sc->sc_ih);
if (error != 0) {
device_printf(dev, "could not set up interrupt\n");
goto fail;
}
- ieee80211_announce(ic);
+ if (bootverbose)
+ ieee80211_announce(ic);
#ifdef XXX_DEBUG
ieee80211_announce_channels(ic);
#endif
@@ -772,7 +728,6 @@ wpi_detach(device_t dev)
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = ic->ic_ifp;
int ac;
- WPI_LOCK_DECL;
if (ifp != NULL) {
wpi_stop(sc);
@@ -789,7 +744,6 @@ wpi_detach(device_t dev)
wpi_free_tx_ring(sc, &sc->cmdq);
wpi_free_rx_ring(sc, &sc->rxq);
- wpi_free_rpool(sc);
wpi_free_shared(sc);
}
@@ -813,7 +767,6 @@ wpi_detach(device_t dev)
if_free(ifp);
taskqueue_free(sc->sc_tq);
- taskqueue_free(sc->sc_tq2);
WPI_LOCK_DESTROY(sc);
WPI_CMD_LOCK_DESTROY(sc);
@@ -832,31 +785,46 @@ wpi_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
*(bus_addr_t *)arg = segs[0].ds_addr;
}
+/*
+ * Allocates a contiguous block of dma memory of the requested size and
+ * alignment. Due to limitations of the FreeBSD dma subsystem as of 20071217,
+ * allocations greater than 4096 may fail. Hence if the requested alignment is
+ * greater we allocate 'alignment' size extra memory and shift the vaddr and
+ * paddr after the dma load. This bypasses the problem at the cost of a little
+ * more memory.
+ */
static int
wpi_dma_contig_alloc(struct wpi_softc *sc, struct wpi_dma_info *dma,
void **kvap, bus_size_t size, bus_size_t alignment, int flags)
{
int error;
- int count = 0;
+ bus_size_t align;
+ bus_size_t reqsize;
DPRINTFN(WPI_DEBUG_DMA,
- ("Size: %zd - alignement %zd\n", size, alignment));
+ ("Size: %zd - alignment %zd\n", size, alignment));
dma->size = size;
dma->tag = NULL;
-again:
- error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), alignment,
+ if (alignment > 4096) {
+ align = PAGE_SIZE;
+ reqsize = size + alignment;
+ } else {
+ align = alignment;
+ reqsize = size;
+ }
+ error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), align,
0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
- NULL, NULL, size,
- 1, size, flags,
+ NULL, NULL, reqsize,
+ 1, reqsize, flags,
NULL, NULL, &dma->tag);
if (error != 0) {
device_printf(sc->sc_dev,
"could not create shared page DMA tag\n");
goto fail;
}
- error = bus_dmamem_alloc(dma->tag, (void **)&dma->vaddr,
+ error = bus_dmamem_alloc(dma->tag, (void **)&dma->vaddr_start,
flags | BUS_DMA_ZERO, &dma->map);
if (error != 0) {
device_printf(sc->sc_dev,
@@ -864,30 +832,33 @@ again:
goto fail;
}
- /**
- * Sadly FreeBSD can't always align on a 16k boundary, hence we give it
- * 10 attempts increasing the size of the allocation by 4k each time.
- * This should eventually align us on a 16k boundary at the cost
- * of chewing up dma memory
+ error = bus_dmamap_load(dma->tag, dma->map, dma->vaddr_start,
+ reqsize, wpi_dma_map_addr, &dma->paddr_start, flags);
+
+ /* Save the original pointers so we can free all the memory */
+ dma->paddr = dma->paddr_start;
+ dma->vaddr = dma->vaddr_start;
+
+ /*
+ * Check the alignment and increment by 4096 until we get the
+ * requested alignment. Fail if can't obtain the alignment
+ * we requested.
*/
- if ((((uintptr_t)dma->vaddr) & (alignment-1)) && count < 10) {
- DPRINTFN(WPI_DEBUG_DMA,
- ("Memory Unaligned, trying again: %d\n", count++));
- wpi_dma_contig_free(dma);
- size += 4096;
- goto again;
- }
-
- DPRINTFN(WPI_DEBUG_DMA,("Memory, allocated & %s Aligned!\n",
- count == 10 ? "FAILED" : ""));
- if (count == 10) {
- device_printf(sc->sc_dev, "Unable to align memory\n");
- error = ENOMEM;
- goto fail;
- }
+ if ((dma->paddr & (alignment -1 )) != 0) {
+ int i;
- error = bus_dmamap_load(dma->tag, dma->map, dma->vaddr,
- size, wpi_dma_map_addr, &dma->paddr, flags);
+ for (i = 0; i < alignment / 4096; i++) {
+ if ((dma->paddr & (alignment - 1 )) == 0)
+ break;
+ dma->paddr += 4096;
+ dma->vaddr += 4096;
+ }
+ if (i == alignment / 4096) {
+ device_printf(sc->sc_dev,
+ "alignment requirement was not satisfied\n");
+ goto fail;
+ }
+ }
if (error != 0) {
device_printf(sc->sc_dev,
@@ -910,12 +881,12 @@ wpi_dma_contig_free(struct wpi_dma_info *dma)
{
if (dma->tag) {
if (dma->map != NULL) {
- if (dma->paddr == 0) {
+ if (dma->paddr_start != 0) {
bus_dmamap_sync(dma->tag, dma->map,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(dma->tag, dma->map);
}
- bus_dmamem_free(dma->tag, &dma->vaddr, dma->map);
+ bus_dmamem_free(dma->tag, &dma->vaddr_start, dma->map);
}
bus_dma_tag_destroy(dma->tag);
}
@@ -948,134 +919,79 @@ wpi_free_shared(struct wpi_softc *sc)
wpi_dma_contig_free(&sc->shared_dma);
}
-struct wpi_rbuf *
-wpi_alloc_rbuf(struct wpi_softc *sc)
-{
- struct wpi_rbuf *rbuf;
-
- rbuf = SLIST_FIRST(&sc->rxq.freelist);
- if (rbuf == NULL)
- return NULL;
- SLIST_REMOVE_HEAD(&sc->rxq.freelist, next);
- return rbuf;
-}
-
-/*
- * This is called automatically by the network stack when the mbuf to which our
- * Rx buffer is attached is freed.
- */
-static void
-wpi_free_rbuf(void *buf, void *arg)
-{
- struct wpi_rbuf *rbuf = arg;
- struct wpi_softc *sc = rbuf->sc;
- WPI_LOCK_DECL;
-
- WPI_LOCK(sc);
-
- /* put the buffer back in the free list */
- SLIST_INSERT_HEAD(&sc->rxq.freelist, rbuf, next);
-
- WPI_UNLOCK(sc);
-}
-
-static int
-wpi_alloc_rpool(struct wpi_softc *sc)
-{
- struct wpi_rx_ring *ring = &sc->rxq;
- struct wpi_rbuf *rbuf;
- int i, error;
-
- /* allocate a big chunk of DMA'able memory.. */
- error = wpi_dma_contig_alloc(sc, &ring->buf_dma, NULL,
- WPI_RBUF_COUNT * WPI_RBUF_SIZE, PAGE_SIZE, BUS_DMA_NOWAIT);
- if (error != 0) {
- device_printf(sc->sc_dev,
- "could not allocate Rx buffers DMA memory\n");
- return error;
- }
-
- /* ..and split it into 3KB chunks */
- SLIST_INIT(&ring->freelist);
- for (i = 0; i < WPI_RBUF_COUNT; i++) {
- rbuf = &ring->rbuf[i];
-
- rbuf->sc = sc; /* backpointer for callbacks */
- rbuf->vaddr = ring->buf_dma.vaddr + i * WPI_RBUF_SIZE;
- rbuf->paddr = ring->buf_dma.paddr + i * WPI_RBUF_SIZE;
-
- SLIST_INSERT_HEAD(&ring->freelist, rbuf, next);
- }
- return 0;
-}
-
-static void
-wpi_free_rpool(struct wpi_softc *sc)
-{
- wpi_dma_contig_free(&sc->rxq.buf_dma);
-}
-
static int
wpi_alloc_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring)
{
- struct wpi_rx_data *data;
- struct wpi_rbuf *rbuf;
int i, error;
ring->cur = 0;
error = wpi_dma_contig_alloc(sc, &ring->desc_dma,
- (void **)&ring->desc, WPI_RX_RING_COUNT * sizeof (uint32_t),
- WPI_RING_DMA_ALIGN, BUS_DMA_NOWAIT);
+ (void **)&ring->desc, WPI_RX_RING_COUNT * sizeof (uint32_t),
+ WPI_RING_DMA_ALIGN, BUS_DMA_NOWAIT);
if (error != 0) {
- device_printf(sc->sc_dev,
- "could not allocate rx ring DMA memory\n");
- goto fail;
+ device_printf(sc->sc_dev,
+ "%s: could not allocate rx ring DMA memory, error %d\n",
+ __func__, error);
+ goto fail;
}
+ error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR, NULL, NULL, MJUMPAGESIZE, 1,
+ MJUMPAGESIZE, BUS_DMA_NOWAIT, NULL, NULL, &ring->data_dmat);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: bus_dma_tag_create_failed, error %d\n",
+ __func__, error);
+ goto fail;
+ }
+
/*
- * Allocate Rx buffers.
+ * Setup Rx buffers.
*/
for (i = 0; i < WPI_RX_RING_COUNT; i++) {
- data = &ring->data[i];
+ struct wpi_rx_data *data = &ring->data[i];
+ struct mbuf *m;
+ bus_addr_t paddr;
- data->m = m_gethdr(M_DONTWAIT, MT_DATA);
- if (data->m == NULL) {
+ error = bus_dmamap_create(ring->data_dmat, 0, &data->map);
+ if (error != 0) {
device_printf(sc->sc_dev,
- "could not allocate rx mbuf\n");
- error = ENOBUFS;
+ "%s: bus_dmamap_create failed, error %d\n",
+ __func__, error);
goto fail;
}
-
- if ((rbuf = wpi_alloc_rbuf(sc)) == NULL) {
- m_freem(data->m);
- data->m = NULL;
+ m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
+ if (m == NULL) {
device_printf(sc->sc_dev,
- "could not allocate rx buffer\n");
- error = ENOBUFS;
+ "%s: could not allocate rx mbuf\n", __func__);
+ error = ENOMEM;
goto fail;
}
-
- /* attach RxBuffer to mbuf */
- MEXTADD(data->m, rbuf->vaddr, WPI_RBUF_SIZE,wpi_free_rbuf,
- rbuf->vaddr, rbuf, 0, EXT_NET_DRV);
-
- if ((data->m->m_flags & M_EXT) == 0) {
- m_freem(data->m);
- data->m = NULL;
- error = ENOBUFS;
+ /* map page */
+ error = bus_dmamap_load(ring->data_dmat, data->map,
+ mtod(m, caddr_t), MJUMPAGESIZE,
+ wpi_dma_map_addr, &paddr, BUS_DMA_NOWAIT);
+ if (error != 0 && error != EFBIG) {
+ device_printf(sc->sc_dev,
+ "%s: bus_dmamap_load failed, error %d\n",
+ __func__, error);
+ m_freem(m);
+ error = ENOMEM; /* XXX unique code */
goto fail;
}
- ring->desc[i] = htole32(rbuf->paddr);
- }
+ bus_dmamap_sync(ring->data_dmat, data->map,
+ BUS_DMASYNC_PREWRITE);
+ data->m = m;
+ ring->desc[i] = htole32(paddr);
+ }
bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
BUS_DMASYNC_PREWRITE);
-
return 0;
-
fail:
wpi_free_rx_ring(sc, ring);
return error;
@@ -1099,7 +1015,7 @@ wpi_reset_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring)
wpi_mem_unlock(sc);
#ifdef WPI_DEBUG
- if (ntries == 100 && wpi_debug > 0)
+ if (ntries == 100)
device_printf(sc->sc_dev, "timeout resetting Rx ring\n");
#endif
@@ -1113,12 +1029,9 @@ wpi_free_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring)
wpi_dma_contig_free(&ring->desc_dma);
- for (i = 0; i < WPI_RX_RING_COUNT; i++) {
- if (ring->data[i].m != NULL) {
+ for (i = 0; i < WPI_RX_RING_COUNT; i++)
+ if (ring->data[i].m != NULL)
m_freem(ring->data[i].m);
- ring->data[i].m = NULL;
- }
- }
}
static int
@@ -1188,7 +1101,8 @@ wpi_alloc_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring, int count,
return 0;
-fail: wpi_free_tx_ring(sc, ring);
+fail:
+ wpi_free_tx_ring(sc, ring);
return error;
}
@@ -1207,10 +1121,9 @@ wpi_reset_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring)
DELAY(10);
}
#ifdef WPI_DEBUG
- if (ntries == 100 && wpi_debug > 0) {
+ if (ntries == 100)
device_printf(sc->sc_dev, "timeout resetting Tx ring %d\n",
ring->qid);
- }
#endif
wpi_mem_unlock(sc);
@@ -1260,7 +1173,6 @@ static int
wpi_shutdown(device_t dev)
{
struct wpi_softc *sc = device_get_softc(dev);
- WPI_LOCK_DECL;
WPI_LOCK(sc);
wpi_stop_locked(sc);
@@ -1329,18 +1241,15 @@ wpi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
{
struct ifnet *ifp = ic->ic_ifp;
struct wpi_softc *sc = ifp->if_softc;
- struct ieee80211_node *ni;
- int error;
- WPI_LOCK_DECL;
- WPI_LOCK(sc);
- callout_stop(&sc->calib_to);
- WPI_UNLOCK(sc);
+ DPRINTF(("%s: %s -> %s\n", __func__,
+ ieee80211_state_name[ic->ic_state],
+ ieee80211_state_name[nstate]));
switch (nstate) {
case IEEE80211_S_SCAN:
- DPRINTF(("NEWSTATE:SCAN\n"));
- /* Scanning is handled in net80211 via the scan_start,
+ /*
+ * Scanning is handled in net80211 via the scan_start,
* scan_end, scan_curchan functions. Hence all we do when
* changing to the SCAN state is update the leds
*/
@@ -1349,93 +1258,27 @@ wpi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
wpi_set_led(sc, WPI_LED_LINK, 20, 2);
break;
- case IEEE80211_S_ASSOC:
- DPRINTF(("NEWSTATE:ASSOC\n"));
- if (ic->ic_state != IEEE80211_S_RUN)
- break;
- /* FALLTHROUGH */
-
case IEEE80211_S_AUTH:
- DPRINTF(("NEWSTATE:AUTH\n"));
- sc->flags |= WPI_FLAG_AUTH;
- sc->config.associd = 0;
- sc->config.filter &= ~htole32(WPI_FILTER_BSS);
- wpi_queue_cmd(sc,WPI_AUTH);
- DPRINTF(("END AUTH\n"));
- break;
+ /* Delay the auth transition until we can update the firmware */
+ return wpi_queue_cmd(sc, WPI_AUTH, arg, WPI_QUEUE_NORMAL);
case IEEE80211_S_RUN:
- DPRINTF(("NEWSTATE:RUN\n"));
if (ic->ic_opmode == IEEE80211_M_MONITOR) {
/* link LED blinks while monitoring */
wpi_set_led(sc, WPI_LED_LINK, 5, 5);
break;
}
-
-#if 0
- if (ic->ic_opmode != IEEE80211_M_STA) {
- (void) wpi_auth(sc); /* XXX */
- wpi_setup_beacon(sc, ic->ic_bss);
- }
-#endif
-
- ni = ic->ic_bss;
- wpi_enable_tsf(sc, ni);
-
- /* update adapter's configuration */
- sc->config.associd = htole16(ni->ni_associd & ~0xc000);
- /* short preamble/slot time are negotiated when associating */
- sc->config.flags &= ~htole32(WPI_CONFIG_SHPREAMBLE |
- WPI_CONFIG_SHSLOT);
- if (ic->ic_flags & IEEE80211_F_SHSLOT)
- sc->config.flags |= htole32(WPI_CONFIG_SHSLOT);
- if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
- sc->config.flags |= htole32(WPI_CONFIG_SHPREAMBLE);
- sc->config.filter |= htole32(WPI_FILTER_BSS);
-#if 0
- if (ic->ic_opmode != IEEE80211_M_STA)
- sc->config.filter |= htole32(WPI_FILTER_BEACON);
-#endif
-
-/* XXX put somewhere HC_QOS_SUPPORT_ASSOC + HC_IBSS_START */
-
- DPRINTF(("config chan %d flags %x\n", sc->config.chan,
- sc->config.flags));
- error = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->config,
- sizeof (struct wpi_config), 1);
- if (error != 0) {
- device_printf(sc->sc_dev,
- "could not update configuration\n");
- return error;
- }
-
- if ((error = wpi_set_txpower(sc, ic->ic_bss->ni_chan, 1)) != 0) {
- device_printf(sc->sc_dev,
- "could set txpower\n");
- return error;
- }
-
- if (ic->ic_opmode == IEEE80211_M_STA) {
- /* fake a join to init the tx rate */
- wpi_newassoc(ic->ic_bss, 1);
- }
-
- /* start automatic rate control timer */
- callout_reset(&sc->calib_to, hz/2, wpi_calib_timeout, sc);
-
- /* link LED always on while associated */
- wpi_set_led(sc, WPI_LED_LINK, 0, 1);
- break;
-
- case IEEE80211_S_INIT:
- DPRINTF(("NEWSTATE:INIT\n"));
+ if (ic->ic_state != IEEE80211_S_RUN)
+ /* set the association id first */
+ return wpi_queue_cmd(sc, WPI_RUN, arg,
+ WPI_QUEUE_NORMAL);
break;
default:
break;
}
- return (*sc->sc_newstate)(ic, nstate, arg);
+ return sc->sc_newstate(ic, nstate, arg);
}
/*
@@ -1594,11 +1437,10 @@ wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc,
struct wpi_rx_stat *stat;
struct wpi_rx_head *head;
struct wpi_rx_tail *tail;
- struct wpi_rbuf *rbuf;
- struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m, *mnew;
- WPI_LOCK_DECL;
+ bus_addr_t paddr;
+ int error;
stat = (struct wpi_rx_stat *)(desc + 1);
@@ -1616,43 +1458,39 @@ wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc,
le16toh(head->len), (int8_t)stat->rssi, head->rate, head->chan,
(uintmax_t)le64toh(tail->tstamp)));
- m = data->m;
+ /* XXX don't need mbuf, just dma buffer */
+ mnew = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
+ if (mnew == NULL) {
+ DPRINTFN(WPI_DEBUG_RX, ("%s: no mbuf to restock ring\n",
+ __func__));
+ ic->ic_stats.is_rx_nobuf++;
+ ifp->if_ierrors++;
+ return;
+ }
+ error = bus_dmamap_load(ring->data_dmat, data->map,
+ mtod(mnew, caddr_t), MJUMPAGESIZE,
+ wpi_dma_map_addr, &paddr, BUS_DMA_NOWAIT);
+ if (error != 0 && error != EFBIG) {
+ device_printf(sc->sc_dev,
+ "%s: bus_dmamap_load failed, error %d\n", __func__, error);
+ m_freem(mnew);
+ ic->ic_stats.is_rx_nobuf++; /* XXX need stat */
+ ifp->if_ierrors++;
+ return;
+ }
+ bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE);
- /* finalize mbuf */
+ /* finalize mbuf and swap in new one */
+ m = data->m;
m->m_pkthdr.rcvif = ifp;
m->m_data = (caddr_t)(head + 1);
m->m_pkthdr.len = m->m_len = le16toh(head->len);
- if ((rbuf = SLIST_FIRST(&sc->rxq.freelist)) != NULL) {
- mnew = m_gethdr(M_DONTWAIT,MT_DATA);
- if (mnew == NULL) {
- ifp->if_ierrors++;
- return;
- }
+ data->m = mnew;
+ /* update Rx descriptor */
+ ring->desc[ring->cur] = htole32(paddr);
- /* attach Rx buffer to mbuf */
- MEXTADD(mnew, rbuf->vaddr, WPI_RBUF_SIZE, wpi_free_rbuf,
- rbuf->vaddr, rbuf, 0, EXT_NET_DRV);
- SLIST_REMOVE_HEAD(&sc->rxq.freelist, next);
- data->m = mnew;
-
- /* update Rx descriptor */
- ring->desc[ring->cur] = htole32(rbuf->paddr);
- } else {
- /* no free rbufs, copy frame */
- m = m_dup(m, M_DONTWAIT);
- if (m == NULL) {
- /* no free mbufs either, drop frame */
- ifp->if_ierrors++;
- return;
- }
- }
-
-#ifndef WPI_CURRENT
- if (sc->sc_drvbpf != NULL) {
-#else
if (bpf_peers_present(sc->sc_drvbpf)) {
-#endif
struct wpi_rx_radiotap_header *tap = &sc->sc_rxtap;
tap->wr_flags = 0;
@@ -1688,12 +1526,11 @@ wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc,
bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
}
- wh = mtod(m, struct ieee80211_frame *);
WPI_UNLOCK(sc);
/* XXX frame length > sizeof(struct ieee80211_frame_min)? */
/* grab a reference to the source node */
- ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
+ ni = ieee80211_find_rxnode(ic, mtod(m, struct ieee80211_frame_min *));
/* send the frame to the 802.11 layer */
ieee80211_input(ic, m, ni, stat->rssi, 0, 0);
@@ -1746,8 +1583,6 @@ wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc)
ring->queued--;
sc->sc_tx_timer = 0;
- sc->watchdog_cnt = 0;
- callout_stop(&sc->watchdog_to);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
wpi_start(ifp);
}
@@ -1783,6 +1618,7 @@ static void
wpi_notif_intr(struct wpi_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = ic->ic_ifp;
struct wpi_rx_desc *desc;
struct wpi_rx_data *data;
uint32_t hw;
@@ -1842,9 +1678,10 @@ wpi_notif_intr(struct wpi_softc *sc)
device_printf(sc->sc_dev,
"Radio transmitter is switched off\n");
sc->flags |= WPI_FLAG_HW_RADIO_OFF;
- break;
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ /* Disable firmware commands */
+ WPI_WRITE(sc, WPI_UCODE_SET, WPI_DISABLE_CMD);
}
- sc->flags &= ~WPI_FLAG_HW_RADIO_OFF;
break;
}
case WPI_START_SCAN:
@@ -1855,9 +1692,6 @@ wpi_notif_intr(struct wpi_softc *sc)
DPRINTFN(WPI_DEBUG_SCANNING,
("scanning channel %d status %x\n",
scan->chan, le32toh(scan->status)));
-
- /* fix current channel */
- ic->ic_bss->ni_chan = &ic->ic_channels[scan->chan];
break;
}
case WPI_STOP_SCAN:
@@ -1869,7 +1703,8 @@ wpi_notif_intr(struct wpi_softc *sc)
("scan finished nchan=%d status=%d chan=%d\n",
scan->nchan, scan->status, scan->chan));
- wpi_queue_cmd(sc, WPI_SCAN_NEXT);
+ sc->sc_scan_timer = 0;
+ ieee80211_scan_next(ic);
break;
}
case WPI_MISSED_BEACON:
@@ -1877,12 +1712,14 @@ wpi_notif_intr(struct wpi_softc *sc)
struct wpi_missed_beacon *beacon =
(struct wpi_missed_beacon *)(desc + 1);
- if (le32toh(beacon->consecutive) >= ic->ic_bmissthreshold) {
+ if (le32toh(beacon->consecutive) >=
+ ic->ic_bmissthreshold) {
DPRINTF(("Beacon miss: %u >= %u\n",
le32toh(beacon->consecutive),
ic->ic_bmissthreshold));
ieee80211_beacon_miss(ic);
}
+ break;
}
}
@@ -1892,7 +1729,6 @@ wpi_notif_intr(struct wpi_softc *sc)
/* tell the firmware what we have processed */
hw = (hw == 0) ? WPI_RX_RING_COUNT - 1 : hw - 1;
WPI_WRITE(sc, WPI_RX_WIDX, hw & ~7);
-
}
static void
@@ -1900,7 +1736,6 @@ wpi_intr(void *arg)
{
struct wpi_softc *sc = arg;
uint32_t r;
- WPI_LOCK_DECL;
WPI_LOCK(sc);
@@ -1919,7 +1754,7 @@ wpi_intr(void *arg)
device_printf(sc->sc_dev, "fatal firmware error\n");
DPRINTFN(6,("(%s)\n", (r & WPI_SW_ERROR) ? "(Software Error)" :
"(Hardware Error)"));
- taskqueue_enqueue(sc->sc_tq2, &sc->sc_restarttask);
+ wpi_queue_cmd(sc, WPI_RESTART, 0, WPI_QUEUE_CLEAR);
sc->flags &= ~WPI_FLAG_BUSY;
WPI_UNLOCK(sc);
return;
@@ -1977,6 +1812,7 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
int ac)
{
struct ieee80211com *ic = &sc->sc_ic;
+ const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams;
struct wpi_tx_ring *ring = &sc->txq[ac];
struct wpi_tx_desc *desc;
struct wpi_tx_data *data;
@@ -1984,9 +1820,8 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
struct wpi_cmd_data *tx;
struct ieee80211_frame *wh;
struct ieee80211_key *k;
- const struct chanAccParams *cap;
struct mbuf *mnew;
- int i, error, nsegs, rate, hdrlen, noack = 0;
+ int i, error, nsegs, rate, hdrlen, ismcast;
bus_dma_segment_t segs[WPI_MAX_SCATTER];
desc = &ring->desc[ring->cur];
@@ -1994,60 +1829,19 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
wh = mtod(m0, struct ieee80211_frame *);
- if (IEEE80211_QOS_HAS_SEQ(wh)) {
- hdrlen = sizeof (struct ieee80211_qosframe);
- cap = &ic->ic_wme.wme_chanParams;
- noack = cap->cap_wmeParams[ac].wmep_noackPolicy;
- } else
- hdrlen = sizeof (struct ieee80211_frame);
+ hdrlen = ieee80211_hdrsize(wh);
+ ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
- if ((k = ieee80211_crypto_encap(ic, ni, m0)) == NULL) {
+ k = ieee80211_crypto_encap(ic, ni, m0);
+ if (k == NULL) {
m_freem(m0);
return ENOBUFS;
}
-
/* packet header may have moved, reset our local pointer */
wh = mtod(m0, struct ieee80211_frame *);
}
- /* pickup a rate */
- if (IEEE80211_IS_MULTICAST(wh->i_addr1)||
- ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
- IEEE80211_FC0_TYPE_MGT)) {
- /*
- * mgmt/multicast frames are sent at the lowest available
- * bit-rate
- */
- rate = ni->ni_rates.rs_rates[0];
- } else {
- if (ic->ic_fixed_rate != -1) {
- rate = ic->ic_sup_rates[ic->ic_curmode].
- rs_rates[ic->ic_fixed_rate];
- } else
- rate = ni->ni_rates.rs_rates[ni->ni_txrate];
- }
- rate &= IEEE80211_RATE_VAL;
-
-#ifndef WPI_CURRENT
- if (sc->sc_drvbpf != NULL) {
-#else
- if (bpf_peers_present(sc->sc_drvbpf)) {
-#endif
-
- struct wpi_tx_radiotap_header *tap = &sc->sc_txtap;
-
- tap->wt_flags = 0;
- tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq);
- tap->wt_chan_flags = htole16(ni->ni_chan->ic_flags);
- tap->wt_rate = rate;
- tap->wt_hwqueue = ac;
- if (wh->i_fc[1] & IEEE80211_FC1_WEP)
- tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
-
- bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0);
- }
-
cmd = &ring->cmd[ring->cur];
cmd->code = WPI_CMD_TX_DATA;
cmd->flags = 0;
@@ -2055,45 +1849,62 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
cmd->idx = ring->cur;
tx = (struct wpi_cmd_data *)cmd->data;
- tx->flags = 0;
+ tx->flags = htole32(WPI_TX_AUTO_SEQ);
+ tx->timeout= htole16(0);
+ tx->ofdm_mask = 0xff;
+ tx->cck_mask = 0x0f;
+ tx->lifetime = htole32(WPI_LIFETIME_INFINITE);
+ tx->id = ismcast ? WPI_ID_BROADCAST : WPI_ID_BSS;
+ tx->len = htole16(m0->m_pkthdr.len);
- if (!noack && !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
- tx->flags |= htole32(WPI_TX_NEED_ACK);
- } else if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) {
- tx->flags |= htole32(WPI_TX_NEED_RTS | WPI_TX_FULL_TXOP);
+ if (ismcast) {
+ if ((ni->ni_flags & IEEE80211_NODE_QOS) == 0 ||
+ !cap->cap_wmeParams[ac].wmep_noackPolicy)
+ tx->flags |= htole32(WPI_TX_NEED_ACK);
+ if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) {
+ tx->flags |= htole32(WPI_TX_NEED_RTS|WPI_TX_FULL_TXOP);
+ tx->rts_ntries = 7;
+ }
}
- tx->flags |= htole32(WPI_TX_AUTO_SEQ);
-
- tx->id = IEEE80211_IS_MULTICAST(wh->i_addr1) ? WPI_ID_BROADCAST :
- WPI_ID_BSS;
-
- if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
- IEEE80211_FC0_TYPE_MGT) {
+ /* pick a rate */
+ if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_MASK) {
uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
/* tell h/w to set timestamp in probe responses */
if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
- tx->flags |= htole32(WPI_TX_INSERT_TSTAMP);
+ tx->flags |= htole32(WPI_TX_INSERT_TSTAMP);
if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ ||
- subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ)
+ subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ)
tx->timeout = htole16(3);
else
tx->timeout = htole16(2);
- } else
- tx->timeout = htole16(0);
+ rate = ni->ni_rates.rs_rates[0] & IEEE80211_RATE_VAL;
+ } else if (ismcast) {
+ rate = ic->ic_mcast_rate;
+ } else if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
+ rate = ic->ic_fixed_rate;
+ } else {
+ rate = ni->ni_rates.rs_rates[ni->ni_txrate];
+ rate &= IEEE80211_RATE_VAL;
+ }
tx->rate = wpi_plcp_signal(rate);
/* be very persistant at sending frames out */
- tx->rts_ntries = 7;
- tx->data_ntries = 15;
-
- tx->ofdm_mask = 0xff;
- tx->cck_mask = 0x0f;
- tx->lifetime = htole32(WPI_LIFETIME_INFINITE);
+ tx->data_ntries = 15; /* XXX Way too high */
- tx->len = htole16(m0->m_pkthdr.len);
+ if (bpf_peers_present(sc->sc_drvbpf)) {
+ struct wpi_tx_radiotap_header *tap = &sc->sc_txtap;
+ tap->wt_flags = 0;
+ tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq);
+ tap->wt_chan_flags = htole16(ni->ni_chan->ic_flags);
+ tap->wt_rate = rate;
+ tap->wt_hwqueue = ac;
+ if (wh->i_fc[1] & IEEE80211_FC1_WEP)
+ tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
+ bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0);
+ }
/* save and trim IEEE802.11 header */
m_copydata(m0, 0, hdrlen, (caddr_t)&tx->wh);
@@ -2169,16 +1980,18 @@ wpi_start(struct ifnet *ifp)
struct ieee80211_node *ni;
struct ether_header *eh;
struct mbuf *m0;
- int ac;
- WPI_LOCK_DECL;
+ int ac, waslocked;
- WPI_LOCK(sc);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ return;
+
+ waslocked = WPI_LOCK_OWNED(sc);
+ if (!waslocked)
+ WPI_LOCK(sc);
for (;;) {
- IF_POLL(&ic->ic_mgtq, m0);
+ IF_DEQUEUE(&ic->ic_mgtq, m0);
if (m0 != NULL) {
- IF_DEQUEUE(&ic->ic_mgtq, m0);
-
ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
m0->m_pkthdr.rcvif = NULL;
@@ -2196,7 +2009,7 @@ wpi_start(struct ifnet *ifp)
if (ic->ic_state != IEEE80211_S_RUN)
break;
- IFQ_POLL(&ifp->if_snd, m0);
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
if (m0 == NULL)
break;
@@ -2227,10 +2040,7 @@ wpi_start(struct ifnet *ifp)
continue;
}
- /* no QoS encapsulation for EAPOL frames */
- ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?
- M_WME_GETAC(m0) : WME_AC_BE;
-
+ ac = M_WME_GETAC(m0);
if (sc->txq[ac].queued > sc->txq[ac].count - 8) {
/* there is no place left in this ring */
IFQ_DRV_PREPEND(&ifp->if_snd, m0);
@@ -2238,7 +2048,6 @@ wpi_start(struct ifnet *ifp)
break;
}
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
BPF_MTAP(ifp, m0);
m0 = ieee80211_encap(ic, m0, ni);
@@ -2248,11 +2057,7 @@ wpi_start(struct ifnet *ifp)
continue;
}
-#ifndef WPI_CURRENT
- if (ic->ic_rawbpf != NULL)
-#else
if (bpf_peers_present(ic->ic_rawbpf))
-#endif
bpf_mtap(ic->ic_rawbpf, m0);
if (wpi_tx_data(sc, m0, ni, ac) != 0) {
@@ -2263,33 +2068,11 @@ wpi_start(struct ifnet *ifp)
}
sc->sc_tx_timer = 5;
- sc->watchdog_cnt = 5;
ic->ic_lastdata = ticks;
}
- WPI_UNLOCK(sc);
-}
-
-static void
-wpi_watchdog(struct ifnet *ifp)
-{
- struct wpi_softc *sc = ifp->if_softc;
- WPI_LOCK_DECL;
-
- WPI_LOCK(sc);
-
- DPRINTFN(WPI_DEBUG_WATCHDOG, ("watchdog_cnt: %d\n", sc->watchdog_cnt));
-
- if (sc->watchdog_cnt == 0 || --sc->watchdog_cnt)
- goto done;
-
- if (--sc->sc_tx_timer != 0) {
- device_printf(sc->sc_dev,"device timeout\n");
- ifp->if_oerrors++;
- taskqueue_enqueue(sc->sc_tq2, &sc->sc_restarttask);
- }
-done:
- WPI_UNLOCK(sc);
+ if (!waslocked)
+ WPI_UNLOCK(sc);
}
static int
@@ -2298,7 +2081,6 @@ wpi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
struct wpi_softc *sc = ifp->if_softc;
struct ieee80211com *ic = &sc->sc_ic;
int error = 0;
- WPI_LOCK_DECL;
WPI_LOCK(sc);
@@ -2306,8 +2088,9 @@ wpi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCSIFFLAGS:
if ((ifp->if_flags & IFF_UP)) {
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
- wpi_init(sc);
- } else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ wpi_init_locked(sc, 0);
+ } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) ||
+ (sc->flags & WPI_FLAG_HW_RADIO_OFF))
wpi_stop_locked(sc);
break;
default:
@@ -2320,7 +2103,7 @@ wpi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
if ((ifp->if_flags & IFF_UP) &&
(ifp->if_drv_flags & IFF_DRV_RUNNING) &&
ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
- wpi_init(sc);
+ wpi_init_locked(sc, 0);
error = 0;
}
@@ -2619,7 +2402,10 @@ wpi_auth(struct wpi_softc *sc)
struct wpi_node_info node;
int error;
+
/* update adapter's configuration */
+ sc->config.associd = 0;
+ sc->config.filter &= ~htole32(WPI_FILTER_BSS);
IEEE80211_ADDR_COPY(sc->config.bssid, ni->ni_bssid);
sc->config.chan = ieee80211_chan2ieee(ic, ni->ni_chan);
if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {
@@ -2664,14 +2450,62 @@ wpi_auth(struct wpi_softc *sc)
node.action = htole32(WPI_ACTION_SET_RATE);
node.antenna = WPI_ANTENNA_BOTH;
error = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 1);
- if (error != 0) {
+ if (error != 0)
device_printf(sc->sc_dev, "could not add BSS node\n");
+
+ return (error);
+}
+
+static int
+wpi_run(struct wpi_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211_node *ni = ic->ic_bss;
+ int error;
+
+ ni = ic->ic_bss;
+ wpi_enable_tsf(sc, ni);
+
+ /* update adapter's configuration */
+ sc->config.associd = htole16(ni->ni_associd & ~0xc000);
+ /* short preamble/slot time are negotiated when associating */
+ sc->config.flags &= ~htole32(WPI_CONFIG_SHPREAMBLE |
+ WPI_CONFIG_SHSLOT);
+ if (ic->ic_flags & IEEE80211_F_SHSLOT)
+ sc->config.flags |= htole32(WPI_CONFIG_SHSLOT);
+ if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
+ sc->config.flags |= htole32(WPI_CONFIG_SHPREAMBLE);
+ sc->config.filter |= htole32(WPI_FILTER_BSS);
+
+ /* XXX put somewhere HC_QOS_SUPPORT_ASSOC + HC_IBSS_START */
+
+ DPRINTF(("config chan %d flags %x\n", sc->config.chan,
+ sc->config.flags));
+ error = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->config, sizeof (struct
+ wpi_config), 1);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could not update configuration\n");
return error;
}
- sc->flags &= ~WPI_FLAG_AUTH;
+ error = wpi_set_txpower(sc, ic->ic_bsschan, 1);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could set txpower\n");
+ return error;
+ }
- return 0;
+ if (ic->ic_opmode == IEEE80211_M_STA) {
+ /* fake a join to init the tx rate */
+ wpi_newassoc(ic->ic_bss, 1);
+ }
+
+ /* link LED always on while associated */
+ wpi_set_led(sc, WPI_LED_LINK, 0, 1);
+
+ /* start automatic rate control timer */
+ callout_reset(&sc->calib_to, hz/2, wpi_calib_timeout, sc);
+
+ return (error);
}
/*
@@ -2686,6 +2520,7 @@ static int
wpi_scan(struct wpi_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
struct wpi_tx_ring *ring = &sc->cmdq;
struct wpi_tx_desc *desc;
struct wpi_tx_data *data;
@@ -2697,7 +2532,7 @@ wpi_scan(struct wpi_softc *sc)
struct ieee80211_channel *c;
enum ieee80211_phymode mode;
uint8_t *frm;
- int nrates, pktlen, error;
+ int nrates, pktlen, error, i, nssid;
bus_addr_t physaddr;
struct ifnet *ifp = ic->ic_ifp;
@@ -2744,17 +2579,21 @@ wpi_scan(struct wpi_softc *sc)
hdr->tx.flags = htole32(WPI_TX_AUTO_SEQ);
/*XXX Need to cater for multiple essids */
- memset(&hdr->scan_essids[0], 0, 4 * sizeof(hdr->scan_essids[0]));
- hdr->scan_essids[0].id = IEEE80211_ELEMID_SSID;
- hdr->scan_essids[0].esslen = ic->ic_des_ssid[0].len;
- memcpy(hdr->scan_essids[0].essid, ic->ic_des_ssid[0].ssid,
- ic->ic_des_ssid[0].len);
-
- if (wpi_debug & WPI_DEBUG_SCANNING) {
- printf("Scanning Essid: ");
- ieee80211_print_essid(ic->ic_des_ssid[0].ssid,
- ic->ic_des_ssid[0].len);
- printf("\n");
+ memset(&hdr->scan_essids, 0, sizeof(hdr->scan_essids));
+ nssid = MIN(ss->ss_nssid, WPI_SCAN_MAX_ESSIDS);
+ for (i = 0; i < nssid; i++ ){
+ hdr->scan_essids[i].id = IEEE80211_ELEMID_SSID;
+ hdr->scan_essids[i].esslen = MIN(ss->ss_ssid[i].len, 32);
+ memcpy(hdr->scan_essids[i].essid, ss->ss_ssid[i].ssid,
+ hdr->scan_essids[i].esslen);
+#ifdef WPI_DEBUG
+ if (wpi_debug & WPI_DEBUG_SCANNING) {
+ printf("Scanning Essid: ");
+ ieee80211_print_essid(ic->ic_des_ssid[i].ssid,
+ ic->ic_des_ssid[i].len);
+ printf("\n");
+ }
+#endif
}
/*
@@ -2896,6 +2735,7 @@ wpi_scan(struct wpi_softc *sc)
ring->cur = (ring->cur + 1) % WPI_CMD_RING_COUNT;
WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur);
+ sc->sc_scan_timer = 5;
return 0; /* will be notified async. of failure/success */
}
@@ -2977,7 +2817,7 @@ wpi_config(struct wpi_softc *sc)
}
/* configuration has changed, set Tx power accordingly */
- if ((error = wpi_set_txpower(sc, ic->ic_curchan,0)) != 0) {
+ if ((error = wpi_set_txpower(sc, ic->ic_curchan, 0)) != 0) {
device_printf(sc->sc_dev, "could not set Tx power\n");
return error;
}
@@ -3125,16 +2965,83 @@ wpi_hw_config(struct wpi_softc *sc)
}
static void
+wpi_rfkill_resume(struct wpi_softc *sc)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
+ int ntries;
+
+ /* enable firmware again */
+ WPI_WRITE(sc, WPI_UCODE_CLR, WPI_RADIO_OFF);
+ WPI_WRITE(sc, WPI_UCODE_CLR, WPI_DISABLE_CMD);
+
+ /* wait for thermal sensors to calibrate */
+ for (ntries = 0; ntries < 1000; ntries++) {
+ if ((sc->temp = (int)WPI_READ(sc, WPI_TEMPERATURE)) != 0)
+ break;
+ DELAY(10);
+ }
+
+ if (ntries == 1000) {
+ device_printf(sc->sc_dev,
+ "timeout waiting for thermal calibration\n");
+ WPI_UNLOCK(sc);
+ return;
+ }
+ DPRINTFN(WPI_DEBUG_TEMP,("temperature %d\n", sc->temp));
+
+ if (wpi_config(sc) != 0) {
+ device_printf(sc->sc_dev, "device config failed\n");
+ WPI_UNLOCK(sc);
+ return;
+ }
+
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->flags &= ~WPI_FLAG_HW_RADIO_OFF;
+
+ if (ic->ic_flags & IEEE80211_F_SCAN)
+ ieee80211_scan_next(ic);
+
+ ieee80211_beacon_miss(ic);
+
+ /* reset the led sequence */
+ switch (ic->ic_state) {
+ case IEEE80211_S_SCAN:
+ wpi_set_led(sc, WPI_LED_LINK, 20, 2);
+ break;
+
+ case IEEE80211_S_RUN:
+ if (ic->ic_opmode == IEEE80211_M_MONITOR)
+ wpi_set_led(sc, WPI_LED_LINK, 5, 5);
+ else
+ wpi_set_led(sc, WPI_LED_LINK, 0, 1);
+ break;
+
+ default:
+ break; /* please compiler */
+ }
+
+ callout_reset(&sc->watchdog_to, hz, wpi_watchdog, sc);
+}
+
+static void
wpi_init(void *arg)
{
struct wpi_softc *sc = arg;
+
+ WPI_LOCK(sc);
+ wpi_init_locked(sc, 0);
+ WPI_UNLOCK(sc);
+}
+
+static void
+wpi_init_locked(struct wpi_softc *sc, int force)
+{
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = ic->ic_ifp;
uint32_t tmp;
- int ntries, error, qid;
- WPI_LOCK_DECL;
-
- WPI_LOCK(sc);
+ int ntries, qid;
wpi_stop_locked(sc);
(void)wpi_reset(sc);
@@ -3192,7 +3099,7 @@ wpi_init(void *arg)
WPI_WRITE(sc, WPI_UCODE_CLR, WPI_RADIO_OFF);
WPI_WRITE(sc, WPI_UCODE_CLR, WPI_RADIO_OFF);
- if ((error = wpi_load_firmware(sc)) != 0) {
+ if ((wpi_load_firmware(sc)) != 0) {
device_printf(sc->sc_dev,
"A problem occurred loading the firmware to the driver\n");
return;
@@ -3201,7 +3108,7 @@ wpi_init(void *arg)
/* At this point the firmware is up and running. If the hardware
* RF switch is turned off thermal calibration will fail, though
* the card is still happy to continue to accept commands, catch
- * this case and record the hw is disabled.
+ * this case and schedule a task to watch for it to be turned on.
*/
wpi_mem_lock(sc);
tmp = wpi_mem_read(sc, WPI_MEM_HW_RADIO_OFF);
@@ -3209,10 +3116,8 @@ wpi_init(void *arg)
if (!(tmp & 0x1)) {
sc->flags |= WPI_FLAG_HW_RADIO_OFF;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
device_printf(sc->sc_dev,"Radio Transmitter is switched off\n");
- return;
+ goto out;
}
/* wait for thermal sensors to calibrate */
@@ -3225,26 +3130,30 @@ wpi_init(void *arg)
if (ntries == 1000) {
device_printf(sc->sc_dev,
"timeout waiting for thermal sensors calibration\n");
- error = ETIMEDOUT;
return;
}
DPRINTFN(WPI_DEBUG_TEMP,("temperature %d\n", sc->temp));
+ if (wpi_config(sc) != 0) {
+ device_printf(sc->sc_dev, "device config failed\n");
+ return;
+ }
+
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
- callout_reset(&sc->watchdog_to, hz, wpi_tick, sc);
- WPI_UNLOCK(sc);
+out:
+ callout_reset(&sc->watchdog_to, hz, wpi_watchdog, sc);
if (ic->ic_opmode == IEEE80211_M_MONITOR)
ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
else if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
+ return;
}
static void
wpi_stop(struct wpi_softc *sc)
{
- WPI_LOCK_DECL;
WPI_LOCK(sc);
wpi_stop_locked(sc);
@@ -3260,8 +3169,13 @@ wpi_stop_locked(struct wpi_softc *sc)
uint32_t tmp;
int ac;
- sc->watchdog_cnt = sc->sc_tx_timer = 0;
+ sc->sc_tx_timer = 0;
+ sc->sc_scan_timer = 0;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->flags &= ~WPI_FLAG_HW_RADIO_OFF;
+ callout_stop(&sc->watchdog_to);
+ callout_stop(&sc->calib_to);
+
/* disable interrupts */
WPI_WRITE(sc, WPI_MASK, 0);
@@ -3271,6 +3185,9 @@ wpi_stop_locked(struct wpi_softc *sc)
/* Clear any commands left in the command buffer */
memset(sc->sc_cmd, 0, sizeof(sc->sc_cmd));
+ memset(sc->sc_cmd_arg, 0, sizeof(sc->sc_cmd_arg));
+ sc->sc_cmd_cur = 0;
+ sc->sc_cmd_next = 0;
wpi_mem_lock(sc);
wpi_mem_write(sc, WPI_MEM_MODE, 0);
@@ -3328,16 +3245,16 @@ wpi_calib_timeout(void *arg)
struct wpi_softc *sc = arg;
struct ieee80211com *ic = &sc->sc_ic;
int temp;
- WPI_LOCK_DECL;
+
+ if (ic->ic_state != IEEE80211_S_RUN)
+ return;
/* automatic rate control triggered every 500ms */
if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
- WPI_LOCK(sc);
if (ic->ic_opmode == IEEE80211_M_STA)
wpi_iter_func(sc, ic->ic_bss);
else
ieee80211_iterate_nodes(&ic->ic_sta, wpi_iter_func, sc);
- WPI_UNLOCK(sc);
}
/* update sensor data */
@@ -3616,24 +3533,6 @@ wpi_get_power_index(struct wpi_softc *sc, struct wpi_power_group *group,
#undef fdivround
}
-#if 0
-static void
-wpi_radio_on(void *arg, int pending)
-{
- struct wpi_softc *sc = arg;
-
- device_printf(sc->sc_dev, "radio turned on\n");
-}
-
-static void
-wpi_radio_off(void *arg, int pending)
-{
- struct wpi_softc *sc = arg;
-
- device_printf(sc->sc_dev, "radio turned off\n");
-}
-#endif
-
/**
* Called by net80211 framework to indicate that a scan
* is starting. This function doesn't actually do the scan,
@@ -3647,7 +3546,7 @@ wpi_scan_start(struct ieee80211com *ic)
struct ifnet *ifp = ic->ic_ifp;
struct wpi_softc *sc = ifp->if_softc;
- wpi_queue_cmd(sc, WPI_SCAN_START);
+ wpi_queue_cmd(sc, WPI_SCAN_START, 0, WPI_QUEUE_NORMAL);
}
/**
@@ -3661,7 +3560,7 @@ wpi_scan_end(struct ieee80211com *ic)
struct ifnet *ifp = ic->ic_ifp;
struct wpi_softc *sc = ifp->if_softc;
- wpi_queue_cmd(sc, WPI_SCAN_STOP);
+ wpi_queue_cmd(sc, WPI_SCAN_STOP, 0, WPI_QUEUE_NORMAL);
}
/**
@@ -3674,7 +3573,12 @@ wpi_set_channel(struct ieee80211com *ic)
struct ifnet *ifp = ic->ic_ifp;
struct wpi_softc *sc = ifp->if_softc;
- wpi_queue_cmd(sc, WPI_SET_CHAN);
+ /*
+ * Only need to set the channel in Monitor mode. AP scanning and auth
+ * are already taken care of by their respective firmware commands.
+ */
+ if (ic->ic_opmode == IEEE80211_M_MONITOR)
+ wpi_queue_cmd(sc, WPI_SET_CHAN, 0, WPI_QUEUE_NORMAL);
}
/**
@@ -3690,7 +3594,7 @@ wpi_scan_curchan(struct ieee80211com *ic, unsigned long maxdwell)
sc->maxdwell = maxdwell;
- wpi_queue_cmd(sc, WPI_SCAN_CURCHAN);
+ wpi_queue_cmd(sc, WPI_SCAN_CURCHAN, 0, WPI_QUEUE_NORMAL);
}
/**
@@ -3712,16 +3616,16 @@ wpi_scan_mindwell(struct ieee80211com *ic)
* The task that gets cued is a op task, which ends up calling this function.
*/
static void
-wpi_ops(void *arg, int pending)
+wpi_ops(void *arg0, int pending)
{
- struct wpi_softc *sc = arg;
+ struct wpi_softc *sc = arg0;
struct ieee80211com *ic = &sc->sc_ic;
- WPI_LOCK_DECL;
- int cmd;
+ int cmd, arg, error;
again:
WPI_CMD_LOCK(sc);
cmd = sc->sc_cmd[sc->sc_cmd_cur];
+ arg = sc->sc_cmd_arg[sc->sc_cmd_cur];
if (cmd == 0) {
/* No more commands to process */
@@ -3729,75 +3633,75 @@ again:
return;
}
sc->sc_cmd[sc->sc_cmd_cur] = 0; /* free the slot */
+ sc->sc_cmd_arg[sc->sc_cmd_cur] = 0; /* free the slot */
sc->sc_cmd_cur = (sc->sc_cmd_cur + 1) % WPI_CMD_MAXOPS;
WPI_CMD_UNLOCK(sc);
WPI_LOCK(sc);
- if (!(sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ DPRINTFN(WPI_DEBUG_OPS,("wpi_ops: command: %d\n", cmd));
+
+ switch (cmd) {
+ case WPI_RESTART:
+ wpi_init_locked(sc, 0);
+ WPI_UNLOCK(sc);
+ return;
+
+ case WPI_RF_RESTART:
+ wpi_rfkill_resume(sc);
WPI_UNLOCK(sc);
return;
}
- {
- const char *name[]={"SCAN_START", "SCAN_CURCHAN",0,"STOP",0,0,0,"CHAN",
- 0,0,0,0,0,0,"AUTH",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"NEXT"};
- DPRINTFN(WPI_DEBUG_OPS,("wpi_ops: command: %d %s\n", cmd, name[cmd-1]));
+ if (!(sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ WPI_UNLOCK(sc);
+ return;
}
switch (cmd) {
case WPI_SCAN_START:
- if (sc->flags & WPI_FLAG_HW_RADIO_OFF) {
- DPRINTF(("HERER\n"));
- ieee80211_cancel_scan(ic);
- } else
- sc->flags |= WPI_FLAG_SCANNING;
+ sc->flags |= WPI_FLAG_SCANNING;
break;
case WPI_SCAN_STOP:
sc->flags &= ~WPI_FLAG_SCANNING;
break;
- case WPI_SCAN_NEXT:
- DPRINTF(("NEXT\n"));
- WPI_UNLOCK(sc);
- ieee80211_scan_next(ic);
- WPI_LOCK(sc);
- break;
-
case WPI_SCAN_CURCHAN:
if (wpi_scan(sc))
ieee80211_cancel_scan(ic);
break;
case WPI_SET_CHAN:
- if (sc->flags&WPI_FLAG_AUTH) {
- DPRINTF(("Authenticating, not changing channel\n"));
- break;
- }
- if (wpi_config(sc)) {
- DPRINTF(("Scan cancelled\n"));
- WPI_UNLOCK(sc);
- ieee80211_cancel_scan(ic);
- WPI_LOCK(sc);
- sc->flags &= ~WPI_FLAG_SCANNING;
- wpi_restart(sc,0);
+ error = wpi_config(sc);
+ if (error != 0)
+ device_printf(sc->sc_dev,
+ "error %d settting channel\n", error);
+ break;
+
+ case WPI_AUTH:
+ /* The node must be registered in the firmware before auth */
+ error = wpi_auth(sc);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not move to auth state, error %d\n",
+ __func__, error);
WPI_UNLOCK(sc);
return;
}
+ /* Send the auth frame now */
+ sc->sc_newstate(ic, IEEE80211_S_AUTH, arg);
break;
- case WPI_AUTH:
- if (wpi_auth(sc) != 0) {
+ case WPI_RUN:
+ error = wpi_run(sc);
+ if (error != 0) {
device_printf(sc->sc_dev,
- "could not send authentication request\n");
- wpi_stop_locked(sc);
+ "%s: could not move to run state, error %d\n",
+ __func__, error);
WPI_UNLOCK(sc);
return;
}
- WPI_UNLOCK(sc);
- ieee80211_node_authorize(ic->ic_bss);
- ieee80211_new_state(ic, IEEE80211_S_ASSOC, -1);
- WPI_LOCK(sc);
+ sc->sc_newstate(ic, IEEE80211_S_RUN, arg);
break;
}
WPI_UNLOCK(sc);
@@ -3814,10 +3718,17 @@ again:
* a sleep enabled thread.
*/
static int
-wpi_queue_cmd(struct wpi_softc *sc, int cmd)
+wpi_queue_cmd(struct wpi_softc *sc, int cmd, int arg, int flush)
{
WPI_CMD_LOCK(sc);
+ if (flush) {
+ memset(sc->sc_cmd, 0, sizeof (sc->sc_cmd));
+ memset(sc->sc_cmd_arg, 0, sizeof (sc->sc_cmd_arg));
+ sc->sc_cmd_cur = 0;
+ sc->sc_cmd_next = 0;
+ }
+
if (sc->sc_cmd[sc->sc_cmd_next] != 0) {
WPI_CMD_UNLOCK(sc);
DPRINTF(("%s: command %d dropped\n", __func__, cmd));
@@ -3825,6 +3736,7 @@ wpi_queue_cmd(struct wpi_softc *sc, int cmd)
}
sc->sc_cmd[sc->sc_cmd_next] = cmd;
+ sc->sc_cmd_arg[sc->sc_cmd_next] = arg;
sc->sc_cmd_next = (sc->sc_cmd_next + 1) % WPI_CMD_MAXOPS;
taskqueue_enqueue(sc->sc_tq, &sc->sc_opstask);
@@ -3834,23 +3746,6 @@ wpi_queue_cmd(struct wpi_softc *sc, int cmd)
return 0;
}
-static void
-wpi_restart(void * arg, int pending)
-{
-#if 0
- struct wpi_softc *sc = arg;
- struct ieee80211com *ic = &sc->sc_ic;
- WPI_LOCK_DECL;
-
- DPRINTF(("Device failed, restarting device\n"));
- WPI_LOCK(sc);
- wpi_stop(sc);
- wpi_init(sc);
- WPI_UNLOCK(sc);
- ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
-#endif
-}
-
/*
* Allocate DMA-safe memory for firmware transfer.
*/
@@ -3870,18 +3765,50 @@ wpi_free_fwmem(struct wpi_softc *sc)
}
/**
- * Called every second, wpi_tick used by the watch dog timer
+ * Called every second, wpi_watchdog used by the watch dog timer
* to check that the card is still alive
*/
static void
-wpi_tick(void *arg)
+wpi_watchdog(void *arg)
{
struct wpi_softc *sc = arg;
+ struct ifnet *ifp = sc->sc_ifp;
+ uint32_t tmp;
DPRINTFN(WPI_DEBUG_WATCHDOG,("Watchdog: tick\n"));
- wpi_watchdog(sc->sc_ifp);
- callout_reset(&sc->watchdog_to, hz, wpi_tick, sc);
+ if (sc->flags & WPI_FLAG_HW_RADIO_OFF) {
+ /* No need to lock firmware memory */
+ tmp = wpi_mem_read(sc, WPI_MEM_HW_RADIO_OFF);
+
+ if ((tmp & 0x1) == 0) {
+ /* Radio kill switch is still off */
+ callout_reset(&sc->watchdog_to, hz, wpi_watchdog, sc);
+ return;
+ }
+
+ device_printf(sc->sc_dev, "Hardware Switch Enabled\n");
+ wpi_queue_cmd(sc, WPI_RF_RESTART, 0, WPI_QUEUE_CLEAR);
+ return;
+ }
+
+ if (sc->sc_tx_timer > 0) {
+ if (--sc->sc_tx_timer == 0) {
+ device_printf(sc->sc_dev,"device timeout\n");
+ ifp->if_oerrors++;
+ wpi_queue_cmd(sc, WPI_RESTART, 0, WPI_QUEUE_CLEAR);
+ }
+ }
+ if (sc->sc_scan_timer > 0) {
+ if (--sc->sc_scan_timer == 0) {
+ device_printf(sc->sc_dev,"scan timeout\n");
+ ieee80211_cancel_scan(&sc->sc_ic);
+ wpi_queue_cmd(sc, WPI_RESTART, 0, WPI_QUEUE_CLEAR);
+ }
+ }
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ callout_reset(&sc->watchdog_to, hz, wpi_watchdog, sc);
}
#ifdef WPI_DEBUG
diff --git a/sys/dev/wpi/if_wpireg.h b/sys/dev/wpi/if_wpireg.h
index 0f83d0a..60692a2 100644
--- a/sys/dev/wpi/if_wpireg.h
+++ b/sys/dev/wpi/if_wpireg.h
@@ -44,6 +44,7 @@
#define WPI_GPIO_CTL 0x024
#define WPI_EEPROM_CTL 0x02c
#define WPI_EEPROM_STATUS 0x030
+#define WPI_UCODE_SET 0x058
#define WPI_UCODE_CLR 0x05c
#define WPI_TEMPERATURE 0x060
#define WPI_CHICKEN 0x100
@@ -201,6 +202,7 @@ struct wpi_rx_desc {
#define WPI_RX_DONE 27
#define WPI_TX_DONE 28
#define WPI_START_SCAN 130
+#define WPI_SCAN_RESULTS 131
#define WPI_STOP_SCAN 132
#define WPI_STATE_CHANGED 161
#define WPI_MISSED_BEACON 162
diff --git a/sys/dev/wpi/if_wpivar.h b/sys/dev/wpi/if_wpivar.h
index a8fe4cc..39020df 100644
--- a/sys/dev/wpi/if_wpivar.h
+++ b/sys/dev/wpi/if_wpivar.h
@@ -16,17 +16,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#if ( __FreeBSD_version > 700000 )
#include <net80211/ieee80211_amrr.h>
-#else
-#include <dev/wpi/ieee80211_amrr.h>
-#endif
-
-/* DMA mapping */
-struct wpi_mapping {
- int nsegs;
- bus_dma_segment_t segs[WPI_MAX_SCATTER];
-};
struct wpi_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
@@ -66,8 +56,10 @@ struct wpi_tx_radiotap_header {
struct wpi_dma_info {
bus_dma_tag_t tag;
bus_dmamap_t map;
- bus_addr_t paddr;
- caddr_t vaddr;
+ bus_addr_t paddr; /* aligned p address */
+ bus_addr_t paddr_start; /* possibly unaligned p start*/
+ caddr_t vaddr; /* aligned v address */
+ caddr_t vaddr_start; /* possibly unaligned v start */
bus_size_t size;
};
@@ -92,26 +84,16 @@ struct wpi_tx_ring {
#define WPI_RBUF_COUNT ( WPI_RX_RING_COUNT + 16 )
-struct wpi_softc;
-
-struct wpi_rbuf {
- struct wpi_softc *sc;
- bus_addr_t paddr;
- caddr_t vaddr;
- SLIST_ENTRY(wpi_rbuf) next;
-};
-
struct wpi_rx_data {
- struct mbuf *m;
+ bus_dmamap_t map;
+ struct mbuf *m;
};
struct wpi_rx_ring {
struct wpi_dma_info desc_dma;
- struct wpi_dma_info buf_dma;
uint32_t *desc;
struct wpi_rx_data data[WPI_RX_RING_COUNT];
- struct wpi_rbuf rbuf[WPI_RBUF_COUNT];
- SLIST_HEAD(, wpi_rbuf) freelist;
+ bus_dma_tag_t data_dmat;
int cur;
};
@@ -165,10 +147,6 @@ struct wpi_softc {
#define WPI_FLAG_BUSY (1 << 2)
#define WPI_FLAG_AUTH (1 << 3)
- /* Flags indicating the state of the firmware */
- uint32_t fw_state;
-#define WPI_FW_IDLE (1 << 0 )
-
/* shared area */
struct wpi_dma_info shared_dma;
struct wpi_shared *shared;
@@ -183,7 +161,8 @@ struct wpi_softc {
/* Watch dog timer */
struct callout watchdog_to;
- int watchdog_cnt;
+ /* Hardware switch polling timer */
+ struct callout hwswitch_to;
struct resource *irq;
struct resource *mem;
@@ -198,6 +177,7 @@ struct wpi_softc {
int sc_tx_timer;
+ int sc_scan_timer;
struct bpf_if *sc_drvbpf;
@@ -213,14 +193,21 @@ struct wpi_softc {
struct wpi_dma_info fw_dma;
/* command queue related variables */
- #define WPI_CMD_MAXOPS 10
- #define WPI_SCAN_START (1<<0)
- #define WPI_SCAN_CURCHAN (1<<1)
- #define WPI_SCAN_STOP (1<<2)
- #define WPI_SET_CHAN (1<<3)
- #define WPI_AUTH (1<<4)
- #define WPI_SCAN_NEXT (1<<5)
+#define WPI_SCAN_START (1<<0)
+#define WPI_SCAN_CURCHAN (1<<1)
+#define WPI_SCAN_STOP (1<<2)
+#define WPI_SET_CHAN (1<<3)
+#define WPI_AUTH (1<<4)
+#define WPI_RUN (1<<5)
+#define WPI_SCAN_NEXT (1<<6)
+#define WPI_RESTART (1<<7)
+#define WPI_RF_RESTART (1<<8)
+#define WPI_CMD_MAXOPS 10
+ /* command queuing request type */
+#define WPI_QUEUE_NORMAL 0
+#define WPI_QUEUE_CLEAR 1
int sc_cmd[WPI_CMD_MAXOPS];
+ int sc_cmd_arg[WPI_CMD_MAXOPS];
int sc_cmd_cur; /* current queued scan task */
int sc_cmd_next; /* last queued scan task */
struct mtx sc_cmdlock;
@@ -246,24 +233,15 @@ struct wpi_softc {
#define WPI_LOCK_INIT(_sc) \
mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
MTX_NETWORK_LOCK, MTX_DEF)
-#define WPI_LOCK_DECL int __waslocked = 0
-#define WPI_LOCK(_sc) do {\
- if (!(__waslocked = mtx_owned(&(_sc)->sc_mtx))) \
- mtx_lock(&(_sc)->sc_mtx); \
-} while(0)
-#define WPI_UNLOCK(_sc) do { \
- if (!__waslocked) \
- mtx_unlock(&(_sc)->sc_mtx); \
-} while (0)
-
+#define WPI_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define WPI_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define WPI_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
+#define WPI_LOCK_OWNED(_sc) mtx_owned(&(_sc)->sc_mtx)
#define WPI_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)
+
#define WPI_CMD_LOCK_INIT(_sc) \
- mtx_init(&(_sc)->sc_cmdlock, device_get_nameunit((_sc)->sc_dev), NULL, MTX_DEF);
+ mtx_init(&(_sc)->sc_cmdlock, device_get_nameunit((_sc)->sc_dev), \
+ NULL, MTX_DEF)
#define WPI_CMD_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_cmdlock)
#define WPI_CMD_LOCK(_sc) mtx_lock(&(_sc)->sc_cmdlock)
#define WPI_CMD_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_cmdlock)
-#if defined(INVARIANTS) || defined(INVARIANT_SUPPORT)
-#define WPI_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
-#else
-#define WPI_LOCK_ASSERT(sc)
-#endif
OpenPOWER on IntegriCloud