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

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

libata: implement ata_timing_cycle2mode() and use it in libata-acpi and pata_acpi



libata-acpi is using separate timing tables for transfer modes
although libata-core has the complete ata_timing table.  Implement
ata_timing_cycle2mode() to look for matching mode given transfer type
and cycle duration and use it in libata-acpi and pata_acpi to replace
private timing tables.

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 5df91a25
Loading
Loading
Loading
Loading
+15 −47
Original line number Diff line number Diff line
@@ -441,22 +441,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
	return rc;
}

/* Welcome to ACPI, bring a bucket */
const unsigned int ata_acpi_pio_cycle[7] = {
	600, 383, 240, 180, 120, 100, 80
};
EXPORT_SYMBOL_GPL(ata_acpi_pio_cycle);

const unsigned int ata_acpi_mwdma_cycle[5] = {
	480, 150, 120, 100, 80
};
EXPORT_SYMBOL_GPL(ata_acpi_mwdma_cycle);

const unsigned int ata_acpi_udma_cycle[7] = {
	120, 80, 60, 45, 30, 20, 15
};
EXPORT_SYMBOL_GPL(ata_acpi_udma_cycle);

/**
 * ata_acpi_gtm_xfermode - determine xfermode from GTM parameter
 * @dev: target device
@@ -473,49 +457,33 @@ 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 xfer_mask = 0;
	unsigned int type;
	int unit;
	u8 mode;

	/* 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 */
	t = gtm->drive[unit].pio;
	for (i = 0; i < ARRAY_SIZE(ata_acpi_pio_cycle); i++)
		if (t > ata_acpi_pio_cycle[i])
			break;
	pio_mask = (1 << i) - 1;
	/* PIO */
	mode = ata_timing_cycle2mode(ATA_SHIFT_PIO, gtm->drive[unit].pio);
	xfer_mask |= ata_xfer_mode2mask(mode);

	/* 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.
	 */
	t = gtm->drive[unit].dma;
	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 < ARRAY_SIZE(ata_acpi_udma_cycle); i++)
			if (t > ata_acpi_udma_cycle[i])
				break;
		udma_mask = (1 << i) - 1;
	}
	if (!(gtm->flags & (1 << (2 * unit))))
		type = ATA_SHIFT_MWDMA;
	else
		type = ATA_SHIFT_UDMA;

	mode = ata_timing_cycle2mode(type, gtm->drive[unit].dma);
	xfer_mask |= ata_xfer_mode2mask(mode);

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

+52 −0
Original line number Diff line number Diff line
@@ -2902,6 +2902,57 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
	return 0;
}

/**
 *	ata_timing_cycle2mode - find xfer mode for the specified cycle duration
 *	@xfer_shift: ATA_SHIFT_* value for transfer type to examine.
 *	@cycle: cycle duration in ns
 *
 *	Return matching xfer mode for @cycle.  The returned mode is of
 *	the transfer type specified by @xfer_shift.  If @cycle is too
 *	slow for @xfer_shift, 0xff is returned.  If @cycle is faster
 *	than the fastest known mode, the fasted mode is returned.
 *
 *	LOCKING:
 *	None.
 *
 *	RETURNS:
 *	Matching xfer_mode, 0xff if no match found.
 */
u8 ata_timing_cycle2mode(unsigned int xfer_shift, int cycle)
{
	u8 base_mode = 0xff, last_mode = 0xff;
	const struct ata_xfer_ent *ent;
	const struct ata_timing *t;

	for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
		if (ent->shift == xfer_shift)
			base_mode = ent->base;

	for (t = ata_timing_find_mode(base_mode);
	     t && ata_xfer_mode2shift(t->mode) == xfer_shift; t++) {
		unsigned short this_cycle;

		switch (xfer_shift) {
		case ATA_SHIFT_PIO:
		case ATA_SHIFT_MWDMA:
			this_cycle = t->cycle;
			break;
		case ATA_SHIFT_UDMA:
			this_cycle = t->udma;
			break;
		default:
			return 0xff;
		}

		if (cycle > this_cycle)
			break;

		last_mode = t->mode;
	}

	return last_mode;
}

/**
 *	ata_down_xfermask_limit - adjust dev xfer masks downward
 *	@dev: Device to adjust xfer masks
@@ -7630,6 +7681,7 @@ EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
EXPORT_SYMBOL_GPL(ata_timing_find_mode);
EXPORT_SYMBOL_GPL(ata_timing_compute);
EXPORT_SYMBOL_GPL(ata_timing_merge);
EXPORT_SYMBOL_GPL(ata_timing_cycle2mode);

#ifdef CONFIG_PCI
EXPORT_SYMBOL_GPL(pci_test_config_bits);
+7 −6
Original line number Diff line number Diff line
@@ -133,13 +133,14 @@ static void pacpi_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
	int unit = adev->devno;
	struct pata_acpi *acpi = ap->private_data;
	const struct ata_timing *t;

	if (!(acpi->gtm.flags & 0x10))
		unit = 0;

	/* Now stuff the nS values into the structure */
	acpi->gtm.drive[unit].pio =
		ata_acpi_pio_cycle[adev->pio_mode - XFER_PIO_0];
	t = ata_timing_find_mode(adev->pio_mode);
	acpi->gtm.drive[unit].pio = t->cycle;
	ata_acpi_stm(ap, &acpi->gtm);
	/* See what mode we actually got */
	ata_acpi_gtm(ap, &acpi->gtm);
@@ -155,18 +156,18 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
	int unit = adev->devno;
	struct pata_acpi *acpi = ap->private_data;
	const struct ata_timing *t;

	if (!(acpi->gtm.flags & 0x10))
		unit = 0;

	/* Now stuff the nS values into the structure */
	t = ata_timing_find_mode(adev->dma_mode);
	if (adev->dma_mode >= XFER_UDMA_0) {
		acpi->gtm.drive[unit].dma =
			ata_acpi_udma_cycle[adev->dma_mode - XFER_UDMA_0];
		acpi->gtm.drive[unit].dma = t->udma;
		acpi->gtm.flags |= (1 << (2 * unit));
	} else {
		acpi->gtm.drive[unit].dma =
			ata_acpi_mwdma_cycle[adev->dma_mode - XFER_MW_DMA_0];
		acpi->gtm.drive[unit].dma = t->cycle;
		acpi->gtm.flags &= ~(1 << (2 * unit));
	}
	ata_acpi_stm(ap, &acpi->gtm);
+1 −4
Original line number Diff line number Diff line
@@ -941,6 +941,7 @@ extern int ata_timing_compute(struct ata_device *, unsigned short,
extern void ata_timing_merge(const struct ata_timing *,
			     const struct ata_timing *, struct ata_timing *,
			     unsigned int);
extern u8 ata_timing_cycle2mode(unsigned int xfer_shift, int cycle);

enum {
	ATA_TIMING_SETUP	= (1 << 0),
@@ -961,10 +962,6 @@ enum {

/* libata-acpi.c */
#ifdef CONFIG_ATA_ACPI
extern const unsigned int ata_acpi_pio_cycle[7];
extern const unsigned int ata_acpi_mwdma_cycle[5];
extern const unsigned int ata_acpi_udma_cycle[7];

static inline const struct ata_acpi_gtm *ata_acpi_init_gtm(struct ata_port *ap)
{
	if (ap->pflags & ATA_PFLAG_INIT_GTM_VALID)