From: Tejun Heo <htejun@gmail.com>
To: jeff@garzik.org, alan@lxorguk.ukuu.org.uk, linux-ide@vger.kernel.org
Cc: Tejun Heo <htejun@gmail.com>
Subject: [PATCH 03/10] libata-pmp: hook PMP support and enable it
Date: Sun, 23 Sep 2007 13:19:54 +0900 [thread overview]
Message-ID: <11905211941742-git-send-email-htejun@gmail.com> (raw)
In-Reply-To: <1190521193410-git-send-email-htejun@gmail.com>
Hook PMP support into libata and enable it. Connect SCR and probing
functions, and update ata_dev_classify() to detect PMP.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/libata-core.c | 113 ++++++++++++++++++++++++++++++++-------------
drivers/ata/libata-eh.c | 18 ++++++-
2 files changed, 96 insertions(+), 35 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 23441e1..3b46678 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -59,7 +59,7 @@
#include "libata.h"
-#define DRV_VERSION "2.21" /* must be exactly four chars */
+#define DRV_VERSION "3.00" /* must be exactly four chars */
/* debounce timing parameters in msecs { interval, duration, timeout } */
@@ -672,29 +672,49 @@ static unsigned int ata_devchk(struct ata_port *ap, unsigned int device)
* None.
*
* RETURNS:
- * Device type, %ATA_DEV_ATA, %ATA_DEV_ATAPI, or %ATA_DEV_UNKNOWN
- * the event of failure.
+ * Device type, %ATA_DEV_ATA, %ATA_DEV_ATAPI, %ATA_DEV_PMP or
+ * %ATA_DEV_UNKNOWN the event of failure.
*/
-
unsigned int ata_dev_classify(const struct ata_taskfile *tf)
{
/* Apple's open source Darwin code hints that some devices only
* put a proper signature into the LBA mid/high registers,
* So, we only check those. It's sufficient for uniqueness.
+ *
+ * ATA/ATAPI-7 (d1532v1r1: Feb. 19, 2003) specified separate
+ * signatures for ATA and ATAPI devices attached on SerialATA,
+ * 0x3c/0xc3 and 0x69/0x96 respectively. However, SerialATA
+ * spec has never mentioned about using different signatures
+ * for ATA/ATAPI devices. Then, Serial ATA II: Port
+ * Multiplier specification began to use 0x69/0x96 to identify
+ * port multpliers and 0x3c/0xc3 to identify SEMB device.
+ * ATA/ATAPI-7 dropped descriptions about 0x3c/0xc3 and
+ * 0x69/0x96 shortly and described them as reserved for
+ * SerialATA.
+ *
+ * We follow the current spec and consider that 0x69/0x96
+ * identifies a port multiplier and 0x3c/0xc3 a SEMB device.
*/
-
- if (((tf->lbam == 0) && (tf->lbah == 0)) ||
- ((tf->lbam == 0x3c) && (tf->lbah == 0xc3))) {
+ if ((tf->lbam == 0) && (tf->lbah == 0)) {
DPRINTK("found ATA device by sig\n");
return ATA_DEV_ATA;
}
- if (((tf->lbam == 0x14) && (tf->lbah == 0xeb)) ||
- ((tf->lbam == 0x69) && (tf->lbah == 0x96))) {
+ if ((tf->lbam == 0x14) && (tf->lbah == 0xeb)) {
DPRINTK("found ATAPI device by sig\n");
return ATA_DEV_ATAPI;
}
+ if ((tf->lbam == 0x69) && (tf->lbah == 0x96)) {
+ DPRINTK("found PMP device by sig\n");
+ return ATA_DEV_PMP;
+ }
+
+ if ((tf->lbam == 0x3c) && (tf->lbah == 0xc3)) {
+ printk("ata: SEMB device ignored\n");
+ return ATA_DEV_SEMB_UNSUP; /* not yet */
+ }
+
DPRINTK("unknown device\n");
return ATA_DEV_UNKNOWN;
}
@@ -3424,6 +3444,12 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
(link->flags & ATA_LFLAG_HRST_TO_RESUME))
ehc->i.action |= ATA_EH_HARDRESET;
+ /* Some PMPs don't work with only SRST, force hardreset if PMP
+ * is supported.
+ */
+ if (ap->flags & ATA_FLAG_PMP)
+ ehc->i.action |= ATA_EH_HARDRESET;
+
/* if we're about to do hardreset, nothing more to do */
if (ehc->i.action & ATA_EH_HARDRESET)
return 0;
@@ -3614,6 +3640,16 @@ int sata_std_hardreset(struct ata_link *link, unsigned int *class,
/* wait a while before checking status, see SRST for more info */
msleep(150);
+ /* If PMP is supported, we have to do follow-up SRST. Note
+ * that some PMPs don't send D2H Reg FIS after hardreset at
+ * all if the first port is empty. Wait for it just for a
+ * second and request follow-up SRST.
+ */
+ if (ap->flags & ATA_FLAG_PMP) {
+ ata_wait_ready(ap, jiffies + HZ);
+ return -EAGAIN;
+ }
+
rc = ata_wait_ready(ap, deadline);
/* link occupied, -ENODEV too is an error */
if (rc) {
@@ -5957,22 +5993,26 @@ int sata_scr_valid(struct ata_link *link)
* @val: Place to store read value
*
* Read SCR register @reg of @link into *@val. This function is
- * guaranteed to succeed if the cable type of the port is SATA
- * and the port implements ->scr_read.
+ * guaranteed to succeed if @link is ap->link, the cable type of
+ * the port is SATA and the port implements ->scr_read.
*
* LOCKING:
- * None.
+ * None if @link is ap->link. Kernel thread context otherwise.
*
* RETURNS:
* 0 on success, negative errno on failure.
*/
int sata_scr_read(struct ata_link *link, int reg, u32 *val)
{
- struct ata_port *ap = link->ap;
+ if (ata_is_host_link(link)) {
+ struct ata_port *ap = link->ap;
- if (sata_scr_valid(link))
- return ap->ops->scr_read(ap, reg, val);
- return -EOPNOTSUPP;
+ if (sata_scr_valid(link))
+ return ap->ops->scr_read(ap, reg, val);
+ return -EOPNOTSUPP;
+ }
+
+ return sata_pmp_scr_read(link, reg, val);
}
/**
@@ -5982,22 +6022,26 @@ int sata_scr_read(struct ata_link *link, int reg, u32 *val)
* @val: value to write
*
* Write @val to SCR register @reg of @link. This function is
- * guaranteed to succeed if the cable type of the port is SATA
- * and the port implements ->scr_read.
+ * guaranteed to succeed if @link is ap->link, the cable type of
+ * the port is SATA and the port implements ->scr_read.
*
* LOCKING:
- * None.
+ * None if @link is ap->link. Kernel thread context otherwise.
*
* RETURNS:
* 0 on success, negative errno on failure.
*/
int sata_scr_write(struct ata_link *link, int reg, u32 val)
{
- struct ata_port *ap = link->ap;
+ if (ata_is_host_link(link)) {
+ struct ata_port *ap = link->ap;
- if (sata_scr_valid(link))
- return ap->ops->scr_write(ap, reg, val);
- return -EOPNOTSUPP;
+ if (sata_scr_valid(link))
+ return ap->ops->scr_write(ap, reg, val);
+ return -EOPNOTSUPP;
+ }
+
+ return sata_pmp_scr_write(link, reg, val);
}
/**
@@ -6010,23 +6054,27 @@ int sata_scr_write(struct ata_link *link, int reg, u32 val)
* function performs flush after writing to the register.
*
* LOCKING:
- * None.
+ * None if @link is ap->link. Kernel thread context otherwise.
*
* RETURNS:
* 0 on success, negative errno on failure.
*/
int sata_scr_write_flush(struct ata_link *link, int reg, u32 val)
{
- struct ata_port *ap = link->ap;
- int rc;
+ if (ata_is_host_link(link)) {
+ struct ata_port *ap = link->ap;
+ int rc;
- if (sata_scr_valid(link)) {
- rc = ap->ops->scr_write(ap, reg, val);
- if (rc == 0)
- rc = ap->ops->scr_read(ap, reg, &val);
- return rc;
+ if (sata_scr_valid(link)) {
+ rc = ap->ops->scr_write(ap, reg, val);
+ if (rc == 0)
+ rc = ap->ops->scr_read(ap, reg, &val);
+ return rc;
+ }
+ return -EOPNOTSUPP;
}
- return -EOPNOTSUPP;
+
+ return sata_pmp_scr_write(link, reg, val);
}
/**
@@ -6415,6 +6463,7 @@ static void ata_host_release(struct device *gendev, void *res)
if (ap->scsi_host)
scsi_host_put(ap->scsi_host);
+ kfree(ap->pmp_link);
kfree(ap);
host->ports[i] = NULL;
}
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 687419b..5f2c0f3 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2209,6 +2209,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
readid_flags |= ATA_READID_POSTRESET;
if ((action & ATA_EH_REVALIDATE) && ata_dev_enabled(dev)) {
+ WARN_ON(dev->class == ATA_DEV_PMP);
+
if (ata_link_offline(link)) {
rc = -EIO;
goto err;
@@ -2234,8 +2236,11 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
ata_class_enabled(ehc->classes[dev->devno])) {
dev->class = ehc->classes[dev->devno];
- rc = ata_dev_read_id(dev, &dev->class, readid_flags,
- dev->id);
+ if (dev->class == ATA_DEV_PMP)
+ rc = sata_pmp_attach(dev);
+ else
+ rc = ata_dev_read_id(dev, &dev->class,
+ readid_flags, dev->id);
switch (rc) {
case 0:
new_mask |= 1 << dev->devno;
@@ -2264,7 +2269,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
* device detection messages backwards.
*/
ata_link_for_each_dev(dev, link) {
- if (!(new_mask & (1 << dev->devno)))
+ if (!(new_mask & (1 << dev->devno)) ||
+ dev->class == ATA_DEV_PMP)
continue;
ehc->i.flags |= ATA_EHI_PRINTINFO;
@@ -2521,6 +2527,12 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
if (rc)
goto dev_fail;
+ /* if PMP got attached, return, pmp EH will take care of it */
+ if (link->device->class == ATA_DEV_PMP) {
+ ehc->i.action = 0;
+ return 0;
+ }
+
/* configure transfer mode if necessary */
if (ehc->i.flags & ATA_EHI_SETMODE) {
rc = ata_set_mode(link, &dev);
--
1.5.0.3
next prev parent reply other threads:[~2007-09-23 4:20 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-23 4:19 [PATCHSET 2/2] implement PMP support, take 6 Tejun Heo
2007-09-23 4:19 ` [PATCH 01/10] libata-pmp: update ata_eh_reset() for PMP Tejun Heo
2007-09-23 4:19 ` [PATCH 02/10] libata-pmp: implement Port Multiplier support Tejun Heo
2007-09-23 4:19 ` [PATCH 04/10] libata-pmp: extend ACPI support to cover PMP Tejun Heo
2007-09-23 4:19 ` [PATCH 06/10] sata_sil24: implement PMP support Tejun Heo
2007-09-23 4:19 ` [PATCH 05/10] libata-pmp: implement qc_defer for command switching " Tejun Heo
2007-09-23 4:19 ` Tejun Heo [this message]
2007-09-23 4:19 ` [PATCH 08/10] ahci: implement " Tejun Heo
2007-09-23 4:19 ` [PATCH 07/10] sata_sil24: implement PORT_RST Tejun Heo
2007-09-23 4:19 ` [PATCH 09/10] ahci: move host flags over to pi.private_data Tejun Heo
2007-09-23 4:19 ` [PATCH 10/10] ahci: implement AHCI_HFLAG_NO_PMP Tejun Heo
2007-09-26 2:09 ` Polling (was Re: [PATCHSET 2/2] implement PMP support, take 6) Jeff Garzik
2007-09-26 2:12 ` Jeff Garzik
2007-09-26 8:41 ` Tejun Heo
2007-09-28 12:10 ` Tejun Heo
2007-09-28 13:54 ` Jeff Garzik
2007-09-28 14:18 ` Tejun Heo
2007-09-28 14:57 ` Alan Cox
2007-09-28 15:20 ` Jeff Garzik
2007-09-28 15:43 ` Alan Cox
2007-09-28 15:40 ` Jeff Garzik
2007-09-28 20:00 ` Mark Lord
2007-09-29 1:49 ` Jeff Garzik
2007-09-29 3:29 ` Jeff Garzik
2007-09-29 4:58 ` Andrew Morton
2007-09-29 5:09 ` Jeff Garzik
2007-09-29 16:51 ` Greg Freemyer
2007-09-29 20:56 ` Alan Cox
2007-10-01 12:28 ` Jeff Garzik
2007-09-28 15:22 ` Jeff Garzik
2007-09-28 16:48 ` Tejun Heo
2007-09-28 20:02 ` Mark Lord
2007-09-28 20:25 ` Bartlomiej Zolnierkiewicz
2007-09-28 21:03 ` Alan Cox
2007-09-29 1:43 ` Jeff Garzik
2007-09-29 5:24 ` Tejun Heo
2007-10-01 13:31 ` Jeff Garzik
2007-10-02 0:11 ` Tejun Heo
2007-10-02 14:25 ` Alan Cox
2007-10-02 14:30 ` Jeff Garzik
2007-09-29 12:32 ` Mark Lord
2007-10-01 12:38 ` Jeff Garzik
2007-10-02 0:12 ` Tejun Heo
2007-10-02 12:56 ` Jeff Garzik
2007-10-02 13:06 ` Mark Lord
2007-10-02 13:30 ` Jeff Garzik
2007-10-06 22:02 ` Tejun Heo
2007-10-09 2:09 ` Jeff Garzik
2007-10-09 6:54 ` Tejun Heo
2007-09-28 14:20 ` Mark Lord
2007-09-28 15:36 ` Jeff Garzik
2007-09-28 15:55 ` Alan Cox
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=11905211941742-git-send-email-htejun@gmail.com \
--to=htejun@gmail.com \
--cc=alan@lxorguk.ukuu.org.uk \
--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 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.