Source-Changes-HG archive

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

[src/jdolecek-ncq]: src/sys/dev pass also ata_command via ata_xfer, callers o...



details:   https://anonhg.NetBSD.org/src/rev/eec43e71c042
branches:  jdolecek-ncq
changeset: 822876:eec43e71c042
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Sat Apr 15 17:14:11 2017 +0000

description:
pass also ata_command via ata_xfer, callers of ata_exec_command() is now
responsible for allocation/disposal of the structure

change code to allocate ata_xfer for commands on stack same way as previously
the ata_command were, using c_slot 0; adjust asserts so that it would allow
several xfers with same c_slot, as long as only one such transfer is active
at a time

diffstat:

 sys/dev/ata/ata.c          |   81 +++++++++++---------
 sys/dev/ata/atavar.h       |  125 ++++++++++++++++---------------
 sys/dev/ata/satapmp_subr.c |   72 +++++++++---------
 sys/dev/ata/wd.c           |  175 +++++++++++++++++++++++---------------------
 sys/dev/ic/ahcisata_core.c |   32 +++----
 sys/dev/ic/mvsata.c        |   54 ++++++-------
 sys/dev/ic/siisata.c       |   39 ++++-----
 sys/dev/ic/wdc.c           |   25 ++----
 sys/dev/ic/wdcvar.h        |    4 +-
 sys/dev/scsipi/atapi_wdc.c |   40 +++++-----
 10 files changed, 322 insertions(+), 325 deletions(-)

diffs (truncated from 1622 to 300 lines):

diff -r f4e85c4284d7 -r eec43e71c042 sys/dev/ata/ata.c
--- a/sys/dev/ata/ata.c Sat Apr 15 12:01:23 2017 +0000
+++ b/sys/dev/ata/ata.c Sat Apr 15 17:14:11 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ata.c,v 1.132.8.3 2017/04/15 12:01:23 jdolecek Exp $   */
+/*     $NetBSD: ata.c,v 1.132.8.4 2017/04/15 17:14:11 jdolecek 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.132.8.3 2017/04/15 12:01:23 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.132.8.4 2017/04/15 17:14:11 jdolecek Exp $");
 
 #include "opt_ata.h"
 
@@ -192,10 +192,18 @@
 struct ata_xfer *
 ata_queue_hwslot_to_xfer(struct ata_queue *chq, int hwslot)
 {
+       struct ata_xfer *xfer;
+
        KASSERT(hwslot < chq->queue_openings);
-       KASSERT((chq->queue_xfers_avail & __BIT(hwslot)) == 0);
+       KASSERT(hwslot == 0 || (chq->queue_xfers_avail & __BIT(hwslot)) == 0);
 
-       return &chq->queue_xfers[hwslot];
+       /* Usually the first entry will be the one */
+       TAILQ_FOREACH(xfer, &chq->active_xfers, c_activechain) {
+               if (xfer->c_slot == hwslot)
+                       return xfer;
+       }
+
+       panic("%s: xfer with slot %d not found", __func__, hwslot);
 }
 
 struct ata_queue *
@@ -204,7 +212,7 @@
        if (openings == 0)
                openings = 1;
        struct ata_queue *chq = malloc(offsetof(struct ata_queue, queue_xfers[openings]),
-           M_DEVBUF, M_WAITOK);
+           M_DEVBUF, M_WAITOK | M_ZERO);
        if (chq != NULL) {
                chq->queue_openings = openings;
                chq->queue_xfers_avail = (1 << openings) - 1;
@@ -768,7 +776,7 @@
 ata_get_params(struct ata_drive_datas *drvp, uint8_t flags,
     struct ataparams *prms)
 {
-       struct ata_command ata_c;
+       struct ata_xfer xfer;
        struct ata_channel *chp = drvp->chnl_softc;
        struct atac_softc *atac = chp->ch_atac;
        char *tb;
@@ -779,42 +787,42 @@
 
        tb = kmem_zalloc(DEV_BSIZE, KM_SLEEP);
        memset(prms, 0, sizeof(struct ataparams));
-       memset(&ata_c, 0, sizeof(struct ata_command));
+       memset(&xfer, 0, sizeof(xfer));
 
        if (drvp->drive_type == ATA_DRIVET_ATA) {
-               ata_c.r_command = WDCC_IDENTIFY;
-               ata_c.r_st_bmask = WDCS_DRDY;
-               ata_c.r_st_pmask = WDCS_DRQ;
-               ata_c.timeout = 3000; /* 3s */
+               xfer.c_ata_c.r_command = WDCC_IDENTIFY;
+               xfer.c_ata_c.r_st_bmask = WDCS_DRDY;
+               xfer.c_ata_c.r_st_pmask = WDCS_DRQ;
+               xfer.c_ata_c.timeout = 3000; /* 3s */
        } else if (drvp->drive_type == ATA_DRIVET_ATAPI) {
-               ata_c.r_command = ATAPI_IDENTIFY_DEVICE;
-               ata_c.r_st_bmask = 0;
-               ata_c.r_st_pmask = WDCS_DRQ;
-               ata_c.timeout = 10000; /* 10s */
+               xfer.c_ata_c.r_command = ATAPI_IDENTIFY_DEVICE;
+               xfer.c_ata_c.r_st_bmask = 0;
+               xfer.c_ata_c.r_st_pmask = WDCS_DRQ;
+               xfer.c_ata_c.timeout = 10000; /* 10s */
        } else {
                ATADEBUG_PRINT(("ata_get_parms: no disks\n"),
                    DEBUG_FUNCS|DEBUG_PROBE);
                rv = CMD_ERR;
                goto out;
        }
-       ata_c.flags = AT_READ | flags;
-       ata_c.data = tb;
-       ata_c.bcount = DEV_BSIZE;
+       xfer.c_ata_c.flags = AT_READ | flags;
+       xfer.c_ata_c.data = tb;
+       xfer.c_ata_c.bcount = DEV_BSIZE;
        if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
-                                               &ata_c) != ATACMD_COMPLETE) {
+                                               &xfer) != ATACMD_COMPLETE) {
                ATADEBUG_PRINT(("ata_get_parms: wdc_exec_command failed\n"),
                    DEBUG_FUNCS|DEBUG_PROBE);
                rv = CMD_AGAIN;
                goto out;
        }
