Source-Changes-HG archive

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

[src/netbsd-9]: src/sys/dev Pull up following revision(s) (requested by tsuts...



details:   https://anonhg.NetBSD.org/src/rev/9176a3ffafe0
branches:  netbsd-9
changeset: 372848:9176a3ffafe0
user:      martin <martin%NetBSD.org@localhost>
date:      Fri Dec 30 14:39:09 2022 +0000

description:
Pull up following revision(s) (requested by tsutsui in ticket #1557):

        sys/dev/ic/ahcisata_core.c: revision 1.83
        sys/dev/ic/ahcisata_core.c: revision 1.102
        sys/dev/ata/ata.c: revision 1.164
        sys/dev/ata/ata_wdc.c: revision 1.115
        sys/dev/ata/ata_recovery.c: revision 1.4
        sys/dev/ic/siisata.c: revision 1.42
        sys/dev/ic/wdc.c: revision 1.308
        sys/dev/ic/mvsata.c: revision 1.56
        sys/dev/scsipi/atapi_wdc.c: revision 1.138
        sys/dev/ic/siisata.c: revision 1.49
        sys/dev/ata/atavar.h: revision 1.105
        sys/dev/ata/wd.c: revision 1.460
        sys/dev/ata/ata.c: revision 1.155
        sys/dev/ata/wd.c: revision 1.462
        sys/dev/ata/atavar.h: revision 1.109
        sys/dev/ata/satapmp_subr.c: revision 1.16
        sys/dev/ic/wdc.c: revision 1.299
        sys/dev/ic/ahcisata_core.c: revision 1.93
        sys/dev/ata/ata_wdc.c: revision 1.120
        sys/dev/ic/wdcvar.h: revision 1.100
        sys/dev/scsipi/atapi_wdc.c: revision 1.141
        sys/dev/ic/mvsata.c: revision 1.61
        sys/dev/usb/umass_isdata.c      (apply patch)

drop wd lock in wdstart1() before calling the ata_bio hook; when called
from ata thread context, that can still need to sleep for wdc attachments
in wdcwait()

fix use-after-free for ata xfer on bio submission found by KASAN
driver ata_bio hooks read parts of the xfer after ata_exec_xfer()
call in order to determine return value, change so that the hook
doesn't return any value - callers do not care already,
as all I/O requests are asynchronous

this problem was uncovered by recent change for wd(4) to not hold
wd mutex during ata_bio call, the interrupt for the xfer might
thus actually fire immediately

adjust also ata_exec_command driver hooks similarily - remove all
completion and waiting logic from drivers, upper layer ata code
using AT_WAIT/AT_POLL changed to call ata_wait_cmd() itself
PR kern/55169 by Nick Hudson

Function declaration formating whitespace consistency.  NFCI.

PR kern/56403
Fix kernel freeze for wdc(4) variants with ATAC_CAP_NOIRQ:

(1) Change ata_xfer_ops:c_poll from void to int function. When it returns
    ATAPOLL_AGAIN, let ata_xfer_start() iterate itself again.
(2) Let wdc_ata_bio_poll() return ATAPOLL_AGAIN until ATA_ITSDONE is
    achieved.

A similar change has been made for mvsata(4) (see mvsata_bio_poll()),
and no functional changes for other devices.

This is how the drivers worked before jdolecek-ncq branch was merged.
Note that this changes are less likely to cause infinite recursion:

(1) wdc_ata_bio_intr() called from wdc_ata_bio_poll() asserts ATA_ITSDONE
    in its error handling paths via wdc_ata_bio_done().
(2) Return value from c_start (= wdc_ata_bio_start()) is checked in
    ata_xfer_start().

Therefore, errors encountered in ata_xfer_ops:c_poll and c_start routines
terminate the recursion for wdc(4). The situation is similar for mvsata(4).

Still, there is a possibility where ata_xfer_start() takes long time to
finish a normal operation. This can result in a delayed response for lower
priority interrupts. But, I've never observed such a situation, even when
heavy thrashing takes place for swap partition in wd(4).
"Go ahead" by jdolecek@.

diffstat:

 sys/dev/ata/ata.c          |  27 +++++-------
 sys/dev/ata/ata_recovery.c |  12 ++---
 sys/dev/ata/ata_wdc.c      |  22 +++++----
 sys/dev/ata/atavar.h       |  10 ++-
 sys/dev/ata/satapmp_subr.c |  26 ++++-------
 sys/dev/ata/wd.c           |  97 +++++++++++++++++----------------------------
 sys/dev/ic/ahcisata_core.c |  58 +++++++++-----------------
 sys/dev/ic/mvsata.c        |  61 +++++++++++-----------------
 sys/dev/ic/siisata.c       |  56 +++++++++-----------------
 sys/dev/ic/wdc.c           |  30 ++-----------
 sys/dev/ic/wdcvar.h        |   4 +-
 sys/dev/scsipi/atapi_wdc.c |  22 +++++-----
 sys/dev/usb/umass_isdata.c |  40 +++++++-----------
 13 files changed, 179 insertions(+), 286 deletions(-)

diffs (truncated from 1351 to 300 lines):

diff -r 5409c64da327 -r 9176a3ffafe0 sys/dev/ata/ata.c
--- a/sys/dev/ata/ata.c Wed Dec 28 17:59:01 2022 +0000
+++ b/sys/dev/ata/ata.c Fri Dec 30 14:39:09 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ata.c,v 1.149.2.2 2022/08/30 18:28:42 martin Exp $     */
+/*     $NetBSD: ata.c,v 1.149.2.3 2022/12/30 14:39:10 martin Exp $     */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.149.2.2 2022/08/30 18:28:42 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.149.2.3 2022/12/30 14:39:10 martin Exp $");
 
 #include "opt_ata.h"
 
@@ -842,13 +842,8 @@
        xfer->c_ata_c.flags = AT_READ | flags;
        xfer->c_ata_c.data = tb;
        xfer->c_ata_c.bcount = ATA_BSIZE;
-       if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
-                                               xfer) != ATACMD_COMPLETE) {
-               ATADEBUG_PRINT(("ata_get_parms: wdc_exec_command failed\n"),
-                   DEBUG_FUNCS|DEBUG_PROBE);
-               rv = CMD_AGAIN;
-               goto out;
-       }
+       (*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer);
+       ata_wait_cmd(chp, xfer);
        if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
                ATADEBUG_PRINT(("ata_get_parms: ata_c.flags=0x%x\n",
                    xfer->c_ata_c.flags), DEBUG_FUNCS|DEBUG_PROBE);
