summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_iwi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/if_iwi.c')
-rw-r--r--sys/dev/pci/if_iwi.c144
1 files changed, 56 insertions, 88 deletions
diff --git a/sys/dev/pci/if_iwi.c b/sys/dev/pci/if_iwi.c
index 0cfdc95f3c1..64dc8c74db1 100644
--- a/sys/dev/pci/if_iwi.c
+++ b/sys/dev/pci/if_iwi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwi.c,v 1.93 2008/09/03 19:47:58 damien Exp $ */
+/* $OpenBSD: if_iwi.c,v 1.94 2008/09/04 15:59:52 damien Exp $ */
/*-
* Copyright (c) 2004-2008
@@ -79,7 +79,7 @@ int iwi_alloc_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *);
void iwi_reset_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *);
void iwi_free_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *);
int iwi_alloc_tx_ring(struct iwi_softc *, struct iwi_tx_ring *,
- bus_size_t, bus_size_t);
+ int);
void iwi_reset_tx_ring(struct iwi_softc *, struct iwi_tx_ring *);
void iwi_free_tx_ring(struct iwi_softc *, struct iwi_tx_ring *);
int iwi_alloc_rx_ring(struct iwi_softc *, struct iwi_rx_ring *);
@@ -168,7 +168,7 @@ iwi_attach(struct device *parent, struct device *self, void *aux)
pci_intr_handle_t ih;
pcireg_t data;
uint16_t val;
- int error, i;
+ int error, ac, i;
sc->sc_pct = pa->pa_pc;
sc->sc_pcitag = pa->pa_tag;
@@ -215,44 +215,19 @@ iwi_attach(struct device *parent, struct device *self, void *aux)
/*
* Allocate rings.
*/
- error = iwi_alloc_cmd_ring(sc, &sc->cmdq);
- if (error != 0) {
+ if (iwi_alloc_cmd_ring(sc, &sc->cmdq) != 0) {
printf(": could not allocate Cmd ring\n");
return;
}
-
- error = iwi_alloc_tx_ring(sc, &sc->txq[0], IWI_CSR_TX1_RIDX,
- IWI_CSR_TX1_WIDX);
- if (error != 0) {
- printf(": could not allocate Tx ring 1\n");
- goto fail1;
- }
-
- error = iwi_alloc_tx_ring(sc, &sc->txq[1], IWI_CSR_TX2_RIDX,
- IWI_CSR_TX2_WIDX);
- if (error != 0) {
- printf(": could not allocate Tx ring 2\n");
- goto fail2;
- }
-
- error = iwi_alloc_tx_ring(sc, &sc->txq[2], IWI_CSR_TX3_RIDX,
- IWI_CSR_TX3_WIDX);
- if (error != 0) {
- printf(": could not allocate Tx ring 3\n");
- goto fail3;
- }
-
- error = iwi_alloc_tx_ring(sc, &sc->txq[3], IWI_CSR_TX4_RIDX,
- IWI_CSR_TX4_WIDX);
- if (error != 0) {
- printf(": could not allocate Tx ring 4\n");
- goto fail4;
+ for (ac = 0; ac < EDCA_NUM_AC; ac++) {
+ if (iwi_alloc_tx_ring(sc, &sc->txq[ac], ac) != 0) {
+ printf(": could not allocate Tx ring %d\n", ac);
+ goto fail;
+ }
}
-
- error = iwi_alloc_rx_ring(sc, &sc->rxq);
- if (error != 0) {
+ if (iwi_alloc_rx_ring(sc, &sc->rxq) != 0) {
printf(": could not allocate Rx ring\n");
- goto fail5;
+ goto fail;
}
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -353,11 +328,9 @@ iwi_attach(struct device *parent, struct device *self, void *aux)
return;
-fail5: iwi_free_tx_ring(sc, &sc->txq[3]);
-fail4: iwi_free_tx_ring(sc, &sc->txq[2]);
-fail3: iwi_free_tx_ring(sc, &sc->txq[1]);
-fail2: iwi_free_tx_ring(sc, &sc->txq[0]);
-fail1: iwi_free_cmd_ring(sc, &sc->cmdq);
+fail: while (--ac >= 0)
+ iwi_free_tx_ring(sc, &sc->txq[ac]);
+ iwi_free_cmd_ring(sc, &sc->cmdq);
}
void
@@ -366,6 +339,7 @@ iwi_power(int why, void *arg)
struct iwi_softc *sc = arg;
struct ifnet *ifp;
pcireg_t data;
+ int s;
if (why != PWR_RESUME)
return;
@@ -375,12 +349,14 @@ iwi_power(int why, void *arg)
data &= ~0x0000ff00;
pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data);
+ s = splnet();
ifp = &sc->sc_ic.ic_if;
if (ifp->if_flags & IFF_UP) {
ifp->if_init(ifp);
if (ifp->if_flags & IFF_RUNNING)
ifp->if_start(ifp);
}
+ splx(s);
}
int
@@ -457,16 +433,15 @@ iwi_free_cmd_ring(struct iwi_softc *sc, struct iwi_cmd_ring *ring)
}
int
-iwi_alloc_tx_ring(struct iwi_softc *sc, struct iwi_tx_ring *ring,
- bus_size_t csr_ridx, bus_size_t csr_widx)
+iwi_alloc_tx_ring(struct iwi_softc *sc, struct iwi_tx_ring *ring, int ac)
{
struct iwi_tx_data *data;
int i, nsegs, error;
ring->queued = 0;
ring->cur = ring->next = 0;
- ring->csr_ridx = csr_ridx;
- ring->csr_widx = csr_widx;
+ ring->csr_ridx = IWI_CSR_TX_RIDX(ac);
+ ring->csr_widx = IWI_CSR_TX_WIDX(ac);
error = bus_dmamap_create(sc->sc_dmat,
sizeof (struct iwi_tx_desc) * IWI_TX_RING_COUNT, 1,
@@ -1240,7 +1215,7 @@ iwi_cmd(struct iwi_softc *sc, uint8_t type, void *data, uint8_t len, int async)
CSR_WRITE_4(sc, IWI_CSR_CMD_WIDX, sc->cmdq.next);
}
- return async ? 0 : tsleep(sc, 0, "iwicmd", hz);
+ return async ? 0 : tsleep(sc, PCATCH, "iwicmd", hz);
}
/* ARGSUSED */
@@ -1542,6 +1517,7 @@ iwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
void
iwi_stop_master(struct iwi_softc *sc)
{
+ uint32_t tmp;
int ntries;
/* disable interrupts */
@@ -1558,8 +1534,8 @@ iwi_stop_master(struct iwi_softc *sc)
sc->sc_dev.dv_xname);
}
- CSR_WRITE_4(sc, IWI_CSR_RST, CSR_READ_4(sc, IWI_CSR_RST) |
- IWI_RST_PRINCETON_RESET);
+ tmp = CSR_READ_4(sc, IWI_CSR_RST);
+ CSR_WRITE_4(sc, IWI_CSR_RST, tmp | IWI_RST_PRINCETON_RESET);
sc->flags &= ~IWI_FLAG_FW_INITED;
}
@@ -1567,13 +1543,14 @@ iwi_stop_master(struct iwi_softc *sc)
int
iwi_reset(struct iwi_softc *sc)
{
+ uint32_t tmp;
int i, ntries;
iwi_stop_master(sc);
/* move adapter to D0 state */
- CSR_WRITE_4(sc, IWI_CSR_CTL, CSR_READ_4(sc, IWI_CSR_CTL) |
- IWI_CTL_INIT);
+ tmp = CSR_READ_4(sc, IWI_CSR_CTL);
+ CSR_WRITE_4(sc, IWI_CSR_CTL, tmp | IWI_CTL_INIT);
CSR_WRITE_4(sc, IWI_CSR_READ_INT, IWI_READ_INT_INIT_HOST);
@@ -1589,13 +1566,13 @@ iwi_reset(struct iwi_softc *sc)
return ETIMEDOUT;
}
- CSR_WRITE_4(sc, IWI_CSR_RST, CSR_READ_4(sc, IWI_CSR_RST) |
- IWI_RST_SW_RESET);
+ tmp = CSR_READ_4(sc, IWI_CSR_RST);
+ CSR_WRITE_4(sc, IWI_CSR_RST, tmp | IWI_RST_SW_RESET);
DELAY(10);
- CSR_WRITE_4(sc, IWI_CSR_CTL, CSR_READ_4(sc, IWI_CSR_CTL) |
- IWI_CTL_INIT);
+ tmp = CSR_READ_4(sc, IWI_CSR_CTL);
+ CSR_WRITE_4(sc, IWI_CSR_CTL, tmp | IWI_CTL_INIT);
/* clear NIC memory */
CSR_WRITE_4(sc, IWI_CSR_AUTOINC_ADDR, 0);
@@ -1609,10 +1586,11 @@ int
iwi_load_ucode(struct iwi_softc *sc, const char *data, int size)
{
const uint16_t *w;
+ uint32_t tmp;
int ntries, i;
- CSR_WRITE_4(sc, IWI_CSR_RST, CSR_READ_4(sc, IWI_CSR_RST) |
- IWI_RST_STOP_MASTER);
+ tmp = CSR_READ_4(sc, IWI_CSR_RST);
+ CSR_WRITE_4(sc, IWI_CSR_RST, tmp | IWI_RST_STOP_MASTER);
for (ntries = 0; ntries < 5; ntries++) {
if (CSR_READ_4(sc, IWI_CSR_RST) & IWI_RST_MASTER_DISABLED)
break;
@@ -1627,8 +1605,8 @@ iwi_load_ucode(struct iwi_softc *sc, const char *data, int size)
MEM_WRITE_4(sc, 0x3000e0, 0x80000000);
DELAY(5000);
- CSR_WRITE_4(sc, IWI_CSR_RST, CSR_READ_4(sc, IWI_CSR_RST) &
- ~IWI_RST_PRINCETON_RESET);
+ tmp = CSR_READ_4(sc, IWI_CSR_RST);
+ CSR_WRITE_4(sc, IWI_CSR_RST, tmp & ~IWI_RST_PRINCETON_RESET);
DELAY(5000);
MEM_WRITE_4(sc, 0x3000e0, 0);
@@ -1679,7 +1657,7 @@ iwi_load_firmware(struct iwi_softc *sc, const char *data, int size)
bus_dma_segment_t seg;
caddr_t virtaddr;
u_char *p, *end;
- uint32_t sentinel, ctl, src, dst, sum, len, mlen;
+ uint32_t sentinel, tmp, ctl, src, dst, sum, len, mlen;
int ntries, nsegs, error;
/* allocate DMA memory to store firmware image */
@@ -1761,8 +1739,9 @@ iwi_load_firmware(struct iwi_softc *sc, const char *data, int size)
sentinel = CSR_READ_4(sc, IWI_CSR_AUTOINC_ADDR);
CSR_WRITE_4(sc, IWI_CSR_AUTOINC_DATA, 0);
- CSR_WRITE_4(sc, IWI_CSR_RST, CSR_READ_4(sc, IWI_CSR_RST) &
- ~(IWI_RST_MASTER_DISABLED | IWI_RST_STOP_MASTER));
+ tmp = CSR_READ_4(sc, IWI_CSR_RST);
+ tmp &= ~(IWI_RST_MASTER_DISABLED | IWI_RST_STOP_MASTER);
+ CSR_WRITE_4(sc, IWI_CSR_RST, tmp);
/* tell the adapter to start processing command blocks */
MEM_WRITE_4(sc, 0x3000a4, 0x540100);
@@ -1788,11 +1767,11 @@ iwi_load_firmware(struct iwi_softc *sc, const char *data, int size)
/* tell the adapter to initialize the firmware */
CSR_WRITE_4(sc, IWI_CSR_RST, 0);
- CSR_WRITE_4(sc, IWI_CSR_CTL, CSR_READ_4(sc, IWI_CSR_CTL) |
- IWI_CTL_ALLOW_STANDBY);
+ tmp = CSR_READ_4(sc, IWI_CSR_CTL);
+ CSR_WRITE_4(sc, IWI_CSR_CTL, tmp | IWI_CTL_ALLOW_STANDBY);
/* wait at most one second for firmware initialization to complete */
- if ((error = tsleep(sc, 0, "iwiinit", hz)) != 0) {
+ if ((error = tsleep(sc, PCATCH, "iwiinit", hz)) != 0) {
printf("%s: timeout waiting for firmware initialization to "
"complete\n", sc->sc_dev.dv_xname);
goto fail5;
@@ -1936,7 +1915,7 @@ iwi_config(struct iwi_softc *sc)
return error;
}
- data = arc4random();
+ arc4random_buf(&data, sizeof data);
DPRINTF(("Setting random seed to %u\n", data));
error = iwi_cmd(sc, IWI_CMD_SET_RANDOM_SEED, &data, sizeof data, 0);
if (error != 0)
@@ -2167,7 +2146,7 @@ iwi_auth_and_assoc(struct iwi_softc *sc)
assoc.plen = IWI_ASSOC_SHPREAMBLE;
bcopy(ni->ni_tstamp, assoc.tstamp, 8);
capinfo = IEEE80211_CAPINFO_ESS;
- if (ic->ic_flags & (IEEE80211_F_WEPON | IEEE80211_F_RSNON))
+ if (ic->ic_flags & IEEE80211_F_WEPON)
capinfo |= IEEE80211_CAPINFO_PRIVACY;
if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
@@ -2200,7 +2179,7 @@ iwi_init(struct ifnet *ifp)
const char *name, *fw;
u_char *data;
size_t size;
- int i, error;
+ int i, ac, error;
iwi_stop(ifp, 0);
@@ -2209,7 +2188,7 @@ iwi_init(struct ifnet *ifp)
goto fail1;
}
- switch (sc->sc_ic.ic_opmode) {
+ switch (ic->ic_opmode) {
case IEEE80211_M_STA:
name = "iwi-bss";
break;
@@ -2233,14 +2212,12 @@ iwi_init(struct ifnet *ifp)
sc->sc_dev.dv_xname, error, name);
goto fail1;
}
-
if (size < sizeof (struct iwi_firmware_hdr)) {
printf("%s: firmware image too short: %u bytes\n",
sc->sc_dev.dv_xname, size);
error = EINVAL;
goto fail2;
}
-
hdr = (struct iwi_firmware_hdr *)data;
if (hdr->vermaj < 3 || hdr->bootsz == 0 || hdr->ucodesz == 0 ||
@@ -2279,21 +2256,12 @@ iwi_init(struct ifnet *ifp)
CSR_WRITE_4(sc, IWI_CSR_CMD_SIZE, IWI_CMD_RING_COUNT);
CSR_WRITE_4(sc, IWI_CSR_CMD_WIDX, sc->cmdq.cur);
- CSR_WRITE_4(sc, IWI_CSR_TX1_BASE, sc->txq[0].map->dm_segs[0].ds_addr);
- CSR_WRITE_4(sc, IWI_CSR_TX1_SIZE, IWI_TX_RING_COUNT);
- CSR_WRITE_4(sc, IWI_CSR_TX1_WIDX, sc->txq[0].cur);
-
- CSR_WRITE_4(sc, IWI_CSR_TX2_BASE, sc->txq[1].map->dm_segs[0].ds_addr);
- CSR_WRITE_4(sc, IWI_CSR_TX2_SIZE, IWI_TX_RING_COUNT);
- CSR_WRITE_4(sc, IWI_CSR_TX2_WIDX, sc->txq[1].cur);
-
- CSR_WRITE_4(sc, IWI_CSR_TX3_BASE, sc->txq[2].map->dm_segs[0].ds_addr);
- CSR_WRITE_4(sc, IWI_CSR_TX3_SIZE, IWI_TX_RING_COUNT);
- CSR_WRITE_4(sc, IWI_CSR_TX3_WIDX, sc->txq[2].cur);
-
- CSR_WRITE_4(sc, IWI_CSR_TX4_BASE, sc->txq[3].map->dm_segs[0].ds_addr);
- CSR_WRITE_4(sc, IWI_CSR_TX4_SIZE, IWI_TX_RING_COUNT);
- CSR_WRITE_4(sc, IWI_CSR_TX4_WIDX, sc->txq[3].cur);
+ for (ac = 0; ac < EDCA_NUM_AC; ac++) {
+ CSR_WRITE_4(sc, IWI_CSR_TX_BASE(ac),
+ sc->txq[ac].map->dm_segs[0].ds_addr);
+ CSR_WRITE_4(sc, IWI_CSR_TX_SIZE(ac), IWI_TX_RING_COUNT);
+ CSR_WRITE_4(sc, IWI_CSR_TX_WIDX(ac), sc->txq[ac].cur);
+ }
for (i = 0; i < IWI_RX_RING_COUNT; i++) {
struct iwi_rx_data *data = &sc->rxq.data[i];
@@ -2339,7 +2307,7 @@ iwi_stop(struct ifnet *ifp, int disable)
{
struct iwi_softc *sc = ifp->if_softc;
struct ieee80211com *ic = &sc->sc_ic;
- int i;
+ int ac;
sc->sc_tx_timer = 0;
ifp->if_timer = 0;
@@ -2353,8 +2321,8 @@ iwi_stop(struct ifnet *ifp, int disable)
/* reset rings */
iwi_reset_cmd_ring(sc, &sc->cmdq);
- for (i = 0; i < 4; i++)
- iwi_reset_tx_ring(sc, &sc->txq[i]);
+ for (ac = 0; ac < EDCA_NUM_AC; ac++)
+ iwi_reset_tx_ring(sc, &sc->txq[ac]);
iwi_reset_rx_ring(sc, &sc->rxq);
}