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