Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/jdolecek-ncqfixes]: src/sys/dev/ata remove explicit ata_channel_start() ...



details:   https://anonhg.NetBSD.org/src/rev/5f6a0a4f2370
branches:  jdolecek-ncqfixes
changeset: 850583:5f6a0a4f2370
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Sat Sep 22 17:50:09 2018 +0000

description:
remove explicit ata_channel_start() calls, it's no longer necessary
now that ata_xfer's are allocated via pool and not really limited;
replace by just a callout to restart the processing for rare cases
where system runs out of memory

diffstat:

 sys/dev/ata/TODO.ncq   |   2 -
 sys/dev/ata/ata_subr.c |  52 +------------------------------------------------
 sys/dev/ata/atavar.h   |   4 +--
 sys/dev/ata/wd.c       |  40 ++++++++++++++++++--------------------
 sys/dev/ata/wdvar.h    |   3 +-
 5 files changed, 24 insertions(+), 77 deletions(-)

diffs (264 lines):

diff -r 7db6c7bb3860 -r 5f6a0a4f2370 sys/dev/ata/TODO.ncq
--- a/sys/dev/ata/TODO.ncq      Sat Sep 22 16:14:25 2018 +0000
+++ b/sys/dev/ata/TODO.ncq      Sat Sep 22 17:50:09 2018 +0000
@@ -1,6 +1,4 @@
 jdolecek-ncqfixes goals:
-- add to wd(4) a callout to restart buf queue processing when ata_get_xfer()
-  call fails and remove ata_channel_start()
 - re-fix QEMU ahci(4) bug workaround (no READ LOG EXT support) - now it
   triggers KASSERT()
 - fix ahci(4) error handling under paralles - invalid bio via WD_CHAOS_MONKEY
diff -r 7db6c7bb3860 -r 5f6a0a4f2370 sys/dev/ata/ata_subr.c
--- a/sys/dev/ata/ata_subr.c    Sat Sep 22 16:14:25 2018 +0000
+++ b/sys/dev/ata/ata_subr.c    Sat Sep 22 17:50:09 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ata_subr.c,v 1.6.2.5 2018/09/22 09:22:59 jdolecek Exp $        */
+/*     $NetBSD: ata_subr.c,v 1.6.2.6 2018/09/22 17:50:09 jdolecek Exp $        */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata_subr.c,v 1.6.2.5 2018/09/22 09:22:59 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_subr.c,v 1.6.2.6 2018/09/22 17:50:09 jdolecek Exp $");
 
 #include "opt_ata.h"
 
@@ -257,54 +257,6 @@
        splx(s);
 }
 
