We occasionally access the register from two or more processes. Please

use the simple-queue.
This commit is contained in:
kiyohara 2007-06-16 11:18:45 +00:00
parent cc7db3d88b
commit c3234fb8d7
2 changed files with 49 additions and 18 deletions

View File

@ -1,5 +1,5 @@
/* $OpenBSD: if_zyd.c,v 1.52 2007/02/11 00:08:04 jsg Exp $ */
/* $NetBSD: if_zyd.c,v 1.4 2007/06/16 11:09:31 kiyohara Exp $ */
/* $NetBSD: if_zyd.c,v 1.5 2007/06/16 11:18:45 kiyohara Exp $ */
/*-
* Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr>
@ -22,7 +22,7 @@
* ZyDAS ZD1211/ZD1211B USB WLAN driver.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_zyd.c,v 1.4 2007/06/16 11:09:31 kiyohara Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_zyd.c,v 1.5 2007/06/16 11:18:45 kiyohara Exp $");
#include "bpfilter.h"
@ -328,6 +328,8 @@ USB_ATTACH(zyd)
/* XXXX: alloc temporarily until the layer2 can be configured. */
if_alloc_sadl(ifp);
SIMPLEQ_INIT(&sc->sc_rqh);
USB_ATTACH_SUCCESS_RETURN;
}
@ -791,6 +793,7 @@ zyd_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, int ilen,
{
usbd_xfer_handle xfer;
struct zyd_cmd cmd;
struct rq rq;
uint16_t xferflags;
usbd_status error;
int s = 0;
@ -804,11 +807,13 @@ zyd_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, int ilen,
xferflags = USBD_FORCE_SHORT_XFER;
if (!(flags & ZYD_CMD_FLAG_READ))
xferflags |= USBD_SYNCHRONOUS;
else
else {
s = splusb();
sc->odata = odata;
sc->olen = olen;
rq.idata = idata;
rq.odata = odata;
rq.len = olen / sizeof (struct zyd_pair);
SIMPLEQ_INSERT_TAIL(&sc->sc_rqh, &rq, rq);
}
usbd_setup_xfer(xfer, sc->zyd_ep[ZYD_ENDPT_IOUT], 0, &cmd,
sizeof (uint16_t) + ilen, xferflags, ZYD_INTR_TIMEOUT, NULL);
@ -826,8 +831,10 @@ zyd_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, int ilen,
return 0; /* write: don't wait for reply */
}
/* wait at most one second for command reply */
error = tsleep(sc, PCATCH, "zydcmd", hz);
sc->odata = NULL; /* in case answer is received too late */
error = tsleep(odata, PCATCH, "zydcmd", hz);
if (error == EWOULDBLOCK)
printf("%s: zyd_read sleep timeout\n", USBDEVNAME(sc->sc_dev));
SIMPLEQ_REMOVE(&sc->sc_rqh, &rq, rq, rq);
splx(s);
(void)usbd_free_xfer(xfer);
@ -1810,7 +1817,7 @@ zyd_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
{
struct zyd_softc *sc = (struct zyd_softc *)priv;
struct zyd_cmd *cmd;
uint32_t len;
uint32_t datalen;
if (status != USBD_NORMAL_COMPLETION) {
if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
@ -1854,18 +1861,36 @@ zyd_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
ifp->if_oerrors++; /* too many retries */
} else if (le16toh(cmd->code) == ZYD_NOTIF_IORD) {
struct rq *rqp;
if (le16toh(*(uint16_t *)cmd->data) == ZYD_CR_INTERRUPT)
return; /* HMAC interrupt */
if (sc->odata == NULL)
return; /* unexpected IORD notification */
usbd_get_xfer_status(xfer, NULL, NULL, &datalen, NULL);
datalen -= sizeof(cmd->code);
datalen -= 2; /* XXX: padding? */
/* copy answer into caller-supplied buffer */
usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
bcopy(cmd->data, sc->odata, sc->olen);
SIMPLEQ_FOREACH(rqp, &sc->sc_rqh, rq) {
int i;
wakeup(sc); /* wakeup caller */
if (rqp->len != datalen)
continue;
for (i = 0; i < rqp->len; i++) {
if (*(((const uint16_t *)rqp->idata) + i) !=
(((struct zyd_pair *)cmd->data) + i)->reg)
break;
}
if (i != rqp->len)
continue;
/* copy answer into caller-supplied buffer */
bcopy(cmd->data, rqp->odata,
sizeof(struct zyd_pair) * rqp->len);
wakeup(rqp->odata); /* wakeup caller */
return;
}
return; /* unexpected IORD notification */
} else {
printf("%s: unknown notification %x\n", USBDEVNAME(sc->sc_dev),
le16toh(cmd->code));

View File

@ -1,5 +1,5 @@
/* $OpenBSD: if_zydreg.h,v 1.19 2006/11/30 19:28:07 damien Exp $ */
/* $NetBSD: if_zydreg.h,v 1.1 2007/06/09 11:20:55 kiyohara Exp $ */
/* $NetBSD: if_zydreg.h,v 1.2 2007/06/16 11:18:45 kiyohara Exp $ */
/*-
* Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr>
@ -1158,6 +1158,13 @@ struct zyd_rf {
int width;
};
struct rq {
const uint16_t *idata;
struct zyd_pair *odata;
int len;
SIMPLEQ_ENTRY(rq) rq;
};
struct zyd_softc {
USBBASEDEVICE sc_dev;
struct ethercom sc_ec;
@ -1183,8 +1190,7 @@ struct zyd_softc {
struct ieee80211_amrr amrr;
void *odata;
int olen;
SIMPLEQ_HEAD(rqh, rq) sc_rqh;
uint16_t fwbase;
uint8_t regdomain;