Module Name:    src
Committed By:   jdolecek
Date:           Sun Oct 22 13:13:55 UTC 2017

Modified Files:
        src/sys/dev/pci: cmdide.c pciidevar.h

Log Message:
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


To generate a diff of this commit:
cvs rdiff -u -r1.42 -r1.43 src/sys/dev/pci/cmdide.c
cvs rdiff -u -r1.48 -r1.49 src/sys/dev/pci/pciidevar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/cmdide.c
diff -u src/sys/dev/pci/cmdide.c:1.42 src/sys/dev/pci/cmdide.c:1.43
--- src/sys/dev/pci/cmdide.c:1.42	Fri Oct 20 21:51:29 2017
+++ src/sys/dev/pci/cmdide.c	Sun Oct 22 13:13:55 2017
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: cmdide.c,v 1
 #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_chip_map(struct pc
 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 @@ cmd_channel_map(const struct pci_attach_
 	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 @@ cmd_channel_map(const struct pci_attach_
 	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)
 {

Index: src/sys/dev/pci/pciidevar.h
diff -u src/sys/dev/pci/pciidevar.h:1.48 src/sys/dev/pci/pciidevar.h:1.49
--- src/sys/dev/pci/pciidevar.h:1.48	Thu Oct 19 20:11:38 2017
+++ src/sys/dev/pci/pciidevar.h	Sun Oct 22 13:13:55 2017
@@ -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 @@ struct pciide_softc {
 	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 */

Reply via email to