From: Tejun Heo <htejun@gmail.com>
To: jeff@garzik.org, linux-ide@vger.kernel.org
Cc: Tejun Heo <htejun@gmail.com>
Subject: [PATCH 4/4] libata: implement ATAPI per-command-type DMA horkages
Date: Wed, 2 Jan 2008 20:12:50 +0900 [thread overview]
Message-ID: <1199272371169-git-send-email-htejun@gmail.com> (raw)
In-Reply-To: <11992723701811-git-send-email-htejun@gmail.com>
ATAPI DMA is filled with mines. Sector aligned READ transfers usually
work but many other commands transfer non-sector aligned or variable
number of bytes, and there are devices and controllers which have
problems dealing with such non-aligned DMA transactions.
This patch implement ATAPI per-command-type DMA horkages and EH logic
to set those quickly. This way, failures localized to certain command
type don't affect other operations (most importantly READs) and
working configuration is found quickly such that the device can be
used.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/libata-core.c | 21 +++++++++++++++++++++
drivers/ata/libata-eh.c | 35 +++++++++++++++++++++++++++++++++++
include/linux/libata.h | 4 ++++
3 files changed, 60 insertions(+), 0 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index d763c07..32dde5b 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4628,6 +4628,27 @@ static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
int ata_check_atapi_dma(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
+ unsigned int horkage = qc->dev->horkage;
+
+ switch (atapi_cmd_type(qc->cdb[0])) {
+ case ATAPI_READ:
+ break;
+
+ case ATAPI_WRITE:
+ if (horkage & ATAPI_DMA_HORKAGE_WRITE)
+ return 1;
+ break;
+
+ case ATAPI_READ_CD:
+ if (horkage & ATAPI_DMA_HORKAGE_READ_CD)
+ return 1;
+ break;
+
+ case ATAPI_MISC:
+ if (horkage & ATAPI_DMA_HORKAGE_MISC)
+ return 1;
+ break;
+ }
/* Don't allow DMA if it isn't multiple of 16 bytes. Quite a
* few ATAPI devices choke on such DMA requests.
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index e93dde1..4399e9e 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1490,6 +1490,38 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
return action;
}
+static void atapi_eh_dma_horkages(struct ata_queued_cmd *qc)
+{
+ struct ata_device *dev = qc->dev;
+ const char *type;
+
+ if (!ata_is_atapi(qc->tf.protocol) || !ata_is_dma(qc->tf.protocol) ||
+ !(qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT)))
+ return;
+
+ switch (atapi_cmd_type(qc->cdb[0])) {
+ case ATAPI_WRITE:
+ type = "WRITE";
+ dev->horkage |= ATAPI_DMA_HORKAGE_WRITE;
+ break;
+ case ATAPI_READ_CD:
+ type = "READ CD [MSF]";
+ dev->horkage |= ATAPI_DMA_HORKAGE_READ_CD;
+ break;
+ case ATAPI_MISC:
+ type = "MISC";
+ dev->horkage |= ATAPI_DMA_HORKAGE_MISC;
+ break;
+ default:
+ return;
+ }
+
+ ata_dev_printk(dev, KERN_WARNING, "ATAPI DMA for %s disabled (0x%x). \n"
+ " If this continues to happen, please report to\n"
+ " linux-ide@vger.kernel.org\n",
+ type, dev->horkage);
+}
+
static int ata_eh_categorize_error(unsigned int eflags, unsigned int err_mask,
int *xfer_ok)
{
@@ -1810,6 +1842,9 @@ static void ata_eh_link_autopsy(struct ata_link *link)
all_err_mask |= qc->err_mask;
if (qc->flags & ATA_QCFLAG_IO)
eflags |= ATA_EFLAG_IS_IO;
+
+ /* handle ATAPI DMA horkages */
+ atapi_eh_dma_horkages(qc);
}
/* enforce default EH actions */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 9fa49e9..1601bbd 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -341,6 +341,10 @@ enum {
ATA_HORKAGE_IVB = (1 << 8), /* cbl det validity bit bugs */
ATA_HORKAGE_STUCK_ERR = (1 << 9), /* stuck ERR on next PACKET */
+ ATAPI_DMA_HORKAGE_WRITE = (1 << 29), /* PIO for WRITEs */
+ ATAPI_DMA_HORKAGE_READ_CD = (1 << 30), /* PIO for READ_CDs */
+ ATAPI_DMA_HORKAGE_MISC = (1 << 31), /* PIO for MISC commands */
+
/* DMA mask for user DMA control: User visible values; DO NOT
renumber */
ATA_DMA_MASK_ATA = (1 << 0), /* DMA on ATA Disk */
--
1.5.2.4
next prev parent reply other threads:[~2008-01-02 11:12 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-02 11:12 [PATCHSET #upstream] libata: improve ATAPI data transfer handling, take #4 Tejun Heo
2008-01-02 11:12 ` [PATCH 1/4] sata_qstor: convert to new data_xfer prototype Tejun Heo
2008-01-02 13:51 ` [PATCH 1/4] pata_pcmcia: " Tejun Heo
2008-01-16 10:24 ` [PATCH 1/4] sata_qstor: " Jeff Garzik
2008-01-02 11:12 ` [PATCH 2/4] libata: update ATAPI overflow draining Tejun Heo
2008-02-01 20:34 ` Jeff Garzik
2008-02-07 0:14 ` Jeff Garzik
2008-01-02 11:12 ` [PATCH 3/4] libata: implement ATAPI drain buffer Tejun Heo
2008-01-10 17:30 ` [RFC 1/2] block: implement drain buffers James Bottomley
2008-01-10 17:42 ` [RFC 2/2] libata: " James Bottomley
2008-01-14 16:01 ` [RFC 1/2] block: " James Bottomley
2008-02-07 0:14 ` [PATCH 3/4] libata: implement ATAPI drain buffer Jeff Garzik
2008-01-02 11:12 ` Tejun Heo [this message]
2008-01-02 13:34 ` [PATCH 4/4] libata: implement ATAPI per-command-type DMA horkages Alan Cox
2008-01-02 13:49 ` Tejun Heo
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=1199272371169-git-send-email-htejun@gmail.com \
--to=htejun@gmail.com \
--cc=jeff@garzik.org \
--cc=linux-ide@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 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).