diff options
author | ps <ps@FreeBSD.org> | 2006-02-02 17:50:59 +0000 |
---|---|---|
committer | ps <ps@FreeBSD.org> | 2006-02-02 17:50:59 +0000 |
commit | b87c25138f58266568e950a37a8393d572732fe6 (patch) | |
tree | f3c03546987c969238ae589c2509a6c5fc55d3a0 | |
parent | c8f0963c9e61ccb376847f9be4be743370b21162 (diff) | |
download | FreeBSD-src-b87c25138f58266568e950a37a8393d572732fe6.zip FreeBSD-src-b87c25138f58266568e950a37a8393d572732fe6.tar.gz |
- 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.
-rw-r--r-- | sys/dev/amr/amr.c | 119 | ||||
-rw-r--r-- | sys/dev/amr/amrvar.h | 2 |
2 files changed, 60 insertions, 61 deletions
diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c index 1e16d12..c8bb39e 100644 --- a/sys/dev/amr/amr.c +++ b/sys/dev/amr/amr.c @@ -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; } diff --git a/sys/dev/amr/amrvar.h b/sys/dev/amr/amrvar.h index 84b3c61..2f9a728 100644 --- a/sys/dev/amr/amrvar.h +++ b/sys/dev/amr/amrvar.h @@ -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); |