1
0
Fork 0

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>
alistair/sensors
Bartlomiej Zolnierkiewicz 2020-03-26 16:58:07 +01:00 committed by Jens Axboe
parent 4e16818704
commit a9b2c120e3
5 changed files with 226 additions and 187 deletions

View File

@ -37,6 +37,9 @@ config ATA_NONSTANDARD
config SATA_HOST config SATA_HOST
bool bool
config PATA_TIMINGS
bool
config ATA_VERBOSE_ERROR config ATA_VERBOSE_ERROR
bool "Verbose ATA error reporting" bool "Verbose ATA error reporting"
default y default y
@ -51,6 +54,7 @@ config ATA_VERBOSE_ERROR
config ATA_ACPI config ATA_ACPI
bool "ATA ACPI Support" bool "ATA ACPI Support"
depends on ACPI depends on ACPI
select PATA_TIMINGS
default y default y
help help
This option adds support for ATA-related ACPI objects. This option adds support for ATA-related ACPI objects.
@ -341,6 +345,7 @@ config PDC_ADMA
config PATA_OCTEON_CF config PATA_OCTEON_CF
tristate "OCTEON Boot Bus Compact Flash support" tristate "OCTEON Boot Bus Compact Flash support"
depends on CAVIUM_OCTEON_SOC depends on CAVIUM_OCTEON_SOC
select PATA_TIMINGS
help help
This option enables a polled compact flash driver for use with This option enables a polled compact flash driver for use with
compact flash cards attached to the OCTEON boot bus. compact flash cards attached to the OCTEON boot bus.
@ -536,6 +541,7 @@ comment "PATA SFF controllers with BMDMA"
config PATA_ALI config PATA_ALI
tristate "ALi PATA support" tristate "ALi PATA support"
depends on PCI depends on PCI
select PATA_TIMINGS
help help
This option enables support for the ALi ATA interfaces This option enables support for the ALi ATA interfaces
found on the many ALi chipsets. found on the many ALi chipsets.
@ -545,6 +551,7 @@ config PATA_ALI
config PATA_AMD config PATA_AMD
tristate "AMD/NVidia PATA support" tristate "AMD/NVidia PATA support"
depends on PCI depends on PCI
select PATA_TIMINGS
help help
This option enables support for the AMD and NVidia PATA This option enables support for the AMD and NVidia PATA
interfaces found on the chipsets for Athlon/Athlon64. interfaces found on the chipsets for Athlon/Athlon64.
@ -579,6 +586,7 @@ config PATA_ATIIXP
config PATA_ATP867X config PATA_ATP867X
tristate "ARTOP/Acard ATP867X PATA support" tristate "ARTOP/Acard ATP867X PATA support"
depends on PCI depends on PCI
select PATA_TIMINGS
help help
This option enables support for ARTOP/Acard ATP867X PATA This option enables support for ARTOP/Acard ATP867X PATA
controllers. controllers.
@ -588,6 +596,7 @@ config PATA_ATP867X
config PATA_BK3710 config PATA_BK3710
tristate "Palmchip BK3710 PATA support" tristate "Palmchip BK3710 PATA support"
depends on ARCH_DAVINCI depends on ARCH_DAVINCI
select PATA_TIMINGS
help help
This option enables support for the integrated IDE controller on This option enables support for the integrated IDE controller on
the TI DaVinci SoC. the TI DaVinci SoC.
@ -597,6 +606,7 @@ config PATA_BK3710
config PATA_CMD64X config PATA_CMD64X
tristate "CMD64x PATA support" tristate "CMD64x PATA support"
depends on PCI depends on PCI
select PATA_TIMINGS
help help
This option enables support for the CMD64x series chips This option enables support for the CMD64x series chips
except for the CMD640. except for the CMD640.
@ -642,6 +652,7 @@ config PATA_CS5536
config PATA_CYPRESS config PATA_CYPRESS
tristate "Cypress CY82C693 PATA support (Very Experimental)" tristate "Cypress CY82C693 PATA support (Very Experimental)"
depends on PCI depends on PCI
select PATA_TIMINGS
help help
This option enables support for the Cypress/Contaq CY82C693 This option enables support for the Cypress/Contaq CY82C693
chipset found in some Alpha systems chipset found in some Alpha systems
@ -660,6 +671,7 @@ config PATA_EFAR
config PATA_EP93XX config PATA_EP93XX
tristate "Cirrus Logic EP93xx PATA support" tristate "Cirrus Logic EP93xx PATA support"
depends on ARCH_EP93XX depends on ARCH_EP93XX
select PATA_TIMINGS
help help
This option enables support for the PATA controller in This option enables support for the PATA controller in
the Cirrus Logic EP9312 and EP9315 ARM CPU. the Cirrus Logic EP9312 and EP9315 ARM CPU.
@ -724,6 +736,7 @@ config PATA_HPT3X3_DMA
config PATA_ICSIDE config PATA_ICSIDE
tristate "Acorn ICS PATA support" tristate "Acorn ICS PATA support"
depends on ARM && ARCH_ACORN depends on ARM && ARCH_ACORN
select PATA_TIMINGS
help help
On Acorn systems, say Y here if you wish to use the ICS PATA On Acorn systems, say Y here if you wish to use the ICS PATA
interface card. This is not required for ICS partition support. interface card. This is not required for ICS partition support.
@ -732,6 +745,7 @@ config PATA_ICSIDE
config PATA_IMX config PATA_IMX
tristate "PATA support for Freescale iMX" tristate "PATA support for Freescale iMX"
depends on ARCH_MXC depends on ARCH_MXC
select PATA_TIMINGS
help help
This option enables support for the PATA host available on Freescale This option enables support for the PATA host available on Freescale
iMX SoCs. iMX SoCs.
@ -817,6 +831,7 @@ config PATA_NINJA32
config PATA_NS87415 config PATA_NS87415
tristate "Nat Semi NS87415 PATA support" tristate "Nat Semi NS87415 PATA support"
depends on PCI depends on PCI
select PATA_TIMINGS
help help
This option enables support for the National Semiconductor This option enables support for the National Semiconductor
NS87415 PCI-IDE controller. NS87415 PCI-IDE controller.
@ -941,6 +956,7 @@ config PATA_TRIFLEX
config PATA_VIA config PATA_VIA
tristate "VIA PATA support" tristate "VIA PATA support"
depends on PCI depends on PCI
select PATA_TIMINGS
help help
This option enables support for the VIA PATA interfaces This option enables support for the VIA PATA interfaces
found on the many VIA chipsets. found on the many VIA chipsets.
@ -974,6 +990,7 @@ comment "PIO-only SFF controllers"
config PATA_CMD640_PCI config PATA_CMD640_PCI
tristate "CMD640 PCI PATA support (Experimental)" tristate "CMD640 PCI PATA support (Experimental)"
depends on PCI depends on PCI
select PATA_TIMINGS
help help
This option enables support for the CMD640 PCI IDE This option enables support for the CMD640 PCI IDE
interface chip. Only the primary channel is currently interface chip. Only the primary channel is currently
@ -1044,6 +1061,7 @@ config PATA_MPIIX
config PATA_NS87410 config PATA_NS87410
tristate "Nat Semi NS87410 PATA support" tristate "Nat Semi NS87410 PATA support"
depends on PCI depends on PCI
select PATA_TIMINGS
help help
This option enables support for the National Semiconductor This option enables support for the National Semiconductor
NS87410 PCI-IDE controller. NS87410 PCI-IDE controller.
@ -1124,6 +1142,7 @@ config PATA_RZ1000
config PATA_SAMSUNG_CF config PATA_SAMSUNG_CF
tristate "Samsung SoC PATA support" tristate "Samsung SoC PATA support"
depends on SAMSUNG_DEV_IDE depends on SAMSUNG_DEV_IDE
select PATA_TIMINGS
help help
This option enables basic support for Samsung's S3C/S5P board This option enables basic support for Samsung's S3C/S5P board
PATA controllers via the new ATA layer PATA controllers via the new ATA layer
@ -1143,6 +1162,7 @@ comment "Generic fallback / legacy drivers"
config PATA_ACPI config PATA_ACPI
tristate "ACPI firmware driver for PATA" tristate "ACPI firmware driver for PATA"
depends on ATA_ACPI && ATA_BMDMA && PCI depends on ATA_ACPI && ATA_BMDMA && PCI
select PATA_TIMINGS
help help
This option enables an ACPI method driver which drives This option enables an ACPI method driver which drives
motherboard PATA controller interfaces through the ACPI motherboard PATA controller interfaces through the ACPI
@ -1162,6 +1182,7 @@ config ATA_GENERIC
config PATA_LEGACY config PATA_LEGACY
tristate "Legacy ISA PATA support (Experimental)" tristate "Legacy ISA PATA support (Experimental)"
depends on (ISA || PCI) depends on (ISA || PCI)
select PATA_TIMINGS
help help
This option enables support for ISA/VLB/PCI bus legacy PATA This option enables support for ISA/VLB/PCI bus legacy PATA
ports and allows them to be accessed via the new ATA layer. ports and allows them to be accessed via the new ATA layer.

