Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic More SDIO stability and performance fixes
details: https://anonhg.NetBSD.org/src/rev/d1ec4c3da97e
branches: trunk
changeset: 968661:d1ec4c3da97e
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Thu Jan 23 23:53:55 2020 +0000
description:
More SDIO stability and performance fixes
diffstat:
sys/dev/ic/dwc_mmc.c | 59 +++++++++++++++++++++++++++++++++++++++--------
sys/dev/ic/dwc_mmc_var.h | 4 ++-
2 files changed, 51 insertions(+), 12 deletions(-)
diffs (174 lines):
diff -r aa21462bdd60 -r d1ec4c3da97e sys/dev/ic/dwc_mmc.c
--- a/sys/dev/ic/dwc_mmc.c Thu Jan 23 23:52:13 2020 +0000
+++ b/sys/dev/ic/dwc_mmc.c Thu Jan 23 23:53:55 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_mmc.c,v 1.21 2020/01/22 23:19:12 jmcneill Exp $ */
+/* $NetBSD: dwc_mmc.c,v 1.22 2020/01/23 23:53:55 jmcneill Exp $ */
/*-
* Copyright (c) 2014-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.21 2020/01/22 23:19:12 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.22 2020/01/23 23:53:55 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -297,6 +297,11 @@
static int
dwc_mmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
{
+ struct dwc_mmc_softc *sc = sch;
+
+ if (ocr == 0)
+ sc->sc_card_inited = false;
+
return 0;
}
@@ -573,6 +578,7 @@
uint32_t cmdval = DWC_MMC_CMD_START;
int retry, error;
uint32_t imask;
+ u_int reg;
#ifdef DWC_MMC_DEBUG
aprint_normal_dev(sc->sc_dev,
@@ -581,24 +587,41 @@
cmd->c_blklen);
#endif
- mutex_enter(&sc->sc_intr_lock);
+ mutex_enter(&sc->sc_lock);
if (sc->sc_curcmd != NULL) {
device_printf(sc->sc_dev,
"WARNING: driver submitted a command while the controller was busy\n");
cmd->c_error = EBUSY;
SET(cmd->c_flags, SCF_ITSDONE);
- mutex_exit(&sc->sc_intr_lock);
+ mutex_exit(&sc->sc_lock);
return;
}
sc->sc_curcmd = cmd;
MMC_WRITE(sc, DWC_MMC_IDST, 0xffffffff);
+ if (!sc->sc_card_inited) {
+ cmdval |= DWC_MMC_CMD_SEND_INIT_SEQ;
+ sc->sc_card_inited = true;
+ }
+
if (ISSET(sc->sc_flags, DWC_MMC_F_USE_HOLD_REG))
cmdval |= DWC_MMC_CMD_USE_HOLD_REG;
- if (cmd->c_opcode == MMC_GO_IDLE_STATE)
- cmdval |= DWC_MMC_CMD_SEND_INIT_SEQ;
+ switch (cmd->c_opcode) {
+ case SD_IO_RW_DIRECT:
+ reg = (cmd->c_arg >> SD_ARG_CMD52_REG_SHIFT) &
+ SD_ARG_CMD52_REG_MASK;
+ if (reg != 0x6) /* func abort / card reset */
+ break;
+ /* FALLTHROUGH */
+ case MMC_GO_IDLE_STATE:
+ case MMC_STOP_TRANSMISSION:
+ case MMC_INACTIVE_STATE:
+ cmdval |= DWC_MMC_CMD_STOP_ABORT_CMD;
+ break;
+ }
+
if (cmd->c_flags & SCF_RSP_PRESENT)
cmdval |= DWC_MMC_CMD_RSP_EXP;
if (cmd->c_flags & SCF_RSP_136)
@@ -613,10 +636,10 @@
MMC_WRITE(sc, DWC_MMC_GCTRL,
MMC_READ(sc, DWC_MMC_GCTRL) | DWC_MMC_GCTRL_FIFORESET);
- for (retry = 0; retry < 100; retry++) {
+ for (retry = 0; retry < 100000; retry++) {
if (!(MMC_READ(sc, DWC_MMC_DMAC) & DWC_MMC_DMAC_SOFTRESET))
break;
- kpause("dwcmmcfifo", false, uimax(mstohz(1), 1), &sc->sc_intr_lock);
+ delay(1);
}
cmdval |= DWC_MMC_CMD_DATA_EXP | DWC_MMC_CMD_WAIT_PRE_OVER;
@@ -671,6 +694,16 @@
}
sc->sc_wait_cmd = true;
+ if ((cmdval & DWC_MMC_CMD_WAIT_PRE_OVER) != 0) {
+ for (retry = 0; retry < 10000; retry++) {
+ if (!(MMC_READ(sc, DWC_MMC_STATUS) & DWC_MMC_STATUS_CARD_DATA_BUSY))
+ break;
+ delay(1);
+ }
+ }
+
+ mutex_enter(&sc->sc_intr_lock);
+
MMC_WRITE(sc, DWC_MMC_CMD, cmdval | cmd->c_opcode);
if (sc->sc_wait_dma)
@@ -688,6 +721,8 @@
}
}
+ mutex_exit(&sc->sc_intr_lock);
+
if (cmd->c_error == 0 && cmd->c_datalen > 0)
dwc_mmc_dma_complete(sc, cmd);
@@ -720,8 +755,6 @@
MMC_WRITE(sc, DWC_MMC_IDIE, 0);
MMC_WRITE(sc, DWC_MMC_RINT, 0x7fff);
MMC_WRITE(sc, DWC_MMC_IDST, 0xffffffff);
- sc->sc_curcmd = NULL;
- mutex_exit(&sc->sc_intr_lock);
if (cmd->c_error) {
#ifdef DWC_MMC_DEBUG
@@ -731,9 +764,12 @@
for (retry = 0; retry < 100; retry++) {
if (!(MMC_READ(sc, DWC_MMC_DMAC) & DWC_MMC_DMAC_SOFTRESET))
break;
- kpause("dwcmmcrst", false, uimax(mstohz(1), 1), NULL);
+ kpause("dwcmmcrst", false, uimax(mstohz(1), 1), &sc->sc_lock);
}
}
+
+ sc->sc_curcmd = NULL;
+ mutex_exit(&sc->sc_lock);
}
static void
@@ -788,6 +824,7 @@
if (sc->sc_intr_cardmask == 0)
sc->sc_intr_cardmask = DWC_MMC_INT_SDIO_INT(0);
+ mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
cv_init(&sc->sc_intr_cv, "dwcmmcirq");
diff -r aa21462bdd60 -r d1ec4c3da97e sys/dev/ic/dwc_mmc_var.h
--- a/sys/dev/ic/dwc_mmc_var.h Thu Jan 23 23:52:13 2020 +0000
+++ b/sys/dev/ic/dwc_mmc_var.h Thu Jan 23 23:53:55 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_mmc_var.h,v 1.12 2020/01/22 23:19:12 jmcneill Exp $ */
+/* $NetBSD: dwc_mmc_var.h,v 1.13 2020/01/23 23:53:55 jmcneill Exp $ */
/*-
* Copyright (c) 2014-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -44,8 +44,10 @@
uint32_t sc_fifo_depth;
u_int sc_clock_freq;
u_int sc_bus_width;
+ bool sc_card_inited;
void *sc_ih;
+ kmutex_t sc_lock;
kmutex_t sc_intr_lock;
kcondvar_t sc_intr_cv;
Home |
Main Index |
Thread Index |
Old Index