Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b15b3eba authored by Alan Cox's avatar Alan Cox Committed by Jeff Garzik
Browse files

libata: Fix a large collection of DMA mode mismatches



Dave Müller sent a diff for the pata_oldpiix that highlighted a problem
where a lot of the ATA drivers assume dma_mode == 0 means "no DMA" while
the core code uses 0xFF.

This turns out to have other consequences such as code doing >= XFER_UDMA_0
also catching 0xFF as UDMAlots. Fortunately it doesn't generally affect
set_dma_mode, although some drivers call back into their own set mode code
from other points.

Having been through the drivers I've added helpers for using_udma/using_mwdma
dma_enabled so that people don't open code ranges that may change (eg if UDMA8
appears somewhere)

Thanks to David for the initial bits
[and added fix for pata_oldpiix from and signed-off-by Dave Mueller
 <dave.mueller@gmx.ch>  -jg]

Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 20e2de4a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -3288,7 +3288,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
		dev->dma_mode = ata_xfer_mask2mode(dma_mask);

		found = 1;
		if (dev->dma_mode != 0xff)
		if (ata_dma_enabled(dev))
			used_dma = 1;
	}
	if (!found)
@@ -3313,7 +3313,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)

	/* step 3: set host DMA timings */
	ata_link_for_each_dev(dev, link) {
		if (!ata_dev_enabled(dev) || dev->dma_mode == 0xff)
		if (!ata_dev_enabled(dev) || !ata_dma_enabled(dev))
			continue;

		dev->xfer_mode = dev->dma_mode;
+1 −1
Original line number Diff line number Diff line
@@ -181,7 +181,7 @@ static unsigned int pacpi_qc_issue(struct ata_queued_cmd *qc)

	if (adev != acpi->last) {
		pacpi_set_piomode(ap, adev);
		if (adev->dma_mode)
		if (ata_dma_enabled(adev))
			pacpi_set_dmamode(ap, adev);
		acpi->last = adev;
	}
+1 −1
Original line number Diff line number Diff line
@@ -183,7 +183,7 @@ static void atiixp_bmdma_start(struct ata_queued_cmd *qc)
	u16 tmp16;

	pci_read_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
	if (adev->dma_mode >= XFER_UDMA_0)
	if (ata_using_udma(adev))
		tmp16 |= (1 << dn);
	else
		tmp16 &= ~(1 << dn);
+3 −3
Original line number Diff line number Diff line
@@ -149,10 +149,10 @@ static unsigned int cs5530_qc_issue(struct ata_queued_cmd *qc)
	struct ata_device *prev = ap->private_data;

	/* See if the DMA settings could be wrong */
	if (adev->dma_mode != 0 && adev != prev && prev != NULL) {
	if (ata_dma_enabled(adev) && adev != prev && prev != NULL) {
		/* Maybe, but do the channels match MWDMA/UDMA ? */
		if ((adev->dma_mode >= XFER_UDMA_0 && prev->dma_mode < XFER_UDMA_0) ||
		    (adev->dma_mode < XFER_UDMA_0 && prev->dma_mode >= XFER_UDMA_0))
		if ((ata_using_udma(adev) && !ata_using_udma(prev)) ||
		    (ata_using_udma(prev) && !ata_using_udma(adev)))
		    	/* Switch the mode bits */
		    	cs5530_set_dmamode(ap, adev);
	}
+1 −1
Original line number Diff line number Diff line
@@ -198,7 +198,7 @@ static unsigned int oldpiix_qc_issue(struct ata_queued_cmd *qc)

	if (adev != ap->private_data) {
		oldpiix_set_piomode(ap, adev);
		if (adev->dma_mode)
		if (ata_dma_enabled(adev))
			oldpiix_set_dmamode(ap, adev);
	}
	return ata_sff_qc_issue(qc);
Loading