@@ -932,11 +927,8 @@
        xfer->c_ata_c.r_count = mode;
        xfer->c_ata_c.flags = flags;
        xfer->c_ata_c.timeout = 1000; /* 1s */
-       if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
-                                               xfer) != ATACMD_COMPLETE) {
-               rv = CMD_AGAIN;
-               goto out;
-       }
+       (*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer);
+       ata_wait_cmd(chp, xfer);
        if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
                rv = CMD_ERR;
                goto out;
@@ -1218,10 +1210,11 @@
 ata_xfer_start(struct ata_xfer *xfer)
 {
        struct ata_channel *chp = xfer->c_chp;
-       int rv;
+       int rv, status;
 
        KASSERT(mutex_owned(&chp->ch_lock));
 
+again:
        rv = xfer->ops->c_start(chp, xfer);
        switch (rv) {
        case ATASTART_STARTED:
@@ -1235,8 +1228,10 @@
                /* can happen even in thread context for some ATAPI devices */
                ata_channel_unlock(chp);
                KASSERT(xfer->ops != NULL && xfer->ops->c_poll != NULL);
-               xfer->ops->c_poll(chp, xfer);
+               status = xfer->ops->c_poll(chp, xfer);
                ata_channel_lock(chp);
+               if (status == ATAPOLL_AGAIN)
+                       goto again;
                break;
        case ATASTART_ABORT:
                ata_channel_unlock(chp);
diff -r 5409c64da327 -r 9176a3ffafe0 sys/dev/ata/ata_recovery.c
--- a/sys/dev/ata/ata_recovery.c        Wed Dec 28 17:59:01 2022 +0000
+++ b/sys/dev/ata/ata_recovery.c        Fri Dec 30 14:39:09 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ata_recovery.c,v 1.2.8.1 2022/02/08 14:45:00 martin Exp $      */
+/*     $NetBSD: ata_recovery.c,v 1.2.8.2 2022/12/30 14:39:10 martin Exp $      */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata_recovery.c,v 1.2.8.1 2022/02/08 14:45:00 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_recovery.c,v 1.2.8.2 2022/12/30 14:39:10 martin Exp $");
 
 #include "opt_ata.h"
 
@@ -103,11 +103,9 @@
        xfer->c_ata_c.data = tb;
        xfer->c_ata_c.bcount = sizeof(chp->recovery_blk);
 
-       if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
-                                               xfer) != ATACMD_COMPLETE) {
-               rv = EAGAIN;
-               goto out;
-       }
+       (*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer);
+       ata_wait_cmd(chp, xfer);
+
        if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
                rv = EINVAL;
                goto out;
