- Move the command setup from amr_start1 into the card specific submit

routines.
- Add or replace cpu_spinwait() with DELAY(1) to a few of the busy
  loops when reading from the controller to work around firmware bugs
  which can crash the controller.
This commit is contained in:
Paul Saab 2006-02-02 17:50:59 +00:00
parent f5cdbcf14c
commit 447c943f68
2 changed files with 60 additions and 61 deletions

View File

@ -138,7 +138,6 @@ static int amr_wait_command(struct amr_command *ac) __unused;
static int amr_mapcmd(struct amr_command *ac);
static void amr_unmapcmd(struct amr_command *ac);
static int amr_start(struct amr_command *ac);
static int amr_start1(struct amr_softc *sc, struct amr_command *ac);
static void amr_complete(void *context, int pending);
static void amr_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error);
static void amr_setup_dma64map(void *arg, bus_dma_segment_t *segs, int nsegments, int error);
@ -152,12 +151,12 @@ static void amr_periodic(void *data);
/*
* Interface-specific shims
*/
static int amr_quartz_submit_command(struct amr_softc *sc);
static int amr_quartz_submit_command(struct amr_command *ac);
static int amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave);
static int amr_quartz_poll_command(struct amr_command *ac);
static int amr_quartz_poll_command1(struct amr_softc *sc, struct amr_command *ac);
static int amr_std_submit_command(struct amr_softc *sc);
static int amr_std_submit_command(struct amr_command *ac);
static int amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave);
static int amr_std_poll_command(struct amr_command *ac);
static void amr_std_attach_mailbox(struct amr_softc *sc);
@ -1474,17 +1473,21 @@ amr_quartz_poll_command1(struct amr_softc *sc, struct amr_command *ac)
AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT);
while(sc->amr_mailbox->mb_nstatus == 0xFF);
while(sc->amr_mailbox->mb_status == 0xFF);
while(sc->amr_mailbox->mb_nstatus == 0xFF)
DELAY(1);
while(sc->amr_mailbox->mb_status == 0xFF)
DELAY(1);
ac->ac_status=sc->amr_mailbox->mb_status;
error = (ac->ac_status !=AMR_STATUS_SUCCESS) ? 1:0;
while(sc->amr_mailbox->mb_poll != 0x77);
while(sc->amr_mailbox->mb_poll != 0x77)
DELAY(1);
sc->amr_mailbox->mb_poll = 0;
sc->amr_mailbox->mb_ack = 0x77;
/* acknowledge that we have the commands */
AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_ACK);
while(AMR_QGET_IDB(sc) & AMR_QIDB_ACK);
while(AMR_QGET_IDB(sc) & AMR_QIDB_ACK)
DELAY(1);
mtx_unlock(&sc->amr_hw_lock);
/* unmap the command's data buffer */
@ -1677,7 +1680,7 @@ amr_setup_ccbmap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
ac->ac_flags |= AMR_CMD_MAPPED;
if (amr_start1(sc, ac) == EBUSY) {
if (sc->amr_submit_command(ac) == EBUSY) {
amr_freeslot(ac);
amr_requeue_ready(ac);
}
@ -1746,7 +1749,7 @@ amr_setup_ccb64map(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
ac->ac_flags |= AMR_CMD_MAPPED;
if (amr_start1(sc, ac) == EBUSY) {
if (sc->amr_submit_command(ac) == EBUSY) {
amr_freeslot(ac);
amr_requeue_ready(ac);
}
@ -1796,7 +1799,7 @@ amr_mapcmd(struct amr_command *ac)
}
}
} else {
if (amr_start1(sc, ac) == EBUSY) {
if (sc->amr_submit_command(ac) == EBUSY) {
amr_freeslot(ac);
amr_requeue_ready(ac);
}
@ -1875,7 +1878,7 @@ amr_setup_data_dmamap(void *arg, bus_dma_segment_t *segs, int nsegs, int err)
}
ac->ac_flags |= AMR_CMD_MAPPED;
if (amr_start1(sc, ac) == EBUSY) {
if (sc->amr_submit_command(ac) == EBUSY) {
amr_freeslot(ac);
amr_requeue_ready(ac);
}
@ -1917,43 +1920,6 @@ amr_start(struct amr_command *ac)
return (error);
}
static int
amr_start1(struct amr_softc *sc, struct amr_command *ac)
{
int i = 0;
mtx_lock(&sc->amr_hw_lock);
while (sc->amr_mailbox->mb_busy && (i++ < 10))
DELAY(1);
if (sc->amr_mailbox->mb_busy) {
mtx_unlock(&sc->amr_hw_lock);
return (EBUSY);
}
/*
* Save the slot number so that we can locate this command when complete.
* Note that ident = 0 seems to be special, so we don't use it.
*/
ac->ac_mailbox.mb_ident = ac->ac_slot + 1; /* will be coppied into mbox */
bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, 14);
sc->amr_mailbox->mb_busy = 1;
sc->amr_mailbox->mb_poll = 0;
sc->amr_mailbox->mb_ack = 0;
sc->amr_mailbox64->sg64_hi = ac->ac_sg64_hi;
sc->amr_mailbox64->sg64_lo = ac->ac_sg64_lo;
if (sc->amr_submit_command(sc)) {
/* the controller wasn't ready to take the command, forget that we tried to post it */
sc->amr_mailbox->mb_busy = 0;
mtx_unlock(&sc->amr_hw_lock);
return (EBUSY);
}
mtx_unlock(&sc->amr_hw_lock);
return(0);
}
/********************************************************************************
* Extract one or more completed commands from the controller (sc)
*
@ -2188,26 +2154,59 @@ amr_freecmd_cluster(struct amr_command_cluster *acc)
* Tell the controller that the mailbox contains a valid command
*/
static int
amr_quartz_submit_command(struct amr_softc *sc)
amr_quartz_submit_command(struct amr_command *ac)
{
debug_called(3);
struct amr_softc *sc = ac->ac_sc;
int i = 0;
mtx_lock(&sc->amr_hw_lock);
while (sc->amr_mailbox->mb_busy && (i++ < 10))
DELAY(1);
if (sc->amr_mailbox->mb_busy) {
mtx_unlock(&sc->amr_hw_lock);
return (EBUSY);
}
/*
* Save the slot number so that we can locate this command when complete.
* Note that ident = 0 seems to be special, so we don't use it.
*/
ac->ac_mailbox.mb_ident = ac->ac_slot + 1; /* will be coppied into mbox */
bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, 14);
sc->amr_mailbox->mb_busy = 1;
sc->amr_mailbox->mb_poll = 0;
sc->amr_mailbox->mb_ack = 0;
sc->amr_mailbox64->sg64_hi = ac->ac_sg64_hi;
sc->amr_mailbox64->sg64_lo = ac->ac_sg64_lo;
#if 0
if (AMR_QGET_IDB(sc) & AMR_QIDB_SUBMIT)
return(EBUSY);
#endif
AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT);
mtx_unlock(&sc->amr_hw_lock);
return(0);
}
static int
amr_std_submit_command(struct amr_softc *sc)
amr_std_submit_command(struct amr_command *ac)
{
debug_called(3);
struct amr_softc *sc = ac->ac_sc;
mtx_lock(&sc->amr_hw_lock);
if (AMR_SGET_MBSTAT(sc) & AMR_SMBOX_BUSYFLAG) {
mtx_unlock(&sc->amr_hw_lock);
return (EBUSY);
}
/*
* Save the slot number so that we can locate this command when complete.
* Note that ident = 0 seems to be special, so we don't use it.
*/
ac->ac_mailbox.mb_ident = ac->ac_slot + 1; /* will be coppied into mbox */
bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, 14);
sc->amr_mailbox->mb_busy = 1;
sc->amr_mailbox->mb_poll = 0;
sc->amr_mailbox->mb_ack = 0;
if (AMR_SGET_MBSTAT(sc) & AMR_SMBOX_BUSYFLAG)
return(EBUSY);
AMR_SPOST_COMMAND(sc);
mtx_unlock(&sc->amr_hw_lock);
return(0);
}
@ -2234,13 +2233,13 @@ amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave)
AMR_QPUT_ODB(sc, AMR_QODB_READY);
while ((nstatus = sc->amr_mailbox->mb_nstatus) == 0xff)
cpu_spinwait();
DELAY(1);
sc->amr_mailbox->mb_nstatus = 0xff;
/* wait until fw wrote out all completions */
for (i = 0; i < nstatus; i++) {
while ((completed[i] = sc->amr_mailbox->mb_completed[i]) == 0xff)
cpu_spinwait();
DELAY(1);
sc->amr_mailbox->mb_completed[i] = 0xff;
}

View File

@ -231,7 +231,7 @@ struct amr_softc
#define AMR_IS_40LD(sc) ((sc)->amr_type & AMR_TYPE_40LD)
#define AMR_TYPE_SG64 (1<<2)
#define AMR_IS_SG64(sc) ((sc)->amr_type & AMR_TYPE_SG64)
int (* amr_submit_command)(struct amr_softc *sc);
int (* amr_submit_command)(struct amr_command *ac);
int (* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave);
int (*amr_poll_command)(struct amr_command *ac);
int (*amr_poll_command1)(struct amr_softc *sc, struct amr_command *ac);