libata: allow LLDs w/o any reset method
PATCH 1/2 libata: allow LLDs w/o any reset method
Some old SFF controllers don't have any way to reset the channel. Currently, this isn't supported and libata EH causes an oops. Allow LLDs w/o any reset method and just assume ATA class in such cases.
--- drivers/ata/libata-eh.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/ata/libata-eh.c +10 -0
@@ -2150,6 +2150,15 @@ int ata_eh_reset(struct ata_link *link, ap->ops->set_piomode (ap, dev); } +if (!softreset && !hardreset) { +if (verbose) +ata_link_printk (link,KERN_INFO ,"no reset method " +"available, skipping reset\n" ); +if (!(lflags &ATA_LFLAG_ASSUME_CLASS )) + lflags |=ATA_LFLAG_ASSUME_ATA ; + goto done; + } +/* Determine which reset to use and record in ehc->i.action. * prereset() may examine and modify it. */
@@ -2254,6 +2263,7 @@ int ata_eh_reset(struct ata_link *link, lflags |=ATA_LFLAG_ASSUME_ATA ; } + done:ata_link_for_each_dev (dev, link) {/* After the reset, the device state is PIO 0 and the * controller state is undefined. Reset also wakes up
PATCH 2/2 libata-sff: handle controllers w/o ctl register
SFF incorrectly assumed that ctl register is available for all controllers while some old SFF controllers don't have ctl register. Make SFF handle controllers w/o ctl register by conditionalizing ctl register access and softreset method.
--- drivers/ata/libata-sff.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-)
drivers/ata/libata-sff.c +22 -14
@@ -56,7 +56,8 @@ u8 ata_irq_on(struct ata_port *ap) ap->ctl &= ~ATA_NIEN ; ap->last_ctl = ap->ctl; -iowrite8 (ap->ctl, ioaddr->ctl_addr); +if (ioaddr->ctl_addr) +iowrite8 (ap->ctl, ioaddr->ctl_addr); tmp =ata_wait_idle (ap); ap->ops->irq_clear (ap);
@@ -81,12 +82,14 @@ void ata_tf_load(struct ata_port *ap, counsigned int is_addr = tf->flags &ATA_TFLAG_ISADDR ;if (tf->ctl != ap->last_ctl) { -iowrite8 (tf->ctl, ioaddr->ctl_addr); +if (ioaddr->ctl_addr) +iowrite8 (tf->ctl, ioaddr->ctl_addr); ap->last_ctl = tf->ctl;ata_wait_idle (ap); }if (is_addr && (tf->flags &ATA_TFLAG_LBA48 )) { +WARN_ON (!ioaddr->ctl_addr);iowrite8 (tf->hob_feature, ioaddr->feature_addr);iowrite8 (tf->hob_nsect, ioaddr->nsect_addr);iowrite8 (tf->hob_lbal, ioaddr->lbal_addr);
@@ -167,14 +170,17 @@ void ata_tf_read(struct ata_port *ap, st tf->device =ioread8 (ioaddr->device_addr);if (tf->flags &ATA_TFLAG_LBA48 ) { -iowrite8 (tf->ctl |ATA_HOB , ioaddr->ctl_addr); - tf->hob_feature =ioread8 (ioaddr->error_addr); - tf->hob_nsect =ioread8 (ioaddr->nsect_addr); - tf->hob_lbal =ioread8 (ioaddr->lbal_addr); - tf->hob_lbam =ioread8 (ioaddr->lbam_addr); - tf->hob_lbah =ioread8 (ioaddr->lbah_addr); -iowrite8 (tf->ctl, ioaddr->ctl_addr); - ap->last_ctl = tf->ctl; +if (likely (ioaddr->ctl_addr)) { +iowrite8 (tf->ctl |ATA_HOB , ioaddr->ctl_addr); + tf->hob_feature =ioread8 (ioaddr->error_addr); + tf->hob_nsect =ioread8 (ioaddr->nsect_addr); + tf->hob_lbal =ioread8 (ioaddr->lbal_addr); + tf->hob_lbam =ioread8 (ioaddr->lbam_addr); + tf->hob_lbah =ioread8 (ioaddr->lbah_addr); +iowrite8 (tf->ctl, ioaddr->ctl_addr); + ap->last_ctl = tf->ctl; + }else +WARN_ON (1 ); } }
@@ -352,7 +358,8 @@ void ata_bmdma_freeze(struct ata_port *a ap->ctl |=ATA_NIEN ; ap->last_ctl = ap->ctl; -iowrite8 (ap->ctl, ioaddr->ctl_addr); +if (ioaddr->ctl_addr) +iowrite8 (ap->ctl, ioaddr->ctl_addr);/* Under certain circumstances, some controllers raise IRQ on * ATA_NIEN manipulation. Also, many controllers fail to mask
@@ -459,13 +466,14 @@ void ata_bmdma_drive_eh(struct ata_port*/ void ata_bmdma_error_handler (struct ata_port *ap) { -ata_reset_fn_t hardreset; +ata_reset_fn_t softreset =NULL , hardreset =NULL ; - hardreset =NULL ; +if (ap->ioaddr.ctl_addr) + softreset = ata_std_softreset;if (sata_scr_valid (&ap->link)) hardreset = sata_std_hardreset; -ata_bmdma_drive_eh (ap, ata_std_prereset, ata_std_softreset, hardreset, +ata_bmdma_drive_eh (ap, ata_std_prereset, softreset, hardreset, ata_std_postreset); }
Quoted 3 lines · Tejun Heo
Some old SFF controllers don't have any way to reset the channel. Currently, this isn't supported and libata EH causes an oops. Allow LLDs w/o any reset method and just assume ATA class in such cases.
just to make sure, this is a must-have for 2.6.25 - it causes a boot regression on one of my boxes.
Ingo
Quoted 9 lines · Tejun Heo
Some old SFF controllers don't have any way to reset the channel. Currently, this isn't supported and libata EH causes an oops. Allow LLDs w/o any reset method and just assume ATA class in such cases.
Signed-off-by Tejun Heo <[email protected]>Signed-off-by Ingo Molnar <[email protected]>--- drivers/ata/libata-eh.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
applied 1-2
BTW, nice work on patch #2 (make ctl optional). That removed a stumbling block preventing support for a few esoteric platform IDE drivers.
Jeff