diff -r 5409c64da327 -r 9176a3ffafe0 sys/dev/ata/ata_wdc.c
--- a/sys/dev/ata/ata_wdc.c     Wed Dec 28 17:59:01 2022 +0000
+++ b/sys/dev/ata/ata_wdc.c     Fri Dec 30 14:39:09 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ata_wdc.c,v 1.113 2018/11/12 18:51:01 jdolecek Exp $   */
+/*     $NetBSD: ata_wdc.c,v 1.113.4.1 2022/12/30 14:39:10 martin Exp $ */
 
 /*
  * Copyright (c) 1998, 2001, 2003 Manuel Bouyer.
@@ -54,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.113 2018/11/12 18:51:01 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.113.4.1 2022/12/30 14:39:10 martin Exp $");
 
 #include "opt_ata.h"
 #include "opt_wdc.h"
@@ -102,10 +102,10 @@
 
 #define ATA_DELAY 10000 /* 10s for a drive I/O */
 
-static int     wdc_ata_bio(struct ata_drive_datas*, struct ata_xfer *);
+static void    wdc_ata_bio(struct ata_drive_datas*, struct ata_xfer *);
 static int     wdc_ata_bio_start(struct ata_channel *,struct ata_xfer *);
 static int     _wdc_ata_bio_start(struct ata_channel *,struct ata_xfer *);
-static void    wdc_ata_bio_poll(struct ata_channel *,struct ata_xfer *);
+static int     wdc_ata_bio_poll(struct ata_channel *,struct ata_xfer *);
 static int     wdc_ata_bio_intr(struct ata_channel *, struct ata_xfer *,
                                 int);
 static void    wdc_ata_bio_kill_xfer(struct ata_channel *,
@@ -140,10 +140,9 @@
 };
 
 /*
- * Handle block I/O operation. Return ATACMD_COMPLETE, ATACMD_QUEUED, or
- * ATACMD_TRY_AGAIN. Must be called at splbio().
+ * Handle block I/O operation.
  */
-static int
+static void
 wdc_ata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer)
 {
        struct ata_channel *chp = drvp->chnl_softc;
@@ -171,7 +170,6 @@
        xfer->c_bcount = ata_bio->bcount;
        xfer->ops = &wdc_bio_xfer_ops;
        ata_exec_xfer(chp, xfer);
-       return (ata_bio->flags & ATA_ITSDONE) ? ATACMD_COMPLETE : ATACMD_QUEUED;
 }
 
 static int
@@ -617,7 +615,7 @@
        return ATASTART_ABORT;
 }
 
-static void
+static int
 wdc_ata_bio_poll(struct ata_channel *chp, struct ata_xfer *xfer)
 {
        /* Wait for at last 400ns for status bit to be valid */
@@ -629,6 +627,7 @@
        }
 #endif
        wdc_ata_bio_intr(chp, xfer, 0);
+       return (xfer->c_bio.flags & ATA_ITSDONE) ? ATAPOLL_DONE : ATAPOLL_AGAIN;
 }
 
 static int
@@ -779,7 +778,10 @@
                        /* Start the next operation */
                        ata_xfer_start(xfer);
                } else {
-                       /* Let _wdc_ata_bio_start do the loop */
+                       /*
+                        * Let ata_xfer_start() do the loop;
+                        * see wdc_ata_bio_poll().
+                        */
                }
                ata_channel_unlock(chp);
                return 1;
diff -r 5409c64da327 -r 9176a3ffafe0 sys/dev/ata/atavar.h
--- a/sys/dev/ata/atavar.h      Wed Dec 28 17:59:01 2022 +0000
+++ b/sys/dev/ata/atavar.h      Fri Dec 30 14:39:09 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: atavar.h,v 1.103 2019/04/05 21:31:44 bouyer Exp $      */
+/*     $NetBSD: atavar.h,v 1.103.4.1 2022/12/30 14:39:10 martin Exp $  */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -178,7 +178,9 @@
 #define ATASTART_TH            1       /* xfer needs to be run in thread */
 #define ATASTART_POLL          2       /* xfer needs to be polled */
 #define ATASTART_ABORT         3       /* error occurred, abort xfer */
