summaryrefslogtreecommitdiffstats
path: root/sys/dev/aac
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2003-02-10 00:34:24 +0000
committerscottl <scottl@FreeBSD.org>2003-02-10 00:34:24 +0000
commit2daf7453dde98804a70cc16585f80bd268c9a87e (patch)
treef1e3dc2506bcce1e8d198b6f3d0708e0a036dc58 /sys/dev/aac
parenta616f22441fef6592f8c15c7b6d9c2b733127d50 (diff)
downloadFreeBSD-src-2daf7453dde98804a70cc16585f80bd268c9a87e.zip
FreeBSD-src-2daf7453dde98804a70cc16585f80bd268c9a87e.tar.gz
Implement a new dynamic command allocator. FIBs are allocated in 1 page
blocks now, which should eliminate problems with the driver failing to attach due to insufficient contiguous RAM. Allow the FIB pool to grow from the default of 128 to the max of 512 as demand grows. Also pad the adapter init struct to work around the 2120/2200 DMA bug now that there is no longer a FIB slab.
Diffstat (limited to 'sys/dev/aac')
-rw-r--r--sys/dev/aac/aac.c127
-rw-r--r--sys/dev/aac/aac_pci.c2
-rw-r--r--sys/dev/aac/aacvar.h23
3 files changed, 96 insertions, 56 deletions
diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c
index f612c15..509026e 100644
--- a/sys/dev/aac/aac.c
+++ b/sys/dev/aac/aac.c
@@ -89,7 +89,7 @@ static void aac_host_response(struct aac_softc *sc);
static void aac_map_command_helper(void *arg, bus_dma_segment_t *segs,
int nseg, int error);
static int aac_alloc_commands(struct aac_softc *sc);
-static void aac_free_commands(struct aac_softc *sc);
+static void aac_free_commands(struct aac_softc *sc, struct aac_fibmap *fm);
static void aac_map_command(struct aac_command *cm);
static void aac_unmap_command(struct aac_command *cm);
@@ -257,13 +257,6 @@ aac_attach(struct aac_softc *sc)
if ((error = aac_check_firmware(sc)) != 0)
return(error);
- /*
- * Allocate command structures. This must be done before aac_init()
- * in order to work around a 2120/2200 bug.
- */
- if ((error = aac_alloc_commands(sc)) != 0)
- return(error);
-
/* Init the sync fib lock */
AAC_LOCK_INIT(&sc->aac_sync_lock, "AAC sync FIB lock");
@@ -434,6 +427,8 @@ aac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f)
void
aac_free(struct aac_softc *sc)
{
+ struct aac_fibmap *fm;
+
debug_called(1);
/* remove the control device */
@@ -441,11 +436,16 @@ aac_free(struct aac_softc *sc)
destroy_dev(sc->aac_dev_t);
/* throw away any FIB buffers, discard the FIB DMA tag */
- if (sc->aac_fibs != NULL)
- aac_free_commands(sc);
+ while ((fm = TAILQ_FIRST(&sc->aac_fibmap_tqh)) != NULL) {
+ TAILQ_REMOVE(&sc->aac_fibmap_tqh, fm, fm_link);
+ aac_free_commands(sc, fm);
+ free(fm, M_AACBUF);
+ }
if (sc->aac_fib_dmat)
bus_dma_tag_destroy(sc->aac_fib_dmat);
+ free(sc->aac_commands, M_AACBUF);
+
/* destroy the common area */
if (sc->aac_common) {
bus_dmamap_unload(sc->aac_common_dmat, sc->aac_common_dmamap);
@@ -1096,8 +1096,12 @@ aac_alloc_command(struct aac_softc *sc, struct aac_command **cmp)
debug_called(3);
- if ((cm = aac_dequeue_free(sc)) == NULL)
- return(ENOMEM);
+ if ((cm = aac_dequeue_free(sc)) == NULL) {
+ if (aac_alloc_commands(sc))
+ return(ENOMEM);
+ if ((cm = aac_dequeue_free(sc)) == NULL)
+ return (ENOMEM);
+ }
*cmp = cm;
return(0);
@@ -1139,13 +1143,13 @@ aac_release_command(struct aac_command *cm)
static void
aac_map_command_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
- struct aac_softc *sc;
+ uintptr_t *fibphys;
- sc = (struct aac_softc *)arg;
+ fibphys = (uintptr_t *)arg;
debug_called(3);
- sc->aac_fibphys = segs[0].ds_addr;
+ *fibphys = segs[0].ds_addr;
}
/*
@@ -1155,44 +1159,49 @@ static int
aac_alloc_commands(struct aac_softc *sc)
{
struct aac_command *cm;
- int i;
+ struct aac_fibmap *fm;
+ uintptr_t fibphys;
+ int i, error;
debug_called(1);
+ if (sc->total_fibs + AAC_FIB_COUNT > AAC_MAX_FIBS)
+ return (ENOMEM);
+
+ fm = malloc(sizeof(struct aac_fibmap), M_AACBUF, /*M_WAITOK|*/M_ZERO);
+
/* allocate the FIBs in DMAable memory and load them */
- if (bus_dmamem_alloc(sc->aac_fib_dmat, (void **)&sc->aac_fibs,
- BUS_DMA_NOWAIT, &sc->aac_fibmap)) {
+ if (bus_dmamem_alloc(sc->aac_fib_dmat, (void **)&fm->aac_fibs,
+ BUS_DMA_NOWAIT, &fm->aac_fibmap)) {
device_printf(sc->aac_dev,
"Not enough contiguous memory available.\n");
return (ENOMEM);
}
- /*
- * Work around a bug in the 2120 and 2200 that cannot DMA commands
- * below address 8192 in physical memory.
- * XXX If the padding is not needed, can it be put to use instead
- * of ignored?
- */
- bus_dmamap_load(sc->aac_fib_dmat, sc->aac_fibmap, sc->aac_fibs,
- 8192 + AAC_FIB_COUNT * sizeof(struct aac_fib),
- aac_map_command_helper, sc, 0);
-
- if (sc->aac_fibphys < 8192) {
- sc->aac_fibs += (8192 / sizeof(struct aac_fib));
- sc->aac_fibphys += 8192;
- }
+ bus_dmamap_load(sc->aac_fib_dmat, fm->aac_fibmap, fm->aac_fibs,
+ AAC_FIB_COUNT * sizeof(struct aac_fib),
+ aac_map_command_helper, &fibphys, 0);
/* initialise constant fields in the command structure */
- bzero(sc->aac_fibs, AAC_FIB_COUNT * sizeof(struct aac_fib));
+ bzero(fm->aac_fibs, AAC_FIB_COUNT * sizeof(struct aac_fib));
for (i = 0; i < AAC_FIB_COUNT; i++) {
- cm = &sc->aac_command[i];
+ cm = sc->aac_commands + sc->total_fibs + i;
+ fm->aac_commands = cm;
cm->cm_sc = sc;
- cm->cm_fib = sc->aac_fibs + i;
- cm->cm_fibphys = sc->aac_fibphys + (i * sizeof(struct aac_fib));
+ cm->cm_fib = fm->aac_fibs + i;
+ cm->cm_fibphys = (uint32_t)fibphys +
+ (i * sizeof(struct aac_fib));
- if (!bus_dmamap_create(sc->aac_buffer_dmat, 0, &cm->cm_datamap))
+ if ((error = bus_dmamap_create(sc->aac_buffer_dmat, 0,
+ &cm->cm_datamap)) == 0)
aac_release_command(cm);
+ else
+ return (error);
}
+
+ sc->total_fibs += AAC_FIB_COUNT;
+ TAILQ_INSERT_TAIL(&sc->aac_fibmap_tqh, fm, fm_link);
+
return (0);
}
@@ -1200,18 +1209,20 @@ aac_alloc_commands(struct aac_softc *sc)
* Free FIBs owned by this adapter.
*/
static void
-aac_free_commands(struct aac_softc *sc)
+aac_free_commands(struct aac_softc *sc, struct aac_fibmap *fm)
{
+ struct aac_command *cm;
int i;
debug_called(1);
- for (i = 0; i < AAC_FIB_COUNT; i++)
- bus_dmamap_destroy(sc->aac_buffer_dmat,
- sc->aac_command[i].cm_datamap);
+ for (i = 0; i < AAC_FIB_COUNT; i++) {
+ cm = fm->aac_commands + i;
+ bus_dmamap_destroy(sc->aac_buffer_dmat, cm->cm_datamap);
+ }
- bus_dmamap_unload(sc->aac_fib_dmat, sc->aac_fibmap);
- bus_dmamem_free(sc->aac_fib_dmat, sc->aac_fibs, sc->aac_fibmap);
+ bus_dmamap_unload(sc->aac_fib_dmat, fm->aac_fibmap);
+ bus_dmamem_free(sc->aac_fib_dmat, fm->aac_fibs, fm->aac_fibmap);
}
/*
@@ -1364,6 +1375,7 @@ aac_init(struct aac_softc *sc)
time_t then;
u_int32_t code;
u_int8_t *qaddr;
+ int i;
debug_called(1);
@@ -1398,7 +1410,7 @@ aac_init(struct aac_softc *sc)
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
- sizeof(struct aac_common), /* maxsize */
+ 8192 + sizeof(struct aac_common), /* maxsize */
1, /* nsegments */
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
0, /* flags */
@@ -1412,10 +1424,33 @@ aac_init(struct aac_softc *sc)
device_printf(sc->aac_dev, "can't allocate common structure\n");
return(ENOMEM);
}
+
+ /*
+ * Work around a bug in the 2120 and 2200 that cannot DMA commands
+ * below address 8192 in physical memory.
+ * XXX If the padding is not needed, can it be put to use instead
+ * of ignored?
+ */
bus_dmamap_load(sc->aac_common_dmat, sc->aac_common_dmamap,
- sc->aac_common, sizeof(*sc->aac_common), aac_common_map,
- sc, 0);
+ sc->aac_common, 8192 + sizeof(*sc->aac_common),
+ aac_common_map, sc, 0);
+
+ if (sc->aac_common_busaddr < 8192) {
+ (uint8_t *)sc->aac_common += 8192;
+ sc->aac_common_busaddr += 8192;
+ }
bzero(sc->aac_common, sizeof(*sc->aac_common));
+
+ /* Allocate some FIBs and associated command structs */
+ TAILQ_INIT(&sc->aac_fibmap_tqh);
+ sc->aac_commands = malloc(AAC_MAX_FIBS * sizeof(struct aac_command),
+ M_AACBUF, /*M_WAITOK|*/M_ZERO);
+ for (i = 0; i < 16; i++) {
+ if (aac_alloc_commands(sc) != 0)
+ break;
+ }
+ if (sc->total_fibs == 0)
+ return (ENOMEM);
/*
* Fill in the init structure. This tells the adapter about the
diff --git a/sys/dev/aac/aac_pci.c b/sys/dev/aac/aac_pci.c
index 1182342..6f6b7e3 100644
--- a/sys/dev/aac/aac_pci.c
+++ b/sys/dev/aac/aac_pci.c
@@ -275,7 +275,7 @@ aac_pci_attach(device_t dev)
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
- 8192 + AAC_FIB_COUNT * /* XXX dma hack */
+ AAC_FIB_COUNT *
sizeof(struct aac_fib), 1, /* maxsize, nsegments */
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
0, /* flags */
diff --git a/sys/dev/aac/aacvar.h b/sys/dev/aac/aacvar.h
index dd56bcb..a303731 100644
--- a/sys/dev/aac/aacvar.h
+++ b/sys/dev/aac/aacvar.h
@@ -45,12 +45,11 @@
#define AAC_ADAPTER_FIBS 8
/*
- * FIBs are allocated up-front, and the pool isn't grown. We should allocate
- * enough here to let us keep the adapter busy without wasting large amounts
- * of kernel memory. The current interface implementation limits us to 512
- * FIBs queued for the adapter at any one time.
+ * FIBs are allocated in page-size chunks and can grow up to the 512
+ * limit imposed by the hardware.
*/
-#define AAC_FIB_COUNT 128
+#define AAC_FIB_COUNT 8
+#define AAC_MAX_FIBS 512
/*
* The controller reports status events in AIFs. We hang on to a number of
@@ -181,6 +180,13 @@ struct aac_command
int cm_queue;
};
+struct aac_fibmap {
+ TAILQ_ENTRY(aac_fibmap) fm_link; /* list linkage */
+ struct aac_fib *aac_fibs;
+ bus_dmamap_t aac_fibmap;
+ struct aac_command *aac_commands;
+};
+
/*
* We gather a number of adapter-visible items into a single structure.
*
@@ -324,10 +330,9 @@ struct aac_softc
/* command/fib resources */
bus_dma_tag_t aac_fib_dmat; /* DMA tag for allocing FIBs */
- struct aac_fib *aac_fibs;
- bus_dmamap_t aac_fibmap;
- u_int32_t aac_fibphys;
- struct aac_command aac_command[AAC_FIB_COUNT];
+ TAILQ_HEAD(,aac_fibmap) aac_fibmap_tqh;
+ uint total_fibs;
+ struct aac_command *aac_commands;
/* command management */
TAILQ_HEAD(,aac_command) aac_free; /* command structures
OpenPOWER on IntegriCloud