diff options
author | jhb <jhb@FreeBSD.org> | 2012-09-17 15:27:30 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2012-09-17 15:27:30 +0000 |
commit | 1c617b0215c987e6d4fa0ebf715289dc62fad795 (patch) | |
tree | 101051e595babb417c37add67ba9f87bd7904b6a /sys/dev/mlx/mlx_pci.c | |
parent | 5d4e58ed8e46965b1c3efc1c7bb56298074b68dd (diff) | |
download | FreeBSD-src-1c617b0215c987e6d4fa0ebf715289dc62fad795.zip FreeBSD-src-1c617b0215c987e6d4fa0ebf715289dc62fad795.tar.gz |
Add locking to mlx(4) to make it MPSAFE along with some other fixes:
- Use callout(9) rather than timeout(9).
- Add a mutex as an I/O lock that protects the adapter and is used
for the I/O path.
- Add an sx lock as a configuration lock that protects the relationship
of configured volumes.
- Freeze the request queue when a DMA load is deferred with EINPROGRESS
and unfreeze the queue when the DMA callback is invoked.
- Explicitly poll the hardware while waiting to submit a command to
allow completed commands to free up slots in the command ring.
- Remove driver-wide 'initted' variable from mlx_*_fw_handshake() routines.
That state should be per-controller instead. Add it as an argument
since the first caller knows when it is the first caller.
- Remove explicit bus_space tag/handle and use bus_*() rather than
bus_space_*().
- Move duplicated PCI device ID probing into a mlx_pci_match() routine.
- Don't check for PCIM_CMD_MEMEN (the PCI bus will enable that when
allocating the resource) and use pci_enable_busmaster() rather than
manipulating the register directly.
Tested by: no one despite multiple requests (hope it works)
Diffstat (limited to 'sys/dev/mlx/mlx_pci.c')
-rw-r--r-- | sys/dev/mlx/mlx_pci.c | 71 |
1 files changed, 33 insertions, 38 deletions
diff --git a/sys/dev/mlx/mlx_pci.c b/sys/dev/mlx/mlx_pci.c index 92ad878..abc2d90 100644 --- a/sys/dev/mlx/mlx_pci.c +++ b/sys/dev/mlx/mlx_pci.c @@ -30,7 +30,10 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> +#include <sys/lock.h> #include <sys/module.h> +#include <sys/mutex.h> +#include <sys/sx.h> #include <sys/bus.h> #include <sys/conf.h> @@ -88,6 +91,21 @@ struct mlx_ident {0, 0, 0, 0, 0, 0} }; +static struct mlx_ident * +mlx_pci_match(device_t dev) +{ + struct mlx_ident *m; + + for (m = mlx_identifiers; m->vendor != 0; m++) { + if ((m->vendor == pci_get_vendor(dev)) && + (m->device == pci_get_device(dev)) && + ((m->subvendor == 0) || ((m->subvendor == pci_get_subvendor(dev)) && + (m->subdevice == pci_get_subdevice(dev))))) + return (m); + } + return (NULL); +} + static int mlx_pci_probe(device_t dev) { @@ -95,15 +113,10 @@ mlx_pci_probe(device_t dev) debug_called(1); - for (m = mlx_identifiers; m->vendor != 0; m++) { - if ((m->vendor == pci_get_vendor(dev)) && - (m->device == pci_get_device(dev)) && - ((m->subvendor == 0) || ((m->subvendor == pci_get_subvendor(dev)) && - (m->subdevice == pci_get_subdevice(dev))))) { - - device_set_desc(dev, m->desc); - return(BUS_PROBE_DEFAULT); - } + m = mlx_pci_match(dev); + if (m != NULL) { + device_set_desc(dev, m->desc); + return(BUS_PROBE_DEFAULT); } return(ENXIO); } @@ -112,45 +125,29 @@ static int mlx_pci_attach(device_t dev) { struct mlx_softc *sc; - int i, error; - u_int32_t command; + struct mlx_ident *m; + int error; debug_called(1); - /* - * Make sure we are going to be able to talk to this board. - */ - command = pci_read_config(dev, PCIR_COMMAND, 2); - if ((command & PCIM_CMD_MEMEN) == 0) { - device_printf(dev, "memory window not available\n"); - return(ENXIO); - } - /* force the busmaster enable bit on */ - command |= PCIM_CMD_BUSMASTEREN; - pci_write_config(dev, PCIR_COMMAND, command, 2); + pci_enable_busmaster(dev); - /* - * Initialise softc. - */ sc = device_get_softc(dev); - bzero(sc, sizeof(*sc)); sc->mlx_dev = dev; /* * Work out what sort of adapter this is (we need to know this in order * to map the appropriate interface resources). */ - sc->mlx_iftype = 0; - for (i = 0; mlx_identifiers[i].vendor != 0; i++) { - if ((mlx_identifiers[i].vendor == pci_get_vendor(dev)) && - (mlx_identifiers[i].device == pci_get_device(dev))) { - sc->mlx_iftype = mlx_identifiers[i].iftype; - break; - } - } - if (sc->mlx_iftype == 0) /* shouldn't happen */ + m = mlx_pci_match(dev); + if (m == NULL) /* shouldn't happen */ return(ENXIO); - + sc->mlx_iftype = m->iftype; + + mtx_init(&sc->mlx_io_lock, "mlx I/O", NULL, MTX_DEF); + sx_init(&sc->mlx_config_lock, "mlx config"); + callout_init_mtx(&sc->mlx_timeout, &sc->mlx_io_lock, 0); + /* * Allocate the PCI register window. */ @@ -183,8 +180,6 @@ mlx_pci_attach(device_t dev) mlx_free(sc); return(ENXIO); } - sc->mlx_btag = rman_get_bustag(sc->mlx_mem); - sc->mlx_bhandle = rman_get_bushandle(sc->mlx_mem); /* * Allocate the parent bus DMA tag appropriate for PCI. |