* [PATCH 2/5] libata: convert @post_reset to @flags in ata_dev_read_id()
2006-11-10 9:08 [PATCHSET #upstream] libata: implement presence detection using polling IDENTIFY for ata_piix, take #2 Tejun Heo
@ 2006-11-10 9:08 ` Tejun Heo
2006-11-10 9:08 ` [PATCH 4/5] ata_piix: apply device detection via polling IDENTIFY Tejun Heo
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Tejun Heo @ 2006-11-10 9:08 UTC (permalink / raw)
To: jgarzik, alan, linux-ide; +Cc: Tejun Heo
Make ata_dev_read_id() take @flags instead of @post_reset. Currently
there is only one flag defined - ATA_READID_POSTRESET, which is
equivalent to @post_reset. This is preparation for polling presence
detection.
---
drivers/ata/libata-core.c | 17 +++++++++--------
drivers/ata/libata-eh.c | 11 +++++++----
drivers/ata/libata.h | 9 +++++++--
3 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 9fdb266..486cabf 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1224,7 +1224,7 @@ unsigned int ata_pio_need_iordy(const st
* ata_dev_read_id - Read ID data from the specified device
* @dev: target device
* @p_class: pointer to class of the target device (may be changed)
- * @post_reset: is this read ID post-reset?
+ * @flags: ATA_READID_* flags
* @id: buffer to read IDENTIFY data into
*
* Read ID data from the specified device. ATA_CMD_ID_ATA is
@@ -1239,7 +1239,7 @@ unsigned int ata_pio_need_iordy(const st
* 0 on success, -errno otherwise.
*/
int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
- int post_reset, u16 *id)
+ unsigned int flags, u16 *id)
{
struct ata_port *ap = dev->ap;
unsigned int class = *p_class;
@@ -1294,7 +1294,7 @@ int ata_dev_read_id(struct ata_device *d
goto err_out;
}
- if (post_reset && class == ATA_DEV_ATA) {
+ if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) {
/*
* The exact sequence expected by certain pre-ATA4 drives is:
* SRST RESET
@@ -1314,7 +1314,7 @@ int ata_dev_read_id(struct ata_device *d
/* current CHS translation info (id[53-58]) might be
* changed. reread the identify device info.
*/
- post_reset = 0;
+ flags &= ~ATA_READID_POSTRESET;
goto retry;
}
}
@@ -1639,7 +1639,8 @@ int ata_bus_probe(struct ata_port *ap)
if (!ata_dev_enabled(dev))
continue;
- rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
+ rc = ata_dev_read_id(dev, &dev->class, ATA_READID_POSTRESET,
+ dev->id);
if (rc)
goto fail;
@@ -3019,7 +3020,7 @@ static int ata_dev_same_device(struct at
/**
* ata_dev_revalidate - Revalidate ATA device
* @dev: device to revalidate
- * @post_reset: is this revalidation after reset?
+ * @readid_flags: read ID flags
*
* Re-read IDENTIFY page and make sure @dev is still attached to
* the port.
@@ -3030,7 +3031,7 @@ static int ata_dev_same_device(struct at
* RETURNS:
* 0 on success, negative errno otherwise
*/
-int ata_dev_revalidate(struct ata_device *dev, int post_reset)
+int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags)
{
unsigned int class = dev->class;
u16 *id = (void *)dev->ap->sector_buf;
@@ -3042,7 +3043,7 @@ int ata_dev_revalidate(struct ata_device
}
/* read ID data */
- rc = ata_dev_read_id(dev, &class, post_reset, id);
+ rc = ata_dev_read_id(dev, &class, readid_flags, id);
if (rc)
goto fail;
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 4776488..755fc68 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1634,11 +1634,14 @@ static int ata_eh_revalidate_and_attach(
DPRINTK("ENTER\n");
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- unsigned int action;
+ unsigned int action, readid_flags = 0;
dev = &ap->device[i];
action = ata_eh_dev_action(dev);
+ if (ehc->i.flags & ATA_EHI_DID_RESET)
+ readid_flags |= ATA_READID_POSTRESET;
+
if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) {
if (ata_port_offline(ap)) {
rc = -EIO;
@@ -1646,8 +1649,7 @@ static int ata_eh_revalidate_and_attach(
}
ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE);
- rc = ata_dev_revalidate(dev,
- ehc->i.flags & ATA_EHI_DID_RESET);
+ rc = ata_dev_revalidate(dev, readid_flags);
if (rc)
break;
@@ -1665,7 +1667,8 @@ static int ata_eh_revalidate_and_attach(
ata_class_enabled(ehc->classes[dev->devno])) {
dev->class = ehc->classes[dev->devno];
- rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
+ rc = ata_dev_read_id(dev, &dev->class, readid_flags,
+ dev->id);
if (rc == 0) {
ehc->i.flags |= ATA_EHI_PRINTINFO;
rc = ata_dev_configure(dev);
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index e4ffb2e..bb98390 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -39,6 +39,11 @@ struct ata_scsi_args {
};
/* libata-core.c */
+enum {
+ /* flags for ata_dev_read_id() */
+ ATA_READID_POSTRESET = (1 << 0), /* reading ID after reset */
+};
+
extern struct workqueue_struct *ata_aux_wq;
extern int atapi_enabled;
extern int atapi_dmadir;
@@ -52,8 +57,8 @@ extern unsigned ata_exec_internal(struct
int dma_dir, void *buf, unsigned int buflen);
extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd);
extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
- int post_reset, u16 *id);
-extern int ata_dev_revalidate(struct ata_device *dev, int post_reset);
+ unsigned int flags, u16 *id);
+extern int ata_dev_revalidate(struct ata_device *dev, unsigned int flags);
extern int ata_dev_configure(struct ata_device *dev);
extern int sata_down_spd_limit(struct ata_port *ap);
extern int sata_set_spd_needed(struct ata_port *ap);
--
1.4.3.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 4/5] ata_piix: apply device detection via polling IDENTIFY
2006-11-10 9:08 [PATCHSET #upstream] libata: implement presence detection using polling IDENTIFY for ata_piix, take #2 Tejun Heo
2006-11-10 9:08 ` [PATCH 2/5] libata: convert @post_reset to @flags in ata_dev_read_id() Tejun Heo
@ 2006-11-10 9:08 ` Tejun Heo
2006-11-10 9:08 ` [PATCH 5/5] ata_piix: strip now unneded MAP related stuff Tejun Heo
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Tejun Heo @ 2006-11-10 9:08 UTC (permalink / raw)
To: jgarzik, alan, linux-ide; +Cc: Tejun Heo
PATA PIIX uses reset signature + TF r/w test for device presence
detection, which doesn't always work. It sometimes reports phantom
device which results in IDENTIFY timeouts.
SATA PIIX uses some combination of PCS + reset signature + TF r/w test
for device presence detection. No combination satifies all and for
some controllers, there doesn't seem to be any combination which
works reliably.
This patch makes both PATA and SATA piix's use reset signature + TF
r/w + polling IDENTIFY for device detection. This is what the old
libata (before irq-pio and new EH) did and what IDE does.
This patch also removes now obsolete PIIX_FLAG_IGNORE_PCS, force_pcs
and related code.
---
drivers/ata/ata_piix.c | 104 +++---------------------------------------------
1 files changed, 6 insertions(+), 98 deletions(-)
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 90ac33a..7bf2386 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -101,13 +101,13 @@ enum {
ICH5_PCS = 0x92, /* port control and status */
PIIX_SCC = 0x0A, /* sub-class code register */
- PIIX_FLAG_IGNORE_PCS = (1 << 25), /* ignore PCS present bits */
PIIX_FLAG_SCR = (1 << 26), /* SCR available */
PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */
PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */
- PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS,
- PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
+ PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS | ATA_FLAG_DETECT_POLLING,
+ PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR |
+ ATA_FLAG_DETECT_POLLING,
/* combined mode. if set, PATA is channel 0.
* if clear, PATA is channel 1.
@@ -490,7 +490,7 @@ static struct ata_port_info piix_port_in
/* ich5_sata: 5 */
{
.sht = &piix_sht,
- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_IGNORE_PCS,
+ .flags = PIIX_SATA_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 */
@@ -500,7 +500,7 @@ static struct ata_port_info piix_port_in
/* i6300esb_sata: 6 */
{
.sht = &piix_sht,
- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_IGNORE_PCS,
+ .flags = PIIX_SATA_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 */
@@ -563,11 +563,6 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
MODULE_VERSION(DRV_VERSION);
-static int force_pcs = 0;
-module_param(force_pcs, int, 0444);
-MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around "
- "device mis-detection (0=default, 1=ignore PCS, 2=honor PCS)");
-
struct ich_laptop {
u16 device;
u16 subvendor;
@@ -685,84 +680,9 @@ static void ich_pata_error_handler(struc
ata_std_postreset);
}
-/**
- * piix_sata_present_mask - determine present mask for SATA host controller
- * @ap: Target port
- *
- * Reads SATA PCI device's PCI config register Port Configuration
- * and Status (PCS) to determine port and device availability.
- *
- * LOCKING:
- * None (inherited from caller).
- *
- * RETURNS:
- * determined present_mask
- */
-static unsigned int piix_sata_present_mask(struct ata_port *ap)
-{
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- struct piix_host_priv *hpriv = ap->host->private_data;
- const unsigned int *map = hpriv->map;
- int base = 2 * ap->port_no;
- unsigned int present_mask = 0;
- int port, i;
- u16 pcs;
-
- pci_read_config_word(pdev, ICH5_PCS, &pcs);
- DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base);
-
- for (i = 0; i < 2; i++) {
- port = map[base + i];
- if (port < 0)
- continue;
- if ((ap->flags & PIIX_FLAG_IGNORE_PCS) ||
- (pcs & 1 << (hpriv->map_db->present_shift + port)))
- present_mask |= 1 << i;
- }
-
- DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n",
- ap->id, pcs, present_mask);
-
- return present_mask;
-}
-
-/**
- * piix_sata_softreset - reset SATA host port via ATA SRST
- * @ap: port to reset
- * @classes: resulting classes of attached devices
- *
- * Reset SATA host port via ATA SRST. On controllers with
- * reliable PCS present bits, the bits are used to determine
- * device presence.
- *
- * LOCKING:
- * Kernel thread context (may sleep)
- *
- * RETURNS:
- * 0 on success, -errno otherwise.
- */
-static int piix_sata_softreset(struct ata_port *ap, unsigned int *classes)
-{
- unsigned int present_mask;
- int i, rc;
-
- present_mask = piix_sata_present_mask(ap);
-
- rc = ata_std_softreset(ap, classes);
- if (rc)
- return rc;
-
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- if (!(present_mask & (1 << i)))
- classes[i] = ATA_DEV_NONE;
- }
-
- return 0;
-}
-
static void piix_sata_error_handler(struct ata_port *ap)
{
- ata_bmdma_drive_eh(ap, ata_std_prereset, piix_sata_softreset, NULL,
+ ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
ata_std_postreset);
}
@@ -1077,18 +997,6 @@ static void __devinit piix_init_pcs(stru
pci_write_config_word(pdev, ICH5_PCS, new_pcs);
msleep(150);
}
-
- if (force_pcs == 1) {
- dev_printk(KERN_INFO, &pdev->dev,
- "force ignoring PCS (0x%x)\n", new_pcs);
- pinfo[0].flags |= PIIX_FLAG_IGNORE_PCS;
- pinfo[1].flags |= PIIX_FLAG_IGNORE_PCS;
- } else if (force_pcs == 2) {
- dev_printk(KERN_INFO, &pdev->dev,
- "force honoring PCS (0x%x)\n", new_pcs);
- pinfo[0].flags &= ~PIIX_FLAG_IGNORE_PCS;
- pinfo[1].flags &= ~PIIX_FLAG_IGNORE_PCS;
- }
}
static void __devinit piix_init_sata_map(struct pci_dev *pdev,
--
1.4.3.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 5/5] ata_piix: strip now unneded MAP related stuff
2006-11-10 9:08 [PATCHSET #upstream] libata: implement presence detection using polling IDENTIFY for ata_piix, take #2 Tejun Heo
2006-11-10 9:08 ` [PATCH 2/5] libata: convert @post_reset to @flags in ata_dev_read_id() Tejun Heo
2006-11-10 9:08 ` [PATCH 4/5] ata_piix: apply device detection via polling IDENTIFY Tejun Heo
@ 2006-11-10 9:08 ` Tejun Heo
2006-11-10 9:08 ` [PATCH 1/5] ata_piix: clean up port flags Tejun Heo
2006-11-10 9:08 ` [PATCH 3/5] libata: implement presence detection via polling IDENTIFY Tejun Heo
4 siblings, 0 replies; 7+ messages in thread
From: Tejun Heo @ 2006-11-10 9:08 UTC (permalink / raw)
To: jgarzik, alan, linux-ide; +Cc: Tejun Heo
Now that PCS isn't used for device detection anymore...
* esb_sata is identical to ich5_sata
* no reason to know present_shift
* no reason to store map_db in host private area
The MAP table itself is left because it can be used for SCR access.
---
drivers/ata/ata_piix.c | 39 ++++++++++-----------------------------
1 files changed, 10 insertions(+), 29 deletions(-)
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 7bf2386..788a269 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -125,11 +125,10 @@ enum {
ich_pata_100 = 3, /* ICH up to UDMA 100 */
ich_pata_133 = 4, /* ICH up to UDMA 133 */
ich5_sata = 5,
- esb_sata = 6,
- ich6_sata = 7,
- ich6_sata_ahci = 8,
- ich6m_sata_ahci = 9,
- ich8_sata_ahci = 10,
+ ich6_sata = 6,
+ ich6_sata_ahci = 7,
+ ich6m_sata_ahci = 8,
+ ich8_sata_ahci = 9,
/* constants for mapping table */
P0 = 0, /* port 0 */
@@ -146,13 +145,11 @@ enum {
struct piix_map_db {
const u32 mask;
const u16 port_enable;
- const int present_shift;
const int map[][4];
};
struct piix_host_priv {
const int *map;
- const struct piix_map_db *map_db;
};
static int piix_init_one (struct pci_dev *pdev,
@@ -217,9 +214,9 @@ static const struct pci_device_id piix_p
/* 82801EB (ICH5) */
{ 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
/* 6300ESB (ICH5 variant with broken PCS present bits) */
- { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
+ { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
/* 6300ESB pretending RAID */
- { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
+ { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
/* 82801FB/FW (ICH6/ICH6W) */
{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
/* 82801FR/FRW (ICH6R/ICH6RW) */
@@ -370,7 +367,6 @@ static const struct ata_port_operations
static const struct piix_map_db ich5_map_db = {
.mask = 0x7,
.port_enable = 0x3,
- .present_shift = 4,
.map = {
/* PM PS SM SS MAP */
{ P0, NA, P1, NA }, /* 000b */
@@ -387,7 +383,6 @@ static const struct piix_map_db ich5_map
static const struct piix_map_db ich6_map_db = {
.mask = 0x3,
.port_enable = 0xf,
- .present_shift = 4,
.map = {
/* PM PS SM SS MAP */
{ P0, P2, P1, P3 }, /* 00b */
@@ -400,7 +395,6 @@ static const struct piix_map_db ich6_map
static const struct piix_map_db ich6m_map_db = {
.mask = 0x3,
.port_enable = 0x5,
- .present_shift = 4,
/* Map 01b isn't specified in the doc but some notebooks use
* it anyway. MAP 01b have been spotted on both ICH6M and
@@ -418,7 +412,6 @@ static const struct piix_map_db ich6m_ma
static const struct piix_map_db ich8_map_db = {
.mask = 0x3,
.port_enable = 0x3,
- .present_shift = 8,
.map = {
/* PM PS SM SS MAP */
{ P0, P2, P1, P3 }, /* 00b (hardwired when in AHCI) */
@@ -430,7 +423,6 @@ static const struct piix_map_db ich8_map
static const struct piix_map_db *piix_map_db_table[] = {
[ich5_sata] = &ich5_map_db,
- [esb_sata] = &ich5_map_db,
[ich6_sata] = &ich6_map_db,
[ich6_sata_ahci] = &ich6_map_db,
[ich6m_sata_ahci] = &ich6m_map_db,
@@ -497,17 +489,7 @@ static struct ata_port_info piix_port_in
.port_ops = &piix_sata_ops,
},
- /* i6300esb_sata: 6 */
- {
- .sht = &piix_sht,
- .flags = PIIX_SATA_FLAGS,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
- .port_ops = &piix_sata_ops,
- },
-
- /* ich6_sata: 7 */
+ /* ich6_sata: 6 */
{
.sht = &piix_sht,
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR,
@@ -517,7 +499,7 @@ static struct ata_port_info piix_port_in
.port_ops = &piix_sata_ops,
},
- /* ich6_sata_ahci: 8 */
+ /* ich6_sata_ahci: 7 */
{
.sht = &piix_sht,
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
@@ -528,7 +510,7 @@ static struct ata_port_info piix_port_in
.port_ops = &piix_sata_ops,
},
- /* ich6m_sata_ahci: 9 */
+ /* ich6m_sata_ahci: 8 */
{
.sht = &piix_sht,
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
@@ -539,7 +521,7 @@ static struct ata_port_info piix_port_in
.port_ops = &piix_sata_ops,
},
- /* ich8_sata_ahci: 10 */
+ /* ich8_sata_ahci: 9 */
{
.sht = &piix_sht,
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
@@ -1046,7 +1028,6 @@ static void __devinit piix_init_sata_map
"invalid MAP value %u\n", map_value);
hpriv->map = map;
- hpriv->map_db = map_db;
}
/**
--
1.4.3.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 1/5] ata_piix: clean up port flags
2006-11-10 9:08 [PATCHSET #upstream] libata: implement presence detection using polling IDENTIFY for ata_piix, take #2 Tejun Heo
` (2 preceding siblings ...)
2006-11-10 9:08 ` [PATCH 5/5] ata_piix: strip now unneded MAP related stuff Tejun Heo
@ 2006-11-10 9:08 ` Tejun Heo
2006-11-14 19:23 ` Jeff Garzik
2006-11-10 9:08 ` [PATCH 3/5] libata: implement presence detection via polling IDENTIFY Tejun Heo
4 siblings, 1 reply; 7+ messages in thread
From: Tejun Heo @ 2006-11-10 9:08 UTC (permalink / raw)
To: jgarzik, alan, linux-ide; +Cc: Tejun Heo
* move common flags into PIIX_PATA_FLAGS and PIIX_SATA_FLAGS
* kill unnecessary ATA_FLAG_SRST
---
drivers/ata/ata_piix.c | 31 ++++++++++++++-----------------
1 files changed, 14 insertions(+), 17 deletions(-)
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 14b726b..90ac33a 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -106,6 +106,9 @@ enum {
PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */
PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */
+ PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS,
+ PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
+
/* combined mode. if set, PATA is channel 0.
* if clear, PATA is channel 1.
*/
@@ -438,7 +441,7 @@ static struct ata_port_info piix_port_in
/* piix_pata_33: 0: PIIX3 or 4 at 33MHz */
{
.sht = &piix_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = PIIX_PATA_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
.udma_mask = ATA_UDMA_MASK_40C,
@@ -448,7 +451,7 @@ static struct ata_port_info piix_port_in
/* ich_pata_33: 1 ICH0 - ICH at 33Mhz*/
{
.sht = &piix_sht,
- .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS,
+ .flags = PIIX_PATA_FLAGS,
.pio_mask = 0x1f, /* pio 0-4 */
.mwdma_mask = 0x06, /* Check: maybe 0x07 */
.udma_mask = ATA_UDMA2, /* UDMA33 */
@@ -457,7 +460,7 @@ static struct ata_port_info piix_port_in
/* ich_pata_66: 2 ICH controllers up to 66MHz */
{
.sht = &piix_sht,
- .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS,
+ .flags = PIIX_PATA_FLAGS,
.pio_mask = 0x1f, /* pio 0-4 */
.mwdma_mask = 0x06, /* MWDMA0 is broken on chip */
.udma_mask = ATA_UDMA4,
@@ -467,7 +470,7 @@ static struct ata_port_info piix_port_in
/* ich_pata_100: 3 */
{
.sht = &piix_sht,
- .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR,
+ .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x06, /* mwdma1-2 */
.udma_mask = ATA_UDMA5, /* udma0-5 */
@@ -477,7 +480,7 @@ static struct ata_port_info piix_port_in
/* ich_pata_133: 4 ICH with full UDMA6 */
{
.sht = &piix_sht,
- .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR,
+ .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
.pio_mask = 0x1f, /* pio 0-4 */
.mwdma_mask = 0x06, /* Check: maybe 0x07 */
.udma_mask = ATA_UDMA6, /* UDMA133 */
@@ -487,8 +490,7 @@ static struct ata_port_info piix_port_in
/* ich5_sata: 5 */
{
.sht = &piix_sht,
- .flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR |
- PIIX_FLAG_IGNORE_PCS,
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_IGNORE_PCS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 */
@@ -498,8 +500,7 @@ static struct ata_port_info piix_port_in
/* i6300esb_sata: 6 */
{
.sht = &piix_sht,
- .flags = ATA_FLAG_SATA |
- PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS,
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_IGNORE_PCS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 */
@@ -509,8 +510,7 @@ static struct ata_port_info piix_port_in
/* ich6_sata: 7 */
{
.sht = &piix_sht,
- .flags = ATA_FLAG_SATA |
- PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR,
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 */
@@ -520,8 +520,7 @@ static struct ata_port_info piix_port_in
/* ich6_sata_ahci: 8 */
{
.sht = &piix_sht,
- .flags = ATA_FLAG_SATA |
- PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
@@ -532,8 +531,7 @@ static struct ata_port_info piix_port_in
/* ich6m_sata_ahci: 9 */
{
.sht = &piix_sht,
- .flags = ATA_FLAG_SATA |
- PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
@@ -544,8 +542,7 @@ static struct ata_port_info piix_port_in
/* ich8_sata_ahci: 10 */
{
.sht = &piix_sht,
- .flags = ATA_FLAG_SATA |
- PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
--
1.4.3.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 3/5] libata: implement presence detection via polling IDENTIFY
2006-11-10 9:08 [PATCHSET #upstream] libata: implement presence detection using polling IDENTIFY for ata_piix, take #2 Tejun Heo
` (3 preceding siblings ...)
2006-11-10 9:08 ` [PATCH 1/5] ata_piix: clean up port flags Tejun Heo
@ 2006-11-10 9:08 ` Tejun Heo
4 siblings, 0 replies; 7+ messages in thread
From: Tejun Heo @ 2006-11-10 9:08 UTC (permalink / raw)
To: jgarzik, alan, linux-ide; +Cc: Tejun Heo
On some controllers (ICHs in piix mode), there is *NO* reliable way to
determine device presence other than issuing IDENTIFY and see how the
transaction proceeds by watching the TF status register.
libata acted this way before irq-pio and phantom devices caused very
little problem but now that IDENTIFY is performed using IRQ drive PIO,
such phantom devices now result in multiple 30sec timeouts during
boot.
This patch implements ATA_FLAG_DETECT_POLLING. If a LLD sets this
flag, libata core issues the initial IDENTIFY in polling mode and if
the initial data transfer fails w/ HSM violation, the port is
considered to be empty thus replicating the old libata and IDE
behavior.
---
drivers/ata/libata-core.c | 19 +++++++++++++++++--
drivers/ata/libata-eh.c | 23 ++++++++++++++++++-----
drivers/ata/libata.h | 2 ++
include/linux/libata.h | 3 +++
4 files changed, 40 insertions(+), 7 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 486cabf..4616bb3 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1272,9 +1272,20 @@ int ata_dev_read_id(struct ata_device *d
tf.protocol = ATA_PROT_PIO;
+ /* presence detection using polling IDENTIFY? */
+ if (flags & ATA_READID_DETECT)
+ tf.flags |= ATA_TFLAG_POLLING;
+
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
id, sizeof(id[0]) * ATA_ID_WORDS);
if (err_mask) {
+ if ((flags & ATA_READID_DETECT) &&
+ (err_mask & AC_ERR_NODEV_HINT)) {
+ DPRINTK("ata%u.%d: NODEV after polling detection\n",
+ ap->id, dev->devno);
+ return -ENOENT;
+ }
+
rc = -EIO;
reason = "I/O error";
goto err_out;
@@ -4281,8 +4292,12 @@ fsm_start:
/* device stops HSM for abort/error */
qc->err_mask |= AC_ERR_DEV;
else
- /* HSM violation. Let EH handle this */
- qc->err_mask |= AC_ERR_HSM;
+ /* HSM violation. Let EH handle this.
+ * Phantom devices also trigger this
+ * condition. Mark hint.
+ */
+ qc->err_mask |= AC_ERR_HSM |
+ AC_ERR_NODEV_HINT;
ap->hsm_task_state = HSM_ST_ERR;
goto fsm_start;
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 755fc68..e69f3df 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1667,12 +1667,23 @@ static int ata_eh_revalidate_and_attach(
ata_class_enabled(ehc->classes[dev->devno])) {
dev->class = ehc->classes[dev->devno];
+ if (ap->flags & ATA_FLAG_DETECT_POLLING)
+ readid_flags |= ATA_READID_DETECT;
+
rc = ata_dev_read_id(dev, &dev->class, readid_flags,
dev->id);
if (rc == 0) {
ehc->i.flags |= ATA_EHI_PRINTINFO;
rc = ata_dev_configure(dev);
ehc->i.flags &= ~ATA_EHI_PRINTINFO;
+ } else if (rc == -ENOENT) {
+ /* IDENTIFY was issued to non-existent
+ * device. No need to reset. Just
+ * thaw and kill the device.
+ */
+ ata_eh_thaw_port(ap);
+ dev->class = ATA_DEV_UNKNOWN;
+ rc = 0;
}
if (rc) {
@@ -1680,12 +1691,14 @@ static int ata_eh_revalidate_and_attach(
break;
}
- spin_lock_irqsave(ap->lock, flags);
- ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
- spin_unlock_irqrestore(ap->lock, flags);
+ if (ata_dev_enabled(dev)) {
+ spin_lock_irqsave(ap->lock, flags);
+ ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
+ spin_unlock_irqrestore(ap->lock, flags);
- /* new device discovered, configure transfer mode */
- ehc->i.flags |= ATA_EHI_SETMODE;
+ /* new device discovered, configure xfermode */
+ ehc->i.flags |= ATA_EHI_SETMODE;
+ }
}
}
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index bb98390..be2ac39 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -42,6 +42,8 @@ struct ata_scsi_args {
enum {
/* flags for ata_dev_read_id() */
ATA_READID_POSTRESET = (1 << 0), /* reading ID after reset */
+ ATA_READID_DETECT = (1 << 1), /* perform presence detection
+ * using polling IDENTIFY */
};
extern struct workqueue_struct *ata_aux_wq;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 0d0ddea..4236efc 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -175,6 +175,8 @@ enum {
ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H
* Register FIS clearing BSY */
ATA_FLAG_DEBUGMSG = (1 << 13),
+ ATA_FLAG_DETECT_POLLING = (1 << 14), /* detect device presence by
+ * polling IDENTIFY */
/* The following flag belongs to ap->pflags but is kept in
* ap->flags because it's referenced in many LLDs and will be
@@ -334,6 +336,7 @@ enum ata_completion_errors {
AC_ERR_SYSTEM = (1 << 6), /* system error */
AC_ERR_INVALID = (1 << 7), /* invalid argument */
AC_ERR_OTHER = (1 << 8), /* unknown */
+ AC_ERR_NODEV_HINT = (1 << 9), /* polling device detection hint */
};
/* forward declarations */
--
1.4.3.3
^ permalink raw reply related [flat|nested] 7+ messages in thread