summaryrefslogtreecommitdiffstats
path: root/sys/dev/pdq/if_fpa.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2009-11-19 19:25:47 +0000
committerjhb <jhb@FreeBSD.org>2009-11-19 19:25:47 +0000
commitfe250fcdf4c9009883dd08122d4d08d2f070dcc8 (patch)
tree8e7c8dbe27ba288246c747dd803c2e949f1da3cd /sys/dev/pdq/if_fpa.c
parent92fc9b53e8ad2c7ba20dc51ea8c0099d4196560f (diff)
downloadFreeBSD-src-fe250fcdf4c9009883dd08122d4d08d2f070dcc8.zip
FreeBSD-src-fe250fcdf4c9009883dd08122d4d08d2f070dcc8.tar.gz
Several fixes to these drivers. Note that these two drivers are actually
just two different attachments (EISA and PCI) to a single driver. - Add real locking. Previously these drivers only acquired their lock in their interrupt handler or in the ioctl routine (but too broadly in the latter). No locking was used for the stack calling down into the driver via if_init() or if_start(), for device shutdown or detach. Also, the interrupt handler held the driver lock while calling if_input(). All this stuff should be fixed in the locking changes. - Really fix these drivers to handle if_alloc(). The front-end attachments were using if_initname() before the ifnet was allocated. Fix this by moving some of the duplicated logic from each driver into pdq_ifattach(). While here, make pdq_ifattach() return an error so that the driver just fails to attach if if_alloc() fails rather than panic'ing. Also, defer freeing the ifnet until the driver has stopped using it during detach. - Add a new private timer to drive the watchdog timer. - Pass the softc pointer to the interrupt handlers instead of the device_t so we can avoid the use of device_get_softc() and to better match what other drivers do.
Diffstat (limited to 'sys/dev/pdq/if_fpa.c')
-rw-r--r--sys/dev/pdq/if_fpa.c30
1 files changed, 10 insertions, 20 deletions
diff --git a/sys/dev/pdq/if_fpa.c b/sys/dev/pdq/if_fpa.c
index ced3b8f..3fe88ad 100644
--- a/sys/dev/pdq/if_fpa.c
+++ b/sys/dev/pdq/if_fpa.c
@@ -73,11 +73,9 @@ static void pdq_pci_ifintr (void *);
static void
pdq_pci_ifintr(void *arg)
{
- device_t dev;
pdq_softc_t *sc;
- dev = (device_t)arg;
- sc = device_get_softc(dev);
+ sc = arg;
PDQ_LOCK(sc);
(void) pdq_interrupt(sc->sc_pdq);
@@ -105,12 +103,10 @@ static int
pdq_pci_attach(device_t dev)
{
pdq_softc_t *sc;
- struct ifnet *ifp;
u_int32_t command;
int error;
sc = device_get_softc(dev);
- ifp = sc->ifp;
sc->dev = dev;
@@ -146,26 +142,18 @@ pdq_pci_attach(device_t dev)
goto bad;
}
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
-
- sc->sc_pdq = pdq_initialize(sc->mem_bst, sc->mem_bsh,
- ifp->if_xname, -1,
- (void *)sc, PDQ_DEFPA);
- if (sc->sc_pdq == NULL) {
- device_printf(dev, "Initialization failed.\n");
- error = ENXIO;
+ error = pdq_ifattach(sc, sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, PDQ_DEFPA);
+ if (error)
goto bad;
- }
-
- error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, NULL,
- pdq_pci_ifintr, dev, &sc->irq_ih);
+
+ error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, NULL,
+ pdq_pci_ifintr, sc, &sc->irq_ih);
if (error) {
device_printf(dev, "Failed to setup interrupt handler.\n");
- error = ENXIO;
- goto bad;
+ pdq_ifdetach(sc);
+ return (error);
}
- pdq_ifattach(sc, sc->sc_pdq->pdq_hwaddr.lanaddr_bytes);
return (0);
bad:
@@ -191,7 +179,9 @@ pdq_pci_shutdown(device_t dev)
pdq_softc_t *sc;
sc = device_get_softc(dev);
+ PDQ_LOCK(sc);
pdq_hwreset(sc->sc_pdq);
+ PDQ_UNLOCK(sc);
return (0);
}
OpenPOWER on IntegriCloud