* [PATCH 11/16] libata: fold ata_dev_config() into ata_dev_configure()
2006-01-26 15:39 [PATCHSET] libata: reorganize configuration and implement revalidation Tejun Heo
@ 2006-01-26 15:39 ` Tejun Heo
2006-01-26 15:39 ` [PATCH 09/16] libata: kill ata_dev_reread_id() Tejun Heo
` (10 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2006-01-26 15:39 UTC (permalink / raw)
To: jgarzik, linux-ide, albertcc, alan; +Cc: Tejun Heo
ata_dev_config() needs to be done everytime a device is configured.
Fold it into ata_dev_configure().
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 49 +++++++++++++++-----------------------------
include/linux/libata.h | 1 -
2 files changed, 17 insertions(+), 33 deletions(-)
74f80371779e436674c85f66df5ee339dfe44657
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 8289fc5..7bc3a59 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1429,6 +1429,12 @@ static int ata_dev_read_id(struct ata_po
return rc;
}
+static inline u8 ata_dev_knobble(const struct ata_port *ap,
+ struct ata_device *dev)
+{
+ return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
+}
+
/**
* ata_dev_configure - Configure the specified ATA/ATAPI device
* @ap: Port on which target device resides
@@ -1543,6 +1549,17 @@ static int ata_dev_configure(struct ata_
ap->host->max_cmd_len,
ap->device[i].cdb_len);
+ /* limit bridge transfers to udma5, 200 sectors */
+ if (ata_dev_knobble(ap, dev)) {
+ printk(KERN_INFO "ata%u(%u): applying bridge limits\n",
+ ap->id, dev->devno);
+ ap->udma_mask &= ATA_UDMA5;
+ dev->max_sectors = ATA_MAX_SECTORS;
+ }
+
+ if (ap->ops->dev_config)
+ ap->ops->dev_config(ap, dev);
+
DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap));
return 0;
@@ -1553,36 +1570,6 @@ err_out_nosup:
return rc;
}
-
-static inline u8 ata_dev_knobble(const struct ata_port *ap,
- struct ata_device *dev)
-{
- return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
-}
-
-/**
- * ata_dev_config - Run device specific handlers and check for
- * SATA->PATA bridges
- * @ap: Bus
- * @i: Device
- *
- * LOCKING:
- */
-
-void ata_dev_config(struct ata_port *ap, unsigned int i)
-{
- /* limit bridge transfers to udma5, 200 sectors */
- if (ata_dev_knobble(ap, &ap->device[i])) {
- printk(KERN_INFO "ata%u(%u): applying bridge limits\n",
- ap->id, i);
- ap->udma_mask &= ATA_UDMA5;
- ap->device[i].max_sectors = ATA_MAX_SECTORS;
- }
-
- if (ap->ops->dev_config)
- ap->ops->dev_config(ap, &ap->device[i]);
-}
-
/**
* ata_bus_probe - Reset and probe ATA bus
* @ap: Bus to probe
@@ -1639,7 +1626,6 @@ static int ata_bus_probe(struct ata_port
continue;
}
- ata_dev_config(ap, i);
found = 1;
}
@@ -5564,7 +5550,6 @@ EXPORT_SYMBOL_GPL(ata_host_intr);
EXPORT_SYMBOL_GPL(ata_dev_classify);
EXPORT_SYMBOL_GPL(ata_dev_id_string);
EXPORT_SYMBOL_GPL(ata_dev_id_c_string);
-EXPORT_SYMBOL_GPL(ata_dev_config);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 1fceafd..2221013 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -547,7 +547,6 @@ extern void ata_dev_id_string(const u16
unsigned int ofs, unsigned int len);
extern void ata_dev_id_c_string(const u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len);
-extern void ata_dev_config(struct ata_port *ap, unsigned int i);
extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
extern void ata_bmdma_start (struct ata_queued_cmd *qc);
extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
--
1.1.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 09/16] libata: kill ata_dev_reread_id()
2006-01-26 15:39 [PATCHSET] libata: reorganize configuration and implement revalidation Tejun Heo
2006-01-26 15:39 ` [PATCH 11/16] libata: fold ata_dev_config() into ata_dev_configure() Tejun Heo
@ 2006-01-26 15:39 ` Tejun Heo
2006-01-26 15:39 ` [PATCH 12/16] libata: reorganize ata_bus_probe() Tejun Heo
` (9 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2006-01-26 15:39 UTC (permalink / raw)
To: jgarzik, linux-ide, albertcc, alan; +Cc: Tejun Heo
Kill now-unused ata_dev_reread_id().
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 42 ------------------------------------------
1 files changed, 0 insertions(+), 42 deletions(-)
8afcb5146c2019c84595beebcdb68335570a754d
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 9575ce0..d1cec73 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -61,7 +61,6 @@
#include "libata.h"
-static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev);
static unsigned int ata_dev_init_params(struct ata_port *ap,
struct ata_device *dev);
static void ata_set_mode(struct ata_port *ap);
@@ -2867,47 +2866,6 @@ static void ata_dev_set_xfermode(struct
}
/**
- * ata_dev_reread_id - Reread the device identify device info
- * @ap: port where the device is
- * @dev: device to reread the identify device info
- *
- * LOCKING:
- */
-
-static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
-{
- struct ata_taskfile tf;
-
- ata_tf_init(ap, &tf, dev->devno);
-
- if (dev->class == ATA_DEV_ATA) {
- tf.command = ATA_CMD_ID_ATA;
- DPRINTK("do ATA identify\n");
- } else {
- tf.command = ATA_CMD_ID_ATAPI;
- DPRINTK("do ATAPI identify\n");
- }
-
- tf.flags |= ATA_TFLAG_DEVICE;
- tf.protocol = ATA_PROT_PIO;
-
- if (ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
- dev->id, sizeof(dev->id)))
- goto err_out;
-
- swap_buf_le16(dev->id, ATA_ID_WORDS);
-
- ata_dump_id(dev->id);
-
- DPRINTK("EXIT\n");
-
- return;
-err_out:
- printk(KERN_ERR "ata%u: failed to reread ID, disabled\n", ap->id);
- ata_port_disable(ap);
-}
-
-/**
* ata_dev_init_params - Issue INIT DEV PARAMS command
* @ap: Port associated with device @dev
* @dev: Device to which command will be sent
--
1.1.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 12/16] libata: reorganize ata_bus_probe()
2006-01-26 15:39 [PATCHSET] libata: reorganize configuration and implement revalidation Tejun Heo
2006-01-26 15:39 ` [PATCH 11/16] libata: fold ata_dev_config() into ata_dev_configure() Tejun Heo
2006-01-26 15:39 ` [PATCH 09/16] libata: kill ata_dev_reread_id() Tejun Heo
@ 2006-01-26 15:39 ` Tejun Heo
2006-01-26 15:39 ` [PATCH 04/16] libata: separate out ata_id_major_version() Tejun Heo
` (8 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2006-01-26 15:39 UTC (permalink / raw)
To: jgarzik, linux-ide, albertcc, alan; +Cc: Tejun Heo
Now that reset and configure are converted such that they don't modify
or disable libata core data structures, reorganize ata_bus_probe() to
reflect this change.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 39 +++++++++++++++++++++------------------
1 files changed, 21 insertions(+), 18 deletions(-)
20afcd17a5a534cf8ca54b381822368d8eb69ba2
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 7bc3a59..ab6b38c 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1587,32 +1587,36 @@ err_out_nosup:
static int ata_bus_probe(struct ata_port *ap)
{
- unsigned int i, found = 0;
+ unsigned int classes[ATA_MAX_DEVICES];
+ unsigned int i, rc, found = 0;
- if (ap->ops->probe_reset) {
- unsigned int classes[ATA_MAX_DEVICES];
- int rc;
-
- ata_port_probe(ap);
+ ata_port_probe(ap);
+ /* reset */
+ if (ap->ops->probe_reset) {
rc = ap->ops->probe_reset(ap, classes);
- if (rc == 0) {
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- ap->device[i].class = classes[i];
- } else {
- printk(KERN_ERR "ata%u: probe reset failed, "
- "disabling port\n", ap->id);
- ata_port_disable(ap);
+ if (rc) {
+ printk("ata%u: reset failed (errno=%d)\n", ap->id, rc);
+ return rc;
}
- } else
+ } else {
ap->ops->phy_reset(ap);
- if (ap->flags & ATA_FLAG_PORT_DISABLED)
- goto err_out;
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ if (!(ap->flags & ATA_FLAG_PORT_DISABLED))
+ classes[i] = ap->device[i].class;
+ else
+ ap->device[i].class = ATA_DEV_UNKNOWN;
+ }
+ ata_port_probe(ap);
+ }
+ /* read IDENTIFY page and configure devices */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->device[i];
+ dev->class = classes[i];
+
if (!ata_dev_present(dev))
continue;
@@ -1629,7 +1633,7 @@ static int ata_bus_probe(struct ata_port
found = 1;
}
- if ((!found) || (ap->flags & ATA_FLAG_PORT_DISABLED))
+ if (!found)
goto err_out_disable;
ata_set_mode(ap);
@@ -1640,7 +1644,6 @@ static int ata_bus_probe(struct ata_port
err_out_disable:
ap->ops->port_disable(ap);
-err_out:
return -1;
}
--
1.1.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 04/16] libata: separate out ata_id_major_version()
2006-01-26 15:39 [PATCHSET] libata: reorganize configuration and implement revalidation Tejun Heo
` (2 preceding siblings ...)
2006-01-26 15:39 ` [PATCH 12/16] libata: reorganize ata_bus_probe() Tejun Heo
@ 2006-01-26 15:39 ` Tejun Heo
2006-01-26 15:39 ` [PATCH 05/16] libata: make ata_dump_id() take @id instead of @dev Tejun Heo
` (7 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2006-01-26 15:39 UTC (permalink / raw)
To: jgarzik, linux-ide, albertcc, alan; +Cc: Tejun Heo
Separate out ATA major version calculation from ata_dev_identify()
into ata_id_major_version(). It's preparation for splitting
ata_dev_identify().
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 6 +-----
include/linux/ata.h | 10 ++++++++++
2 files changed, 11 insertions(+), 5 deletions(-)
4bb86c7dff884e19b8d611950c9928d38837c905
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 5719e4c..dd31f3b 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1325,7 +1325,6 @@ static void ata_dev_identify(struct ata_
{
struct ata_device *dev = &ap->device[device];
unsigned int major_version;
- u16 tmp;
unsigned long xfer_modes;
unsigned int using_edd;
struct ata_taskfile tf;
@@ -1429,10 +1428,7 @@ retry:
goto err_out_nosup;
/* get major version */
- tmp = dev->id[ATA_ID_MAJOR_VER];
- for (major_version = 14; major_version >= 1; major_version--)
- if (tmp & (1 << major_version))
- break;
+ major_version = ata_id_major_version(dev->id);
/*
* The exact sequence expected by certain pre-ATA4 drives is:
diff --git a/include/linux/ata.h b/include/linux/ata.h
index a8155ca..b02a16c 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -267,6 +267,16 @@ struct ata_taskfile {
((u64) (id)[(n) + 1] << 16) | \
((u64) (id)[(n) + 0]) )
+static inline unsigned int ata_id_major_version(const u16 *id)
+{
+ unsigned int mver;
+
+ for (mver = 14; mver >= 1; mver--)
+ if (id[ATA_ID_MAJOR_VER] & (1 << mver))
+ break;
+ return mver;
+}
+
static inline int ata_id_current_chs_valid(const u16 *id)
{
/* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command
--
1.1.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 05/16] libata: make ata_dump_id() take @id instead of @dev
2006-01-26 15:39 [PATCHSET] libata: reorganize configuration and implement revalidation Tejun Heo
` (3 preceding siblings ...)
2006-01-26 15:39 ` [PATCH 04/16] libata: separate out ata_id_major_version() Tejun Heo
@ 2006-01-26 15:39 ` Tejun Heo
2006-01-26 15:39 ` [PATCH 01/16] libata: implement ata_dev_id_c_string() Tejun Heo
` (6 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2006-01-26 15:39 UTC (permalink / raw)
To: jgarzik, linux-ide, albertcc, alan; +Cc: Tejun Heo
Make ata_dump_id() take @id instead of @dev. This is preparation for
splitting ata_dev_identify().
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 42 ++++++++++++------------------------------
1 files changed, 12 insertions(+), 30 deletions(-)
332f5a854f0662e15289e3fd8e34e7fd76345bb7
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index dd31f3b..776d00d 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1049,41 +1049,23 @@ void ata_dev_select(struct ata_port *ap,
/**
* ata_dump_id - IDENTIFY DEVICE info debugging output
- * @dev: Device whose IDENTIFY DEVICE page we will dump
+ * @id: IDENTIFY DEVICE page to dump
*
- * Dump selected 16-bit words from a detected device's
- * IDENTIFY PAGE page.
+ * Dump selected 16-bit words from the given IDENTIFY DEVICE
+ * page.
*
* LOCKING:
* caller.
*/
-static inline void ata_dump_id(const struct ata_device *dev)
+static inline void ata_dump_id(const u16 *id)
{
- DPRINTK("49==0x%04x "
- "53==0x%04x "
- "63==0x%04x "
- "64==0x%04x "
- "75==0x%04x \n",
- dev->id[49],
- dev->id[53],
- dev->id[63],
- dev->id[64],
- dev->id[75]);
- DPRINTK("80==0x%04x "
- "81==0x%04x "
- "82==0x%04x "
- "83==0x%04x "
- "84==0x%04x \n",
- dev->id[80],
- dev->id[81],
- dev->id[82],
- dev->id[83],
- dev->id[84]);
- DPRINTK("88==0x%04x "
- "93==0x%04x\n",
- dev->id[88],
- dev->id[93]);
+ DPRINTK("49==0x%04x 53==0x%04x 63==0x%04x 64==0x%04x 75==0x%04x \n",
+ id[49], id[53], id[63], id[64], id[75]);
+ DPRINTK("80==0x%04x 81==0x%04x 82==0x%04x 83==0x%04x 84==0x%04x \n",
+ id[80], id[81], id[82], id[83], id[84]);
+ DPRINTK("88==0x%04x 93==0x%04x\n",
+ id[88], id[93]);
}
/*
@@ -1418,7 +1400,7 @@ retry:
if (!xfer_modes)
xfer_modes = ata_pio_modes(dev);
- ata_dump_id(dev);
+ ata_dump_id(dev->id);
/* ATA-specific feature tests */
if (dev->class == ATA_DEV_ATA) {
@@ -2854,7 +2836,7 @@ static void ata_dev_reread_id(struct ata
swap_buf_le16(dev->id, ATA_ID_WORDS);
- ata_dump_id(dev);
+ ata_dump_id(dev->id);
DPRINTK("EXIT\n");
--
1.1.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 01/16] libata: implement ata_dev_id_c_string()
2006-01-26 15:39 [PATCHSET] libata: reorganize configuration and implement revalidation Tejun Heo
` (4 preceding siblings ...)
2006-01-26 15:39 ` [PATCH 05/16] libata: make ata_dump_id() take @id instead of @dev Tejun Heo
@ 2006-01-26 15:39 ` Tejun Heo
2006-01-26 15:39 ` [PATCH 07/16] libata: convert dev->id to pointer Tejun Heo
` (5 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2006-01-26 15:39 UTC (permalink / raw)
To: jgarzik, linux-ide, albertcc, alan; +Cc: Tejun Heo
ata_dev_id_c_string() reads ATA string from the specified offset of
the given IDENTIFY PAGE and puts it in the specified buffer in trimmed
and NULL-terminated form. The caller must supply a buffer which is
one byte larger than the maximum size of the target ID string.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 30 ++++++++++++++++++++++++++++++
include/linux/libata.h | 2 ++
2 files changed, 32 insertions(+), 0 deletions(-)
170e46fb5e18c2bc6c6606f9bf6650bfb2b4f578
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index b1ec4e5..2dfc3e9 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -916,6 +916,35 @@ void ata_dev_id_string(const u16 *id, un
}
}
+/**
+ * ata_dev_id_c_string - Convert IDENTIFY DEVICE page into C string
+ * @id: IDENTIFY DEVICE results we will examine
+ * @s: string into which data is output
+ * @ofs: offset into identify device page
+ * @len: length of string to return. must be an odd number.
+ *
+ * This function is identical to ata_dev_id_string except that it
+ * trims trailing spaces and terminates the resulting string with
+ * null. @len must be actual maximum length (even number) + 1.
+ *
+ * LOCKING:
+ * caller.
+ */
+void ata_dev_id_c_string(const u16 *id, unsigned char *s,
+ unsigned int ofs, unsigned int len)
+{
+ unsigned char *p;
+
+ assert(len & 1);
+ s[len - 1] = ' ';
+
+ ata_dev_id_string(id, s, ofs, len - 1);
+
+ p = s + strnlen(s, len) - 1;
+ while (p >= s && *p == ' ')
+ p--;
+ *++p = '\0';
+}
/**
* ata_noop_dev_select - Select device 0/1 on ATA bus
@@ -5531,6 +5560,7 @@ EXPORT_SYMBOL_GPL(ata_scsi_release);
EXPORT_SYMBOL_GPL(ata_host_intr);
EXPORT_SYMBOL_GPL(ata_dev_classify);
EXPORT_SYMBOL_GPL(ata_dev_id_string);
+EXPORT_SYMBOL_GPL(ata_dev_id_c_string);
EXPORT_SYMBOL_GPL(ata_dev_config);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index a30aba8..5bcbab0 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -545,6 +545,8 @@ extern void ata_sg_init(struct ata_queue
extern unsigned int ata_dev_classify(const struct ata_taskfile *tf);
extern void ata_dev_id_string(const u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len);
+extern void ata_dev_id_c_string(const u16 *id, unsigned char *s,
+ unsigned int ofs, unsigned int len);
extern void ata_dev_config(struct ata_port *ap, unsigned int i);
extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
extern void ata_bmdma_start (struct ata_queued_cmd *qc);
--
1.1.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 07/16] libata: convert dev->id to pointer
2006-01-26 15:39 [PATCHSET] libata: reorganize configuration and implement revalidation Tejun Heo
` (5 preceding siblings ...)
2006-01-26 15:39 ` [PATCH 01/16] libata: implement ata_dev_id_c_string() Tejun Heo
@ 2006-01-26 15:39 ` Tejun Heo
2006-01-26 15:39 ` [PATCH 02/16] libata: use ata_dev_id_c_string() Tejun Heo
` (4 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2006-01-26 15:39 UTC (permalink / raw)
To: jgarzik, linux-ide, albertcc, alan; +Cc: Tejun Heo
Convert dev->id from array to pointer. This is to accomodate
revalidation. During revalidation, both old and new IDENTIFY pages
should be accessible and single ->id array doesn't cut it.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 7 +++++++
include/linux/libata.h | 2 +-
2 files changed, 8 insertions(+), 1 deletions(-)
993b529e88acd500b15d745edb3f5b7d18badf38
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 4453060..c7e9dc0 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1333,6 +1333,10 @@ static void ata_dev_identify(struct ata_
ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
+ dev->id = kmalloc(sizeof(dev->id[0]) * ATA_ID_WORDS, GFP_KERNEL);
+ if (dev->id == NULL)
+ goto err_out;
+
retry:
ata_tf_init(ap, &tf, device);
@@ -5053,11 +5057,14 @@ void ata_host_set_remove(struct ata_host
int ata_scsi_release(struct Scsi_Host *host)
{
struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
+ int i;
DPRINTK("ENTER\n");
ap->ops->port_disable(ap);
ata_host_remove(ap, 0);
+ for (i = 0; i < ATA_MAX_DEVICES; i++)
+ kfree(ap->device[i].id);
DPRINTK("EXIT\n");
return 1;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 5bcbab0..1fceafd 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -347,7 +347,7 @@ struct ata_device {
unsigned long flags; /* ATA_DFLAG_xxx */
unsigned int class; /* ATA_DEV_xxx */
unsigned int devno; /* 0 or 1 */
- u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
+ u16 *id; /* IDENTIFY xxx DEVICE data */
u8 pio_mode;
u8 dma_mode;
u8 xfer_mode;
--
1.1.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 02/16] libata: use ata_dev_id_c_string()
2006-01-26 15:39 [PATCHSET] libata: reorganize configuration and implement revalidation Tejun Heo
` (6 preceding siblings ...)
2006-01-26 15:39 ` [PATCH 07/16] libata: convert dev->id to pointer Tejun Heo
@ 2006-01-26 15:39 ` Tejun Heo
2006-01-26 15:39 ` [PATCH 15/16] libata: implement ata_dev_revalidate() Tejun Heo
` (3 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2006-01-26 15:39 UTC (permalink / raw)
To: jgarzik, linux-ide, albertcc, alan; +Cc: Tejun Heo
Use ata_dev_id_c_string()
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 18 ++++--------------
drivers/scsi/sata_sil.c | 21 ++++++---------------
2 files changed, 10 insertions(+), 29 deletions(-)
22d4913cf3ea0abd082d94abc648bb2be3142673
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 2dfc3e9..4b9d7f4 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2645,24 +2645,14 @@ static const char * const ata_dma_blackl
static int ata_dma_blacklisted(const struct ata_device *dev)
{
- unsigned char model_num[40];
- char *s;
- unsigned int len;
+ unsigned char model_num[41];
int i;
- ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
- sizeof(model_num));
- s = &model_num[0];
- len = strnlen(s, sizeof(model_num));
-
- /* ATAPI specifies that empty space is blank-filled; remove blanks */
- while ((len > 0) && (s[len - 1] == ' ')) {
- len--;
- s[len] = 0;
- }
+ ata_dev_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS,
+ sizeof(model_num));
for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++)
- if (!strncmp(ata_dma_blacklist[i], s, len))
+ if (!strcmp(ata_dma_blacklist[i], model_num))
return 1;
return 0;
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 7c28f38..7b099e6 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -331,22 +331,13 @@ static void sil_scr_write (struct ata_po
static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
{
unsigned int n, quirks = 0;
- unsigned char model_num[40];
- const char *s;
- unsigned int len;
-
- ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
- sizeof(model_num));
- s = &model_num[0];
- len = strnlen(s, sizeof(model_num));
-
- /* ATAPI specifies that empty space is blank-filled; remove blanks */
- while ((len > 0) && (s[len - 1] == ' '))
- len--;
+ unsigned char model_num[41];
+
+ ata_dev_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS,
+ sizeof(model_num));
for (n = 0; sil_blacklist[n].product; n++)
- if (!memcmp(sil_blacklist[n].product, s,
- strlen(sil_blacklist[n].product))) {
+ if (!strcmp(sil_blacklist[n].product, model_num)) {
quirks = sil_blacklist[n].quirk;
break;
}
@@ -362,7 +353,7 @@ static void sil_dev_config(struct ata_po
/* limit to udma5 */
if (quirks & SIL_QUIRK_UDMA5MAX) {
printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n",
- ap->id, dev->devno, s);
+ ap->id, dev->devno, model_num);
ap->udma_mask &= ATA_UDMA5;
return;
}
--
1.1.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 15/16] libata: implement ata_dev_revalidate()
2006-01-26 15:39 [PATCHSET] libata: reorganize configuration and implement revalidation Tejun Heo
` (7 preceding siblings ...)
2006-01-26 15:39 ` [PATCH 02/16] libata: use ata_dev_id_c_string() Tejun Heo
@ 2006-01-26 15:39 ` Tejun Heo
2006-01-26 15:39 ` [PATCH 16/16] libata: revalidate after transfer mode configuration Tejun Heo
` (2 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2006-01-26 15:39 UTC (permalink / raw)
To: jgarzik, linux-ide, albertcc, alan; +Cc: Tejun Heo
ata_dev_revalidate() re-reads IDENTIFY PAGE of the given device and
makes sure it's the same device as the configured one. Once it's
verified that it's the same device, @dev is configured according to
newly read IDENTIFY PAGE. Note that revalidation currently doesn't
invoke transfer mode reconfiguration.
Criteria for 'same device'
* same class (of course)
* same model string
* same serial string
* if ATA, same n_sectors (to catch geometry parameter changes)
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 119 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/libata.h | 2 +
2 files changed, 121 insertions(+), 0 deletions(-)
f6a56c850e45513559d097c0f3523e4fe9d8fbeb
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 4150335..68ee230 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2660,6 +2660,124 @@ int ata_drive_probe_reset(struct ata_por
return rc;
}
+/**
+ * ata_dev_same_device - Determine whether new ID matches configured device
+ * @ap: port on which the device to compare against resides
+ * @dev: device to compare against
+ * @new_class: class of the new device
+ * @new_id: IDENTIFY page of the new device
+ *
+ * Compare @new_class and @new_id against @dev and determine
+ * whether @dev is the device indicated by @new_class and
+ * @new_id.
+ *
+ * LOCKING:
+ * None.
+ *
+ * RETURNS:
+ * 1 if @dev matches @new_class and @new_id, 0 otherwise.
+ */
+static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev,
+ unsigned int new_class, const u16 *new_id)
+{
+ const u16 *old_id = dev->id;
+ unsigned char model[2][41], serial[2][21];
+ u64 new_n_sectors;
+
+ if (dev->class != new_class) {
+ printk(KERN_WARNING
+ "ata%u: dev %u class mismatch %d != %d\n",
+ ap->id, dev->devno, dev->class, new_class);
+ return 0;
+ }
+
+ ata_dev_id_c_string(old_id, model[0],
+ ATA_ID_PROD_OFS, sizeof(model[0]));
+ ata_dev_id_c_string(new_id, model[1],
+ ATA_ID_PROD_OFS, sizeof(model[1]));
+ ata_dev_id_c_string(old_id, serial[0],
+ ATA_ID_SERNO_OFS, sizeof(serial[0]));
+ ata_dev_id_c_string(new_id, serial[1],
+ ATA_ID_SERNO_OFS, sizeof(serial[1]));
+ new_n_sectors = ata_id_n_sectors(new_id);
+
+ if (strcmp(model[0], model[1])) {
+ printk(KERN_WARNING
+ "ata%u: dev %u model number mismatch '%s' != '%s'\n",
+ ap->id, dev->devno, model[0], model[1]);
+ return 0;
+ }
+
+ if (strcmp(serial[0], serial[1])) {
+ printk(KERN_WARNING
+ "ata%u: dev %u serial number mismatch '%s' != '%s'\n",
+ ap->id, dev->devno, serial[0], serial[1]);
+ return 0;
+ }
+
+ if (dev->class == ATA_DEV_ATA && dev->n_sectors != new_n_sectors) {
+ printk(KERN_WARNING
+ "ata%u: dev %u n_sectors mismatch %llu != %llu\n",
+ ap->id, dev->devno, (unsigned long long)dev->n_sectors,
+ (unsigned long long)new_n_sectors);
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
+ * ata_dev_revalidate - Revalidate ATA device
+ * @ap: port on which the device to revalidate resides
+ * @dev: device to revalidate
+ * @post_reset: is this revalidation after reset?
+ *
+ * Re-read IDENTIFY page and make sure @dev is still attached to
+ * the port.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ *
+ * RETURNS:
+ * 0 on success, negative errno otherwise
+ */
+int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev,
+ int post_reset)
+{
+ unsigned int class;
+ u16 *id;
+ int rc;
+
+ if (!ata_dev_present(dev))
+ return 0;
+
+ class = dev->class;
+ id = NULL;
+
+ /* allocate & read ID data */
+ rc = ata_dev_read_id(ap, dev, &class, post_reset, &id);
+ if (rc)
+ goto fail;
+
+ /* is the device still there? */
+ if (!ata_dev_same_device(ap, dev, class, id)) {
+ rc = -ENODEV;
+ goto fail;
+ }
+
+ kfree(dev->id);
+ dev->id = id;
+
+ /* configure device according to the new ID */
+ return ata_dev_configure(ap, dev, 0);
+
+ fail:
+ printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n",
+ ap->id, dev->devno, rc);
+ kfree(id);
+ return rc;
+}
+
static void ata_pr_blacklisted(const struct ata_port *ap,
const struct ata_device *dev)
{
@@ -5560,6 +5678,7 @@ EXPORT_SYMBOL_GPL(sata_std_hardreset);
EXPORT_SYMBOL_GPL(ata_std_postreset);
EXPORT_SYMBOL_GPL(ata_std_probe_reset);
EXPORT_SYMBOL_GPL(ata_drive_probe_reset);
+EXPORT_SYMBOL_GPL(ata_dev_revalidate);
EXPORT_SYMBOL_GPL(ata_port_disable);
EXPORT_SYMBOL_GPL(ata_ratelimit);
EXPORT_SYMBOL_GPL(ata_busy_sleep);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 2221013..4ccea16 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -491,6 +491,8 @@ extern int ata_std_softreset(struct ata_
extern int sata_std_hardreset(struct ata_port *ap, int verbose,
unsigned int *class);
extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes);
+extern int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev,
+ int post_reset);
extern void ata_port_disable(struct ata_port *);
extern void ata_std_ports(struct ata_ioports *ioaddr);
#ifdef CONFIG_PCI
--
1.1.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 16/16] libata: revalidate after transfer mode configuration
2006-01-26 15:39 [PATCHSET] libata: reorganize configuration and implement revalidation Tejun Heo
` (8 preceding siblings ...)
2006-01-26 15:39 ` [PATCH 15/16] libata: implement ata_dev_revalidate() Tejun Heo
@ 2006-01-26 15:39 ` Tejun Heo
2006-01-26 15:39 ` [PATCH 13/16] libata: re-initialize parameters before configuring Tejun Heo
2006-01-26 17:42 ` [PATCHSET] libata: reorganize configuration and implement revalidation Mark Lord
11 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2006-01-26 15:39 UTC (permalink / raw)
To: jgarzik, linux-ide, albertcc, alan; +Cc: Tejun Heo
Revalidate device after transfer mode configuration. This also makes
dev->id up-to-date.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
35fcb729b1ff75eff6bd088b0ac1444255238e9e
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 68ee230..613c317 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1996,6 +1996,12 @@ static void ata_dev_set_mode(struct ata_
idx = ofs + dev->xfer_shift;
WARN_ON(idx >= ARRAY_SIZE(xfer_mode_str));
+ if (ata_dev_revalidate(ap, dev, 0)) {
+ printk(KERN_ERR "ata%u: failed to revalidate after set "
+ "xfermode, disabled\n", ap->id);
+ ata_port_disable(ap);
+ }
+
DPRINTK("idx=%d xfer_shift=%u, xfer_mode=0x%x, base=0x%x, offset=%d\n",
idx, dev->xfer_shift, (int)dev->xfer_mode, (int)base, ofs);
--
1.1.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 13/16] libata: re-initialize parameters before configuring
2006-01-26 15:39 [PATCHSET] libata: reorganize configuration and implement revalidation Tejun Heo
` (9 preceding siblings ...)
2006-01-26 15:39 ` [PATCH 16/16] libata: revalidate after transfer mode configuration Tejun Heo
@ 2006-01-26 15:39 ` Tejun Heo
2006-01-26 17:42 ` [PATCHSET] libata: reorganize configuration and implement revalidation Mark Lord
11 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2006-01-26 15:39 UTC (permalink / raw)
To: jgarzik, linux-ide, albertcc, alan; +Cc: Tejun Heo
In ata_dev_configure(), reinitialize parameters before configuring.
This change is for revalidation and hotplug. As ata_dev_configure()
can be entered multiple times, parameters need to be reinitialized.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/libata-core.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
403e45409fde12b368ad951e40e8ad0f4769b521
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index ab6b38c..9b1d225 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1462,6 +1462,15 @@ static int ata_dev_configure(struct ata_
DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno);
+ /* initialize to-be-configured parameters */
+ dev->flags = 0;
+ dev->max_sectors = 0;
+ dev->cdb_len = 0;
+ dev->n_sectors = 0;
+ dev->cylinders = 0;
+ dev->heads = 0;
+ dev->sectors = 0;
+
/*
* common ATA, ATAPI feature tests
*/
--
1.1.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCHSET] libata: reorganize configuration and implement revalidation
2006-01-26 15:39 [PATCHSET] libata: reorganize configuration and implement revalidation Tejun Heo
` (10 preceding siblings ...)
2006-01-26 15:39 ` [PATCH 13/16] libata: re-initialize parameters before configuring Tejun Heo
@ 2006-01-26 17:42 ` Mark Lord
11 siblings, 0 replies; 13+ messages in thread
From: Mark Lord @ 2006-01-26 17:42 UTC (permalink / raw)
To: Tejun Heo; +Cc: jgarzik, linux-ide, albertcc, alan
Tejun Heo wrote:
>
> Also, please pay attention to the following. It's taken from #08's
> description.
>
> This function is probably the place to set transfer mode to PIO0
> before IDENTIFY. However, reset -> identify -> init_dev_params
> order should be kept for pre-ATA4 devices so we cannot set transfer
> mode before IDENTIFY for them. How do we know if a device is
> post-ATA4 before IDENTIFY?
>
> How should we do this? Ignore pre-ATA4 devices?
It should be more a matter of setting the chipset to PIO0
before doing the IDENTIFY.
The drives themselves should "just work", as the RESET would
have bumped them back to their default (slow) PIO timing mode.
IDENTIFY has to be the very first drive command, so there's no
way to do a SET_FEATURES/XFER_MODE beforehand.
-ml
^ permalink raw reply [flat|nested] 13+ messages in thread