Commit dcd03447 authored by Akira Iguchi's avatar Akira Iguchi Committed by Jeff Garzik
Browse files

pata_scc.c: small fixes (Workaround for errata A308)



This patch fixes some issues of the previous patch:
- Use mode_filter() hook to limit ATAPI UDMA mode
- "data loss" warning message
- handling of udma_mask

Signed-off-by: default avatarKou Ishizaki <kou.ishizaki@toshiba.co.jp>
Signed-off-by: default avatarAkira Iguchi <akira2.iguchi@toshiba.co.jp>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 028a2596
Loading
Loading
Loading
Loading
+16 −11
Original line number Diff line number Diff line
@@ -238,12 +238,6 @@ static void scc_set_dmamode (struct ata_port *ap, struct ata_device *adev)
	else
		offset = 0;	/* 100MHz */

	/* errata A308 workaround: limit ATAPI UDMA mode to UDMA4 */
	if (adev->class == ATA_DEV_ATAPI && speed > XFER_UDMA_4) {
		printk(KERN_INFO "%s: limit ATAPI UDMA to UDMA4\n", DRV_NAME);
		speed = XFER_UDMA_4;
	}

	if (speed >= XFER_UDMA_0)
		idx = speed - XFER_UDMA_0;
	else
@@ -264,6 +258,17 @@ static void scc_set_dmamode (struct ata_port *ap, struct ata_device *adev)
		 JCTSStbl[offset][idx] << 16 | JCENVTtbl[offset][idx]);
}

unsigned long scc_mode_filter(struct ata_device *adev, unsigned long mask)
{
	/* errata A308 workaround: limit ATAPI UDMA mode to UDMA4 */
	if (adev->class == ATA_DEV_ATAPI &&
	    (mask & (0xE0 << ATA_SHIFT_UDMA))) {
		printk(KERN_INFO "%s: limit ATAPI UDMA to UDMA4\n", DRV_NAME);
		mask &= ~(0xE0 << ATA_SHIFT_UDMA);
	}
	return ata_pci_default_filter(adev, mask);
}

/**
 *	scc_tf_load - send taskfile registers to host controller
 *	@ap: Port to which output is sent
@@ -741,7 +746,7 @@ static u8 scc_bmdma_status (struct ata_port *ap)
		return host_stat;

	/* errata A252,A308 workaround: Step4 */
	if (ata_altstatus(ap) & ATA_ERR && int_status & INTSTS_INTRQ)
	if ((ata_altstatus(ap) & ATA_ERR) && (int_status & INTSTS_INTRQ))
		return (host_stat | ATA_DMA_INTR);

	/* errata A308 workaround Step5 */
@@ -752,11 +757,11 @@ static u8 scc_bmdma_status (struct ata_port *ap)
		if ((qc->tf.protocol == ATA_PROT_DMA &&
		     qc->dev->xfer_mode > XFER_UDMA_4)) {
			if (!(int_status & INTSTS_ACTEINT)) {
				printk(KERN_WARNING "ata%u: data lost occurred. (ACTEINT==0, retry:%d)\n",
				       ap->print_id, retry);
				printk(KERN_WARNING "ata%u: operation failed (transfer data loss)\n",
				       ap->print_id);
				host_stat |= ATA_DMA_ERR;
				if (retry++)
					ap->udma_mask >>= 1;
					ap->udma_mask &= ~(1 << qc->dev->xfer_mode);
			} else
				retry = 0;
		}
@@ -1016,7 +1021,7 @@ static const struct ata_port_operations scc_pata_ops = {
	.port_disable		= ata_port_disable,
	.set_piomode		= scc_set_piomode,
	.set_dmamode		= scc_set_dmamode,
	.mode_filter		= ata_pci_default_filter,
	.mode_filter		= scc_mode_filter,

	.tf_load		= scc_tf_load,
	.tf_read		= scc_tf_read,