Do mii frobbing in process context.

Now we can finally get rid of the evil USBD_NO_TSLEEP hack in the aue driver.
This commit is contained in:
augustss 2001-04-13 11:17:11 +00:00
parent b728f196e9
commit cbcea5e84c
2 changed files with 73 additions and 33 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_aue.c,v 1.55 2001/03/25 22:59:43 augustss Exp $ */
/* $NetBSD: if_aue.c,v 1.56 2001/04/13 11:17:11 augustss Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000
* Bill Paul <wpaul@ee.columbia.edu>. All rights reserved.
@ -88,6 +88,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sockio.h>
#include <sys/lock.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
@ -191,6 +192,7 @@ Static void aue_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
Static void aue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
Static void aue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
Static void aue_tick(void *);
Static void aue_tick_task(void *);
Static void aue_start(struct ifnet *);
Static int aue_ioctl(struct ifnet *, u_long, caddr_t);
Static void aue_init(void *);
@ -206,6 +208,9 @@ Static int aue_miibus_readreg(device_ptr_t, int, int);
Static void aue_miibus_writereg(device_ptr_t, int, int, int);
Static void aue_miibus_statchg(device_ptr_t);
Static void aue_lock_mii(struct aue_softc *);
Static void aue_unlock_mii(struct aue_softc *);
Static void aue_setmulti(struct aue_softc *);
Static u_int32_t aue_crc(caddr_t);
Static void aue_reset(struct aue_softc *);
@ -215,9 +220,6 @@ Static int aue_csr_write_1(struct aue_softc *, int, int);
Static int aue_csr_read_2(struct aue_softc *, int);
Static int aue_csr_write_2(struct aue_softc *, int, int);
#define AUE_DO_REQUEST(dev, req, data) \
usbd_do_request_flags(dev, req, data, USBD_NO_TSLEEP, NULL)
#define AUE_SETBIT(sc, reg, x) \
aue_csr_write_1(sc, reg, aue_csr_read_1(sc, reg) | (x))
@ -230,7 +232,6 @@ aue_csr_read_1(struct aue_softc *sc, int reg)
usb_device_request_t req;
usbd_status err;
uByte val = 0;
int s;
if (sc->aue_dying)
return (0);
@ -241,9 +242,7 @@ aue_csr_read_1(struct aue_softc *sc, int reg)
USETW(req.wIndex, reg);
USETW(req.wLength, 1);
s = splusb();
err = AUE_DO_REQUEST(sc->aue_udev, &req, &val);
splx(s);
err = usbd_do_request(sc->aue_udev, &req, &val);
if (err) {
DPRINTF(("%s: aue_csr_read_1: reg=0x%x err=%s\n",
@ -260,7 +259,6 @@ aue_csr_read_2(struct aue_softc *sc, int reg)
usb_device_request_t req;
usbd_status err;
uWord val;
int s;
if (sc->aue_dying)
return (0);
@ -271,9 +269,7 @@ aue_csr_read_2(struct aue_softc *sc, int reg)
USETW(req.wIndex, reg);
USETW(req.wLength, 2);
s = splusb();
err = AUE_DO_REQUEST(sc->aue_udev, &req, &val);
splx(s);
err = usbd_do_request(sc->aue_udev, &req, &val);
if (err) {
DPRINTF(("%s: aue_csr_read_2: reg=0x%x err=%s\n",
@ -289,7 +285,6 @@ aue_csr_write_1(struct aue_softc *sc, int reg, int aval)
{
usb_device_request_t req;
usbd_status err;
int s;
uByte val;
if (sc->aue_dying)
@ -302,9 +297,7 @@ aue_csr_write_1(struct aue_softc *sc, int reg, int aval)
USETW(req.wIndex, reg);
USETW(req.wLength, 1);
s = splusb();
err = AUE_DO_REQUEST(sc->aue_udev, &req, &val);
splx(s);
err = usbd_do_request(sc->aue_udev, &req, &val);
if (err) {
DPRINTF(("%s: aue_csr_write_1: reg=0x%x err=%s\n",
@ -320,7 +313,6 @@ aue_csr_write_2(struct aue_softc *sc, int reg, int aval)
{
usb_device_request_t req;
usbd_status err;
int s;
uWord val;
if (sc->aue_dying)
@ -333,9 +325,7 @@ aue_csr_write_2(struct aue_softc *sc, int reg, int aval)
USETW(req.wIndex, reg);
USETW(req.wLength, 2);
s = splusb();
err = AUE_DO_REQUEST(sc->aue_udev, &req, &val);
splx(s);
err = usbd_do_request(sc->aue_udev, &req, &val);
if (err) {
DPRINTF(("%s: aue_csr_write_2: reg=0x%x err=%s\n",
@ -389,6 +379,19 @@ aue_read_mac(struct aue_softc *sc, u_char *dest)
}
}
/* Get exclusive access to the MII registers */
Static void
aue_lock_mii(struct aue_softc *sc)
{
lockmgr(&sc->aue_mii_lock, LK_EXCLUSIVE, NULL);
}
Static void
aue_unlock_mii(struct aue_softc *sc)
{
lockmgr(&sc->aue_mii_lock, LK_RELEASE, NULL);
}
Static int
aue_miibus_readreg(device_ptr_t dev, int phy, int reg)
{
@ -414,6 +417,7 @@ aue_miibus_readreg(device_ptr_t dev, int phy, int reg)
}
#endif
aue_lock_mii(sc);
aue_csr_write_1(sc, AUE_PHY_ADDR, phy);
aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_READ);
@ -431,6 +435,7 @@ aue_miibus_readreg(device_ptr_t dev, int phy, int reg)
DPRINTFN(11,("%s: %s: phy=%d reg=%d => 0x%04x\n",
USBDEVNAME(sc->aue_dev), __FUNCTION__, phy, reg, val));
aue_unlock_mii(sc);
return (val);
}
@ -451,6 +456,7 @@ aue_miibus_writereg(device_ptr_t dev, int phy, int reg, int data)
DPRINTFN(11,("%s: %s: phy=%d reg=%d data=0x%04x\n",
USBDEVNAME(sc->aue_dev), __FUNCTION__, phy, reg, data));
aue_lock_mii(sc);
aue_csr_write_2(sc, AUE_PHY_DATA, data);
aue_csr_write_1(sc, AUE_PHY_ADDR, phy);
aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_WRITE);
@ -464,6 +470,7 @@ aue_miibus_writereg(device_ptr_t dev, int phy, int reg, int data)
printf("%s: MII read timed out\n",
USBDEVNAME(sc->aue_dev));
}
aue_unlock_mii(sc);
}
Static void
@ -474,6 +481,7 @@ aue_miibus_statchg(device_ptr_t dev)
DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->aue_dev), __FUNCTION__));
aue_lock_mii(sc);
AUE_CLRBIT(sc, AUE_CTL0, AUE_CTL0_RX_ENB | AUE_CTL0_TX_ENB);
if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) {
@ -488,6 +496,7 @@ aue_miibus_statchg(device_ptr_t dev)
AUE_CLRBIT(sc, AUE_CTL1, AUE_CTL1_DUPLEX);
AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_RX_ENB | AUE_CTL0_TX_ENB);
aue_unlock_mii(sc);
/*
* Set the LED modes on the LinkSys adapter.
@ -664,6 +673,10 @@ USB_ATTACH(aue)
USB_ATTACH_ERROR_RETURN;
}
usb_init_task(&sc->aue_tick_task, aue_tick_task, sc);
usb_init_task(&sc->aue_stop_task, (void (*)(void *))aue_stop, sc);
lockinit(&sc->aue_mii_lock, PZERO, "auemii", 0, 0);
err = usbd_device2interface_handle(dev, AUE_IFACE_IDX, &iface);
if (err) {
printf("%s: getting interface handle failed\n",
@ -707,7 +720,7 @@ USB_ATTACH(aue)
}
s = splimp();
s = splnet();
/* Reset the adapter. */
aue_reset(sc);
@ -744,6 +757,7 @@ USB_ATTACH(aue)
mii->mii_readreg = aue_miibus_readreg;
mii->mii_writereg = aue_miibus_writereg;
mii->mii_statchg = aue_miibus_statchg;
mii->mii_flags = MIIF_AUTOTSLEEP;
ifmedia_init(&mii->mii_media, 0, aue_ifmedia_upd, aue_ifmedia_sts);
mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);
if (LIST_FIRST(&mii->mii_phys) == NULL) {
@ -779,9 +793,15 @@ USB_DETACH(aue)
DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->aue_dev), __FUNCTION__));
s = splusb();
usb_uncallout(sc->aue_stat_ch, aue_tick, sc);
/*
* Remove any pending tasks. They cannot be executing because they run
* in the same thread as detach.
*/
usb_rem_task(sc->aue_udev, &sc->aue_tick_task);
usb_rem_task(sc->aue_udev, &sc->aue_stop_task);
s = splusb();
if (!sc->aue_attached) {
/* Detached before attached finished, so just bail out. */
@ -1037,7 +1057,7 @@ aue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
m->m_pkthdr.rcvif = ifp;
s = splimp();
s = splnet();
/* XXX ugly */
if (aue_newbuf(sc, c, NULL) == ENOBUFS) {
@ -1091,7 +1111,7 @@ aue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
if (sc->aue_dying)
return;
s = splimp();
s = splnet();
DPRINTFN(10,("%s: %s: enter status=%d\n", USBDEVNAME(sc->aue_dev),
__FUNCTION__, status));
@ -1128,15 +1148,29 @@ Static void
aue_tick(void *xsc)
{
struct aue_softc *sc = xsc;
struct ifnet *ifp;
struct mii_data *mii;
int s;
DPRINTFN(15,("%s: %s: enter\n", USBDEVNAME(sc->aue_dev),__FUNCTION__));
if (sc == NULL)
return;
if (sc->aue_dying)
return;
/* Perform periodic stuff in process context. */
usb_add_task(sc->aue_udev, &sc->aue_tick_task);
}
Static void
aue_tick_task(void *xsc)
{
struct aue_softc *sc = xsc;
struct ifnet *ifp;
struct mii_data *mii;
int s;
DPRINTFN(15,("%s: %s: enter\n", USBDEVNAME(sc->aue_dev),__FUNCTION__));
if (sc->aue_dying)
return;
@ -1145,7 +1179,7 @@ aue_tick(void *xsc)
if (mii == NULL)
return;
s = splimp();
s = splnet();
mii_tick(mii);
if (!sc->aue_link) {
@ -1202,7 +1236,8 @@ aue_send(struct aue_softc *sc, struct mbuf *m, int idx)
if (err != USBD_IN_PROGRESS) {
printf("%s: aue_send error=%s\n", USBDEVNAME(sc->aue_dev),
usbd_errstr(err));
aue_stop(sc);
/* Stop the interface from process context. */
usb_add_task(sc->aue_udev, &sc->aue_stop_task);
return (EIO);
}
DPRINTFN(5,("%s: %s: send %d bytes\n", USBDEVNAME(sc->aue_dev),
@ -1276,7 +1311,7 @@ aue_init(void *xsc)
if (ifp->if_flags & IFF_RUNNING)
return;
s = splimp();
s = splnet();
/*
* Cancel pending I/O and free all RX/TX buffers.
@ -1437,7 +1472,7 @@ aue_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if (sc->aue_dying)
return (EIO);
s = splimp();
s = splnet();
switch(command) {
case SIOCSIFADDR:

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_auereg.h,v 1.13 2000/05/06 20:38:59 augustss Exp $ */
/* $NetBSD: if_auereg.h,v 1.14 2001/04/13 11:17:11 augustss Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
* Bill Paul <wpaul@ee.columbia.edu>. All rights reserved.
@ -265,6 +265,11 @@ struct aue_softc {
u_int aue_rx_errs;
u_int aue_intr_errs;
struct timeval aue_rx_notice;
struct usb_task aue_tick_task;
struct usb_task aue_stop_task;
struct lock aue_mii_lock;
};
#define AUE_TIMEOUT 1000