-       if (ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
+       if (xfer.c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
                ATADEBUG_PRINT(("ata_get_parms: ata_c.flags=0x%x\n",
-                   ata_c.flags), DEBUG_FUNCS|DEBUG_PROBE);
+                   xfer.c_ata_c.flags), DEBUG_FUNCS|DEBUG_PROBE);
                rv = CMD_ERR;
                goto out;
        }
        /* if we didn't read any data something is wrong */
-       if ((ata_c.flags & AT_XFDONE) == 0) {
+       if ((xfer.c_ata_c.flags & AT_XFDONE) == 0) {
                rv = CMD_ERR;
                goto out;
        }
@@ -868,24 +876,24 @@
 int
 ata_set_mode(struct ata_drive_datas *drvp, uint8_t mode, uint8_t flags)
 {
-       struct ata_command ata_c;
+       struct ata_xfer xfer;
        struct ata_channel *chp = drvp->chnl_softc;
        struct atac_softc *atac = chp->ch_atac;
 
        ATADEBUG_PRINT(("ata_set_mode=0x%x\n", mode), DEBUG_FUNCS);
-       memset(&ata_c, 0, sizeof(struct ata_command));
+       memset(&xfer, 0, sizeof(xfer));
 
-       ata_c.r_command = SET_FEATURES;
-       ata_c.r_st_bmask = 0;
-       ata_c.r_st_pmask = 0;
-       ata_c.r_features = WDSF_SET_MODE;
-       ata_c.r_count = mode;
-       ata_c.flags = flags;
-       ata_c.timeout = 1000; /* 1s */
+       xfer.c_ata_c.r_command = SET_FEATURES;
+       xfer.c_ata_c.r_st_bmask = 0;
+       xfer.c_ata_c.r_st_pmask = 0;
+       xfer.c_ata_c.r_features = WDSF_SET_MODE;
+       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,
-                                               &ata_c) != ATACMD_COMPLETE)
+                                               &xfer) != ATACMD_COMPLETE)
                return CMD_AGAIN;
-       if (ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
+       if (xfer.c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
                return CMD_ERR;
        }
        return CMD_OK;
@@ -1113,11 +1121,11 @@
        struct ata_queue * const chq = chp->ch_queue;
 
        KASSERT(chq->queue_active < chq->queue_openings);
-       KASSERT((chq->queue_xfers_avail & __BIT(xfer->c_slot)) == 0);
+       KASSERT((chq->active_xfers_used & __BIT(xfer->c_slot)) == 0);
 
        TAILQ_REMOVE(&chq->queue_xfer, xfer, c_xferchain);
        TAILQ_INSERT_TAIL(&chq->active_xfers, xfer, c_activechain);
-
+       chq->active_xfers_used |= __BIT(xfer->c_slot);
        chq->queue_active++;
 }
 
@@ -1127,12 +1135,13 @@
        struct ata_queue * const chq = chp->ch_queue;
 
        KASSERT(chq->queue_active > 0);
-       KASSERT((chq->queue_xfers_avail & __BIT(xfer->c_slot)) == 0);
+       KASSERT((chq->active_xfers_used & __BIT(xfer->c_slot)) != 0);
 
        //if ((xfer->c_flags & C_TIMEOU) == 0)
        callout_stop(&chp->ch_callout);
 
        TAILQ_REMOVE(&chq->active_xfers, xfer, c_activechain);
+       chq->active_xfers_used &= ~__BIT(xfer->c_slot);
        chq->queue_active--;
 }
 
