Mark Lord wrote: > Tejun Heo wrote: >> .. >> Then, PACKET_IDENTIFY after configuring transfer mode fails with >> -ENOENT. Meaning it saw (status & (ATA_BUSY|ATA_DRQ|ATA_ERR|ATA_DF)) == >> 0 in HSM_ST. > .. >> So, PATA gurus, can you bless us with enlightenment? :-) > > Heh.. guaranteeing detection of all the strange implementations out there > is part black magic. > > But the simple thing to do here is, just for fun, hack the code > to do the infamous 50 millisecond hard wait before issuing the > PACKET_IDENTIFY. > If that fixes it, then it's just a matter of tuning to discover the real > amount of delay required, and a nicer way of doing the delay. Okay. > Also, zero out the features register before issuing PACKET_IDENTIFY, > if the code isn't already doing that. Okay. > After the drive asserts BUSY, and later deasserts BUSY, > there might be a slight delay before the drive asserts DRQ. > So, it is possible for the status to read zeros in the important bits. > > My suggestion is to wait up to the infamous 50 milliseconds again here, > if needed. Okay, the attached patch does what Mark suggested. Art, can you please give it a shot and report dmesg? My thanks for sticking around till now. -- tejun
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 667acd2..4c81433 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1478,7 +1478,8 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, } tf.protocol = ATA_PROT_PIO; - tf.flags |= ATA_TFLAG_POLLING; /* for polling presence detection */ + /* POLLING for polling detection, ISADDR|DEVICE to clear TF */ + tf.flags |= ATA_TFLAG_POLLING | ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, id, sizeof(id[0]) * ATA_ID_WORDS); @@ -4477,6 +4478,18 @@ fsm_start: goto fsm_start; } else { + unsigned long timeout = jiffies + msecs_to_jiffies(50); + + while (time_before(jiffies, timeout)) { + if (status & ATA_DRQ) + break; + ata_dev_printk(qc->dev, KERN_INFO, + "XXX: waiting for DRQ, status=0x%x\n", + status); + msleep(10); + status = ata_chk_status(ap); + } + /* ATA PIO protocol */ if (unlikely((status & ATA_DRQ) == 0)) { /* handle BSY=0, DRQ=0 as error */