diff options
| author | David Milburn <dmilburn@redhat.com> | 2012-10-29 18:00:22 -0500 | 
|---|---|---|
| committer | Jeff Garzik <jgarzik@redhat.com> | 2012-11-15 23:54:41 -0500 | 
| commit | b03e66a6be91f8389fcd902ab6c1563db1c9c06b (patch) | |
| tree | 97049500a3dd0fd3c7c7801d5f6a697b006f1fb1 | |
| parent | cd705d5ad49bb8894dda2726dcaef8f63ddeba43 (diff) | |
sata_svw: check DMA start bit before reset
If kdump is triggered with pending IO, controller may not respond causing
kdump to fail.
http://marc.info/?l=linux-ide&m=133032255424658&w=2
During error recovery ata_do_dev_read_id never completes due hang
in mmio_insw.
ata_do_dev_read_id
 ata_sff_data_xfer
  ioread16_rep
   mmio_insw
if DMA start bit is cleared before reset, PIO command is successful
and kdump succeeds.
Signed-off-by: David Milburn <dmilburn@redhat.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
| -rw-r--r-- | drivers/ata/sata_svw.c | 35 | 
1 files changed, 35 insertions, 0 deletions
| diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index 44a4256533e1..08608de87e4e 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -142,6 +142,39 @@ static int k2_sata_scr_write(struct ata_link *link,  	return 0;  } +static int k2_sata_softreset(struct ata_link *link, +			     unsigned int *class, unsigned long deadline) +{ +	u8 dmactl; +	void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + +	dmactl = readb(mmio + ATA_DMA_CMD); + +	/* Clear the start bit */ +	if (dmactl & ATA_DMA_START) { +		dmactl &= ~ATA_DMA_START; +		writeb(dmactl, mmio + ATA_DMA_CMD); +	} + +	return ata_sff_softreset(link, class, deadline); +} + +static int k2_sata_hardreset(struct ata_link *link, +			     unsigned int *class, unsigned long deadline) +{ +	u8 dmactl; +	void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + +	dmactl = readb(mmio + ATA_DMA_CMD); + +	/* Clear the start bit */ +	if (dmactl & ATA_DMA_START) { +		dmactl &= ~ATA_DMA_START; +		writeb(dmactl, mmio + ATA_DMA_CMD); +	} + +	return sata_sff_hardreset(link, class, deadline); +}  static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)  { @@ -346,6 +379,8 @@ static struct scsi_host_template k2_sata_sht = {  static struct ata_port_operations k2_sata_ops = {  	.inherits		= &ata_bmdma_port_ops, +	.softreset              = k2_sata_softreset, +	.hardreset              = k2_sata_hardreset,  	.sff_tf_load		= k2_sata_tf_load,  	.sff_tf_read		= k2_sata_tf_read,  	.sff_check_status	= k2_stat_check_status, | 
