* [PATCHSET] libata: implement and use ata_dev_revalidate(), take #2
@ 2006-03-01 8:20 Tejun Heo
2006-03-01 8:20 ` [PATCH 4/4] libata: revalidate after transfer mode configuration Tejun Heo
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Tejun Heo @ 2006-03-01 8:20 UTC (permalink / raw)
To: jgarzik, linux-ide, htejun
Hello, Jeff.
This is the second take of implement-and-use-ata_dev_revalidate
patchset. In the last take[1], out of four patches, %1 got ACK'ed, %2
had some minor issues, %3 got no comment and %4 had some issue but got
resolved.
Changes from the last take are...
* in #2, @verbose is renamed to @print_info as suggested
* in #2, lba_desc change is described in the patch description
This patchset is against
the current #upstream[2]
+ kill-illegal-kfree patch[3]
+ reorganize-ata_dev_identify patchset[4]
Thanks.
--
tejun
[1] http://article.gmane.org/gmane.linux.ide/8050
[2] cccc65a3b60edaf721cdee5a14f68ba009341822
[3] http://article.gmane.org/gmane.linux.ide/8324
[4] http://article.gmane.org/gmane.linux.ide/8412
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 4/4] libata: revalidate after transfer mode configuration 2006-03-01 8:20 [PATCHSET] libata: implement and use ata_dev_revalidate(), take #2 Tejun Heo @ 2006-03-01 8:20 ` Tejun Heo 2006-03-03 22:42 ` Jeff Garzik 2006-03-01 8:20 ` [PATCH 1/4] libata: re-initialize parameters before configuring Tejun Heo 2006-03-01 8:20 ` [PATCH 3/4] libata: implement ata_dev_revalidate() Tejun Heo 2 siblings, 1 reply; 8+ messages in thread From: Tejun Heo @ 2006-03-01 8:20 UTC (permalink / raw) To: jgarzik, linux-ide; +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(-) 05f0163669d505077e04f114027bea39083320bc diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d599e8f..d73109e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1621,6 +1621,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.2.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 4/4] libata: revalidate after transfer mode configuration 2006-03-01 8:20 ` [PATCH 4/4] libata: revalidate after transfer mode configuration Tejun Heo @ 2006-03-03 22:42 ` Jeff Garzik 0 siblings, 0 replies; 8+ messages in thread From: Jeff Garzik @ 2006-03-03 22:42 UTC (permalink / raw) To: Tejun Heo; +Cc: linux-ide Tejun Heo wrote: > Revalidate device after transfer mode configuration. This also makes > dev->id up-to-date. > > Signed-off-by: Tejun Heo <htejun@gmail.com> ACK 1, 2 and 4. ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/4] libata: re-initialize parameters before configuring 2006-03-01 8:20 [PATCHSET] libata: implement and use ata_dev_revalidate(), take #2 Tejun Heo 2006-03-01 8:20 ` [PATCH 4/4] libata: revalidate after transfer mode configuration Tejun Heo @ 2006-03-01 8:20 ` Tejun Heo 2006-03-01 8:20 ` [PATCH 3/4] libata: implement ata_dev_revalidate() Tejun Heo 2 siblings, 0 replies; 8+ messages in thread From: Tejun Heo @ 2006-03-01 8:20 UTC (permalink / raw) To: jgarzik, linux-ide; +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(-) ce0cef100691a38180b32a74ce6ab7ca90b390f0 diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 63ba1aa..17d113b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1082,6 +1082,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.2.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/4] libata: implement ata_dev_revalidate() 2006-03-01 8:20 [PATCHSET] libata: implement and use ata_dev_revalidate(), take #2 Tejun Heo 2006-03-01 8:20 ` [PATCH 4/4] libata: revalidate after transfer mode configuration Tejun Heo 2006-03-01 8:20 ` [PATCH 1/4] libata: re-initialize parameters before configuring Tejun Heo @ 2006-03-01 8:20 ` Tejun Heo 2006-03-03 22:39 ` Jeff Garzik 2 siblings, 1 reply; 8+ messages in thread From: Tejun Heo @ 2006-03-01 8:20 UTC (permalink / raw) To: jgarzik, linux-ide; +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 | 115 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 2 + 2 files changed, 117 insertions(+), 0 deletions(-) 5f157f520bce43bee189d18e0736065ce7997334 diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 64e087b..d599e8f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2341,6 +2341,120 @@ 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_id_c_string(old_id, model[0], ATA_ID_PROD_OFS, sizeof(model[0])); + ata_id_c_string(new_id, model[1], ATA_ID_PROD_OFS, sizeof(model[1])); + ata_id_c_string(old_id, serial[0], ATA_ID_SERNO_OFS, sizeof(serial[0])); + ata_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) { @@ -4960,6 +5074,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 1aab218..1392d22 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -485,6 +485,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.2.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 3/4] libata: implement ata_dev_revalidate() 2006-03-01 8:20 ` [PATCH 3/4] libata: implement ata_dev_revalidate() Tejun Heo @ 2006-03-03 22:39 ` Jeff Garzik 0 siblings, 0 replies; 8+ messages in thread From: Jeff Garzik @ 2006-03-03 22:39 UTC (permalink / raw) To: Tejun Heo; +Cc: linux-ide Tejun Heo wrote: > 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 | 115 ++++++++++++++++++++++++++++++++++++++++++++ > include/linux/libata.h | 2 + > 2 files changed, 117 insertions(+), 0 deletions(-) > > 5f157f520bce43bee189d18e0736065ce7997334 > diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c > index 64e087b..d599e8f 100644 > --- a/drivers/scsi/libata-core.c > +++ b/drivers/scsi/libata-core.c > @@ -2341,6 +2341,120 @@ 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_id_c_string(old_id, model[0], ATA_ID_PROD_OFS, sizeof(model[0])); > + ata_id_c_string(new_id, model[1], ATA_ID_PROD_OFS, sizeof(model[1])); > + ata_id_c_string(old_id, serial[0], ATA_ID_SERNO_OFS, sizeof(serial[0])); > + ata_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; For the hotplug case, its inaccurate to call these warnings. > + * 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; I would think the proper return value for this case is -ENODEV. Otherwise OK. Jeff ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCHSET] libata: implement and use ata_dev_revalidate(), take #3
@ 2006-03-05 8:55 Tejun Heo
2006-03-05 8:55 ` [PATCH 3/4] libata: implement ata_dev_revalidate() Tejun Heo
0 siblings, 1 reply; 8+ messages in thread
From: Tejun Heo @ 2006-03-05 8:55 UTC (permalink / raw)
To: jgarzik, linux-ide, htejun
Hello, Jeff.
This is the third take of implement-and-use-ata_dev_revalidate
patchset. In the last take[1], out of four patches, %1, %2 and %4 got
ACK'ed while %3 had some minor issues.
Changes from the last take are...
* in #3, ata_dev_same_device() tags mismatch messages with KERN_INFO
instead of KERN_WARNING.
* in #3, ata_dev_revalidate() returns -ENODEV instead of 0 if device
isn't present
Thanks.
--
tejun
[1] http://marc.theaimsgroup.com/?l=linux-ide&m=114120130020500&w=2
(gmane is down...)
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 3/4] libata: implement ata_dev_revalidate() 2006-03-05 8:55 [PATCHSET] libata: implement and use ata_dev_revalidate(), take #3 Tejun Heo @ 2006-03-05 8:55 ` Tejun Heo 0 siblings, 0 replies; 8+ messages in thread From: Tejun Heo @ 2006-03-05 8:55 UTC (permalink / raw) To: jgarzik, linux-ide; +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 | 115 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 2 + 2 files changed, 117 insertions(+), 0 deletions(-) 291782c65f9b708317c75869df3cbe58c36cb2b2 diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d65aa86..5d0adfa 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2345,6 +2345,120 @@ 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_INFO + "ata%u: dev %u class mismatch %d != %d\n", + ap->id, dev->devno, dev->class, new_class); + return 0; + } + + ata_id_c_string(old_id, model[0], ATA_ID_PROD_OFS, sizeof(model[0])); + ata_id_c_string(new_id, model[1], ATA_ID_PROD_OFS, sizeof(model[1])); + ata_id_c_string(old_id, serial[0], ATA_ID_SERNO_OFS, sizeof(serial[0])); + ata_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_INFO + "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_INFO + "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_INFO + "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 -ENODEV; + + 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) { @@ -4964,6 +5078,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 86a504f..66dce58 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -485,6 +485,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.2.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCHSET] libata: implement and use ata_dev_revalidate()
@ 2006-02-15 10:02 Tejun Heo
2006-02-15 10:02 ` [PATCH 3/4] libata: implement ata_dev_revalidate() Tejun Heo
0 siblings, 1 reply; 8+ messages in thread
From: Tejun Heo @ 2006-02-15 10:02 UTC (permalink / raw)
To: jgarzik, albertcc, linux-ide; +Cc: htejun
Hello, Jeff. Hello, Albert.
This patchset is the fourth and last part of divided 'reorganize
configuration and implement revalidation' patchset[1]. The third part
was posted about half an hour ago[2].
This patchset is against
the current upstream (254a5c45f8e53775a1e1dd7498a8dcd665341f1e)
+ rename ata_dev_id_[c_]string() patch [3]
+ reorganize ata_dev_identify() patchset [2]
Note: Jeff, I generated patches over the rename patch as the patch
make naming not only shorter but also more consistent. If you
don't like the rename, I'll regenerate this patchset without it.
This patchset implements ata_dev_revalidate() and use it after
configuring transfer mode.
Thanks.
--
tejun
[1] http://article.gmane.org/gmane.linux.ide/7632
[2] http://article.gmane.org/gmane.linux.ide/8048
[3] http://article.gmane.org/gmane.linux.ide/7997
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 3/4] libata: implement ata_dev_revalidate() 2006-02-15 10:02 [PATCHSET] libata: implement and use ata_dev_revalidate() Tejun Heo @ 2006-02-15 10:02 ` Tejun Heo 0 siblings, 0 replies; 8+ messages in thread From: Tejun Heo @ 2006-02-15 10:02 UTC (permalink / raw) To: jgarzik, albertcc, linux-ide; +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 | 115 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 2 + 2 files changed, 117 insertions(+), 0 deletions(-) 95213b21c681afd2eef1e5cbae21337208ac4c46 diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 05dadf5..54ed8fd 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2341,6 +2341,120 @@ 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_id_c_string(old_id, model[0], ATA_ID_PROD_OFS, sizeof(model[0])); + ata_id_c_string(new_id, model[1], ATA_ID_PROD_OFS, sizeof(model[1])); + ata_id_c_string(old_id, serial[0], ATA_ID_SERNO_OFS, sizeof(serial[0])); + ata_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) { @@ -4956,6 +5070,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 e8e02a0..81014be 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -485,6 +485,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.5 ^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2006-03-05 8:56 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2006-03-01 8:20 [PATCHSET] libata: implement and use ata_dev_revalidate(), take #2 Tejun Heo 2006-03-01 8:20 ` [PATCH 4/4] libata: revalidate after transfer mode configuration Tejun Heo 2006-03-03 22:42 ` Jeff Garzik 2006-03-01 8:20 ` [PATCH 1/4] libata: re-initialize parameters before configuring Tejun Heo 2006-03-01 8:20 ` [PATCH 3/4] libata: implement ata_dev_revalidate() Tejun Heo 2006-03-03 22:39 ` Jeff Garzik -- strict thread matches above, loose matches on Subject: below -- 2006-03-05 8:55 [PATCHSET] libata: implement and use ata_dev_revalidate(), take #3 Tejun Heo 2006-03-05 8:55 ` [PATCH 3/4] libata: implement ata_dev_revalidate() Tejun Heo 2006-02-15 10:02 [PATCHSET] libata: implement and use ata_dev_revalidate() Tejun Heo 2006-02-15 10:02 ` [PATCH 3/4] libata: implement ata_dev_revalidate() Tejun Heo
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).