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 */