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 DIOCCACHESYNC to the sdmmc task queue so...



details:   https://anonhg.NetBSD.org/src/rev/2953b7a476d0
branches:  trunk
changeset: 445696:2953b7a476d0
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Fri Nov 09 14:39:19 2018 +0000

description:
Defer DIOCCACHESYNC to the sdmmc task queue so they are serialized with other requests.

diffstat:

 sys/dev/sdmmc/ld_sdmmc.c |  62 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 57 insertions(+), 5 deletions(-)

diffs (119 lines):

diff -r db0736464653 -r 2953b7a476d0 sys/dev/sdmmc/ld_sdmmc.c
--- a/sys/dev/sdmmc/ld_sdmmc.c  Fri Nov 09 14:38:36 2018 +0000
+++ b/sys/dev/sdmmc/ld_sdmmc.c  Fri Nov 09 14:39:19 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ld_sdmmc.c,v 1.34 2017/08/20 15:58:43 mlelstv Exp $    */
+/*     $NetBSD: ld_sdmmc.c,v 1.35 2018/11/09 14:39:19 jmcneill Exp $   */
 
 /*
  * Copyright (c) 2008 KIYOHARA Takashi
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ld_sdmmc.c,v 1.34 2017/08/20 15:58:43 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ld_sdmmc.c,v 1.35 2018/11/09 14:39:19 jmcneill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -78,6 +78,11 @@
        struct buf *task_bp;
        int task_retries; /* number of xfer retry */
        struct callout task_restart_ch;
+
+       kmutex_t task_lock;
+       kcondvar_t task_cv;
+
+       uintptr_t task_data;
 };
 
 struct ld_sdmmc_softc {
@@ -91,6 +96,7 @@
        struct evcnt sc_ev_discard;     /* discard counter */
        struct evcnt sc_ev_discarderr;  /* discard error counter */
        struct evcnt sc_ev_discardbusy; /* discard busy counter */
+       struct evcnt sc_ev_cachesyncbusy; /* cache sync busy counter */
 };
 
 static int ld_sdmmc_match(device_t, cfdata_t, void *);
@@ -153,6 +159,8 @@
                task = &sc->sc_task[i];
                task->task_sc = sc;
                callout_init(&task->task_restart_ch, CALLOUT_MPSAFE);
+               mutex_init(&task->task_lock, MUTEX_DEFAULT, IPL_NONE);
+               cv_init(&task->task_cv, "ldsdmmctask");
                pcq_put(sc->sc_freeq, task);
        }
 
@@ -224,8 +232,11 @@
                return rv;
        ldenddetach(ld);
 
-       for (i = 0; i < __arraycount(sc->sc_task); i++)
+       for (i = 0; i < __arraycount(sc->sc_task); i++) {
                callout_destroy(&sc->sc_task[i].task_restart_ch);
+               mutex_destroy(&sc->sc_task[i].task_lock);
+               cv_destroy(&sc->sc_task[i].task_cv);
+       }
 
        pcq_destroy(sc->sc_freeq);
        evcnt_detach(&sc->sc_ev_discard);
@@ -379,15 +390,56 @@
        return 0;
 }
 
+static void
+ld_sdmmc_docachesync(void *arg)
+{
+       struct ld_sdmmc_task *task = arg;
+       struct ld_sdmmc_softc *sc = task->task_sc;
+       const bool poll = (bool)task->task_data;
+
+       task->task_data = sdmmc_mem_flush_cache(sc->sc_sf, poll);
+
+       mutex_enter(&task->task_lock);
+       cv_signal(&task->task_cv);
+       mutex_exit(&task->task_lock);
+}
+
+static int
+ld_sdmmc_cachesync(struct ld_softc *ld, bool poll)
+{
+       struct ld_sdmmc_softc *sc = device_private(ld->sc_dv);
+       struct ld_sdmmc_task *task = pcq_get(sc->sc_freeq);
+       int error = 0;
+
+       if (task == NULL) {
+               sc->sc_ev_cachesyncbusy.ev_count++;
+               return EBUSY;
+       }
+
+       sdmmc_init_task(&task->task, ld_sdmmc_docachesync, task);
+       task->task_data = poll;
+
+       mutex_enter(&task->task_lock);
+       sdmmc_add_task(sc->sc_sf->sc, &task->task);
+       error = cv_wait_sig(&task->task_cv, &task->task_lock);
+       mutex_exit(&task->task_lock);
+
+       if (error == 0)
+               error = (int)task->task_data;
+
+       pcq_put(sc->sc_freeq, task);
+
+       return error;
+}
+
 static int
 ld_sdmmc_ioctl(struct ld_softc *ld, u_long cmd, void *addr, int32_t flag,
     bool poll)
 {
-       struct ld_sdmmc_softc *sc = device_private(ld->sc_dv);
 
        switch (cmd) {
        case DIOCCACHESYNC:
-               return sdmmc_mem_flush_cache(sc->sc_sf, poll);
+               return ld_sdmmc_cachesync(ld, poll);
        default:
                return EPASSTHROUGH;
        }



Home | Main Index | Thread Index | Old Index