From: Jens Axboe <axboe@suse.de>
To: Jeff Garzik <jgarzik@pobox.com>
Cc: linux-ide@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: Playing with SATA NCQ
Date: Thu, 26 May 2005 19:07:00 +0200 [thread overview]
Message-ID: <20050526170658.GT1419@suse.de> (raw)
In-Reply-To: <4295F87B.9070106@pobox.com>
On Thu, May 26 2005, Jeff Garzik wrote:
> > static void ahci_qc_prep(struct ata_queued_cmd *qc)
> > {
> > struct ahci_port_priv *pp = qc->ap->private_data;
> >- u32 opts;
> >+ void *port_mmio = (void *) qc->ap->ioaddr.cmd_addr;
> > const u32 cmd_fis_len = 5; /* five dwords */
> >+ dma_addr_t cmd_tbl_dma;
> >+ u32 opts;
> >+ int offset;
> >+
> >+ if (qc->flags & ATA_QCFLAG_NCQ) {
> >+ pp->sactive |= (1 << qc->tag);
> >+
> >+ writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
> >+ readl(port_mmio + PORT_SCR_ACT); /* flush */
> >+ }
>
> Wrong, you should do this in ahci_qc_issue not here.
Are you sure, I moved this on purpose? I think the reason I did this was
the wording at the back of the the sata-ii spec (appendix b) that says
something ala 'preset the active bit and transmit a register FIS'. Feel
free to point me at the authoritative wording in the ACHI spec.
One thing that I definitely think _was_ wrong with the sactive bit
before, is that you set it unconditionally of whether this was an NCQ
command or not. The maxtor drives don't clear sactive on non-fpdma
commands, which confused me at first.
> >+static void ahci_host_ncq_intr_err(struct ata_port *ap)
> >+{
> >+ struct ahci_port_priv *pp = ap->private_data;
> >+ void *mmio = ap->host_set->mmio_base;
> >+ void *port_mmio = ahci_port_base(mmio, ap->port_no);
> >+ unsigned long flags;
> >+ char *buffer;
> >+
> >+ printk(KERN_ERR "ata%u: ncq interrupt error\n", ap->id);
> >+
> >+ /*
> >+ * error all io first
> >+ */
> >+ spin_lock_irqsave(&ap->host_set->lock, flags);
> >+
> >+ while (pp->sactive) {
> >+ struct ata_queued_cmd *qc;
> >+ int tag = ffs(pp->sactive) - 1;
> >+
> >+ pp->sactive &= ~(1 << tag);
> >+ qc = ata_qc_from_tag(ap, tag);
> >+ if (qc)
> >+ ata_qc_complete(qc, ATA_ERR);
>
> else printk error "I couldn't find the tag!"
Agree.
> >@@ -632,18 +767,27 @@
> > status = readl(port_mmio + PORT_IRQ_STAT);
> > writel(status, port_mmio + PORT_IRQ_STAT);
> >
> >- ci = readl(port_mmio + PORT_CMD_ISSUE);
> >- if (likely((ci & 0x1) == 0)) {
> >- if (qc) {
> >- ata_qc_complete(qc, 0);
> >- qc = NULL;
> >+ if (ap->ncq_depth) {
> >+ if (!serr)
>
> incorrect test. serr is not the only error indicator.
Yes, I'm aware of that. There are still quite a few loose ends wrt error
handling, as mentioned. I also don't check the irq fatal stat in the ncq
interrupt handler.
> >@@ -1139,6 +1143,10 @@
> > goto err_out_nosup;
> > }
> >
> >+ if (ap->flags & ATA_FLAG_NCQ)
> >+ if (ata_id_queue_depth(dev->id) > 1)
> >+ dev->flags |= ATA_DFLAG_NCQ;
>
> This will turn on queueing for older TCQ devices that are plugged into
> an NCQ-capable board.
Yup, that is an error. At that time, I could not easily find what
feature bit encompassed NCQ, that needs to be added of course.
> >+int ata_read_log_page(struct ata_port *ap, unsigned int device, char page,
> >+ char *buffer, unsigned int sectors)
> >+{
> >+ struct ata_device *dev = &ap->device[device];
> >+ DECLARE_COMPLETION(wait);
> >+ struct ata_queued_cmd *qc;
> >+ unsigned long flags;
> >+ u8 status;
> >+ int rc;
> >+
> >+ assert(dev->class == ATA_DEV_ATA);
> >+
> >+ ata_dev_select(ap, device, 1, 1);
>
> is this needed? These types of calls need to be removed, in general, as
> they don't make sense on FIS-based hardware at all.
You tell me, this read_log_page() was mainly copy-pasted from the pio
driven function above it. I'll try and kill the select when doing error
testing.
> >+ printk("RLP issue\n");
> >+ spin_lock_irqsave(&ap->host_set->lock, flags);
> >+ rc = ata_qc_issue(qc);
> >+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
> >+ printk("RLP issue done\n");
> >+
> >+ if (rc)
> >+ return -EIO;
> >+
> >+ wait_for_completion(&wait);
> >+
> >+ printk("RLP wait done\n");
> >+
> >+ status = ata_chk_status(ap);
> >+ if (status & (ATA_ERR | ATA_ABORTED))
> >+ return -EIO;
>
> we need to get rid of this too for AHCI-like devices
Can you expand on that?
> >@@ -2753,6 +2830,16 @@
> > struct ata_port *ap = qc->ap;
> > unsigned int tag, do_clear = 0;
> >
> >+ if (likely(qc->flags & ATA_QCFLAG_ACCOUNT)) {
> >+ if (qc->flags & ATA_QCFLAG_NCQ) {
> >+ assert(ap->ncq_depth);
> >+ ap->ncq_depth--;
> >+ } else {
> >+ assert(ap->depth);
> >+ ap->depth--;
> >+ }
> >+ }
>
> why is this accounting conditional?
Because if you free a qc before it has gone to the device, you don't
want to account it. Hmm, perhaps ACTIVE would work fine in fact. I'll
double check!
> > #ifdef CONFIG_PCI
> > EXPORT_SYMBOL_GPL(pci_test_config_bits);
> >Index: drivers/scsi/libata-scsi.c
> >===================================================================
> >--- f5c58b6b0cfd2a92fb3b1d1f4cbfdfb3df6f45d6/drivers/scsi/libata-scsi.c
> >(mode:100644)
> >+++ uncommitted/drivers/scsi/libata-scsi.c (mode:100644)
> >@@ -336,6 +336,7 @@
> > if (sdev->id < ATA_MAX_DEVICES) {
> > struct ata_port *ap;
> > struct ata_device *dev;
> >+ int depth;
> >
> > ap = (struct ata_port *) &sdev->host->hostdata[0];
> > dev = &ap->device[sdev->id];
> >@@ -353,6 +354,13 @@
> > */
> > blk_queue_max_sectors(sdev->request_queue, 2048);
> > }
> >+
> >+ if (dev->flags & ATA_DFLAG_NCQ) {
> >+ int ddepth = ata_id_queue_depth(dev->id) + 1;
> >+
> >+ depth = min(sdev->host->can_queue, ddepth);
> >+ scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
> >depth);
>
> For all hardware that uses SActive (all NCQ), the max is 31 not 32.
That's not true, the max is 32 counting 0 as a valid tag. So 31 is
indeed th max tag value, but 32 is the depth.
> 32 tags == 0xffffffff SActive, which is the same value as that which
> occurs when the hardware is dead/unplugged/etc.
Well you would think you would notice the hardware going dead by other
means than just SActive, right? Seems silly to cap the depth because of
that.
> Also... NCQ does not provide ordered tags. I think MSG_SIMPLE_TAG is
> more appropriate.
Yep indeed, thanks.
> >+ if (ncq)
> >+ qc->flags |= ATA_QCFLAG_NCQ;
> >+
> > if (scsicmd[0] == READ_10 || scsicmd[0] == WRITE_10) {
> >- if (lba48) {
> >+ if (ncq) {
> >+ tf->hob_feature = scsicmd[7];
> >+ tf->feature = scsicmd[8];
> >+ tf->nsect = qc->tag << 3;
> >+ tf->hob_lbal = scsicmd[2];
> >+ qc->nsect = ((unsigned int)scsicmd[7] << 8) |
> >+ scsicmd[8];
> >+ } else if (lba48) {
> > tf->hob_nsect = scsicmd[7];
> > tf->hob_lbal = scsicmd[2];
> >
> >@@ -569,7 +588,8 @@
> > qc->nsect = scsicmd[8];
> > }
> >
> >- tf->nsect = scsicmd[8];
> >+ if (!ncq)
> >+ tf->nsect = scsicmd[8];
>
> the other changes seem fine, but this seem strange
How so? FPDMA has the tag in nsect, others store the bottom 8 bits of
lba.
> >@@ -308,6 +317,11 @@
> > struct ata_queued_cmd qcmd[ATA_MAX_QUEUE];
> > unsigned long qactive;
> > unsigned int active_tag;
> >+ int ncq_depth;
> >+ int depth;
>
> I don't think we need two depths
The two depths were added because we need to differentiate between the
two for issuing new commands. ncq_depth > 0 is fine for issuing a new
FPDMA request, where as non-FPDMA commands need both !ncq_depth and
!depth.
Thanks for your comments!
--
Jens Axboe
next prev parent reply other threads:[~2005-05-26 17:06 UTC|newest]
Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-05-26 14:00 Playing with SATA NCQ Jens Axboe
2005-05-26 16:25 ` Jeff Garzik
2005-05-26 17:07 ` Jens Axboe [this message]
2005-05-26 17:11 ` Jens Axboe
2005-05-26 17:15 ` Jeff Garzik
2005-05-26 17:33 ` Jens Axboe
2005-05-26 19:49 ` Jeff Garzik
2005-05-26 20:30 ` Jens Axboe
2005-05-27 7:20 ` Jens Axboe
2005-05-27 7:29 ` Jeff Garzik
2005-05-27 7:33 ` Jens Axboe
2005-05-27 7:51 ` Jeff Garzik
2005-05-27 8:00 ` Jens Axboe
2005-05-27 8:23 ` Jeff Garzik
2005-05-26 21:50 ` Mark Lord
2005-05-27 6:28 ` Jens Axboe
2005-05-27 6:58 ` Jeff Garzik
2005-05-27 7:15 ` Jens Axboe
2005-05-27 4:41 ` Jeff Garzik
2005-05-27 6:39 ` Jens Axboe
2005-05-27 21:40 ` Michael Thonke
2005-05-27 22:16 ` Jeff Garzik
2005-05-27 22:30 ` Michael Thonke
2005-05-28 12:12 ` Jens Axboe
2005-05-29 13:01 ` Michael Thonke
2005-05-29 14:09 ` Mark Lord
2005-05-29 14:24 ` Tyler
2005-05-29 15:22 ` Eric D. Mudama
2005-05-29 19:04 ` Jens Axboe
2005-05-29 19:05 ` Jeff Garzik
2005-05-29 19:21 ` Jens Axboe
2005-05-29 19:03 ` Jens Axboe
2005-05-29 20:12 ` Michael Thonke
2005-05-29 20:17 ` Jeff Garzik
2005-05-30 6:05 ` Jens Axboe
2005-05-30 6:07 ` Jens Axboe
2005-05-29 18:10 ` Michael Thonke
2005-05-29 19:06 ` Jens Axboe
2005-05-29 16:03 ` Erik Slagter
2005-05-29 16:34 ` Jeff Garzik
2005-05-29 16:50 ` Erik Slagter
2005-05-29 16:59 ` Jeff Garzik
2005-05-29 17:23 ` Erik Slagter
2005-05-29 17:29 ` Jeff Garzik
2005-05-29 17:45 ` Erik Slagter
2005-05-29 18:01 ` Jeff Garzik
2005-05-29 18:10 ` Erik Slagter
2005-05-29 18:14 ` Jeff Garzik
2005-05-29 18:27 ` Michael Thonke
2005-05-29 18:31 ` Jeff Garzik
2005-05-29 16:57 ` Michael Thonke
2005-05-29 17:26 ` Erik Slagter
2005-05-30 0:06 ` Mark Lord
2005-05-30 7:29 ` Erik Slagter
2005-05-30 18:09 ` Mark Lord
2005-05-30 18:22 ` Erik Slagter
2005-05-30 18:25 ` Mark Lord
2005-05-30 18:34 ` Michael Thonke
2005-05-30 18:51 ` Jeff Garzik
2005-05-30 18:48 ` Jeff Garzik
2005-05-30 18:50 ` Jeff Garzik
2005-05-30 20:03 ` Erik Slagter
2005-05-30 20:19 ` Jeff Garzik
2005-05-31 7:44 ` Erik Slagter
2005-05-30 23:14 ` Mark Lord
2005-05-31 7:48 ` Erik Slagter
2005-05-31 8:05 ` Patrick McFarland
2005-05-29 21:49 ` Michael Thonke
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=20050526170658.GT1419@suse.de \
--to=axboe@suse.de \
--cc=jgarzik@pobox.com \
--cc=linux-ide@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.