18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * SATA specific part of ATA helper library 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2003-2004 Red Hat, Inc. All rights reserved. 68c2ecf20Sopenharmony_ci * Copyright 2003-2004 Jeff Garzik 78c2ecf20Sopenharmony_ci * Copyright 2006 Tejun Heo <htejun@gmail.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <scsi/scsi_cmnd.h> 138c2ecf20Sopenharmony_ci#include <scsi/scsi_device.h> 148c2ecf20Sopenharmony_ci#include <linux/libata.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "libata.h" 178c2ecf20Sopenharmony_ci#include "libata-transport.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* debounce timing parameters in msecs { interval, duration, timeout } */ 208c2ecf20Sopenharmony_ciconst unsigned long sata_deb_timing_normal[] = { 5, 100, 2000 }; 218c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sata_deb_timing_normal); 228c2ecf20Sopenharmony_ciconst unsigned long sata_deb_timing_hotplug[] = { 25, 500, 2000 }; 238c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sata_deb_timing_hotplug); 248c2ecf20Sopenharmony_ciconst unsigned long sata_deb_timing_long[] = { 100, 2000, 5000 }; 258c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sata_deb_timing_long); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/** 288c2ecf20Sopenharmony_ci * sata_scr_valid - test whether SCRs are accessible 298c2ecf20Sopenharmony_ci * @link: ATA link to test SCR accessibility for 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * Test whether SCRs are accessible for @link. 328c2ecf20Sopenharmony_ci * 338c2ecf20Sopenharmony_ci * LOCKING: 348c2ecf20Sopenharmony_ci * None. 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci * RETURNS: 378c2ecf20Sopenharmony_ci * 1 if SCRs are accessible, 0 otherwise. 388c2ecf20Sopenharmony_ci */ 398c2ecf20Sopenharmony_ciint sata_scr_valid(struct ata_link *link) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci struct ata_port *ap = link->ap; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci return (ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read; 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sata_scr_valid); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci/** 488c2ecf20Sopenharmony_ci * sata_scr_read - read SCR register of the specified port 498c2ecf20Sopenharmony_ci * @link: ATA link to read SCR for 508c2ecf20Sopenharmony_ci * @reg: SCR to read 518c2ecf20Sopenharmony_ci * @val: Place to store read value 528c2ecf20Sopenharmony_ci * 538c2ecf20Sopenharmony_ci * Read SCR register @reg of @link into *@val. This function is 548c2ecf20Sopenharmony_ci * guaranteed to succeed if @link is ap->link, the cable type of 558c2ecf20Sopenharmony_ci * the port is SATA and the port implements ->scr_read. 568c2ecf20Sopenharmony_ci * 578c2ecf20Sopenharmony_ci * LOCKING: 588c2ecf20Sopenharmony_ci * None if @link is ap->link. Kernel thread context otherwise. 598c2ecf20Sopenharmony_ci * 608c2ecf20Sopenharmony_ci * RETURNS: 618c2ecf20Sopenharmony_ci * 0 on success, negative errno on failure. 628c2ecf20Sopenharmony_ci */ 638c2ecf20Sopenharmony_ciint sata_scr_read(struct ata_link *link, int reg, u32 *val) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci if (ata_is_host_link(link)) { 668c2ecf20Sopenharmony_ci if (sata_scr_valid(link)) 678c2ecf20Sopenharmony_ci return link->ap->ops->scr_read(link, reg, val); 688c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci return sata_pmp_scr_read(link, reg, val); 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sata_scr_read); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/** 768c2ecf20Sopenharmony_ci * sata_scr_write - write SCR register of the specified port 778c2ecf20Sopenharmony_ci * @link: ATA link to write SCR for 788c2ecf20Sopenharmony_ci * @reg: SCR to write 798c2ecf20Sopenharmony_ci * @val: value to write 808c2ecf20Sopenharmony_ci * 818c2ecf20Sopenharmony_ci * Write @val to SCR register @reg of @link. This function is 828c2ecf20Sopenharmony_ci * guaranteed to succeed if @link is ap->link, the cable type of 838c2ecf20Sopenharmony_ci * the port is SATA and the port implements ->scr_read. 848c2ecf20Sopenharmony_ci * 858c2ecf20Sopenharmony_ci * LOCKING: 868c2ecf20Sopenharmony_ci * None if @link is ap->link. Kernel thread context otherwise. 878c2ecf20Sopenharmony_ci * 888c2ecf20Sopenharmony_ci * RETURNS: 898c2ecf20Sopenharmony_ci * 0 on success, negative errno on failure. 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_ciint sata_scr_write(struct ata_link *link, int reg, u32 val) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci if (ata_is_host_link(link)) { 948c2ecf20Sopenharmony_ci if (sata_scr_valid(link)) 958c2ecf20Sopenharmony_ci return link->ap->ops->scr_write(link, reg, val); 968c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci return sata_pmp_scr_write(link, reg, val); 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sata_scr_write); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci/** 1048c2ecf20Sopenharmony_ci * sata_scr_write_flush - write SCR register of the specified port and flush 1058c2ecf20Sopenharmony_ci * @link: ATA link to write SCR for 1068c2ecf20Sopenharmony_ci * @reg: SCR to write 1078c2ecf20Sopenharmony_ci * @val: value to write 1088c2ecf20Sopenharmony_ci * 1098c2ecf20Sopenharmony_ci * This function is identical to sata_scr_write() except that this 1108c2ecf20Sopenharmony_ci * function performs flush after writing to the register. 1118c2ecf20Sopenharmony_ci * 1128c2ecf20Sopenharmony_ci * LOCKING: 1138c2ecf20Sopenharmony_ci * None if @link is ap->link. Kernel thread context otherwise. 1148c2ecf20Sopenharmony_ci * 1158c2ecf20Sopenharmony_ci * RETURNS: 1168c2ecf20Sopenharmony_ci * 0 on success, negative errno on failure. 1178c2ecf20Sopenharmony_ci */ 1188c2ecf20Sopenharmony_ciint sata_scr_write_flush(struct ata_link *link, int reg, u32 val) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci if (ata_is_host_link(link)) { 1218c2ecf20Sopenharmony_ci int rc; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci if (sata_scr_valid(link)) { 1248c2ecf20Sopenharmony_ci rc = link->ap->ops->scr_write(link, reg, val); 1258c2ecf20Sopenharmony_ci if (rc == 0) 1268c2ecf20Sopenharmony_ci rc = link->ap->ops->scr_read(link, reg, &val); 1278c2ecf20Sopenharmony_ci return rc; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci return sata_pmp_scr_write(link, reg, val); 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sata_scr_write_flush); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci/** 1378c2ecf20Sopenharmony_ci * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure 1388c2ecf20Sopenharmony_ci * @tf: Taskfile to convert 1398c2ecf20Sopenharmony_ci * @pmp: Port multiplier port 1408c2ecf20Sopenharmony_ci * @is_cmd: This FIS is for command 1418c2ecf20Sopenharmony_ci * @fis: Buffer into which data will output 1428c2ecf20Sopenharmony_ci * 1438c2ecf20Sopenharmony_ci * Converts a standard ATA taskfile to a Serial ATA 1448c2ecf20Sopenharmony_ci * FIS structure (Register - Host to Device). 1458c2ecf20Sopenharmony_ci * 1468c2ecf20Sopenharmony_ci * LOCKING: 1478c2ecf20Sopenharmony_ci * Inherited from caller. 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_civoid ata_tf_to_fis(const struct ata_taskfile *tf, u8 pmp, int is_cmd, u8 *fis) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci fis[0] = 0x27; /* Register - Host to Device FIS */ 1528c2ecf20Sopenharmony_ci fis[1] = pmp & 0xf; /* Port multiplier number*/ 1538c2ecf20Sopenharmony_ci if (is_cmd) 1548c2ecf20Sopenharmony_ci fis[1] |= (1 << 7); /* bit 7 indicates Command FIS */ 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci fis[2] = tf->command; 1578c2ecf20Sopenharmony_ci fis[3] = tf->feature; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci fis[4] = tf->lbal; 1608c2ecf20Sopenharmony_ci fis[5] = tf->lbam; 1618c2ecf20Sopenharmony_ci fis[6] = tf->lbah; 1628c2ecf20Sopenharmony_ci fis[7] = tf->device; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci fis[8] = tf->hob_lbal; 1658c2ecf20Sopenharmony_ci fis[9] = tf->hob_lbam; 1668c2ecf20Sopenharmony_ci fis[10] = tf->hob_lbah; 1678c2ecf20Sopenharmony_ci fis[11] = tf->hob_feature; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci fis[12] = tf->nsect; 1708c2ecf20Sopenharmony_ci fis[13] = tf->hob_nsect; 1718c2ecf20Sopenharmony_ci fis[14] = 0; 1728c2ecf20Sopenharmony_ci fis[15] = tf->ctl; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci fis[16] = tf->auxiliary & 0xff; 1758c2ecf20Sopenharmony_ci fis[17] = (tf->auxiliary >> 8) & 0xff; 1768c2ecf20Sopenharmony_ci fis[18] = (tf->auxiliary >> 16) & 0xff; 1778c2ecf20Sopenharmony_ci fis[19] = (tf->auxiliary >> 24) & 0xff; 1788c2ecf20Sopenharmony_ci} 1798c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_tf_to_fis); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci/** 1828c2ecf20Sopenharmony_ci * ata_tf_from_fis - Convert SATA FIS to ATA taskfile 1838c2ecf20Sopenharmony_ci * @fis: Buffer from which data will be input 1848c2ecf20Sopenharmony_ci * @tf: Taskfile to output 1858c2ecf20Sopenharmony_ci * 1868c2ecf20Sopenharmony_ci * Converts a serial ATA FIS structure to a standard ATA taskfile. 1878c2ecf20Sopenharmony_ci * 1888c2ecf20Sopenharmony_ci * LOCKING: 1898c2ecf20Sopenharmony_ci * Inherited from caller. 1908c2ecf20Sopenharmony_ci */ 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_civoid ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci tf->command = fis[2]; /* status */ 1958c2ecf20Sopenharmony_ci tf->feature = fis[3]; /* error */ 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci tf->lbal = fis[4]; 1988c2ecf20Sopenharmony_ci tf->lbam = fis[5]; 1998c2ecf20Sopenharmony_ci tf->lbah = fis[6]; 2008c2ecf20Sopenharmony_ci tf->device = fis[7]; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci tf->hob_lbal = fis[8]; 2038c2ecf20Sopenharmony_ci tf->hob_lbam = fis[9]; 2048c2ecf20Sopenharmony_ci tf->hob_lbah = fis[10]; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci tf->nsect = fis[12]; 2078c2ecf20Sopenharmony_ci tf->hob_nsect = fis[13]; 2088c2ecf20Sopenharmony_ci} 2098c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_tf_from_fis); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci/** 2128c2ecf20Sopenharmony_ci * sata_link_debounce - debounce SATA phy status 2138c2ecf20Sopenharmony_ci * @link: ATA link to debounce SATA phy status for 2148c2ecf20Sopenharmony_ci * @params: timing parameters { interval, duration, timeout } in msec 2158c2ecf20Sopenharmony_ci * @deadline: deadline jiffies for the operation 2168c2ecf20Sopenharmony_ci * 2178c2ecf20Sopenharmony_ci * Make sure SStatus of @link reaches stable state, determined by 2188c2ecf20Sopenharmony_ci * holding the same value where DET is not 1 for @duration polled 2198c2ecf20Sopenharmony_ci * every @interval, before @timeout. Timeout constraints the 2208c2ecf20Sopenharmony_ci * beginning of the stable state. Because DET gets stuck at 1 on 2218c2ecf20Sopenharmony_ci * some controllers after hot unplugging, this functions waits 2228c2ecf20Sopenharmony_ci * until timeout then returns 0 if DET is stable at 1. 2238c2ecf20Sopenharmony_ci * 2248c2ecf20Sopenharmony_ci * @timeout is further limited by @deadline. The sooner of the 2258c2ecf20Sopenharmony_ci * two is used. 2268c2ecf20Sopenharmony_ci * 2278c2ecf20Sopenharmony_ci * LOCKING: 2288c2ecf20Sopenharmony_ci * Kernel thread context (may sleep) 2298c2ecf20Sopenharmony_ci * 2308c2ecf20Sopenharmony_ci * RETURNS: 2318c2ecf20Sopenharmony_ci * 0 on success, -errno on failure. 2328c2ecf20Sopenharmony_ci */ 2338c2ecf20Sopenharmony_ciint sata_link_debounce(struct ata_link *link, const unsigned long *params, 2348c2ecf20Sopenharmony_ci unsigned long deadline) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci unsigned long interval = params[0]; 2378c2ecf20Sopenharmony_ci unsigned long duration = params[1]; 2388c2ecf20Sopenharmony_ci unsigned long last_jiffies, t; 2398c2ecf20Sopenharmony_ci u32 last, cur; 2408c2ecf20Sopenharmony_ci int rc; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci t = ata_deadline(jiffies, params[2]); 2438c2ecf20Sopenharmony_ci if (time_before(t, deadline)) 2448c2ecf20Sopenharmony_ci deadline = t; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci if ((rc = sata_scr_read(link, SCR_STATUS, &cur))) 2478c2ecf20Sopenharmony_ci return rc; 2488c2ecf20Sopenharmony_ci cur &= 0xf; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci last = cur; 2518c2ecf20Sopenharmony_ci last_jiffies = jiffies; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci while (1) { 2548c2ecf20Sopenharmony_ci ata_msleep(link->ap, interval); 2558c2ecf20Sopenharmony_ci if ((rc = sata_scr_read(link, SCR_STATUS, &cur))) 2568c2ecf20Sopenharmony_ci return rc; 2578c2ecf20Sopenharmony_ci cur &= 0xf; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci /* DET stable? */ 2608c2ecf20Sopenharmony_ci if (cur == last) { 2618c2ecf20Sopenharmony_ci if (cur == 1 && time_before(jiffies, deadline)) 2628c2ecf20Sopenharmony_ci continue; 2638c2ecf20Sopenharmony_ci if (time_after(jiffies, 2648c2ecf20Sopenharmony_ci ata_deadline(last_jiffies, duration))) 2658c2ecf20Sopenharmony_ci return 0; 2668c2ecf20Sopenharmony_ci continue; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci /* unstable, start over */ 2708c2ecf20Sopenharmony_ci last = cur; 2718c2ecf20Sopenharmony_ci last_jiffies = jiffies; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* Check deadline. If debouncing failed, return 2748c2ecf20Sopenharmony_ci * -EPIPE to tell upper layer to lower link speed. 2758c2ecf20Sopenharmony_ci */ 2768c2ecf20Sopenharmony_ci if (time_after(jiffies, deadline)) 2778c2ecf20Sopenharmony_ci return -EPIPE; 2788c2ecf20Sopenharmony_ci } 2798c2ecf20Sopenharmony_ci} 2808c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sata_link_debounce); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci/** 2838c2ecf20Sopenharmony_ci * sata_link_resume - resume SATA link 2848c2ecf20Sopenharmony_ci * @link: ATA link to resume SATA 2858c2ecf20Sopenharmony_ci * @params: timing parameters { interval, duration, timeout } in msec 2868c2ecf20Sopenharmony_ci * @deadline: deadline jiffies for the operation 2878c2ecf20Sopenharmony_ci * 2888c2ecf20Sopenharmony_ci * Resume SATA phy @link and debounce it. 2898c2ecf20Sopenharmony_ci * 2908c2ecf20Sopenharmony_ci * LOCKING: 2918c2ecf20Sopenharmony_ci * Kernel thread context (may sleep) 2928c2ecf20Sopenharmony_ci * 2938c2ecf20Sopenharmony_ci * RETURNS: 2948c2ecf20Sopenharmony_ci * 0 on success, -errno on failure. 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_ciint sata_link_resume(struct ata_link *link, const unsigned long *params, 2978c2ecf20Sopenharmony_ci unsigned long deadline) 2988c2ecf20Sopenharmony_ci{ 2998c2ecf20Sopenharmony_ci int tries = ATA_LINK_RESUME_TRIES; 3008c2ecf20Sopenharmony_ci u32 scontrol, serror; 3018c2ecf20Sopenharmony_ci int rc; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol))) 3048c2ecf20Sopenharmony_ci return rc; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci /* 3078c2ecf20Sopenharmony_ci * Writes to SControl sometimes get ignored under certain 3088c2ecf20Sopenharmony_ci * controllers (ata_piix SIDPR). Make sure DET actually is 3098c2ecf20Sopenharmony_ci * cleared. 3108c2ecf20Sopenharmony_ci */ 3118c2ecf20Sopenharmony_ci do { 3128c2ecf20Sopenharmony_ci scontrol = (scontrol & 0x0f0) | 0x300; 3138c2ecf20Sopenharmony_ci if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol))) 3148c2ecf20Sopenharmony_ci return rc; 3158c2ecf20Sopenharmony_ci /* 3168c2ecf20Sopenharmony_ci * Some PHYs react badly if SStatus is pounded 3178c2ecf20Sopenharmony_ci * immediately after resuming. Delay 200ms before 3188c2ecf20Sopenharmony_ci * debouncing. 3198c2ecf20Sopenharmony_ci */ 3208c2ecf20Sopenharmony_ci if (!(link->flags & ATA_LFLAG_NO_DEBOUNCE_DELAY)) 3218c2ecf20Sopenharmony_ci ata_msleep(link->ap, 200); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci /* is SControl restored correctly? */ 3248c2ecf20Sopenharmony_ci if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol))) 3258c2ecf20Sopenharmony_ci return rc; 3268c2ecf20Sopenharmony_ci } while ((scontrol & 0xf0f) != 0x300 && --tries); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci if ((scontrol & 0xf0f) != 0x300) { 3298c2ecf20Sopenharmony_ci ata_link_warn(link, "failed to resume link (SControl %X)\n", 3308c2ecf20Sopenharmony_ci scontrol); 3318c2ecf20Sopenharmony_ci return 0; 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci if (tries < ATA_LINK_RESUME_TRIES) 3358c2ecf20Sopenharmony_ci ata_link_warn(link, "link resume succeeded after %d retries\n", 3368c2ecf20Sopenharmony_ci ATA_LINK_RESUME_TRIES - tries); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci if ((rc = sata_link_debounce(link, params, deadline))) 3398c2ecf20Sopenharmony_ci return rc; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci /* clear SError, some PHYs require this even for SRST to work */ 3428c2ecf20Sopenharmony_ci if (!(rc = sata_scr_read(link, SCR_ERROR, &serror))) 3438c2ecf20Sopenharmony_ci rc = sata_scr_write(link, SCR_ERROR, serror); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci return rc != -EINVAL ? rc : 0; 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sata_link_resume); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci/** 3508c2ecf20Sopenharmony_ci * sata_link_scr_lpm - manipulate SControl IPM and SPM fields 3518c2ecf20Sopenharmony_ci * @link: ATA link to manipulate SControl for 3528c2ecf20Sopenharmony_ci * @policy: LPM policy to configure 3538c2ecf20Sopenharmony_ci * @spm_wakeup: initiate LPM transition to active state 3548c2ecf20Sopenharmony_ci * 3558c2ecf20Sopenharmony_ci * Manipulate the IPM field of the SControl register of @link 3568c2ecf20Sopenharmony_ci * according to @policy. If @policy is ATA_LPM_MAX_POWER and 3578c2ecf20Sopenharmony_ci * @spm_wakeup is %true, the SPM field is manipulated to wake up 3588c2ecf20Sopenharmony_ci * the link. This function also clears PHYRDY_CHG before 3598c2ecf20Sopenharmony_ci * returning. 3608c2ecf20Sopenharmony_ci * 3618c2ecf20Sopenharmony_ci * LOCKING: 3628c2ecf20Sopenharmony_ci * EH context. 3638c2ecf20Sopenharmony_ci * 3648c2ecf20Sopenharmony_ci * RETURNS: 3658c2ecf20Sopenharmony_ci * 0 on success, -errno otherwise. 3668c2ecf20Sopenharmony_ci */ 3678c2ecf20Sopenharmony_ciint sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy, 3688c2ecf20Sopenharmony_ci bool spm_wakeup) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci struct ata_eh_context *ehc = &link->eh_context; 3718c2ecf20Sopenharmony_ci bool woken_up = false; 3728c2ecf20Sopenharmony_ci u32 scontrol; 3738c2ecf20Sopenharmony_ci int rc; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci rc = sata_scr_read(link, SCR_CONTROL, &scontrol); 3768c2ecf20Sopenharmony_ci if (rc) 3778c2ecf20Sopenharmony_ci return rc; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci switch (policy) { 3808c2ecf20Sopenharmony_ci case ATA_LPM_MAX_POWER: 3818c2ecf20Sopenharmony_ci /* disable all LPM transitions */ 3828c2ecf20Sopenharmony_ci scontrol |= (0x7 << 8); 3838c2ecf20Sopenharmony_ci /* initiate transition to active state */ 3848c2ecf20Sopenharmony_ci if (spm_wakeup) { 3858c2ecf20Sopenharmony_ci scontrol |= (0x4 << 12); 3868c2ecf20Sopenharmony_ci woken_up = true; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci break; 3898c2ecf20Sopenharmony_ci case ATA_LPM_MED_POWER: 3908c2ecf20Sopenharmony_ci /* allow LPM to PARTIAL */ 3918c2ecf20Sopenharmony_ci scontrol &= ~(0x1 << 8); 3928c2ecf20Sopenharmony_ci scontrol |= (0x6 << 8); 3938c2ecf20Sopenharmony_ci break; 3948c2ecf20Sopenharmony_ci case ATA_LPM_MED_POWER_WITH_DIPM: 3958c2ecf20Sopenharmony_ci case ATA_LPM_MIN_POWER_WITH_PARTIAL: 3968c2ecf20Sopenharmony_ci case ATA_LPM_MIN_POWER: 3978c2ecf20Sopenharmony_ci if (ata_link_nr_enabled(link) > 0) { 3988c2ecf20Sopenharmony_ci /* assume no restrictions on LPM transitions */ 3998c2ecf20Sopenharmony_ci scontrol &= ~(0x7 << 8); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci /* 4028c2ecf20Sopenharmony_ci * If the controller does not support partial, slumber, 4038c2ecf20Sopenharmony_ci * or devsleep, then disallow these transitions. 4048c2ecf20Sopenharmony_ci */ 4058c2ecf20Sopenharmony_ci if (link->ap->host->flags & ATA_HOST_NO_PART) 4068c2ecf20Sopenharmony_ci scontrol |= (0x1 << 8); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci if (link->ap->host->flags & ATA_HOST_NO_SSC) 4098c2ecf20Sopenharmony_ci scontrol |= (0x2 << 8); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci if (link->ap->host->flags & ATA_HOST_NO_DEVSLP) 4128c2ecf20Sopenharmony_ci scontrol |= (0x4 << 8); 4138c2ecf20Sopenharmony_ci } else { 4148c2ecf20Sopenharmony_ci /* empty port, power off */ 4158c2ecf20Sopenharmony_ci scontrol &= ~0xf; 4168c2ecf20Sopenharmony_ci scontrol |= (0x1 << 2); 4178c2ecf20Sopenharmony_ci } 4188c2ecf20Sopenharmony_ci break; 4198c2ecf20Sopenharmony_ci default: 4208c2ecf20Sopenharmony_ci WARN_ON(1); 4218c2ecf20Sopenharmony_ci } 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci rc = sata_scr_write(link, SCR_CONTROL, scontrol); 4248c2ecf20Sopenharmony_ci if (rc) 4258c2ecf20Sopenharmony_ci return rc; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci /* give the link time to transit out of LPM state */ 4288c2ecf20Sopenharmony_ci if (woken_up) 4298c2ecf20Sopenharmony_ci msleep(10); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci /* clear PHYRDY_CHG from SError */ 4328c2ecf20Sopenharmony_ci ehc->i.serror &= ~SERR_PHYRDY_CHG; 4338c2ecf20Sopenharmony_ci return sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG); 4348c2ecf20Sopenharmony_ci} 4358c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sata_link_scr_lpm); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_cistatic int __sata_set_spd_needed(struct ata_link *link, u32 *scontrol) 4388c2ecf20Sopenharmony_ci{ 4398c2ecf20Sopenharmony_ci struct ata_link *host_link = &link->ap->link; 4408c2ecf20Sopenharmony_ci u32 limit, target, spd; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci limit = link->sata_spd_limit; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci /* Don't configure downstream link faster than upstream link. 4458c2ecf20Sopenharmony_ci * It doesn't speed up anything and some PMPs choke on such 4468c2ecf20Sopenharmony_ci * configuration. 4478c2ecf20Sopenharmony_ci */ 4488c2ecf20Sopenharmony_ci if (!ata_is_host_link(link) && host_link->sata_spd) 4498c2ecf20Sopenharmony_ci limit &= (1 << host_link->sata_spd) - 1; 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci if (limit == UINT_MAX) 4528c2ecf20Sopenharmony_ci target = 0; 4538c2ecf20Sopenharmony_ci else 4548c2ecf20Sopenharmony_ci target = fls(limit); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci spd = (*scontrol >> 4) & 0xf; 4578c2ecf20Sopenharmony_ci *scontrol = (*scontrol & ~0xf0) | ((target & 0xf) << 4); 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci return spd != target; 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci/** 4638c2ecf20Sopenharmony_ci * sata_set_spd_needed - is SATA spd configuration needed 4648c2ecf20Sopenharmony_ci * @link: Link in question 4658c2ecf20Sopenharmony_ci * 4668c2ecf20Sopenharmony_ci * Test whether the spd limit in SControl matches 4678c2ecf20Sopenharmony_ci * @link->sata_spd_limit. This function is used to determine 4688c2ecf20Sopenharmony_ci * whether hardreset is necessary to apply SATA spd 4698c2ecf20Sopenharmony_ci * configuration. 4708c2ecf20Sopenharmony_ci * 4718c2ecf20Sopenharmony_ci * LOCKING: 4728c2ecf20Sopenharmony_ci * Inherited from caller. 4738c2ecf20Sopenharmony_ci * 4748c2ecf20Sopenharmony_ci * RETURNS: 4758c2ecf20Sopenharmony_ci * 1 if SATA spd configuration is needed, 0 otherwise. 4768c2ecf20Sopenharmony_ci */ 4778c2ecf20Sopenharmony_cistatic int sata_set_spd_needed(struct ata_link *link) 4788c2ecf20Sopenharmony_ci{ 4798c2ecf20Sopenharmony_ci u32 scontrol; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci if (sata_scr_read(link, SCR_CONTROL, &scontrol)) 4828c2ecf20Sopenharmony_ci return 1; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci return __sata_set_spd_needed(link, &scontrol); 4858c2ecf20Sopenharmony_ci} 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci/** 4888c2ecf20Sopenharmony_ci * sata_set_spd - set SATA spd according to spd limit 4898c2ecf20Sopenharmony_ci * @link: Link to set SATA spd for 4908c2ecf20Sopenharmony_ci * 4918c2ecf20Sopenharmony_ci * Set SATA spd of @link according to sata_spd_limit. 4928c2ecf20Sopenharmony_ci * 4938c2ecf20Sopenharmony_ci * LOCKING: 4948c2ecf20Sopenharmony_ci * Inherited from caller. 4958c2ecf20Sopenharmony_ci * 4968c2ecf20Sopenharmony_ci * RETURNS: 4978c2ecf20Sopenharmony_ci * 0 if spd doesn't need to be changed, 1 if spd has been 4988c2ecf20Sopenharmony_ci * changed. Negative errno if SCR registers are inaccessible. 4998c2ecf20Sopenharmony_ci */ 5008c2ecf20Sopenharmony_ciint sata_set_spd(struct ata_link *link) 5018c2ecf20Sopenharmony_ci{ 5028c2ecf20Sopenharmony_ci u32 scontrol; 5038c2ecf20Sopenharmony_ci int rc; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol))) 5068c2ecf20Sopenharmony_ci return rc; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci if (!__sata_set_spd_needed(link, &scontrol)) 5098c2ecf20Sopenharmony_ci return 0; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol))) 5128c2ecf20Sopenharmony_ci return rc; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci return 1; 5158c2ecf20Sopenharmony_ci} 5168c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sata_set_spd); 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci/** 5198c2ecf20Sopenharmony_ci * sata_link_hardreset - reset link via SATA phy reset 5208c2ecf20Sopenharmony_ci * @link: link to reset 5218c2ecf20Sopenharmony_ci * @timing: timing parameters { interval, duration, timeout } in msec 5228c2ecf20Sopenharmony_ci * @deadline: deadline jiffies for the operation 5238c2ecf20Sopenharmony_ci * @online: optional out parameter indicating link onlineness 5248c2ecf20Sopenharmony_ci * @check_ready: optional callback to check link readiness 5258c2ecf20Sopenharmony_ci * 5268c2ecf20Sopenharmony_ci * SATA phy-reset @link using DET bits of SControl register. 5278c2ecf20Sopenharmony_ci * After hardreset, link readiness is waited upon using 5288c2ecf20Sopenharmony_ci * ata_wait_ready() if @check_ready is specified. LLDs are 5298c2ecf20Sopenharmony_ci * allowed to not specify @check_ready and wait itself after this 5308c2ecf20Sopenharmony_ci * function returns. Device classification is LLD's 5318c2ecf20Sopenharmony_ci * responsibility. 5328c2ecf20Sopenharmony_ci * 5338c2ecf20Sopenharmony_ci * *@online is set to one iff reset succeeded and @link is online 5348c2ecf20Sopenharmony_ci * after reset. 5358c2ecf20Sopenharmony_ci * 5368c2ecf20Sopenharmony_ci * LOCKING: 5378c2ecf20Sopenharmony_ci * Kernel thread context (may sleep) 5388c2ecf20Sopenharmony_ci * 5398c2ecf20Sopenharmony_ci * RETURNS: 5408c2ecf20Sopenharmony_ci * 0 on success, -errno otherwise. 5418c2ecf20Sopenharmony_ci */ 5428c2ecf20Sopenharmony_ciint sata_link_hardreset(struct ata_link *link, const unsigned long *timing, 5438c2ecf20Sopenharmony_ci unsigned long deadline, 5448c2ecf20Sopenharmony_ci bool *online, int (*check_ready)(struct ata_link *)) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci u32 scontrol; 5478c2ecf20Sopenharmony_ci int rc; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci DPRINTK("ENTER\n"); 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci if (online) 5528c2ecf20Sopenharmony_ci *online = false; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci if (sata_set_spd_needed(link)) { 5558c2ecf20Sopenharmony_ci /* SATA spec says nothing about how to reconfigure 5568c2ecf20Sopenharmony_ci * spd. To be on the safe side, turn off phy during 5578c2ecf20Sopenharmony_ci * reconfiguration. This works for at least ICH7 AHCI 5588c2ecf20Sopenharmony_ci * and Sil3124. 5598c2ecf20Sopenharmony_ci */ 5608c2ecf20Sopenharmony_ci if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol))) 5618c2ecf20Sopenharmony_ci goto out; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci scontrol = (scontrol & 0x0f0) | 0x304; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol))) 5668c2ecf20Sopenharmony_ci goto out; 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci sata_set_spd(link); 5698c2ecf20Sopenharmony_ci } 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci /* issue phy wake/reset */ 5728c2ecf20Sopenharmony_ci if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol))) 5738c2ecf20Sopenharmony_ci goto out; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci scontrol = (scontrol & 0x0f0) | 0x301; 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci if ((rc = sata_scr_write_flush(link, SCR_CONTROL, scontrol))) 5788c2ecf20Sopenharmony_ci goto out; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci /* Couldn't find anything in SATA I/II specs, but AHCI-1.1 5818c2ecf20Sopenharmony_ci * 10.4.2 says at least 1 ms. 5828c2ecf20Sopenharmony_ci */ 5838c2ecf20Sopenharmony_ci ata_msleep(link->ap, 1); 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci /* bring link back */ 5868c2ecf20Sopenharmony_ci rc = sata_link_resume(link, timing, deadline); 5878c2ecf20Sopenharmony_ci if (rc) 5888c2ecf20Sopenharmony_ci goto out; 5898c2ecf20Sopenharmony_ci /* if link is offline nothing more to do */ 5908c2ecf20Sopenharmony_ci if (ata_phys_link_offline(link)) 5918c2ecf20Sopenharmony_ci goto out; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci /* Link is online. From this point, -ENODEV too is an error. */ 5948c2ecf20Sopenharmony_ci if (online) 5958c2ecf20Sopenharmony_ci *online = true; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci if (sata_pmp_supported(link->ap) && ata_is_host_link(link)) { 5988c2ecf20Sopenharmony_ci /* If PMP is supported, we have to do follow-up SRST. 5998c2ecf20Sopenharmony_ci * Some PMPs don't send D2H Reg FIS after hardreset if 6008c2ecf20Sopenharmony_ci * the first port is empty. Wait only for 6018c2ecf20Sopenharmony_ci * ATA_TMOUT_PMP_SRST_WAIT. 6028c2ecf20Sopenharmony_ci */ 6038c2ecf20Sopenharmony_ci if (check_ready) { 6048c2ecf20Sopenharmony_ci unsigned long pmp_deadline; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci pmp_deadline = ata_deadline(jiffies, 6078c2ecf20Sopenharmony_ci ATA_TMOUT_PMP_SRST_WAIT); 6088c2ecf20Sopenharmony_ci if (time_after(pmp_deadline, deadline)) 6098c2ecf20Sopenharmony_ci pmp_deadline = deadline; 6108c2ecf20Sopenharmony_ci ata_wait_ready(link, pmp_deadline, check_ready); 6118c2ecf20Sopenharmony_ci } 6128c2ecf20Sopenharmony_ci rc = -EAGAIN; 6138c2ecf20Sopenharmony_ci goto out; 6148c2ecf20Sopenharmony_ci } 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci rc = 0; 6178c2ecf20Sopenharmony_ci if (check_ready) 6188c2ecf20Sopenharmony_ci rc = ata_wait_ready(link, deadline, check_ready); 6198c2ecf20Sopenharmony_ci out: 6208c2ecf20Sopenharmony_ci if (rc && rc != -EAGAIN) { 6218c2ecf20Sopenharmony_ci /* online is set iff link is online && reset succeeded */ 6228c2ecf20Sopenharmony_ci if (online) 6238c2ecf20Sopenharmony_ci *online = false; 6248c2ecf20Sopenharmony_ci ata_link_err(link, "COMRESET failed (errno=%d)\n", rc); 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci DPRINTK("EXIT, rc=%d\n", rc); 6278c2ecf20Sopenharmony_ci return rc; 6288c2ecf20Sopenharmony_ci} 6298c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sata_link_hardreset); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci/** 6328c2ecf20Sopenharmony_ci * ata_qc_complete_multiple - Complete multiple qcs successfully 6338c2ecf20Sopenharmony_ci * @ap: port in question 6348c2ecf20Sopenharmony_ci * @qc_active: new qc_active mask 6358c2ecf20Sopenharmony_ci * 6368c2ecf20Sopenharmony_ci * Complete in-flight commands. This functions is meant to be 6378c2ecf20Sopenharmony_ci * called from low-level driver's interrupt routine to complete 6388c2ecf20Sopenharmony_ci * requests normally. ap->qc_active and @qc_active is compared 6398c2ecf20Sopenharmony_ci * and commands are completed accordingly. 6408c2ecf20Sopenharmony_ci * 6418c2ecf20Sopenharmony_ci * Always use this function when completing multiple NCQ commands 6428c2ecf20Sopenharmony_ci * from IRQ handlers instead of calling ata_qc_complete() 6438c2ecf20Sopenharmony_ci * multiple times to keep IRQ expect status properly in sync. 6448c2ecf20Sopenharmony_ci * 6458c2ecf20Sopenharmony_ci * LOCKING: 6468c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 6478c2ecf20Sopenharmony_ci * 6488c2ecf20Sopenharmony_ci * RETURNS: 6498c2ecf20Sopenharmony_ci * Number of completed commands on success, -errno otherwise. 6508c2ecf20Sopenharmony_ci */ 6518c2ecf20Sopenharmony_ciint ata_qc_complete_multiple(struct ata_port *ap, u64 qc_active) 6528c2ecf20Sopenharmony_ci{ 6538c2ecf20Sopenharmony_ci u64 done_mask, ap_qc_active = ap->qc_active; 6548c2ecf20Sopenharmony_ci int nr_done = 0; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci /* 6578c2ecf20Sopenharmony_ci * If the internal tag is set on ap->qc_active, then we care about 6588c2ecf20Sopenharmony_ci * bit0 on the passed in qc_active mask. Move that bit up to match 6598c2ecf20Sopenharmony_ci * the internal tag. 6608c2ecf20Sopenharmony_ci */ 6618c2ecf20Sopenharmony_ci if (ap_qc_active & (1ULL << ATA_TAG_INTERNAL)) { 6628c2ecf20Sopenharmony_ci qc_active |= (qc_active & 0x01) << ATA_TAG_INTERNAL; 6638c2ecf20Sopenharmony_ci qc_active ^= qc_active & 0x01; 6648c2ecf20Sopenharmony_ci } 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci done_mask = ap_qc_active ^ qc_active; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci if (unlikely(done_mask & qc_active)) { 6698c2ecf20Sopenharmony_ci ata_port_err(ap, "illegal qc_active transition (%08llx->%08llx)\n", 6708c2ecf20Sopenharmony_ci ap->qc_active, qc_active); 6718c2ecf20Sopenharmony_ci return -EINVAL; 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci while (done_mask) { 6758c2ecf20Sopenharmony_ci struct ata_queued_cmd *qc; 6768c2ecf20Sopenharmony_ci unsigned int tag = __ffs64(done_mask); 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci qc = ata_qc_from_tag(ap, tag); 6798c2ecf20Sopenharmony_ci if (qc) { 6808c2ecf20Sopenharmony_ci ata_qc_complete(qc); 6818c2ecf20Sopenharmony_ci nr_done++; 6828c2ecf20Sopenharmony_ci } 6838c2ecf20Sopenharmony_ci done_mask &= ~(1ULL << tag); 6848c2ecf20Sopenharmony_ci } 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci return nr_done; 6878c2ecf20Sopenharmony_ci} 6888c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_qc_complete_multiple); 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci/** 6918c2ecf20Sopenharmony_ci * ata_slave_link_init - initialize slave link 6928c2ecf20Sopenharmony_ci * @ap: port to initialize slave link for 6938c2ecf20Sopenharmony_ci * 6948c2ecf20Sopenharmony_ci * Create and initialize slave link for @ap. This enables slave 6958c2ecf20Sopenharmony_ci * link handling on the port. 6968c2ecf20Sopenharmony_ci * 6978c2ecf20Sopenharmony_ci * In libata, a port contains links and a link contains devices. 6988c2ecf20Sopenharmony_ci * There is single host link but if a PMP is attached to it, 6998c2ecf20Sopenharmony_ci * there can be multiple fan-out links. On SATA, there's usually 7008c2ecf20Sopenharmony_ci * a single device connected to a link but PATA and SATA 7018c2ecf20Sopenharmony_ci * controllers emulating TF based interface can have two - master 7028c2ecf20Sopenharmony_ci * and slave. 7038c2ecf20Sopenharmony_ci * 7048c2ecf20Sopenharmony_ci * However, there are a few controllers which don't fit into this 7058c2ecf20Sopenharmony_ci * abstraction too well - SATA controllers which emulate TF 7068c2ecf20Sopenharmony_ci * interface with both master and slave devices but also have 7078c2ecf20Sopenharmony_ci * separate SCR register sets for each device. These controllers 7088c2ecf20Sopenharmony_ci * need separate links for physical link handling 7098c2ecf20Sopenharmony_ci * (e.g. onlineness, link speed) but should be treated like a 7108c2ecf20Sopenharmony_ci * traditional M/S controller for everything else (e.g. command 7118c2ecf20Sopenharmony_ci * issue, softreset). 7128c2ecf20Sopenharmony_ci * 7138c2ecf20Sopenharmony_ci * slave_link is libata's way of handling this class of 7148c2ecf20Sopenharmony_ci * controllers without impacting core layer too much. For 7158c2ecf20Sopenharmony_ci * anything other than physical link handling, the default host 7168c2ecf20Sopenharmony_ci * link is used for both master and slave. For physical link 7178c2ecf20Sopenharmony_ci * handling, separate @ap->slave_link is used. All dirty details 7188c2ecf20Sopenharmony_ci * are implemented inside libata core layer. From LLD's POV, the 7198c2ecf20Sopenharmony_ci * only difference is that prereset, hardreset and postreset are 7208c2ecf20Sopenharmony_ci * called once more for the slave link, so the reset sequence 7218c2ecf20Sopenharmony_ci * looks like the following. 7228c2ecf20Sopenharmony_ci * 7238c2ecf20Sopenharmony_ci * prereset(M) -> prereset(S) -> hardreset(M) -> hardreset(S) -> 7248c2ecf20Sopenharmony_ci * softreset(M) -> postreset(M) -> postreset(S) 7258c2ecf20Sopenharmony_ci * 7268c2ecf20Sopenharmony_ci * Note that softreset is called only for the master. Softreset 7278c2ecf20Sopenharmony_ci * resets both M/S by definition, so SRST on master should handle 7288c2ecf20Sopenharmony_ci * both (the standard method will work just fine). 7298c2ecf20Sopenharmony_ci * 7308c2ecf20Sopenharmony_ci * LOCKING: 7318c2ecf20Sopenharmony_ci * Should be called before host is registered. 7328c2ecf20Sopenharmony_ci * 7338c2ecf20Sopenharmony_ci * RETURNS: 7348c2ecf20Sopenharmony_ci * 0 on success, -errno on failure. 7358c2ecf20Sopenharmony_ci */ 7368c2ecf20Sopenharmony_ciint ata_slave_link_init(struct ata_port *ap) 7378c2ecf20Sopenharmony_ci{ 7388c2ecf20Sopenharmony_ci struct ata_link *link; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci WARN_ON(ap->slave_link); 7418c2ecf20Sopenharmony_ci WARN_ON(ap->flags & ATA_FLAG_PMP); 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci link = kzalloc(sizeof(*link), GFP_KERNEL); 7448c2ecf20Sopenharmony_ci if (!link) 7458c2ecf20Sopenharmony_ci return -ENOMEM; 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci ata_link_init(ap, link, 1); 7488c2ecf20Sopenharmony_ci ap->slave_link = link; 7498c2ecf20Sopenharmony_ci return 0; 7508c2ecf20Sopenharmony_ci} 7518c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_slave_link_init); 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci/** 7548c2ecf20Sopenharmony_ci * sata_lpm_ignore_phy_events - test if PHY event should be ignored 7558c2ecf20Sopenharmony_ci * @link: Link receiving the event 7568c2ecf20Sopenharmony_ci * 7578c2ecf20Sopenharmony_ci * Test whether the received PHY event has to be ignored or not. 7588c2ecf20Sopenharmony_ci * 7598c2ecf20Sopenharmony_ci * LOCKING: 7608c2ecf20Sopenharmony_ci * None: 7618c2ecf20Sopenharmony_ci * 7628c2ecf20Sopenharmony_ci * RETURNS: 7638c2ecf20Sopenharmony_ci * True if the event has to be ignored. 7648c2ecf20Sopenharmony_ci */ 7658c2ecf20Sopenharmony_cibool sata_lpm_ignore_phy_events(struct ata_link *link) 7668c2ecf20Sopenharmony_ci{ 7678c2ecf20Sopenharmony_ci unsigned long lpm_timeout = link->last_lpm_change + 7688c2ecf20Sopenharmony_ci msecs_to_jiffies(ATA_TMOUT_SPURIOUS_PHY); 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci /* if LPM is enabled, PHYRDY doesn't mean anything */ 7718c2ecf20Sopenharmony_ci if (link->lpm_policy > ATA_LPM_MAX_POWER) 7728c2ecf20Sopenharmony_ci return true; 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci /* ignore the first PHY event after the LPM policy changed 7758c2ecf20Sopenharmony_ci * as it is might be spurious 7768c2ecf20Sopenharmony_ci */ 7778c2ecf20Sopenharmony_ci if ((link->flags & ATA_LFLAG_CHANGED) && 7788c2ecf20Sopenharmony_ci time_before(jiffies, lpm_timeout)) 7798c2ecf20Sopenharmony_ci return true; 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci return false; 7828c2ecf20Sopenharmony_ci} 7838c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sata_lpm_ignore_phy_events); 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_cistatic const char *ata_lpm_policy_names[] = { 7868c2ecf20Sopenharmony_ci [ATA_LPM_UNKNOWN] = "max_performance", 7878c2ecf20Sopenharmony_ci [ATA_LPM_MAX_POWER] = "max_performance", 7888c2ecf20Sopenharmony_ci [ATA_LPM_MED_POWER] = "medium_power", 7898c2ecf20Sopenharmony_ci [ATA_LPM_MED_POWER_WITH_DIPM] = "med_power_with_dipm", 7908c2ecf20Sopenharmony_ci [ATA_LPM_MIN_POWER_WITH_PARTIAL] = "min_power_with_partial", 7918c2ecf20Sopenharmony_ci [ATA_LPM_MIN_POWER] = "min_power", 7928c2ecf20Sopenharmony_ci}; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_cistatic ssize_t ata_scsi_lpm_store(struct device *device, 7958c2ecf20Sopenharmony_ci struct device_attribute *attr, 7968c2ecf20Sopenharmony_ci const char *buf, size_t count) 7978c2ecf20Sopenharmony_ci{ 7988c2ecf20Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(device); 7998c2ecf20Sopenharmony_ci struct ata_port *ap = ata_shost_to_port(shost); 8008c2ecf20Sopenharmony_ci struct ata_link *link; 8018c2ecf20Sopenharmony_ci struct ata_device *dev; 8028c2ecf20Sopenharmony_ci enum ata_lpm_policy policy; 8038c2ecf20Sopenharmony_ci unsigned long flags; 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci /* UNKNOWN is internal state, iterate from MAX_POWER */ 8068c2ecf20Sopenharmony_ci for (policy = ATA_LPM_MAX_POWER; 8078c2ecf20Sopenharmony_ci policy < ARRAY_SIZE(ata_lpm_policy_names); policy++) { 8088c2ecf20Sopenharmony_ci const char *name = ata_lpm_policy_names[policy]; 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci if (strncmp(name, buf, strlen(name)) == 0) 8118c2ecf20Sopenharmony_ci break; 8128c2ecf20Sopenharmony_ci } 8138c2ecf20Sopenharmony_ci if (policy == ARRAY_SIZE(ata_lpm_policy_names)) 8148c2ecf20Sopenharmony_ci return -EINVAL; 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci spin_lock_irqsave(ap->lock, flags); 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci ata_for_each_link(link, ap, EDGE) { 8198c2ecf20Sopenharmony_ci ata_for_each_dev(dev, &ap->link, ENABLED) { 8208c2ecf20Sopenharmony_ci if (dev->horkage & ATA_HORKAGE_NOLPM) { 8218c2ecf20Sopenharmony_ci count = -EOPNOTSUPP; 8228c2ecf20Sopenharmony_ci goto out_unlock; 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci } 8258c2ecf20Sopenharmony_ci } 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci ap->target_lpm_policy = policy; 8288c2ecf20Sopenharmony_ci ata_port_schedule_eh(ap); 8298c2ecf20Sopenharmony_ciout_unlock: 8308c2ecf20Sopenharmony_ci spin_unlock_irqrestore(ap->lock, flags); 8318c2ecf20Sopenharmony_ci return count; 8328c2ecf20Sopenharmony_ci} 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_cistatic ssize_t ata_scsi_lpm_show(struct device *dev, 8358c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 8368c2ecf20Sopenharmony_ci{ 8378c2ecf20Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 8388c2ecf20Sopenharmony_ci struct ata_port *ap = ata_shost_to_port(shost); 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci if (ap->target_lpm_policy >= ARRAY_SIZE(ata_lpm_policy_names)) 8418c2ecf20Sopenharmony_ci return -EINVAL; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci return snprintf(buf, PAGE_SIZE, "%s\n", 8448c2ecf20Sopenharmony_ci ata_lpm_policy_names[ap->target_lpm_policy]); 8458c2ecf20Sopenharmony_ci} 8468c2ecf20Sopenharmony_ciDEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR, 8478c2ecf20Sopenharmony_ci ata_scsi_lpm_show, ata_scsi_lpm_store); 8488c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy); 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_cistatic ssize_t ata_ncq_prio_enable_show(struct device *device, 8518c2ecf20Sopenharmony_ci struct device_attribute *attr, 8528c2ecf20Sopenharmony_ci char *buf) 8538c2ecf20Sopenharmony_ci{ 8548c2ecf20Sopenharmony_ci struct scsi_device *sdev = to_scsi_device(device); 8558c2ecf20Sopenharmony_ci struct ata_port *ap; 8568c2ecf20Sopenharmony_ci struct ata_device *dev; 8578c2ecf20Sopenharmony_ci bool ncq_prio_enable; 8588c2ecf20Sopenharmony_ci int rc = 0; 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci ap = ata_shost_to_port(sdev->host); 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci spin_lock_irq(ap->lock); 8638c2ecf20Sopenharmony_ci dev = ata_scsi_find_dev(ap, sdev); 8648c2ecf20Sopenharmony_ci if (!dev) { 8658c2ecf20Sopenharmony_ci rc = -ENODEV; 8668c2ecf20Sopenharmony_ci goto unlock; 8678c2ecf20Sopenharmony_ci } 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci ncq_prio_enable = dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLE; 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ciunlock: 8728c2ecf20Sopenharmony_ci spin_unlock_irq(ap->lock); 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci return rc ? rc : snprintf(buf, 20, "%u\n", ncq_prio_enable); 8758c2ecf20Sopenharmony_ci} 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_cistatic ssize_t ata_ncq_prio_enable_store(struct device *device, 8788c2ecf20Sopenharmony_ci struct device_attribute *attr, 8798c2ecf20Sopenharmony_ci const char *buf, size_t len) 8808c2ecf20Sopenharmony_ci{ 8818c2ecf20Sopenharmony_ci struct scsi_device *sdev = to_scsi_device(device); 8828c2ecf20Sopenharmony_ci struct ata_port *ap; 8838c2ecf20Sopenharmony_ci struct ata_device *dev; 8848c2ecf20Sopenharmony_ci long int input; 8858c2ecf20Sopenharmony_ci int rc; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci rc = kstrtol(buf, 10, &input); 8888c2ecf20Sopenharmony_ci if (rc) 8898c2ecf20Sopenharmony_ci return rc; 8908c2ecf20Sopenharmony_ci if ((input < 0) || (input > 1)) 8918c2ecf20Sopenharmony_ci return -EINVAL; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci ap = ata_shost_to_port(sdev->host); 8948c2ecf20Sopenharmony_ci dev = ata_scsi_find_dev(ap, sdev); 8958c2ecf20Sopenharmony_ci if (unlikely(!dev)) 8968c2ecf20Sopenharmony_ci return -ENODEV; 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci spin_lock_irq(ap->lock); 8998c2ecf20Sopenharmony_ci if (input) 9008c2ecf20Sopenharmony_ci dev->flags |= ATA_DFLAG_NCQ_PRIO_ENABLE; 9018c2ecf20Sopenharmony_ci else 9028c2ecf20Sopenharmony_ci dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLE; 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci dev->link->eh_info.action |= ATA_EH_REVALIDATE; 9058c2ecf20Sopenharmony_ci dev->link->eh_info.flags |= ATA_EHI_QUIET; 9068c2ecf20Sopenharmony_ci ata_port_schedule_eh(ap); 9078c2ecf20Sopenharmony_ci spin_unlock_irq(ap->lock); 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci ata_port_wait_eh(ap); 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci if (input) { 9128c2ecf20Sopenharmony_ci spin_lock_irq(ap->lock); 9138c2ecf20Sopenharmony_ci if (!(dev->flags & ATA_DFLAG_NCQ_PRIO)) { 9148c2ecf20Sopenharmony_ci dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLE; 9158c2ecf20Sopenharmony_ci rc = -EIO; 9168c2ecf20Sopenharmony_ci } 9178c2ecf20Sopenharmony_ci spin_unlock_irq(ap->lock); 9188c2ecf20Sopenharmony_ci } 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci return rc ? rc : len; 9218c2ecf20Sopenharmony_ci} 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ciDEVICE_ATTR(ncq_prio_enable, S_IRUGO | S_IWUSR, 9248c2ecf20Sopenharmony_ci ata_ncq_prio_enable_show, ata_ncq_prio_enable_store); 9258c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dev_attr_ncq_prio_enable); 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_cistruct device_attribute *ata_ncq_sdev_attrs[] = { 9288c2ecf20Sopenharmony_ci &dev_attr_unload_heads, 9298c2ecf20Sopenharmony_ci &dev_attr_ncq_prio_enable, 9308c2ecf20Sopenharmony_ci NULL 9318c2ecf20Sopenharmony_ci}; 9328c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_ncq_sdev_attrs); 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_cistatic ssize_t 9358c2ecf20Sopenharmony_ciata_scsi_em_message_store(struct device *dev, struct device_attribute *attr, 9368c2ecf20Sopenharmony_ci const char *buf, size_t count) 9378c2ecf20Sopenharmony_ci{ 9388c2ecf20Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 9398c2ecf20Sopenharmony_ci struct ata_port *ap = ata_shost_to_port(shost); 9408c2ecf20Sopenharmony_ci if (ap->ops->em_store && (ap->flags & ATA_FLAG_EM)) 9418c2ecf20Sopenharmony_ci return ap->ops->em_store(ap, buf, count); 9428c2ecf20Sopenharmony_ci return -EINVAL; 9438c2ecf20Sopenharmony_ci} 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_cistatic ssize_t 9468c2ecf20Sopenharmony_ciata_scsi_em_message_show(struct device *dev, struct device_attribute *attr, 9478c2ecf20Sopenharmony_ci char *buf) 9488c2ecf20Sopenharmony_ci{ 9498c2ecf20Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 9508c2ecf20Sopenharmony_ci struct ata_port *ap = ata_shost_to_port(shost); 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci if (ap->ops->em_show && (ap->flags & ATA_FLAG_EM)) 9538c2ecf20Sopenharmony_ci return ap->ops->em_show(ap, buf); 9548c2ecf20Sopenharmony_ci return -EINVAL; 9558c2ecf20Sopenharmony_ci} 9568c2ecf20Sopenharmony_ciDEVICE_ATTR(em_message, S_IRUGO | S_IWUSR, 9578c2ecf20Sopenharmony_ci ata_scsi_em_message_show, ata_scsi_em_message_store); 9588c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dev_attr_em_message); 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_cistatic ssize_t 9618c2ecf20Sopenharmony_ciata_scsi_em_message_type_show(struct device *dev, struct device_attribute *attr, 9628c2ecf20Sopenharmony_ci char *buf) 9638c2ecf20Sopenharmony_ci{ 9648c2ecf20Sopenharmony_ci struct Scsi_Host *shost = class_to_shost(dev); 9658c2ecf20Sopenharmony_ci struct ata_port *ap = ata_shost_to_port(shost); 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci return snprintf(buf, 23, "%d\n", ap->em_message_type); 9688c2ecf20Sopenharmony_ci} 9698c2ecf20Sopenharmony_ciDEVICE_ATTR(em_message_type, S_IRUGO, 9708c2ecf20Sopenharmony_ci ata_scsi_em_message_type_show, NULL); 9718c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dev_attr_em_message_type); 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_cistatic ssize_t 9748c2ecf20Sopenharmony_ciata_scsi_activity_show(struct device *dev, struct device_attribute *attr, 9758c2ecf20Sopenharmony_ci char *buf) 9768c2ecf20Sopenharmony_ci{ 9778c2ecf20Sopenharmony_ci struct scsi_device *sdev = to_scsi_device(dev); 9788c2ecf20Sopenharmony_ci struct ata_port *ap = ata_shost_to_port(sdev->host); 9798c2ecf20Sopenharmony_ci struct ata_device *atadev = ata_scsi_find_dev(ap, sdev); 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci if (atadev && ap->ops->sw_activity_show && 9828c2ecf20Sopenharmony_ci (ap->flags & ATA_FLAG_SW_ACTIVITY)) 9838c2ecf20Sopenharmony_ci return ap->ops->sw_activity_show(atadev, buf); 9848c2ecf20Sopenharmony_ci return -EINVAL; 9858c2ecf20Sopenharmony_ci} 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_cistatic ssize_t 9888c2ecf20Sopenharmony_ciata_scsi_activity_store(struct device *dev, struct device_attribute *attr, 9898c2ecf20Sopenharmony_ci const char *buf, size_t count) 9908c2ecf20Sopenharmony_ci{ 9918c2ecf20Sopenharmony_ci struct scsi_device *sdev = to_scsi_device(dev); 9928c2ecf20Sopenharmony_ci struct ata_port *ap = ata_shost_to_port(sdev->host); 9938c2ecf20Sopenharmony_ci struct ata_device *atadev = ata_scsi_find_dev(ap, sdev); 9948c2ecf20Sopenharmony_ci enum sw_activity val; 9958c2ecf20Sopenharmony_ci int rc; 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci if (atadev && ap->ops->sw_activity_store && 9988c2ecf20Sopenharmony_ci (ap->flags & ATA_FLAG_SW_ACTIVITY)) { 9998c2ecf20Sopenharmony_ci val = simple_strtoul(buf, NULL, 0); 10008c2ecf20Sopenharmony_ci switch (val) { 10018c2ecf20Sopenharmony_ci case OFF: case BLINK_ON: case BLINK_OFF: 10028c2ecf20Sopenharmony_ci rc = ap->ops->sw_activity_store(atadev, val); 10038c2ecf20Sopenharmony_ci if (!rc) 10048c2ecf20Sopenharmony_ci return count; 10058c2ecf20Sopenharmony_ci else 10068c2ecf20Sopenharmony_ci return rc; 10078c2ecf20Sopenharmony_ci } 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci return -EINVAL; 10108c2ecf20Sopenharmony_ci} 10118c2ecf20Sopenharmony_ciDEVICE_ATTR(sw_activity, S_IWUSR | S_IRUGO, ata_scsi_activity_show, 10128c2ecf20Sopenharmony_ci ata_scsi_activity_store); 10138c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dev_attr_sw_activity); 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci/** 10168c2ecf20Sopenharmony_ci * __ata_change_queue_depth - helper for ata_scsi_change_queue_depth 10178c2ecf20Sopenharmony_ci * @ap: ATA port to which the device change the queue depth 10188c2ecf20Sopenharmony_ci * @sdev: SCSI device to configure queue depth for 10198c2ecf20Sopenharmony_ci * @queue_depth: new queue depth 10208c2ecf20Sopenharmony_ci * 10218c2ecf20Sopenharmony_ci * libsas and libata have different approaches for associating a sdev to 10228c2ecf20Sopenharmony_ci * its ata_port. 10238c2ecf20Sopenharmony_ci * 10248c2ecf20Sopenharmony_ci */ 10258c2ecf20Sopenharmony_ciint __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev, 10268c2ecf20Sopenharmony_ci int queue_depth) 10278c2ecf20Sopenharmony_ci{ 10288c2ecf20Sopenharmony_ci struct ata_device *dev; 10298c2ecf20Sopenharmony_ci unsigned long flags; 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci if (queue_depth < 1 || queue_depth == sdev->queue_depth) 10328c2ecf20Sopenharmony_ci return sdev->queue_depth; 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci dev = ata_scsi_find_dev(ap, sdev); 10358c2ecf20Sopenharmony_ci if (!dev || !ata_dev_enabled(dev)) 10368c2ecf20Sopenharmony_ci return sdev->queue_depth; 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci /* NCQ enabled? */ 10398c2ecf20Sopenharmony_ci spin_lock_irqsave(ap->lock, flags); 10408c2ecf20Sopenharmony_ci dev->flags &= ~ATA_DFLAG_NCQ_OFF; 10418c2ecf20Sopenharmony_ci if (queue_depth == 1 || !ata_ncq_enabled(dev)) { 10428c2ecf20Sopenharmony_ci dev->flags |= ATA_DFLAG_NCQ_OFF; 10438c2ecf20Sopenharmony_ci queue_depth = 1; 10448c2ecf20Sopenharmony_ci } 10458c2ecf20Sopenharmony_ci spin_unlock_irqrestore(ap->lock, flags); 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci /* limit and apply queue depth */ 10488c2ecf20Sopenharmony_ci queue_depth = min(queue_depth, sdev->host->can_queue); 10498c2ecf20Sopenharmony_ci queue_depth = min(queue_depth, ata_id_queue_depth(dev->id)); 10508c2ecf20Sopenharmony_ci queue_depth = min(queue_depth, ATA_MAX_QUEUE); 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci if (sdev->queue_depth == queue_depth) 10538c2ecf20Sopenharmony_ci return -EINVAL; 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci return scsi_change_queue_depth(sdev, queue_depth); 10568c2ecf20Sopenharmony_ci} 10578c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__ata_change_queue_depth); 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci/** 10608c2ecf20Sopenharmony_ci * ata_scsi_change_queue_depth - SCSI callback for queue depth config 10618c2ecf20Sopenharmony_ci * @sdev: SCSI device to configure queue depth for 10628c2ecf20Sopenharmony_ci * @queue_depth: new queue depth 10638c2ecf20Sopenharmony_ci * 10648c2ecf20Sopenharmony_ci * This is libata standard hostt->change_queue_depth callback. 10658c2ecf20Sopenharmony_ci * SCSI will call into this callback when user tries to set queue 10668c2ecf20Sopenharmony_ci * depth via sysfs. 10678c2ecf20Sopenharmony_ci * 10688c2ecf20Sopenharmony_ci * LOCKING: 10698c2ecf20Sopenharmony_ci * SCSI layer (we don't care) 10708c2ecf20Sopenharmony_ci * 10718c2ecf20Sopenharmony_ci * RETURNS: 10728c2ecf20Sopenharmony_ci * Newly configured queue depth. 10738c2ecf20Sopenharmony_ci */ 10748c2ecf20Sopenharmony_ciint ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth) 10758c2ecf20Sopenharmony_ci{ 10768c2ecf20Sopenharmony_ci struct ata_port *ap = ata_shost_to_port(sdev->host); 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci return __ata_change_queue_depth(ap, sdev, queue_depth); 10798c2ecf20Sopenharmony_ci} 10808c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth); 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci/** 10838c2ecf20Sopenharmony_ci * port_alloc - Allocate port for a SAS attached SATA device 10848c2ecf20Sopenharmony_ci * @host: ATA host container for all SAS ports 10858c2ecf20Sopenharmony_ci * @port_info: Information from low-level host driver 10868c2ecf20Sopenharmony_ci * @shost: SCSI host that the scsi device is attached to 10878c2ecf20Sopenharmony_ci * 10888c2ecf20Sopenharmony_ci * LOCKING: 10898c2ecf20Sopenharmony_ci * PCI/etc. bus probe sem. 10908c2ecf20Sopenharmony_ci * 10918c2ecf20Sopenharmony_ci * RETURNS: 10928c2ecf20Sopenharmony_ci * ata_port pointer on success / NULL on failure. 10938c2ecf20Sopenharmony_ci */ 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_cistruct ata_port *ata_sas_port_alloc(struct ata_host *host, 10968c2ecf20Sopenharmony_ci struct ata_port_info *port_info, 10978c2ecf20Sopenharmony_ci struct Scsi_Host *shost) 10988c2ecf20Sopenharmony_ci{ 10998c2ecf20Sopenharmony_ci struct ata_port *ap; 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci ap = ata_port_alloc(host); 11028c2ecf20Sopenharmony_ci if (!ap) 11038c2ecf20Sopenharmony_ci return NULL; 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci ap->port_no = 0; 11068c2ecf20Sopenharmony_ci ap->lock = &host->lock; 11078c2ecf20Sopenharmony_ci ap->pio_mask = port_info->pio_mask; 11088c2ecf20Sopenharmony_ci ap->mwdma_mask = port_info->mwdma_mask; 11098c2ecf20Sopenharmony_ci ap->udma_mask = port_info->udma_mask; 11108c2ecf20Sopenharmony_ci ap->flags |= port_info->flags; 11118c2ecf20Sopenharmony_ci ap->ops = port_info->port_ops; 11128c2ecf20Sopenharmony_ci ap->cbl = ATA_CBL_SATA; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci return ap; 11158c2ecf20Sopenharmony_ci} 11168c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_sas_port_alloc); 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci/** 11198c2ecf20Sopenharmony_ci * ata_sas_port_start - Set port up for dma. 11208c2ecf20Sopenharmony_ci * @ap: Port to initialize 11218c2ecf20Sopenharmony_ci * 11228c2ecf20Sopenharmony_ci * Called just after data structures for each port are 11238c2ecf20Sopenharmony_ci * initialized. 11248c2ecf20Sopenharmony_ci * 11258c2ecf20Sopenharmony_ci * May be used as the port_start() entry in ata_port_operations. 11268c2ecf20Sopenharmony_ci * 11278c2ecf20Sopenharmony_ci * LOCKING: 11288c2ecf20Sopenharmony_ci * Inherited from caller. 11298c2ecf20Sopenharmony_ci */ 11308c2ecf20Sopenharmony_ciint ata_sas_port_start(struct ata_port *ap) 11318c2ecf20Sopenharmony_ci{ 11328c2ecf20Sopenharmony_ci /* 11338c2ecf20Sopenharmony_ci * the port is marked as frozen at allocation time, but if we don't 11348c2ecf20Sopenharmony_ci * have new eh, we won't thaw it 11358c2ecf20Sopenharmony_ci */ 11368c2ecf20Sopenharmony_ci if (!ap->ops->error_handler) 11378c2ecf20Sopenharmony_ci ap->pflags &= ~ATA_PFLAG_FROZEN; 11388c2ecf20Sopenharmony_ci return 0; 11398c2ecf20Sopenharmony_ci} 11408c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_sas_port_start); 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_ci/** 11438c2ecf20Sopenharmony_ci * ata_port_stop - Undo ata_sas_port_start() 11448c2ecf20Sopenharmony_ci * @ap: Port to shut down 11458c2ecf20Sopenharmony_ci * 11468c2ecf20Sopenharmony_ci * May be used as the port_stop() entry in ata_port_operations. 11478c2ecf20Sopenharmony_ci * 11488c2ecf20Sopenharmony_ci * LOCKING: 11498c2ecf20Sopenharmony_ci * Inherited from caller. 11508c2ecf20Sopenharmony_ci */ 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_civoid ata_sas_port_stop(struct ata_port *ap) 11538c2ecf20Sopenharmony_ci{ 11548c2ecf20Sopenharmony_ci} 11558c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_sas_port_stop); 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci/** 11588c2ecf20Sopenharmony_ci * ata_sas_async_probe - simply schedule probing and return 11598c2ecf20Sopenharmony_ci * @ap: Port to probe 11608c2ecf20Sopenharmony_ci * 11618c2ecf20Sopenharmony_ci * For batch scheduling of probe for sas attached ata devices, assumes 11628c2ecf20Sopenharmony_ci * the port has already been through ata_sas_port_init() 11638c2ecf20Sopenharmony_ci */ 11648c2ecf20Sopenharmony_civoid ata_sas_async_probe(struct ata_port *ap) 11658c2ecf20Sopenharmony_ci{ 11668c2ecf20Sopenharmony_ci __ata_port_probe(ap); 11678c2ecf20Sopenharmony_ci} 11688c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_sas_async_probe); 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ciint ata_sas_sync_probe(struct ata_port *ap) 11718c2ecf20Sopenharmony_ci{ 11728c2ecf20Sopenharmony_ci return ata_port_probe(ap); 11738c2ecf20Sopenharmony_ci} 11748c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_sas_sync_probe); 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci/** 11788c2ecf20Sopenharmony_ci * ata_sas_port_init - Initialize a SATA device 11798c2ecf20Sopenharmony_ci * @ap: SATA port to initialize 11808c2ecf20Sopenharmony_ci * 11818c2ecf20Sopenharmony_ci * LOCKING: 11828c2ecf20Sopenharmony_ci * PCI/etc. bus probe sem. 11838c2ecf20Sopenharmony_ci * 11848c2ecf20Sopenharmony_ci * RETURNS: 11858c2ecf20Sopenharmony_ci * Zero on success, non-zero on error. 11868c2ecf20Sopenharmony_ci */ 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ciint ata_sas_port_init(struct ata_port *ap) 11898c2ecf20Sopenharmony_ci{ 11908c2ecf20Sopenharmony_ci int rc = ap->ops->port_start(ap); 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci if (rc) 11938c2ecf20Sopenharmony_ci return rc; 11948c2ecf20Sopenharmony_ci ap->print_id = atomic_inc_return(&ata_print_id); 11958c2ecf20Sopenharmony_ci return 0; 11968c2ecf20Sopenharmony_ci} 11978c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_sas_port_init); 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ciint ata_sas_tport_add(struct device *parent, struct ata_port *ap) 12008c2ecf20Sopenharmony_ci{ 12018c2ecf20Sopenharmony_ci return ata_tport_add(parent, ap); 12028c2ecf20Sopenharmony_ci} 12038c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_sas_tport_add); 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_civoid ata_sas_tport_delete(struct ata_port *ap) 12068c2ecf20Sopenharmony_ci{ 12078c2ecf20Sopenharmony_ci ata_tport_delete(ap); 12088c2ecf20Sopenharmony_ci} 12098c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_sas_tport_delete); 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci/** 12128c2ecf20Sopenharmony_ci * ata_sas_port_destroy - Destroy a SATA port allocated by ata_sas_port_alloc 12138c2ecf20Sopenharmony_ci * @ap: SATA port to destroy 12148c2ecf20Sopenharmony_ci * 12158c2ecf20Sopenharmony_ci */ 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_civoid ata_sas_port_destroy(struct ata_port *ap) 12188c2ecf20Sopenharmony_ci{ 12198c2ecf20Sopenharmony_ci if (ap->ops->port_stop) 12208c2ecf20Sopenharmony_ci ap->ops->port_stop(ap); 12218c2ecf20Sopenharmony_ci kfree(ap); 12228c2ecf20Sopenharmony_ci} 12238c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_sas_port_destroy); 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci/** 12268c2ecf20Sopenharmony_ci * ata_sas_slave_configure - Default slave_config routine for libata devices 12278c2ecf20Sopenharmony_ci * @sdev: SCSI device to configure 12288c2ecf20Sopenharmony_ci * @ap: ATA port to which SCSI device is attached 12298c2ecf20Sopenharmony_ci * 12308c2ecf20Sopenharmony_ci * RETURNS: 12318c2ecf20Sopenharmony_ci * Zero. 12328c2ecf20Sopenharmony_ci */ 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ciint ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap) 12358c2ecf20Sopenharmony_ci{ 12368c2ecf20Sopenharmony_ci ata_scsi_sdev_config(sdev); 12378c2ecf20Sopenharmony_ci ata_scsi_dev_config(sdev, ap->link.device); 12388c2ecf20Sopenharmony_ci return 0; 12398c2ecf20Sopenharmony_ci} 12408c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_sas_slave_configure); 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci/** 12438c2ecf20Sopenharmony_ci * ata_sas_queuecmd - Issue SCSI cdb to libata-managed device 12448c2ecf20Sopenharmony_ci * @cmd: SCSI command to be sent 12458c2ecf20Sopenharmony_ci * @ap: ATA port to which the command is being sent 12468c2ecf20Sopenharmony_ci * 12478c2ecf20Sopenharmony_ci * RETURNS: 12488c2ecf20Sopenharmony_ci * Return value from __ata_scsi_queuecmd() if @cmd can be queued, 12498c2ecf20Sopenharmony_ci * 0 otherwise. 12508c2ecf20Sopenharmony_ci */ 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ciint ata_sas_queuecmd(struct scsi_cmnd *cmd, struct ata_port *ap) 12538c2ecf20Sopenharmony_ci{ 12548c2ecf20Sopenharmony_ci int rc = 0; 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci ata_scsi_dump_cdb(ap, cmd); 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci if (likely(ata_dev_enabled(ap->link.device))) 12598c2ecf20Sopenharmony_ci rc = __ata_scsi_queuecmd(cmd, ap->link.device); 12608c2ecf20Sopenharmony_ci else { 12618c2ecf20Sopenharmony_ci cmd->result = (DID_BAD_TARGET << 16); 12628c2ecf20Sopenharmony_ci cmd->scsi_done(cmd); 12638c2ecf20Sopenharmony_ci } 12648c2ecf20Sopenharmony_ci return rc; 12658c2ecf20Sopenharmony_ci} 12668c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_sas_queuecmd); 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ciint ata_sas_allocate_tag(struct ata_port *ap) 12698c2ecf20Sopenharmony_ci{ 12708c2ecf20Sopenharmony_ci unsigned int max_queue = ap->host->n_tags; 12718c2ecf20Sopenharmony_ci unsigned int i, tag; 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci for (i = 0, tag = ap->sas_last_tag + 1; i < max_queue; i++, tag++) { 12748c2ecf20Sopenharmony_ci tag = tag < max_queue ? tag : 0; 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ci /* the last tag is reserved for internal command. */ 12778c2ecf20Sopenharmony_ci if (ata_tag_internal(tag)) 12788c2ecf20Sopenharmony_ci continue; 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci if (!test_and_set_bit(tag, &ap->sas_tag_allocated)) { 12818c2ecf20Sopenharmony_ci ap->sas_last_tag = tag; 12828c2ecf20Sopenharmony_ci return tag; 12838c2ecf20Sopenharmony_ci } 12848c2ecf20Sopenharmony_ci } 12858c2ecf20Sopenharmony_ci return -1; 12868c2ecf20Sopenharmony_ci} 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_civoid ata_sas_free_tag(unsigned int tag, struct ata_port *ap) 12898c2ecf20Sopenharmony_ci{ 12908c2ecf20Sopenharmony_ci clear_bit(tag, &ap->sas_tag_allocated); 12918c2ecf20Sopenharmony_ci} 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci/** 12948c2ecf20Sopenharmony_ci * sata_async_notification - SATA async notification handler 12958c2ecf20Sopenharmony_ci * @ap: ATA port where async notification is received 12968c2ecf20Sopenharmony_ci * 12978c2ecf20Sopenharmony_ci * Handler to be called when async notification via SDB FIS is 12988c2ecf20Sopenharmony_ci * received. This function schedules EH if necessary. 12998c2ecf20Sopenharmony_ci * 13008c2ecf20Sopenharmony_ci * LOCKING: 13018c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 13028c2ecf20Sopenharmony_ci * 13038c2ecf20Sopenharmony_ci * RETURNS: 13048c2ecf20Sopenharmony_ci * 1 if EH is scheduled, 0 otherwise. 13058c2ecf20Sopenharmony_ci */ 13068c2ecf20Sopenharmony_ciint sata_async_notification(struct ata_port *ap) 13078c2ecf20Sopenharmony_ci{ 13088c2ecf20Sopenharmony_ci u32 sntf; 13098c2ecf20Sopenharmony_ci int rc; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci if (!(ap->flags & ATA_FLAG_AN)) 13128c2ecf20Sopenharmony_ci return 0; 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci rc = sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf); 13158c2ecf20Sopenharmony_ci if (rc == 0) 13168c2ecf20Sopenharmony_ci sata_scr_write(&ap->link, SCR_NOTIFICATION, sntf); 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci if (!sata_pmp_attached(ap) || rc) { 13198c2ecf20Sopenharmony_ci /* PMP is not attached or SNTF is not available */ 13208c2ecf20Sopenharmony_ci if (!sata_pmp_attached(ap)) { 13218c2ecf20Sopenharmony_ci /* PMP is not attached. Check whether ATAPI 13228c2ecf20Sopenharmony_ci * AN is configured. If so, notify media 13238c2ecf20Sopenharmony_ci * change. 13248c2ecf20Sopenharmony_ci */ 13258c2ecf20Sopenharmony_ci struct ata_device *dev = ap->link.device; 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci if ((dev->class == ATA_DEV_ATAPI) && 13288c2ecf20Sopenharmony_ci (dev->flags & ATA_DFLAG_AN)) 13298c2ecf20Sopenharmony_ci ata_scsi_media_change_notify(dev); 13308c2ecf20Sopenharmony_ci return 0; 13318c2ecf20Sopenharmony_ci } else { 13328c2ecf20Sopenharmony_ci /* PMP is attached but SNTF is not available. 13338c2ecf20Sopenharmony_ci * ATAPI async media change notification is 13348c2ecf20Sopenharmony_ci * not used. The PMP must be reporting PHY 13358c2ecf20Sopenharmony_ci * status change, schedule EH. 13368c2ecf20Sopenharmony_ci */ 13378c2ecf20Sopenharmony_ci ata_port_schedule_eh(ap); 13388c2ecf20Sopenharmony_ci return 1; 13398c2ecf20Sopenharmony_ci } 13408c2ecf20Sopenharmony_ci } else { 13418c2ecf20Sopenharmony_ci /* PMP is attached and SNTF is available */ 13428c2ecf20Sopenharmony_ci struct ata_link *link; 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci /* check and notify ATAPI AN */ 13458c2ecf20Sopenharmony_ci ata_for_each_link(link, ap, EDGE) { 13468c2ecf20Sopenharmony_ci if (!(sntf & (1 << link->pmp))) 13478c2ecf20Sopenharmony_ci continue; 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_ci if ((link->device->class == ATA_DEV_ATAPI) && 13508c2ecf20Sopenharmony_ci (link->device->flags & ATA_DFLAG_AN)) 13518c2ecf20Sopenharmony_ci ata_scsi_media_change_notify(link->device); 13528c2ecf20Sopenharmony_ci } 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci /* If PMP is reporting that PHY status of some 13558c2ecf20Sopenharmony_ci * downstream ports has changed, schedule EH. 13568c2ecf20Sopenharmony_ci */ 13578c2ecf20Sopenharmony_ci if (sntf & (1 << SATA_PMP_CTRL_PORT)) { 13588c2ecf20Sopenharmony_ci ata_port_schedule_eh(ap); 13598c2ecf20Sopenharmony_ci return 1; 13608c2ecf20Sopenharmony_ci } 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci return 0; 13638c2ecf20Sopenharmony_ci } 13648c2ecf20Sopenharmony_ci} 13658c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sata_async_notification); 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci/** 13688c2ecf20Sopenharmony_ci * ata_eh_read_log_10h - Read log page 10h for NCQ error details 13698c2ecf20Sopenharmony_ci * @dev: Device to read log page 10h from 13708c2ecf20Sopenharmony_ci * @tag: Resulting tag of the failed command 13718c2ecf20Sopenharmony_ci * @tf: Resulting taskfile registers of the failed command 13728c2ecf20Sopenharmony_ci * 13738c2ecf20Sopenharmony_ci * Read log page 10h to obtain NCQ error details and clear error 13748c2ecf20Sopenharmony_ci * condition. 13758c2ecf20Sopenharmony_ci * 13768c2ecf20Sopenharmony_ci * LOCKING: 13778c2ecf20Sopenharmony_ci * Kernel thread context (may sleep). 13788c2ecf20Sopenharmony_ci * 13798c2ecf20Sopenharmony_ci * RETURNS: 13808c2ecf20Sopenharmony_ci * 0 on success, -errno otherwise. 13818c2ecf20Sopenharmony_ci */ 13828c2ecf20Sopenharmony_cistatic int ata_eh_read_log_10h(struct ata_device *dev, 13838c2ecf20Sopenharmony_ci int *tag, struct ata_taskfile *tf) 13848c2ecf20Sopenharmony_ci{ 13858c2ecf20Sopenharmony_ci u8 *buf = dev->link->ap->sector_buf; 13868c2ecf20Sopenharmony_ci unsigned int err_mask; 13878c2ecf20Sopenharmony_ci u8 csum; 13888c2ecf20Sopenharmony_ci int i; 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, 0, buf, 1); 13918c2ecf20Sopenharmony_ci if (err_mask) 13928c2ecf20Sopenharmony_ci return -EIO; 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci csum = 0; 13958c2ecf20Sopenharmony_ci for (i = 0; i < ATA_SECT_SIZE; i++) 13968c2ecf20Sopenharmony_ci csum += buf[i]; 13978c2ecf20Sopenharmony_ci if (csum) 13988c2ecf20Sopenharmony_ci ata_dev_warn(dev, "invalid checksum 0x%x on log page 10h\n", 13998c2ecf20Sopenharmony_ci csum); 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci if (buf[0] & 0x80) 14028c2ecf20Sopenharmony_ci return -ENOENT; 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci *tag = buf[0] & 0x1f; 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_ci tf->command = buf[2]; 14078c2ecf20Sopenharmony_ci tf->feature = buf[3]; 14088c2ecf20Sopenharmony_ci tf->lbal = buf[4]; 14098c2ecf20Sopenharmony_ci tf->lbam = buf[5]; 14108c2ecf20Sopenharmony_ci tf->lbah = buf[6]; 14118c2ecf20Sopenharmony_ci tf->device = buf[7]; 14128c2ecf20Sopenharmony_ci tf->hob_lbal = buf[8]; 14138c2ecf20Sopenharmony_ci tf->hob_lbam = buf[9]; 14148c2ecf20Sopenharmony_ci tf->hob_lbah = buf[10]; 14158c2ecf20Sopenharmony_ci tf->nsect = buf[12]; 14168c2ecf20Sopenharmony_ci tf->hob_nsect = buf[13]; 14178c2ecf20Sopenharmony_ci if (dev->class == ATA_DEV_ZAC && ata_id_has_ncq_autosense(dev->id)) 14188c2ecf20Sopenharmony_ci tf->auxiliary = buf[14] << 16 | buf[15] << 8 | buf[16]; 14198c2ecf20Sopenharmony_ci 14208c2ecf20Sopenharmony_ci return 0; 14218c2ecf20Sopenharmony_ci} 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci/** 14248c2ecf20Sopenharmony_ci * ata_eh_analyze_ncq_error - analyze NCQ error 14258c2ecf20Sopenharmony_ci * @link: ATA link to analyze NCQ error for 14268c2ecf20Sopenharmony_ci * 14278c2ecf20Sopenharmony_ci * Read log page 10h, determine the offending qc and acquire 14288c2ecf20Sopenharmony_ci * error status TF. For NCQ device errors, all LLDDs have to do 14298c2ecf20Sopenharmony_ci * is setting AC_ERR_DEV in ehi->err_mask. This function takes 14308c2ecf20Sopenharmony_ci * care of the rest. 14318c2ecf20Sopenharmony_ci * 14328c2ecf20Sopenharmony_ci * LOCKING: 14338c2ecf20Sopenharmony_ci * Kernel thread context (may sleep). 14348c2ecf20Sopenharmony_ci */ 14358c2ecf20Sopenharmony_civoid ata_eh_analyze_ncq_error(struct ata_link *link) 14368c2ecf20Sopenharmony_ci{ 14378c2ecf20Sopenharmony_ci struct ata_port *ap = link->ap; 14388c2ecf20Sopenharmony_ci struct ata_eh_context *ehc = &link->eh_context; 14398c2ecf20Sopenharmony_ci struct ata_device *dev = link->device; 14408c2ecf20Sopenharmony_ci struct ata_queued_cmd *qc; 14418c2ecf20Sopenharmony_ci struct ata_taskfile tf; 14428c2ecf20Sopenharmony_ci int tag, rc; 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci /* if frozen, we can't do much */ 14458c2ecf20Sopenharmony_ci if (ap->pflags & ATA_PFLAG_FROZEN) 14468c2ecf20Sopenharmony_ci return; 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci /* is it NCQ device error? */ 14498c2ecf20Sopenharmony_ci if (!link->sactive || !(ehc->i.err_mask & AC_ERR_DEV)) 14508c2ecf20Sopenharmony_ci return; 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci /* has LLDD analyzed already? */ 14538c2ecf20Sopenharmony_ci ata_qc_for_each_raw(ap, qc, tag) { 14548c2ecf20Sopenharmony_ci if (!(qc->flags & ATA_QCFLAG_FAILED)) 14558c2ecf20Sopenharmony_ci continue; 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci if (qc->err_mask) 14588c2ecf20Sopenharmony_ci return; 14598c2ecf20Sopenharmony_ci } 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_ci /* okay, this error is ours */ 14628c2ecf20Sopenharmony_ci memset(&tf, 0, sizeof(tf)); 14638c2ecf20Sopenharmony_ci rc = ata_eh_read_log_10h(dev, &tag, &tf); 14648c2ecf20Sopenharmony_ci if (rc) { 14658c2ecf20Sopenharmony_ci ata_link_err(link, "failed to read log page 10h (errno=%d)\n", 14668c2ecf20Sopenharmony_ci rc); 14678c2ecf20Sopenharmony_ci return; 14688c2ecf20Sopenharmony_ci } 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_ci if (!(link->sactive & (1 << tag))) { 14718c2ecf20Sopenharmony_ci ata_link_err(link, "log page 10h reported inactive tag %d\n", 14728c2ecf20Sopenharmony_ci tag); 14738c2ecf20Sopenharmony_ci return; 14748c2ecf20Sopenharmony_ci } 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci /* we've got the perpetrator, condemn it */ 14778c2ecf20Sopenharmony_ci qc = __ata_qc_from_tag(ap, tag); 14788c2ecf20Sopenharmony_ci memcpy(&qc->result_tf, &tf, sizeof(tf)); 14798c2ecf20Sopenharmony_ci qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48; 14808c2ecf20Sopenharmony_ci qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ; 14818c2ecf20Sopenharmony_ci if (dev->class == ATA_DEV_ZAC && 14828c2ecf20Sopenharmony_ci ((qc->result_tf.command & ATA_SENSE) || qc->result_tf.auxiliary)) { 14838c2ecf20Sopenharmony_ci char sense_key, asc, ascq; 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_ci sense_key = (qc->result_tf.auxiliary >> 16) & 0xff; 14868c2ecf20Sopenharmony_ci asc = (qc->result_tf.auxiliary >> 8) & 0xff; 14878c2ecf20Sopenharmony_ci ascq = qc->result_tf.auxiliary & 0xff; 14888c2ecf20Sopenharmony_ci ata_scsi_set_sense(dev, qc->scsicmd, sense_key, asc, ascq); 14898c2ecf20Sopenharmony_ci ata_scsi_set_sense_information(dev, qc->scsicmd, 14908c2ecf20Sopenharmony_ci &qc->result_tf); 14918c2ecf20Sopenharmony_ci qc->flags |= ATA_QCFLAG_SENSE_VALID; 14928c2ecf20Sopenharmony_ci } 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci ehc->i.err_mask &= ~AC_ERR_DEV; 14958c2ecf20Sopenharmony_ci} 14968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_eh_analyze_ncq_error); 1497