-       void    (*c_poll)(struct ata_channel *, struct ata_xfer *);
+       int     (*c_poll)(struct ata_channel *, struct ata_xfer *);
+#define        ATAPOLL_DONE            0
+#define        ATAPOLL_AGAIN           1
        void    (*c_abort)(struct ata_channel *, struct ata_xfer *);
        int     (*c_intr)(struct ata_channel *, struct ata_xfer *, int);
        void    (*c_kill_xfer)(struct ata_channel *, struct ata_xfer *, int);
@@ -358,10 +360,10 @@
  */
 struct ata_bustype {
        int     bustype_type;   /* symbolic name of type */
-       int     (*ata_bio)(struct ata_drive_datas *, struct ata_xfer *);
+       void    (*ata_bio)(struct ata_drive_datas *, struct ata_xfer *);
        void    (*ata_reset_drive)(struct ata_drive_datas *, int, uint32_t *);
        void    (*ata_reset_channel)(struct ata_channel *, int);
-       int     (*ata_exec_command)(struct ata_drive_datas *,
+       void    (*ata_exec_command)(struct ata_drive_datas *,
                                    struct ata_xfer *);
 
 #define        ATACMD_COMPLETE         0x01
diff -r 5409c64da327 -r 9176a3ffafe0 sys/dev/ata/satapmp_subr.c
--- a/sys/dev/ata/satapmp_subr.c        Wed Dec 28 17:59:01 2022 +0000
+++ b/sys/dev/ata/satapmp_subr.c        Fri Dec 30 14:39:09 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: satapmp_subr.c,v 1.15 2018/10/22 20:13:47 jdolecek Exp $       */
+/*     $NetBSD: satapmp_subr.c,v 1.15.4.1 2022/12/30 14:39:10 martin Exp $     */
 
 /*
  * Copyright (c) 2012 Manuel Bouyer.  All rights reserved.
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: satapmp_subr.c,v 1.15 2018/10/22 20:13:47 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: satapmp_subr.c,v 1.15.4.1 2022/12/30 14:39:10 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -72,13 +72,10 @@
        xfer->c_ata_c.flags = AT_LBA48 | AT_READREG | AT_WAIT;
 
        ata_channel_unlock(chp);
-       if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
-           xfer) != ATACMD_COMPLETE) {
-               aprint_error_dev(chp->atabus,
-                   "PMP port %d register %d read failed\n", port, reg);
-               error = EIO;
-               goto out;
-       }
+
+       (*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer);
+       ata_wait_cmd(chp, xfer);
+
        if (xfer->c_ata_c.flags & (AT_TIMEOU | AT_DF)) {
                aprint_error_dev(chp->atabus,
                    "PMP port %d register %d read failed, flags 0x%x\n",
@@ -148,13 +145,10 @@
        xfer->c_ata_c.flags = AT_LBA48 | AT_WAIT;
 
        ata_channel_unlock(chp);
-       if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
-           xfer) != ATACMD_COMPLETE) {
-               aprint_error_dev(chp->atabus,
-                   "PMP port %d register %d write failed\n", port, reg);
-               error = EIO;
-               goto out;
-       }
+
+       (*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer);
+       ata_wait_cmd(chp, xfer);
+
        if (xfer->c_ata_c.flags & (AT_TIMEOU | AT_DF)) {
                aprint_error_dev(chp->atabus,
                    "PMP port %d register %d write failed, flags 0x%x\n",
diff -r 5409c64da327 -r 9176a3ffafe0 sys/dev/ata/wd.c
--- a/sys/dev/ata/wd.c  Wed Dec 28 17:59:01 2022 +0000
+++ b/sys/dev/ata/wd.c  Fri Dec 30 14:39:09 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wd.c,v 1.452.2.2 2020/03/21 15:52:09 martin Exp $ */
+/*     $NetBSD: wd.c,v 1.452.2.3 2022/12/30 14:39:10 martin 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.452.2.2 2020/03/21 15:52:09 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.452.2.3 2022/12/30 14:39:10 martin Exp $");
 
 #include "opt_ata.h"
 #include "opt_wd.h"
@@ -201,7 +201,7 @@
 static void    wdbioretry(void *);
 static void    wdbiorequeue(void *);
 static void    wddone(device_t, struct ata_xfer *);
-static int     wd_get_params(struct wd_softc *, uint8_t, struct ataparams *);
+static int     wd_get_params(struct wd_softc *, struct ataparams *);
 static void    wd_set_geometry(struct wd_softc *);
 static int     wd_flushcache(struct wd_softc *, int, bool);



Home | Main Index | Thread Index | Old Index