-/*
- * Must be called without any locks, i.e. with both drive and channel locks
- * released.
- */ 
-void
-ata_channel_start(struct ata_channel *chp, int drive, bool start_self)
-{
-       int i, s;
-       struct ata_drive_datas *drvp;
-
-       s = splbio();
-
-       KASSERT(chp->ch_ndrives > 0);
-
-#define ATA_DRIVE_START(chp, drive) \
-       do {                                                    \
-               KASSERT(drive < chp->ch_ndrives);               \
-               drvp = &chp->ch_drive[drive];                   \
-                                                               \
-               if (drvp->drive_type != ATA_DRIVET_ATA &&       \
-                   drvp->drive_type != ATA_DRIVET_ATAPI &&     \
-                   drvp->drive_type != ATA_DRIVET_OLD)         \
-                       continue;                               \
-                                                               \
-               if (drvp->drv_start != NULL)                    \
-                       (*drvp->drv_start)(drvp->drv_softc);    \
-       } while (0)
-
-       /*
-        * Process drives in round robin fashion starting with next one after
-        * the one which finished transfer. Thus no single drive would
-        * completely starve other drives on same channel. 
-        * This loop processes all but the current drive, so won't do anything
-        * if there is only one drive in channel.
-        */
-       for (i = (drive + 1) % chp->ch_ndrives; i != drive;
-           i = (i + 1) % chp->ch_ndrives) {
-               ATA_DRIVE_START(chp, i);
-       }
-
-       /* Now try to kick off xfers on the current drive */
-       if (start_self)
-               ATA_DRIVE_START(chp, drive);
-
-       splx(s);
-#undef ATA_DRIVE_START
-}
-
 void
 ata_channel_lock(struct ata_channel *chp)
 {
diff -r 7db6c7bb3860 -r 5f6a0a4f2370 sys/dev/ata/atavar.h
--- a/sys/dev/ata/atavar.h      Sat Sep 22 16:14:25 2018 +0000
+++ b/sys/dev/ata/atavar.h      Sat Sep 22 17:50:09 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: atavar.h,v 1.99.2.6 2018/09/22 16:14:25 jdolecek Exp $ */
+/*     $NetBSD: atavar.h,v 1.99.2.7 2018/09/22 17:50:09 jdolecek Exp $ */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -327,7 +327,6 @@
 
        /* Callbacks into the drive's driver. */
        void    (*drv_done)(device_t, struct ata_xfer *); /* xfer is done */
-       void    (*drv_start)(device_t);                   /* start queue */
 
        device_t drv_softc;             /* ATA drives softc, if any */
        struct ata_channel *chnl_softc; /* channel softc */
@@ -547,7 +546,6 @@
 void   ata_reset_channel(struct ata_channel *, int);
 void   ata_channel_freeze(struct ata_channel *);
 void   ata_channel_thaw(struct ata_channel *);
-void   ata_channel_start(struct ata_channel *, int, bool);
 void   ata_channel_lock(struct ata_channel *);
 void   ata_channel_unlock(struct ata_channel *);
 void   ata_channel_lock_owned(struct ata_channel *);
diff -r 7db6c7bb3860 -r 5f6a0a4f2370 sys/dev/ata/wd.c
--- a/sys/dev/ata/wd.c  Sat Sep 22 16:14:25 2018 +0000
+++ b/sys/dev/ata/wd.c  Sat Sep 22 17:50:09 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wd.c,v 1.441.2.5 2018/09/22 16:14:25 jdolecek Exp $ */
+/*     $NetBSD: wd.c,v 1.441.2.6 2018/09/22 17:50:09 jdolecek Exp $ */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
@@ -54,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.441.2.5 2018/09/22 16:14:25 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.441.2.6 2018/09/22 17:50:09 jdolecek Exp $");
 
 #include "opt_ata.h"
 #include "opt_wd.h"
@@ -192,7 +192,7 @@
 static struct  wd_ioctl *wi_get(struct wd_softc *);
 static void    wdioctlstrategy(struct buf *);
 
-static void    wdstart(device_t);
+static void    wdrestart(void *);
 static void    wdstart1(struct wd_softc *, struct buf *, struct ata_xfer *);
 static int     wd_diskstart(device_t, struct buf *);
 static int     wd_dumpblocks(device_t, void *, daddr_t, int);
@@ -324,7 +324,6 @@
        wd->drvp = adev->adev_drv_data;
 
        wd->drvp->drv_openings = 1;
-       wd->drvp->drv_start = wdstart;
        wd->drvp->drv_done = wddone;
        wd->drvp->drv_softc = dksc->sc_dev; /* done in atabusconfig_thread()
                                             but too late */
@@ -333,6 +332,7 @@
        SLIST_INIT(&wd->sc_requeue_list);
        callout_init(&wd->sc_retry_callout, 0);         /* XXX MPSAFE */
        callout_init(&wd->sc_requeue_callout, 0);       /* XXX MPSAFE */
+       callout_init(&wd->sc_restart_diskqueue, 0);     /* XXX MPSAFE */
 
        aprint_naive("\n");
        aprint_normal("\n");
@@ -527,6 +527,8 @@
        callout_destroy(&wd->sc_retry_callout);
        callout_halt(&wd->sc_requeue_callout, &wd->sc_lock);
        callout_destroy(&wd->sc_requeue_callout);
+       callout_halt(&wd->sc_restart_diskqueue, &wd->sc_lock);
+       callout_destroy(&wd->sc_restart_diskqueue);
 
        mutex_exit(&wd->sc_lock);
 
@@ -749,6 +751,17 @@
        if (xfer == NULL) {
                ATADEBUG_PRINT(("wd_diskstart %s no xfer\n",
                    dksc->sc_xname), DEBUG_XFERS);
+
+               /*
+                * No available memory, retry later. This happens very rarely
+                * and only under memory pressure, so wait relatively long
+                * before retry.
+                */
+               if (!callout_pending(&wd->sc_restart_diskqueue)) {
+                       callout_reset(&wd->sc_restart_diskqueue, hz / 2,
+                           wdrestart, dev);
+               }
+
                mutex_exit(&wd->sc_lock);
                return EAGAIN;
        }
@@ -764,8 +777,9 @@
  * Queue a drive for I/O.
  */
 static void
-wdstart(device_t self)
+wdrestart(void *x)
 {
+       device_t self = x;
        struct wd_softc *wd = device_private(self);
        struct dk_softc *dksc = &wd->sc_dksc;
 
@@ -919,7 +933,6 @@
        ata_free_xfer(wd->drvp->chnl_softc, xfer);
 
        dk_done(dksc, bp);
-       ata_channel_start(wd->drvp->chnl_softc, wd->drvp->drive, true);
 }
 
 static void
@@ -1687,7 +1700,6 @@
 
 out:
        ata_free_xfer(wd->drvp->chnl_softc, xfer);
-       ata_channel_start(wd->drvp->chnl_softc, wd->drvp->drive, true);
        return error;
 }
 
