lkml.org 
[lkml]   [2020]   [Mar]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 12/27] ata: separate PATA timings code from libata-core.c
    Date
    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>
    ---
    drivers/ata/Kconfig | 21 ++++
    drivers/ata/Makefile | 1 +
    drivers/ata/libata-core.c | 183 +---------------------------
    drivers/ata/libata-pata-timings.c | 192 ++++++++++++++++++++++++++++++
    include/linux/libata.h | 16 ++-
    5 files changed, 226 insertions(+), 187 deletions(-)
    create mode 100644 drivers/ata/libata-pata-timings.c

    diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
    index ad7760656f71..5b55ebf56b5a 100644
    --- a/drivers/ata/Kconfig
    +++ b/drivers/ata/Kconfig
    @@ -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.
    diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
    index d8cc2e04a6c7..cdaf965fed25 100644
    --- a/drivers/ata/Makefile
    +++ b/drivers/ata/Makefile
    @@ -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
    diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
    index acdcedcb3d10..0a56968e2e98 100644
    --- a/drivers/ata/libata-core.c
    +++ b/drivers/ata/libata-core.c
    @@ -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
    diff --git a/drivers/ata/libata-pata-timings.c b/drivers/ata/libata-pata-timings.c
    new file mode 100644
    index 000000000000..af341226cc64
    --- /dev/null
    +++ b/drivers/ata/libata-pata-timings.c
    @@ -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);
    diff --git a/include/linux/libata.h b/include/linux/libata.h
    index 236e4c55be48..500b709ed3de 100644
    --- a/include/linux/libata.h
    +++ b/include/linux/libata.h
    @@ -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
    */
    --
    2.24.1
    \
     
     \ /
      Last update: 2020-03-26 17:00    [W:4.047 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site