summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Long <scottl@FreeBSD.org>2003-02-10 00:34:24 +0000
committerScott Long <scottl@FreeBSD.org>2003-02-10 00:34:24 +0000
commitffb37f33f84e7633774fdd776ec5a527d44c4c43 (patch)
treef1e3dc2506bcce1e8d198b6f3d0708e0a036dc58
parent7bd4e7b4a0e3b44a4a7fd0e240c2617fabc0db18 (diff)
Notes
-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 f612c1515fe6c..509026e5f9c9f 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 11823422ccbfa..6f6b7e3568263 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 dd56bcb318e85..a3037311fc31a 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