Subject: Re: botch in wi0 on alpha
To: mel kravitz <melk@switchpwr.com>
From: David Young <dyoung@pobox.com>
List: tech-net
Date: 12/22/2003 02:18:42
--W/nzBZO5zC0uMSeA
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Sun, Dec 21, 2003 at 09:25:40PM -0600, David Young wrote:
> On Sun, Dec 21, 2003 at 08:28:04AM -0500, mel kravitz wrote:
> > Any one trying to use wi0 (pci card) on alpha with -current
> > (1.6ZG)? ifconfig wi0 inet xxxy.... will crash the box , as
> > reported: http://mail-index.netbsd.org/port-alpha/2003/05/06/0000.html
> > This is on an AlphaServer 500/333 with supported card:
>
> I do not have the docs I need to interpret the machine-check
> exception. Does anyone? My guess is that it indicates either bad
> alignment, or else some bus exception raised by your wi(4) instance---can
> a PCI adapter return the equivalent of EAGAIN or EBUSY?
>
> wi(4) contains no bus barriers, but lots of code could be sensitive to
> out-of-order reads & writes. I am adding barriers where I think they are
> called for. I will send a patch, soon. If somebody who understands the
> fine points of bus barriers will review my patches, I would appreciate it.
I propose to add the attached bus barriers to wi, just as soon as there
is a way for me to test them. Note that these are no-ops, now.
Dave
--
David Young OJC Technologies
dyoung@ojctech.com Urbana, IL * (217) 278-3933
--W/nzBZO5zC0uMSeA
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=wi-barriers
Index: sys/dev/ic/wi.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/wi.c,v
retrieving revision 1.148
diff -u -r1.148 wi.c
--- sys/dev/ic/wi.c 7 Dec 2003 05:44:49 -0000 1.148
+++ sys/dev/ic/wi.c 22 Dec 2003 08:08:34 -0000
@@ -241,7 +241,9 @@
/* Make sure interrupts are disabled. */
CSR_WRITE_2(sc, WI_INT_EN, 0);
+ CSR_WBW_2(sc, WI_INT_EN, WI_EVENT_ACK);
CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
+ CSR_SYNC_2(sc, WI_INT_EN, WI_EVENT_ACK);/* XXX paranoia? */
sc->sc_invalid = 0;
@@ -523,7 +525,9 @@
if ((ifp->if_flags & IFF_UP) == 0) {
CSR_WRITE_2(sc, WI_INT_EN, 0);
+ CSR_WBW_2(sc, WI_INT_EN, WI_EVENT_ACK); /* XXX paranoia? */
CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
+ CSR_SYNC_2(sc, WI_INT_EN, WI_EVENT_ACK);/* XXX paranoia? */
return 1;
}
@@ -531,6 +535,7 @@
* do not disable interrupts.
*/
CSR_WRITE_2(sc, WI_INT_EN, 0);
+ CSR_WBW_2(sc, WI_INT_EN, WI_INT_EN);
/* maximum 10 loops per interrupt */
for (i = 0; i < 10; i++) {
@@ -542,6 +547,7 @@
* it is updated.
*/
status = CSR_READ_2(sc, WI_EVENT_STAT);
+ CSR_RBR_2(sc, WI_EVENT_STAT, WI_EVENT_STAT);/* XXX paranoia? */
if ((status & WI_INTRS) == 0)
break;
@@ -568,6 +574,7 @@
/* re-enable interrupts */
CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
+ CSR_SYNC_2(sc, WI_INT_EN, WI_INT_EN); /* XXX paranoia? */
return 1;
}
@@ -725,6 +732,7 @@
/* Enable interrupts */
CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
+ CSR_SYNC_2(sc, WI_INT_EN, WI_INT_EN); /* XXX paranoia? */
if (!wasenabled &&
ic->ic_opmode == IEEE80211_M_HOSTAP &&
@@ -747,7 +755,6 @@
if (sc->sc_firmware_type != WI_LUCENT)
wi_write_rid(sc, WI_RID_JOIN_REQ, &join, sizeof(join));
}
-
out:
if (error) {
printf("%s: interface not running\n", sc->sc_dev.dv_xname);
@@ -775,6 +782,7 @@
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
if (!sc->sc_invalid) {
CSR_WRITE_2(sc, WI_INT_EN, 0);
+ CSR_SYNC_2(sc, WI_INT_EN, WI_INT_EN);
wi_cmd(sc, WI_CMD_DISABLE | sc->sc_portnum, 0, 0, 0);
}
@@ -1130,7 +1138,9 @@
return error;
}
CSR_WRITE_2(sc, WI_INT_EN, 0);
+ CSR_WBW_2(sc, WI_INT_EN, WI_EVENT_ACK);
CSR_WRITE_2(sc, WI_EVENT_ACK, ~0);
+ CSR_SYNC_2(sc, WI_INT_EN, WI_EVENT_ACK);
/* Calibrate timer. */
wi_write_val(sc, WI_RID_TICK_TIME, 0);
@@ -1461,10 +1471,12 @@
u_int32_t rstamp;
fid = CSR_READ_2(sc, WI_RX_FID);
+ CSR_RBW_2(sc, WI_RX_FID, WI_EVENT_ACK);
/* First read in the frame header */
if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
+ CSR_WBR_2(sc, WI_EVENT_ACK, WI_EVENT_STAT);
ifp->if_ierrors++;
DPRINTF(("wi_rx_intr: read fid %x failed\n", fid));
return;
@@ -1480,6 +1492,7 @@
if ((status & WI_STAT_ERRSTAT) != 0 &&
ic->ic_opmode != IEEE80211_M_MONITOR) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
+ CSR_WBR_2(sc, WI_EVENT_ACK, WI_EVENT_STAT);
ifp->if_ierrors++;
DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
return;
@@ -1497,6 +1510,7 @@
if (off + len > MCLBYTES) {
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
+ CSR_WBR_2(sc, WI_EVENT_ACK, WI_EVENT_STAT);
ifp->if_ierrors++;
DPRINTF(("wi_rx_intr: oversized packet\n"));
return;
@@ -1507,6 +1521,7 @@
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
+ CSR_WBR_2(sc, WI_EVENT_ACK, WI_EVENT_STAT);
ifp->if_ierrors++;
DPRINTF(("wi_rx_intr: MGET failed\n"));
return;
@@ -1515,6 +1530,7 @@
MCLGET(m, M_DONTWAIT);
if ((m->m_flags & M_EXT) == 0) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
+ CSR_WBR_2(sc, WI_EVENT_ACK, WI_EVENT_STAT);
m_freem(m);
ifp->if_ierrors++;
DPRINTF(("wi_rx_intr: MCLGET failed\n"));
@@ -1530,6 +1546,7 @@
m->m_pkthdr.rcvif = ifp;
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
+ CSR_WBR_2(sc, WI_EVENT_ACK, WI_EVENT_STAT);
#if NBPFILTER > 0
if (sc->sc_drvbpf) {
@@ -1596,6 +1613,8 @@
u_int16_t status;
fid = CSR_READ_2(sc, WI_TX_CMP_FID);
+ CSR_RBW_2(sc, WI_TX_CMP_FID, WI_EVENT_ACK);
+
/* Read in the frame header */
if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) {
printf("wi_tx_ex_intr: read fid %x failed\n", fid);
@@ -1651,6 +1670,7 @@
ifp->if_flags &= ~IFF_OACTIVE;
bad_header:
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
+ CSR_WBR_2(sc, WI_EVENT_ACK, WI_EVENT_STAT);
}
static void
@@ -1661,6 +1681,7 @@
int fid, cur;
fid = CSR_READ_2(sc, WI_ALLOC_FID);
+ CSR_RBW_2(sc, WI_ALLOC_FID, WI_EVENT_ACK);
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
cur = sc->sc_txcur;
@@ -1700,6 +1721,8 @@
int fid;
fid = CSR_READ_2(sc, WI_TX_CMP_FID);
+ CSR_RBW_2(sc, WI_TX_CMP_FID, WI_EVENT_ACK);
+
/* Read in the frame header */
if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) {
printf("wi_tx_intr: read fid %x failed\n", fid);
@@ -1729,6 +1752,7 @@
ifp->if_flags &= ~IFF_OACTIVE;
out:
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
+ CSR_WBR_2(sc, WI_EVENT_ACK, WI_EVENT_STAT);
}
static void
@@ -1742,6 +1766,7 @@
u_int32_t *ptr;
fid = CSR_READ_2(sc, WI_INFO_FID);
+ CSR_RBW_2(sc, WI_INFO_FID, WI_EVENT_ACK);
wi_read_bap(sc, fid, 0, ltbuf, sizeof(ltbuf));
switch (le16toh(ltbuf[1])) {
@@ -1811,6 +1836,7 @@
break;
}
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
+ CSR_WBR_2(sc, WI_EVENT_ACK, WI_EVENT_STAT);
}
static int
@@ -2407,6 +2433,7 @@
/* wait for the busy bit to clear */
for (i = 500; i > 0; i--) { /* 5s */
+ CSR_RBR_2(sc, WI_COMMAND, WI_COMMAND); /* XXX paranoia? */
if ((CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY) == 0)
break;
DELAY(10*1000); /* 10 m sec */
@@ -2419,7 +2446,11 @@
CSR_WRITE_2(sc, WI_PARAM0, val0);
CSR_WRITE_2(sc, WI_PARAM1, val1);
CSR_WRITE_2(sc, WI_PARAM2, val2);
+
+ /* Note that WI_COMMAND < WI_PARAM0 < WI_PARAM1 < WI_PARAM2. */
+ CSR_WBW_2(sc, WI_COMMAND, WI_PARAM2);
CSR_WRITE_2(sc, WI_COMMAND, cmd);
+ CSR_WBR_2(sc, WI_COMMAND, WI_EVENT_STAT);
if (cmd == WI_CMD_INI) {
/* XXX: should sleep here. */
@@ -2429,13 +2460,16 @@
for (i = 0; i < WI_TIMEOUT; i++) {
if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
break;
+ CSR_RBR_2(sc, WI_EVENT_STAT, WI_EVENT_STAT); /* XXX paranoia? */
DELAY(WI_DELAY);
}
status = CSR_READ_2(sc, WI_STATUS);
+ CSR_RBW_2(sc, WI_STATUS, WI_EVENT_ACK);
/* Ack the command */
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
+ CSR_WBR_2(sc, WI_EVENT_ACK, WI_EVENT_STAT);
if (i == WI_TIMEOUT) {
printf("%s: command timed out, cmd=0x%x, arg=0x%x\n",
@@ -2456,11 +2490,16 @@
{
int i, status;
+ /* finish pending I/O before seeking. */
+ CSR_WBW_2(sc, WI_SEL0, WI_DATA0);
CSR_WRITE_2(sc, WI_SEL0, id);
+ CSR_WBW_2(sc, WI_SEL0, WI_OFF0); /* XXX paranoia? */
CSR_WRITE_2(sc, WI_OFF0, off);
+ CSR_WBR_2(sc, WI_SEL0, WI_OFF0);
for (i = 0; ; i++) {
status = CSR_READ_2(sc, WI_OFF0);
+ CSR_RBR_2(sc, WI_OFF0, WI_OFF0); /* XXX paranoia? */
if ((status & WI_OFF_BUSY) == 0)
break;
if (i == WI_TIMEOUT) {
@@ -2534,11 +2573,13 @@
*/
if ((sc->sc_flags & WI_FLAGS_BUG_AUTOINC) && (id & 0xf000) == 0) {
CSR_WRITE_2(sc, WI_DATA0, 0x1234);
+ CSR_WBW_2(sc, WI_DATA0, WI_DATA0);
CSR_WRITE_2(sc, WI_DATA0, 0x5678);
wi_seek_bap(sc, id, sc->sc_bap_off);
sc->sc_bap_off = WI_OFF_ERR; /* invalidate */
if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
- CSR_READ_2(sc, WI_DATA0) != 0x5678) {
+ (CSR_RBR_2(sc, WI_DATA0, WI_DATA0),
+ CSR_READ_2(sc, WI_DATA0)) != 0x5678) {
printf("%s: detect auto increment bug, try again\n",
sc->sc_dev.dv_xname);
goto again;
@@ -2589,6 +2630,7 @@
for (i = 0; i < WI_TIMEOUT; i++) {
if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
break;
+ CSR_RBR_2(sc, WI_EVENT_STAT, WI_EVENT_STAT);
if (i == WI_TIMEOUT) {
printf("%s: timeout in alloc\n", sc->sc_dev.dv_xname);
return ETIMEDOUT;
@@ -2596,6 +2638,7 @@
DELAY(1);
}
*idp = CSR_READ_2(sc, WI_ALLOC_FID);
+ CSR_RBW_2(sc, WI_ALLOC_FID, WI_EVENT_ACK);
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
return 0;
}
Index: sys/dev/ic/wivar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/wivar.h,v
retrieving revision 1.41
diff -u -r1.41 wivar.h
--- sys/dev/ic/wivar.h 7 Dec 2003 05:44:49 -0000 1.41
+++ sys/dev/ic/wivar.h 22 Dec 2003 08:08:34 -0000
@@ -248,6 +248,63 @@
(sc->sc_pci? reg * 2: reg))
#endif
+/* bus_space(9) lied? */
+#ifndef BUS_SPACE_BARRIER_SYNC
+#define BUS_SPACE_BARRIER_SYNC (BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE)
+#endif
+
+#ifndef BUS_SPACE_BARRIER_READ_BEFORE_READ
+#define BUS_SPACE_BARRIER_READ_BEFORE_READ BUS_SPACE_BARRIER_READ
+#endif
+
+#ifndef BUS_SPACE_BARRIER_READ_BEFORE_WRITE
+#define BUS_SPACE_BARRIER_READ_BEFORE_WRITE BUS_SPACE_BARRIER_READ
+#endif
+
+#ifndef BUS_SPACE_BARRIER_WRITE_BEFORE_READ
+#define BUS_SPACE_BARRIER_WRITE_BEFORE_READ BUS_SPACE_BARRIER_WRITE
+#endif
+
+#ifndef BUS_SPACE_BARRIER_WRITE_BEFORE_WRITE
+#define BUS_SPACE_BARRIER_WRITE_BEFORE_WRITE BUS_SPACE_BARRIER_WRITE
+#endif
+
+/*
+ * CSR bus barrier
+ *
+ * Complete outstanding read and/or write ops on [reg0, reg1]
+ * ([reg1, reg0]) before starting new ops on the same region. See
+ * acceptable bus_space_barrier(9) for the flag definitions.
+ */
+#define CSR_BARRIER_2(sc, reg0, reg1, flags) \
+ bus_space_barrier(sc->sc_iot, sc->sc_ioh, \
+ (sc->sc_pci ? 2 : 1) * MIN(reg0, reg1), \
+ (sc->sc_pci ? 2 : 1) * \
+ (MAX(reg0, reg1) - MIN(reg0, reg1)) + 2, flags)
+
+/*
+ * Barrier convenience macros.
+ */
+/* sync */
+#define CSR_SYNC_2(sc, reg0, reg1) \
+ CSR_BARRIER_2(sc, reg0, reg1, BUS_SPACE_BARRIER_SYNC)
+
+/* write-before-write */
+#define CSR_WBW_2(sc, reg0, reg1) \
+ CSR_BARRIER_2(sc, reg0, reg1, BUS_SPACE_BARRIER_WRITE_BEFORE_WRITE)
+
+/* write-before-read */
+#define CSR_WBR_2(sc, reg0, reg1) \
+ CSR_BARRIER_2(sc, reg0, reg1, BUS_SPACE_BARRIER_WRITE_BEFORE_READ)
+
+/* read-before-read */
+#define CSR_RBR_2(sc, reg0, reg1) \
+ CSR_BARRIER_2(sc, reg0, reg1, BUS_SPACE_BARRIER_READ_BEFORE_READ)
+
+/* read-before-read */
+#define CSR_RBW_2(sc, reg0, reg1) \
+ CSR_BARRIER_2(sc, reg0, reg1, BUS_SPACE_BARRIER_READ_BEFORE_WRITE)
+
#ifndef __BUS_SPACE_HAS_STREAM_METHODS
#define bus_space_write_stream_2 bus_space_write_2
#define bus_space_write_multi_stream_2 bus_space_write_multi_2
Index: sys/dev/pci/if_wi_pci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_wi_pci.c,v
retrieving revision 1.30
diff -u -r1.30 if_wi_pci.c
--- sys/dev/pci/if_wi_pci.c 14 Dec 2003 10:04:33 -0000 1.30
+++ sys/dev/pci/if_wi_pci.c 22 Dec 2003 08:08:34 -0000
@@ -175,17 +175,23 @@
bus_space_write_2(sc->sc_iot, sc->sc_ioh,
WI_PCI_COR, WI_COR_SOFT_RESET);
+ bus_space_barrier(sc->sc_iot, sc->sc_ioh, WI_PCI_COR, 2,
+ BUS_SPACE_BARRIER_SYNC);
DELAY(250*1000); /* 1/4 second */
bus_space_write_2(sc->sc_iot, sc->sc_ioh,
WI_PCI_COR, WI_COR_CLEAR);
+ bus_space_barrier(sc->sc_iot, sc->sc_ioh, WI_PCI_COR, 2,
+ BUS_SPACE_BARRIER_SYNC);
DELAY(500*1000); /* 1/2 second */
/* wait 2 seconds for firmware to complete initialization. */
- for (i = 200000; i--; DELAY(10))
+ for (i = 200000; i--; DELAY(10)) {
if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
break;
+ CSR_RBR_2(sc, WI_COMMAND, WI_COMMAND);
+ }
if (i < 0) {
printf("%s: PCI reset timed out\n", sc->sc_dev.dv_xname);
@@ -329,7 +335,9 @@
sc->sc_ioh = ioh;
/* Make sure interrupts are disabled. */
CSR_WRITE_2(sc, WI_INT_EN, 0);
+ CSR_WBW_2(sc, WI_INT_EN, WI_EVENT_ACK);
CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
+ CSR_WBR_2(sc, WI_EVENT_ACK, WI_EVENT_STAT);
if (wpp->wpp_chip == CHIP_PLX_OTHER) {
uint32_t command;
Index: sys/dev/pcmcia/if_wi_pcmcia.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pcmcia/if_wi_pcmcia.c,v
retrieving revision 1.38
diff -u -r1.38 if_wi_pcmcia.c
--- sys/dev/pcmcia/if_wi_pcmcia.c 7 Dec 2003 05:44:49 -0000 1.38
+++ sys/dev/pcmcia/if_wi_pcmcia.c 22 Dec 2003 08:08:34 -0000
@@ -612,25 +612,37 @@
CSR_WRITE_2(sc, WI_PARAM0, WI_AUX_KEY0);
CSR_WRITE_2(sc, WI_PARAM1, WI_AUX_KEY1);
CSR_WRITE_2(sc, WI_PARAM2, WI_AUX_KEY2);
+ /* Note: WI_PARAM0 < WI_PARAM1 < WI_PARAM2 < WI_CNTL. */
+ CSR_WBW_2(sc, WI_PARAM0, WI_CNTL);
CSR_WRITE_2(sc, WI_CNTL, WI_CNTL_AUX_ENA_CNTL);
+ /* no use tsleep'ing until after the register is written. */
+ CSR_SYNC_2(sc, WI_CNTL, WI_CNTL);
}
/* issue read EEPROM command: XXX copied from wi_cmd() */
CSR_WRITE_2(sc, WI_PARAM0, 0);
CSR_WRITE_2(sc, WI_PARAM1, 0);
CSR_WRITE_2(sc, WI_PARAM2, 0);
+ /* Note: WI_COMMAND < WI_PARAM0 < WI_PARAM1 < WI_PARAM2. */
+ CSR_WBW_2(sc, WI_COMMAND, WI_PARAM2);
CSR_WRITE_2(sc, WI_COMMAND, WI_CMD_READEE);
+ CSR_WBR_2(sc, WI_COMMAND, WI_EVENT_STAT);
for (i = 0; i < WI_TIMEOUT; i++) {
if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD)
break;
+ CSR_RBR_2(sc, WI_EVENT_STAT, WI_EVENT_STAT);/* XXX paranoia? */
DELAY(1);
}
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
+ CSR_WBR_2(sc, WI_EVENT_ACK, WI_EVENT_STAT);
CSR_WRITE_2(sc, WI_AUX_PAGE, WI_SBCF_PDIADDR / WI_AUX_PGSZ);
+ CSR_WBW_2(sc, WI_AUX_PAGE, WI_AUX_OFFSET);
CSR_WRITE_2(sc, WI_AUX_OFFSET, WI_SBCF_PDIADDR % WI_AUX_PGSZ);
+ CSR_WBR_2(sc, WI_AUX_DATA, WI_AUX_OFFSET);
CSR_READ_MULTI_STREAM_2(sc, WI_AUX_DATA,
(u_int16_t *)ebuf, sizeof(ebuf) / 2);
+ CSR_RBW_2(sc, WI_AUX_DATA, WI_AUX_PAGE);
if (GETLE16(ebuf) > sizeof(ebuf))
return EIO;
if (wi_pcmcia_write_firm(sc, secsym, seclen, ebuf + 4, GETLE16(ebuf)))
@@ -667,9 +679,12 @@
addr = GETLE32(p); p += 4;
len = GETLE16(p); p += 2;
CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
+ CSR_WBW_2(sc, WI_AUX_PAGE, WI_AUX_OFFSET);
CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
+ CSR_WBW_2(sc, WI_AUX_OFFSET, WI_AUX_DATA);
CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
(const u_int16_t *)p, len / 2);
+ CSR_WBW_2(sc, WI_AUX_PAGE, WI_AUX_DATA);
p += len;
}
@@ -690,9 +705,12 @@
if (eid != id)
continue;
CSR_WRITE_2(sc, WI_AUX_PAGE, addr / WI_AUX_PGSZ);
+ CSR_WBW_2(sc, WI_AUX_PAGE, WI_AUX_OFFSET);
CSR_WRITE_2(sc, WI_AUX_OFFSET, addr % WI_AUX_PGSZ);
+ CSR_WBW_2(sc, WI_AUX_OFFSET, WI_AUX_DATA);
CSR_WRITE_MULTI_STREAM_2(sc, WI_AUX_DATA,
(const u_int16_t *)q, len / 2);
+ CSR_WBW_2(sc, WI_AUX_OFFSET, WI_AUX_PAGE);
break;
}
}
@@ -707,12 +725,16 @@
u_int16_t hcr;
CSR_WRITE_2(sc, WI_COR, WI_COR_RESET);
+ /* no use tsleep'ing until after the register is written */
+ CSR_SYNC_2(sc, WI_COR, WI_COR);
tsleep(sc, PWAIT, "wiinit", 1);
hcr = CSR_READ_2(sc, WI_HCR);
hcr = (hcr & WI_HCR_4WIRE) | (mode & ~WI_HCR_4WIRE);
CSR_WRITE_2(sc, WI_HCR, hcr);
+ CSR_SYNC_2(sc, WI_HCR, WI_HCR);
tsleep(sc, PWAIT, "wiinit", 1);
CSR_WRITE_2(sc, WI_COR, WI_COR_IOMODE);
+ CSR_SYNC_2(sc, WI_COR, WI_COR);
tsleep(sc, PWAIT, "wiinit", 1);
return 0;
}
--W/nzBZO5zC0uMSeA--