summaryrefslogtreecommitdiffstats
path: root/sys/dev/amr
diff options
context:
space:
mode:
authormsmith <msmith@FreeBSD.org>2000-04-01 00:35:15 +0000
committermsmith <msmith@FreeBSD.org>2000-04-01 00:35:15 +0000
commitf64f3341e29b7db0ce82d24048194a7a135cb2a5 (patch)
treeef10b943193262336e2b225f694f7786b37db403 /sys/dev/amr
parent66b7eaeb75e1664bb1de7c364a673b357bcdf5f4 (diff)
downloadFreeBSD-src-f64f3341e29b7db0ce82d24048194a7a135cb2a5.zip
FreeBSD-src-f64f3341e29b7db0ce82d24048194a7a135cb2a5.tar.gz
Update to latest working version.
- Add periodic status monitoring routine. Currently just detects lost commands, further functionality pending data from AMI. Add some new commands states; WEDGED (never coming back) and LATE (for when a command that wasmarked as WEDGED comes bacj, - Remove a number of redundant efforts to poll the card for completed commands. This is what interrupt handlers are for. - Limit the maximum number of outstanding I/O transactions. It seems that some controllers report more than they can really handle, and exceding this limit can cause the controller to lock up. - Don't use 'wait' mode for anything where the controller might not be able to generate interrupts. (Keep the 'wait' mode though sa it will become useful when we start taking userspace commands. - Use a similar atomic locking trategy to the Mylex driver to prevent some reentrancy problems. - Correctly calculate the block count for non-whoile-bloch transfers (actually illegal). - Use the dsik device's si_drv1 field instead of b_driver1 in the buf struct to pass the driver identifier arond. - Rewrite amr_start and amr_done() along the lines of the Mylex driver in order to improve robustnes. - Always force the PCI busmaster bit on.
Diffstat (limited to 'sys/dev/amr')
-rw-r--r--sys/dev/amr/amr.c257
-rw-r--r--sys/dev/amr/amr_disk.c49
-rw-r--r--sys/dev/amr/amr_pci.c7
-rw-r--r--sys/dev/amr/amrvar.h31
4 files changed, 248 insertions, 96 deletions
diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c
index 3145e08..c38f1d1 100644
--- a/sys/dev/amr/amr.c
+++ b/sys/dev/amr/amr.c
@@ -108,6 +108,11 @@ static void amr_releasecmd(struct amr_command *ac);
static void amr_freecmd(struct amr_command *ac);
/*
+ * Status monitoring
+ */
+static void amr_periodic(void *data);
+
+/*
* Interface-specific shims
*/
static void amr_quartz_submit_command(struct amr_softc *sc);
@@ -142,6 +147,8 @@ amr_free(struct amr_softc *sc)
debug("called");
+ /* cancel status timeout */
+ untimeout(amr_periodic, sc, sc->amr_timeout);
/* throw away any command buffers */
while ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL) {
@@ -405,6 +412,11 @@ amr_attach(struct amr_softc *sc)
if (amr_sglist_map(sc))
return(ENXIO);
+ /*
+ * Start the timeout routine.
+ */
+ sc->amr_timeout = timeout(amr_periodic, sc, hz);
+
return(0);
}
@@ -536,7 +548,6 @@ amr_shutdown(device_t dev)
sc->amr_drive[i].al_disk = 0;
}
}
- bus_generic_detach(sc->amr_dev);
out:
splx(s);
@@ -585,16 +596,11 @@ void
amr_intr(void *arg)
{
struct amr_softc *sc = (struct amr_softc *)arg;
- int worked;
- debug("called on %p", sc);
+ debug("called");
- /* spin collecting finished commands, process them if we find anything */
- worked = 0;
- while (amr_done(sc))
- worked = 1;
- if (worked)
- amr_complete(sc);
+ /* collect finished commands, queue anything waiting */
+ amr_done(sc);
};
/*******************************************************************************
@@ -667,6 +673,52 @@ amr_submit_ioctl(struct amr_softc *sc, struct amr_logdrive *drive, u_long cmd,
/********************************************************************************
********************************************************************************
+ Status Monitoring
+ ********************************************************************************
+ ********************************************************************************/
+
+/********************************************************************************
+ * Perform a periodic check of the controller status
+ */
+static void
+amr_periodic(void *data)
+{
+ struct amr_softc *sc = (struct amr_softc *)data;
+ int s, i;
+
+ debug("called");
+
+
+ /*
+ * Check for commands that are massively late. This will need to be
+ * revisited if/when we deal with eg. device format commands.
+ * The 30 second value is entirely arbitrary.
+ */
+ s = splbio();
+ if (sc->amr_busycmdcount > 0) {
+ for (i = 0; i < AMR_MAXCMD; i++) {
+ /*
+ * If the command has been busy for more than 30 seconds, declare it
+ * wedged and retire it with an error.
+ */
+ if ((sc->amr_busycmd[i] != NULL) &&
+ (sc->amr_busycmd[i]->ac_status == AMR_STATUS_BUSY) &&
+ ((sc->amr_busycmd[i]->ac_stamp + 30) < time_second)) {
+ device_printf(sc->amr_dev, "command %d wedged after 30 seconds\n", i);
+ sc->amr_busycmd[i]->ac_status = AMR_STATUS_WEDGED;
+ amr_completeio(sc->amr_busycmd[i]);
+ }
+ }
+ }
+ splx(s);
+
+ /* reschedule */
+ sc->amr_timeout = timeout(amr_periodic, sc, hz);
+}
+
+
+/********************************************************************************
+ ********************************************************************************
Command Wrappers
********************************************************************************
********************************************************************************/
@@ -698,7 +750,13 @@ amr_query_controller(struct amr_softc *sc)
ae->ae_adapter.aa_memorysize);
}
sc->amr_maxdrives = 8;
- sc->amr_maxio = ae->ae_adapter.aa_maxio;
+
+ /*
+ * Cap the maximum number of outstanding I/Os. AMI's Linux driver doesn't trust
+ * the controller's reported value, and lockups have been seen when we do.
+ */
+ sc->amr_maxio = imin(ae->ae_adapter.aa_maxio, AMR_LIMITCMD);
+
for (i = 0; i < ae->ae_ldrv.al_numdrives; i++) {
sc->amr_drive[i].al_size = ae->ae_ldrv.al_size[i];
sc->amr_drive[i].al_state = ae->ae_ldrv.al_state[i];
@@ -710,6 +768,10 @@ amr_query_controller(struct amr_softc *sc)
sc->amr_drive[i].al_size = 0xffffffff;
free(ae, M_DEVBUF);
} else {
+ /*
+ * The "40LD" (40 logical drive support) firmware is mentioned in the Linux
+ * driver, but no adapters from AMI appear to support it.
+ */
free(buf, M_DEVBUF);
sc->amr_maxdrives = 40;
@@ -764,8 +826,8 @@ amr_enquiry(struct amr_softc *sc, size_t bufsize, u_int8_t cmd, u_int8_t cmdsub,
mbox[3] = cmdqual;
ac->ac_mailbox.mb_physaddr = ac->ac_dataphys;
- /* run the command in polled/wait mode as suits the current mode */
- if ((sc->amr_state & AMR_STATE_INTEN) ? amr_wait_command(ac) : amr_poll_command(ac))
+ /* can't assume that interrupts are going to work here, so play it safe */
+ if (amr_poll_command(ac))
goto out;
error = ac->ac_status;
@@ -800,8 +862,8 @@ amr_flush(struct amr_softc *sc)
/* build the command proper */
ac->ac_mailbox.mb_command = AMR_CMD_FLUSH;
- /* run the command in polled/wait mode as suits the current mode */
- if ((sc->amr_state & AMR_STATE_INTEN) ? amr_wait_command(ac) : amr_poll_command(ac))
+ /* we have to poll, as the system may be going down or otherwise damaged */
+ if (amr_poll_command(ac))
goto out;
error = ac->ac_status;
@@ -828,6 +890,10 @@ amr_startio(struct amr_softc *sc)
int cmd;
int s;
+ /* avoid reentrancy */
+ if (amr_lock_tas(sc, AMR_LOCK_STARTING))
+ return;
+
/* spin until something prevents us from doing any work */
s = splbio();
for (;;) {
@@ -865,9 +931,9 @@ amr_startio(struct amr_softc *sc)
amr_mapcmd(ac);
/* build a suitable I/O command (assumes 512-byte rounded transfers) */
- amrd = (struct amrd_softc *)bp->b_driver1;
- driveno = amrd->amrd_drive - &sc->amr_drive[0];
- blkcount = bp->b_bcount / AMR_BLKSIZE;
+ amrd = (struct amrd_softc *)bp->b_dev->si_drv1;
+ driveno = amrd->amrd_drive - sc->amr_drive;
+ blkcount = (bp->b_bcount + AMR_BLKSIZE - 1) / AMR_BLKSIZE;
if ((bp->b_pblkno + blkcount) > sc->amr_drive[driveno].al_size)
device_printf(sc->amr_dev, "I/O beyond end of unit (%u,%d > %u)\n",
@@ -892,6 +958,7 @@ amr_startio(struct amr_softc *sc)
s = splbio();
}
splx(s);
+ amr_lock_clr(sc, AMR_LOCK_STARTING);
}
/********************************************************************************
@@ -902,6 +969,10 @@ amr_completeio(struct amr_command *ac)
{
struct amr_softc *sc = ac->ac_sc;
struct buf *bp = (struct buf *)ac->ac_private;
+ int notify, release;
+
+ notify = 1;
+ release = 1;
if (ac->ac_status != AMR_STATUS_SUCCESS) { /* could be more verbose here? */
bp->b_error = EIO;
@@ -909,14 +980,24 @@ amr_completeio(struct amr_command *ac)
switch(ac->ac_status) {
/* XXX need more information on I/O error reasons */
+ case AMR_STATUS_LATE:
+ notify = 0; /* we've already notified the parent */
+ break;
+
+ case AMR_STATUS_WEDGED:
+ release = 0; /* the command is still outstanding, we can't release */
+ break;
+
default:
device_printf(sc->amr_dev, "I/O error - %x\n", ac->ac_status);
amr_printcommand(ac);
break;
}
}
- amr_releasecmd(ac);
- amrd_intr(bp);
+ if (release)
+ amr_releasecmd(ac);
+ if (notify)
+ amrd_intr(bp);
}
/********************************************************************************
@@ -1101,14 +1182,13 @@ amr_unmapcmd(struct amr_command *ac)
}
/********************************************************************************
- * Take a command and give it to the controller. Take care of any completed
- * commands we encouter while waiting.
+ * Take a command and give it to the controller.
*/
static int
amr_start(struct amr_command *ac)
{
struct amr_softc *sc = ac->ac_sc;
- int worked, done, s, i;
+ int done, s, i;
debug("called");
@@ -1124,9 +1204,11 @@ amr_start(struct amr_command *ac)
/* set impossible status so that a woken sleeper can tell the command is busy */
ac->ac_status = AMR_STATUS_BUSY;
- /* spin waiting for the mailbox */
+ /*
+ * Spin waiting for the mailbox, give up after ~1 second.
+ */
debug("wait for mailbox");
- for (i = 10000, done = 0, worked = 0; (i > 0) && !done; i--) {
+ for (i = 10000, done = 0; (i > 0) && !done; i--) {
s = splbio();
/* is the mailbox free? */
@@ -1142,20 +1224,12 @@ amr_start(struct amr_command *ac)
/* not free, try to clean up while we wait */
} else {
debug("busy flag %x\n", sc->amr_mailbox->mb_busy);
- /* try to kill some time being useful */
- if (amr_done(sc)) {
- worked = 1;
- } else {
- DELAY(100);
- }
+ /* this is somewhat ugly */
+ DELAY(100);
}
- splx(s);
+ splx(s); /* drop spl to allow completion interrupts */
}
- /* do completion processing if we picked anything up */
- if (worked)
- amr_complete(sc);
-
/* command is enqueued? */
if (done) {
ac->ac_stamp = time_second;
@@ -1170,6 +1244,7 @@ amr_start(struct amr_command *ac)
sc->amr_busycmd[ac->ac_slot] = NULL;
device_printf(sc->amr_dev, "controller wedged (not taking commands)\n");
ac->ac_status = AMR_STATUS_WEDGED;
+ amr_complete(sc);
return(EIO);
}
@@ -1183,43 +1258,63 @@ amr_done(struct amr_softc *sc)
{
struct amr_command *ac;
struct amr_mailbox mbox;
- int i, idx, result;
+ int i, idx, s, result;
debug("called");
/* See if there's anything for us to do */
result = 0;
- if (sc->amr_get_work(sc, &mbox)) {
- /* iterate over completed commands */
- for (i = 0; i < mbox.mb_nstatus; i++) {
- /* get pointer to busy command */
- idx = mbox.mb_completed[i] - 1;
- ac = sc->amr_busycmd[idx];
-
- /* really a busy command? */
- if (ac != NULL) {
-
- /* pull the command from the busy index */
- sc->amr_busycmd[idx] = NULL;
- sc->amr_busycmdcount--;
+
+ /* loop collecting completed commands */
+ s = splbio();
+ for (;;) {
+ /* poll for a completed command's identifier and status */
+ if (sc->amr_get_work(sc, &mbox)) {
+ result = 1;
+
+ /* iterate over completed commands in this result */
+ for (i = 0; i < mbox.mb_nstatus; i++) {
+ /* get pointer to busy command */
+ idx = mbox.mb_completed[i] - 1;
+ ac = sc->amr_busycmd[idx];
+
+ /* really a busy command? */
+ if (ac != NULL) {
+
+ /* pull the command from the busy index */
+ sc->amr_busycmd[idx] = NULL;
+ sc->amr_busycmdcount--;
- /* unmap data buffer */
- amr_unmapcmd(ac);
-
- /* aborted command? */
- if (ac == (struct amr_command *)sc) {
- device_printf(sc->amr_dev, "aborted command completed (%d)\n", idx);
- ac = NULL;
-
- /* completed normally, save status */
- } else {
- ac->ac_status = mbox.mb_status;
- debug("completed command with status %x", mbox.mb_status);
+ /* aborted command? */
+ if (ac == (struct amr_command *)sc) {
+ device_printf(sc->amr_dev, "aborted command completed (%d)\n", idx);
+ sc->amr_busycmd[idx] = NULL; /* free the slot again */
+ ac = NULL;
+
+ /* wedged command? */
+ } else if (ac->ac_status == AMR_STATUS_WEDGED) {
+ device_printf(sc->amr_dev, "wedged command completed (%d)\n", idx);
+ ac->ac_status = AMR_STATUS_LATE;
+
+ /* completed normally, save status */
+ } else {
+ ac->ac_status = mbox.mb_status;
+ debug("completed command with status %x", mbox.mb_status);
+ }
}
- result = 1;
}
+ } else {
+ break;
}
}
+
+ /* if we've completed any commands, try posting some more */
+ if (result)
+ amr_startio(sc);
+
+ /* handle completion and timeouts */
+ amr_complete(sc);
+
return(result);
}
@@ -1234,15 +1329,22 @@ amr_complete(struct amr_softc *sc)
debug("called");
- count = 0;
+ if (amr_lock_tas(sc, AMR_LOCK_COMPLETING))
+ return;
s = splbio();
+ count = 0;
+
+ /* scan the list of busy/done commands */
ac = TAILQ_FIRST(&sc->amr_work);
while (ac != NULL) {
nc = TAILQ_NEXT(ac, ac_link);
- /* Skip if command is still active */
+ /* Command has been completed in some fashion */
if (ac->ac_status != AMR_STATUS_BUSY) {
+
+ /* unmap the command's data buffer */
+ amr_unmapcmd(ac);
/*
* Is there a completion handler?
@@ -1273,9 +1375,8 @@ amr_complete(struct amr_softc *sc)
ac = nc;
}
splx(s);
-
- /* queue more work if we can */
- amr_startio(sc);
+
+ amr_lock_clr(sc, AMR_LOCK_COMPLETING);
}
/********************************************************************************
@@ -1377,7 +1478,6 @@ amr_quartz_submit_command(struct amr_softc *sc)
sc->amr_mailbox->mb_poll = 0;
sc->amr_mailbox->mb_ack = 0;
- /* XXX write barrier? */
while(AMR_QGET_IDB(sc) & AMR_QIDB_SUBMIT)
; /* XXX aiee! what if it dies? */
AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT);
@@ -1404,7 +1504,7 @@ amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave)
int s, worked;
u_int32_t outd;
- debug("called");
+/* debug("called"); */
worked = 0;
s = splbio();
@@ -1502,7 +1602,7 @@ amr_printcommand(struct amr_command *ac)
device_printf(sc->amr_dev, "blkcount %d lba %d\n",
ac->ac_mailbox.mb_blkcount, ac->ac_mailbox.mb_lba);
device_printf(sc->amr_dev, "virtaddr %p length %lu\n", ac->ac_data, (unsigned long)ac->ac_length);
- device_printf(sc->amr_dev, "physaddr %08x nsg %d\n",
+ device_printf(sc->amr_dev, "sg physaddr %08x nsg %d\n",
ac->ac_mailbox.mb_physaddr, ac->ac_mailbox.mb_nsgelem);
/* get base address of s/g table */
@@ -1510,3 +1610,20 @@ amr_printcommand(struct amr_command *ac)
for (i = 0; i < ac->ac_mailbox.mb_nsgelem; i++, sg++)
device_printf(sc->amr_dev, " %x/%d\n", sg->sg_addr, sg->sg_count);
}
+
+/********************************************************************************
+ * Print information on all the controllers in the system, useful mostly
+ * for calling from DDB.
+ */
+void
+amr_report(void)
+{
+ struct amr_softc *sc;
+ int i, s;
+
+ s = splbio();
+ for (i = 0; (sc = devclass_get_softc(amr_devclass, i)) != NULL; i++) {
+ device_printf(sc->amr_dev, "amr_waitbufs %d amr_busycmdcount %d amr_workcount %d\n",
+ sc->amr_waitbufs, sc->amr_busycmdcount, sc->amr_workcount);
+ }
+}
diff --git a/sys/dev/amr/amr_disk.c b/sys/dev/amr/amr_disk.c
index e9c0567..6ce523d 100644
--- a/sys/dev/amr/amr_disk.c
+++ b/sys/dev/amr/amr_disk.c
@@ -105,19 +105,10 @@ static driver_t amrd_driver = {
DRIVER_MODULE(amrd, amr, amrd_driver, amrd_devclass, 0, 0);
-static __inline struct amrd_softc *
-amrd_getsoftc(dev_t dev)
-{
- int unit;
-
- unit = dkunit(dev);
- return ((struct amrd_softc *)devclass_get_softc(amrd_devclass, unit));
-}
-
static int
amrd_open(dev_t dev, int flags, int fmt, struct proc *p)
{
- struct amrd_softc *sc = amrd_getsoftc(dev);
+ struct amrd_softc *sc = (struct amrd_softc *)dev->si_drv1;
struct disklabel *label;
debug("called");
@@ -146,7 +137,7 @@ amrd_open(dev_t dev, int flags, int fmt, struct proc *p)
static int
amrd_close(dev_t dev, int flags, int fmt, struct proc *p)
{
- struct amrd_softc *sc = amrd_getsoftc(dev);
+ struct amrd_softc *sc = (struct amrd_softc *)dev->si_drv1;
debug("called");
@@ -159,7 +150,7 @@ amrd_close(dev_t dev, int flags, int fmt, struct proc *p)
static int
amrd_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
{
- struct amrd_softc *sc = amrd_getsoftc(dev);
+ struct amrd_softc *sc = (struct amrd_softc *)dev->si_drv1;
int error;
debug("called");
@@ -183,9 +174,10 @@ amrd_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
static void
amrd_strategy(struct buf *bp)
{
- struct amrd_softc *sc = amrd_getsoftc(bp->b_dev);
+ struct amrd_softc *sc = (struct amrd_softc *)bp->b_dev->si_drv1;
- debug("called");
+ debug("called to %s %d bytes at b_blkno 0x%x b_pblkno 0x%x",
+ (bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount, bp->b_blkno, bp->b_pblkno);
/* bogus disk? */
if (sc == NULL) {
@@ -205,8 +197,6 @@ amrd_strategy(struct buf *bp)
if (bp->b_bcount == 0)
goto done;
- /* pass reference to us */
- bp->b_driver1 = sc;
devstat_start_transaction(&sc->amrd_stats);
amr_submit_buf(sc->amrd_controller, bp);
return;
@@ -227,14 +217,21 @@ void
amrd_intr(void *data)
{
struct buf *bp = (struct buf *)data;
- struct amrd_softc *sc = (struct amrd_softc *)bp->b_driver1;
+ struct amrd_softc *sc = (struct amrd_softc *)bp->b_dev->si_drv1;
debug("called");
-
- if (bp->b_flags & B_ERROR)
+
+ if (bp->b_flags & B_ERROR) {
bp->b_error = EIO;
- else
+ debug("i/o error\n");
+ } else {
+#if 0
+ int i;
+ for (i = 0; i < 512; i += 16)
+ debug(" %04x %16D", i, bp->b_data + i, " ");
+#endif
bp->b_resid = 0;
+ }
devstat_end_transaction_buf(&sc->amrd_stats, bp);
biodone(bp);
@@ -291,9 +288,13 @@ amrd_attach(device_t dev)
DEVSTAT_TYPE_STORARRAY | DEVSTAT_TYPE_IF_OTHER,
DEVSTAT_PRIORITY_ARRAY);
- disk_create(sc->amrd_unit, &sc->amrd_disk, 0, &amrd_cdevsw, &amrddisk_cdevsw);
+ sc->amrd_dev_t = disk_create(sc->amrd_unit, &sc->amrd_disk, 0, &amrd_cdevsw, &amrddisk_cdevsw);
+ sc->amrd_dev_t->si_drv1 = sc;
disks_registered++;
+ /* set maximum I/O size */
+ /* dsk->si_iosize_max = ??? */;
+
return (0);
}
@@ -305,11 +306,7 @@ amrd_detach(device_t dev)
debug("called");
devstat_remove_entry(&sc->amrd_stats);
-
- /* hack to handle lack of destroy_disk() */
- if (--disks_registered == 0)
- cdevsw_remove(&amrddisk_cdevsw);
-
+ disk_destroy(sc->amrd_dev_t);
return(0);
}
diff --git a/sys/dev/amr/amr_pci.c b/sys/dev/amr/amr_pci.c
index 7968a32..382a4a8 100644
--- a/sys/dev/amr/amr_pci.c
+++ b/sys/dev/amr/amr_pci.c
@@ -159,6 +159,13 @@ amr_pci_attach(device_t dev)
}
}
+ /* force the busmaster enable bit on */
+ if (!(command & PCIM_CMD_BUSMASTEREN)) {
+ device_printf(dev, "busmaster bit not set, enabling\n");
+ command |= PCIM_CMD_BUSMASTEREN;
+ pci_write_config(dev, PCIR_COMMAND, command, 2);
+ }
+
/*
* Allocate the PCI register window.
*/
diff --git a/sys/dev/amr/amrvar.h b/sys/dev/amr/amrvar.h
index 13e0f46..84777b5 100644
--- a/sys/dev/amr/amrvar.h
+++ b/sys/dev/amr/amrvar.h
@@ -38,6 +38,7 @@
#define AMR_SIGNATURE 0x3344
#define AMR_MAXCMD 255 /* ident = 0 not allowed */
+#define AMR_LIMITCMD 120 /* maximum count of outstanding commands */
#define AMR_MAXLD 40
#define AMR_BLKSIZE 512
@@ -75,6 +76,7 @@ struct amr_command
int ac_status;
#define AMR_STATUS_BUSY 0xffff
#define AMR_STATUS_WEDGED 0xdead
+#define AMR_STATUS_LATE 0xdeed
struct amr_mailbox ac_mailbox;
u_int32_t ac_sgphys;
int ac_nsgent;
@@ -131,6 +133,7 @@ struct amr_softc
#define AMR_STATE_SUSPEND (1<<1)
#define AMR_STATE_INTEN (1<<2)
#define AMR_STATE_SHUTDOWN (1<<3)
+ struct callout_handle amr_timeout; /* periodic status check */
/* per-controller queues */
struct buf_queue_head amr_bufq; /* pending I/O */
@@ -141,6 +144,8 @@ struct amr_softc
int amr_workcount;
TAILQ_HEAD(,amr_command) amr_freecmds;
+ int amr_locks; /* reentrancy avoidance */
+
/* controller type-specific support */
int amr_type;
#define AMR_TYPE_STD 0
@@ -151,6 +156,30 @@ struct amr_softc
};
/*
+ * Simple (stupid) locks.
+ *
+ * Note that these are designed to avoid reentrancy, not concurrency, and will
+ * need to be replaced with something better.
+ */
+#define AMR_LOCK_COMPLETING (1<<0)
+#define AMR_LOCK_STARTING (1<<1)
+
+static __inline int
+amr_lock_tas(struct amr_softc *sc, int lock)
+{
+ if ((sc)->amr_locks & (lock))
+ return(1);
+ atomic_set_int(&sc->amr_locks, lock);
+ return(0);
+}
+
+static __inline void
+amr_lock_clr(struct amr_softc *sc, int lock)
+{
+ atomic_clear_int(&sc->amr_locks, lock);
+}
+
+/*
* I/O primitives
*/
/* Quartz */
@@ -196,6 +225,7 @@ extern devclass_t amr_devclass;
struct amrd_softc
{
device_t amrd_dev;
+ dev_t amrd_dev_t;
struct amr_softc *amrd_controller;
struct amr_logdrive *amrd_drive;
struct disk amrd_disk;
@@ -214,3 +244,4 @@ extern int amr_submit_ioctl(struct amr_softc *sc, struct amr_logdrive *drive, u_
caddr_t addr, int32_t flag, struct proc *p);
extern void amrd_intr(void *data);
+extern void amr_report(void);
OpenPOWER on IntegriCloud