summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2003-01-11 01:59:21 +0000
committerscottl <scottl@FreeBSD.org>2003-01-11 01:59:21 +0000
commit4aa40a12f56d9164ca352b3652c32aa687b6265f (patch)
treeba264515156bed4dd0eeda60d385bb22213cea8b /sys
parent7060fb8de0e3d82d1352b6ba4c60da0059ec8837 (diff)
downloadFreeBSD-src-4aa40a12f56d9164ca352b3652c32aa687b6265f.zip
FreeBSD-src-4aa40a12f56d9164ca352b3652c32aa687b6265f.tar.gz
Major bugfixes for large memory and fast systems.
aac.c: Re-arrange the interrupt handler to optimize the common case of the adapter interrupting us because one or more commands are complete, and do a read across the pci bus to ensure that all posted status writes are flushed. This should close a race that could cause command completion interrupts to be lost. Follow the spec a bit closer when filling out command structures. Enable the Fast Response feature to eliminate the need for the card to DMA successfull command completions back into host memory. Tell the controller how much physical memory we have. Without this there was a chance that our DMA regions would collide with the memory window used by the cache on the controller. The result would be massive data corruption. This seemed to mainly affect systems with >2GB of memory. Fix a few whitespace problems. aac_debug.c: Add an extra diagnostic when printing out commands. aac_disk.c: Add extra sanity checks. aacreg.h: Prepare for making this 64-bit clean by reducing the use of enumeration types in structures. Many thanks to Justin Gibbs for helping track these down.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/aac/aac.c89
-rw-r--r--sys/dev/aac/aac_debug.c5
-rw-r--r--sys/dev/aac/aac_disk.c9
-rw-r--r--sys/dev/aac/aacreg.h54
4 files changed, 90 insertions, 67 deletions
diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c
index 42587dd..046fa19 100644
--- a/sys/dev/aac/aac.c
+++ b/sys/dev/aac/aac.c
@@ -624,45 +624,43 @@ aac_intr(void *arg)
{
struct aac_softc *sc;
u_int16_t reason;
+ u_int32_t *resp_queue;
debug_called(2);
sc = (struct aac_softc *)arg;
- reason = AAC_GET_ISTATUS(sc);
+ /*
+ * Optimize the common case of adapter response interrupts.
+ * We must read from the card prior to processing the responses
+ * to ensure the clear is flushed prior to accessing the queues.
+ * Reading the queues from local memory might save us a PCI read.
+ */
+ resp_queue = sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE];
+ if (resp_queue[AAC_PRODUCER_INDEX] != resp_queue[AAC_CONSUMER_INDEX])
+ reason = AAC_DB_RESPONSE_READY;
+ else
+ reason = AAC_GET_ISTATUS(sc);
+ AAC_CLEAR_ISTATUS(sc, reason);
+ (void)AAC_GET_ISTATUS(sc);
+
+ /* It's not ok to return here because of races with the previous step */
+ if (reason & AAC_DB_RESPONSE_READY)
+ aac_host_response(sc);
/* controller wants to talk to the log */
- if (reason & AAC_DB_PRINTF) {
- AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF);
+ if (reason & AAC_DB_PRINTF)
aac_print_printf(sc);
- }
/* controller has a message for us? */
if (reason & AAC_DB_COMMAND_READY) {
- AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY);
/* XXX What happens if the thread is already awake? */
if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
sc->aifflags |= AAC_AIFFLAGS_PENDING;
wakeup(sc->aifthread);
}
}
-
- /* controller has a response for us? */
- if (reason & AAC_DB_RESPONSE_READY) {
- AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
- aac_host_response(sc);
- }
-
- /*
- * spurious interrupts that we don't use - reset the mask and clear the
- * interrupts
- */
- if (reason & (AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL)) {
- AAC_UNMASK_INTERRUPTS(sc);
- AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_NOT_FULL |
- AAC_DB_RESPONSE_NOT_FULL);
- }
-};
+}
/*
* Command Processing
@@ -729,7 +727,6 @@ aac_start(struct aac_command *cm)
/* save a pointer to the command for speedy reverse-lookup */
cm->cm_fib->Header.SenderData = (u_int32_t)cm; /* XXX 64-bit physical
* address issue */
-
/* put the FIB on the outbound queue */
error = aac_enqueue_fib(sc, cm->cm_queue, cm);
return(error);
@@ -928,11 +925,14 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
/* build the FIB */
fib = cm->cm_fib;
fib->Header.XferState =
- AAC_FIBSTATE_HOSTOWNED |
- AAC_FIBSTATE_INITIALISED |
- AAC_FIBSTATE_FROMHOST |
- AAC_FIBSTATE_REXPECTED |
- AAC_FIBSTATE_NORM;
+ AAC_FIBSTATE_HOSTOWNED |
+ AAC_FIBSTATE_INITIALISED |
+ AAC_FIBSTATE_EMPTY |
+ AAC_FIBSTATE_FROMHOST |
+ AAC_FIBSTATE_REXPECTED |
+ AAC_FIBSTATE_NORM |
+ AAC_FIBSTATE_ASYNC |
+ AAC_FIBSTATE_FAST_RESPONSE;
fib->Header.Command = ContainerCommand;
fib->Header.Size = sizeof(struct aac_fib_header);
@@ -1081,7 +1081,8 @@ aac_release_command(struct aac_command *cm)
* initialised here for debugging purposes only.
*/
cm->cm_fib->Header.SenderFibAddress = (u_int32_t)cm->cm_fib;
- cm->cm_fib->Header.ReceiverFibAddress = cm->cm_fibphys;
+ cm->cm_fib->Header.ReceiverFibAddress = (u_int32_t)cm->cm_fibphys;
+ cm->cm_fib->Header.SenderData = 0;
aac_enqueue_free(cm);
}
@@ -1121,7 +1122,7 @@ aac_alloc_commands(struct aac_softc *sc)
bus_dmamap_load(sc->aac_fib_dmat, sc->aac_fibmap, sc->aac_fibs,
AAC_FIB_COUNT * sizeof(struct aac_fib),
aac_map_command_helper, sc, 0);
-
+ bzero(sc->aac_fibs, AAC_FIB_COUNT * sizeof(struct aac_fib));
/* initialise constant fields in the command structure */
for (i = 0; i < AAC_FIB_COUNT; i++) {
cm = &sc->aac_command[i];
@@ -1206,12 +1207,12 @@ aac_map_command(struct aac_command *cm)
cm->cm_data, cm->cm_datalen,
aac_map_command_sg, cm, 0);
- if (cm->cm_flags & AAC_CMD_DATAIN)
- bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
- BUS_DMASYNC_PREREAD);
- if (cm->cm_flags & AAC_CMD_DATAOUT)
- bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
- BUS_DMASYNC_PREWRITE);
+ if (cm->cm_flags & AAC_CMD_DATAIN)
+ bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
+ BUS_DMASYNC_PREREAD);
+ if (cm->cm_flags & AAC_CMD_DATAOUT)
+ bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
+ BUS_DMASYNC_PREWRITE);
}
cm->cm_flags |= AAC_CMD_MAPPED;
}
@@ -1362,10 +1363,11 @@ aac_init(struct aac_softc *sc)
*/
ip = &sc->aac_common->ac_init;
ip->InitStructRevision = AAC_INIT_STRUCT_REVISION;
+ ip->MiniPortRevision = AAC_INIT_STRUCT_MINIPORT_REVISION;
ip->AdapterFibsPhysicalAddress = sc->aac_common_busaddr +
offsetof(struct aac_common, ac_fibs);
- ip->AdapterFibsVirtualAddress = &sc->aac_common->ac_fibs[0];
+ ip->AdapterFibsVirtualAddress = (u_int32_t)&sc->aac_common->ac_fibs[0];
ip->AdapterFibsSize = AAC_ADAPTER_FIBS * sizeof(struct aac_fib);
ip->AdapterFibAlign = sizeof(struct aac_fib);
@@ -1373,7 +1375,8 @@ aac_init(struct aac_softc *sc)
offsetof(struct aac_common, ac_printf);
ip->PrintfBufferSize = AAC_PRINTF_BUFSIZE;
- ip->HostPhysMemPages = 0; /* not used? */
+ /* The adapter assumes that pages are 4K in size */
+ ip->HostPhysMemPages = ctob(physmem) / AAC_PAGE_SIZE;
ip->HostElapsedSeconds = time_second; /* reset later if invalid */
/*
@@ -1398,7 +1401,6 @@ aac_init(struct aac_softc *sc)
ip->CommHeaderAddress = sc->aac_common_busaddr +
((u_int32_t)sc->aac_queues -
(u_int32_t)sc->aac_common);
- bzero(sc->aac_queues, sizeof(struct aac_queue_table));
sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
AAC_HOST_NORM_CMD_ENTRIES;
@@ -1704,6 +1706,15 @@ aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
*fib_addr = (struct aac_fib *)(sc->aac_qentries[queue] +
ci)->aq_fib_addr;
+ /*
+ * Is this a fast response? If it is, update the fib fields in
+ * local memory so the whole fib doesn't have to be DMA'd back up.
+ */
+ if (*(uintptr_t *)fib_addr & 0x01) {
+ *(uintptr_t *)fib_addr &= ~0x01;
+ (*fib_addr)->Header.XferState |= AAC_FIBSTATE_DONEADAP;
+ *((u_int32_t*)((*fib_addr)->data)) = AAC_ERROR_NORMAL;
+ }
/* update consumer index */
sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
diff --git a/sys/dev/aac/aac_debug.c b/sys/dev/aac/aac_debug.c
index 3a71318..36cfa4f 100644
--- a/sys/dev/aac/aac_debug.c
+++ b/sys/dev/aac/aac_debug.c
@@ -185,6 +185,11 @@ aac_panic(struct aac_softc *sc, char *reason)
void
aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, const char *caller)
{
+ if (fib == NULL) {
+ device_printf(sc->aac_dev,
+ "aac_print_fib called with NULL fib\n");
+ return;
+ }
device_printf(sc->aac_dev, "%s: FIB @ %p\n", caller, fib);
device_printf(sc->aac_dev, " XferState %b\n", fib->Header.XferState,
"\20"
diff --git a/sys/dev/aac/aac_disk.c b/sys/dev/aac/aac_disk.c
index 68692aa..668778d 100644
--- a/sys/dev/aac/aac_disk.c
+++ b/sys/dev/aac/aac_disk.c
@@ -135,12 +135,17 @@ aac_disk_open(dev_t dev, int flags, int fmt, d_thread_t *td)
sc = (struct aac_disk *)dev->si_drv1;
- if (sc == NULL)
+ if (sc == NULL) {
+ printf("aac_disk_open: No Softc\n");
return (ENXIO);
+ }
/* check that the controller is up and running */
- if (sc->ad_controller->aac_state & AAC_STATE_SUSPEND)
+ if (sc->ad_controller->aac_state & AAC_STATE_SUSPEND) {
+ printf("Controller Suspended controller state = 0x%x\n",
+ sc->ad_controller->aac_state);
return(ENXIO);
+ }
sc->ad_disk.d_sectorsize = AAC_BLOCK_SIZE;
sc->ad_disk.d_mediasize = (off_t)sc->ad_size * AAC_BLOCK_SIZE;
diff --git a/sys/dev/aac/aacreg.h b/sys/dev/aac/aacreg.h
index cf2c13f..75bb21c 100644
--- a/sys/dev/aac/aacreg.h
+++ b/sys/dev/aac/aacreg.h
@@ -128,8 +128,8 @@ struct aac_queue_table {
* our private command structure and don't touch these)
*/
struct aac_fib_list_entry {
- struct fib_list_entry *Flink;
- struct fib_list_entry *Blink;
+ u_int32_t Flink;
+ u_int32_t Blink;
} __packed;
/*
@@ -269,17 +269,19 @@ typedef enum {
*/
struct aac_adapter_init {
u_int32_t InitStructRevision;
-#define AAC_INIT_STRUCT_REVISION 3
+#define AAC_INIT_STRUCT_REVISION 3
u_int32_t MiniPortRevision;
+#define AAC_INIT_STRUCT_MINIPORT_REVISION 1
u_int32_t FilesystemRevision;
u_int32_t CommHeaderAddress;
u_int32_t FastIoCommAreaAddress;
u_int32_t AdapterFibsPhysicalAddress;
- void *AdapterFibsVirtualAddress;
+ u_int32_t AdapterFibsVirtualAddress;
u_int32_t AdapterFibsSize;
u_int32_t AdapterFibAlign;
u_int32_t PrintfBufferAddress;
u_int32_t PrintfBufferSize;
+#define AAC_PAGE_SIZE 4096
u_int32_t HostPhysMemPages;
u_int32_t HostElapsedSeconds;
} __packed;
@@ -969,8 +971,8 @@ struct aac_mntobj {
char FileSystemName[16];
struct aac_container_creation CreateInfo;
u_int32_t Capacity;
- AAC_FSAVolType VolType;
- AAC_FType ObjType;
+ u_int32_t VolType;
+ u_int32_t ObjType;
u_int32_t ContentState;
#define FSCS_READONLY 0x0002 /* XXX need more information
* than this */
@@ -981,14 +983,14 @@ struct aac_mntobj {
} __packed;
struct aac_mntinfo {
- AAC_VMCommand Command;
- AAC_FType MntType;
+ u_int32_t Command;
+ u_int32_t MntType;
u_int32_t MntCount;
} __packed;
struct aac_mntinforesp {
- AAC_FSAStatus Status;
- AAC_FType MntType;
+ u_int32_t Status;
+ u_int32_t MntType;
u_int32_t MntRespCount;
struct aac_mntobj MntTable[1];
} __packed;
@@ -1006,13 +1008,13 @@ struct aac_closecommand {
*/
#define CT_GET_SCSI_METHOD 64
struct aac_ctcfg {
- AAC_VMCommand Command;
+ u_int32_t Command;
u_int32_t cmd;
u_int32_t param;
} __packed;
struct aac_ctcfg_resp {
- AAC_FSAStatus Status;
+ u_int32_t Status;
u_int32_t resp;
u_int32_t param;
} __packed;
@@ -1036,8 +1038,8 @@ struct aac_getbusinf {
} __packed;
struct aac_vmioctl {
- AAC_VMCommand Command;
- AAC_FType ObjType;
+ u_int32_t Command;
+ u_int32_t ObjType;
u_int32_t MethId;
u_int32_t ObjId;
u_int32_t IoctlCmd;
@@ -1045,8 +1047,8 @@ struct aac_vmioctl {
} __packed;
struct aac_vmi_businf_resp {
- AAC_FSAStatus Status;
- AAC_FType ObjType;
+ u_int32_t Status;
+ u_int32_t ObjType;
u_int32_t MethId;
u_int32_t ObjId;
u_int32_t IoctlCmd;
@@ -1058,8 +1060,8 @@ struct aac_vmi_businf_resp {
#define GetDeviceProbeInfo 0x5
struct aac_vmi_devinfo_resp {
- AAC_FSAStatus Status;
- AAC_FType ObjType;
+ u_int32_t Status;
+ u_int32_t ObjType;
u_int32_t MethId;
u_int32_t ObjId;
u_int32_t IoctlCmd;
@@ -1125,7 +1127,7 @@ typedef enum {
*/
struct aac_blockread {
- AAC_VMCommand Command; /* not FSACommand! */
+ u_int32_t Command; /* not FSACommand! */
u_int32_t ContainerId;
u_int32_t BlockNumber;
u_int32_t ByteCount;
@@ -1133,31 +1135,31 @@ struct aac_blockread {
} __packed;
struct aac_blockread_response {
- AAC_FSAStatus Status;
+ u_int32_t Status;
u_int32_t ByteCount;
} __packed;
struct aac_blockwrite {
- AAC_VMCommand Command; /* not FSACommand! */
+ u_int32_t Command; /* not FSACommand! */
u_int32_t ContainerId;
u_int32_t BlockNumber;
u_int32_t ByteCount;
- AAC_CacheLevel Stable;
+ u_int32_t Stable;
struct aac_sg_table SgMap; /* variable size */
} __packed;
struct aac_blockwrite_response {
- AAC_FSAStatus Status;
+ u_int32_t Status;
u_int32_t ByteCount;
- AAC_CommitLevel Committed;
+ u_int32_t Committed;
} __packed;
/*
* Container shutdown command.
*/
struct aac_close_command {
- AAC_VMCommand Command;
- u_int32_t ContainerId;
+ u_int32_t Command;
+ u_int32_t ContainerId;
};
/*
OpenPOWER on IntegriCloud