View File

@ -127,3 +127,4 @@ libata-$(CONFIG_ATA_SFF) += libata-sff.o
libata-$(CONFIG_SATA_PMP) += libata-pmp.o libata-$(CONFIG_SATA_PMP) += libata-pmp.o
libata-$(CONFIG_ATA_ACPI) += libata-acpi.o libata-$(CONFIG_ATA_ACPI) += libata-acpi.o
libata-$(CONFIG_SATA_ZPODD) += libata-zpodd.o libata-$(CONFIG_SATA_ZPODD) += libata-zpodd.o
libata-$(CONFIG_PATA_TIMINGS) += libata-pata-timings.o

View File

@ -3204,187 +3204,7 @@ int sata_set_spd(struct ata_link *link)
} }
EXPORT_SYMBOL_GPL(sata_set_spd); EXPORT_SYMBOL_GPL(sata_set_spd);
/* #ifdef CONFIG_ATA_ACPI
* 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);
/** /**
* ata_timing_cycle2mode - find xfer mode for the specified cycle duration * ata_timing_cycle2mode - find xfer mode for the specified cycle duration
* @xfer_shift: ATA_SHIFT_* value for transfer type to examine. * @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; return last_mode;
} }
#endif
/** /**
* ata_down_xfermask_limit - adjust dev xfer masks downward * ata_down_xfermask_limit - adjust dev xfer masks downward

View File

@ -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);

View File

@ -1205,12 +1205,6 @@ extern int ata_cable_unknown(struct ata_port *ap);
/* Timing helpers */ /* Timing helpers */
extern unsigned int ata_pio_need_iordy(const struct ata_device *); 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); extern u8 ata_timing_cycle2mode(unsigned int xfer_shift, int cycle);
/* PCI */ /* PCI */
@ -1807,6 +1801,16 @@ static inline int ata_dma_enabled(struct ata_device *adev)
return (adev->dma_mode == 0xFF ? 0 : 1); 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 * PMP - drivers/ata/libata-pmp.c
*/ */