@@ -1729,13 +1741,6 @@
 
 out:
        ata_free_xfer(wd->drvp->chnl_softc, xfer);
-
-       /*
-        * Drive is supposed to go idle, start only other drives.
-        * bufq might be actually already freed at this moment.
-        */
-       ata_channel_start(wd->drvp->chnl_softc, wd->drvp->drive, false);
-
        return error;
 }
 
@@ -1792,10 +1797,6 @@
 
 out_xfer:
        ata_free_xfer(wd->drvp->chnl_softc, xfer);
-
-       /* start again I/O processing possibly stopped due to no xfer */
-       ata_channel_start(wd->drvp->chnl_softc, wd->drvp->drive, start_self);
-
        return error;
 }
 
@@ -1855,7 +1856,6 @@
 
 out:
        ata_free_xfer(wd->drvp->chnl_softc, xfer);
-       ata_channel_start(wd->drvp->chnl_softc, wd->drvp->drive, true);
        return error;
 }
 
@@ -2062,8 +2062,6 @@
 
 out:
        ata_free_xfer(wi->wi_softc->drvp->chnl_softc, xfer);
-       ata_channel_start(wi->wi_softc->drvp->chnl_softc,
-           wi->wi_softc->drvp->drive, true);
 out2:
        bp->b_error = error;
        if (error)
diff -r 7db6c7bb3860 -r 5f6a0a4f2370 sys/dev/ata/wdvar.h
--- a/sys/dev/ata/wdvar.h       Sat Sep 22 16:14:25 2018 +0000
+++ b/sys/dev/ata/wdvar.h       Sat Sep 22 17:50:09 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wdvar.h,v 1.46.6.3 2018/09/22 16:14:25 jdolecek Exp $  */
+/*     $NetBSD: wdvar.h,v 1.46.6.4 2018/09/22 17:50:09 jdolecek Exp $  */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -67,6 +67,7 @@
        /* Retry/requeue failed transfers */
        SLIST_HEAD(, ata_xfer) sc_retry_list;
        struct callout sc_retry_callout;        /* retry callout handle */
+       struct callout sc_restart_diskqueue;    /* restart queue processing */
 
        SLIST_HEAD(, ata_xfer) sc_requeue_list;
        struct callout sc_requeue_callout;      /* requeue callout handle */



Home | Main Index | Thread Index | Old Index