// SPDX-License-Identifier: GPL-2.0-only /* * libata-pmp.c - libata port multiplier support * * Copyright (c) 2007 SUSE Linux Products GmbH * Copyright (c) 2007 Tejun Heo <[email protected]> */ #include <linux/kernel.h> #include <linux/export.h> #include <linux/libata.h> #include <linux/slab.h> #include "libata.h" #include "libata-transport.h" const struct ata_port_operations sata_pmp_port_ops = …; /** * sata_pmp_read - read PMP register * @link: link to read PMP register for * @reg: register to read * @r_val: resulting value * * Read PMP register. * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, AC_ERR_* mask on failure. */ static unsigned int sata_pmp_read(struct ata_link *link, int reg, u32 *r_val) { … } /** * sata_pmp_write - write PMP register * @link: link to write PMP register for * @reg: register to write * @val: value to write * * Write PMP register. * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, AC_ERR_* mask on failure. */ static unsigned int sata_pmp_write(struct ata_link *link, int reg, u32 val) { … } /** * sata_pmp_qc_defer_cmd_switch - qc_defer for command switching PMP * @qc: ATA command in question * * A host which has command switching PMP support cannot issue * commands to multiple links simultaneously. * * LOCKING: * spin_lock_irqsave(host lock) * * RETURNS: * ATA_DEFER_* if deferring is needed, 0 otherwise. */ int sata_pmp_qc_defer_cmd_switch(struct ata_queued_cmd *qc) { … } /** * sata_pmp_scr_read - read PSCR * @link: ATA link to read PSCR for * @reg: PSCR to read * @r_val: resulting value * * Read PSCR @reg into @r_val for @link, to be called from * ata_scr_read(). * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, -errno on failure. */ int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *r_val) { … } /** * sata_pmp_scr_write - write PSCR * @link: ATA link to write PSCR for * @reg: PSCR to write * @val: value to be written * * Write @val to PSCR @reg for @link, to be called from * ata_scr_write() and ata_scr_write_flush(). * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, -errno on failure. */ int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val) { … } /** * sata_pmp_set_lpm - configure LPM for a PMP link * @link: PMP link to configure LPM for * @policy: target LPM policy * @hints: LPM hints * * Configure LPM for @link. This function will contain any PMP * specific workarounds if necessary. * * LOCKING: * EH context. * * RETURNS: * 0 on success, -errno on failure. */ int sata_pmp_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, unsigned hints) { … } /** * sata_pmp_read_gscr - read GSCR block of SATA PMP * @dev: PMP device * @gscr: buffer to read GSCR block into * * Read selected PMP GSCRs from the PMP at @dev. This will serve * as configuration and identification info for the PMP. * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, -errno on failure. */ static int sata_pmp_read_gscr(struct ata_device *dev, u32 *gscr) { … } static const char *sata_pmp_spec_rev_str(const u32 *gscr) { … } #define PMP_GSCR_SII_POL … static int sata_pmp_configure(struct ata_device *dev, int print_info) { … } static int sata_pmp_init_links (struct ata_port *ap, int nr_ports) { … } static void sata_pmp_quirks(struct ata_port *ap) { … } /** * sata_pmp_attach - attach a SATA PMP device * @dev: SATA PMP device to attach * * Configure and attach SATA PMP device @dev. This function is * also responsible for allocating and initializing PMP links. * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, -errno on failure. */ int sata_pmp_attach(struct ata_device *dev) { … } /** * sata_pmp_detach - detach a SATA PMP device * @dev: SATA PMP device to detach * * Detach SATA PMP device @dev. This function is also * responsible for deconfiguring PMP links. * * LOCKING: * Kernel thread context (may sleep). */ static void sata_pmp_detach(struct ata_device *dev) { … } /** * sata_pmp_same_pmp - does new GSCR matches the configured PMP? * @dev: PMP device to compare against * @new_gscr: GSCR block of the new device * * Compare @new_gscr against @dev and determine whether @dev is * the PMP described by @new_gscr. * * LOCKING: * None. * * RETURNS: * 1 if @dev matches @new_gscr, 0 otherwise. */ static int sata_pmp_same_pmp(struct ata_device *dev, const u32 *new_gscr) { … } /** * sata_pmp_revalidate - revalidate SATA PMP * @dev: PMP device to revalidate * @new_class: new class code * * Re-read GSCR block and make sure @dev is still attached to the * port and properly configured. * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, -errno otherwise. */ static int sata_pmp_revalidate(struct ata_device *dev, unsigned int new_class) { … } /** * sata_pmp_revalidate_quick - revalidate SATA PMP quickly * @dev: PMP device to revalidate * * Make sure the attached PMP is accessible. * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, -errno otherwise. */ static int sata_pmp_revalidate_quick(struct ata_device *dev) { … } /** * sata_pmp_eh_recover_pmp - recover PMP * @ap: ATA port PMP is attached to * @prereset: prereset method (can be NULL) * @softreset: softreset method * @hardreset: hardreset method * @postreset: postreset method (can be NULL) * * Recover PMP attached to @ap. Recovery procedure is somewhat * similar to that of ata_eh_recover() except that reset should * always be performed in hard->soft sequence and recovery * failure results in PMP detachment. * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, -errno on failure. */ static int sata_pmp_eh_recover_pmp(struct ata_port *ap, ata_prereset_fn_t prereset, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { … } static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap) { … } static int sata_pmp_handle_link_fail(struct ata_link *link, int *link_tries) { … } /** * sata_pmp_eh_recover - recover PMP-enabled port * @ap: ATA port to recover * * Drive EH recovery operation for PMP enabled port @ap. This * function recovers host and PMP ports with proper retrials and * fallbacks. Actual recovery operations are performed using * ata_eh_recover() and sata_pmp_eh_recover_pmp(). * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, -errno on failure. */ static int sata_pmp_eh_recover(struct ata_port *ap) { … } /** * sata_pmp_error_handler - do standard error handling for PMP-enabled host * @ap: host port to handle error for * * Perform standard error handling sequence for PMP-enabled host * @ap. * * LOCKING: * Kernel thread context (may sleep). */ void sata_pmp_error_handler(struct ata_port *ap) { … } EXPORT_SYMBOL_GPL(…); EXPORT_SYMBOL_GPL(…); EXPORT_SYMBOL_GPL(…);