Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/sdmmc Support retry when error. like wd(4).
details: https://anonhg.NetBSD.org/src/rev/fab05b017ad6
branches: trunk
changeset: 820329:fab05b017ad6
user: kiyohara <kiyohara%NetBSD.org@localhost>
date: Sat Jan 07 14:49:53 2017 +0000
description:
Support retry when error. like wd(4).
diffstat:
sys/dev/sdmmc/ld_sdmmc.c | 61 ++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 51 insertions(+), 10 deletions(-)
diffs (160 lines):
diff -r fea1cce3cb3a -r fab05b017ad6 sys/dev/sdmmc/ld_sdmmc.c
--- a/sys/dev/sdmmc/ld_sdmmc.c Sat Jan 07 14:44:26 2017 +0000
+++ b/sys/dev/sdmmc/ld_sdmmc.c Sat Jan 07 14:49:53 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ld_sdmmc.c,v 1.23 2016/09/27 03:33:33 pgoyette Exp $ */
+/* $NetBSD: ld_sdmmc.c,v 1.24 2017/01/07 14:49:53 kiyohara Exp $ */
/*
* Copyright (c) 2008 KIYOHARA Takashi
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ld_sdmmc.c,v 1.23 2016/09/27 03:33:33 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ld_sdmmc.c,v 1.24 2017/01/07 14:49:53 kiyohara Exp $");
#ifdef _KERNEL_OPT
#include "opt_sdmmc.h"
@@ -59,6 +59,9 @@
#define DPRINTF(s) /**/
#endif
+#define LD_SDMMC_IORETRIES 5 /* number of retries before giving up */
+#define RECOVERYTIME hz/2 /* time to wait before retrying a cmd */
+
struct ld_sdmmc_softc;
struct ld_sdmmc_task {
@@ -66,6 +69,8 @@
struct ld_sdmmc_softc *task_sc;
struct buf *task_bp;
+ int task_retries; /* number of xfer retry */
+ struct callout task_restart_ch;
};
struct ld_sdmmc_softc {
@@ -75,7 +80,7 @@
struct sdmmc_function *sc_sf;
#define LD_SDMMC_MAXQUEUECNT 4
struct ld_sdmmc_task sc_task[LD_SDMMC_MAXQUEUECNT];
- int sc_nexttask;
+ TAILQ_HEAD(, sdmmc_task) sc_freeq;
};
static int ld_sdmmc_match(device_t, cfdata_t, void *);
@@ -84,6 +89,7 @@
static int ld_sdmmc_dump(struct ld_softc *, void *, int, int);
static int ld_sdmmc_start(struct ld_softc *, struct buf *);
+static void ld_sdmmc_restart(void *);
static void ld_sdmmc_doattach(void *);
static void ld_sdmmc_dobio(void *);
@@ -110,7 +116,9 @@
struct ld_sdmmc_softc *sc = device_private(self);
struct sdmmc_attach_args *sa = aux;
struct ld_softc *ld = &sc->sc_ld;
+ struct ld_sdmmc_task *task;
struct lwp *lwp;
+ int i;
ld->sc_dv = self;
@@ -119,7 +127,13 @@
sa->sf->cid.rev, sa->sf->cid.psn, sa->sf->cid.mdt);
aprint_naive("\n");
- sc->sc_nexttask = 0;
+ TAILQ_INIT(&sc->sc_freeq);
+ for (i = 0; i < __arraycount(sc->sc_task); i++) {
+ task = &sc->sc_task[i];
+ task->task_sc = sc;
+ callout_init(&task->task_restart_ch, 0);
+ TAILQ_INSERT_TAIL(&sc->sc_freeq, &task->task, next);
+ }
sc->sc_hwunit = 0; /* always 0? */
sc->sc_sf = sa->sf;
@@ -168,12 +182,15 @@
{
struct ld_sdmmc_softc *sc = device_private(dev);
struct ld_softc *ld = &sc->sc_ld;
- int rv;
+ int rv, i;
if ((rv = ldbegindetach(ld, flags)) != 0)
return rv;
ldenddetach(ld);
+ for (i = 0; i < __arraycount(sc->sc_task); i++)
+ callout_destroy(&sc->sc_task[i].task_restart_ch);
+
return 0;
}
@@ -181,12 +198,12 @@
ld_sdmmc_start(struct ld_softc *ld, struct buf *bp)
{
struct ld_sdmmc_softc *sc = device_private(ld->sc_dv);
- struct ld_sdmmc_task *task = &sc->sc_task[sc->sc_nexttask];
+ struct ld_sdmmc_task *task = (void *)TAILQ_FIRST(&sc->sc_freeq);
- sc->sc_nexttask = (sc->sc_nexttask + 1) % LD_SDMMC_MAXQUEUECNT;
+ TAILQ_REMOVE(&sc->sc_freeq, &task->task, next);
- task->task_sc = sc;
task->task_bp = bp;
+ task->task_retries = 0;
sdmmc_init_task(&task->task, ld_sdmmc_dobio, task);
sdmmc_add_task(sc->sc_sf->sc, &task->task);
@@ -195,6 +212,18 @@
}
static void
+ld_sdmmc_restart(void *arg)
+{
+ struct ld_sdmmc_task *task = (struct ld_sdmmc_task *)arg;
+ struct ld_sdmmc_softc *sc = task->task_sc;
+ struct buf *bp = task->task_bp;
+
+ bp->b_resid = bp->b_bcount;
+
+ sdmmc_add_task(sc->sc_sf->sc, &task->task);
+}
+
+static void
ld_sdmmc_dobio(void *arg)
{
struct ld_sdmmc_task *task = (struct ld_sdmmc_task *)arg;
@@ -228,14 +257,26 @@
error = sdmmc_mem_write_block(sc->sc_sf, bp->b_rawblkno,
bp->b_data, bp->b_bcount);
if (error) {
- DPRINTF(("%s: error %d\n", device_xname(sc->sc_ld.sc_dv),
- error));
+ if (task->task_retries < LD_SDMMC_IORETRIES) {
+ struct dk_softc *dksc = &sc->sc_ld.sc_dksc;
+ struct cfdriver *cd = device_cfdriver(dksc->sc_dev);
+
+ diskerr(bp, cd->cd_name, "error", LOG_PRINTF, 0,
+ dksc->sc_dkdev.dk_label);
+ printf(", retrying\n");
+ task->task_retries++;
+ callout_reset(&task->task_restart_ch, RECOVERYTIME,
+ ld_sdmmc_restart, task);
+ return;
+ }
bp->b_error = error;
bp->b_resid = bp->b_bcount;
} else {
bp->b_resid = 0;
}
+ TAILQ_INSERT_TAIL(&sc->sc_freeq, &task->task, next);
+
lddone(&sc->sc_ld, bp);
}
Home |
Main Index |
Thread Index |
Old Index