Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci do not share queue between the non-indepedant ch...



details:   https://anonhg.NetBSD.org/src/rev/72b267aa9e0e
branches:  trunk
changeset: 827259:72b267aa9e0e
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Sun Oct 22 13:13:55 2017 +0000

description:
do not share queue between the non-indepedant channels; instead make
sure only one of the channels is ever active on the same controller

fixes PR kern/52606 by Martin Husemann, thanks for report and testing

diffstat:

 sys/dev/pci/cmdide.c    |  56 ++++++++++++++++++++++++++++++++++++++++++------
 sys/dev/pci/pciidevar.h |   5 +++-
 2 files changed, 53 insertions(+), 8 deletions(-)

diffs (120 lines):

diff -r 5d507e4a4e46 -r 72b267aa9e0e sys/dev/pci/cmdide.c
--- a/sys/dev/pci/cmdide.c      Sun Oct 22 11:17:39 2017 +0000
+++ b/sys/dev/pci/cmdide.c      Sun Oct 22 13:13:55 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cmdide.c,v 1.42 2017/10/20 21:51:29 jdolecek Exp $     */
+/*     $NetBSD: cmdide.c,v 1.43 2017/10/22 13:13:55 jdolecek Exp $     */
 
 /*
  * Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
@@ -25,10 +25,11 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cmdide.c,v 1.42 2017/10/20 21:51:29 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cmdide.c,v 1.43 2017/10/22 13:13:55 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/atomic.h>
 
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcidevs.h>
@@ -36,6 +37,7 @@
 #include <dev/pci/pciidevar.h>
 #include <dev/pci/pciide_cmd_reg.h>
 
+#define CMDIDE_ACT_CHANNEL_NONE        0xff
 
 static int  cmdide_match(device_t, cfdata_t, void *);
 static void cmdide_attach(device_t, device_t, void *);
@@ -49,6 +51,8 @@
 static void cmd0643_9_setup_channel(struct ata_channel*);
 static void cmd_channel_map(const struct pci_attach_args *,
                            struct pciide_softc *, int);
+static int cmd064x_claim_hw(struct ata_channel *, int);
+static void cmd064x_free_hw(struct ata_channel *);
 static int  cmd_pci_intr(void *);
 static void cmd646_9_irqack(struct ata_channel *);
 static void cmd680_chip_map(struct pciide_softc*,
@@ -151,11 +155,10 @@
        cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac;
 
        if (channel > 0 && one_channel) {
-               cp->ata_channel.ch_queue =
-                   sc->pciide_channels[0].ata_channel.ch_queue;
-       } else {
-               /* XXX */
-               cp->ata_channel.ch_queue = ata_queue_alloc(1);
+               /* Channels are not independant, need synchronization */
+               sc->sc_wdcdev.sc_atac.atac_claim_hw = cmd064x_claim_hw;
+               sc->sc_wdcdev.sc_atac.atac_free_hw  = cmd064x_free_hw;
+               sc->sc_cmd_act_channel = CMDIDE_ACT_CHANNEL_NONE;
        }
 
        aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev,
@@ -181,6 +184,45 @@
        pciide_mapchan(pa, cp, interface, cmd_pci_intr);
 }
 
+/*
+ * Check if we can execute next xfer on the channel.
+ * Called with chp channel lock held.
+ */
+static int
+cmd064x_claim_hw(struct ata_channel *chp, int maysleep)
+{
+       struct pciide_softc *sc = CHAN_TO_PCIIDE(chp);
+
+       return atomic_cas_uint(&sc->sc_cmd_act_channel,
+           CMDIDE_ACT_CHANNEL_NONE, chp->ch_channel)
+           == CMDIDE_ACT_CHANNEL_NONE;
+}
+
+/* Allow another channel to run. Called with ochp channel lock held. */
+static void
+cmd064x_free_hw(struct ata_channel *ochp)
+{
+       struct pciide_softc *sc = CHAN_TO_PCIIDE(ochp);
+       uint oact = atomic_cas_uint(&sc->sc_cmd_act_channel,
+           ochp->ch_channel, CMDIDE_ACT_CHANNEL_NONE);
+       struct ata_channel *nchp;
+
+       KASSERT(oact == ochp->ch_channel);
+
+       /* Start the other channel(s) */
+       for(uint i = 0; i < sc->sc_wdcdev.sc_atac.atac_nchannels; i++) {
+               /* Skip the current channel */
+               if (i == oact)
+                       continue;
+
+               nchp = &sc->pciide_channels[i].ata_channel;
+               if (nchp->ch_ndrives == 0)
+                       continue;
+
+               atastart(nchp);
+       }
+}
+
 static int
 cmd_pci_intr(void *arg)
 {
diff -r 5d507e4a4e46 -r 72b267aa9e0e sys/dev/pci/pciidevar.h
--- a/sys/dev/pci/pciidevar.h   Sun Oct 22 11:17:39 2017 +0000
+++ b/sys/dev/pci/pciidevar.h   Sun Oct 22 13:13:55 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pciidevar.h,v 1.48 2017/10/19 20:11:38 jdolecek Exp $  */
+/*     $NetBSD: pciidevar.h,v 1.49 2017/10/22 13:13:55 jdolecek Exp $  */
 
 /*
  * Copyright (c) 1998 Christopher G. Demetriou.  All rights reserved.
@@ -122,6 +122,9 @@
        int sc_ba5_en;
 #endif /* NATA_DMA */
 
+       /* for CMD Technology 064x */
+       uint sc_cmd_act_channel;
+
        /* Vendor info (for interpreting Chip description) */
        pcireg_t sc_pci_id;
        /* Chip description */



Home | Main Index | Thread Index | Old Index