diff -r f4e85c4284d7 -r eec43e71c042 sys/dev/ata/atavar.h
--- a/sys/dev/ata/atavar.h      Sat Apr 15 12:01:23 2017 +0000
+++ b/sys/dev/ata/atavar.h      Sat Apr 15 17:14:11 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: atavar.h,v 1.92.8.3 2017/04/15 12:01:23 jdolecek Exp $ */
+/*     $NetBSD: atavar.h,v 1.92.8.4 2017/04/15 17:14:11 jdolecek Exp $ */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -69,6 +69,64 @@
 };
 
 /*
+ * ATA/ATAPI commands description
+ *
+ * This structure defines the interface between the ATA/ATAPI device driver
+ * and the controller for short commands. It contains the command's parameter,
+ * the length of data to read/write (if any), and a function to call upon
+ * completion.
+ * If no sleep is allowed, the driver can poll for command completion.
+ * Once the command completed, if the error registered is valid, the flag
+ * AT_ERROR is set and the error register value is copied to r_error .
+ * A separate interface is needed for read/write or ATAPI packet commands
+ * (which need multiple interrupts per commands).
+ */
+struct ata_command {
+       /* ATA parameters */
+       uint64_t r_lba;         /* before & after */
+       uint16_t r_count;       /* before & after */
+       union {
+               uint16_t r_features; /* before */
+               uint8_t r_error; /* after */
+       };
+       union {
+               uint8_t r_command; /* before */
+               uint8_t r_status; /* after */
+       };
+       uint8_t r_device;       /* before & after */
+
+       uint8_t r_st_bmask;     /* status register mask to wait for before
+                                  command */
+       uint8_t r_st_pmask;     /* status register mask to wait for after
+                                  command */
+       volatile uint16_t flags;
+
+#define AT_READ     0x0001 /* There is data to read */
+#define AT_WRITE    0x0002 /* There is data to write (excl. with AT_READ) */
+#define AT_WAIT     0x0008 /* wait in controller code for command completion */
+#define AT_POLL     0x0010 /* poll for command completion (no interrupts) */
+#define AT_DONE     0x0020 /* command is done */
+#define AT_XFDONE   0x0040 /* data xfer is done */
+#define AT_ERROR    0x0080 /* command is done with error */
+#define AT_TIMEOU   0x0100 /* command timed out */
+#define AT_DF       0x0200 /* Drive fault */
+#define AT_RESET    0x0400 /* command terminated by channel reset */
+#define AT_GONE     0x0800 /* command terminated because device is gone */
+#define AT_READREG  0x1000 /* Read registers on completion */
+#define AT_LBA      0x2000 /* LBA28 */
+#define AT_LBA48    0x4000 /* LBA48 */
+
+       int timeout;            /* timeout (in ms) */
+       void *data;             /* Data buffer address */
+       int bcount;             /* number of bytes to transfer */
+       void (*callback)(void *); /* command to call once command completed */
+       void *callback_arg;     /* argument passed to *callback() */
+};
+
+/* Forward declaration for ata_xfer */
+struct scsipi_xfer;
+
+/*
  * Description of a command to be handled by an ATA controller.  These
  * commands are queued in a list.
  */
@@ -80,7 +138,6 @@
        uint16_t c_drive;
        int8_t c_slot;                  /* queue slot # */
 
-       void    *c_cmd;                 /* private request structure pointer */
        void    *c_databuf;             /* pointer to data buffer */
        int     c_bcount;               /* byte count left */
        int     c_skip;                 /* bytes already transferred */
@@ -88,9 +145,13 @@
        int     c_lenoff;               /* offset to c_bcount (ATAPI) */
 
        union {
-               struct ata_bio  c_bio;  /* block I/O context */
+               struct ata_bio  c_bio;          /* ATA transfer */
+               struct ata_command c_ata_c;     /* ATA command */ 
+               struct scsipi_xfer *c_scsipi;   /* SCSI transfer */
        } u;
 #define c_bio  u.c_bio
+#define c_ata_c        u.c_ata_c
+#define c_scsipi u.c_scsipi
 
        /* Link on the command queue. */
        TAILQ_ENTRY(ata_xfer) c_xferchain;
@@ -127,6 +188,7 @@
        int queue_openings; /* max number of active transfers */
 #ifdef ATABUS_PRIVATE
        TAILQ_HEAD(, ata_xfer) active_xfers;    /* active commands */
+       uint32_t active_xfers_used;             /* mask of active commands */
        uint32_t queue_xfers_avail;             /* available xfers mask */
        struct ata_xfer queue_xfers[0];         /* xfers */
 #endif
@@ -240,61 +302,6 @@
 #define ATA_CONFIG_UDMA_OFF    8
 
 /*
- * ATA/ATAPI commands description
- *
- * This structure defines the interface between the ATA/ATAPI device driver
- * and the controller for short commands. It contains the command's parameter,
- * the length of data to read/write (if any), and a function to call upon
- * completion.
- * If no sleep is allowed, the driver can poll for command completion.
- * Once the command completed, if the error registered is valid, the flag
- * AT_ERROR is set and the error register value is copied to r_error .
- * A separate interface is needed for read/write or ATAPI packet commands



Home | Main Index | Thread Index | Old Index