Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/jdolecek-ncq]: src/sys/dev Add NCQ support to siisata(4).
details: https://anonhg.NetBSD.org/src/rev/8dbb9509bf3d
branches: jdolecek-ncq
changeset: 352669:8dbb9509bf3d
user: jakllsch <jakllsch%NetBSD.org@localhost>
date: Tue Jun 13 00:02:19 2017 +0000
description:
Add NCQ support to siisata(4).
There are still issues that need to be address before I consider this
mergable.
diffstat:
sys/dev/ata/TODO.ncq | 2 +-
sys/dev/ic/siisata.c | 274 +++++++++++++++++++++++++++++------------------
sys/dev/ic/siisatavar.h | 4 +-
3 files changed, 171 insertions(+), 109 deletions(-)
diffs (truncated from 693 to 300 lines):
diff -r 391facd5ec33 -r 8dbb9509bf3d sys/dev/ata/TODO.ncq
--- a/sys/dev/ata/TODO.ncq Mon Jun 12 23:51:40 2017 +0000
+++ b/sys/dev/ata/TODO.ncq Tue Jun 13 00:02:19 2017 +0000
@@ -3,7 +3,7 @@
test crashdump with ahci
-siisata - fix all 'XXX slot' -- jakllsch has this done but uncommited
+siisata - fix all new XXX and unmergable bits
test crashdump with siisata
diff -r 391facd5ec33 -r 8dbb9509bf3d sys/dev/ic/siisata.c
--- a/sys/dev/ic/siisata.c Mon Jun 12 23:51:40 2017 +0000
+++ b/sys/dev/ic/siisata.c Tue Jun 13 00:02:19 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: siisata.c,v 1.30.4.14 2017/04/24 21:19:21 jakllsch Exp $ */
+/* $NetBSD: siisata.c,v 1.30.4.15 2017/06/13 00:02:19 jakllsch Exp $ */
/* from ahcisata_core.c */
@@ -79,7 +79,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.30.4.14 2017/04/24 21:19:21 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.30.4.15 2017/06/13 00:02:19 jakllsch Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -148,7 +148,7 @@
void siisata_cmd_start(struct ata_channel *, struct ata_xfer *);
int siisata_cmd_complete(struct ata_channel *, struct ata_xfer *, int);
-void siisata_cmd_done(struct ata_channel *, struct ata_xfer *, int);
+void siisata_cmd_done(struct ata_channel *, struct ata_xfer *);
void siisata_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *, int);
void siisata_bio_start(struct ata_channel *, struct ata_xfer *);
@@ -209,7 +209,7 @@
SIISATA_DEBUG_PRINT(("%s: %s: GR_GC: 0x%08x\n",
SIISATANAME(sc), __func__, GRREAD(sc, GR_GC)), DEBUG_FUNCS);
- sc->sc_atac.atac_cap = ATAC_CAP_DMA | ATAC_CAP_UDMA;
+ sc->sc_atac.atac_cap = ATAC_CAP_DMA | ATAC_CAP_UDMA | ATAC_CAP_NCQ;
sc->sc_atac.atac_pio_cap = 4;
sc->sc_atac.atac_dma_cap = 2;
sc->sc_atac.atac_udma_cap = 6;
@@ -246,10 +246,7 @@
{
struct siisata_softc *sc = (struct siisata_softc *)chp->ch_atac;
- /* clear any interrupts */
- (void)PRREAD(sc, PRX(chp->ch_channel, PRO_PSS));
- PRWRITE(sc, PRX(chp->ch_channel, PRO_PIS), 0xffffffff);
- /* and enable CmdErrr+CmdCmpl interrupting */
+ /* enable CmdErrr+CmdCmpl interrupting */
PRWRITE(sc, PRX(chp->ch_channel, PRO_PIES),
PR_PIS_CMDERRR | PR_PIS_CMDCMPL);
}
@@ -263,9 +260,12 @@
schp = &sc->sc_channels[port];
chp = (struct ata_channel *)schp;
- /* come out of reset, 64-bit activation */
+ /*
+ * Come out of reset. Disable no clearing of PR_PIS_CMDCMPL on read
+ * of PR_PSS. Disable 32-bit PRB activation, we use 64-bit activation.
+ */
PRWRITE(sc, PRX(chp->ch_channel, PRO_PCC),
- PR_PC_32BA | PR_PC_PORT_RESET);
+ PR_PC_32BA | PR_PC_INCOR | PR_PC_PORT_RESET);
/* initialize port */
siisata_reinit_port(chp);
/* enable CmdErrr+CmdCmpl interrupting */
@@ -473,53 +473,71 @@
struct siisata_softc *sc;
struct ata_channel *chp;
struct ata_xfer *xfer;
- int slot;
+ u_int slot;
uint32_t pss, pis;
uint32_t prbfis;
sc = (struct siisata_softc *)schp->ata_channel.ch_atac;
chp = &schp->ata_channel;
- xfer = ata_queue_hwslot_to_xfer(chp->ch_queue, 0); /* XXX slot */
- slot = SIISATA_NON_NCQ_SLOT;
+
+ /* get slot status, clearing completion interrupt (PR_PIS_CMDCMPL) */
+ pss = PRREAD(sc, PRX(chp->ch_channel, PRO_PSS));
+ SIISATA_DEBUG_PRINT(("%s: %s port %d, pss 0x%x\n",
+ SIISATANAME(sc), __func__, chp->ch_channel, pss), DEBUG_INTR);
+
+ for (slot = 0; slot < SIISATA_MAX_SLOTS; slot++) {
+ if (((schp->sch_active_slots >> slot) & 1) == 0)
+ /* there's nothing executing here, skip */
+ continue;
+ if (((pss >> slot) & 1) != 0)
+ /* execution is incomplete or unsuccessful, skip for now */
+ continue;
+ xfer = ata_queue_hwslot_to_xfer(chp->ch_queue, slot);
+ if (xfer->c_intr == NULL) {
+ wakeup(schp);
+ continue;
+ }
+ KASSERT(xfer != NULL);
+ KASSERT(xfer->c_intr != NULL);
+ xfer->c_intr(chp, xfer, 0);
+ }
+ /* if no errors, we're done now */
+ if ((pss & PR_PSS_ATTENTION) == 0) {
+ pis = PRREAD(sc, PRX(chp->ch_channel, PRO_PIS));
+ pis &= 0xffff;
+ if (pis) {
+ PRWRITE(sc, PRX(chp->ch_channel, PRO_PIS),
+ pis & 0xfffcfffc);
+ }
+ return;
+ }
pis = PRREAD(sc, PRX(chp->ch_channel, PRO_PIS));
SIISATA_DEBUG_PRINT(("%s: %s port %d, pis 0x%x ", SIISATANAME(sc),
__func__, chp->ch_channel, pis), DEBUG_INTR);
- if (pis & PR_PIS_CMDCMPL) {
- /* get slot status, clearing completion interrupt */
- pss = PRREAD(sc, PRX(chp->ch_channel, PRO_PSS));
- SIISATA_DEBUG_PRINT(("pss 0x%x\n", pss), DEBUG_INTR);
- /* is this expected? */
- /* XXX improve */
- if ((schp->sch_active_slots & __BIT(slot)) == 0) {
- aprint_error( "%s: unexpected command "
- "completion on port %d\n",
- SIISATANAME(sc), chp->ch_channel);
- return;
- }
- if ((~pss & __BIT(slot)) == 0) {
- aprint_error( "%s: unknown slot "
- "completion on port %d, pss 0x%x\n",
- SIISATANAME(sc), chp->ch_channel, pss);
- return;
- }
- } else if (pis & PR_PIS_CMDERRR) {
+ if (pis & PR_PIS_CMDERRR) {
uint32_t ec;
+ uint32_t ps;
+
+ ps = PRREAD(sc, PRX(chp->ch_channel, PRO_PS));
+ ec = PRREAD(sc, PRX(chp->ch_channel, PRO_PCE));
+ SIISATA_DEBUG_PRINT(("ec %d\n", ec), DEBUG_INTR);
+
+ slot = PR_PS_ACTIVE_SLOT(ps); /* XXX invalid for NCQ? */
/* emulate a CRC error by default */
chp->ch_status = WDCS_ERR;
chp->ch_error = WDCE_CRC;
- ec = PRREAD(sc, PRX(chp->ch_channel, PRO_PCE));
- SIISATA_DEBUG_PRINT(("ec %d\n", ec), DEBUG_INTR);
if (ec <= PR_PCE_DATAFISERROR) {
- if (ec == PR_PCE_DEVICEERROR && xfer != NULL) {
+ if (ec == PR_PCE_DEVICEERROR) {
/* read in specific information about error */
prbfis = bus_space_read_stream_4(
sc->sc_prt, sc->sc_prh,
- PRSX(chp->ch_channel, slot, PRSO_FIS));
+ PRSX(chp->ch_channel, slot,
+ PRSO_FIS));
/* set ch_status and ch_error */
satafis_rdh_parse(chp, (uint8_t *)&prbfis);
}
@@ -532,12 +550,19 @@
/* okay, we have a "Fatal Error" */
siisata_device_reset(chp);
}
+ for (slot = 0; slot < SIISATA_MAX_SLOTS; slot++) {
+ /* there's nothing executing here, skip */
+ if (((schp->sch_active_slots >> slot) & 1) == 0)
+ continue;
+ xfer = ata_queue_hwslot_to_xfer(chp->ch_queue, slot);
+ if (xfer == NULL)
+ continue;
+ xfer->c_intr(chp, xfer, 0);
+ }
}
- /* clear some (ok, all) ints */
- PRWRITE(sc, PRX(chp->ch_channel, PRO_PIS), 0xffffffff);
- if (xfer && xfer->c_intr)
- xfer->c_intr(chp, xfer, 0);
+ /* clear */
+ PRWRITE(sc, PRX(chp->ch_channel, PRO_PIS), pis);
return;
}
@@ -549,49 +574,80 @@
struct siisata_softc *sc = (struct siisata_softc *)chp->ch_atac;
struct siisata_channel *schp = (struct siisata_channel *)chp;
struct siisata_prb *prb;
- int slot = SIISATA_NON_NCQ_SLOT;
+ struct ata_xfer *xfer;
+ uint32_t pss, pis;
int i;
/* wait for ready */
while (!(PRREAD(sc, PRX(chp->ch_channel, PRO_PS)) & PR_PS_PORT_READY))
DELAY(10);
- prb = schp->sch_prb[slot];
+ xfer = ata_get_xfer(chp); /* Is this right? What if the slots are full? */
+ if (xfer == NULL)
+ return;
+
+ prb = schp->sch_prb[xfer->c_slot];
memset(prb, 0, SIISATA_CMD_SIZE);
prb->prb_control =
- htole16(PRB_CF_SOFT_RESET | PRB_CF_INTERRUPT_MASK);
+ htole16(PRB_CF_SOFT_RESET /* | PRB_CF_INTERRUPT_MASK */);
KASSERT(drvp->drive <= PMP_PORT_CTL);
prb->prb_fis[rhd_c] = drvp->drive;
- siisata_activate_prb(schp, slot);
+ ata_activate_xfer(chp, xfer);
+ siisata_activate_prb(schp, xfer->c_slot);
for(i = 0; i < 3100; i++) {
- if ((PRREAD(sc, PRX(chp->ch_channel, PRO_PSS)) &
- PR_PXSS(slot)) == 0)
+#if 0 /* XXX-jak-jd-ncq this block needs re-work... XXX */
+ PRWRITE(sc, PRX(chp->ch_channel, PRO_PCS), PR_PC_INCOR);
+ pss = PRREAD(sc, PRX(chp->ch_channel, PRO_PSS));
+ PRWRITE(sc, PRX(chp->ch_channel, PRO_PCC), PR_PC_INCOR);
+ if ((pss & PR_PXSS(xfer->c_slot)) == 0)
break;
- if (flags & AT_WAIT)
+ if (pss & PR_PSS_ATTENTION)
+ break;
+#else
+ pss = PR_PXSS(xfer->c_slot);
+ /* XXX DO NOT MERGE UNTIL THIS IS FIXED XXX */
+#endif
+ if ((flags & AT_POLL) == 0)
tsleep(schp, PRIBIO, "siiprb", mstohz(10));
else
DELAY(10000);
}
- siisata_deactivate_prb(schp, slot);
+ siisata_deactivate_prb(schp, xfer->c_slot);
+
+ if ((pss & PR_PSS_ATTENTION) != 0) {
+ pis = PRREAD(sc, PRX(chp->ch_channel, PRO_PIS));
+ const uint32_t ps = PRREAD(sc, PRX(chp->ch_channel, PRO_PS));
+ const u_int slot = PR_PS_ACTIVE_SLOT(ps);
+ if (slot != xfer->c_slot)
+ device_printf(sc->sc_atac.atac_dev, "%s port %d "
+ "drive %d slot %d c_slot %d", __func__,
+ chp->ch_channel, drvp->drive, slot, xfer->c_slot);
+ PRWRITE(sc, PRX(chp->ch_channel, PRO_PIS), pis &
+ PR_PIS_CMDERRR);
+ }
+
if (i == 3100) {
/* timeout */
- siisata_device_reset(chp);
+ siisata_device_reset(chp); /* XXX is this right? */
if (sigp)
*sigp = 0xffffffff;
} else {
/* read the signature out of the FIS */
if (sigp) {
*sigp = 0;
- *sigp |= (PRREAD(sc, PRSX(chp->ch_channel, slot,
+ *sigp |= (PRREAD(sc, PRSX(chp->ch_channel, xfer->c_slot,
PRSO_FIS+0x4)) & 0x00ffffff) << 8;
- *sigp |= PRREAD(sc, PRSX(chp->ch_channel, slot,
+ *sigp |= PRREAD(sc, PRSX(chp->ch_channel, xfer->c_slot,
PRSO_FIS+0xc)) & 0xff;
}
}
+ ata_deactivate_xfer(chp, xfer);
+ ata_free_xfer(chp, xfer);
+
#if 1
/* attempt to downgrade signaling in event of CRC error */
/* XXX should be part of the MI (S)ATA subsystem */
@@ -624,8 +680,8 @@
struct siisata_softc *sc = (struct siisata_softc *)chp->ch_atac;
struct siisata_channel *schp = (struct siisata_channel *)chp;
- SIISATA_DEBUG_PRINT(("%s: %s\n", SIISATANAME(sc), __func__),
- DEBUG_FUNCS);
+ SIISATA_DEBUG_PRINT(("%s: %s channel %d\n", SIISATANAME(sc), __func__,
+ chp->ch_channel), DEBUG_FUNCS);
if (sata_reset_interface(chp, sc->sc_prt, schp->sch_scontrol,
schp->sch_sstatus, flags) != SStatus_DET_DEV) {
Home |
Main Index |
Thread Index |
Old Index