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