* Re: [PATCH 3/7] libata: separate out ata_dev_read_id()
[not found] <1139995449455-git-send-email-htejun@gmail.com>
@ 2006-02-20 10:35 ` Jeff Garzik
2006-02-20 15:04 ` Tejun Heo
0 siblings, 1 reply; 2+ messages in thread
From: Jeff Garzik @ 2006-02-20 10:35 UTC (permalink / raw)
To: Tejun Heo; +Cc: albertcc, linux-ide
Tejun Heo wrote:
> Separate out ata_dev_read_id() from ata_dev_identify(). This is the
> first half of splitting ata_dev_identify(). ata_dev_read_id() will
> also be used for revalidation. This patch does not make any behavior
> change.
>
> ata_dev_read_id() doesn't modify any of libata-internal data
> structures. It simply reads IDENTIFY page and returns error code on
> failure. INIT_DEV_PARAMS and EDD wrong class code are also handled by
> this function.
>
> Re-reading IDENTIFY after INIT_DEV_PARAMS is performed by jumping to
> retry: instead of calling ata_dev_reread_id(). This is done because
> 1. there's retry label anyway 2. ata_dev_reread_id() cannot be used
> anywhere else so there's no reason to keep it.
>
> 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?
>
> Signed-off-by: Tejun Heo <htejun@gmail.com>
>
> ---
>
> drivers/scsi/libata-core.c | 219 +++++++++++++++++++++++++++-----------------
> 1 files changed, 135 insertions(+), 84 deletions(-)
>
> 44fd0f6a248de6216af9ee63ee1ccb2bb438bf7b
> diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
> index a435454..6de78d1 100644
> --- a/drivers/scsi/libata-core.c
> +++ b/drivers/scsi/libata-core.c
> @@ -903,42 +903,37 @@ unsigned int ata_pio_need_iordy(const st
> }
>
> /**
> - * ata_dev_identify - obtain IDENTIFY x DEVICE page
> - * @ap: port on which device we wish to probe resides
> - * @device: device bus address, starting at zero
> - *
> - * Following bus reset, we issue the IDENTIFY [PACKET] DEVICE
> - * command, and read back the 512-byte device information page.
> - * The device information page is fed to us via the standard
> - * PIO-IN protocol, but we hand-code it here. (TODO: investigate
> - * using standard PIO-IN paths)
> - *
> - * After reading the device information page, we use several
> - * bits of information from it to initialize data structures
> - * that will be used during the lifetime of the ata_device.
> - * Other data from the info page is used to disqualify certain
> - * older ATA devices we do not wish to support.
> + * ata_dev_read_id - Read ID data from the specified device
> + * @ap: port on which target device resides
> + * @dev: target device
> + * @p_class: pointer to class of the target device (may be changed)
> + * @post_reset: is this read ID post-reset?
> + * @p_id: read IDENTIFY page (newly allocated)
> + *
> + * Read ID data from the specified device. ATA_CMD_ID_ATA is
> + * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI
> + * devices. This function also takes care of EDD signature
> + * misreporting (to be removed once EDD support is gone) and
> + * issues ATA_CMD_INIT_DEV_PARAMS for pre-ATA4 drives.
> *
> * LOCKING:
> - * Inherited from caller. Some functions called by this function
> - * obtain the host_set lock.
> + * Kernel thread context (may sleep)
> + *
> + * RETURNS:
> + * 0 on success, -errno otherwise.
> */
> -
> -static void ata_dev_identify(struct ata_port *ap, unsigned int device)
> +static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
> + unsigned int *p_class, int post_reset, u16 **p_id)
> {
> - struct ata_device *dev = &ap->device[device];
> - unsigned int major_version;
> - unsigned long xfer_modes;
> + unsigned int class = *p_class;
> unsigned int using_edd;
> struct ata_taskfile tf;
> - unsigned int err_mask;
> - int i, rc;
> + unsigned int err_mask = 0;
> + u16 *id;
> + const char *reason;
> + int rc;
>
> - if (!ata_dev_present(dev)) {
> - DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n",
> - ap->id, device);
> - return;
> - }
> + DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno);
>
> if (ap->ops->probe_reset ||
> ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET))
> @@ -946,34 +941,40 @@ static void ata_dev_identify(struct ata_
> else
> using_edd = 1;
>
> - DPRINTK("ENTER, host %u, dev %u\n", ap->id, device);
> -
> - WARN_ON(dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ATAPI &&
> - dev->class != ATA_DEV_NONE);
> + ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
>
> - 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)
> + id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL);
> + if (id == NULL) {
> + rc = -ENOMEM;
> + reason = "out of memory";
> goto err_out;
> + }
>
> -retry:
> - ata_tf_init(ap, &tf, device);
> + retry:
> + ata_tf_init(ap, &tf, dev->devno);
>
> - if (dev->class == ATA_DEV_ATA) {
> + switch (class) {
> + case ATA_DEV_ATA:
> tf.command = ATA_CMD_ID_ATA;
> - DPRINTK("do ATA identify\n");
> - } else {
> + break;
> + case ATA_DEV_ATAPI:
> tf.command = ATA_CMD_ID_ATAPI;
> - DPRINTK("do ATAPI identify\n");
> + break;
> + default:
> + rc = -ENODEV;
> + reason = "unsupported class";
> + goto err_out;
> }
>
> tf.protocol = ATA_PROT_PIO;
>
> err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
> - dev->id, sizeof(dev->id[0]) * ATA_ID_WORDS);
> + id, sizeof(id[0]) * ATA_ID_WORDS);
>
> if (err_mask) {
> + rc = -EIO;
> + reason = "I/O error";
> +
> if (err_mask & ~AC_ERR_DEV)
> goto err_out;
>
> @@ -988,25 +989,106 @@ retry:
> * ATA software reset (SRST, the default) does not appear
> * to have this problem.
> */
> - if ((using_edd) && (dev->class == ATA_DEV_ATA)) {
> + if ((using_edd) && (class == ATA_DEV_ATA)) {
> u8 err = tf.feature;
> if (err & ATA_ABORTED) {
> - dev->class = ATA_DEV_ATAPI;
> + class = ATA_DEV_ATAPI;
> goto retry;
> }
> }
> goto err_out;
> }
>
> - swap_buf_le16(dev->id, ATA_ID_WORDS);
> + swap_buf_le16(id, ATA_ID_WORDS);
>
> /* print device capabilities */
> printk(KERN_DEBUG "ata%u: dev %u cfg "
> "49:%04x 82:%04x 83:%04x 84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n",
> - ap->id, device, dev->id[49],
> - dev->id[82], dev->id[83], dev->id[84],
> - dev->id[85], dev->id[86], dev->id[87],
> - dev->id[88]);
> + ap->id, dev->devno,
> + id[49], id[82], id[83], id[84], id[85], id[86], id[87], id[88]);
> +
> + /* sanity check */
> + if ((class == ATA_DEV_ATA) != ata_id_is_ata(id)) {
> + rc = -EINVAL;
> + reason = "device reports illegal type";
> + goto err_out;
> + }
> +
> + if (post_reset && class == ATA_DEV_ATA) {
> + /*
> + * The exact sequence expected by certain pre-ATA4 drives is:
> + * SRST RESET
> + * IDENTIFY
> + * INITIALIZE DEVICE PARAMETERS
> + * anything else..
> + * Some drives were very specific about that exact sequence.
> + */
> + if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
> + err_mask = ata_dev_init_params(ap, dev);
> + if (err_mask) {
> + rc = -EIO;
> + reason = "INIT_DEV_PARAMS failed";
> + goto err_out;
> + }
> +
> + /* current CHS translation info (id[53-58]) might be
> + * changed. reread the identify device info.
> + */
> + post_reset = 0;
> + goto retry;
> + }
> + }
> +
> + *p_class = class;
> + *p_id = id;
> + return 0;
I think you should order this patch before the dev->id[0] reworked patch.
In particular, "p_id = id" appears to stomp on the existing dev->id
allocation.
Jeff
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH 3/7] libata: separate out ata_dev_read_id()
2006-02-20 10:35 ` [PATCH 3/7] libata: separate out ata_dev_read_id() Jeff Garzik
@ 2006-02-20 15:04 ` Tejun Heo
0 siblings, 0 replies; 2+ messages in thread
From: Tejun Heo @ 2006-02-20 15:04 UTC (permalink / raw)
To: Jeff Garzik; +Cc: albertcc, linux-ide
Jeff Garzik wrote:
> Tejun Heo wrote:
>
>> Separate out ata_dev_read_id() from ata_dev_identify(). This is the
>> first half of splitting ata_dev_identify(). ata_dev_read_id() will
>> also be used for revalidation. This patch does not make any behavior
>> change.
>>
>> ata_dev_read_id() doesn't modify any of libata-internal data
>> structures. It simply reads IDENTIFY page and returns error code on
>> failure. INIT_DEV_PARAMS and EDD wrong class code are also handled by
>> this function.
>>
>> Re-reading IDENTIFY after INIT_DEV_PARAMS is performed by jumping to
>> retry: instead of calling ata_dev_reread_id(). This is done because
>> 1. there's retry label anyway 2. ata_dev_reread_id() cannot be used
>> anywhere else so there's no reason to keep it.
>>
>> 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?
>>
>> Signed-off-by: Tejun Heo <htejun@gmail.com>
>>
>
> I think you should order this patch before the dev->id[0] reworked patch.
Will do.
> In particular, "p_id = id" appears to stomp on the existing dev->id
> allocation.
Hmmm... ata_dev_read_id() is responsible for allocating id array and the
caller is responsible for making sure what p_id points to is
deallocated. e.g. ata_dev_revalidate() frees dev->id before passing it
to ata_dev_read_id(). Seems problemetic?
--
tejun
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2006-02-20 15:04 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1139995449455-git-send-email-htejun@gmail.com>
2006-02-20 10:35 ` [PATCH 3/7] libata: separate out ata_dev_read_id() Jeff Garzik
2006-02-20 15:04 ` 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).