// SPDX-License-Identifier: GPL-2.0-or-later/* * libata-core.c - helper library for ATA * * Copyright 2003-2004 Red Hat, Inc. All rights reserved. * Copyright 2003-2004 Jeff Garzik * * libata documentation is available via 'make {ps|pdf}docs', * as Documentation/driver-api/libata.rst * * Hardware documentation available from http://www.t13.org/ and * http://www.sata-io.org/ * * Standards documents from: * http://www.t13.org (ATA standards, PCI DMA IDE spec) * http://www.t10.org (SCSI MMC - for ATAPI MMC) * http://www.sata-io.org (SATA) * http://www.compactflash.org (CF) * http://www.qic.org (QIC157 - Tape and DSC) * http://www.ce-ata.org (CE-ATA: not supported) * * libata is essentially a library of internal helper functions for * low-level ATA host controller drivers. As such, the API/ABI is * likely to change as new drivers are added and updated. * Do not depend on ABI/API stability. */ #include <linux/kernel.h>#include <linux/module.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/list.h>#include <linux/mm.h>#include <linux/spinlock.h>#include <linux/blkdev.h>#include <linux/delay.h>#include <linux/timer.h>#include <linux/time.h>#include <linux/interrupt.h>#include <linux/completion.h>#include <linux/suspend.h>#include <linux/workqueue.h>#include <linux/scatterlist.h>#include <linux/io.h>#include <linux/log2.h>#include <linux/slab.h>#include <linux/glob.h>#include <scsi/scsi.h>#include <scsi/scsi_cmnd.h>#include <scsi/scsi_host.h>#include <linux/libata.h>#include <asm/byteorder.h>#include <linux/unaligned.h>#include <linux/cdrom.h>#include <linux/ratelimit.h>#include <linux/leds.h>#include <linux/pm_runtime.h>#include <linux/platform_device.h>#include <asm/setup.h> #define CREATE_TRACE_POINTS#include <trace/events/libata.h> #include "libata.h"#include "libata-transport.h" const struct ata_port_operations ata_base_port_ops = { .reset.prereset = ata_std_prereset, .reset.postreset = ata_std_postreset, .error_handler = ata_std_error_handler, .sched_eh = ata_std_sched_eh, .end_eh = ata_std_end_eh,}; static unsigned int ata_dev_init_params(struct ata_device *dev, u16 heads, u16 sectors);static unsigned int ata_dev_set_xfermode(struct ata_device *dev);static void ata_dev_xfermask(struct ata_device *dev);static u64 ata_dev_quirks(const struct ata_device *dev);static u64 ata_dev_get_quirk_value(struct ata_device *dev, u64 quirk); static DEFINE_IDA(ata_ida); #ifdef CONFIG_ATA_FORCEstruct ata_force_param { const char *name; u64 value; u8 cbl; u8 spd_limit; unsigned int xfer_mask; u64 quirk_on; u64 quirk_off; unsigned int pflags_on; u16 lflags_on; u16 lflags_off;}; struct ata_force_ent { int port; int device; struct ata_force_param param;}; static struct ata_force_ent *ata_force_tbl;static int ata_force_tbl_size; static char ata_force_param_buf[COMMAND_LINE_SIZE] __initdata;/* param_buf is thrown away after initialization, disallow read */module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0);MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/admin-guide/kernel-parameters.rst for details)");#endif static int atapi_enabled = 1;module_param(atapi_enabled, int, 0444);MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on [default])"); static int atapi_dmadir = 0;module_param(atapi_dmadir, int, 0444);MODULE_PARM_DESC(atapi_dmadir, "Enable ATAPI DMADIR bridge support (0=off [default], 1=on)"); int atapi_passthru16 = 1;module_param(atapi_passthru16, int, 0444);MODULE_PARM_DESC(atapi_passthru16, "Enable ATA_16 passthru for ATAPI devices (0=off, 1=on [default])"); int libata_fua = 0;module_param_named(fua, libata_fua, int, 0444);MODULE_PARM_DESC(fua, "FUA support (0=off [default], 1=on)"); static int ata_ignore_hpa;module_param_named(ignore_hpa, ata_ignore_hpa, int, 0644);MODULE_PARM_DESC(ignore_hpa, "Ignore HPA limit (0=keep BIOS limits, 1=ignore limits, using full disk)"); static int libata_dma_mask = ATA_DMA_MASK_ATA|ATA_DMA_MASK_ATAPI|ATA_DMA_MASK_CFA;module_param_named(dma, libata_dma_mask, int, 0444);MODULE_PARM_DESC(dma, "DMA enable/disable (0x1==ATA, 0x2==ATAPI, 0x4==CF)"); static int ata_probe_timeout;module_param(ata_probe_timeout, int, 0444);MODULE_PARM_DESC(ata_probe_timeout, "Set ATA probing timeout (seconds)"); int libata_noacpi = 0;module_param_named(noacpi, libata_noacpi, int, 0444);MODULE_PARM_DESC(noacpi, "Disable the use of ACPI in probe/suspend/resume (0=off [default], 1=on)"); int libata_allow_tpm = 0;module_param_named(allow_tpm, libata_allow_tpm, int, 0444);MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands (0=off [default], 1=on)"); static int atapi_an;module_param(atapi_an, int, 0444);MODULE_PARM_DESC(atapi_an, "Enable ATAPI AN media presence notification (0=0ff [default], 1=on)"); MODULE_AUTHOR("Jeff Garzik");MODULE_DESCRIPTION("Library module for ATA devices");MODULE_LICENSE("GPL");MODULE_VERSION(DRV_VERSION); static inline bool ata_dev_print_info(const struct ata_device *dev){ struct ata_eh_context *ehc = &dev->link->eh_context; return ehc->i.flags & ATA_EHI_PRINTINFO;} /** * ata_link_next - link iteration helper * @link: the previous link, NULL to start * @ap: ATA port containing links to iterate * @mode: iteration mode, one of ATA_LITER_* * * LOCKING: * Host lock or EH context. * * RETURNS: * Pointer to the next link. */struct ata_link *ata_link_next(struct ata_link *link, struct ata_port *ap, enum ata_link_iter_mode mode){ BUG_ON(mode != ATA_LITER_EDGE && mode != ATA_LITER_PMP_FIRST && mode != ATA_LITER_HOST_FIRST); /* NULL link indicates start of iteration */ if (!link) switch (mode) { case ATA_LITER_EDGE: case ATA_LITER_PMP_FIRST: if (sata_pmp_attached(ap)) return ap->pmp_link; fallthrough; case ATA_LITER_HOST_FIRST: return &ap->link; } /* we just iterated over the host link, what's next? */ if (link == &ap->link) switch (mode) { case ATA_LITER_HOST_FIRST: if (sata_pmp_attached(ap)) return ap->pmp_link; fallthrough; case ATA_LITER_PMP_FIRST: if (unlikely(ap->slave_link)) return ap->slave_link; fallthrough; case ATA_LITER_EDGE: return NULL; } /* slave_link excludes PMP */ if (unlikely(link == ap->slave_link)) return NULL; /* we were over a PMP link */ if (++link < ap->pmp_link + ap->nr_pmp_links) return link; if (mode == ATA_LITER_PMP_FIRST) return &ap->link; return NULL;}EXPORT_SYMBOL_GPL(ata_link_next); /** * ata_dev_next - device iteration helper * @dev: the previous device, NULL to start * @link: ATA link containing devices to iterate * @mode: iteration mode, one of ATA_DITER_* * * LOCKING: * Host lock or EH context. * * RETURNS: * Pointer to the next device. */struct ata_device *ata_dev_next(struct ata_device *dev, struct ata_link *link, enum ata_dev_iter_mode mode){ BUG_ON(mode != ATA_DITER_ENABLED && mode != ATA_DITER_ENABLED_REVERSE && mode != ATA_DITER_ALL && mode != ATA_DITER_ALL_REVERSE); /* NULL dev indicates start of iteration */ if (!dev) switch (mode) { case ATA_DITER_ENABLED: case ATA_DITER_ALL: dev = link->device; goto check; case ATA_DITER_ENABLED_REVERSE: case ATA_DITER_ALL_REVERSE: dev = link->device + ata_link_max_devices(link) - 1; goto check; } next: /* move to the next one */ switch (mode) { case ATA_DITER_ENABLED: case ATA_DITER_ALL: if (++dev < link->device + ata_link_max_devices(link)) goto check; return NULL; case ATA_DITER_ENABLED_REVERSE: case ATA_DITER_ALL_REVERSE: if (--dev >= link->device) goto check; return NULL; } check: if ((mode == ATA_DITER_ENABLED || mode == ATA_DITER_ENABLED_REVERSE) && !ata_dev_enabled(dev)) goto next; return dev;}EXPORT_SYMBOL_GPL(ata_dev_next); /** * ata_dev_phys_link - find physical link for a device * @dev: ATA device to look up physical link for * * Look up physical link which @dev is attached to. Note that * this is different from @dev->link only when @dev is on slave * link. For all other cases, it's the same as @dev->link. * * LOCKING: * Don't care. * * RETURNS: * Pointer to the found physical link. */struct ata_link *ata_dev_phys_link(struct ata_device *dev){ struct ata_port *ap = dev->link->ap; if (!ap->slave_link) return dev->link; if (!dev->devno) return &ap->link; return ap->slave_link;} #ifdef CONFIG_ATA_FORCE/** * ata_force_cbl - force cable type according to libata.force * @ap: ATA port of interest * * Force cable type according to libata.force and whine about it. * The last entry which has matching port number is used, so it * can be specified as part of device force parameters. For * example, both "a:40c,1.00:udma4" and "1.00:40c,udma4" have the * same effect. * * LOCKING: * EH context. */void ata_force_cbl(struct ata_port *ap){ int i; for (i = ata_force_tbl_size - 1; i >= 0; i--) { const struct ata_force_ent *fe = &ata_force_tbl[i]; if (fe->port != -1 && fe->port != ap->print_id) continue; if (fe->param.cbl == ATA_CBL_NONE) continue; ap->cbl = fe->param.cbl; ata_port_notice(ap, "FORCE: cable set to %s\n", fe->param.name); return; }} /** * ata_force_pflags - force port flags according to libata.force * @ap: ATA port of interest * * Force port flags according to libata.force and whine about it. * * LOCKING: * EH context. */static void ata_force_pflags(struct ata_port *ap){ int i; for (i = ata_force_tbl_size - 1; i >= 0; i--) { const struct ata_force_ent *fe = &ata_force_tbl[i]; if (fe->port != -1 && fe->port != ap->print_id) continue; /* let pflags stack */ if (fe->param.pflags_on) { ap->pflags |= fe->param.pflags_on; ata_port_notice(ap, "FORCE: port flag 0x%x forced -> 0x%x\n", fe->param.pflags_on, ap->pflags); } }} /** * ata_force_link_limits - force link limits according to libata.force * @link: ATA link of interest * * Force link flags and SATA spd limit according to libata.force * and whine about it. When only the port part is specified * (e.g. 1:), the limit applies to all links connected to both * the host link and all fan-out ports connected via PMP. If the * device part is specified as 0 (e.g. 1.00:), it specifies the * first fan-out link not the host link. Device number 15 always * points to the host link whether PMP is attached or not. If the * controller has slave link, device number 16 points to it. * * LOCKING: * EH context. */static void ata_force_link_limits(struct ata_link *link){ bool did_spd = false; int linkno = link->pmp; int i; if (ata_is_host_link(link)) linkno += 15; for (i = ata_force_tbl_size - 1; i >= 0; i--) { const struct ata_force_ent *fe = &ata_force_tbl[i]; if (fe->port != -1 && fe->port != link->ap->print_id) continue; if (fe->device != -1 && fe->device != linkno) continue; /* only honor the first spd limit */ if (!did_spd && fe->param.spd_limit) { link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1; ata_link_notice(link, "FORCE: PHY spd limit set to %s\n", fe->param.name); did_spd = true; } /* let lflags stack */ if (fe->param.lflags_on) { link->flags |= fe->param.lflags_on; ata_link_notice(link, "FORCE: link flag 0x%x forced -> 0x%x\n", fe->param.lflags_on, link->flags); } if (fe->param.lflags_off) { link->flags &= ~fe->param.lflags_off; ata_link_notice(link, "FORCE: link flag 0x%x cleared -> 0x%x\n", fe->param.lflags_off, link->flags); } }} /** * ata_force_xfermask - force xfermask according to libata.force * @dev: ATA device of interest * * Force xfer_mask according to libata.force and whine about it. * For consistency with link selection, device number 15 selects * the first device connected to the host link. * * LOCKING: * EH context. */static void ata_force_xfermask(struct ata_device *dev){ int devno = dev->link->pmp + dev->devno; int alt_devno = devno; int i; /* allow n.15/16 for devices attached to host port */ if (ata_is_host_link(dev->link)) alt_devno += 15; for (i = ata_force_tbl_size - 1; i >= 0; i--) { const struct ata_force_ent *fe = &ata_force_tbl[i]; unsigned int pio_mask, mwdma_mask, udma_mask; if (fe->port != -1 && fe->port != dev->link->ap->print_id) continue; if (fe->device != -1 && fe->device != devno && fe->device != alt_devno) continue; if (!fe->param.xfer_mask) continue; ata_unpack_xfermask(fe->param.xfer_mask, &pio_mask, &mwdma_mask, &udma_mask); if (udma_mask) dev->udma_mask = udma_mask; else if (mwdma_mask) { dev->udma_mask = 0; dev->mwdma_mask = mwdma_mask; } else { dev->udma_mask = 0; dev->mwdma_mask = 0; dev->pio_mask = pio_mask; } ata_dev_notice(dev, "FORCE: xfer_mask set to %s\n", fe->param.name); return; }} static const struct ata_force_ent *ata_force_get_fe_for_dev(struct ata_device *dev){ const struct ata_force_ent *fe; int devno = dev->link->pmp + dev->devno; int alt_devno = devno; int i; /* allow n.15/16 for devices attached to host port */ if (ata_is_host_link(dev->link)) alt_devno += 15; for (i = 0; i < ata_force_tbl_size; i++) { fe = &ata_force_tbl[i]; if (fe->port != -1 && fe->port != dev->link->ap->print_id) continue; if (fe->device != -1 && fe->device != devno && fe->device != alt_devno) continue; return fe; }Lines 1–500 of 7036. Load more
// SPDX-License-Identifier: GPL-2.0-or-later /* * libata-core.c - helper library for ATA * * Copyright 2003-2004 Red Hat, Inc. All rights reserved. * Copyright 2003-2004 Jeff Garzik * * libata documentation is available via 'make {ps|pdf}docs', * as Documentation/driver-api/libata.rst * * Hardware documentation available from http://www.t13.org/ and * http://www.sata-io.org/ * * Standards documents from: * http://www.t13.org (ATA standards, PCI DMA IDE spec) * http://www.t10.org (SCSI MMC - for ATAPI MMC) * http://www.sata-io.org (SATA) * http://www.compactflash.org (CF) * http://www.qic.org (QIC157 - Tape and DSC) * http://www.ce-ata.org (CE-ATA: not supported) * * libata is essentially a library of internal helper functions for * low-level ATA host controller drivers. As such, the API/ABI is * likely to change as new drivers are added and updated. * Do not depend on ABI/API stability. */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/init.h> #include <linux/list.h> #include <linux/mm.h> #include <linux/spinlock.h> #include <linux/blkdev.h> #include <linux/delay.h> #include <linux/timer.h> #include <linux/time.h> #include <linux/interrupt.h> #include <linux/completion.h> #include <linux/suspend.h> #include <linux/workqueue.h> #include <linux/scatterlist.h> #include <linux/io.h> #include <linux/log2.h> #include <linux/slab.h> #include <linux/glob.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_host.h> #include <linux/libata.h> #include <asm/byteorder.h> #include <linux/unaligned.h> #include <linux/cdrom.h> #include <linux/ratelimit.h> #include <linux/leds.h> #include <linux/pm_runtime.h> #include <linux/platform_device.h> #include <asm/setup.h> #define CREATE_TRACE_POINTS #include <trace/events/libata.h> #include "libata.h" #include "libata-transport.h" const struct ata_port_operations ata_base_port_ops = { .reset.prereset = ata_std_prereset, .reset.postreset = ata_std_postreset, .error_handler = ata_std_error_handler, .sched_eh = ata_std_sched_eh, .end_eh = ata_std_end_eh, }; static unsigned int ata_dev_init_params(struct ata_device *dev, u16 heads, u16 sectors); static unsigned int ata_dev_set_xfermode(struct ata_device *dev); static void ata_dev_xfermask(struct ata_device *dev); static u64 ata_dev_quirks(const struct ata_device *dev); static u64 ata_dev_get_quirk_value(struct ata_device *dev, u64 quirk); static DEFINE_IDA(ata_ida); #ifdef CONFIG_ATA_FORCE struct ata_force_param { const char *name; u64 value; u8 cbl; u8 spd_limit; unsigned int xfer_mask; u64 quirk_on; u64 quirk_off; unsigned int pflags_on; u16 lflags_on; u16 lflags_off; }; struct ata_force_ent { int port; int device; struct ata_force_param param; }; static struct ata_force_ent *ata_force_tbl; static int ata_force_tbl_size; static char ata_force_param_buf[COMMAND_LINE_SIZE] __initdata; /* param_buf is thrown away after initialization, disallow read */ module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0); MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/admin-guide/kernel-parameters.rst for details)"); #endif static int atapi_enabled = 1; module_param(atapi_enabled, int, 0444); MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on [default])"); static int atapi_dmadir = 0; module_param(atapi_dmadir, int, 0444); MODULE_PARM_DESC(atapi_dmadir, "Enable ATAPI DMADIR bridge support (0=off [default], 1=on)"); int atapi_passthru16 = 1; module_param(atapi_passthru16, int, 0444); MODULE_PARM_DESC(atapi_passthru16, "Enable ATA_16 passthru for ATAPI devices (0=off, 1=on [default])"); int libata_fua = 0; module_param_named(fua, libata_fua, int, 0444); MODULE_PARM_DESC(fua, "FUA support (0=off [default], 1=on)"); static int ata_ignore_hpa; module_param_named(ignore_hpa, ata_ignore_hpa, int, 0644); MODULE_PARM_DESC(ignore_hpa, "Ignore HPA limit (0=keep BIOS limits, 1=ignore limits, using full disk)"); static int libata_dma_mask = ATA_DMA_MASK_ATA|ATA_DMA_MASK_ATAPI|ATA_DMA_MASK_CFA; module_param_named(dma, libata_dma_mask, int, 0444); MODULE_PARM_DESC(dma, "DMA enable/disable (0x1==ATA, 0x2==ATAPI, 0x4==CF)"); static int ata_probe_timeout; module_param(ata_probe_timeout, int, 0444); MODULE_PARM_DESC(ata_probe_timeout, "Set ATA probing timeout (seconds)"); int libata_noacpi = 0; module_param_named(noacpi, libata_noacpi, int, 0444); MODULE_PARM_DESC(noacpi, "Disable the use of ACPI in probe/suspend/resume (0=off [default], 1=on)"); int libata_allow_tpm = 0; module_param_named(allow_tpm, libata_allow_tpm, int, 0444); MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands (0=off [default], 1=on)"); static int atapi_an; module_param(atapi_an, int, 0444); MODULE_PARM_DESC(atapi_an, "Enable ATAPI AN media presence notification (0=0ff [default], 1=on)"); MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("Library module for ATA devices"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); static inline bool ata_dev_print_info(const struct ata_device *dev) { struct ata_eh_context *ehc = &dev->link->eh_context; return ehc->i.flags & ATA_EHI_PRINTINFO; } /** * ata_link_next - link iteration helper * @link: the previous link, NULL to start * @ap: ATA port containing links to iterate * @mode: iteration mode, one of ATA_LITER_* * * LOCKING: * Host lock or EH context. * * RETURNS: * Pointer to the next link. */ struct ata_link *ata_link_next(struct ata_link *link, struct ata_port *ap, enum ata_link_iter_mode mode) { BUG_ON(mode != ATA_LITER_EDGE && mode != ATA_LITER_PMP_FIRST && mode != ATA_LITER_HOST_FIRST); /* NULL link indicates start of iteration */ if (!link) switch (mode) { case ATA_LITER_EDGE: case ATA_LITER_PMP_FIRST: if (sata_pmp_attached(ap)) return ap->pmp_link; fallthrough; case ATA_LITER_HOST_FIRST: return &ap->link; } /* we just iterated over the host link, what's next? */ if (link == &ap->link) switch (mode) { case ATA_LITER_HOST_FIRST: if (sata_pmp_attached(ap)) return ap->pmp_link; fallthrough; case ATA_LITER_PMP_FIRST: if (unlikely(ap->slave_link)) return ap->slave_link; fallthrough; case ATA_LITER_EDGE: return NULL; } /* slave_link excludes PMP */ if (unlikely(link == ap->slave_link)) return NULL; /* we were over a PMP link */ if (++link < ap->pmp_link + ap->nr_pmp_links) return link; if (mode == ATA_LITER_PMP_FIRST) return &ap->link; return NULL; } EXPORT_SYMBOL_GPL(ata_link_next); /** * ata_dev_next - device iteration helper * @dev: the previous device, NULL to start * @link: ATA link containing devices to iterate * @mode: iteration mode, one of ATA_DITER_* * * LOCKING: * Host lock or EH context. * * RETURNS: * Pointer to the next device. */ struct ata_device *ata_dev_next(struct ata_device *dev, struct ata_link *link, enum ata_dev_iter_mode mode) { BUG_ON(mode != ATA_DITER_ENABLED && mode != ATA_DITER_ENABLED_REVERSE && mode != ATA_DITER_ALL && mode != ATA_DITER_ALL_REVERSE); /* NULL dev indicates start of iteration */ if (!dev) switch (mode) { case ATA_DITER_ENABLED: case ATA_DITER_ALL: dev = link->device; goto check; case ATA_DITER_ENABLED_REVERSE: case ATA_DITER_ALL_REVERSE: dev = link->device + ata_link_max_devices(link) - 1; goto check; } next: /* move to the next one */ switch (mode) { case ATA_DITER_ENABLED: case ATA_DITER_ALL: if (++dev < link->device + ata_link_max_devices(link)) goto check; return NULL; case ATA_DITER_ENABLED_REVERSE: case ATA_DITER_ALL_REVERSE: if (--dev >= link->device) goto check; return NULL; } check: if ((mode == ATA_DITER_ENABLED || mode == ATA_DITER_ENABLED_REVERSE) && !ata_dev_enabled(dev)) goto next; return dev; } EXPORT_SYMBOL_GPL(ata_dev_next); /** * ata_dev_phys_link - find physical link for a device * @dev: ATA device to look up physical link for * * Look up physical link which @dev is attached to. Note that * this is different from @dev->link only when @dev is on slave * link. For all other cases, it's the same as @dev->link. * * LOCKING: * Don't care. * * RETURNS: * Pointer to the found physical link. */ struct ata_link *ata_dev_phys_link(struct ata_device *dev) { struct ata_port *ap = dev->link->ap; if (!ap->slave_link) return dev->link; if (!dev->devno) return &ap->link; return ap->slave_link; } #ifdef CONFIG_ATA_FORCE /** * ata_force_cbl - force cable type according to libata.force * @ap: ATA port of interest * * Force cable type according to libata.force and whine about it. * The last entry which has matching port number is used, so it * can be specified as part of device force parameters. For * example, both "a:40c,1.00:udma4" and "1.00:40c,udma4" have the * same effect. * * LOCKING: * EH context. */ void ata_force_cbl(struct ata_port *ap) { int i; for (i = ata_force_tbl_size - 1; i >= 0; i--) { const struct ata_force_ent *fe = &ata_force_tbl[i]; if (fe->port != -1 && fe->port != ap->print_id) continue; if (fe->param.cbl == ATA_CBL_NONE) continue; ap->cbl = fe->param.cbl; ata_port_notice(ap, "FORCE: cable set to %s\n", fe->param.name); return; } } /** * ata_force_pflags - force port flags according to libata.force * @ap: ATA port of interest * * Force port flags according to libata.force and whine about it. * * LOCKING: * EH context. */ static void ata_force_pflags(struct ata_port *ap) { int i; for (i = ata_force_tbl_size - 1; i >= 0; i--) { const struct ata_force_ent *fe = &ata_force_tbl[i]; if (fe->port != -1 && fe->port != ap->print_id) continue; /* let pflags stack */ if (fe->param.pflags_on) { ap->pflags |= fe->param.pflags_on; ata_port_notice(ap, "FORCE: port flag 0x%x forced -> 0x%x\n", fe->param.pflags_on, ap->pflags); } } } /** * ata_force_link_limits - force link limits according to libata.force * @link: ATA link of interest * * Force link flags and SATA spd limit according to libata.force * and whine about it. When only the port part is specified * (e.g. 1:), the limit applies to all links connected to both * the host link and all fan-out ports connected via PMP. If the * device part is specified as 0 (e.g. 1.00:), it specifies the * first fan-out link not the host link. Device number 15 always * points to the host link whether PMP is attached or not. If the * controller has slave link, device number 16 points to it. * * LOCKING: * EH context. */ static void ata_force_link_limits(struct ata_link *link) { bool did_spd = false; int linkno = link->pmp; int i; if (ata_is_host_link(link)) linkno += 15; for (i = ata_force_tbl_size - 1; i >= 0; i--) { const struct ata_force_ent *fe = &ata_force_tbl[i]; if (fe->port != -1 && fe->port != link->ap->print_id) continue; if (fe->device != -1 && fe->device != linkno) continue; /* only honor the first spd limit */ if (!did_spd && fe->param.spd_limit) { link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1; ata_link_notice(link, "FORCE: PHY spd limit set to %s\n", fe->param.name); did_spd = true; } /* let lflags stack */ if (fe->param.lflags_on) { link->flags |= fe->param.lflags_on; ata_link_notice(link, "FORCE: link flag 0x%x forced -> 0x%x\n", fe->param.lflags_on, link->flags); } if (fe->param.lflags_off) { link->flags &= ~fe->param.lflags_off; ata_link_notice(link, "FORCE: link flag 0x%x cleared -> 0x%x\n", fe->param.lflags_off, link->flags); } } } /** * ata_force_xfermask - force xfermask according to libata.force * @dev: ATA device of interest * * Force xfer_mask according to libata.force and whine about it. * For consistency with link selection, device number 15 selects * the first device connected to the host link. * * LOCKING: * EH context. */ static void ata_force_xfermask(struct ata_device *dev) { int devno = dev->link->pmp + dev->devno; int alt_devno = devno; int i; /* allow n.15/16 for devices attached to host port */ if (ata_is_host_link(dev->link)) alt_devno += 15; for (i = ata_force_tbl_size - 1; i >= 0; i--) { const struct ata_force_ent *fe = &ata_force_tbl[i]; unsigned int pio_mask, mwdma_mask, udma_mask; if (fe->port != -1 && fe->port != dev->link->ap->print_id) continue; if (fe->device != -1 && fe->device != devno && fe->device != alt_devno) continue; if (!fe->param.xfer_mask) continue; ata_unpack_xfermask(fe->param.xfer_mask, &pio_mask, &mwdma_mask, &udma_mask); if (udma_mask) dev->udma_mask = udma_mask; else if (mwdma_mask) { dev->udma_mask = 0; dev->mwdma_mask = mwdma_mask; } else { dev->udma_mask = 0; dev->mwdma_mask = 0; dev->pio_mask = pio_mask; } ata_dev_notice(dev, "FORCE: xfer_mask set to %s\n", fe->param.name); return; } } static const struct ata_force_ent * ata_force_get_fe_for_dev(struct ata_device *dev) { const struct ata_force_ent *fe; int devno = dev->link->pmp + dev->devno; int alt_devno = devno; int i; /* allow n.15/16 for devices attached to host port */ if (ata_is_host_link(dev->link)) alt_devno += 15; for (i = 0; i < ata_force_tbl_size; i++) { fe = &ata_force_tbl[i]; if (fe->port != -1 && fe->port != dev->link->ap->print_id) continue; if (fe->device != -1 && fe->device != devno && fe->device != alt_devno) continue; return fe; }