ata: separate PATA timings code from libata-core.c
Separate PATA timings code from libata-core.c: * add PATA_TIMINGS config option and make corresponding PATA host drivers (and ATA ACPI code) select it * move following PATA timings code to libata-pata-timings.c: - ata_timing_quantize() - ata_timing_merge() - ata_timing_find_mode() - ata_timing_compute() * group above functions together in <linux/libata.h> * include libata-pata-timings.c in the build when PATA_TIMINGS config option is enabled * cover ata_timing_cycle2mode() with CONFIG_ATA_ACPI ifdef (it depends on code from libata-core.c and libata-pata-timings.c while its only user is ATA ACPI) Code size savings on m68k arch using (modified) atari_defconfig: text data bss dec hex filename before: 39688 573 40 40301 9d6d drivers/ata/libata-core.o after: 37820 572 40 38432 9620 drivers/ata/libata-core.o Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Родитель
4e16818704
Коммит
a9b2c120e3
|
@ -37,6 +37,9 @@ config ATA_NONSTANDARD
|
|||
config SATA_HOST
|
||||
bool
|
||||
|
||||
config PATA_TIMINGS
|
||||
bool
|
||||
|
||||
config ATA_VERBOSE_ERROR
|
||||
bool "Verbose ATA error reporting"
|
||||
default y
|
||||
|
@ -51,6 +54,7 @@ config ATA_VERBOSE_ERROR
|
|||
config ATA_ACPI
|
||||
bool "ATA ACPI Support"
|
||||
depends on ACPI
|
||||
select PATA_TIMINGS
|
||||
default y
|
||||
help
|
||||
This option adds support for ATA-related ACPI objects.
|
||||
|
@ -341,6 +345,7 @@ config PDC_ADMA
|
|||
config PATA_OCTEON_CF
|
||||
tristate "OCTEON Boot Bus Compact Flash support"
|
||||
depends on CAVIUM_OCTEON_SOC
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables a polled compact flash driver for use with
|
||||
compact flash cards attached to the OCTEON boot bus.
|
||||
|
@ -536,6 +541,7 @@ comment "PATA SFF controllers with BMDMA"
|
|||
config PATA_ALI
|
||||
tristate "ALi PATA support"
|
||||
depends on PCI
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables support for the ALi ATA interfaces
|
||||
found on the many ALi chipsets.
|
||||
|
@ -545,6 +551,7 @@ config PATA_ALI
|
|||
config PATA_AMD
|
||||
tristate "AMD/NVidia PATA support"
|
||||
depends on PCI
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables support for the AMD and NVidia PATA
|
||||
interfaces found on the chipsets for Athlon/Athlon64.
|
||||
|
@ -579,6 +586,7 @@ config PATA_ATIIXP
|
|||
config PATA_ATP867X
|
||||
tristate "ARTOP/Acard ATP867X PATA support"
|
||||
depends on PCI
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables support for ARTOP/Acard ATP867X PATA
|
||||
controllers.
|
||||
|
@ -588,6 +596,7 @@ config PATA_ATP867X
|
|||
config PATA_BK3710
|
||||
tristate "Palmchip BK3710 PATA support"
|
||||
depends on ARCH_DAVINCI
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables support for the integrated IDE controller on
|
||||
the TI DaVinci SoC.
|
||||
|
@ -597,6 +606,7 @@ config PATA_BK3710
|
|||
config PATA_CMD64X
|
||||
tristate "CMD64x PATA support"
|
||||
depends on PCI
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables support for the CMD64x series chips
|
||||
except for the CMD640.
|
||||
|
@ -642,6 +652,7 @@ config PATA_CS5536
|
|||
config PATA_CYPRESS
|
||||
tristate "Cypress CY82C693 PATA support (Very Experimental)"
|
||||
depends on PCI
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables support for the Cypress/Contaq CY82C693
|
||||
chipset found in some Alpha systems
|
||||
|
@ -660,6 +671,7 @@ config PATA_EFAR
|
|||
config PATA_EP93XX
|
||||
tristate "Cirrus Logic EP93xx PATA support"
|
||||
depends on ARCH_EP93XX
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables support for the PATA controller in
|
||||
the Cirrus Logic EP9312 and EP9315 ARM CPU.
|
||||
|
@ -724,6 +736,7 @@ config PATA_HPT3X3_DMA
|
|||
config PATA_ICSIDE
|
||||
tristate "Acorn ICS PATA support"
|
||||
depends on ARM && ARCH_ACORN
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
On Acorn systems, say Y here if you wish to use the ICS PATA
|
||||
interface card. This is not required for ICS partition support.
|
||||
|
@ -732,6 +745,7 @@ config PATA_ICSIDE
|
|||
config PATA_IMX
|
||||
tristate "PATA support for Freescale iMX"
|
||||
depends on ARCH_MXC
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables support for the PATA host available on Freescale
|
||||
iMX SoCs.
|
||||
|
@ -817,6 +831,7 @@ config PATA_NINJA32
|
|||
config PATA_NS87415
|
||||
tristate "Nat Semi NS87415 PATA support"
|
||||
depends on PCI
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables support for the National Semiconductor
|
||||
NS87415 PCI-IDE controller.
|
||||
|
@ -941,6 +956,7 @@ config PATA_TRIFLEX
|
|||
config PATA_VIA
|
||||
tristate "VIA PATA support"
|
||||
depends on PCI
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables support for the VIA PATA interfaces
|
||||
found on the many VIA chipsets.
|
||||
|
@ -974,6 +990,7 @@ comment "PIO-only SFF controllers"
|
|||
config PATA_CMD640_PCI
|
||||
tristate "CMD640 PCI PATA support (Experimental)"
|
||||
depends on PCI
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables support for the CMD640 PCI IDE
|
||||
interface chip. Only the primary channel is currently
|
||||
|
@ -1044,6 +1061,7 @@ config PATA_MPIIX
|
|||
config PATA_NS87410
|
||||
tristate "Nat Semi NS87410 PATA support"
|
||||
depends on PCI
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables support for the National Semiconductor
|
||||
NS87410 PCI-IDE controller.
|
||||
|
@ -1124,6 +1142,7 @@ config PATA_RZ1000
|
|||
config PATA_SAMSUNG_CF
|
||||
tristate "Samsung SoC PATA support"
|
||||
depends on SAMSUNG_DEV_IDE
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables basic support for Samsung's S3C/S5P board
|
||||
PATA controllers via the new ATA layer
|
||||
|
@ -1143,6 +1162,7 @@ comment "Generic fallback / legacy drivers"
|
|||
config PATA_ACPI
|
||||
tristate "ACPI firmware driver for PATA"
|
||||
depends on ATA_ACPI && ATA_BMDMA && PCI
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables an ACPI method driver which drives
|
||||
motherboard PATA controller interfaces through the ACPI
|
||||
|
@ -1162,6 +1182,7 @@ config ATA_GENERIC
|
|||
config PATA_LEGACY
|
||||
tristate "Legacy ISA PATA support (Experimental)"
|
||||
depends on (ISA || PCI)
|
||||
select PATA_TIMINGS
|
||||
help
|
||||
This option enables support for ISA/VLB/PCI bus legacy PATA
|
||||
ports and allows them to be accessed via the new ATA layer.
|
||||
|
|
|
@ -127,3 +127,4 @@ libata-$(CONFIG_ATA_SFF) += libata-sff.o
|
|||
libata-$(CONFIG_SATA_PMP) += libata-pmp.o
|
||||
libata-$(CONFIG_ATA_ACPI) += libata-acpi.o
|
||||
libata-$(CONFIG_SATA_ZPODD) += libata-zpodd.o
|
||||
libata-$(CONFIG_PATA_TIMINGS) += libata-pata-timings.o
|
||||
|
|
|
@ -3204,187 +3204,7 @@ int sata_set_spd(struct ata_link *link)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(sata_set_spd);
|
||||
|
||||
/*
|
||||
* This mode timing computation functionality is ported over from
|
||||
* drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik
|
||||
*/
|
||||
/*
|
||||
* PIO 0-4, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
|
||||
* These were taken from ATA/ATAPI-6 standard, rev 0a, except
|
||||
* for UDMA6, which is currently supported only by Maxtor drives.
|
||||
*
|
||||
* For PIO 5/6 MWDMA 3/4 see the CFA specification 3.0.
|
||||
*/
|
||||
|
||||
static const struct ata_timing ata_timing[] = {
|
||||
/* { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 0, 960, 0 }, */
|
||||
{ XFER_PIO_0, 70, 290, 240, 600, 165, 150, 0, 600, 0 },
|
||||
{ XFER_PIO_1, 50, 290, 93, 383, 125, 100, 0, 383, 0 },
|
||||
{ XFER_PIO_2, 30, 290, 40, 330, 100, 90, 0, 240, 0 },
|
||||
{ XFER_PIO_3, 30, 80, 70, 180, 80, 70, 0, 180, 0 },
|
||||
{ XFER_PIO_4, 25, 70, 25, 120, 70, 25, 0, 120, 0 },
|
||||
{ XFER_PIO_5, 15, 65, 25, 100, 65, 25, 0, 100, 0 },
|
||||
{ XFER_PIO_6, 10, 55, 20, 80, 55, 20, 0, 80, 0 },
|
||||
|
||||
{ XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 50, 960, 0 },
|
||||
{ XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 30, 480, 0 },
|
||||
{ XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 20, 240, 0 },
|
||||
|
||||
{ XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 20, 480, 0 },
|
||||
{ XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 5, 150, 0 },
|
||||
{ XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 5, 120, 0 },
|
||||
{ XFER_MW_DMA_3, 25, 0, 0, 0, 65, 25, 5, 100, 0 },
|
||||
{ XFER_MW_DMA_4, 25, 0, 0, 0, 55, 20, 5, 80, 0 },
|
||||
|
||||
/* { XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 0, 150 }, */
|
||||
{ XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 0, 120 },
|
||||
{ XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 0, 80 },
|
||||
{ XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 0, 60 },
|
||||
{ XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 0, 45 },
|
||||
{ XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 0, 30 },
|
||||
{ XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 0, 20 },
|
||||
{ XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 0, 15 },
|
||||
|
||||
{ 0xFF }
|
||||
};
|
||||
|
||||
#define ENOUGH(v, unit) (((v)-1)/(unit)+1)
|
||||
#define EZ(v, unit) ((v)?ENOUGH(((v) * 1000), unit):0)
|
||||
|
||||
static void ata_timing_quantize(const struct ata_timing *t,
|
||||
struct ata_timing *q, int T, int UT)
|
||||
{
|
||||
q->setup = EZ(t->setup, T);
|
||||
q->act8b = EZ(t->act8b, T);
|
||||
q->rec8b = EZ(t->rec8b, T);
|
||||
q->cyc8b = EZ(t->cyc8b, T);
|
||||
q->active = EZ(t->active, T);
|
||||
q->recover = EZ(t->recover, T);
|
||||
q->dmack_hold = EZ(t->dmack_hold, T);
|
||||
q->cycle = EZ(t->cycle, T);
|
||||
q->udma = EZ(t->udma, UT);
|
||||
}
|
||||
|
||||
void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
|
||||
struct ata_timing *m, unsigned int what)
|
||||
{
|
||||
if (what & ATA_TIMING_SETUP)
|
||||
m->setup = max(a->setup, b->setup);
|
||||
if (what & ATA_TIMING_ACT8B)
|
||||
m->act8b = max(a->act8b, b->act8b);
|
||||
if (what & ATA_TIMING_REC8B)
|
||||
m->rec8b = max(a->rec8b, b->rec8b);
|
||||
if (what & ATA_TIMING_CYC8B)
|
||||
m->cyc8b = max(a->cyc8b, b->cyc8b);
|
||||
if (what & ATA_TIMING_ACTIVE)
|
||||
m->active = max(a->active, b->active);
|
||||
if (what & ATA_TIMING_RECOVER)
|
||||
m->recover = max(a->recover, b->recover);
|
||||
if (what & ATA_TIMING_DMACK_HOLD)
|
||||
m->dmack_hold = max(a->dmack_hold, b->dmack_hold);
|
||||
if (what & ATA_TIMING_CYCLE)
|
||||
m->cycle = max(a->cycle, b->cycle);
|
||||
if (what & ATA_TIMING_UDMA)
|
||||
m->udma = max(a->udma, b->udma);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_timing_merge);
|
||||
|
||||
const struct ata_timing *ata_timing_find_mode(u8 xfer_mode)
|
||||
{
|
||||
const struct ata_timing *t = ata_timing;
|
||||
|
||||
while (xfer_mode > t->mode)
|
||||
t++;
|
||||
|
||||
if (xfer_mode == t->mode)
|
||||
return t;
|
||||
|
||||
WARN_ONCE(true, "%s: unable to find timing for xfer_mode 0x%x\n",
|
||||
__func__, xfer_mode);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_timing_find_mode);
|
||||
|
||||
int ata_timing_compute(struct ata_device *adev, unsigned short speed,
|
||||
struct ata_timing *t, int T, int UT)
|
||||
{
|
||||
const u16 *id = adev->id;
|
||||
const struct ata_timing *s;
|
||||
struct ata_timing p;
|
||||
|
||||
/*
|
||||
* Find the mode.
|
||||
*/
|
||||
s = ata_timing_find_mode(speed);
|
||||
if (!s)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(t, s, sizeof(*s));
|
||||
|
||||
/*
|
||||
* If the drive is an EIDE drive, it can tell us it needs extended
|
||||
* PIO/MW_DMA cycle timing.
|
||||
*/
|
||||
|
||||
if (id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */
|
||||
memset(&p, 0, sizeof(p));
|
||||
|
||||
if (speed >= XFER_PIO_0 && speed < XFER_SW_DMA_0) {
|
||||
if (speed <= XFER_PIO_2)
|
||||
p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO];
|
||||
else if ((speed <= XFER_PIO_4) ||
|
||||
(speed == XFER_PIO_5 && !ata_id_is_cfa(id)))
|
||||
p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY];
|
||||
} else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
|
||||
p.cycle = id[ATA_ID_EIDE_DMA_MIN];
|
||||
|
||||
ata_timing_merge(&p, t, t, ATA_TIMING_CYCLE | ATA_TIMING_CYC8B);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the timing to bus clock counts.
|
||||
*/
|
||||
|
||||
ata_timing_quantize(t, t, T, UT);
|
||||
|
||||
/*
|
||||
* Even in DMA/UDMA modes we still use PIO access for IDENTIFY,
|
||||
* S.M.A.R.T * and some other commands. We have to ensure that the
|
||||
* DMA cycle timing is slower/equal than the fastest PIO timing.
|
||||
*/
|
||||
|
||||
if (speed > XFER_PIO_6) {
|
||||
ata_timing_compute(adev, adev->pio_mode, &p, T, UT);
|
||||
ata_timing_merge(&p, t, t, ATA_TIMING_ALL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lengthen active & recovery time so that cycle time is correct.
|
||||
*/
|
||||
|
||||
if (t->act8b + t->rec8b < t->cyc8b) {
|
||||
t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2;
|
||||
t->rec8b = t->cyc8b - t->act8b;
|
||||
}
|
||||
|
||||
if (t->active + t->recover < t->cycle) {
|
||||
t->active += (t->cycle - (t->active + t->recover)) / 2;
|
||||
t->recover = t->cycle - t->active;
|
||||
}
|
||||
|
||||
/*
|
||||
* In a few cases quantisation may produce enough errors to
|
||||
* leave t->cycle too low for the sum of active and recovery
|
||||
* if so we must correct this.
|
||||
*/
|
||||
if (t->active + t->recover > t->cycle)
|
||||
t->cycle = t->active + t->recover;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_timing_compute);
|
||||
|
||||
#ifdef CONFIG_ATA_ACPI
|
||||
/**
|
||||
* ata_timing_cycle2mode - find xfer mode for the specified cycle duration
|
||||
* @xfer_shift: ATA_SHIFT_* value for transfer type to examine.
|
||||
|
@ -3435,6 +3255,7 @@ u8 ata_timing_cycle2mode(unsigned int xfer_shift, int cycle)
|
|||
|
||||
return last_mode;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ata_down_xfermask_limit - adjust dev xfer masks downward
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Helper library for PATA timings
|
||||
*
|
||||
* Copyright 2003-2004 Red Hat, Inc. All rights reserved.
|
||||
* Copyright 2003-2004 Jeff Garzik
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/libata.h>
|
||||
|
||||
/*
|
||||
* This mode timing computation functionality is ported over from
|
||||
* drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik
|
||||
*/
|
||||
/*
|
||||
* PIO 0-4, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
|
||||
* These were taken from ATA/ATAPI-6 standard, rev 0a, except
|
||||
* for UDMA6, which is currently supported only by Maxtor drives.
|
||||
*
|
||||
* For PIO 5/6 MWDMA 3/4 see the CFA specification 3.0.
|
||||
*/
|
||||
|
||||
static const struct ata_timing ata_timing[] = {
|
||||
/* { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 0, 960, 0 }, */
|
||||
{ XFER_PIO_0, 70, 290, 240, 600, 165, 150, 0, 600, 0 },
|
||||
{ XFER_PIO_1, 50, 290, 93, 383, 125, 100, 0, 383, 0 },
|
||||
{ XFER_PIO_2, 30, 290, 40, 330, 100, 90, 0, 240, 0 },
|
||||
{ XFER_PIO_3, 30, 80, 70, 180, 80, 70, 0, 180, 0 },
|
||||
{ XFER_PIO_4, 25, 70, 25, 120, 70, 25, 0, 120, 0 },
|
||||
{ XFER_PIO_5, 15, 65, 25, 100, 65, 25, 0, 100, 0 },
|
||||
{ XFER_PIO_6, 10, 55, 20, 80, 55, 20, 0, 80, 0 },
|
||||
|
||||
{ XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 50, 960, 0 },
|
||||
{ XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 30, 480, 0 },
|
||||
{ XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 20, 240, 0 },
|
||||
|
||||
{ XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 20, 480, 0 },
|
||||
{ XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 5, 150, 0 },
|
||||
{ XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 5, 120, 0 },
|
||||
{ XFER_MW_DMA_3, 25, 0, 0, 0, 65, 25, 5, 100, 0 },
|
||||
{ XFER_MW_DMA_4, 25, 0, 0, 0, 55, 20, 5, 80, 0 },
|
||||
|
||||
/* { XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 0, 150 }, */
|
||||
{ XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 0, 120 },
|
||||
{ XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 0, 80 },
|
||||
{ XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 0, 60 },
|
||||
{ XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 0, 45 },
|
||||
{ XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 0, 30 },
|
||||
{ XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 0, 20 },
|
||||
{ XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 0, 15 },
|
||||
|
||||
{ 0xFF }
|
||||
};
|
||||
|
||||
#define ENOUGH(v, unit) (((v)-1)/(unit)+1)
|
||||
#define EZ(v, unit) ((v)?ENOUGH(((v) * 1000), unit):0)
|
||||
|
||||
static void ata_timing_quantize(const struct ata_timing *t,
|
||||
struct ata_timing *q, int T, int UT)
|
||||
{
|
||||
q->setup = EZ(t->setup, T);
|
||||
q->act8b = EZ(t->act8b, T);
|
||||
q->rec8b = EZ(t->rec8b, T);
|
||||
q->cyc8b = EZ(t->cyc8b, T);
|
||||
q->active = EZ(t->active, T);
|
||||
q->recover = EZ(t->recover, T);
|
||||
q->dmack_hold = EZ(t->dmack_hold, T);
|
||||
q->cycle = EZ(t->cycle, T);
|
||||
q->udma = EZ(t->udma, UT);
|
||||
}
|
||||
|
||||
void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
|
||||
struct ata_timing *m, unsigned int what)
|
||||
{
|
||||
if (what & ATA_TIMING_SETUP)
|
||||
m->setup = max(a->setup, b->setup);
|
||||
if (what & ATA_TIMING_ACT8B)
|
||||
m->act8b = max(a->act8b, b->act8b);
|
||||
if (what & ATA_TIMING_REC8B)
|
||||
m->rec8b = max(a->rec8b, b->rec8b);
|
||||
if (what & ATA_TIMING_CYC8B)
|
||||
m->cyc8b = max(a->cyc8b, b->cyc8b);
|
||||
if (what & ATA_TIMING_ACTIVE)
|
||||
m->active = max(a->active, b->active);
|
||||
if (what & ATA_TIMING_RECOVER)
|
||||
m->recover = max(a->recover, b->recover);
|
||||
if (what & ATA_TIMING_DMACK_HOLD)
|
||||
m->dmack_hold = max(a->dmack_hold, b->dmack_hold);
|
||||
if (what & ATA_TIMING_CYCLE)
|
||||
m->cycle = max(a->cycle, b->cycle);
|
||||
if (what & ATA_TIMING_UDMA)
|
||||
m->udma = max(a->udma, b->udma);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_timing_merge);
|
||||
|
||||
const struct ata_timing *ata_timing_find_mode(u8 xfer_mode)
|
||||
{
|
||||
const struct ata_timing *t = ata_timing;
|
||||
|
||||
while (xfer_mode > t->mode)
|
||||
t++;
|
||||
|
||||
if (xfer_mode == t->mode)
|
||||
return t;
|
||||
|
||||
WARN_ONCE(true, "%s: unable to find timing for xfer_mode 0x%x\n",
|
||||
__func__, xfer_mode);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_timing_find_mode);
|
||||
|
||||
int ata_timing_compute(struct ata_device *adev, unsigned short speed,
|
||||
struct ata_timing *t, int T, int UT)
|
||||
{
|
||||
const u16 *id = adev->id;
|
||||
const struct ata_timing *s;
|
||||
struct ata_timing p;
|
||||
|
||||
/*
|
||||
* Find the mode.
|
||||
*/
|
||||
s = ata_timing_find_mode(speed);
|
||||
if (!s)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(t, s, sizeof(*s));
|
||||
|
||||
/*
|
||||
* If the drive is an EIDE drive, it can tell us it needs extended
|
||||
* PIO/MW_DMA cycle timing.
|
||||
*/
|
||||
|
||||
if (id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */
|
||||
memset(&p, 0, sizeof(p));
|
||||
|
||||
if (speed >= XFER_PIO_0 && speed < XFER_SW_DMA_0) {
|
||||
if (speed <= XFER_PIO_2)
|
||||
p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO];
|
||||
else if ((speed <= XFER_PIO_4) ||
|
||||
(speed == XFER_PIO_5 && !ata_id_is_cfa(id)))
|
||||
p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY];
|
||||
} else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
|
||||
p.cycle = id[ATA_ID_EIDE_DMA_MIN];
|
||||
|
||||
ata_timing_merge(&p, t, t, ATA_TIMING_CYCLE | ATA_TIMING_CYC8B);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the timing to bus clock counts.
|
||||
*/
|
||||
|
||||
ata_timing_quantize(t, t, T, UT);
|
||||
|
||||
/*
|
||||
* Even in DMA/UDMA modes we still use PIO access for IDENTIFY,
|
||||
* S.M.A.R.T * and some other commands. We have to ensure that the
|
||||
* DMA cycle timing is slower/equal than the fastest PIO timing.
|
||||
*/
|
||||
|
||||
if (speed > XFER_PIO_6) {
|
||||
ata_timing_compute(adev, adev->pio_mode, &p, T, UT);
|
||||
ata_timing_merge(&p, t, t, ATA_TIMING_ALL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lengthen active & recovery time so that cycle time is correct.
|
||||
*/
|
||||
|
||||
if (t->act8b + t->rec8b < t->cyc8b) {
|
||||
t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2;
|
||||
t->rec8b = t->cyc8b - t->act8b;
|
||||
}
|
||||
|
||||
if (t->active + t->recover < t->cycle) {
|
||||
t->active += (t->cycle - (t->active + t->recover)) / 2;
|
||||
t->recover = t->cycle - t->active;
|
||||
}
|
||||
|
||||
/*
|
||||
* In a few cases quantisation may produce enough errors to
|
||||
* leave t->cycle too low for the sum of active and recovery
|
||||
* if so we must correct this.
|
||||
*/
|
||||
if (t->active + t->recover > t->cycle)
|
||||
t->cycle = t->active + t->recover;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_timing_compute);
|
|
@ -1205,12 +1205,6 @@ extern int ata_cable_unknown(struct ata_port *ap);
|
|||
|
||||
/* Timing helpers */
|
||||
extern unsigned int ata_pio_need_iordy(const struct ata_device *);
|
||||
extern const struct ata_timing *ata_timing_find_mode(u8 xfer_mode);
|
||||
extern int ata_timing_compute(struct ata_device *, unsigned short,
|
||||
struct ata_timing *, int, int);
|
||||
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);
|
||||
|
||||
/* PCI */
|
||||
|
@ -1807,6 +1801,16 @@ static inline int ata_dma_enabled(struct ata_device *adev)
|
|||
return (adev->dma_mode == 0xFF ? 0 : 1);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* PATA timings - drivers/ata/libata-pata-timings.c
|
||||
*/
|
||||
extern const struct ata_timing *ata_timing_find_mode(u8 xfer_mode);
|
||||
extern int ata_timing_compute(struct ata_device *, unsigned short,
|
||||
struct ata_timing *, int, int);
|
||||
extern void ata_timing_merge(const struct ata_timing *,
|
||||
const struct ata_timing *, struct ata_timing *,
|
||||
unsigned int);
|
||||
|
||||
/**************************************************************************
|
||||
* PMP - drivers/ata/libata-pmp.c
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче