// SPDX-License-Identifier: GPL-2.0-or-later /* * SATA specific part of ATA helper library * * Copyright 2003-2004 Red Hat, Inc. All rights reserved. * Copyright 2003-2004 Jeff Garzik * Copyright 2006 Tejun Heo <[email protected]> */ #include <linux/kernel.h> #include <linux/module.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> #include <scsi/scsi_eh.h> #include <linux/libata.h> #include <asm/unaligned.h> #include "libata.h" #include "libata-transport.h" /* debounce timing parameters in msecs { interval, duration, timeout } */ const unsigned int sata_deb_timing_normal[] = …; EXPORT_SYMBOL_GPL(…); const unsigned int sata_deb_timing_hotplug[] = …; EXPORT_SYMBOL_GPL(…); const unsigned int sata_deb_timing_long[] = …; EXPORT_SYMBOL_GPL(…); /** * sata_scr_valid - test whether SCRs are accessible * @link: ATA link to test SCR accessibility for * * Test whether SCRs are accessible for @link. * * LOCKING: * None. * * RETURNS: * 1 if SCRs are accessible, 0 otherwise. */ int sata_scr_valid(struct ata_link *link) { … } EXPORT_SYMBOL_GPL(…); /** * sata_scr_read - read SCR register of the specified port * @link: ATA link to read SCR for * @reg: SCR to read * @val: Place to store read value * * Read SCR register @reg of @link into *@val. This function is * guaranteed to succeed if @link is ap->link, the cable type of * the port is SATA and the port implements ->scr_read. * * LOCKING: * None if @link is ap->link. Kernel thread context otherwise. * * RETURNS: * 0 on success, negative errno on failure. */ int sata_scr_read(struct ata_link *link, int reg, u32 *val) { … } EXPORT_SYMBOL_GPL(…); /** * sata_scr_write - write SCR register of the specified port * @link: ATA link to write SCR for * @reg: SCR to write * @val: value to write * * Write @val to SCR register @reg of @link. This function is * guaranteed to succeed if @link is ap->link, the cable type of * the port is SATA and the port implements ->scr_read. * * LOCKING: * None if @link is ap->link. Kernel thread context otherwise. * * RETURNS: * 0 on success, negative errno on failure. */ int sata_scr_write(struct ata_link *link, int reg, u32 val) { … } EXPORT_SYMBOL_GPL(…); /** * sata_scr_write_flush - write SCR register of the specified port and flush * @link: ATA link to write SCR for * @reg: SCR to write * @val: value to write * * This function is identical to sata_scr_write() except that this * function performs flush after writing to the register. * * LOCKING: * None if @link is ap->link. Kernel thread context otherwise. * * RETURNS: * 0 on success, negative errno on failure. */ int sata_scr_write_flush(struct ata_link *link, int reg, u32 val) { … } EXPORT_SYMBOL_GPL(…); /** * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure * @tf: Taskfile to convert * @pmp: Port multiplier port * @is_cmd: This FIS is for command * @fis: Buffer into which data will output * * Converts a standard ATA taskfile to a Serial ATA * FIS structure (Register - Host to Device). * * LOCKING: * Inherited from caller. */ void ata_tf_to_fis(const struct ata_taskfile *tf, u8 pmp, int is_cmd, u8 *fis) { … } EXPORT_SYMBOL_GPL(…); /** * ata_tf_from_fis - Convert SATA FIS to ATA taskfile * @fis: Buffer from which data will be input * @tf: Taskfile to output * * Converts a serial ATA FIS structure to a standard ATA taskfile. * * LOCKING: * Inherited from caller. */ void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf) { … } EXPORT_SYMBOL_GPL(…); /** * sata_link_debounce - debounce SATA phy status * @link: ATA link to debounce SATA phy status for * @params: timing parameters { interval, duration, timeout } in msec * @deadline: deadline jiffies for the operation * * Make sure SStatus of @link reaches stable state, determined by * holding the same value where DET is not 1 for @duration polled * every @interval, before @timeout. Timeout constraints the * beginning of the stable state. Because DET gets stuck at 1 on * some controllers after hot unplugging, this functions waits * until timeout then returns 0 if DET is stable at 1. * * @timeout is further limited by @deadline. The sooner of the * two is used. * * LOCKING: * Kernel thread context (may sleep) * * RETURNS: * 0 on success, -errno on failure. */ int sata_link_debounce(struct ata_link *link, const unsigned int *params, unsigned long deadline) { … } EXPORT_SYMBOL_GPL(…); /** * sata_link_resume - resume SATA link * @link: ATA link to resume SATA * @params: timing parameters { interval, duration, timeout } in msec * @deadline: deadline jiffies for the operation * * Resume SATA phy @link and debounce it. * * LOCKING: * Kernel thread context (may sleep) * * RETURNS: * 0 on success, -errno on failure. */ int sata_link_resume(struct ata_link *link, const unsigned int *params, unsigned long deadline) { … } EXPORT_SYMBOL_GPL(…); /** * sata_link_scr_lpm - manipulate SControl IPM and SPM fields * @link: ATA link to manipulate SControl for * @policy: LPM policy to configure * @spm_wakeup: initiate LPM transition to active state * * Manipulate the IPM field of the SControl register of @link * according to @policy. If @policy is ATA_LPM_MAX_POWER and * @spm_wakeup is %true, the SPM field is manipulated to wake up * the link. This function also clears PHYRDY_CHG before * returning. * * LOCKING: * EH context. * * RETURNS: * 0 on success, -errno otherwise. */ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy, bool spm_wakeup) { … } EXPORT_SYMBOL_GPL(…); static int __sata_set_spd_needed(struct ata_link *link, u32 *scontrol) { … } /** * sata_set_spd_needed - is SATA spd configuration needed * @link: Link in question * * Test whether the spd limit in SControl matches * @link->sata_spd_limit. This function is used to determine * whether hardreset is necessary to apply SATA spd * configuration. * * LOCKING: * Inherited from caller. * * RETURNS: * 1 if SATA spd configuration is needed, 0 otherwise. */ static int sata_set_spd_needed(struct ata_link *link) { … } /** * sata_set_spd - set SATA spd according to spd limit * @link: Link to set SATA spd for * * Set SATA spd of @link according to sata_spd_limit. * * LOCKING: * Inherited from caller. * * RETURNS: * 0 if spd doesn't need to be changed, 1 if spd has been * changed. Negative errno if SCR registers are inaccessible. */ int sata_set_spd(struct ata_link *link) { … } EXPORT_SYMBOL_GPL(…); /** * sata_link_hardreset - reset link via SATA phy reset * @link: link to reset * @timing: timing parameters { interval, duration, timeout } in msec * @deadline: deadline jiffies for the operation * @online: optional out parameter indicating link onlineness * @check_ready: optional callback to check link readiness * * SATA phy-reset @link using DET bits of SControl register. * After hardreset, link readiness is waited upon using * ata_wait_ready() if @check_ready is specified. LLDs are * allowed to not specify @check_ready and wait itself after this * function returns. Device classification is LLD's * responsibility. * * *@online is set to one iff reset succeeded and @link is online * after reset. * * LOCKING: * Kernel thread context (may sleep) * * RETURNS: * 0 on success, -errno otherwise. */ int sata_link_hardreset(struct ata_link *link, const unsigned int *timing, unsigned long deadline, bool *online, int (*check_ready)(struct ata_link *)) { … } EXPORT_SYMBOL_GPL(…); /** * ata_qc_complete_multiple - Complete multiple qcs successfully * @ap: port in question * @qc_active: new qc_active mask * * Complete in-flight commands. This functions is meant to be * called from low-level driver's interrupt routine to complete * requests normally. ap->qc_active and @qc_active is compared * and commands are completed accordingly. * * Always use this function when completing multiple NCQ commands * from IRQ handlers instead of calling ata_qc_complete() * multiple times to keep IRQ expect status properly in sync. * * LOCKING: * spin_lock_irqsave(host lock) * * RETURNS: * Number of completed commands on success, -errno otherwise. */ int ata_qc_complete_multiple(struct ata_port *ap, u64 qc_active) { … } EXPORT_SYMBOL_GPL(…); /** * ata_slave_link_init - initialize slave link * @ap: port to initialize slave link for * * Create and initialize slave link for @ap. This enables slave * link handling on the port. * * In libata, a port contains links and a link contains devices. * There is single host link but if a PMP is attached to it, * there can be multiple fan-out links. On SATA, there's usually * a single device connected to a link but PATA and SATA * controllers emulating TF based interface can have two - master * and slave. * * However, there are a few controllers which don't fit into this * abstraction too well - SATA controllers which emulate TF * interface with both master and slave devices but also have * separate SCR register sets for each device. These controllers * need separate links for physical link handling * (e.g. onlineness, link speed) but should be treated like a * traditional M/S controller for everything else (e.g. command * issue, softreset). * * slave_link is libata's way of handling this class of * controllers without impacting core layer too much. For * anything other than physical link handling, the default host * link is used for both master and slave. For physical link * handling, separate @ap->slave_link is used. All dirty details * are implemented inside libata core layer. From LLD's POV, the * only difference is that prereset, hardreset and postreset are * called once more for the slave link, so the reset sequence * looks like the following. * * prereset(M) -> prereset(S) -> hardreset(M) -> hardreset(S) -> * softreset(M) -> postreset(M) -> postreset(S) * * Note that softreset is called only for the master. Softreset * resets both M/S by definition, so SRST on master should handle * both (the standard method will work just fine). * * LOCKING: * Should be called before host is registered. * * RETURNS: * 0 on success, -errno on failure. */ int ata_slave_link_init(struct ata_port *ap) { … } EXPORT_SYMBOL_GPL(…); /** * sata_lpm_ignore_phy_events - test if PHY event should be ignored * @link: Link receiving the event * * Test whether the received PHY event has to be ignored or not. * * LOCKING: * None: * * RETURNS: * True if the event has to be ignored. */ bool sata_lpm_ignore_phy_events(struct ata_link *link) { … } EXPORT_SYMBOL_GPL(…); static const char *ata_lpm_policy_names[] = …; static ssize_t ata_scsi_lpm_store(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { … } static ssize_t ata_scsi_lpm_show(struct device *dev, struct device_attribute *attr, char *buf) { … } DEVICE_ATTR(…); EXPORT_SYMBOL_GPL(…); /** * ata_ncq_prio_supported - Check if device supports NCQ Priority * @ap: ATA port of the target device * @sdev: SCSI device * @supported: Address of a boolean to store the result * * Helper to check if device supports NCQ Priority feature. * * Context: Any context. Takes and releases @ap->lock. * * Return: * * %0 - OK. Status is stored into @supported * * %-ENODEV - Failed to find the ATA device */ int ata_ncq_prio_supported(struct ata_port *ap, struct scsi_device *sdev, bool *supported) { … } EXPORT_SYMBOL_GPL(…); static ssize_t ata_ncq_prio_supported_show(struct device *device, struct device_attribute *attr, char *buf) { … } DEVICE_ATTR(…); EXPORT_SYMBOL_GPL(…); /** * ata_ncq_prio_enabled - Check if NCQ Priority is enabled * @ap: ATA port of the target device * @sdev: SCSI device * @enabled: Address of a boolean to store the result * * Helper to check if NCQ Priority feature is enabled. * * Context: Any context. Takes and releases @ap->lock. * * Return: * * %0 - OK. Status is stored into @enabled * * %-ENODEV - Failed to find the ATA device */ int ata_ncq_prio_enabled(struct ata_port *ap, struct scsi_device *sdev, bool *enabled) { … } EXPORT_SYMBOL_GPL(…); static ssize_t ata_ncq_prio_enable_show(struct device *device, struct device_attribute *attr, char *buf) { … } /** * ata_ncq_prio_enable - Enable/disable NCQ Priority * @ap: ATA port of the target device * @sdev: SCSI device * @enable: true - enable NCQ Priority, false - disable NCQ Priority * * Helper to enable/disable NCQ Priority feature. * * Context: Any context. Takes and releases @ap->lock. * * Return: * * %0 - OK. Status is stored into @enabled * * %-ENODEV - Failed to find the ATA device * * %-EINVAL - NCQ Priority is not supported or CDL is enabled */ int ata_ncq_prio_enable(struct ata_port *ap, struct scsi_device *sdev, bool enable) { … } EXPORT_SYMBOL_GPL(…); static ssize_t ata_ncq_prio_enable_store(struct device *device, struct device_attribute *attr, const char *buf, size_t len) { … } DEVICE_ATTR(…); EXPORT_SYMBOL_GPL(…); static struct attribute *ata_ncq_sdev_attrs[] = …; static const struct attribute_group ata_ncq_sdev_attr_group = …; const struct attribute_group *ata_ncq_sdev_groups[] = …; EXPORT_SYMBOL_GPL(…); static ssize_t ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { … } static ssize_t ata_scsi_em_message_show(struct device *dev, struct device_attribute *attr, char *buf) { … } DEVICE_ATTR(…); EXPORT_SYMBOL_GPL(…); static ssize_t ata_scsi_em_message_type_show(struct device *dev, struct device_attribute *attr, char *buf) { … } DEVICE_ATTR(…); EXPORT_SYMBOL_GPL(…); static ssize_t ata_scsi_activity_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t ata_scsi_activity_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { … } DEVICE_ATTR(…); EXPORT_SYMBOL_GPL(…); /** * ata_change_queue_depth - Set a device maximum queue depth * @ap: ATA port of the target device * @sdev: SCSI device to configure queue depth for * @queue_depth: new queue depth * * Helper to set a device maximum queue depth, usable with both libsas * and libata. * */ int ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev, int queue_depth) { … } EXPORT_SYMBOL_GPL(…); /** * ata_scsi_change_queue_depth - SCSI callback for queue depth config * @sdev: SCSI device to configure queue depth for * @queue_depth: new queue depth * * This is libata standard hostt->change_queue_depth callback. * SCSI will call into this callback when user tries to set queue * depth via sysfs. * * LOCKING: * SCSI layer (we don't care) * * RETURNS: * Newly configured queue depth. */ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth) { … } EXPORT_SYMBOL_GPL(…); /** * ata_sas_device_configure - Default device_configure routine for libata * devices * @sdev: SCSI device to configure * @lim: queue limits * @ap: ATA port to which SCSI device is attached * * RETURNS: * Zero. */ int ata_sas_device_configure(struct scsi_device *sdev, struct queue_limits *lim, struct ata_port *ap) { … } EXPORT_SYMBOL_GPL(…); /** * ata_sas_queuecmd - Issue SCSI cdb to libata-managed device * @cmd: SCSI command to be sent * @ap: ATA port to which the command is being sent * * RETURNS: * Return value from __ata_scsi_queuecmd() if @cmd can be queued, * 0 otherwise. */ int ata_sas_queuecmd(struct scsi_cmnd *cmd, struct ata_port *ap) { … } EXPORT_SYMBOL_GPL(…); /** * sata_async_notification - SATA async notification handler * @ap: ATA port where async notification is received * * Handler to be called when async notification via SDB FIS is * received. This function schedules EH if necessary. * * LOCKING: * spin_lock_irqsave(host lock) * * RETURNS: * 1 if EH is scheduled, 0 otherwise. */ int sata_async_notification(struct ata_port *ap) { … } EXPORT_SYMBOL_GPL(…); /** * ata_eh_read_log_10h - Read log page 10h for NCQ error details * @dev: Device to read log page 10h from * @tag: Resulting tag of the failed command * @tf: Resulting taskfile registers of the failed command * * Read log page 10h to obtain NCQ error details and clear error * condition. * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, -errno otherwise. */ static int ata_eh_read_log_10h(struct ata_device *dev, int *tag, struct ata_taskfile *tf) { … } /** * ata_eh_read_sense_success_ncq_log - Read the sense data for successful * NCQ commands log * @link: ATA link to get sense data for * * Read the sense data for successful NCQ commands log page to obtain * sense data for all NCQ commands that completed successfully with * the sense data available bit set. * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, -errno otherwise. */ int ata_eh_read_sense_success_ncq_log(struct ata_link *link) { … } EXPORT_SYMBOL_GPL(…); /** * ata_eh_analyze_ncq_error - analyze NCQ error * @link: ATA link to analyze NCQ error for * * Read log page 10h, determine the offending qc and acquire * error status TF. For NCQ device errors, all LLDDs have to do * is setting AC_ERR_DEV in ehi->err_mask. This function takes * care of the rest. * * LOCKING: * Kernel thread context (may sleep). */ void ata_eh_analyze_ncq_error(struct ata_link *link) { … } EXPORT_SYMBOL_GPL(…);