Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/sdmmc Defer sdmmc discard operations to the sdmmc ta...
details: https://anonhg.NetBSD.org/src/rev/53f9857d08c5
branches: trunk
changeset: 355725:53f9857d08c5
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Fri Aug 11 18:41:42 2017 +0000
description:
Defer sdmmc discard operations to the sdmmc task queue. Fixes a panic
introduced by ld.c r1.102.
diffstat:
sys/dev/sdmmc/ld_sdmmc.c | 65 ++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 60 insertions(+), 5 deletions(-)
diffs (136 lines):
diff -r b6b1065ee846 -r 53f9857d08c5 sys/dev/sdmmc/ld_sdmmc.c
--- a/sys/dev/sdmmc/ld_sdmmc.c Fri Aug 11 16:47:42 2017 +0000
+++ b/sys/dev/sdmmc/ld_sdmmc.c Fri Aug 11 18:41:42 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ld_sdmmc.c,v 1.32 2017/08/09 16:44:40 mlelstv Exp $ */
+/* $NetBSD: ld_sdmmc.c,v 1.33 2017/08/11 18:41:42 jmcneill Exp $ */
/*
* Copyright (c) 2008 KIYOHARA Takashi
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ld_sdmmc.c,v 1.32 2017/08/09 16:44:40 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ld_sdmmc.c,v 1.33 2017/08/11 18:41:42 jmcneill Exp $");
#ifdef _KERNEL_OPT
#include "opt_sdmmc.h"
@@ -65,15 +65,24 @@
#define LD_SDMMC_IORETRIES 5 /* number of retries before giving up */
#define RECOVERYTIME hz/2 /* time to wait before retrying a cmd */
+#define LD_SDMMC_MAXQUEUECNT 4 /* number of queued bio requests */
+#define LD_SDMMC_MAXTASKCNT 8 /* number of tasks in task pool */
+
struct ld_sdmmc_softc;
struct ld_sdmmc_task {
struct sdmmc_task task;
struct ld_sdmmc_softc *task_sc;
+
+ /* bio tasks */
struct buf *task_bp;
int task_retries; /* number of xfer retry */
struct callout task_restart_ch;
+
+ /* discard tasks */
+ off_t task_pos;
+ off_t task_len;
};
struct ld_sdmmc_softc {
@@ -81,9 +90,12 @@
int sc_hwunit;
struct sdmmc_function *sc_sf;
-#define LD_SDMMC_MAXQUEUECNT 4
- struct ld_sdmmc_task sc_task[LD_SDMMC_MAXQUEUECNT];
+ struct ld_sdmmc_task sc_task[LD_SDMMC_MAXTASKCNT];
pcq_t *sc_freeq;
+
+ struct evcnt sc_ev_discard; /* discard counter */
+ struct evcnt sc_ev_discarderr; /* discard error counter */
+ struct evcnt sc_ev_discardbusy; /* discard busy counter */
};
static int ld_sdmmc_match(device_t, cfdata_t, void *);
@@ -98,6 +110,7 @@
static void ld_sdmmc_doattach(void *);
static void ld_sdmmc_dobio(void *);
+static void ld_sdmmc_dodiscard(void *);
CFATTACH_DECL_NEW(ld_sdmmc, sizeof(struct ld_sdmmc_softc),
ld_sdmmc_match, ld_sdmmc_attach, ld_sdmmc_detach, NULL);
@@ -132,6 +145,13 @@
sa->sf->cid.rev, sa->sf->cid.psn, sa->sf->cid.mdt);
aprint_naive("\n");
+ evcnt_attach_dynamic(&sc->sc_ev_discard, EVCNT_TYPE_MISC,
+ NULL, device_xname(self), "sdmmc discard count");
+ evcnt_attach_dynamic(&sc->sc_ev_discarderr, EVCNT_TYPE_MISC,
+ NULL, device_xname(self), "sdmmc discard errors");
+ evcnt_attach_dynamic(&sc->sc_ev_discardbusy, EVCNT_TYPE_MISC,
+ NULL, device_xname(self), "sdmmc discard busy");
+
const int ntask = __arraycount(sc->sc_task);
sc->sc_freeq = pcq_create(ntask, KM_SLEEP);
for (i = 0; i < ntask; i++) {
@@ -213,6 +233,9 @@
callout_destroy(&sc->sc_task[i].task_restart_ch);
pcq_destroy(sc->sc_freeq);
+ evcnt_detach(&sc->sc_ev_discard);
+ evcnt_detach(&sc->sc_ev_discarderr);
+ evcnt_detach(&sc->sc_ev_discardbusy);
return 0;
}
@@ -314,12 +337,44 @@
blkcnt * ld->sc_secsize);
}
+static void
+ld_sdmmc_dodiscard(void *arg)
+{
+ struct ld_sdmmc_task *task = arg;
+ struct ld_sdmmc_softc *sc = task->task_sc;
+ const off_t pos = task->task_pos;
+ const off_t len = task->task_len;
+ int error;
+
+ /* An error from discard is non-fatal */
+ error = sdmmc_mem_discard(sc->sc_sf, pos, len);
+ if (error != 0)
+ sc->sc_ev_discarderr.ev_count++;
+ else
+ sc->sc_ev_discard.ev_count++;
+
+ pcq_put(sc->sc_freeq, task);
+}
+
static int
ld_sdmmc_discard(struct ld_softc *ld, off_t pos, off_t len)
{
struct ld_sdmmc_softc *sc = device_private(ld->sc_dv);
+ struct ld_sdmmc_task *task = pcq_get(sc->sc_freeq);
- return sdmmc_mem_discard(sc->sc_sf, pos, len);
+ if (task == NULL) {
+ sc->sc_ev_discardbusy.ev_count++;
+ return 0;
+ }
+
+ task->task_pos = pos;
+ task->task_len = len;
+
+ sdmmc_init_task(&task->task, ld_sdmmc_dodiscard, task);
+
+ sdmmc_add_task(sc->sc_sf->sc, &task->task);
+
+ return 0;
}
static int
Home |
Main Index |
Thread Index |
Old Index