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

Commit 5df91a25 authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik
Browse files

libata: fix ata_acpi_gtm_xfermask()



ata_acpi_gtm_xfermask() as separated out from pacpi_discover_modes()
has various bugs.  Fix them.

* The wrong comparison operator is used when finding for matching
  cycle resulting totally bogus result.

* With the comparion operator fixed, boundary condtion handling is
  clumsy.

* Setting of any DMA mask bit set all bits in PIO mask.

* MWDMA and UDMA blocks are swapped.

Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 7c77fa4d
Loading
Loading
Loading
Loading
+21 −21
Original line number Diff line number Diff line
@@ -473,49 +473,49 @@ EXPORT_SYMBOL_GPL(ata_acpi_udma_cycle);
unsigned long ata_acpi_gtm_xfermask(struct ata_device *dev,
				    const struct ata_acpi_gtm *gtm)
{
	unsigned long pio_mask = 0, mwdma_mask = 0, udma_mask = 0;
	int unit, i;
	u32 t;
	unsigned long mask = (0x7f << ATA_SHIFT_UDMA) | (0x7 << ATA_SHIFT_MWDMA) | (0x1F << ATA_SHIFT_PIO);

	/* we always use the 0 slot for crap hardware */
	unit = dev->devno;
	if (!(gtm->flags & 0x10))
		unit = 0;

	/* Values larger than the longest cycle results in 0 mask
	 * while values equal to smaller than the shortest cycle
	 * results in mask which includes all supported modes.
	 * Disabled transfer method has the value of 0xffffffff which
	 * will always result in 0 mask.
	 */

	/* start by scanning for PIO modes */
	for (i = 0; i < 7; i++) {
	t = gtm->drive[unit].pio;
		if (t <= ata_acpi_pio_cycle[i]) {
			mask |= (2 << (ATA_SHIFT_PIO + i)) - 1;
	for (i = 0; i < ARRAY_SIZE(ata_acpi_pio_cycle); i++)
		if (t > ata_acpi_pio_cycle[i])
			break;
		}
	}
	pio_mask = (1 << i) - 1;

	/* See if we have MWDMA or UDMA data. We don't bother with
	 * MWDMA if UDMA is available as this means the BIOS set UDMA
	 * and our error changedown if it works is UDMA to PIO anyway.
	 */
	if (gtm->flags & (1 << (2 * unit))) {
		/* MWDMA */
		for (i = 0; i < 5; i++) {
	t = gtm->drive[unit].dma;
			if (t <= ata_acpi_mwdma_cycle[i]) {
				mask |= (2 << (ATA_SHIFT_MWDMA + i)) - 1;
	if (!(gtm->flags & (1 << (2 * unit)))) {
		/* MWDMA */
		for (i = 0; i < ARRAY_SIZE(ata_acpi_mwdma_cycle); i++)
			if (t > ata_acpi_mwdma_cycle[i])
				break;
			}
		}
		mwdma_mask = (1 << i) - 1;
	} else {
		/* UDMA */
		for (i = 0; i < 7; i++) {
			t = gtm->drive[unit].dma;
			if (t <= ata_acpi_udma_cycle[i]) {
				mask |= (2 << (ATA_SHIFT_UDMA + i)) - 1;
		for (i = 0; i < ARRAY_SIZE(ata_acpi_udma_cycle); i++)
			if (t > ata_acpi_udma_cycle[i])
				break;
			}
		}
		udma_mask = (1 << i) - 1;
	}

	return mask;
	return ata_pack_xfermask(pio_mask, mwdma_mask, udma_mask);
}
EXPORT_SYMBOL_GPL(ata_acpi_gtm_xfermask);