summaryrefslogtreecommitdiffstats
path: root/sys/dev/mlx/mlx_pci.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2012-09-17 15:27:30 +0000
committerjhb <jhb@FreeBSD.org>2012-09-17 15:27:30 +0000
commit1c617b0215c987e6d4fa0ebf715289dc62fad795 (patch)
tree101051e595babb417c37add67ba9f87bd7904b6a /sys/dev/mlx/mlx_pci.c
parent5d4e58ed8e46965b1c3efc1c7bb56298074b68dd (diff)
downloadFreeBSD-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.c71
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.
OpenPOWER on IntegriCloud