From: Mikulas Patocka <mpatocka@redhat.com>
To: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Mikael Pettersson <mikpe@it.uu.se>,
"David S. Miller" <davem@davemloft.net>,
linux-ide@vger.kernel.org
Subject: Re: [PATCH] Serialize CMD643 and CMD646 to fix a hardware bug with SSD
Date: Tue, 27 Oct 2009 21:10:48 -0400 (EDT) [thread overview]
Message-ID: <Pine.LNX.4.64.0910272109370.24376@hs20-bc2-1.build.redhat.com> (raw)
In-Reply-To: <20091027113427.5998c4be@lxorguk.ukuu.org.uk>
With every transfer, the pastchcauses this:
------------[ cut here ]------------
WARNING: at drivers/ata/pata_cmd64x.c:276 cmd64x_bmdma_stop+0x48/0x60()
Modules linked in: nbd sunhme openpromfs sermouse unix
Call Trace:
[00000000005cab68] cmd64x_bmdma_stop+0x48/0x60
[00000000005c99b8] ata_sff_host_intr+0x158/0x1e0
[00000000005cb2f8] cmd64x_interrupt+0x178/0x1a0
[000000000048354c] handle_IRQ_event+0x6c/0x140
[0000000000485380] handle_fasteoi_irq+0x80/0x140
[000000000042a660] handler_irq+0xc0/0x100
[00000000004208b4] tl0_irq5+0x14/0x20
[00000000005ec08c] skb_copy_datagram_iovec+0x1ec/0x220
[0000000010000800] unix_dgram_recvmsg+0xc0/0x300 [unix]
[00000000005e0ca8] sock_recvmsg+0x88/0xc0
[00000000005e1f50] SyS_recvfrom+0x70/0xe0
[0000000000406114] linux_sparc_syscall32+0x34/0x40
---[ end trace 62aae040ef69a03d ]---
Mikulas
On Tue, 27 Oct 2009, Alan Cox wrote:
> > (ata1 is the primary channel)
> > --- I'm wondering, what does it mean? status 0x50 is OK. DMA status 0x24
> > is also OK. What was the problem there?
>
> Beats me still. Thanks to Daniela for the info about the chip contention
> I've got some bits that can be tried, but I don't actually have a 646 to
> check this.
>
> It should do the neccessary serializing and IRQ bit checks to avoid
> hitting the case described in the app note.
>
> cmd64x: implement serialization as per notes
>
> From: Alan Cox <alan@linux.intel.com>
>
> Daniela Engert pointed out that there are some implementation notes for the
> 643 and 646 that deal with certain serialization rules. In theory we don't
> need them because they apply when the motherboard decides not to retry PCI
> requests for long enough and the chip is busy doing a DMA transfer on the
> other channel.
>
> The rule basically is "don't touch the taskfile of the other channel while
> a DMA is in progress". To implement that we need to
>
> - not issue a command on a channel when there is a DMA command queued
> - not issue a DMA command on a channel when there are PIO commands queued
> - use the alternative access to the interrupt source so that we do not
> touch altstatus or status on shared IRQ.
>
> Signed-off-by: Alan Cox <alan@linux.intel.com>
> ---
>
> drivers/ata/pata_cmd64x.c | 132 ++++++++++++++++++++++++++++++++++++++++++---
> 1 files changed, 124 insertions(+), 8 deletions(-)
>
>
> diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
> index f98dffe..64917ac 100644
> --- a/drivers/ata/pata_cmd64x.c
> +++ b/drivers/ata/pata_cmd64x.c
> @@ -31,7 +31,7 @@
> #include <linux/libata.h>
>
> #define DRV_NAME "pata_cmd64x"
> -#define DRV_VERSION "0.2.5"
> +#define DRV_VERSION "0.3.1"
>
> /*
> * CMD64x specific registers definition.
> @@ -75,6 +75,13 @@ enum {
> DTPR1 = 0x7C
> };
>
> +struct cmd_priv
> +{
> + int dma_live; /* Channel using DMA */
> + int irq_t[2]; /* Register to check for IRQ */
> + int irq_m[2]; /* Bit to check */
> +};
> +
> static int cmd648_cable_detect(struct ata_port *ap)
> {
> struct pci_dev *pdev = to_pci_dev(ap->host->dev);
> @@ -254,17 +261,107 @@ static void cmd648_bmdma_stop(struct ata_queued_cmd *qc)
> }
>
> /**
> - * cmd646r1_dma_stop - DMA stop callback
> + * cmd64x_bmdma_stop - DMA stop callback
> * @qc: Command in progress
> *
> - * Stub for now while investigating the r1 quirk in the old driver.
> + * Track the completion of live DMA commands and clear the dma_live
> + * tracking flag as we do.
> */
>
> -static void cmd646r1_bmdma_stop(struct ata_queued_cmd *qc)
> +static void cmd64x_bmdma_stop(struct ata_queued_cmd *qc)
> {
> + struct ata_port *ap = qc->ap;
> + struct cmd_priv *priv = ap->host->private_data;
> ata_bmdma_stop(qc);
> + WARN_ON(priv->dma_live != ap->port_no );
> + priv->dma_live = -1;
> +}
> +
> +/**
> + * cmd64x_qc_defer - Defer logic for chip limits
> + * @qc: queued command
> + *
> + * Decide whether we can issue the command. Called under the host lock.
> + */
> +
> +static int cmd64x_qc_defer(struct ata_queued_cmd *qc)
> +{
> + struct ata_host *host = qc->ap->host;
> + struct cmd_priv *priv = host->private_data;
> + struct ata_port *alt = host->ports[1 ^ qc->ap->port_no];
> + int rc;
> +
> + /* Apply the ATA rules first */
> + rc = ata_std_qc_defer(qc);
> + if (rc)
> + return rc;
> +
> + /* If the other port is not live then issue the command */
> + if (alt == NULL || !alt->qc_active)
> + return 0;
> + /* If there is a live DMA command then wait */
> + if (priv->dma_live != -1)
> + return ATA_DEFER_PORT;
> + if (qc->tf.protocol == ATAPI_PROT_DMA ||
> + qc->tf.protocol == ATA_PROT_DMA) {
> + /* Cannot overlap our DMA command */
> + if (alt->qc_active)
> + return ATA_DEFER_PORT;
> + /* Claim the DMA */
> + priv->dma_live = qc->ap->port_no;
> + }
> + return 0;
> }
>
> +/**
> + * cmd64x_interrupt - ATA host interrupt handler
> + * @irq: irq line (unused)
> + * @dev_instance: pointer to our ata_host information structure
> + *
> + * Our interrupt handler for PCI IDE devices. Calls
> + * ata_sff_host_intr() for each port that is flagging an IRQ. We cannot
> + * use the defaults as we need to avoid touching status/altstatus during
> + * a DMA.
> + *
> + * LOCKING:
> + * Obtains host lock during operation.
> + *
> + * RETURNS:
> + * IRQ_NONE or IRQ_HANDLED.
> + */
> +irqreturn_t cmd64x_interrupt(int irq, void *dev_instance)
> +{
> + struct ata_host *host = dev_instance;
> + struct pci_dev *pdev = to_pci_dev(host->dev);
> + struct cmd_priv *priv = host->private_data;
> + unsigned int i;
> + unsigned int handled = 0;
> + unsigned long flags;
> +
> + /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
> + spin_lock_irqsave(&host->lock, flags);
> +
> + for (i = 0; i < host->n_ports; i++) {
> + struct ata_port *ap;
> + u8 reg;
> +
> + pci_read_config_byte(pdev, priv->irq_t[i], ®);
> + ap = host->ports[i];
> + if (ap && (reg & priv->irq_m[i]) &&
> + !(ap->flags & ATA_FLAG_DISABLED)) {
> + struct ata_queued_cmd *qc;
> +
> + qc = ata_qc_from_tag(ap, ap->link.active_tag);
> + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
> + (qc->flags & ATA_QCFLAG_ACTIVE))
> + handled |= ata_sff_host_intr(ap, qc);
> + }
> + }
> +
> + spin_unlock_irqrestore(&host->lock, flags);
> +
> + return IRQ_RETVAL(handled);
> +}
> static struct scsi_host_template cmd64x_sht = {
> ATA_BMDMA_SHT(DRV_NAME),
> };
> @@ -273,6 +370,8 @@ static const struct ata_port_operations cmd64x_base_ops = {
> .inherits = &ata_bmdma_port_ops,
> .set_piomode = cmd64x_set_piomode,
> .set_dmamode = cmd64x_set_dmamode,
> + .bmdma_stop = cmd64x_bmdma_stop,
> + .qc_defer = cmd64x_qc_defer,
> };
>
> static struct ata_port_operations cmd64x_port_ops = {
> @@ -282,7 +381,6 @@ static struct ata_port_operations cmd64x_port_ops = {
>
> static struct ata_port_operations cmd646r1_port_ops = {
> .inherits = &cmd64x_base_ops,
> - .bmdma_stop = cmd646r1_bmdma_stop,
> .cable_detect = ata_cable_40wire,
> };
>
> @@ -290,6 +388,7 @@ static struct ata_port_operations cmd648_port_ops = {
> .inherits = &cmd64x_base_ops,
> .bmdma_stop = cmd648_bmdma_stop,
> .cable_detect = cmd648_cable_detect,
> + .qc_defer = ata_std_qc_defer
> };
>
> static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
> @@ -340,6 +439,8 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
> const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL };
> u8 mrdmode;
> int rc;
> + struct ata_host *host;
> + struct cmd_priv *cpriv;
>
> rc = pcim_enable_device(pdev);
> if (rc)
> @@ -348,6 +449,17 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
> pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
> class_rev &= 0xFF;
>
> + cpriv = devm_kzalloc(&pdev->dev, sizeof(*cpriv), GFP_KERNEL);
> + if (cpriv == NULL)
> + return -ENOMEM;
> + cpriv->dma_live = -1;
> +
> + /* Table for IRQ checking */
> + cpriv->irq_t[0] = CFR;
> + cpriv->irq_m[0] = 1 << 2;
> + cpriv->irq_t[1] = ARTTIM23;
> + cpriv->irq_m[1] = 1 << 4;
> +
> if (id->driver_data == 0) /* 643 */
> ata_pci_bmdma_clear_simplex(pdev);
>
> @@ -360,20 +472,24 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
> ppi[0] = &cmd_info[3];
> }
>
> +
> pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
> pci_read_config_byte(pdev, MRDMODE, &mrdmode);
> mrdmode &= ~ 0x30; /* IRQ set up */
> mrdmode |= 0x02; /* Memory read line enable */
> pci_write_config_byte(pdev, MRDMODE, mrdmode);
>
> - /* Force PIO 0 here.. */
> -
> /* PPC specific fixup copied from old driver */
> #ifdef CONFIG_PPC
> pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
> #endif
> + rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
> + if (rc)
> + return rc;
> + host->private_data = cpriv;
>
> - return ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL);
> + pci_set_master(pdev);
> + return ata_pci_sff_activate_host(host, cmd64x_interrupt, &cmd64x_sht);
> }
>
> #ifdef CONFIG_PM
>
next prev parent reply other threads:[~2009-10-28 1:10 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-10-21 18:55 [PATCH] Serialize CMD643 and CMD646 to fix a hardware bug with SSD Mikulas Patocka
2009-10-21 19:34 ` Mikael Pettersson
2009-10-21 23:01 ` Mikulas Patocka
2009-10-27 11:34 ` Alan Cox
2009-10-28 1:10 ` Mikulas Patocka [this message]
2009-10-21 19:39 ` Bartlomiej Zolnierkiewicz
2009-10-22 0:41 ` David Miller
2009-10-22 9:44 ` Bartlomiej Zolnierkiewicz
2009-10-22 11:00 ` David Miller
2009-10-22 11:15 ` Bartlomiej Zolnierkiewicz
2009-10-22 11:20 ` David Miller
2009-10-23 14:29 ` Mikulas Patocka
2009-10-23 14:31 ` David Miller
2009-10-23 14:44 ` Bartlomiej Zolnierkiewicz
2009-10-23 14:55 ` Mikulas Patocka
2009-10-23 15:03 ` Bartlomiej Zolnierkiewicz
2009-10-23 15:18 ` Daniela Engert
2009-10-23 16:51 ` Alan Cox
2009-10-23 17:27 ` Sergei Shtylyov
2009-10-23 18:22 ` Alan Cox
2009-10-23 18:52 ` Bartlomiej Zolnierkiewicz
2009-10-24 3:24 ` David Miller
2009-10-24 12:38 ` Bartlomiej Zolnierkiewicz
2009-10-24 12:58 ` David Miller
2009-10-24 13:13 ` Bartlomiej Zolnierkiewicz
2009-10-24 13:20 ` David Miller
2009-10-26 11:36 ` Mikulas Patocka
2009-10-26 12:18 ` Alan Cox
2009-11-05 1:25 ` [PATCH] Don't use UDMA on VIA UDMA33 controller with Transcend SSD Mikulas Patocka
2009-11-05 10:40 ` Alan Cox
2009-11-05 22:18 ` Mikulas Patocka
2009-11-05 22:46 ` Alan Cox
2009-11-05 23:19 ` Mikulas Patocka
2009-11-17 12:30 ` David Miller
2009-11-18 17:09 ` Mikulas Patocka
2009-11-18 17:22 ` Alan Cox
2009-11-18 17:32 ` David Miller
2009-11-18 17:46 ` Mikulas Patocka
2009-11-18 17:53 ` David Miller
2009-11-18 18:04 ` Mikulas Patocka
2009-11-18 17:37 ` Mikulas Patocka
2009-11-18 17:50 ` Alan Cox
2009-11-18 18:02 ` Mikulas Patocka
2011-10-11 17:12 ` Bartlomiej Zolnierkiewicz
2011-10-11 19:05 ` David Miller
2011-10-11 19:39 ` Alan Cox
2011-10-12 14:38 ` Bartlomiej Zolnierkiewicz
2011-10-12 17:59 ` Alan Cox
2011-10-13 10:35 ` Bartlomiej Zolnierkiewicz
2010-01-14 15:49 ` Bartlomiej Zolnierkiewicz
2010-01-14 19:24 ` Alan Cox
2010-01-14 20:17 ` Bartlomiej Zolnierkiewicz
2009-10-23 17:15 ` [PATCH] Serialize CMD643 and CMD646 to fix a hardware bug with SSD Alan Cox
2009-10-22 13:56 ` Alan Cox
2009-10-23 1:30 ` David Miller
2009-10-23 14:50 ` Mikulas Patocka
2009-10-23 20:50 ` Sergei Shtylyov
2009-10-26 11:30 ` Mikulas Patocka
2009-10-26 18:20 ` Sergei Shtylyov
2009-10-24 11:28 ` Frans Pop
2009-10-24 11:31 ` David Miller
2009-10-25 2:48 ` Frans Pop
2009-10-29 10:02 ` David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.64.0910272109370.24376@hs20-bc2-1.build.redhat.com \
--to=mpatocka@redhat.com \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=davem@davemloft.net \
--cc=linux-ide@vger.kernel.org \
--cc=mikpe@it.uu.se \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).