Prepare for a major update to the aac driver:
Update the aac driver with the new crashdump api. Protect sync fibs with a mutex. Align all DMA buffers on a PAGE_SIZE boundary. MFC after: 3 days
This commit is contained in:
parent
d5d1c5a11e
commit
cbfd045b10
sys/dev/aac
@ -73,7 +73,7 @@
|
||||
|
||||
static void aac_startup(void *arg);
|
||||
static void aac_add_container(struct aac_softc *sc,
|
||||
struct aac_mntinforesponse *mir, int f);
|
||||
struct aac_mntinforesp *mir, int f);
|
||||
|
||||
/* Command Processing */
|
||||
static void aac_startio(struct aac_softc *sc);
|
||||
@ -105,10 +105,6 @@ static int aac_init(struct aac_softc *sc);
|
||||
static int aac_sync_command(struct aac_softc *sc, u_int32_t command,
|
||||
u_int32_t arg0, u_int32_t arg1, u_int32_t arg2,
|
||||
u_int32_t arg3, u_int32_t *sp);
|
||||
static int aac_sync_fib(struct aac_softc *sc, u_int32_t command,
|
||||
u_int32_t xferstate, void *data,
|
||||
u_int16_t datasize, void *result,
|
||||
u_int16_t *resultsize);
|
||||
static int aac_enqueue_fib(struct aac_softc *sc, int queue,
|
||||
struct aac_command *cm);
|
||||
static int aac_dequeue_fib(struct aac_softc *sc, int queue,
|
||||
@ -271,6 +267,9 @@ aac_attach(struct aac_softc *sc)
|
||||
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");
|
||||
|
||||
/*
|
||||
* Initialise the adapter.
|
||||
*/
|
||||
@ -338,9 +337,9 @@ static void
|
||||
aac_startup(void *arg)
|
||||
{
|
||||
struct aac_softc *sc;
|
||||
struct aac_mntinfo mi;
|
||||
struct aac_mntinforesponse mir;
|
||||
u_int16_t rsize;
|
||||
struct aac_fib *fib;
|
||||
struct aac_mntinfo *mi;
|
||||
struct aac_mntinforesp *mir = NULL;
|
||||
int i = 0;
|
||||
|
||||
debug_called(1);
|
||||
@ -350,28 +349,28 @@ aac_startup(void *arg)
|
||||
/* disconnect ourselves from the intrhook chain */
|
||||
config_intrhook_disestablish(&sc->aac_ich);
|
||||
|
||||
aac_get_sync_fib(sc, &fib, 0);
|
||||
mi = (struct aac_mntinfo *)&fib->data[0];
|
||||
|
||||
/* loop over possible containers */
|
||||
mi.Command = VM_NameServe;
|
||||
mi.MntType = FT_FILESYS;
|
||||
mi->Command = VM_NameServe;
|
||||
mi->MntType = FT_FILESYS;
|
||||
do {
|
||||
/* request information on this container */
|
||||
mi.MntCount = i;
|
||||
rsize = sizeof(mir);
|
||||
if (aac_sync_fib(sc, ContainerCommand, 0, &mi,
|
||||
sizeof(struct aac_mntinfo), &mir, &rsize)) {
|
||||
mi->MntCount = i;
|
||||
if (aac_sync_fib(sc, ContainerCommand, 0, fib,
|
||||
sizeof(struct aac_mntinfo))) {
|
||||
debug(2, "error probing container %d", i);
|
||||
continue;
|
||||
}
|
||||
/* check response size */
|
||||
if (rsize != sizeof(mir)) {
|
||||
debug(2, "container info response wrong size "
|
||||
"(%d should be %d)", rsize, sizeof(mir));
|
||||
continue;
|
||||
}
|
||||
|
||||
aac_add_container(sc, &mir, 0);
|
||||
mir = (struct aac_mntinforesp *)&fib->data[0];
|
||||
aac_add_container(sc, mir, 0);
|
||||
i++;
|
||||
} while ((i < mir.MntRespCount) && (i < AAC_MAX_CONTAINERS));
|
||||
} while ((i < mir->MntRespCount) && (i < AAC_MAX_CONTAINERS));
|
||||
|
||||
aac_release_sync_fib(sc);
|
||||
|
||||
/* poke the bus to actually attach the child devices */
|
||||
if (bus_generic_attach(sc->aac_dev))
|
||||
@ -391,7 +390,7 @@ aac_startup(void *arg)
|
||||
* Create a device to respresent a new container
|
||||
*/
|
||||
static void
|
||||
aac_add_container(struct aac_softc *sc, struct aac_mntinforesponse *mir, int f)
|
||||
aac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f)
|
||||
{
|
||||
struct aac_container *co;
|
||||
device_t child;
|
||||
@ -527,8 +526,9 @@ int
|
||||
aac_shutdown(device_t dev)
|
||||
{
|
||||
struct aac_softc *sc;
|
||||
struct aac_close_command cc;
|
||||
int s, i;
|
||||
struct aac_fib *fib;
|
||||
struct aac_close_command *cc;
|
||||
int s;
|
||||
|
||||
debug_called(1);
|
||||
|
||||
@ -545,20 +545,24 @@ aac_shutdown(device_t dev)
|
||||
*/
|
||||
device_printf(sc->aac_dev, "shutting down controller...");
|
||||
|
||||
cc.Command = VM_CloseAll;
|
||||
cc.ContainerId = 0xffffffff;
|
||||
if (aac_sync_fib(sc, ContainerCommand, 0, &cc, sizeof(cc), NULL, NULL))
|
||||
aac_get_sync_fib(sc, &fib, AAC_SYNC_LOCK_FORCE);
|
||||
cc = (struct aac_close_command *)&fib->data[0];
|
||||
|
||||
cc->Command = VM_CloseAll;
|
||||
cc->ContainerId = 0xffffffff;
|
||||
if (aac_sync_fib(sc, ContainerCommand, 0, fib,
|
||||
sizeof(struct aac_close_command)))
|
||||
printf("FAILED.\n");
|
||||
else {
|
||||
i = 0;
|
||||
fib->data[0] = 0;
|
||||
/*
|
||||
* XXX Issuing this command to the controller makes it shut down
|
||||
* but also keeps it from coming back up without a reset of the
|
||||
* PCI bus. This is not desirable if you are just unloading the
|
||||
* driver module with the intent to reload it later.
|
||||
*/
|
||||
if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN, &i,
|
||||
sizeof(i), NULL, NULL)) {
|
||||
if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN,
|
||||
fib, 1)) {
|
||||
printf("FAILED.\n");
|
||||
} else {
|
||||
printf("done.\n");
|
||||
@ -999,102 +1003,6 @@ aac_bio_complete(struct aac_command *cm)
|
||||
aac_biodone(bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump a block of data to the controller. If the queue is full, tell the
|
||||
* caller to hold off and wait for the queue to drain.
|
||||
*/
|
||||
int
|
||||
aac_dump_enqueue(struct aac_disk *ad, u_int32_t lba, void *data, int dumppages)
|
||||
{
|
||||
struct aac_softc *sc;
|
||||
struct aac_command *cm;
|
||||
struct aac_fib *fib;
|
||||
struct aac_blockwrite *bw;
|
||||
|
||||
sc = ad->ad_controller;
|
||||
cm = NULL;
|
||||
|
||||
if (aac_alloc_command(sc, &cm))
|
||||
return (EBUSY);
|
||||
|
||||
/* fill out the command */
|
||||
cm->cm_data = data;
|
||||
cm->cm_datalen = dumppages * PAGE_SIZE;
|
||||
cm->cm_complete = NULL;
|
||||
cm->cm_private = NULL;
|
||||
cm->cm_timestamp = time_second;
|
||||
cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
|
||||
|
||||
/* 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;
|
||||
fib->Header.Command = ContainerCommand;
|
||||
fib->Header.Size = sizeof(struct aac_fib_header);
|
||||
|
||||
bw = (struct aac_blockwrite *)&fib->data[0];
|
||||
bw->Command = VM_CtBlockWrite;
|
||||
bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
|
||||
bw->BlockNumber = lba;
|
||||
bw->ByteCount = dumppages * PAGE_SIZE;
|
||||
bw->Stable = CUNSTABLE; /* XXX what's appropriate here? */
|
||||
fib->Header.Size += sizeof(struct aac_blockwrite);
|
||||
cm->cm_flags |= AAC_CMD_DATAOUT;
|
||||
cm->cm_sgtable = &bw->SgMap;
|
||||
|
||||
return (aac_start(cm));
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for the card's queue to drain when dumping. Also check for monitor
|
||||
* printf's
|
||||
*/
|
||||
void
|
||||
aac_dump_complete(struct aac_softc *sc)
|
||||
{
|
||||
struct aac_fib *fib;
|
||||
struct aac_command *cm;
|
||||
u_int16_t reason;
|
||||
u_int32_t pi, ci, fib_size;
|
||||
|
||||
do {
|
||||
reason = AAC_GET_ISTATUS(sc);
|
||||
if (reason & AAC_DB_RESPONSE_READY) {
|
||||
AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
|
||||
for (;;) {
|
||||
if (aac_dequeue_fib(sc,
|
||||
AAC_HOST_NORM_RESP_QUEUE,
|
||||
&fib_size, &fib))
|
||||
break;
|
||||
cm = (struct aac_command *)
|
||||
fib->Header.SenderData;
|
||||
if (cm == NULL)
|
||||
AAC_PRINT_FIB(sc, fib);
|
||||
else {
|
||||
aac_remove_busy(cm);
|
||||
aac_unmap_command(cm);
|
||||
aac_enqueue_complete(cm);
|
||||
aac_release_command(cm);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (reason & AAC_DB_PRINTF) {
|
||||
AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF);
|
||||
aac_print_printf(sc);
|
||||
}
|
||||
pi = sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][
|
||||
AAC_PRODUCER_INDEX];
|
||||
ci = sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][
|
||||
AAC_CONSUMER_INDEX];
|
||||
} while (ci != pi);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Submit a command to the controller, return when it completes.
|
||||
* XXX This is very dangerous! If the card has gone out to lunch, we could
|
||||
@ -1603,20 +1511,44 @@ aac_sync_command(struct aac_softc *sc, u_int32_t command,
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Grab the sync fib area.
|
||||
*/
|
||||
int
|
||||
aac_get_sync_fib(struct aac_softc *sc, struct aac_fib **fib, int flags)
|
||||
{
|
||||
|
||||
/*
|
||||
* If the force flag is set, the system is shutting down, or in
|
||||
* trouble. Ignore the mutex.
|
||||
*/
|
||||
if (!(flags & AAC_SYNC_LOCK_FORCE))
|
||||
AAC_LOCK_ACQUIRE(&sc->aac_sync_lock);
|
||||
|
||||
*fib = &sc->aac_common->ac_sync_fib;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the sync fib area.
|
||||
*/
|
||||
void
|
||||
aac_release_sync_fib(struct aac_softc *sc)
|
||||
{
|
||||
|
||||
AAC_LOCK_RELEASE(&sc->aac_sync_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a synchronous FIB to the controller and wait for a result.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
|
||||
void *data, u_int16_t datasize,
|
||||
void *result, u_int16_t *resultsize)
|
||||
struct aac_fib *fib, u_int16_t datasize)
|
||||
{
|
||||
struct aac_fib *fib;
|
||||
|
||||
debug_called(3);
|
||||
|
||||
fib = &sc->aac_common->ac_sync_fib;
|
||||
|
||||
if (datasize > AAC_FIB_DATASIZE)
|
||||
return(EINVAL);
|
||||
|
||||
@ -1636,17 +1568,6 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
|
||||
offsetof(struct aac_common,
|
||||
ac_sync_fib);
|
||||
|
||||
/*
|
||||
* Copy in data.
|
||||
*/
|
||||
if (data != NULL) {
|
||||
KASSERT(datasize <= sizeof(fib->data),
|
||||
("aac_sync_fib: datasize to large"));
|
||||
bcopy(data, fib->data, datasize);
|
||||
fib->Header.XferState |= AAC_FIBSTATE_FROMHOST |
|
||||
AAC_FIBSTATE_NORM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Give the FIB to the controller, wait for a response.
|
||||
*/
|
||||
@ -1656,19 +1577,7 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
|
||||
return(EIO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy out the result
|
||||
*/
|
||||
if (result != NULL) {
|
||||
u_int copysize;
|
||||
|
||||
copysize = fib->Header.Size - sizeof(struct aac_fib_header);
|
||||
if (copysize > *resultsize)
|
||||
copysize = *resultsize;
|
||||
*resultsize = fib->Header.Size - sizeof(struct aac_fib_header);
|
||||
bcopy(fib->data, result, copysize);
|
||||
}
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2156,28 +2065,19 @@ aac_fa_set_interrupts(struct aac_softc *sc, int enable)
|
||||
static void
|
||||
aac_describe_controller(struct aac_softc *sc)
|
||||
{
|
||||
u_int8_t buf[AAC_FIB_DATASIZE]; /* XXX really a bit big
|
||||
* for the stack */
|
||||
u_int16_t bufsize;
|
||||
struct aac_fib *fib;
|
||||
struct aac_adapter_info *info;
|
||||
u_int8_t arg;
|
||||
|
||||
debug_called(2);
|
||||
|
||||
arg = 0;
|
||||
bufsize = sizeof(buf);
|
||||
if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &buf,
|
||||
&bufsize)) {
|
||||
aac_get_sync_fib(sc, &fib, 0);
|
||||
|
||||
fib->data[0] = 0;
|
||||
if (aac_sync_fib(sc, RequestAdapterInfo, 0, fib, 1)) {
|
||||
device_printf(sc->aac_dev, "RequestAdapterInfo failed\n");
|
||||
return;
|
||||
}
|
||||
if (bufsize != sizeof(*info)) {
|
||||
device_printf(sc->aac_dev,
|
||||
"RequestAdapterInfo returned wrong data size "
|
||||
"(%d != %d)\n", bufsize, sizeof(*info));
|
||||
/*return;*/
|
||||
}
|
||||
info = (struct aac_adapter_info *)&buf[0];
|
||||
info = (struct aac_adapter_info *)&fib->data[0];
|
||||
|
||||
device_printf(sc->aac_dev, "%s %dMHz, %dMB cache memory, %s\n",
|
||||
aac_describe_code(aac_cpu_variant, info->CpuVariant),
|
||||
@ -2444,8 +2344,8 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
|
||||
{
|
||||
struct aac_aif_command *aif;
|
||||
struct aac_container *co, *co_next;
|
||||
struct aac_mntinfo mi;
|
||||
struct aac_mntinforesponse mir;
|
||||
struct aac_mntinfo *mi;
|
||||
struct aac_mntinforesp *mir = NULL;
|
||||
u_int16_t rsize;
|
||||
int next, found;
|
||||
int added = 0, i = 0;
|
||||
@ -2466,8 +2366,10 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
|
||||
* doesn't tell us anything else! Re-enumerate the
|
||||
* containers and sort things out.
|
||||
*/
|
||||
mi.Command = VM_NameServe;
|
||||
mi.MntType = FT_FILESYS;
|
||||
aac_get_sync_fib(sc, &fib, 0);
|
||||
mi = (struct aac_mntinfo *)&fib->data[0];
|
||||
mi->Command = VM_NameServe;
|
||||
mi->MntType = FT_FILESYS;
|
||||
do {
|
||||
/*
|
||||
* Ask the controller for its containers one at
|
||||
@ -2476,32 +2378,28 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
|
||||
* midway through this enumaration?
|
||||
* XXX This should be done async.
|
||||
*/
|
||||
mi.MntCount = i;
|
||||
mi->MntCount = i;
|
||||
rsize = sizeof(mir);
|
||||
if (aac_sync_fib(sc, ContainerCommand, 0, &mi,
|
||||
sizeof(mi), &mir, &rsize)) {
|
||||
if (aac_sync_fib(sc, ContainerCommand, 0, fib,
|
||||
sizeof(struct aac_mntinfo))) {
|
||||
debug(2, "Error probing container %d\n",
|
||||
i);
|
||||
continue;
|
||||
}
|
||||
if (rsize != sizeof(mir)) {
|
||||
debug(2, "Container response size too "
|
||||
"large\n");
|
||||
continue;
|
||||
}
|
||||
mir = (struct aac_mntinforesp *)&fib->data[0];
|
||||
/*
|
||||
* Check the container against our list.
|
||||
* co->co_found was already set to 0 in a
|
||||
* previous run.
|
||||
*/
|
||||
if ((mir.Status == ST_OK) &&
|
||||
(mir.MntTable[0].VolType != CT_NONE)) {
|
||||
if ((mir->Status == ST_OK) &&
|
||||
(mir->MntTable[0].VolType != CT_NONE)) {
|
||||
found = 0;
|
||||
TAILQ_FOREACH(co,
|
||||
&sc->aac_container_tqh,
|
||||
co_link) {
|
||||
if (co->co_mntobj.ObjectId ==
|
||||
mir.MntTable[0].ObjectId) {
|
||||
mir->MntTable[0].ObjectId) {
|
||||
co->co_found = 1;
|
||||
found = 1;
|
||||
break;
|
||||
@ -2519,12 +2417,13 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
|
||||
/*
|
||||
* This is a new container. Do all the
|
||||
* appropriate things to set it up. */
|
||||
aac_add_container(sc, &mir, 1);
|
||||
aac_add_container(sc, mir, 1);
|
||||
added = 1;
|
||||
}
|
||||
i++;
|
||||
} while ((i < mir.MntRespCount) &&
|
||||
} while ((i < mir->MntRespCount) &&
|
||||
(i < AAC_MAX_CONTAINERS));
|
||||
aac_release_sync_fib(sc);
|
||||
|
||||
/*
|
||||
* Go through our list of containers and see which ones
|
||||
|
@ -108,18 +108,18 @@ static driver_t aac_disk_driver = {
|
||||
sizeof(struct aac_disk)
|
||||
};
|
||||
|
||||
#define AAC_MAXIO 65536
|
||||
|
||||
DRIVER_MODULE(aacd, aac, aac_disk_driver, aac_disk_devclass, 0, 0);
|
||||
|
||||
/* sysctl tunables */
|
||||
static unsigned int aac_iosize_max = 65536; /* due to limits of the card */
|
||||
static unsigned int aac_iosize_max = AAC_MAXIO; /* due to limits of the card */
|
||||
TUNABLE_INT("hw.aac.iosize_max", &aac_iosize_max);
|
||||
|
||||
SYSCTL_DECL(_hw_aac);
|
||||
SYSCTL_UINT(_hw_aac, OID_AUTO, iosize_max, CTLFLAG_RD, &aac_iosize_max, 0,
|
||||
"Max I/O size per transfer to an array");
|
||||
|
||||
#define AAC_MAXIO 65536
|
||||
|
||||
/*
|
||||
* Handle open from generic layer.
|
||||
*
|
||||
@ -212,89 +212,90 @@ aac_disk_strategy(struct bio *bp)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Map the S/G elements for doing a dump.
|
||||
*/
|
||||
static void
|
||||
aac_dump_map_sg(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
|
||||
{
|
||||
struct aac_fib *fib;
|
||||
struct aac_blockwrite *bw;
|
||||
struct aac_sg_table *sg;
|
||||
int i;
|
||||
|
||||
fib = (struct aac_fib *)arg;
|
||||
bw = (struct aac_blockwrite *)&fib->data[0];
|
||||
sg = &bw->SgMap;
|
||||
|
||||
if (sg != NULL) {
|
||||
sg->SgCount = nsegs;
|
||||
for (i = 0; i < nsegs; i++) {
|
||||
sg->SgEntry[i].SgAddress = segs[i].ds_addr;
|
||||
sg->SgEntry[i].SgByteCount = segs[i].ds_len;
|
||||
}
|
||||
fib->Header.Size = nsegs * sizeof(struct aac_sg_entry);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump memory out to an array
|
||||
*
|
||||
* This queues blocks of memory of size AAC_MAXIO to the controller and waits
|
||||
* for the controller to complete the requests.
|
||||
* Send out one command at a time with up to AAC_MAXIO of data.
|
||||
*/
|
||||
static int
|
||||
aac_disk_dump(dev_t dev, void *virtual, vm_offset_t physical, off_t offset, size_t length)
|
||||
{
|
||||
|
||||
/* XXX: This needs modified for the new dump API */
|
||||
return (ENXIO);
|
||||
#if 0
|
||||
struct aac_disk *ad;
|
||||
struct aac_softc *sc;
|
||||
vm_offset_t addr;
|
||||
long blkcnt;
|
||||
unsigned int count, blkno, secsize;
|
||||
int dumppages;
|
||||
int i, error;
|
||||
struct aac_fib *fib;
|
||||
struct aac_blockwrite *bw;
|
||||
size_t len;
|
||||
int size;
|
||||
static bus_dmamap_t dump_datamap;
|
||||
static int first = 0;
|
||||
|
||||
ad = dev->si_drv1;
|
||||
addr = 0;
|
||||
dumppages = AAC_MAXIO / PAGE_SIZE;
|
||||
|
||||
if ((error = disk_dumpcheck(dev, &count, &blkno, &secsize)))
|
||||
return (error);
|
||||
|
||||
if (ad == NULL)
|
||||
return (ENXIO);
|
||||
return (EINVAL);
|
||||
|
||||
sc= ad->ad_controller;
|
||||
|
||||
blkcnt = howmany(PAGE_SIZE, secsize);
|
||||
|
||||
while (count > 0) {
|
||||
caddr_t va = NULL;
|
||||
|
||||
if ((count / blkcnt) < dumppages)
|
||||
dumppages = count / blkcnt;
|
||||
|
||||
for (i = 0; i < dumppages; ++i) {
|
||||
vm_offset_t a = addr + (i * PAGE_SIZE);
|
||||
if (is_physical_memory(a)) {
|
||||
va = pmap_kenter_temporary(trunc_page(a), i);
|
||||
} else {
|
||||
va = pmap_kenter_temporary(trunc_page(0), i);
|
||||
}
|
||||
if (!first) {
|
||||
first = 1;
|
||||
if (bus_dmamap_create(sc->aac_buffer_dmat, 0, &dump_datamap)) {
|
||||
printf("bus_dmamap_create failed\n");
|
||||
return (ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
retry:
|
||||
/*
|
||||
* Queue the block to the controller. If the queue is full,
|
||||
* EBUSY will be returned.
|
||||
*/
|
||||
error = aac_dump_enqueue(ad, blkno, va, dumppages);
|
||||
if (error && (error != EBUSY))
|
||||
return (error);
|
||||
aac_get_sync_fib(sc, &fib, AAC_SYNC_LOCK_FORCE);
|
||||
bw = (struct aac_blockwrite *)&fib->data[0];
|
||||
|
||||
if (!error) {
|
||||
if (dumpstatus(addr, (off_t)(count * DEV_BSIZE)) < 0)
|
||||
return (EINTR);
|
||||
while (length > 0) {
|
||||
len = (length > AAC_MAXIO) ? AAC_MAXIO : length;
|
||||
bw->Command = VM_CtBlockWrite;
|
||||
bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
|
||||
bw->BlockNumber = offset / AAC_BLOCK_SIZE;
|
||||
bw->ByteCount = len;
|
||||
bw->Stable = CUNSTABLE;
|
||||
bus_dmamap_load(sc->aac_buffer_dmat, dump_datamap, virtual,
|
||||
len, aac_dump_map_sg, fib, 0);
|
||||
bus_dmamap_sync(sc->aac_buffer_dmat, dump_datamap,
|
||||
BUS_DMASYNC_PREWRITE);
|
||||
|
||||
blkno += blkcnt * dumppages;
|
||||
count -= blkcnt * dumppages;
|
||||
addr += PAGE_SIZE * dumppages;
|
||||
if (count > 0)
|
||||
continue;
|
||||
/* fib->Header.Size is set in aac_dump_map_sg */
|
||||
size = fib->Header.Size + sizeof(struct aac_blockwrite);
|
||||
|
||||
if (aac_sync_fib(sc, ContainerCommand, 0, fib, size)) {
|
||||
printf("Error dumping block 0x%x\n", physical);
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Either the queue was full on the last attemp, or we have no
|
||||
* more data to dump. Let the queue drain out and retry the
|
||||
* block if the queue was full.
|
||||
*/
|
||||
aac_dump_complete(sc);
|
||||
|
||||
if (error == EBUSY)
|
||||
goto retry;
|
||||
length -= len;
|
||||
offset += len;
|
||||
}
|
||||
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -224,7 +224,7 @@ aac_pci_attach(device_t dev)
|
||||
* Note that some of these controllers are 64-bit capable.
|
||||
*/
|
||||
if (bus_dma_tag_create(NULL, /* parent */
|
||||
1, 0, /* algnmnt, boundary */
|
||||
PAGE_SIZE, 0, /* algnmnt, boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
|
@ -986,7 +986,7 @@ struct aac_mntinfo {
|
||||
u_int32_t MntCount;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct aac_mntinforesponse {
|
||||
struct aac_mntinforesp {
|
||||
AAC_FSAStatus Status;
|
||||
AAC_FType MntType;
|
||||
u_int32_t MntRespCount;
|
||||
|
@ -336,6 +336,10 @@ struct aac_softc
|
||||
struct aac_container_tq aac_container_tqh;
|
||||
aac_lock_t aac_container_lock;
|
||||
|
||||
/* Protect the sync fib */
|
||||
#define AAC_SYNC_LOCK_FORCE (1 << 0)
|
||||
aac_lock_t aac_sync_lock;
|
||||
|
||||
/* delayed activity infrastructure */
|
||||
#if __FreeBSD_version >= 500005
|
||||
struct task aac_task_complete; /* deferred-completion
|
||||
@ -373,9 +377,12 @@ extern int aac_resume(device_t dev);
|
||||
extern void aac_intr(void *arg);
|
||||
extern void aac_submit_bio(struct bio *bp);
|
||||
extern void aac_biodone(struct bio *bp);
|
||||
extern int aac_dump_enqueue(struct aac_disk *ad, u_int32_t lba,
|
||||
void *data, int nblks);
|
||||
extern void aac_dump_complete(struct aac_softc *sc);
|
||||
extern int aac_get_sync_fib(struct aac_softc *sc,
|
||||
struct aac_fib **fib, int flags);
|
||||
extern void aac_release_sync_fib(struct aac_softc *sc);
|
||||
extern int aac_sync_fib(struct aac_softc *sc, u_int32_t command,
|
||||
u_int32_t xferstate, struct aac_fib *fib,
|
||||
u_int16_t datasize);
|
||||
|
||||
/*
|
||||
* Debugging levels:
|
||||
@ -400,7 +407,7 @@ extern void aac_print_fib(struct aac_softc *sc, struct aac_fib *fib,
|
||||
extern void aac_print_aif(struct aac_softc *sc,
|
||||
struct aac_aif_command *aif);
|
||||
|
||||
# define AAC_PRINT_FIB(sc, fib) aac_print_fib(sc, fib, __func__)
|
||||
#define AAC_PRINT_FIB(sc, fib) aac_print_fib(sc, fib, __func__)
|
||||
|
||||
#else
|
||||
# define debug(level, fmt, args...)
|
||||
|
Loading…
Reference in New Issue
Block a user