Commit b03e66a6 authored by David Milburn's avatar David Milburn Committed by Jeff Garzik
Browse files

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: default avatarDavid Milburn <dmilburn@redhat.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent cd705d5a
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -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,