18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * sd.c Copyright (C) 1992 Drew Eckhardt 48c2ecf20Sopenharmony_ci * Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Linux scsi disk driver 78c2ecf20Sopenharmony_ci * Initial versions: Drew Eckhardt 88c2ecf20Sopenharmony_ci * Subsequent revisions: Eric Youngdale 98c2ecf20Sopenharmony_ci * Modification history: 108c2ecf20Sopenharmony_ci * - Drew Eckhardt <drew@colorado.edu> original 118c2ecf20Sopenharmony_ci * - Eric Youngdale <eric@andante.org> add scatter-gather, multiple 128c2ecf20Sopenharmony_ci * outstanding request, and other enhancements. 138c2ecf20Sopenharmony_ci * Support loadable low-level scsi drivers. 148c2ecf20Sopenharmony_ci * - Jirka Hanika <geo@ff.cuni.cz> support more scsi disks using 158c2ecf20Sopenharmony_ci * eight major numbers. 168c2ecf20Sopenharmony_ci * - Richard Gooch <rgooch@atnf.csiro.au> support devfs. 178c2ecf20Sopenharmony_ci * - Torben Mathiasen <tmm@image.dk> Resource allocation fixes in 188c2ecf20Sopenharmony_ci * sd_init and cleanups. 198c2ecf20Sopenharmony_ci * - Alex Davis <letmein@erols.com> Fix problem where partition info 208c2ecf20Sopenharmony_ci * not being read in sd_open. Fix problem where removable media 218c2ecf20Sopenharmony_ci * could be ejected after sd_open. 228c2ecf20Sopenharmony_ci * - Douglas Gilbert <dgilbert@interlog.com> cleanup for lk 2.5.x 238c2ecf20Sopenharmony_ci * - Badari Pulavarty <pbadari@us.ibm.com>, Matthew Wilcox 248c2ecf20Sopenharmony_ci * <willy@debian.org>, Kurt Garloff <garloff@suse.de>: 258c2ecf20Sopenharmony_ci * Support 32k/1M disks. 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * Logging policy (needs CONFIG_SCSI_LOGGING defined): 288c2ecf20Sopenharmony_ci * - setting up transfer: SCSI_LOG_HLQUEUE levels 1 and 2 298c2ecf20Sopenharmony_ci * - end of transfer (bh + scsi_lib): SCSI_LOG_HLCOMPLETE level 1 308c2ecf20Sopenharmony_ci * - entering sd_ioctl: SCSI_LOG_IOCTL level 1 318c2ecf20Sopenharmony_ci * - entering other commands: SCSI_LOG_HLQUEUE level 3 328c2ecf20Sopenharmony_ci * Note: when the logging level is set by the user, it must be greater 338c2ecf20Sopenharmony_ci * than the level indicated above to trigger output. 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include <linux/module.h> 378c2ecf20Sopenharmony_ci#include <linux/fs.h> 388c2ecf20Sopenharmony_ci#include <linux/kernel.h> 398c2ecf20Sopenharmony_ci#include <linux/mm.h> 408c2ecf20Sopenharmony_ci#include <linux/bio.h> 418c2ecf20Sopenharmony_ci#include <linux/genhd.h> 428c2ecf20Sopenharmony_ci#include <linux/hdreg.h> 438c2ecf20Sopenharmony_ci#include <linux/errno.h> 448c2ecf20Sopenharmony_ci#include <linux/idr.h> 458c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 468c2ecf20Sopenharmony_ci#include <linux/init.h> 478c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 488c2ecf20Sopenharmony_ci#include <linux/blkpg.h> 498c2ecf20Sopenharmony_ci#include <linux/blk-pm.h> 508c2ecf20Sopenharmony_ci#include <linux/delay.h> 518c2ecf20Sopenharmony_ci#include <linux/mutex.h> 528c2ecf20Sopenharmony_ci#include <linux/string_helpers.h> 538c2ecf20Sopenharmony_ci#include <linux/async.h> 548c2ecf20Sopenharmony_ci#include <linux/slab.h> 558c2ecf20Sopenharmony_ci#include <linux/sed-opal.h> 568c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 578c2ecf20Sopenharmony_ci#include <linux/pr.h> 588c2ecf20Sopenharmony_ci#include <linux/t10-pi.h> 598c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 608c2ecf20Sopenharmony_ci#include <asm/unaligned.h> 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#include <scsi/scsi.h> 638c2ecf20Sopenharmony_ci#include <scsi/scsi_cmnd.h> 648c2ecf20Sopenharmony_ci#include <scsi/scsi_dbg.h> 658c2ecf20Sopenharmony_ci#include <scsi/scsi_device.h> 668c2ecf20Sopenharmony_ci#include <scsi/scsi_driver.h> 678c2ecf20Sopenharmony_ci#include <scsi/scsi_eh.h> 688c2ecf20Sopenharmony_ci#include <scsi/scsi_host.h> 698c2ecf20Sopenharmony_ci#include <scsi/scsi_ioctl.h> 708c2ecf20Sopenharmony_ci#include <scsi/scsicam.h> 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci#include "sd.h" 738c2ecf20Sopenharmony_ci#include "scsi_priv.h" 748c2ecf20Sopenharmony_ci#include "scsi_logging.h" 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ciMODULE_AUTHOR("Eric Youngdale"); 778c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("SCSI disk (sd) driver"); 788c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK0_MAJOR); 818c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK1_MAJOR); 828c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK2_MAJOR); 838c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK3_MAJOR); 848c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK4_MAJOR); 858c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK5_MAJOR); 868c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK6_MAJOR); 878c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK7_MAJOR); 888c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK8_MAJOR); 898c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK9_MAJOR); 908c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK10_MAJOR); 918c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK11_MAJOR); 928c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK12_MAJOR); 938c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK13_MAJOR); 948c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK14_MAJOR); 958c2ecf20Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK15_MAJOR); 968c2ecf20Sopenharmony_ciMODULE_ALIAS_SCSI_DEVICE(TYPE_DISK); 978c2ecf20Sopenharmony_ciMODULE_ALIAS_SCSI_DEVICE(TYPE_MOD); 988c2ecf20Sopenharmony_ciMODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); 998c2ecf20Sopenharmony_ciMODULE_ALIAS_SCSI_DEVICE(TYPE_ZBC); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) 1028c2ecf20Sopenharmony_ci#define SD_MINORS 16 1038c2ecf20Sopenharmony_ci#else 1048c2ecf20Sopenharmony_ci#define SD_MINORS 0 1058c2ecf20Sopenharmony_ci#endif 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic void sd_config_discard(struct scsi_disk *, unsigned int); 1088c2ecf20Sopenharmony_cistatic void sd_config_write_same(struct scsi_disk *); 1098c2ecf20Sopenharmony_cistatic int sd_revalidate_disk(struct gendisk *); 1108c2ecf20Sopenharmony_cistatic void sd_unlock_native_capacity(struct gendisk *disk); 1118c2ecf20Sopenharmony_cistatic int sd_probe(struct device *); 1128c2ecf20Sopenharmony_cistatic int sd_remove(struct device *); 1138c2ecf20Sopenharmony_cistatic void sd_shutdown(struct device *); 1148c2ecf20Sopenharmony_cistatic int sd_suspend_system(struct device *); 1158c2ecf20Sopenharmony_cistatic int sd_suspend_runtime(struct device *); 1168c2ecf20Sopenharmony_cistatic int sd_resume(struct device *); 1178c2ecf20Sopenharmony_cistatic void sd_rescan(struct device *); 1188c2ecf20Sopenharmony_cistatic blk_status_t sd_init_command(struct scsi_cmnd *SCpnt); 1198c2ecf20Sopenharmony_cistatic void sd_uninit_command(struct scsi_cmnd *SCpnt); 1208c2ecf20Sopenharmony_cistatic int sd_done(struct scsi_cmnd *); 1218c2ecf20Sopenharmony_cistatic void sd_eh_reset(struct scsi_cmnd *); 1228c2ecf20Sopenharmony_cistatic int sd_eh_action(struct scsi_cmnd *, int); 1238c2ecf20Sopenharmony_cistatic void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); 1248c2ecf20Sopenharmony_cistatic void scsi_disk_release(struct device *cdev); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_cistatic DEFINE_IDA(sd_index_ida); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci/* This semaphore is used to mediate the 0->1 reference get in the 1298c2ecf20Sopenharmony_ci * face of object destruction (i.e. we can't allow a get on an 1308c2ecf20Sopenharmony_ci * object after last put) */ 1318c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(sd_ref_mutex); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic struct kmem_cache *sd_cdb_cache; 1348c2ecf20Sopenharmony_cistatic mempool_t *sd_cdb_pool; 1358c2ecf20Sopenharmony_cistatic mempool_t *sd_page_pool; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cistatic const char *sd_cache_types[] = { 1388c2ecf20Sopenharmony_ci "write through", "none", "write back", 1398c2ecf20Sopenharmony_ci "write back, no read (daft)" 1408c2ecf20Sopenharmony_ci}; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic void sd_set_flush_flag(struct scsi_disk *sdkp) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci bool wc = false, fua = false; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci if (sdkp->WCE) { 1478c2ecf20Sopenharmony_ci wc = true; 1488c2ecf20Sopenharmony_ci if (sdkp->DPOFUA) 1498c2ecf20Sopenharmony_ci fua = true; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci blk_queue_write_cache(sdkp->disk->queue, wc, fua); 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic ssize_t 1568c2ecf20Sopenharmony_cicache_type_store(struct device *dev, struct device_attribute *attr, 1578c2ecf20Sopenharmony_ci const char *buf, size_t count) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci int ct, rcd, wce, sp; 1608c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 1618c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 1628c2ecf20Sopenharmony_ci char buffer[64]; 1638c2ecf20Sopenharmony_ci char *buffer_data; 1648c2ecf20Sopenharmony_ci struct scsi_mode_data data; 1658c2ecf20Sopenharmony_ci struct scsi_sense_hdr sshdr; 1668c2ecf20Sopenharmony_ci static const char temp[] = "temporary "; 1678c2ecf20Sopenharmony_ci int len; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC) 1708c2ecf20Sopenharmony_ci /* no cache control on RBC devices; theoretically they 1718c2ecf20Sopenharmony_ci * can do it, but there's probably so many exceptions 1728c2ecf20Sopenharmony_ci * it's not worth the risk */ 1738c2ecf20Sopenharmony_ci return -EINVAL; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci if (strncmp(buf, temp, sizeof(temp) - 1) == 0) { 1768c2ecf20Sopenharmony_ci buf += sizeof(temp) - 1; 1778c2ecf20Sopenharmony_ci sdkp->cache_override = 1; 1788c2ecf20Sopenharmony_ci } else { 1798c2ecf20Sopenharmony_ci sdkp->cache_override = 0; 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci ct = sysfs_match_string(sd_cache_types, buf); 1838c2ecf20Sopenharmony_ci if (ct < 0) 1848c2ecf20Sopenharmony_ci return -EINVAL; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci rcd = ct & 0x01 ? 1 : 0; 1878c2ecf20Sopenharmony_ci wce = (ct & 0x02) && !sdkp->write_prot ? 1 : 0; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci if (sdkp->cache_override) { 1908c2ecf20Sopenharmony_ci sdkp->WCE = wce; 1918c2ecf20Sopenharmony_ci sdkp->RCD = rcd; 1928c2ecf20Sopenharmony_ci sd_set_flush_flag(sdkp); 1938c2ecf20Sopenharmony_ci return count; 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT, 1978c2ecf20Sopenharmony_ci sdkp->max_retries, &data, NULL)) 1988c2ecf20Sopenharmony_ci return -EINVAL; 1998c2ecf20Sopenharmony_ci len = min_t(size_t, sizeof(buffer), data.length - data.header_length - 2008c2ecf20Sopenharmony_ci data.block_descriptor_length); 2018c2ecf20Sopenharmony_ci buffer_data = buffer + data.header_length + 2028c2ecf20Sopenharmony_ci data.block_descriptor_length; 2038c2ecf20Sopenharmony_ci buffer_data[2] &= ~0x05; 2048c2ecf20Sopenharmony_ci buffer_data[2] |= wce << 2 | rcd; 2058c2ecf20Sopenharmony_ci sp = buffer_data[0] & 0x80 ? 1 : 0; 2068c2ecf20Sopenharmony_ci buffer_data[0] &= ~0x80; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci /* 2098c2ecf20Sopenharmony_ci * Ensure WP, DPOFUA, and RESERVED fields are cleared in 2108c2ecf20Sopenharmony_ci * received mode parameter buffer before doing MODE SELECT. 2118c2ecf20Sopenharmony_ci */ 2128c2ecf20Sopenharmony_ci data.device_specific = 0; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT, 2158c2ecf20Sopenharmony_ci sdkp->max_retries, &data, &sshdr)) { 2168c2ecf20Sopenharmony_ci if (scsi_sense_valid(&sshdr)) 2178c2ecf20Sopenharmony_ci sd_print_sense_hdr(sdkp, &sshdr); 2188c2ecf20Sopenharmony_ci return -EINVAL; 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci sd_revalidate_disk(sdkp->disk); 2218c2ecf20Sopenharmony_ci return count; 2228c2ecf20Sopenharmony_ci} 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_cistatic ssize_t 2258c2ecf20Sopenharmony_cimanage_start_stop_show(struct device *dev, struct device_attribute *attr, 2268c2ecf20Sopenharmony_ci char *buf) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 2298c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", sdp->manage_start_stop); 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_cistatic ssize_t 2358c2ecf20Sopenharmony_cimanage_start_stop_store(struct device *dev, struct device_attribute *attr, 2368c2ecf20Sopenharmony_ci const char *buf, size_t count) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 2398c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 2408c2ecf20Sopenharmony_ci bool v; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 2438c2ecf20Sopenharmony_ci return -EACCES; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci if (kstrtobool(buf, &v)) 2468c2ecf20Sopenharmony_ci return -EINVAL; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci sdp->manage_start_stop = v; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci return count; 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(manage_start_stop); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic ssize_t 2558c2ecf20Sopenharmony_ciallow_restart_show(struct device *dev, struct device_attribute *attr, char *buf) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", sdkp->device->allow_restart); 2608c2ecf20Sopenharmony_ci} 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_cistatic ssize_t 2638c2ecf20Sopenharmony_ciallow_restart_store(struct device *dev, struct device_attribute *attr, 2648c2ecf20Sopenharmony_ci const char *buf, size_t count) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci bool v; 2678c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 2688c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 2718c2ecf20Sopenharmony_ci return -EACCES; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC) 2748c2ecf20Sopenharmony_ci return -EINVAL; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci if (kstrtobool(buf, &v)) 2778c2ecf20Sopenharmony_ci return -EINVAL; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci sdp->allow_restart = v; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci return count; 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(allow_restart); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic ssize_t 2868c2ecf20Sopenharmony_cicache_type_show(struct device *dev, struct device_attribute *attr, char *buf) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 2898c2ecf20Sopenharmony_ci int ct = sdkp->RCD + 2*sdkp->WCE; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci return sprintf(buf, "%s\n", sd_cache_types[ct]); 2928c2ecf20Sopenharmony_ci} 2938c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(cache_type); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_cistatic ssize_t 2968c2ecf20Sopenharmony_ciFUA_show(struct device *dev, struct device_attribute *attr, char *buf) 2978c2ecf20Sopenharmony_ci{ 2988c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", sdkp->DPOFUA); 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(FUA); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic ssize_t 3058c2ecf20Sopenharmony_ciprotection_type_show(struct device *dev, struct device_attribute *attr, 3068c2ecf20Sopenharmony_ci char *buf) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", sdkp->protection_type); 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistatic ssize_t 3148c2ecf20Sopenharmony_ciprotection_type_store(struct device *dev, struct device_attribute *attr, 3158c2ecf20Sopenharmony_ci const char *buf, size_t count) 3168c2ecf20Sopenharmony_ci{ 3178c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 3188c2ecf20Sopenharmony_ci unsigned int val; 3198c2ecf20Sopenharmony_ci int err; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 3228c2ecf20Sopenharmony_ci return -EACCES; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci err = kstrtouint(buf, 10, &val); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci if (err) 3278c2ecf20Sopenharmony_ci return err; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci if (val <= T10_PI_TYPE3_PROTECTION) 3308c2ecf20Sopenharmony_ci sdkp->protection_type = val; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci return count; 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(protection_type); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cistatic ssize_t 3378c2ecf20Sopenharmony_ciprotection_mode_show(struct device *dev, struct device_attribute *attr, 3388c2ecf20Sopenharmony_ci char *buf) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 3418c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 3428c2ecf20Sopenharmony_ci unsigned int dif, dix; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type); 3458c2ecf20Sopenharmony_ci dix = scsi_host_dix_capable(sdp->host, sdkp->protection_type); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci if (!dix && scsi_host_dix_capable(sdp->host, T10_PI_TYPE0_PROTECTION)) { 3488c2ecf20Sopenharmony_ci dif = 0; 3498c2ecf20Sopenharmony_ci dix = 1; 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci if (!dif && !dix) 3538c2ecf20Sopenharmony_ci return sprintf(buf, "none\n"); 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci return sprintf(buf, "%s%u\n", dix ? "dix" : "dif", dif); 3568c2ecf20Sopenharmony_ci} 3578c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(protection_mode); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic ssize_t 3608c2ecf20Sopenharmony_ciapp_tag_own_show(struct device *dev, struct device_attribute *attr, char *buf) 3618c2ecf20Sopenharmony_ci{ 3628c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", sdkp->ATO); 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(app_tag_own); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistatic ssize_t 3698c2ecf20Sopenharmony_cithin_provisioning_show(struct device *dev, struct device_attribute *attr, 3708c2ecf20Sopenharmony_ci char *buf) 3718c2ecf20Sopenharmony_ci{ 3728c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", sdkp->lbpme); 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(thin_provisioning); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci/* sysfs_match_string() requires dense arrays */ 3798c2ecf20Sopenharmony_cistatic const char *lbp_mode[] = { 3808c2ecf20Sopenharmony_ci [SD_LBP_FULL] = "full", 3818c2ecf20Sopenharmony_ci [SD_LBP_UNMAP] = "unmap", 3828c2ecf20Sopenharmony_ci [SD_LBP_WS16] = "writesame_16", 3838c2ecf20Sopenharmony_ci [SD_LBP_WS10] = "writesame_10", 3848c2ecf20Sopenharmony_ci [SD_LBP_ZERO] = "writesame_zero", 3858c2ecf20Sopenharmony_ci [SD_LBP_DISABLE] = "disabled", 3868c2ecf20Sopenharmony_ci}; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_cistatic ssize_t 3898c2ecf20Sopenharmony_ciprovisioning_mode_show(struct device *dev, struct device_attribute *attr, 3908c2ecf20Sopenharmony_ci char *buf) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci return sprintf(buf, "%s\n", lbp_mode[sdkp->provisioning_mode]); 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_cistatic ssize_t 3988c2ecf20Sopenharmony_ciprovisioning_mode_store(struct device *dev, struct device_attribute *attr, 3998c2ecf20Sopenharmony_ci const char *buf, size_t count) 4008c2ecf20Sopenharmony_ci{ 4018c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 4028c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 4038c2ecf20Sopenharmony_ci int mode; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 4068c2ecf20Sopenharmony_ci return -EACCES; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci if (sd_is_zoned(sdkp)) { 4098c2ecf20Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_DISABLE); 4108c2ecf20Sopenharmony_ci return count; 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci if (sdp->type != TYPE_DISK) 4148c2ecf20Sopenharmony_ci return -EINVAL; 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci mode = sysfs_match_string(lbp_mode, buf); 4178c2ecf20Sopenharmony_ci if (mode < 0) 4188c2ecf20Sopenharmony_ci return -EINVAL; 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci sd_config_discard(sdkp, mode); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci return count; 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(provisioning_mode); 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci/* sysfs_match_string() requires dense arrays */ 4278c2ecf20Sopenharmony_cistatic const char *zeroing_mode[] = { 4288c2ecf20Sopenharmony_ci [SD_ZERO_WRITE] = "write", 4298c2ecf20Sopenharmony_ci [SD_ZERO_WS] = "writesame", 4308c2ecf20Sopenharmony_ci [SD_ZERO_WS16_UNMAP] = "writesame_16_unmap", 4318c2ecf20Sopenharmony_ci [SD_ZERO_WS10_UNMAP] = "writesame_10_unmap", 4328c2ecf20Sopenharmony_ci}; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_cistatic ssize_t 4358c2ecf20Sopenharmony_cizeroing_mode_show(struct device *dev, struct device_attribute *attr, 4368c2ecf20Sopenharmony_ci char *buf) 4378c2ecf20Sopenharmony_ci{ 4388c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci return sprintf(buf, "%s\n", zeroing_mode[sdkp->zeroing_mode]); 4418c2ecf20Sopenharmony_ci} 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_cistatic ssize_t 4448c2ecf20Sopenharmony_cizeroing_mode_store(struct device *dev, struct device_attribute *attr, 4458c2ecf20Sopenharmony_ci const char *buf, size_t count) 4468c2ecf20Sopenharmony_ci{ 4478c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 4488c2ecf20Sopenharmony_ci int mode; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 4518c2ecf20Sopenharmony_ci return -EACCES; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci mode = sysfs_match_string(zeroing_mode, buf); 4548c2ecf20Sopenharmony_ci if (mode < 0) 4558c2ecf20Sopenharmony_ci return -EINVAL; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci sdkp->zeroing_mode = mode; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci return count; 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(zeroing_mode); 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_cistatic ssize_t 4648c2ecf20Sopenharmony_cimax_medium_access_timeouts_show(struct device *dev, 4658c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 4668c2ecf20Sopenharmony_ci{ 4678c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", sdkp->max_medium_access_timeouts); 4708c2ecf20Sopenharmony_ci} 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_cistatic ssize_t 4738c2ecf20Sopenharmony_cimax_medium_access_timeouts_store(struct device *dev, 4748c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, 4758c2ecf20Sopenharmony_ci size_t count) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 4788c2ecf20Sopenharmony_ci int err; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 4818c2ecf20Sopenharmony_ci return -EACCES; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci err = kstrtouint(buf, 10, &sdkp->max_medium_access_timeouts); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci return err ? err : count; 4868c2ecf20Sopenharmony_ci} 4878c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(max_medium_access_timeouts); 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_cistatic ssize_t 4908c2ecf20Sopenharmony_cimax_write_same_blocks_show(struct device *dev, struct device_attribute *attr, 4918c2ecf20Sopenharmony_ci char *buf) 4928c2ecf20Sopenharmony_ci{ 4938c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", sdkp->max_ws_blocks); 4968c2ecf20Sopenharmony_ci} 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_cistatic ssize_t 4998c2ecf20Sopenharmony_cimax_write_same_blocks_store(struct device *dev, struct device_attribute *attr, 5008c2ecf20Sopenharmony_ci const char *buf, size_t count) 5018c2ecf20Sopenharmony_ci{ 5028c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 5038c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 5048c2ecf20Sopenharmony_ci unsigned long max; 5058c2ecf20Sopenharmony_ci int err; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 5088c2ecf20Sopenharmony_ci return -EACCES; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC) 5118c2ecf20Sopenharmony_ci return -EINVAL; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci err = kstrtoul(buf, 10, &max); 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci if (err) 5168c2ecf20Sopenharmony_ci return err; 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci if (max == 0) 5198c2ecf20Sopenharmony_ci sdp->no_write_same = 1; 5208c2ecf20Sopenharmony_ci else if (max <= SD_MAX_WS16_BLOCKS) { 5218c2ecf20Sopenharmony_ci sdp->no_write_same = 0; 5228c2ecf20Sopenharmony_ci sdkp->max_ws_blocks = max; 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci sd_config_write_same(sdkp); 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci return count; 5288c2ecf20Sopenharmony_ci} 5298c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(max_write_same_blocks); 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_cistatic ssize_t 5328c2ecf20Sopenharmony_cizoned_cap_show(struct device *dev, struct device_attribute *attr, char *buf) 5338c2ecf20Sopenharmony_ci{ 5348c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci if (sdkp->device->type == TYPE_ZBC) 5378c2ecf20Sopenharmony_ci return sprintf(buf, "host-managed\n"); 5388c2ecf20Sopenharmony_ci if (sdkp->zoned == 1) 5398c2ecf20Sopenharmony_ci return sprintf(buf, "host-aware\n"); 5408c2ecf20Sopenharmony_ci if (sdkp->zoned == 2) 5418c2ecf20Sopenharmony_ci return sprintf(buf, "drive-managed\n"); 5428c2ecf20Sopenharmony_ci return sprintf(buf, "none\n"); 5438c2ecf20Sopenharmony_ci} 5448c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(zoned_cap); 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_cistatic ssize_t 5478c2ecf20Sopenharmony_cimax_retries_store(struct device *dev, struct device_attribute *attr, 5488c2ecf20Sopenharmony_ci const char *buf, size_t count) 5498c2ecf20Sopenharmony_ci{ 5508c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 5518c2ecf20Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 5528c2ecf20Sopenharmony_ci int retries, err; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci err = kstrtoint(buf, 10, &retries); 5558c2ecf20Sopenharmony_ci if (err) 5568c2ecf20Sopenharmony_ci return err; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci if (retries == SCSI_CMD_RETRIES_NO_LIMIT || retries <= SD_MAX_RETRIES) { 5598c2ecf20Sopenharmony_ci sdkp->max_retries = retries; 5608c2ecf20Sopenharmony_ci return count; 5618c2ecf20Sopenharmony_ci } 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci sdev_printk(KERN_ERR, sdev, "max_retries must be between -1 and %d\n", 5648c2ecf20Sopenharmony_ci SD_MAX_RETRIES); 5658c2ecf20Sopenharmony_ci return -EINVAL; 5668c2ecf20Sopenharmony_ci} 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_cistatic ssize_t 5698c2ecf20Sopenharmony_cimax_retries_show(struct device *dev, struct device_attribute *attr, 5708c2ecf20Sopenharmony_ci char *buf) 5718c2ecf20Sopenharmony_ci{ 5728c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", sdkp->max_retries); 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(max_retries); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_cistatic struct attribute *sd_disk_attrs[] = { 5808c2ecf20Sopenharmony_ci &dev_attr_cache_type.attr, 5818c2ecf20Sopenharmony_ci &dev_attr_FUA.attr, 5828c2ecf20Sopenharmony_ci &dev_attr_allow_restart.attr, 5838c2ecf20Sopenharmony_ci &dev_attr_manage_start_stop.attr, 5848c2ecf20Sopenharmony_ci &dev_attr_protection_type.attr, 5858c2ecf20Sopenharmony_ci &dev_attr_protection_mode.attr, 5868c2ecf20Sopenharmony_ci &dev_attr_app_tag_own.attr, 5878c2ecf20Sopenharmony_ci &dev_attr_thin_provisioning.attr, 5888c2ecf20Sopenharmony_ci &dev_attr_provisioning_mode.attr, 5898c2ecf20Sopenharmony_ci &dev_attr_zeroing_mode.attr, 5908c2ecf20Sopenharmony_ci &dev_attr_max_write_same_blocks.attr, 5918c2ecf20Sopenharmony_ci &dev_attr_max_medium_access_timeouts.attr, 5928c2ecf20Sopenharmony_ci &dev_attr_zoned_cap.attr, 5938c2ecf20Sopenharmony_ci &dev_attr_max_retries.attr, 5948c2ecf20Sopenharmony_ci NULL, 5958c2ecf20Sopenharmony_ci}; 5968c2ecf20Sopenharmony_ciATTRIBUTE_GROUPS(sd_disk); 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_cistatic struct class sd_disk_class = { 5998c2ecf20Sopenharmony_ci .name = "scsi_disk", 6008c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 6018c2ecf20Sopenharmony_ci .dev_release = scsi_disk_release, 6028c2ecf20Sopenharmony_ci .dev_groups = sd_disk_groups, 6038c2ecf20Sopenharmony_ci}; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_cistatic const struct dev_pm_ops sd_pm_ops = { 6068c2ecf20Sopenharmony_ci .suspend = sd_suspend_system, 6078c2ecf20Sopenharmony_ci .resume = sd_resume, 6088c2ecf20Sopenharmony_ci .poweroff = sd_suspend_system, 6098c2ecf20Sopenharmony_ci .restore = sd_resume, 6108c2ecf20Sopenharmony_ci .runtime_suspend = sd_suspend_runtime, 6118c2ecf20Sopenharmony_ci .runtime_resume = sd_resume, 6128c2ecf20Sopenharmony_ci}; 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_cistatic struct scsi_driver sd_template = { 6158c2ecf20Sopenharmony_ci .gendrv = { 6168c2ecf20Sopenharmony_ci .name = "sd", 6178c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 6188c2ecf20Sopenharmony_ci .probe = sd_probe, 6198c2ecf20Sopenharmony_ci .probe_type = PROBE_PREFER_ASYNCHRONOUS, 6208c2ecf20Sopenharmony_ci .remove = sd_remove, 6218c2ecf20Sopenharmony_ci .shutdown = sd_shutdown, 6228c2ecf20Sopenharmony_ci .pm = &sd_pm_ops, 6238c2ecf20Sopenharmony_ci }, 6248c2ecf20Sopenharmony_ci .rescan = sd_rescan, 6258c2ecf20Sopenharmony_ci .init_command = sd_init_command, 6268c2ecf20Sopenharmony_ci .uninit_command = sd_uninit_command, 6278c2ecf20Sopenharmony_ci .done = sd_done, 6288c2ecf20Sopenharmony_ci .eh_action = sd_eh_action, 6298c2ecf20Sopenharmony_ci .eh_reset = sd_eh_reset, 6308c2ecf20Sopenharmony_ci}; 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci/* 6338c2ecf20Sopenharmony_ci * Dummy kobj_map->probe function. 6348c2ecf20Sopenharmony_ci * The default ->probe function will call modprobe, which is 6358c2ecf20Sopenharmony_ci * pointless as this module is already loaded. 6368c2ecf20Sopenharmony_ci */ 6378c2ecf20Sopenharmony_cistatic struct kobject *sd_default_probe(dev_t devt, int *partno, void *data) 6388c2ecf20Sopenharmony_ci{ 6398c2ecf20Sopenharmony_ci return NULL; 6408c2ecf20Sopenharmony_ci} 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci/* 6438c2ecf20Sopenharmony_ci * Device no to disk mapping: 6448c2ecf20Sopenharmony_ci * 6458c2ecf20Sopenharmony_ci * major disc2 disc p1 6468c2ecf20Sopenharmony_ci * |............|.............|....|....| <- dev_t 6478c2ecf20Sopenharmony_ci * 31 20 19 8 7 4 3 0 6488c2ecf20Sopenharmony_ci * 6498c2ecf20Sopenharmony_ci * Inside a major, we have 16k disks, however mapped non- 6508c2ecf20Sopenharmony_ci * contiguously. The first 16 disks are for major0, the next 6518c2ecf20Sopenharmony_ci * ones with major1, ... Disk 256 is for major0 again, disk 272 6528c2ecf20Sopenharmony_ci * for major1, ... 6538c2ecf20Sopenharmony_ci * As we stay compatible with our numbering scheme, we can reuse 6548c2ecf20Sopenharmony_ci * the well-know SCSI majors 8, 65--71, 136--143. 6558c2ecf20Sopenharmony_ci */ 6568c2ecf20Sopenharmony_cistatic int sd_major(int major_idx) 6578c2ecf20Sopenharmony_ci{ 6588c2ecf20Sopenharmony_ci switch (major_idx) { 6598c2ecf20Sopenharmony_ci case 0: 6608c2ecf20Sopenharmony_ci return SCSI_DISK0_MAJOR; 6618c2ecf20Sopenharmony_ci case 1 ... 7: 6628c2ecf20Sopenharmony_ci return SCSI_DISK1_MAJOR + major_idx - 1; 6638c2ecf20Sopenharmony_ci case 8 ... 15: 6648c2ecf20Sopenharmony_ci return SCSI_DISK8_MAJOR + major_idx - 8; 6658c2ecf20Sopenharmony_ci default: 6668c2ecf20Sopenharmony_ci BUG(); 6678c2ecf20Sopenharmony_ci return 0; /* shut up gcc */ 6688c2ecf20Sopenharmony_ci } 6698c2ecf20Sopenharmony_ci} 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_cistatic struct scsi_disk *scsi_disk_get(struct gendisk *disk) 6728c2ecf20Sopenharmony_ci{ 6738c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = NULL; 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci mutex_lock(&sd_ref_mutex); 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci if (disk->private_data) { 6788c2ecf20Sopenharmony_ci sdkp = scsi_disk(disk); 6798c2ecf20Sopenharmony_ci if (scsi_device_get(sdkp->device) == 0) 6808c2ecf20Sopenharmony_ci get_device(&sdkp->dev); 6818c2ecf20Sopenharmony_ci else 6828c2ecf20Sopenharmony_ci sdkp = NULL; 6838c2ecf20Sopenharmony_ci } 6848c2ecf20Sopenharmony_ci mutex_unlock(&sd_ref_mutex); 6858c2ecf20Sopenharmony_ci return sdkp; 6868c2ecf20Sopenharmony_ci} 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_cistatic void scsi_disk_put(struct scsi_disk *sdkp) 6898c2ecf20Sopenharmony_ci{ 6908c2ecf20Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci mutex_lock(&sd_ref_mutex); 6938c2ecf20Sopenharmony_ci put_device(&sdkp->dev); 6948c2ecf20Sopenharmony_ci scsi_device_put(sdev); 6958c2ecf20Sopenharmony_ci mutex_unlock(&sd_ref_mutex); 6968c2ecf20Sopenharmony_ci} 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_SED_OPAL 6998c2ecf20Sopenharmony_cistatic int sd_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, 7008c2ecf20Sopenharmony_ci size_t len, bool send) 7018c2ecf20Sopenharmony_ci{ 7028c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = data; 7038c2ecf20Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 7048c2ecf20Sopenharmony_ci u8 cdb[12] = { 0, }; 7058c2ecf20Sopenharmony_ci int ret; 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci cdb[0] = send ? SECURITY_PROTOCOL_OUT : SECURITY_PROTOCOL_IN; 7088c2ecf20Sopenharmony_ci cdb[1] = secp; 7098c2ecf20Sopenharmony_ci put_unaligned_be16(spsp, &cdb[2]); 7108c2ecf20Sopenharmony_ci put_unaligned_be32(len, &cdb[6]); 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci ret = scsi_execute(sdev, cdb, send ? DMA_TO_DEVICE : DMA_FROM_DEVICE, 7138c2ecf20Sopenharmony_ci buffer, len, NULL, NULL, SD_TIMEOUT, sdkp->max_retries, 0, 7148c2ecf20Sopenharmony_ci RQF_PM, NULL); 7158c2ecf20Sopenharmony_ci return ret <= 0 ? ret : -EIO; 7168c2ecf20Sopenharmony_ci} 7178c2ecf20Sopenharmony_ci#endif /* CONFIG_BLK_SED_OPAL */ 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci/* 7208c2ecf20Sopenharmony_ci * Look up the DIX operation based on whether the command is read or 7218c2ecf20Sopenharmony_ci * write and whether dix and dif are enabled. 7228c2ecf20Sopenharmony_ci */ 7238c2ecf20Sopenharmony_cistatic unsigned int sd_prot_op(bool write, bool dix, bool dif) 7248c2ecf20Sopenharmony_ci{ 7258c2ecf20Sopenharmony_ci /* Lookup table: bit 2 (write), bit 1 (dix), bit 0 (dif) */ 7268c2ecf20Sopenharmony_ci static const unsigned int ops[] = { /* wrt dix dif */ 7278c2ecf20Sopenharmony_ci SCSI_PROT_NORMAL, /* 0 0 0 */ 7288c2ecf20Sopenharmony_ci SCSI_PROT_READ_STRIP, /* 0 0 1 */ 7298c2ecf20Sopenharmony_ci SCSI_PROT_READ_INSERT, /* 0 1 0 */ 7308c2ecf20Sopenharmony_ci SCSI_PROT_READ_PASS, /* 0 1 1 */ 7318c2ecf20Sopenharmony_ci SCSI_PROT_NORMAL, /* 1 0 0 */ 7328c2ecf20Sopenharmony_ci SCSI_PROT_WRITE_INSERT, /* 1 0 1 */ 7338c2ecf20Sopenharmony_ci SCSI_PROT_WRITE_STRIP, /* 1 1 0 */ 7348c2ecf20Sopenharmony_ci SCSI_PROT_WRITE_PASS, /* 1 1 1 */ 7358c2ecf20Sopenharmony_ci }; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci return ops[write << 2 | dix << 1 | dif]; 7388c2ecf20Sopenharmony_ci} 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci/* 7418c2ecf20Sopenharmony_ci * Returns a mask of the protection flags that are valid for a given DIX 7428c2ecf20Sopenharmony_ci * operation. 7438c2ecf20Sopenharmony_ci */ 7448c2ecf20Sopenharmony_cistatic unsigned int sd_prot_flag_mask(unsigned int prot_op) 7458c2ecf20Sopenharmony_ci{ 7468c2ecf20Sopenharmony_ci static const unsigned int flag_mask[] = { 7478c2ecf20Sopenharmony_ci [SCSI_PROT_NORMAL] = 0, 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci [SCSI_PROT_READ_STRIP] = SCSI_PROT_TRANSFER_PI | 7508c2ecf20Sopenharmony_ci SCSI_PROT_GUARD_CHECK | 7518c2ecf20Sopenharmony_ci SCSI_PROT_REF_CHECK | 7528c2ecf20Sopenharmony_ci SCSI_PROT_REF_INCREMENT, 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci [SCSI_PROT_READ_INSERT] = SCSI_PROT_REF_INCREMENT | 7558c2ecf20Sopenharmony_ci SCSI_PROT_IP_CHECKSUM, 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci [SCSI_PROT_READ_PASS] = SCSI_PROT_TRANSFER_PI | 7588c2ecf20Sopenharmony_ci SCSI_PROT_GUARD_CHECK | 7598c2ecf20Sopenharmony_ci SCSI_PROT_REF_CHECK | 7608c2ecf20Sopenharmony_ci SCSI_PROT_REF_INCREMENT | 7618c2ecf20Sopenharmony_ci SCSI_PROT_IP_CHECKSUM, 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci [SCSI_PROT_WRITE_INSERT] = SCSI_PROT_TRANSFER_PI | 7648c2ecf20Sopenharmony_ci SCSI_PROT_REF_INCREMENT, 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci [SCSI_PROT_WRITE_STRIP] = SCSI_PROT_GUARD_CHECK | 7678c2ecf20Sopenharmony_ci SCSI_PROT_REF_CHECK | 7688c2ecf20Sopenharmony_ci SCSI_PROT_REF_INCREMENT | 7698c2ecf20Sopenharmony_ci SCSI_PROT_IP_CHECKSUM, 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci [SCSI_PROT_WRITE_PASS] = SCSI_PROT_TRANSFER_PI | 7728c2ecf20Sopenharmony_ci SCSI_PROT_GUARD_CHECK | 7738c2ecf20Sopenharmony_ci SCSI_PROT_REF_CHECK | 7748c2ecf20Sopenharmony_ci SCSI_PROT_REF_INCREMENT | 7758c2ecf20Sopenharmony_ci SCSI_PROT_IP_CHECKSUM, 7768c2ecf20Sopenharmony_ci }; 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci return flag_mask[prot_op]; 7798c2ecf20Sopenharmony_ci} 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_cistatic unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd, 7828c2ecf20Sopenharmony_ci unsigned int dix, unsigned int dif) 7838c2ecf20Sopenharmony_ci{ 7848c2ecf20Sopenharmony_ci struct bio *bio = scmd->request->bio; 7858c2ecf20Sopenharmony_ci unsigned int prot_op = sd_prot_op(rq_data_dir(scmd->request), dix, dif); 7868c2ecf20Sopenharmony_ci unsigned int protect = 0; 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci if (dix) { /* DIX Type 0, 1, 2, 3 */ 7898c2ecf20Sopenharmony_ci if (bio_integrity_flagged(bio, BIP_IP_CHECKSUM)) 7908c2ecf20Sopenharmony_ci scmd->prot_flags |= SCSI_PROT_IP_CHECKSUM; 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci if (bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false) 7938c2ecf20Sopenharmony_ci scmd->prot_flags |= SCSI_PROT_GUARD_CHECK; 7948c2ecf20Sopenharmony_ci } 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci if (dif != T10_PI_TYPE3_PROTECTION) { /* DIX/DIF Type 0, 1, 2 */ 7978c2ecf20Sopenharmony_ci scmd->prot_flags |= SCSI_PROT_REF_INCREMENT; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci if (bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false) 8008c2ecf20Sopenharmony_ci scmd->prot_flags |= SCSI_PROT_REF_CHECK; 8018c2ecf20Sopenharmony_ci } 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci if (dif) { /* DIX/DIF Type 1, 2, 3 */ 8048c2ecf20Sopenharmony_ci scmd->prot_flags |= SCSI_PROT_TRANSFER_PI; 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci if (bio_integrity_flagged(bio, BIP_DISK_NOCHECK)) 8078c2ecf20Sopenharmony_ci protect = 3 << 5; /* Disable target PI checking */ 8088c2ecf20Sopenharmony_ci else 8098c2ecf20Sopenharmony_ci protect = 1 << 5; /* Enable target PI checking */ 8108c2ecf20Sopenharmony_ci } 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci scsi_set_prot_op(scmd, prot_op); 8138c2ecf20Sopenharmony_ci scsi_set_prot_type(scmd, dif); 8148c2ecf20Sopenharmony_ci scmd->prot_flags &= sd_prot_flag_mask(prot_op); 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci return protect; 8178c2ecf20Sopenharmony_ci} 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_cistatic void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) 8208c2ecf20Sopenharmony_ci{ 8218c2ecf20Sopenharmony_ci struct request_queue *q = sdkp->disk->queue; 8228c2ecf20Sopenharmony_ci unsigned int logical_block_size = sdkp->device->sector_size; 8238c2ecf20Sopenharmony_ci unsigned int max_blocks = 0; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci q->limits.discard_alignment = 8268c2ecf20Sopenharmony_ci sdkp->unmap_alignment * logical_block_size; 8278c2ecf20Sopenharmony_ci q->limits.discard_granularity = 8288c2ecf20Sopenharmony_ci max(sdkp->physical_block_size, 8298c2ecf20Sopenharmony_ci sdkp->unmap_granularity * logical_block_size); 8308c2ecf20Sopenharmony_ci sdkp->provisioning_mode = mode; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci switch (mode) { 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci case SD_LBP_FULL: 8358c2ecf20Sopenharmony_ci case SD_LBP_DISABLE: 8368c2ecf20Sopenharmony_ci blk_queue_max_discard_sectors(q, 0); 8378c2ecf20Sopenharmony_ci blk_queue_flag_clear(QUEUE_FLAG_DISCARD, q); 8388c2ecf20Sopenharmony_ci return; 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci case SD_LBP_UNMAP: 8418c2ecf20Sopenharmony_ci max_blocks = min_not_zero(sdkp->max_unmap_blocks, 8428c2ecf20Sopenharmony_ci (u32)SD_MAX_WS16_BLOCKS); 8438c2ecf20Sopenharmony_ci break; 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci case SD_LBP_WS16: 8468c2ecf20Sopenharmony_ci if (sdkp->device->unmap_limit_for_ws) 8478c2ecf20Sopenharmony_ci max_blocks = sdkp->max_unmap_blocks; 8488c2ecf20Sopenharmony_ci else 8498c2ecf20Sopenharmony_ci max_blocks = sdkp->max_ws_blocks; 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci max_blocks = min_not_zero(max_blocks, (u32)SD_MAX_WS16_BLOCKS); 8528c2ecf20Sopenharmony_ci break; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci case SD_LBP_WS10: 8558c2ecf20Sopenharmony_ci if (sdkp->device->unmap_limit_for_ws) 8568c2ecf20Sopenharmony_ci max_blocks = sdkp->max_unmap_blocks; 8578c2ecf20Sopenharmony_ci else 8588c2ecf20Sopenharmony_ci max_blocks = sdkp->max_ws_blocks; 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci max_blocks = min_not_zero(max_blocks, (u32)SD_MAX_WS10_BLOCKS); 8618c2ecf20Sopenharmony_ci break; 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci case SD_LBP_ZERO: 8648c2ecf20Sopenharmony_ci max_blocks = min_not_zero(sdkp->max_ws_blocks, 8658c2ecf20Sopenharmony_ci (u32)SD_MAX_WS10_BLOCKS); 8668c2ecf20Sopenharmony_ci break; 8678c2ecf20Sopenharmony_ci } 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci blk_queue_max_discard_sectors(q, max_blocks * (logical_block_size >> 9)); 8708c2ecf20Sopenharmony_ci blk_queue_flag_set(QUEUE_FLAG_DISCARD, q); 8718c2ecf20Sopenharmony_ci} 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_cistatic blk_status_t sd_setup_unmap_cmnd(struct scsi_cmnd *cmd) 8748c2ecf20Sopenharmony_ci{ 8758c2ecf20Sopenharmony_ci struct scsi_device *sdp = cmd->device; 8768c2ecf20Sopenharmony_ci struct request *rq = cmd->request; 8778c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); 8788c2ecf20Sopenharmony_ci u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq)); 8798c2ecf20Sopenharmony_ci u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); 8808c2ecf20Sopenharmony_ci unsigned int data_len = 24; 8818c2ecf20Sopenharmony_ci char *buf; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci rq->special_vec.bv_page = mempool_alloc(sd_page_pool, GFP_ATOMIC); 8848c2ecf20Sopenharmony_ci if (!rq->special_vec.bv_page) 8858c2ecf20Sopenharmony_ci return BLK_STS_RESOURCE; 8868c2ecf20Sopenharmony_ci clear_highpage(rq->special_vec.bv_page); 8878c2ecf20Sopenharmony_ci rq->special_vec.bv_offset = 0; 8888c2ecf20Sopenharmony_ci rq->special_vec.bv_len = data_len; 8898c2ecf20Sopenharmony_ci rq->rq_flags |= RQF_SPECIAL_PAYLOAD; 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci cmd->cmd_len = 10; 8928c2ecf20Sopenharmony_ci cmd->cmnd[0] = UNMAP; 8938c2ecf20Sopenharmony_ci cmd->cmnd[8] = 24; 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci buf = page_address(rq->special_vec.bv_page); 8968c2ecf20Sopenharmony_ci put_unaligned_be16(6 + 16, &buf[0]); 8978c2ecf20Sopenharmony_ci put_unaligned_be16(16, &buf[2]); 8988c2ecf20Sopenharmony_ci put_unaligned_be64(lba, &buf[8]); 8998c2ecf20Sopenharmony_ci put_unaligned_be32(nr_blocks, &buf[16]); 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci cmd->allowed = sdkp->max_retries; 9028c2ecf20Sopenharmony_ci cmd->transfersize = data_len; 9038c2ecf20Sopenharmony_ci rq->timeout = SD_TIMEOUT; 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci return scsi_alloc_sgtables(cmd); 9068c2ecf20Sopenharmony_ci} 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_cistatic blk_status_t sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd, 9098c2ecf20Sopenharmony_ci bool unmap) 9108c2ecf20Sopenharmony_ci{ 9118c2ecf20Sopenharmony_ci struct scsi_device *sdp = cmd->device; 9128c2ecf20Sopenharmony_ci struct request *rq = cmd->request; 9138c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); 9148c2ecf20Sopenharmony_ci u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq)); 9158c2ecf20Sopenharmony_ci u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); 9168c2ecf20Sopenharmony_ci u32 data_len = sdp->sector_size; 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci rq->special_vec.bv_page = mempool_alloc(sd_page_pool, GFP_ATOMIC); 9198c2ecf20Sopenharmony_ci if (!rq->special_vec.bv_page) 9208c2ecf20Sopenharmony_ci return BLK_STS_RESOURCE; 9218c2ecf20Sopenharmony_ci clear_highpage(rq->special_vec.bv_page); 9228c2ecf20Sopenharmony_ci rq->special_vec.bv_offset = 0; 9238c2ecf20Sopenharmony_ci rq->special_vec.bv_len = data_len; 9248c2ecf20Sopenharmony_ci rq->rq_flags |= RQF_SPECIAL_PAYLOAD; 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci cmd->cmd_len = 16; 9278c2ecf20Sopenharmony_ci cmd->cmnd[0] = WRITE_SAME_16; 9288c2ecf20Sopenharmony_ci if (unmap) 9298c2ecf20Sopenharmony_ci cmd->cmnd[1] = 0x8; /* UNMAP */ 9308c2ecf20Sopenharmony_ci put_unaligned_be64(lba, &cmd->cmnd[2]); 9318c2ecf20Sopenharmony_ci put_unaligned_be32(nr_blocks, &cmd->cmnd[10]); 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci cmd->allowed = sdkp->max_retries; 9348c2ecf20Sopenharmony_ci cmd->transfersize = data_len; 9358c2ecf20Sopenharmony_ci rq->timeout = unmap ? SD_TIMEOUT : SD_WRITE_SAME_TIMEOUT; 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci return scsi_alloc_sgtables(cmd); 9388c2ecf20Sopenharmony_ci} 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_cistatic blk_status_t sd_setup_write_same10_cmnd(struct scsi_cmnd *cmd, 9418c2ecf20Sopenharmony_ci bool unmap) 9428c2ecf20Sopenharmony_ci{ 9438c2ecf20Sopenharmony_ci struct scsi_device *sdp = cmd->device; 9448c2ecf20Sopenharmony_ci struct request *rq = cmd->request; 9458c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); 9468c2ecf20Sopenharmony_ci u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq)); 9478c2ecf20Sopenharmony_ci u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); 9488c2ecf20Sopenharmony_ci u32 data_len = sdp->sector_size; 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci rq->special_vec.bv_page = mempool_alloc(sd_page_pool, GFP_ATOMIC); 9518c2ecf20Sopenharmony_ci if (!rq->special_vec.bv_page) 9528c2ecf20Sopenharmony_ci return BLK_STS_RESOURCE; 9538c2ecf20Sopenharmony_ci clear_highpage(rq->special_vec.bv_page); 9548c2ecf20Sopenharmony_ci rq->special_vec.bv_offset = 0; 9558c2ecf20Sopenharmony_ci rq->special_vec.bv_len = data_len; 9568c2ecf20Sopenharmony_ci rq->rq_flags |= RQF_SPECIAL_PAYLOAD; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci cmd->cmd_len = 10; 9598c2ecf20Sopenharmony_ci cmd->cmnd[0] = WRITE_SAME; 9608c2ecf20Sopenharmony_ci if (unmap) 9618c2ecf20Sopenharmony_ci cmd->cmnd[1] = 0x8; /* UNMAP */ 9628c2ecf20Sopenharmony_ci put_unaligned_be32(lba, &cmd->cmnd[2]); 9638c2ecf20Sopenharmony_ci put_unaligned_be16(nr_blocks, &cmd->cmnd[7]); 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci cmd->allowed = sdkp->max_retries; 9668c2ecf20Sopenharmony_ci cmd->transfersize = data_len; 9678c2ecf20Sopenharmony_ci rq->timeout = unmap ? SD_TIMEOUT : SD_WRITE_SAME_TIMEOUT; 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci return scsi_alloc_sgtables(cmd); 9708c2ecf20Sopenharmony_ci} 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_cistatic blk_status_t sd_setup_write_zeroes_cmnd(struct scsi_cmnd *cmd) 9738c2ecf20Sopenharmony_ci{ 9748c2ecf20Sopenharmony_ci struct request *rq = cmd->request; 9758c2ecf20Sopenharmony_ci struct scsi_device *sdp = cmd->device; 9768c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); 9778c2ecf20Sopenharmony_ci u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq)); 9788c2ecf20Sopenharmony_ci u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci if (!(rq->cmd_flags & REQ_NOUNMAP)) { 9818c2ecf20Sopenharmony_ci switch (sdkp->zeroing_mode) { 9828c2ecf20Sopenharmony_ci case SD_ZERO_WS16_UNMAP: 9838c2ecf20Sopenharmony_ci return sd_setup_write_same16_cmnd(cmd, true); 9848c2ecf20Sopenharmony_ci case SD_ZERO_WS10_UNMAP: 9858c2ecf20Sopenharmony_ci return sd_setup_write_same10_cmnd(cmd, true); 9868c2ecf20Sopenharmony_ci } 9878c2ecf20Sopenharmony_ci } 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci if (sdp->no_write_same) { 9908c2ecf20Sopenharmony_ci rq->rq_flags |= RQF_QUIET; 9918c2ecf20Sopenharmony_ci return BLK_STS_TARGET; 9928c2ecf20Sopenharmony_ci } 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci if (sdkp->ws16 || lba > 0xffffffff || nr_blocks > 0xffff) 9958c2ecf20Sopenharmony_ci return sd_setup_write_same16_cmnd(cmd, false); 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci return sd_setup_write_same10_cmnd(cmd, false); 9988c2ecf20Sopenharmony_ci} 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_cistatic void sd_config_write_same(struct scsi_disk *sdkp) 10018c2ecf20Sopenharmony_ci{ 10028c2ecf20Sopenharmony_ci struct request_queue *q = sdkp->disk->queue; 10038c2ecf20Sopenharmony_ci unsigned int logical_block_size = sdkp->device->sector_size; 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci if (sdkp->device->no_write_same) { 10068c2ecf20Sopenharmony_ci sdkp->max_ws_blocks = 0; 10078c2ecf20Sopenharmony_ci goto out; 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci /* Some devices can not handle block counts above 0xffff despite 10118c2ecf20Sopenharmony_ci * supporting WRITE SAME(16). Consequently we default to 64k 10128c2ecf20Sopenharmony_ci * blocks per I/O unless the device explicitly advertises a 10138c2ecf20Sopenharmony_ci * bigger limit. 10148c2ecf20Sopenharmony_ci */ 10158c2ecf20Sopenharmony_ci if (sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS) 10168c2ecf20Sopenharmony_ci sdkp->max_ws_blocks = min_not_zero(sdkp->max_ws_blocks, 10178c2ecf20Sopenharmony_ci (u32)SD_MAX_WS16_BLOCKS); 10188c2ecf20Sopenharmony_ci else if (sdkp->ws16 || sdkp->ws10 || sdkp->device->no_report_opcodes) 10198c2ecf20Sopenharmony_ci sdkp->max_ws_blocks = min_not_zero(sdkp->max_ws_blocks, 10208c2ecf20Sopenharmony_ci (u32)SD_MAX_WS10_BLOCKS); 10218c2ecf20Sopenharmony_ci else { 10228c2ecf20Sopenharmony_ci sdkp->device->no_write_same = 1; 10238c2ecf20Sopenharmony_ci sdkp->max_ws_blocks = 0; 10248c2ecf20Sopenharmony_ci } 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci if (sdkp->lbprz && sdkp->lbpws) 10278c2ecf20Sopenharmony_ci sdkp->zeroing_mode = SD_ZERO_WS16_UNMAP; 10288c2ecf20Sopenharmony_ci else if (sdkp->lbprz && sdkp->lbpws10) 10298c2ecf20Sopenharmony_ci sdkp->zeroing_mode = SD_ZERO_WS10_UNMAP; 10308c2ecf20Sopenharmony_ci else if (sdkp->max_ws_blocks) 10318c2ecf20Sopenharmony_ci sdkp->zeroing_mode = SD_ZERO_WS; 10328c2ecf20Sopenharmony_ci else 10338c2ecf20Sopenharmony_ci sdkp->zeroing_mode = SD_ZERO_WRITE; 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci if (sdkp->max_ws_blocks && 10368c2ecf20Sopenharmony_ci sdkp->physical_block_size > logical_block_size) { 10378c2ecf20Sopenharmony_ci /* 10388c2ecf20Sopenharmony_ci * Reporting a maximum number of blocks that is not aligned 10398c2ecf20Sopenharmony_ci * on the device physical size would cause a large write same 10408c2ecf20Sopenharmony_ci * request to be split into physically unaligned chunks by 10418c2ecf20Sopenharmony_ci * __blkdev_issue_write_zeroes() and __blkdev_issue_write_same() 10428c2ecf20Sopenharmony_ci * even if the caller of these functions took care to align the 10438c2ecf20Sopenharmony_ci * large request. So make sure the maximum reported is aligned 10448c2ecf20Sopenharmony_ci * to the device physical block size. This is only an optional 10458c2ecf20Sopenharmony_ci * optimization for regular disks, but this is mandatory to 10468c2ecf20Sopenharmony_ci * avoid failure of large write same requests directed at 10478c2ecf20Sopenharmony_ci * sequential write required zones of host-managed ZBC disks. 10488c2ecf20Sopenharmony_ci */ 10498c2ecf20Sopenharmony_ci sdkp->max_ws_blocks = 10508c2ecf20Sopenharmony_ci round_down(sdkp->max_ws_blocks, 10518c2ecf20Sopenharmony_ci bytes_to_logical(sdkp->device, 10528c2ecf20Sopenharmony_ci sdkp->physical_block_size)); 10538c2ecf20Sopenharmony_ci } 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ciout: 10568c2ecf20Sopenharmony_ci blk_queue_max_write_same_sectors(q, sdkp->max_ws_blocks * 10578c2ecf20Sopenharmony_ci (logical_block_size >> 9)); 10588c2ecf20Sopenharmony_ci blk_queue_max_write_zeroes_sectors(q, sdkp->max_ws_blocks * 10598c2ecf20Sopenharmony_ci (logical_block_size >> 9)); 10608c2ecf20Sopenharmony_ci} 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci/** 10638c2ecf20Sopenharmony_ci * sd_setup_write_same_cmnd - write the same data to multiple blocks 10648c2ecf20Sopenharmony_ci * @cmd: command to prepare 10658c2ecf20Sopenharmony_ci * 10668c2ecf20Sopenharmony_ci * Will set up either WRITE SAME(10) or WRITE SAME(16) depending on 10678c2ecf20Sopenharmony_ci * the preference indicated by the target device. 10688c2ecf20Sopenharmony_ci **/ 10698c2ecf20Sopenharmony_cistatic blk_status_t sd_setup_write_same_cmnd(struct scsi_cmnd *cmd) 10708c2ecf20Sopenharmony_ci{ 10718c2ecf20Sopenharmony_ci struct request *rq = cmd->request; 10728c2ecf20Sopenharmony_ci struct scsi_device *sdp = cmd->device; 10738c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); 10748c2ecf20Sopenharmony_ci struct bio *bio = rq->bio; 10758c2ecf20Sopenharmony_ci u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq)); 10768c2ecf20Sopenharmony_ci u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); 10778c2ecf20Sopenharmony_ci unsigned int nr_bytes = blk_rq_bytes(rq); 10788c2ecf20Sopenharmony_ci blk_status_t ret; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci if (sdkp->device->no_write_same) 10818c2ecf20Sopenharmony_ci return BLK_STS_TARGET; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci BUG_ON(bio_offset(bio) || bio_iovec(bio).bv_len != sdp->sector_size); 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci rq->timeout = SD_WRITE_SAME_TIMEOUT; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci if (sdkp->ws16 || lba > 0xffffffff || nr_blocks > 0xffff) { 10888c2ecf20Sopenharmony_ci cmd->cmd_len = 16; 10898c2ecf20Sopenharmony_ci cmd->cmnd[0] = WRITE_SAME_16; 10908c2ecf20Sopenharmony_ci put_unaligned_be64(lba, &cmd->cmnd[2]); 10918c2ecf20Sopenharmony_ci put_unaligned_be32(nr_blocks, &cmd->cmnd[10]); 10928c2ecf20Sopenharmony_ci } else { 10938c2ecf20Sopenharmony_ci cmd->cmd_len = 10; 10948c2ecf20Sopenharmony_ci cmd->cmnd[0] = WRITE_SAME; 10958c2ecf20Sopenharmony_ci put_unaligned_be32(lba, &cmd->cmnd[2]); 10968c2ecf20Sopenharmony_ci put_unaligned_be16(nr_blocks, &cmd->cmnd[7]); 10978c2ecf20Sopenharmony_ci } 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci cmd->transfersize = sdp->sector_size; 11008c2ecf20Sopenharmony_ci cmd->allowed = sdkp->max_retries; 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci /* 11038c2ecf20Sopenharmony_ci * For WRITE SAME the data transferred via the DATA OUT buffer is 11048c2ecf20Sopenharmony_ci * different from the amount of data actually written to the target. 11058c2ecf20Sopenharmony_ci * 11068c2ecf20Sopenharmony_ci * We set up __data_len to the amount of data transferred via the 11078c2ecf20Sopenharmony_ci * DATA OUT buffer so that blk_rq_map_sg sets up the proper S/G list 11088c2ecf20Sopenharmony_ci * to transfer a single sector of data first, but then reset it to 11098c2ecf20Sopenharmony_ci * the amount of data to be written right after so that the I/O path 11108c2ecf20Sopenharmony_ci * knows how much to actually write. 11118c2ecf20Sopenharmony_ci */ 11128c2ecf20Sopenharmony_ci rq->__data_len = sdp->sector_size; 11138c2ecf20Sopenharmony_ci ret = scsi_alloc_sgtables(cmd); 11148c2ecf20Sopenharmony_ci rq->__data_len = nr_bytes; 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci return ret; 11178c2ecf20Sopenharmony_ci} 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_cistatic blk_status_t sd_setup_flush_cmnd(struct scsi_cmnd *cmd) 11208c2ecf20Sopenharmony_ci{ 11218c2ecf20Sopenharmony_ci struct request *rq = cmd->request; 11228c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci /* flush requests don't perform I/O, zero the S/G table */ 11258c2ecf20Sopenharmony_ci memset(&cmd->sdb, 0, sizeof(cmd->sdb)); 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci cmd->cmnd[0] = SYNCHRONIZE_CACHE; 11288c2ecf20Sopenharmony_ci cmd->cmd_len = 10; 11298c2ecf20Sopenharmony_ci cmd->transfersize = 0; 11308c2ecf20Sopenharmony_ci cmd->allowed = sdkp->max_retries; 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci rq->timeout = rq->q->rq_timeout * SD_FLUSH_TIMEOUT_MULTIPLIER; 11338c2ecf20Sopenharmony_ci return BLK_STS_OK; 11348c2ecf20Sopenharmony_ci} 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_cistatic blk_status_t sd_setup_rw32_cmnd(struct scsi_cmnd *cmd, bool write, 11378c2ecf20Sopenharmony_ci sector_t lba, unsigned int nr_blocks, 11388c2ecf20Sopenharmony_ci unsigned char flags) 11398c2ecf20Sopenharmony_ci{ 11408c2ecf20Sopenharmony_ci cmd->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC); 11418c2ecf20Sopenharmony_ci if (unlikely(cmd->cmnd == NULL)) 11428c2ecf20Sopenharmony_ci return BLK_STS_RESOURCE; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci cmd->cmd_len = SD_EXT_CDB_SIZE; 11458c2ecf20Sopenharmony_ci memset(cmd->cmnd, 0, cmd->cmd_len); 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci cmd->cmnd[0] = VARIABLE_LENGTH_CMD; 11488c2ecf20Sopenharmony_ci cmd->cmnd[7] = 0x18; /* Additional CDB len */ 11498c2ecf20Sopenharmony_ci cmd->cmnd[9] = write ? WRITE_32 : READ_32; 11508c2ecf20Sopenharmony_ci cmd->cmnd[10] = flags; 11518c2ecf20Sopenharmony_ci put_unaligned_be64(lba, &cmd->cmnd[12]); 11528c2ecf20Sopenharmony_ci put_unaligned_be32(lba, &cmd->cmnd[20]); /* Expected Indirect LBA */ 11538c2ecf20Sopenharmony_ci put_unaligned_be32(nr_blocks, &cmd->cmnd[28]); 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci return BLK_STS_OK; 11568c2ecf20Sopenharmony_ci} 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_cistatic blk_status_t sd_setup_rw16_cmnd(struct scsi_cmnd *cmd, bool write, 11598c2ecf20Sopenharmony_ci sector_t lba, unsigned int nr_blocks, 11608c2ecf20Sopenharmony_ci unsigned char flags) 11618c2ecf20Sopenharmony_ci{ 11628c2ecf20Sopenharmony_ci cmd->cmd_len = 16; 11638c2ecf20Sopenharmony_ci cmd->cmnd[0] = write ? WRITE_16 : READ_16; 11648c2ecf20Sopenharmony_ci cmd->cmnd[1] = flags; 11658c2ecf20Sopenharmony_ci cmd->cmnd[14] = 0; 11668c2ecf20Sopenharmony_ci cmd->cmnd[15] = 0; 11678c2ecf20Sopenharmony_ci put_unaligned_be64(lba, &cmd->cmnd[2]); 11688c2ecf20Sopenharmony_ci put_unaligned_be32(nr_blocks, &cmd->cmnd[10]); 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci return BLK_STS_OK; 11718c2ecf20Sopenharmony_ci} 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_cistatic blk_status_t sd_setup_rw10_cmnd(struct scsi_cmnd *cmd, bool write, 11748c2ecf20Sopenharmony_ci sector_t lba, unsigned int nr_blocks, 11758c2ecf20Sopenharmony_ci unsigned char flags) 11768c2ecf20Sopenharmony_ci{ 11778c2ecf20Sopenharmony_ci cmd->cmd_len = 10; 11788c2ecf20Sopenharmony_ci cmd->cmnd[0] = write ? WRITE_10 : READ_10; 11798c2ecf20Sopenharmony_ci cmd->cmnd[1] = flags; 11808c2ecf20Sopenharmony_ci cmd->cmnd[6] = 0; 11818c2ecf20Sopenharmony_ci cmd->cmnd[9] = 0; 11828c2ecf20Sopenharmony_ci put_unaligned_be32(lba, &cmd->cmnd[2]); 11838c2ecf20Sopenharmony_ci put_unaligned_be16(nr_blocks, &cmd->cmnd[7]); 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci return BLK_STS_OK; 11868c2ecf20Sopenharmony_ci} 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_cistatic blk_status_t sd_setup_rw6_cmnd(struct scsi_cmnd *cmd, bool write, 11898c2ecf20Sopenharmony_ci sector_t lba, unsigned int nr_blocks, 11908c2ecf20Sopenharmony_ci unsigned char flags) 11918c2ecf20Sopenharmony_ci{ 11928c2ecf20Sopenharmony_ci /* Avoid that 0 blocks gets translated into 256 blocks. */ 11938c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(nr_blocks == 0)) 11948c2ecf20Sopenharmony_ci return BLK_STS_IOERR; 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci if (unlikely(flags & 0x8)) { 11978c2ecf20Sopenharmony_ci /* 11988c2ecf20Sopenharmony_ci * This happens only if this drive failed 10byte rw 11998c2ecf20Sopenharmony_ci * command with ILLEGAL_REQUEST during operation and 12008c2ecf20Sopenharmony_ci * thus turned off use_10_for_rw. 12018c2ecf20Sopenharmony_ci */ 12028c2ecf20Sopenharmony_ci scmd_printk(KERN_ERR, cmd, "FUA write on READ/WRITE(6) drive\n"); 12038c2ecf20Sopenharmony_ci return BLK_STS_IOERR; 12048c2ecf20Sopenharmony_ci } 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci cmd->cmd_len = 6; 12078c2ecf20Sopenharmony_ci cmd->cmnd[0] = write ? WRITE_6 : READ_6; 12088c2ecf20Sopenharmony_ci cmd->cmnd[1] = (lba >> 16) & 0x1f; 12098c2ecf20Sopenharmony_ci cmd->cmnd[2] = (lba >> 8) & 0xff; 12108c2ecf20Sopenharmony_ci cmd->cmnd[3] = lba & 0xff; 12118c2ecf20Sopenharmony_ci cmd->cmnd[4] = nr_blocks; 12128c2ecf20Sopenharmony_ci cmd->cmnd[5] = 0; 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci return BLK_STS_OK; 12158c2ecf20Sopenharmony_ci} 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_cistatic blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) 12188c2ecf20Sopenharmony_ci{ 12198c2ecf20Sopenharmony_ci struct request *rq = cmd->request; 12208c2ecf20Sopenharmony_ci struct scsi_device *sdp = cmd->device; 12218c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); 12228c2ecf20Sopenharmony_ci sector_t lba = sectors_to_logical(sdp, blk_rq_pos(rq)); 12238c2ecf20Sopenharmony_ci sector_t threshold; 12248c2ecf20Sopenharmony_ci unsigned int nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); 12258c2ecf20Sopenharmony_ci unsigned int mask = logical_to_sectors(sdp, 1) - 1; 12268c2ecf20Sopenharmony_ci bool write = rq_data_dir(rq) == WRITE; 12278c2ecf20Sopenharmony_ci unsigned char protect, fua; 12288c2ecf20Sopenharmony_ci blk_status_t ret; 12298c2ecf20Sopenharmony_ci unsigned int dif; 12308c2ecf20Sopenharmony_ci bool dix; 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci ret = scsi_alloc_sgtables(cmd); 12338c2ecf20Sopenharmony_ci if (ret != BLK_STS_OK) 12348c2ecf20Sopenharmony_ci return ret; 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci ret = BLK_STS_IOERR; 12378c2ecf20Sopenharmony_ci if (!scsi_device_online(sdp) || sdp->changed) { 12388c2ecf20Sopenharmony_ci scmd_printk(KERN_ERR, cmd, "device offline or changed\n"); 12398c2ecf20Sopenharmony_ci goto fail; 12408c2ecf20Sopenharmony_ci } 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci if (blk_rq_pos(rq) + blk_rq_sectors(rq) > get_capacity(rq->rq_disk)) { 12438c2ecf20Sopenharmony_ci scmd_printk(KERN_ERR, cmd, "access beyond end of device\n"); 12448c2ecf20Sopenharmony_ci goto fail; 12458c2ecf20Sopenharmony_ci } 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci if ((blk_rq_pos(rq) & mask) || (blk_rq_sectors(rq) & mask)) { 12488c2ecf20Sopenharmony_ci scmd_printk(KERN_ERR, cmd, "request not aligned to the logical block size\n"); 12498c2ecf20Sopenharmony_ci goto fail; 12508c2ecf20Sopenharmony_ci } 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci /* 12538c2ecf20Sopenharmony_ci * Some SD card readers can't handle accesses which touch the 12548c2ecf20Sopenharmony_ci * last one or two logical blocks. Split accesses as needed. 12558c2ecf20Sopenharmony_ci */ 12568c2ecf20Sopenharmony_ci threshold = sdkp->capacity - SD_LAST_BUGGY_SECTORS; 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci if (unlikely(sdp->last_sector_bug && lba + nr_blocks > threshold)) { 12598c2ecf20Sopenharmony_ci if (lba < threshold) { 12608c2ecf20Sopenharmony_ci /* Access up to the threshold but not beyond */ 12618c2ecf20Sopenharmony_ci nr_blocks = threshold - lba; 12628c2ecf20Sopenharmony_ci } else { 12638c2ecf20Sopenharmony_ci /* Access only a single logical block */ 12648c2ecf20Sopenharmony_ci nr_blocks = 1; 12658c2ecf20Sopenharmony_ci } 12668c2ecf20Sopenharmony_ci } 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci if (req_op(rq) == REQ_OP_ZONE_APPEND) { 12698c2ecf20Sopenharmony_ci ret = sd_zbc_prepare_zone_append(cmd, &lba, nr_blocks); 12708c2ecf20Sopenharmony_ci if (ret) 12718c2ecf20Sopenharmony_ci goto fail; 12728c2ecf20Sopenharmony_ci } 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci fua = rq->cmd_flags & REQ_FUA ? 0x8 : 0; 12758c2ecf20Sopenharmony_ci dix = scsi_prot_sg_count(cmd); 12768c2ecf20Sopenharmony_ci dif = scsi_host_dif_capable(cmd->device->host, sdkp->protection_type); 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci if (dif || dix) 12798c2ecf20Sopenharmony_ci protect = sd_setup_protect_cmnd(cmd, dix, dif); 12808c2ecf20Sopenharmony_ci else 12818c2ecf20Sopenharmony_ci protect = 0; 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci if (protect && sdkp->protection_type == T10_PI_TYPE2_PROTECTION) { 12848c2ecf20Sopenharmony_ci ret = sd_setup_rw32_cmnd(cmd, write, lba, nr_blocks, 12858c2ecf20Sopenharmony_ci protect | fua); 12868c2ecf20Sopenharmony_ci } else if (sdp->use_16_for_rw || (nr_blocks > 0xffff)) { 12878c2ecf20Sopenharmony_ci ret = sd_setup_rw16_cmnd(cmd, write, lba, nr_blocks, 12888c2ecf20Sopenharmony_ci protect | fua); 12898c2ecf20Sopenharmony_ci } else if ((nr_blocks > 0xff) || (lba > 0x1fffff) || 12908c2ecf20Sopenharmony_ci sdp->use_10_for_rw || protect) { 12918c2ecf20Sopenharmony_ci ret = sd_setup_rw10_cmnd(cmd, write, lba, nr_blocks, 12928c2ecf20Sopenharmony_ci protect | fua); 12938c2ecf20Sopenharmony_ci } else { 12948c2ecf20Sopenharmony_ci ret = sd_setup_rw6_cmnd(cmd, write, lba, nr_blocks, 12958c2ecf20Sopenharmony_ci protect | fua); 12968c2ecf20Sopenharmony_ci } 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci if (unlikely(ret != BLK_STS_OK)) 12998c2ecf20Sopenharmony_ci goto fail; 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci /* 13028c2ecf20Sopenharmony_ci * We shouldn't disconnect in the middle of a sector, so with a dumb 13038c2ecf20Sopenharmony_ci * host adapter, it's safe to assume that we can at least transfer 13048c2ecf20Sopenharmony_ci * this many bytes between each connect / disconnect. 13058c2ecf20Sopenharmony_ci */ 13068c2ecf20Sopenharmony_ci cmd->transfersize = sdp->sector_size; 13078c2ecf20Sopenharmony_ci cmd->underflow = nr_blocks << 9; 13088c2ecf20Sopenharmony_ci cmd->allowed = sdkp->max_retries; 13098c2ecf20Sopenharmony_ci cmd->sdb.length = nr_blocks * sdp->sector_size; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci SCSI_LOG_HLQUEUE(1, 13128c2ecf20Sopenharmony_ci scmd_printk(KERN_INFO, cmd, 13138c2ecf20Sopenharmony_ci "%s: block=%llu, count=%d\n", __func__, 13148c2ecf20Sopenharmony_ci (unsigned long long)blk_rq_pos(rq), 13158c2ecf20Sopenharmony_ci blk_rq_sectors(rq))); 13168c2ecf20Sopenharmony_ci SCSI_LOG_HLQUEUE(2, 13178c2ecf20Sopenharmony_ci scmd_printk(KERN_INFO, cmd, 13188c2ecf20Sopenharmony_ci "%s %d/%u 512 byte blocks.\n", 13198c2ecf20Sopenharmony_ci write ? "writing" : "reading", nr_blocks, 13208c2ecf20Sopenharmony_ci blk_rq_sectors(rq))); 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci /* 13238c2ecf20Sopenharmony_ci * This indicates that the command is ready from our end to be queued. 13248c2ecf20Sopenharmony_ci */ 13258c2ecf20Sopenharmony_ci return BLK_STS_OK; 13268c2ecf20Sopenharmony_cifail: 13278c2ecf20Sopenharmony_ci scsi_free_sgtables(cmd); 13288c2ecf20Sopenharmony_ci return ret; 13298c2ecf20Sopenharmony_ci} 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_cistatic blk_status_t sd_init_command(struct scsi_cmnd *cmd) 13328c2ecf20Sopenharmony_ci{ 13338c2ecf20Sopenharmony_ci struct request *rq = cmd->request; 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci switch (req_op(rq)) { 13368c2ecf20Sopenharmony_ci case REQ_OP_DISCARD: 13378c2ecf20Sopenharmony_ci switch (scsi_disk(rq->rq_disk)->provisioning_mode) { 13388c2ecf20Sopenharmony_ci case SD_LBP_UNMAP: 13398c2ecf20Sopenharmony_ci return sd_setup_unmap_cmnd(cmd); 13408c2ecf20Sopenharmony_ci case SD_LBP_WS16: 13418c2ecf20Sopenharmony_ci return sd_setup_write_same16_cmnd(cmd, true); 13428c2ecf20Sopenharmony_ci case SD_LBP_WS10: 13438c2ecf20Sopenharmony_ci return sd_setup_write_same10_cmnd(cmd, true); 13448c2ecf20Sopenharmony_ci case SD_LBP_ZERO: 13458c2ecf20Sopenharmony_ci return sd_setup_write_same10_cmnd(cmd, false); 13468c2ecf20Sopenharmony_ci default: 13478c2ecf20Sopenharmony_ci return BLK_STS_TARGET; 13488c2ecf20Sopenharmony_ci } 13498c2ecf20Sopenharmony_ci case REQ_OP_WRITE_ZEROES: 13508c2ecf20Sopenharmony_ci return sd_setup_write_zeroes_cmnd(cmd); 13518c2ecf20Sopenharmony_ci case REQ_OP_WRITE_SAME: 13528c2ecf20Sopenharmony_ci return sd_setup_write_same_cmnd(cmd); 13538c2ecf20Sopenharmony_ci case REQ_OP_FLUSH: 13548c2ecf20Sopenharmony_ci return sd_setup_flush_cmnd(cmd); 13558c2ecf20Sopenharmony_ci case REQ_OP_READ: 13568c2ecf20Sopenharmony_ci case REQ_OP_WRITE: 13578c2ecf20Sopenharmony_ci case REQ_OP_ZONE_APPEND: 13588c2ecf20Sopenharmony_ci return sd_setup_read_write_cmnd(cmd); 13598c2ecf20Sopenharmony_ci case REQ_OP_ZONE_RESET: 13608c2ecf20Sopenharmony_ci return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_RESET_WRITE_POINTER, 13618c2ecf20Sopenharmony_ci false); 13628c2ecf20Sopenharmony_ci case REQ_OP_ZONE_RESET_ALL: 13638c2ecf20Sopenharmony_ci return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_RESET_WRITE_POINTER, 13648c2ecf20Sopenharmony_ci true); 13658c2ecf20Sopenharmony_ci case REQ_OP_ZONE_OPEN: 13668c2ecf20Sopenharmony_ci return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_OPEN_ZONE, false); 13678c2ecf20Sopenharmony_ci case REQ_OP_ZONE_CLOSE: 13688c2ecf20Sopenharmony_ci return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_CLOSE_ZONE, false); 13698c2ecf20Sopenharmony_ci case REQ_OP_ZONE_FINISH: 13708c2ecf20Sopenharmony_ci return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_FINISH_ZONE, false); 13718c2ecf20Sopenharmony_ci default: 13728c2ecf20Sopenharmony_ci WARN_ON_ONCE(1); 13738c2ecf20Sopenharmony_ci return BLK_STS_NOTSUPP; 13748c2ecf20Sopenharmony_ci } 13758c2ecf20Sopenharmony_ci} 13768c2ecf20Sopenharmony_ci 13778c2ecf20Sopenharmony_cistatic void sd_uninit_command(struct scsi_cmnd *SCpnt) 13788c2ecf20Sopenharmony_ci{ 13798c2ecf20Sopenharmony_ci struct request *rq = SCpnt->request; 13808c2ecf20Sopenharmony_ci u8 *cmnd; 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci if (rq->rq_flags & RQF_SPECIAL_PAYLOAD) 13838c2ecf20Sopenharmony_ci mempool_free(rq->special_vec.bv_page, sd_page_pool); 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci if (SCpnt->cmnd != scsi_req(rq)->cmd) { 13868c2ecf20Sopenharmony_ci cmnd = SCpnt->cmnd; 13878c2ecf20Sopenharmony_ci SCpnt->cmnd = NULL; 13888c2ecf20Sopenharmony_ci SCpnt->cmd_len = 0; 13898c2ecf20Sopenharmony_ci mempool_free(cmnd, sd_cdb_pool); 13908c2ecf20Sopenharmony_ci } 13918c2ecf20Sopenharmony_ci} 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_cistatic bool sd_need_revalidate(struct block_device *bdev, 13948c2ecf20Sopenharmony_ci struct scsi_disk *sdkp) 13958c2ecf20Sopenharmony_ci{ 13968c2ecf20Sopenharmony_ci if (sdkp->device->removable || sdkp->write_prot) { 13978c2ecf20Sopenharmony_ci if (bdev_check_media_change(bdev)) 13988c2ecf20Sopenharmony_ci return true; 13998c2ecf20Sopenharmony_ci } 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci /* 14028c2ecf20Sopenharmony_ci * Force a full rescan after ioctl(BLKRRPART). While the disk state has 14038c2ecf20Sopenharmony_ci * nothing to do with partitions, BLKRRPART is used to force a full 14048c2ecf20Sopenharmony_ci * revalidate after things like a format for historical reasons. 14058c2ecf20Sopenharmony_ci */ 14068c2ecf20Sopenharmony_ci return test_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); 14078c2ecf20Sopenharmony_ci} 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci/** 14108c2ecf20Sopenharmony_ci * sd_open - open a scsi disk device 14118c2ecf20Sopenharmony_ci * @bdev: Block device of the scsi disk to open 14128c2ecf20Sopenharmony_ci * @mode: FMODE_* mask 14138c2ecf20Sopenharmony_ci * 14148c2ecf20Sopenharmony_ci * Returns 0 if successful. Returns a negated errno value in case 14158c2ecf20Sopenharmony_ci * of error. 14168c2ecf20Sopenharmony_ci * 14178c2ecf20Sopenharmony_ci * Note: This can be called from a user context (e.g. fsck(1) ) 14188c2ecf20Sopenharmony_ci * or from within the kernel (e.g. as a result of a mount(1) ). 14198c2ecf20Sopenharmony_ci * In the latter case @inode and @filp carry an abridged amount 14208c2ecf20Sopenharmony_ci * of information as noted above. 14218c2ecf20Sopenharmony_ci * 14228c2ecf20Sopenharmony_ci * Locking: called with bdev->bd_mutex held. 14238c2ecf20Sopenharmony_ci **/ 14248c2ecf20Sopenharmony_cistatic int sd_open(struct block_device *bdev, fmode_t mode) 14258c2ecf20Sopenharmony_ci{ 14268c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk_get(bdev->bd_disk); 14278c2ecf20Sopenharmony_ci struct scsi_device *sdev; 14288c2ecf20Sopenharmony_ci int retval; 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci if (!sdkp) 14318c2ecf20Sopenharmony_ci return -ENXIO; 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_ci SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_open\n")); 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_ci sdev = sdkp->device; 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci /* 14388c2ecf20Sopenharmony_ci * If the device is in error recovery, wait until it is done. 14398c2ecf20Sopenharmony_ci * If the device is offline, then disallow any access to it. 14408c2ecf20Sopenharmony_ci */ 14418c2ecf20Sopenharmony_ci retval = -ENXIO; 14428c2ecf20Sopenharmony_ci if (!scsi_block_when_processing_errors(sdev)) 14438c2ecf20Sopenharmony_ci goto error_out; 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci if (sd_need_revalidate(bdev, sdkp)) 14468c2ecf20Sopenharmony_ci sd_revalidate_disk(bdev->bd_disk); 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci /* 14498c2ecf20Sopenharmony_ci * If the drive is empty, just let the open fail. 14508c2ecf20Sopenharmony_ci */ 14518c2ecf20Sopenharmony_ci retval = -ENOMEDIUM; 14528c2ecf20Sopenharmony_ci if (sdev->removable && !sdkp->media_present && !(mode & FMODE_NDELAY)) 14538c2ecf20Sopenharmony_ci goto error_out; 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci /* 14568c2ecf20Sopenharmony_ci * If the device has the write protect tab set, have the open fail 14578c2ecf20Sopenharmony_ci * if the user expects to be able to write to the thing. 14588c2ecf20Sopenharmony_ci */ 14598c2ecf20Sopenharmony_ci retval = -EROFS; 14608c2ecf20Sopenharmony_ci if (sdkp->write_prot && (mode & FMODE_WRITE)) 14618c2ecf20Sopenharmony_ci goto error_out; 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci /* 14648c2ecf20Sopenharmony_ci * It is possible that the disk changing stuff resulted in 14658c2ecf20Sopenharmony_ci * the device being taken offline. If this is the case, 14668c2ecf20Sopenharmony_ci * report this to the user, and don't pretend that the 14678c2ecf20Sopenharmony_ci * open actually succeeded. 14688c2ecf20Sopenharmony_ci */ 14698c2ecf20Sopenharmony_ci retval = -ENXIO; 14708c2ecf20Sopenharmony_ci if (!scsi_device_online(sdev)) 14718c2ecf20Sopenharmony_ci goto error_out; 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci if ((atomic_inc_return(&sdkp->openers) == 1) && sdev->removable) { 14748c2ecf20Sopenharmony_ci if (scsi_block_when_processing_errors(sdev)) 14758c2ecf20Sopenharmony_ci scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); 14768c2ecf20Sopenharmony_ci } 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_ci return 0; 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_cierror_out: 14818c2ecf20Sopenharmony_ci scsi_disk_put(sdkp); 14828c2ecf20Sopenharmony_ci return retval; 14838c2ecf20Sopenharmony_ci} 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_ci/** 14868c2ecf20Sopenharmony_ci * sd_release - invoked when the (last) close(2) is called on this 14878c2ecf20Sopenharmony_ci * scsi disk. 14888c2ecf20Sopenharmony_ci * @disk: disk to release 14898c2ecf20Sopenharmony_ci * @mode: FMODE_* mask 14908c2ecf20Sopenharmony_ci * 14918c2ecf20Sopenharmony_ci * Returns 0. 14928c2ecf20Sopenharmony_ci * 14938c2ecf20Sopenharmony_ci * Note: may block (uninterruptible) if error recovery is underway 14948c2ecf20Sopenharmony_ci * on this disk. 14958c2ecf20Sopenharmony_ci * 14968c2ecf20Sopenharmony_ci * Locking: called with bdev->bd_mutex held. 14978c2ecf20Sopenharmony_ci **/ 14988c2ecf20Sopenharmony_cistatic void sd_release(struct gendisk *disk, fmode_t mode) 14998c2ecf20Sopenharmony_ci{ 15008c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(disk); 15018c2ecf20Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n")); 15048c2ecf20Sopenharmony_ci 15058c2ecf20Sopenharmony_ci if (atomic_dec_return(&sdkp->openers) == 0 && sdev->removable) { 15068c2ecf20Sopenharmony_ci if (scsi_block_when_processing_errors(sdev)) 15078c2ecf20Sopenharmony_ci scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); 15088c2ecf20Sopenharmony_ci } 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci scsi_disk_put(sdkp); 15118c2ecf20Sopenharmony_ci} 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_cistatic int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) 15148c2ecf20Sopenharmony_ci{ 15158c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); 15168c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 15178c2ecf20Sopenharmony_ci struct Scsi_Host *host = sdp->host; 15188c2ecf20Sopenharmony_ci sector_t capacity = logical_to_sectors(sdp, sdkp->capacity); 15198c2ecf20Sopenharmony_ci int diskinfo[4]; 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_ci /* default to most commonly used values */ 15228c2ecf20Sopenharmony_ci diskinfo[0] = 0x40; /* 1 << 6 */ 15238c2ecf20Sopenharmony_ci diskinfo[1] = 0x20; /* 1 << 5 */ 15248c2ecf20Sopenharmony_ci diskinfo[2] = capacity >> 11; 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci /* override with calculated, extended default, or driver values */ 15278c2ecf20Sopenharmony_ci if (host->hostt->bios_param) 15288c2ecf20Sopenharmony_ci host->hostt->bios_param(sdp, bdev, capacity, diskinfo); 15298c2ecf20Sopenharmony_ci else 15308c2ecf20Sopenharmony_ci scsicam_bios_param(bdev, capacity, diskinfo); 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_ci geo->heads = diskinfo[0]; 15338c2ecf20Sopenharmony_ci geo->sectors = diskinfo[1]; 15348c2ecf20Sopenharmony_ci geo->cylinders = diskinfo[2]; 15358c2ecf20Sopenharmony_ci return 0; 15368c2ecf20Sopenharmony_ci} 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_ci/** 15398c2ecf20Sopenharmony_ci * sd_ioctl - process an ioctl 15408c2ecf20Sopenharmony_ci * @bdev: target block device 15418c2ecf20Sopenharmony_ci * @mode: FMODE_* mask 15428c2ecf20Sopenharmony_ci * @cmd: ioctl command number 15438c2ecf20Sopenharmony_ci * @p: this is third argument given to ioctl(2) system call. 15448c2ecf20Sopenharmony_ci * Often contains a pointer. 15458c2ecf20Sopenharmony_ci * 15468c2ecf20Sopenharmony_ci * Returns 0 if successful (some ioctls return positive numbers on 15478c2ecf20Sopenharmony_ci * success as well). Returns a negated errno value in case of error. 15488c2ecf20Sopenharmony_ci * 15498c2ecf20Sopenharmony_ci * Note: most ioctls are forward onto the block subsystem or further 15508c2ecf20Sopenharmony_ci * down in the scsi subsystem. 15518c2ecf20Sopenharmony_ci **/ 15528c2ecf20Sopenharmony_cistatic int sd_ioctl_common(struct block_device *bdev, fmode_t mode, 15538c2ecf20Sopenharmony_ci unsigned int cmd, void __user *p) 15548c2ecf20Sopenharmony_ci{ 15558c2ecf20Sopenharmony_ci struct gendisk *disk = bdev->bd_disk; 15568c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(disk); 15578c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 15588c2ecf20Sopenharmony_ci int error; 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, " 15618c2ecf20Sopenharmony_ci "cmd=0x%x\n", disk->disk_name, cmd)); 15628c2ecf20Sopenharmony_ci 15638c2ecf20Sopenharmony_ci error = scsi_verify_blk_ioctl(bdev, cmd); 15648c2ecf20Sopenharmony_ci if (error < 0) 15658c2ecf20Sopenharmony_ci return error; 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci /* 15688c2ecf20Sopenharmony_ci * If we are in the middle of error recovery, don't let anyone 15698c2ecf20Sopenharmony_ci * else try and use this device. Also, if error recovery fails, it 15708c2ecf20Sopenharmony_ci * may try and take the device offline, in which case all further 15718c2ecf20Sopenharmony_ci * access to the device is prohibited. 15728c2ecf20Sopenharmony_ci */ 15738c2ecf20Sopenharmony_ci error = scsi_ioctl_block_when_processing_errors(sdp, cmd, 15748c2ecf20Sopenharmony_ci (mode & FMODE_NDELAY) != 0); 15758c2ecf20Sopenharmony_ci if (error) 15768c2ecf20Sopenharmony_ci goto out; 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci if (is_sed_ioctl(cmd)) 15798c2ecf20Sopenharmony_ci return sed_ioctl(sdkp->opal_dev, cmd, p); 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ci /* 15828c2ecf20Sopenharmony_ci * Send SCSI addressing ioctls directly to mid level, send other 15838c2ecf20Sopenharmony_ci * ioctls to block level and then onto mid level if they can't be 15848c2ecf20Sopenharmony_ci * resolved. 15858c2ecf20Sopenharmony_ci */ 15868c2ecf20Sopenharmony_ci switch (cmd) { 15878c2ecf20Sopenharmony_ci case SCSI_IOCTL_GET_IDLUN: 15888c2ecf20Sopenharmony_ci case SCSI_IOCTL_GET_BUS_NUMBER: 15898c2ecf20Sopenharmony_ci error = scsi_ioctl(sdp, cmd, p); 15908c2ecf20Sopenharmony_ci break; 15918c2ecf20Sopenharmony_ci default: 15928c2ecf20Sopenharmony_ci error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p); 15938c2ecf20Sopenharmony_ci break; 15948c2ecf20Sopenharmony_ci } 15958c2ecf20Sopenharmony_ciout: 15968c2ecf20Sopenharmony_ci return error; 15978c2ecf20Sopenharmony_ci} 15988c2ecf20Sopenharmony_ci 15998c2ecf20Sopenharmony_cistatic void set_media_not_present(struct scsi_disk *sdkp) 16008c2ecf20Sopenharmony_ci{ 16018c2ecf20Sopenharmony_ci if (sdkp->media_present) 16028c2ecf20Sopenharmony_ci sdkp->device->changed = 1; 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci if (sdkp->device->removable) { 16058c2ecf20Sopenharmony_ci sdkp->media_present = 0; 16068c2ecf20Sopenharmony_ci sdkp->capacity = 0; 16078c2ecf20Sopenharmony_ci } 16088c2ecf20Sopenharmony_ci} 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_cistatic int media_not_present(struct scsi_disk *sdkp, 16118c2ecf20Sopenharmony_ci struct scsi_sense_hdr *sshdr) 16128c2ecf20Sopenharmony_ci{ 16138c2ecf20Sopenharmony_ci if (!scsi_sense_valid(sshdr)) 16148c2ecf20Sopenharmony_ci return 0; 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci /* not invoked for commands that could return deferred errors */ 16178c2ecf20Sopenharmony_ci switch (sshdr->sense_key) { 16188c2ecf20Sopenharmony_ci case UNIT_ATTENTION: 16198c2ecf20Sopenharmony_ci case NOT_READY: 16208c2ecf20Sopenharmony_ci /* medium not present */ 16218c2ecf20Sopenharmony_ci if (sshdr->asc == 0x3A) { 16228c2ecf20Sopenharmony_ci set_media_not_present(sdkp); 16238c2ecf20Sopenharmony_ci return 1; 16248c2ecf20Sopenharmony_ci } 16258c2ecf20Sopenharmony_ci } 16268c2ecf20Sopenharmony_ci return 0; 16278c2ecf20Sopenharmony_ci} 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_ci/** 16308c2ecf20Sopenharmony_ci * sd_check_events - check media events 16318c2ecf20Sopenharmony_ci * @disk: kernel device descriptor 16328c2ecf20Sopenharmony_ci * @clearing: disk events currently being cleared 16338c2ecf20Sopenharmony_ci * 16348c2ecf20Sopenharmony_ci * Returns mask of DISK_EVENT_*. 16358c2ecf20Sopenharmony_ci * 16368c2ecf20Sopenharmony_ci * Note: this function is invoked from the block subsystem. 16378c2ecf20Sopenharmony_ci **/ 16388c2ecf20Sopenharmony_cistatic unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing) 16398c2ecf20Sopenharmony_ci{ 16408c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk_get(disk); 16418c2ecf20Sopenharmony_ci struct scsi_device *sdp; 16428c2ecf20Sopenharmony_ci int retval; 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci if (!sdkp) 16458c2ecf20Sopenharmony_ci return 0; 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ci sdp = sdkp->device; 16488c2ecf20Sopenharmony_ci SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_check_events\n")); 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci /* 16518c2ecf20Sopenharmony_ci * If the device is offline, don't send any commands - just pretend as 16528c2ecf20Sopenharmony_ci * if the command failed. If the device ever comes back online, we 16538c2ecf20Sopenharmony_ci * can deal with it then. It is only because of unrecoverable errors 16548c2ecf20Sopenharmony_ci * that we would ever take a device offline in the first place. 16558c2ecf20Sopenharmony_ci */ 16568c2ecf20Sopenharmony_ci if (!scsi_device_online(sdp)) { 16578c2ecf20Sopenharmony_ci set_media_not_present(sdkp); 16588c2ecf20Sopenharmony_ci goto out; 16598c2ecf20Sopenharmony_ci } 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci /* 16628c2ecf20Sopenharmony_ci * Using TEST_UNIT_READY enables differentiation between drive with 16638c2ecf20Sopenharmony_ci * no cartridge loaded - NOT READY, drive with changed cartridge - 16648c2ecf20Sopenharmony_ci * UNIT ATTENTION, or with same cartridge - GOOD STATUS. 16658c2ecf20Sopenharmony_ci * 16668c2ecf20Sopenharmony_ci * Drives that auto spin down. eg iomega jaz 1G, will be started 16678c2ecf20Sopenharmony_ci * by sd_spinup_disk() from sd_revalidate_disk(), which happens whenever 16688c2ecf20Sopenharmony_ci * sd_revalidate() is called. 16698c2ecf20Sopenharmony_ci */ 16708c2ecf20Sopenharmony_ci if (scsi_block_when_processing_errors(sdp)) { 16718c2ecf20Sopenharmony_ci struct scsi_sense_hdr sshdr = { 0, }; 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_ci retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, sdkp->max_retries, 16748c2ecf20Sopenharmony_ci &sshdr); 16758c2ecf20Sopenharmony_ci 16768c2ecf20Sopenharmony_ci /* failed to execute TUR, assume media not present */ 16778c2ecf20Sopenharmony_ci if (host_byte(retval)) { 16788c2ecf20Sopenharmony_ci set_media_not_present(sdkp); 16798c2ecf20Sopenharmony_ci goto out; 16808c2ecf20Sopenharmony_ci } 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci if (media_not_present(sdkp, &sshdr)) 16838c2ecf20Sopenharmony_ci goto out; 16848c2ecf20Sopenharmony_ci } 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci /* 16878c2ecf20Sopenharmony_ci * For removable scsi disk we have to recognise the presence 16888c2ecf20Sopenharmony_ci * of a disk in the drive. 16898c2ecf20Sopenharmony_ci */ 16908c2ecf20Sopenharmony_ci if (!sdkp->media_present) 16918c2ecf20Sopenharmony_ci sdp->changed = 1; 16928c2ecf20Sopenharmony_ci sdkp->media_present = 1; 16938c2ecf20Sopenharmony_ciout: 16948c2ecf20Sopenharmony_ci /* 16958c2ecf20Sopenharmony_ci * sdp->changed is set under the following conditions: 16968c2ecf20Sopenharmony_ci * 16978c2ecf20Sopenharmony_ci * Medium present state has changed in either direction. 16988c2ecf20Sopenharmony_ci * Device has indicated UNIT_ATTENTION. 16998c2ecf20Sopenharmony_ci */ 17008c2ecf20Sopenharmony_ci retval = sdp->changed ? DISK_EVENT_MEDIA_CHANGE : 0; 17018c2ecf20Sopenharmony_ci sdp->changed = 0; 17028c2ecf20Sopenharmony_ci scsi_disk_put(sdkp); 17038c2ecf20Sopenharmony_ci return retval; 17048c2ecf20Sopenharmony_ci} 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_cistatic int sd_sync_cache(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr) 17078c2ecf20Sopenharmony_ci{ 17088c2ecf20Sopenharmony_ci int retries, res; 17098c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 17108c2ecf20Sopenharmony_ci const int timeout = sdp->request_queue->rq_timeout 17118c2ecf20Sopenharmony_ci * SD_FLUSH_TIMEOUT_MULTIPLIER; 17128c2ecf20Sopenharmony_ci struct scsi_sense_hdr my_sshdr; 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci if (!scsi_device_online(sdp)) 17158c2ecf20Sopenharmony_ci return -ENODEV; 17168c2ecf20Sopenharmony_ci 17178c2ecf20Sopenharmony_ci /* caller might not be interested in sense, but we need it */ 17188c2ecf20Sopenharmony_ci if (!sshdr) 17198c2ecf20Sopenharmony_ci sshdr = &my_sshdr; 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_ci for (retries = 3; retries > 0; --retries) { 17228c2ecf20Sopenharmony_ci unsigned char cmd[10] = { 0 }; 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ci cmd[0] = SYNCHRONIZE_CACHE; 17258c2ecf20Sopenharmony_ci /* 17268c2ecf20Sopenharmony_ci * Leave the rest of the command zero to indicate 17278c2ecf20Sopenharmony_ci * flush everything. 17288c2ecf20Sopenharmony_ci */ 17298c2ecf20Sopenharmony_ci res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, sshdr, 17308c2ecf20Sopenharmony_ci timeout, sdkp->max_retries, 0, RQF_PM, NULL); 17318c2ecf20Sopenharmony_ci if (res == 0) 17328c2ecf20Sopenharmony_ci break; 17338c2ecf20Sopenharmony_ci } 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci if (res) { 17368c2ecf20Sopenharmony_ci sd_print_result(sdkp, "Synchronize Cache(10) failed", res); 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_ci if (driver_byte(res) == DRIVER_SENSE) 17398c2ecf20Sopenharmony_ci sd_print_sense_hdr(sdkp, sshdr); 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci /* we need to evaluate the error return */ 17428c2ecf20Sopenharmony_ci if (scsi_sense_valid(sshdr) && 17438c2ecf20Sopenharmony_ci (sshdr->asc == 0x3a || /* medium not present */ 17448c2ecf20Sopenharmony_ci sshdr->asc == 0x20 || /* invalid command */ 17458c2ecf20Sopenharmony_ci (sshdr->asc == 0x74 && sshdr->ascq == 0x71))) /* drive is password locked */ 17468c2ecf20Sopenharmony_ci /* this is no error here */ 17478c2ecf20Sopenharmony_ci return 0; 17488c2ecf20Sopenharmony_ci 17498c2ecf20Sopenharmony_ci switch (host_byte(res)) { 17508c2ecf20Sopenharmony_ci /* ignore errors due to racing a disconnection */ 17518c2ecf20Sopenharmony_ci case DID_BAD_TARGET: 17528c2ecf20Sopenharmony_ci case DID_NO_CONNECT: 17538c2ecf20Sopenharmony_ci return 0; 17548c2ecf20Sopenharmony_ci /* signal the upper layer it might try again */ 17558c2ecf20Sopenharmony_ci case DID_BUS_BUSY: 17568c2ecf20Sopenharmony_ci case DID_IMM_RETRY: 17578c2ecf20Sopenharmony_ci case DID_REQUEUE: 17588c2ecf20Sopenharmony_ci case DID_SOFT_ERROR: 17598c2ecf20Sopenharmony_ci return -EBUSY; 17608c2ecf20Sopenharmony_ci default: 17618c2ecf20Sopenharmony_ci return -EIO; 17628c2ecf20Sopenharmony_ci } 17638c2ecf20Sopenharmony_ci } 17648c2ecf20Sopenharmony_ci return 0; 17658c2ecf20Sopenharmony_ci} 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_cistatic void sd_rescan(struct device *dev) 17688c2ecf20Sopenharmony_ci{ 17698c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = dev_get_drvdata(dev); 17708c2ecf20Sopenharmony_ci int ret; 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_ci ret = sd_revalidate_disk(sdkp->disk); 17738c2ecf20Sopenharmony_ci revalidate_disk_size(sdkp->disk, ret == 0); 17748c2ecf20Sopenharmony_ci} 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_cistatic int sd_ioctl(struct block_device *bdev, fmode_t mode, 17778c2ecf20Sopenharmony_ci unsigned int cmd, unsigned long arg) 17788c2ecf20Sopenharmony_ci{ 17798c2ecf20Sopenharmony_ci void __user *p = (void __user *)arg; 17808c2ecf20Sopenharmony_ci int ret; 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci ret = sd_ioctl_common(bdev, mode, cmd, p); 17838c2ecf20Sopenharmony_ci if (ret != -ENOTTY) 17848c2ecf20Sopenharmony_ci return ret; 17858c2ecf20Sopenharmony_ci 17868c2ecf20Sopenharmony_ci return scsi_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p); 17878c2ecf20Sopenharmony_ci} 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT 17908c2ecf20Sopenharmony_cistatic int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, 17918c2ecf20Sopenharmony_ci unsigned int cmd, unsigned long arg) 17928c2ecf20Sopenharmony_ci{ 17938c2ecf20Sopenharmony_ci void __user *p = compat_ptr(arg); 17948c2ecf20Sopenharmony_ci int ret; 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_ci ret = sd_ioctl_common(bdev, mode, cmd, p); 17978c2ecf20Sopenharmony_ci if (ret != -ENOTTY) 17988c2ecf20Sopenharmony_ci return ret; 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci return scsi_compat_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p); 18018c2ecf20Sopenharmony_ci} 18028c2ecf20Sopenharmony_ci#endif 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_cistatic char sd_pr_type(enum pr_type type) 18058c2ecf20Sopenharmony_ci{ 18068c2ecf20Sopenharmony_ci switch (type) { 18078c2ecf20Sopenharmony_ci case PR_WRITE_EXCLUSIVE: 18088c2ecf20Sopenharmony_ci return 0x01; 18098c2ecf20Sopenharmony_ci case PR_EXCLUSIVE_ACCESS: 18108c2ecf20Sopenharmony_ci return 0x03; 18118c2ecf20Sopenharmony_ci case PR_WRITE_EXCLUSIVE_REG_ONLY: 18128c2ecf20Sopenharmony_ci return 0x05; 18138c2ecf20Sopenharmony_ci case PR_EXCLUSIVE_ACCESS_REG_ONLY: 18148c2ecf20Sopenharmony_ci return 0x06; 18158c2ecf20Sopenharmony_ci case PR_WRITE_EXCLUSIVE_ALL_REGS: 18168c2ecf20Sopenharmony_ci return 0x07; 18178c2ecf20Sopenharmony_ci case PR_EXCLUSIVE_ACCESS_ALL_REGS: 18188c2ecf20Sopenharmony_ci return 0x08; 18198c2ecf20Sopenharmony_ci default: 18208c2ecf20Sopenharmony_ci return 0; 18218c2ecf20Sopenharmony_ci } 18228c2ecf20Sopenharmony_ci}; 18238c2ecf20Sopenharmony_ci 18248c2ecf20Sopenharmony_cistatic int sd_pr_command(struct block_device *bdev, u8 sa, 18258c2ecf20Sopenharmony_ci u64 key, u64 sa_key, u8 type, u8 flags) 18268c2ecf20Sopenharmony_ci{ 18278c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); 18288c2ecf20Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 18298c2ecf20Sopenharmony_ci struct scsi_sense_hdr sshdr; 18308c2ecf20Sopenharmony_ci int result; 18318c2ecf20Sopenharmony_ci u8 cmd[16] = { 0, }; 18328c2ecf20Sopenharmony_ci u8 data[24] = { 0, }; 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_ci cmd[0] = PERSISTENT_RESERVE_OUT; 18358c2ecf20Sopenharmony_ci cmd[1] = sa; 18368c2ecf20Sopenharmony_ci cmd[2] = type; 18378c2ecf20Sopenharmony_ci put_unaligned_be32(sizeof(data), &cmd[5]); 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ci put_unaligned_be64(key, &data[0]); 18408c2ecf20Sopenharmony_ci put_unaligned_be64(sa_key, &data[8]); 18418c2ecf20Sopenharmony_ci data[20] = flags; 18428c2ecf20Sopenharmony_ci 18438c2ecf20Sopenharmony_ci result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, &data, sizeof(data), 18448c2ecf20Sopenharmony_ci &sshdr, SD_TIMEOUT, sdkp->max_retries, NULL); 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci if (driver_byte(result) == DRIVER_SENSE && 18478c2ecf20Sopenharmony_ci scsi_sense_valid(&sshdr)) { 18488c2ecf20Sopenharmony_ci sdev_printk(KERN_INFO, sdev, "PR command failed: %d\n", result); 18498c2ecf20Sopenharmony_ci scsi_print_sense_hdr(sdev, NULL, &sshdr); 18508c2ecf20Sopenharmony_ci } 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci return result; 18538c2ecf20Sopenharmony_ci} 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_cistatic int sd_pr_register(struct block_device *bdev, u64 old_key, u64 new_key, 18568c2ecf20Sopenharmony_ci u32 flags) 18578c2ecf20Sopenharmony_ci{ 18588c2ecf20Sopenharmony_ci if (flags & ~PR_FL_IGNORE_KEY) 18598c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 18608c2ecf20Sopenharmony_ci return sd_pr_command(bdev, (flags & PR_FL_IGNORE_KEY) ? 0x06 : 0x00, 18618c2ecf20Sopenharmony_ci old_key, new_key, 0, 18628c2ecf20Sopenharmony_ci (1 << 0) /* APTPL */); 18638c2ecf20Sopenharmony_ci} 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_cistatic int sd_pr_reserve(struct block_device *bdev, u64 key, enum pr_type type, 18668c2ecf20Sopenharmony_ci u32 flags) 18678c2ecf20Sopenharmony_ci{ 18688c2ecf20Sopenharmony_ci if (flags) 18698c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 18708c2ecf20Sopenharmony_ci return sd_pr_command(bdev, 0x01, key, 0, sd_pr_type(type), 0); 18718c2ecf20Sopenharmony_ci} 18728c2ecf20Sopenharmony_ci 18738c2ecf20Sopenharmony_cistatic int sd_pr_release(struct block_device *bdev, u64 key, enum pr_type type) 18748c2ecf20Sopenharmony_ci{ 18758c2ecf20Sopenharmony_ci return sd_pr_command(bdev, 0x02, key, 0, sd_pr_type(type), 0); 18768c2ecf20Sopenharmony_ci} 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_cistatic int sd_pr_preempt(struct block_device *bdev, u64 old_key, u64 new_key, 18798c2ecf20Sopenharmony_ci enum pr_type type, bool abort) 18808c2ecf20Sopenharmony_ci{ 18818c2ecf20Sopenharmony_ci return sd_pr_command(bdev, abort ? 0x05 : 0x04, old_key, new_key, 18828c2ecf20Sopenharmony_ci sd_pr_type(type), 0); 18838c2ecf20Sopenharmony_ci} 18848c2ecf20Sopenharmony_ci 18858c2ecf20Sopenharmony_cistatic int sd_pr_clear(struct block_device *bdev, u64 key) 18868c2ecf20Sopenharmony_ci{ 18878c2ecf20Sopenharmony_ci return sd_pr_command(bdev, 0x03, key, 0, 0, 0); 18888c2ecf20Sopenharmony_ci} 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_cistatic const struct pr_ops sd_pr_ops = { 18918c2ecf20Sopenharmony_ci .pr_register = sd_pr_register, 18928c2ecf20Sopenharmony_ci .pr_reserve = sd_pr_reserve, 18938c2ecf20Sopenharmony_ci .pr_release = sd_pr_release, 18948c2ecf20Sopenharmony_ci .pr_preempt = sd_pr_preempt, 18958c2ecf20Sopenharmony_ci .pr_clear = sd_pr_clear, 18968c2ecf20Sopenharmony_ci}; 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_cistatic const struct block_device_operations sd_fops = { 18998c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 19008c2ecf20Sopenharmony_ci .open = sd_open, 19018c2ecf20Sopenharmony_ci .release = sd_release, 19028c2ecf20Sopenharmony_ci .ioctl = sd_ioctl, 19038c2ecf20Sopenharmony_ci .getgeo = sd_getgeo, 19048c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT 19058c2ecf20Sopenharmony_ci .compat_ioctl = sd_compat_ioctl, 19068c2ecf20Sopenharmony_ci#endif 19078c2ecf20Sopenharmony_ci .check_events = sd_check_events, 19088c2ecf20Sopenharmony_ci .unlock_native_capacity = sd_unlock_native_capacity, 19098c2ecf20Sopenharmony_ci .report_zones = sd_zbc_report_zones, 19108c2ecf20Sopenharmony_ci .pr_ops = &sd_pr_ops, 19118c2ecf20Sopenharmony_ci}; 19128c2ecf20Sopenharmony_ci 19138c2ecf20Sopenharmony_ci/** 19148c2ecf20Sopenharmony_ci * sd_eh_reset - reset error handling callback 19158c2ecf20Sopenharmony_ci * @scmd: sd-issued command that has failed 19168c2ecf20Sopenharmony_ci * 19178c2ecf20Sopenharmony_ci * This function is called by the SCSI midlayer before starting 19188c2ecf20Sopenharmony_ci * SCSI EH. When counting medium access failures we have to be 19198c2ecf20Sopenharmony_ci * careful to register it only only once per device and SCSI EH run; 19208c2ecf20Sopenharmony_ci * there might be several timed out commands which will cause the 19218c2ecf20Sopenharmony_ci * 'max_medium_access_timeouts' counter to trigger after the first 19228c2ecf20Sopenharmony_ci * SCSI EH run already and set the device to offline. 19238c2ecf20Sopenharmony_ci * So this function resets the internal counter before starting SCSI EH. 19248c2ecf20Sopenharmony_ci **/ 19258c2ecf20Sopenharmony_cistatic void sd_eh_reset(struct scsi_cmnd *scmd) 19268c2ecf20Sopenharmony_ci{ 19278c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(scmd->request->rq_disk); 19288c2ecf20Sopenharmony_ci 19298c2ecf20Sopenharmony_ci /* New SCSI EH run, reset gate variable */ 19308c2ecf20Sopenharmony_ci sdkp->ignore_medium_access_errors = false; 19318c2ecf20Sopenharmony_ci} 19328c2ecf20Sopenharmony_ci 19338c2ecf20Sopenharmony_ci/** 19348c2ecf20Sopenharmony_ci * sd_eh_action - error handling callback 19358c2ecf20Sopenharmony_ci * @scmd: sd-issued command that has failed 19368c2ecf20Sopenharmony_ci * @eh_disp: The recovery disposition suggested by the midlayer 19378c2ecf20Sopenharmony_ci * 19388c2ecf20Sopenharmony_ci * This function is called by the SCSI midlayer upon completion of an 19398c2ecf20Sopenharmony_ci * error test command (currently TEST UNIT READY). The result of sending 19408c2ecf20Sopenharmony_ci * the eh command is passed in eh_disp. We're looking for devices that 19418c2ecf20Sopenharmony_ci * fail medium access commands but are OK with non access commands like 19428c2ecf20Sopenharmony_ci * test unit ready (so wrongly see the device as having a successful 19438c2ecf20Sopenharmony_ci * recovery) 19448c2ecf20Sopenharmony_ci **/ 19458c2ecf20Sopenharmony_cistatic int sd_eh_action(struct scsi_cmnd *scmd, int eh_disp) 19468c2ecf20Sopenharmony_ci{ 19478c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(scmd->request->rq_disk); 19488c2ecf20Sopenharmony_ci struct scsi_device *sdev = scmd->device; 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_ci if (!scsi_device_online(sdev) || 19518c2ecf20Sopenharmony_ci !scsi_medium_access_command(scmd) || 19528c2ecf20Sopenharmony_ci host_byte(scmd->result) != DID_TIME_OUT || 19538c2ecf20Sopenharmony_ci eh_disp != SUCCESS) 19548c2ecf20Sopenharmony_ci return eh_disp; 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_ci /* 19578c2ecf20Sopenharmony_ci * The device has timed out executing a medium access command. 19588c2ecf20Sopenharmony_ci * However, the TEST UNIT READY command sent during error 19598c2ecf20Sopenharmony_ci * handling completed successfully. Either the device is in the 19608c2ecf20Sopenharmony_ci * process of recovering or has it suffered an internal failure 19618c2ecf20Sopenharmony_ci * that prevents access to the storage medium. 19628c2ecf20Sopenharmony_ci */ 19638c2ecf20Sopenharmony_ci if (!sdkp->ignore_medium_access_errors) { 19648c2ecf20Sopenharmony_ci sdkp->medium_access_timed_out++; 19658c2ecf20Sopenharmony_ci sdkp->ignore_medium_access_errors = true; 19668c2ecf20Sopenharmony_ci } 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_ci /* 19698c2ecf20Sopenharmony_ci * If the device keeps failing read/write commands but TEST UNIT 19708c2ecf20Sopenharmony_ci * READY always completes successfully we assume that medium 19718c2ecf20Sopenharmony_ci * access is no longer possible and take the device offline. 19728c2ecf20Sopenharmony_ci */ 19738c2ecf20Sopenharmony_ci if (sdkp->medium_access_timed_out >= sdkp->max_medium_access_timeouts) { 19748c2ecf20Sopenharmony_ci scmd_printk(KERN_ERR, scmd, 19758c2ecf20Sopenharmony_ci "Medium access timeout failure. Offlining disk!\n"); 19768c2ecf20Sopenharmony_ci mutex_lock(&sdev->state_mutex); 19778c2ecf20Sopenharmony_ci scsi_device_set_state(sdev, SDEV_OFFLINE); 19788c2ecf20Sopenharmony_ci mutex_unlock(&sdev->state_mutex); 19798c2ecf20Sopenharmony_ci 19808c2ecf20Sopenharmony_ci return SUCCESS; 19818c2ecf20Sopenharmony_ci } 19828c2ecf20Sopenharmony_ci 19838c2ecf20Sopenharmony_ci return eh_disp; 19848c2ecf20Sopenharmony_ci} 19858c2ecf20Sopenharmony_ci 19868c2ecf20Sopenharmony_cistatic unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) 19878c2ecf20Sopenharmony_ci{ 19888c2ecf20Sopenharmony_ci struct request *req = scmd->request; 19898c2ecf20Sopenharmony_ci struct scsi_device *sdev = scmd->device; 19908c2ecf20Sopenharmony_ci unsigned int transferred, good_bytes; 19918c2ecf20Sopenharmony_ci u64 start_lba, end_lba, bad_lba; 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ci /* 19948c2ecf20Sopenharmony_ci * Some commands have a payload smaller than the device logical 19958c2ecf20Sopenharmony_ci * block size (e.g. INQUIRY on a 4K disk). 19968c2ecf20Sopenharmony_ci */ 19978c2ecf20Sopenharmony_ci if (scsi_bufflen(scmd) <= sdev->sector_size) 19988c2ecf20Sopenharmony_ci return 0; 19998c2ecf20Sopenharmony_ci 20008c2ecf20Sopenharmony_ci /* Check if we have a 'bad_lba' information */ 20018c2ecf20Sopenharmony_ci if (!scsi_get_sense_info_fld(scmd->sense_buffer, 20028c2ecf20Sopenharmony_ci SCSI_SENSE_BUFFERSIZE, 20038c2ecf20Sopenharmony_ci &bad_lba)) 20048c2ecf20Sopenharmony_ci return 0; 20058c2ecf20Sopenharmony_ci 20068c2ecf20Sopenharmony_ci /* 20078c2ecf20Sopenharmony_ci * If the bad lba was reported incorrectly, we have no idea where 20088c2ecf20Sopenharmony_ci * the error is. 20098c2ecf20Sopenharmony_ci */ 20108c2ecf20Sopenharmony_ci start_lba = sectors_to_logical(sdev, blk_rq_pos(req)); 20118c2ecf20Sopenharmony_ci end_lba = start_lba + bytes_to_logical(sdev, scsi_bufflen(scmd)); 20128c2ecf20Sopenharmony_ci if (bad_lba < start_lba || bad_lba >= end_lba) 20138c2ecf20Sopenharmony_ci return 0; 20148c2ecf20Sopenharmony_ci 20158c2ecf20Sopenharmony_ci /* 20168c2ecf20Sopenharmony_ci * resid is optional but mostly filled in. When it's unused, 20178c2ecf20Sopenharmony_ci * its value is zero, so we assume the whole buffer transferred 20188c2ecf20Sopenharmony_ci */ 20198c2ecf20Sopenharmony_ci transferred = scsi_bufflen(scmd) - scsi_get_resid(scmd); 20208c2ecf20Sopenharmony_ci 20218c2ecf20Sopenharmony_ci /* This computation should always be done in terms of the 20228c2ecf20Sopenharmony_ci * resolution of the device's medium. 20238c2ecf20Sopenharmony_ci */ 20248c2ecf20Sopenharmony_ci good_bytes = logical_to_bytes(sdev, bad_lba - start_lba); 20258c2ecf20Sopenharmony_ci 20268c2ecf20Sopenharmony_ci return min(good_bytes, transferred); 20278c2ecf20Sopenharmony_ci} 20288c2ecf20Sopenharmony_ci 20298c2ecf20Sopenharmony_ci/** 20308c2ecf20Sopenharmony_ci * sd_done - bottom half handler: called when the lower level 20318c2ecf20Sopenharmony_ci * driver has completed (successfully or otherwise) a scsi command. 20328c2ecf20Sopenharmony_ci * @SCpnt: mid-level's per command structure. 20338c2ecf20Sopenharmony_ci * 20348c2ecf20Sopenharmony_ci * Note: potentially run from within an ISR. Must not block. 20358c2ecf20Sopenharmony_ci **/ 20368c2ecf20Sopenharmony_cistatic int sd_done(struct scsi_cmnd *SCpnt) 20378c2ecf20Sopenharmony_ci{ 20388c2ecf20Sopenharmony_ci int result = SCpnt->result; 20398c2ecf20Sopenharmony_ci unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt); 20408c2ecf20Sopenharmony_ci unsigned int sector_size = SCpnt->device->sector_size; 20418c2ecf20Sopenharmony_ci unsigned int resid; 20428c2ecf20Sopenharmony_ci struct scsi_sense_hdr sshdr; 20438c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk); 20448c2ecf20Sopenharmony_ci struct request *req = SCpnt->request; 20458c2ecf20Sopenharmony_ci int sense_valid = 0; 20468c2ecf20Sopenharmony_ci int sense_deferred = 0; 20478c2ecf20Sopenharmony_ci 20488c2ecf20Sopenharmony_ci switch (req_op(req)) { 20498c2ecf20Sopenharmony_ci case REQ_OP_DISCARD: 20508c2ecf20Sopenharmony_ci case REQ_OP_WRITE_ZEROES: 20518c2ecf20Sopenharmony_ci case REQ_OP_WRITE_SAME: 20528c2ecf20Sopenharmony_ci case REQ_OP_ZONE_RESET: 20538c2ecf20Sopenharmony_ci case REQ_OP_ZONE_RESET_ALL: 20548c2ecf20Sopenharmony_ci case REQ_OP_ZONE_OPEN: 20558c2ecf20Sopenharmony_ci case REQ_OP_ZONE_CLOSE: 20568c2ecf20Sopenharmony_ci case REQ_OP_ZONE_FINISH: 20578c2ecf20Sopenharmony_ci if (!result) { 20588c2ecf20Sopenharmony_ci good_bytes = blk_rq_bytes(req); 20598c2ecf20Sopenharmony_ci scsi_set_resid(SCpnt, 0); 20608c2ecf20Sopenharmony_ci } else { 20618c2ecf20Sopenharmony_ci good_bytes = 0; 20628c2ecf20Sopenharmony_ci scsi_set_resid(SCpnt, blk_rq_bytes(req)); 20638c2ecf20Sopenharmony_ci } 20648c2ecf20Sopenharmony_ci break; 20658c2ecf20Sopenharmony_ci default: 20668c2ecf20Sopenharmony_ci /* 20678c2ecf20Sopenharmony_ci * In case of bogus fw or device, we could end up having 20688c2ecf20Sopenharmony_ci * an unaligned partial completion. Check this here and force 20698c2ecf20Sopenharmony_ci * alignment. 20708c2ecf20Sopenharmony_ci */ 20718c2ecf20Sopenharmony_ci resid = scsi_get_resid(SCpnt); 20728c2ecf20Sopenharmony_ci if (resid & (sector_size - 1)) { 20738c2ecf20Sopenharmony_ci sd_printk(KERN_INFO, sdkp, 20748c2ecf20Sopenharmony_ci "Unaligned partial completion (resid=%u, sector_sz=%u)\n", 20758c2ecf20Sopenharmony_ci resid, sector_size); 20768c2ecf20Sopenharmony_ci scsi_print_command(SCpnt); 20778c2ecf20Sopenharmony_ci resid = min(scsi_bufflen(SCpnt), 20788c2ecf20Sopenharmony_ci round_up(resid, sector_size)); 20798c2ecf20Sopenharmony_ci scsi_set_resid(SCpnt, resid); 20808c2ecf20Sopenharmony_ci } 20818c2ecf20Sopenharmony_ci } 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ci if (result) { 20848c2ecf20Sopenharmony_ci sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr); 20858c2ecf20Sopenharmony_ci if (sense_valid) 20868c2ecf20Sopenharmony_ci sense_deferred = scsi_sense_is_deferred(&sshdr); 20878c2ecf20Sopenharmony_ci } 20888c2ecf20Sopenharmony_ci sdkp->medium_access_timed_out = 0; 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_ci if (driver_byte(result) != DRIVER_SENSE && 20918c2ecf20Sopenharmony_ci (!sense_valid || sense_deferred)) 20928c2ecf20Sopenharmony_ci goto out; 20938c2ecf20Sopenharmony_ci 20948c2ecf20Sopenharmony_ci switch (sshdr.sense_key) { 20958c2ecf20Sopenharmony_ci case HARDWARE_ERROR: 20968c2ecf20Sopenharmony_ci case MEDIUM_ERROR: 20978c2ecf20Sopenharmony_ci good_bytes = sd_completed_bytes(SCpnt); 20988c2ecf20Sopenharmony_ci break; 20998c2ecf20Sopenharmony_ci case RECOVERED_ERROR: 21008c2ecf20Sopenharmony_ci good_bytes = scsi_bufflen(SCpnt); 21018c2ecf20Sopenharmony_ci break; 21028c2ecf20Sopenharmony_ci case NO_SENSE: 21038c2ecf20Sopenharmony_ci /* This indicates a false check condition, so ignore it. An 21048c2ecf20Sopenharmony_ci * unknown amount of data was transferred so treat it as an 21058c2ecf20Sopenharmony_ci * error. 21068c2ecf20Sopenharmony_ci */ 21078c2ecf20Sopenharmony_ci SCpnt->result = 0; 21088c2ecf20Sopenharmony_ci memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); 21098c2ecf20Sopenharmony_ci break; 21108c2ecf20Sopenharmony_ci case ABORTED_COMMAND: 21118c2ecf20Sopenharmony_ci if (sshdr.asc == 0x10) /* DIF: Target detected corruption */ 21128c2ecf20Sopenharmony_ci good_bytes = sd_completed_bytes(SCpnt); 21138c2ecf20Sopenharmony_ci break; 21148c2ecf20Sopenharmony_ci case ILLEGAL_REQUEST: 21158c2ecf20Sopenharmony_ci switch (sshdr.asc) { 21168c2ecf20Sopenharmony_ci case 0x10: /* DIX: Host detected corruption */ 21178c2ecf20Sopenharmony_ci good_bytes = sd_completed_bytes(SCpnt); 21188c2ecf20Sopenharmony_ci break; 21198c2ecf20Sopenharmony_ci case 0x20: /* INVALID COMMAND OPCODE */ 21208c2ecf20Sopenharmony_ci case 0x24: /* INVALID FIELD IN CDB */ 21218c2ecf20Sopenharmony_ci switch (SCpnt->cmnd[0]) { 21228c2ecf20Sopenharmony_ci case UNMAP: 21238c2ecf20Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_DISABLE); 21248c2ecf20Sopenharmony_ci break; 21258c2ecf20Sopenharmony_ci case WRITE_SAME_16: 21268c2ecf20Sopenharmony_ci case WRITE_SAME: 21278c2ecf20Sopenharmony_ci if (SCpnt->cmnd[1] & 8) { /* UNMAP */ 21288c2ecf20Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_DISABLE); 21298c2ecf20Sopenharmony_ci } else { 21308c2ecf20Sopenharmony_ci sdkp->device->no_write_same = 1; 21318c2ecf20Sopenharmony_ci sd_config_write_same(sdkp); 21328c2ecf20Sopenharmony_ci req->rq_flags |= RQF_QUIET; 21338c2ecf20Sopenharmony_ci } 21348c2ecf20Sopenharmony_ci break; 21358c2ecf20Sopenharmony_ci } 21368c2ecf20Sopenharmony_ci } 21378c2ecf20Sopenharmony_ci break; 21388c2ecf20Sopenharmony_ci default: 21398c2ecf20Sopenharmony_ci break; 21408c2ecf20Sopenharmony_ci } 21418c2ecf20Sopenharmony_ci 21428c2ecf20Sopenharmony_ci out: 21438c2ecf20Sopenharmony_ci if (sd_is_zoned(sdkp)) 21448c2ecf20Sopenharmony_ci good_bytes = sd_zbc_complete(SCpnt, good_bytes, &sshdr); 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_ci SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt, 21478c2ecf20Sopenharmony_ci "sd_done: completed %d of %d bytes\n", 21488c2ecf20Sopenharmony_ci good_bytes, scsi_bufflen(SCpnt))); 21498c2ecf20Sopenharmony_ci 21508c2ecf20Sopenharmony_ci return good_bytes; 21518c2ecf20Sopenharmony_ci} 21528c2ecf20Sopenharmony_ci 21538c2ecf20Sopenharmony_ci/* 21548c2ecf20Sopenharmony_ci * spinup disk - called only in sd_revalidate_disk() 21558c2ecf20Sopenharmony_ci */ 21568c2ecf20Sopenharmony_cistatic void 21578c2ecf20Sopenharmony_cisd_spinup_disk(struct scsi_disk *sdkp) 21588c2ecf20Sopenharmony_ci{ 21598c2ecf20Sopenharmony_ci unsigned char cmd[10]; 21608c2ecf20Sopenharmony_ci unsigned long spintime_expire = 0; 21618c2ecf20Sopenharmony_ci int retries, spintime; 21628c2ecf20Sopenharmony_ci unsigned int the_result; 21638c2ecf20Sopenharmony_ci struct scsi_sense_hdr sshdr; 21648c2ecf20Sopenharmony_ci int sense_valid = 0; 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ci spintime = 0; 21678c2ecf20Sopenharmony_ci 21688c2ecf20Sopenharmony_ci /* Spin up drives, as required. Only do this at boot time */ 21698c2ecf20Sopenharmony_ci /* Spinup needs to be done for module loads too. */ 21708c2ecf20Sopenharmony_ci do { 21718c2ecf20Sopenharmony_ci retries = 0; 21728c2ecf20Sopenharmony_ci 21738c2ecf20Sopenharmony_ci do { 21748c2ecf20Sopenharmony_ci cmd[0] = TEST_UNIT_READY; 21758c2ecf20Sopenharmony_ci memset((void *) &cmd[1], 0, 9); 21768c2ecf20Sopenharmony_ci 21778c2ecf20Sopenharmony_ci the_result = scsi_execute_req(sdkp->device, cmd, 21788c2ecf20Sopenharmony_ci DMA_NONE, NULL, 0, 21798c2ecf20Sopenharmony_ci &sshdr, SD_TIMEOUT, 21808c2ecf20Sopenharmony_ci sdkp->max_retries, NULL); 21818c2ecf20Sopenharmony_ci 21828c2ecf20Sopenharmony_ci /* 21838c2ecf20Sopenharmony_ci * If the drive has indicated to us that it 21848c2ecf20Sopenharmony_ci * doesn't have any media in it, don't bother 21858c2ecf20Sopenharmony_ci * with any more polling. 21868c2ecf20Sopenharmony_ci */ 21878c2ecf20Sopenharmony_ci if (media_not_present(sdkp, &sshdr)) 21888c2ecf20Sopenharmony_ci return; 21898c2ecf20Sopenharmony_ci 21908c2ecf20Sopenharmony_ci if (the_result) 21918c2ecf20Sopenharmony_ci sense_valid = scsi_sense_valid(&sshdr); 21928c2ecf20Sopenharmony_ci retries++; 21938c2ecf20Sopenharmony_ci } while (retries < 3 && 21948c2ecf20Sopenharmony_ci (!scsi_status_is_good(the_result) || 21958c2ecf20Sopenharmony_ci ((driver_byte(the_result) == DRIVER_SENSE) && 21968c2ecf20Sopenharmony_ci sense_valid && sshdr.sense_key == UNIT_ATTENTION))); 21978c2ecf20Sopenharmony_ci 21988c2ecf20Sopenharmony_ci if (driver_byte(the_result) != DRIVER_SENSE) { 21998c2ecf20Sopenharmony_ci /* no sense, TUR either succeeded or failed 22008c2ecf20Sopenharmony_ci * with a status error */ 22018c2ecf20Sopenharmony_ci if(!spintime && !scsi_status_is_good(the_result)) { 22028c2ecf20Sopenharmony_ci sd_print_result(sdkp, "Test Unit Ready failed", 22038c2ecf20Sopenharmony_ci the_result); 22048c2ecf20Sopenharmony_ci } 22058c2ecf20Sopenharmony_ci break; 22068c2ecf20Sopenharmony_ci } 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci /* 22098c2ecf20Sopenharmony_ci * The device does not want the automatic start to be issued. 22108c2ecf20Sopenharmony_ci */ 22118c2ecf20Sopenharmony_ci if (sdkp->device->no_start_on_add) 22128c2ecf20Sopenharmony_ci break; 22138c2ecf20Sopenharmony_ci 22148c2ecf20Sopenharmony_ci if (sense_valid && sshdr.sense_key == NOT_READY) { 22158c2ecf20Sopenharmony_ci if (sshdr.asc == 4 && sshdr.ascq == 3) 22168c2ecf20Sopenharmony_ci break; /* manual intervention required */ 22178c2ecf20Sopenharmony_ci if (sshdr.asc == 4 && sshdr.ascq == 0xb) 22188c2ecf20Sopenharmony_ci break; /* standby */ 22198c2ecf20Sopenharmony_ci if (sshdr.asc == 4 && sshdr.ascq == 0xc) 22208c2ecf20Sopenharmony_ci break; /* unavailable */ 22218c2ecf20Sopenharmony_ci if (sshdr.asc == 4 && sshdr.ascq == 0x1b) 22228c2ecf20Sopenharmony_ci break; /* sanitize in progress */ 22238c2ecf20Sopenharmony_ci /* 22248c2ecf20Sopenharmony_ci * Issue command to spin up drive when not ready 22258c2ecf20Sopenharmony_ci */ 22268c2ecf20Sopenharmony_ci if (!spintime) { 22278c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Spinning up disk..."); 22288c2ecf20Sopenharmony_ci cmd[0] = START_STOP; 22298c2ecf20Sopenharmony_ci cmd[1] = 1; /* Return immediately */ 22308c2ecf20Sopenharmony_ci memset((void *) &cmd[2], 0, 8); 22318c2ecf20Sopenharmony_ci cmd[4] = 1; /* Start spin cycle */ 22328c2ecf20Sopenharmony_ci if (sdkp->device->start_stop_pwr_cond) 22338c2ecf20Sopenharmony_ci cmd[4] |= 1 << 4; 22348c2ecf20Sopenharmony_ci scsi_execute_req(sdkp->device, cmd, DMA_NONE, 22358c2ecf20Sopenharmony_ci NULL, 0, &sshdr, 22368c2ecf20Sopenharmony_ci SD_TIMEOUT, sdkp->max_retries, 22378c2ecf20Sopenharmony_ci NULL); 22388c2ecf20Sopenharmony_ci spintime_expire = jiffies + 100 * HZ; 22398c2ecf20Sopenharmony_ci spintime = 1; 22408c2ecf20Sopenharmony_ci } 22418c2ecf20Sopenharmony_ci /* Wait 1 second for next try */ 22428c2ecf20Sopenharmony_ci msleep(1000); 22438c2ecf20Sopenharmony_ci printk(KERN_CONT "."); 22448c2ecf20Sopenharmony_ci 22458c2ecf20Sopenharmony_ci /* 22468c2ecf20Sopenharmony_ci * Wait for USB flash devices with slow firmware. 22478c2ecf20Sopenharmony_ci * Yes, this sense key/ASC combination shouldn't 22488c2ecf20Sopenharmony_ci * occur here. It's characteristic of these devices. 22498c2ecf20Sopenharmony_ci */ 22508c2ecf20Sopenharmony_ci } else if (sense_valid && 22518c2ecf20Sopenharmony_ci sshdr.sense_key == UNIT_ATTENTION && 22528c2ecf20Sopenharmony_ci sshdr.asc == 0x28) { 22538c2ecf20Sopenharmony_ci if (!spintime) { 22548c2ecf20Sopenharmony_ci spintime_expire = jiffies + 5 * HZ; 22558c2ecf20Sopenharmony_ci spintime = 1; 22568c2ecf20Sopenharmony_ci } 22578c2ecf20Sopenharmony_ci /* Wait 1 second for next try */ 22588c2ecf20Sopenharmony_ci msleep(1000); 22598c2ecf20Sopenharmony_ci } else { 22608c2ecf20Sopenharmony_ci /* we don't understand the sense code, so it's 22618c2ecf20Sopenharmony_ci * probably pointless to loop */ 22628c2ecf20Sopenharmony_ci if(!spintime) { 22638c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Unit Not Ready\n"); 22648c2ecf20Sopenharmony_ci sd_print_sense_hdr(sdkp, &sshdr); 22658c2ecf20Sopenharmony_ci } 22668c2ecf20Sopenharmony_ci break; 22678c2ecf20Sopenharmony_ci } 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_ci } while (spintime && time_before_eq(jiffies, spintime_expire)); 22708c2ecf20Sopenharmony_ci 22718c2ecf20Sopenharmony_ci if (spintime) { 22728c2ecf20Sopenharmony_ci if (scsi_status_is_good(the_result)) 22738c2ecf20Sopenharmony_ci printk(KERN_CONT "ready\n"); 22748c2ecf20Sopenharmony_ci else 22758c2ecf20Sopenharmony_ci printk(KERN_CONT "not responding...\n"); 22768c2ecf20Sopenharmony_ci } 22778c2ecf20Sopenharmony_ci} 22788c2ecf20Sopenharmony_ci 22798c2ecf20Sopenharmony_ci/* 22808c2ecf20Sopenharmony_ci * Determine whether disk supports Data Integrity Field. 22818c2ecf20Sopenharmony_ci */ 22828c2ecf20Sopenharmony_cistatic int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) 22838c2ecf20Sopenharmony_ci{ 22848c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 22858c2ecf20Sopenharmony_ci u8 type; 22868c2ecf20Sopenharmony_ci int ret = 0; 22878c2ecf20Sopenharmony_ci 22888c2ecf20Sopenharmony_ci if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) { 22898c2ecf20Sopenharmony_ci sdkp->protection_type = 0; 22908c2ecf20Sopenharmony_ci return ret; 22918c2ecf20Sopenharmony_ci } 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_ci type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ 22948c2ecf20Sopenharmony_ci 22958c2ecf20Sopenharmony_ci if (type > T10_PI_TYPE3_PROTECTION) 22968c2ecf20Sopenharmony_ci ret = -ENODEV; 22978c2ecf20Sopenharmony_ci else if (scsi_host_dif_capable(sdp->host, type)) 22988c2ecf20Sopenharmony_ci ret = 1; 22998c2ecf20Sopenharmony_ci 23008c2ecf20Sopenharmony_ci if (sdkp->first_scan || type != sdkp->protection_type) 23018c2ecf20Sopenharmony_ci switch (ret) { 23028c2ecf20Sopenharmony_ci case -ENODEV: 23038c2ecf20Sopenharmony_ci sd_printk(KERN_ERR, sdkp, "formatted with unsupported" \ 23048c2ecf20Sopenharmony_ci " protection type %u. Disabling disk!\n", 23058c2ecf20Sopenharmony_ci type); 23068c2ecf20Sopenharmony_ci break; 23078c2ecf20Sopenharmony_ci case 1: 23088c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 23098c2ecf20Sopenharmony_ci "Enabling DIF Type %u protection\n", type); 23108c2ecf20Sopenharmony_ci break; 23118c2ecf20Sopenharmony_ci case 0: 23128c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 23138c2ecf20Sopenharmony_ci "Disabling DIF Type %u protection\n", type); 23148c2ecf20Sopenharmony_ci break; 23158c2ecf20Sopenharmony_ci } 23168c2ecf20Sopenharmony_ci 23178c2ecf20Sopenharmony_ci sdkp->protection_type = type; 23188c2ecf20Sopenharmony_ci 23198c2ecf20Sopenharmony_ci return ret; 23208c2ecf20Sopenharmony_ci} 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_cistatic void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, 23238c2ecf20Sopenharmony_ci struct scsi_sense_hdr *sshdr, int sense_valid, 23248c2ecf20Sopenharmony_ci int the_result) 23258c2ecf20Sopenharmony_ci{ 23268c2ecf20Sopenharmony_ci if (driver_byte(the_result) == DRIVER_SENSE) 23278c2ecf20Sopenharmony_ci sd_print_sense_hdr(sdkp, sshdr); 23288c2ecf20Sopenharmony_ci else 23298c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Sense not available.\n"); 23308c2ecf20Sopenharmony_ci 23318c2ecf20Sopenharmony_ci /* 23328c2ecf20Sopenharmony_ci * Set dirty bit for removable devices if not ready - 23338c2ecf20Sopenharmony_ci * sometimes drives will not report this properly. 23348c2ecf20Sopenharmony_ci */ 23358c2ecf20Sopenharmony_ci if (sdp->removable && 23368c2ecf20Sopenharmony_ci sense_valid && sshdr->sense_key == NOT_READY) 23378c2ecf20Sopenharmony_ci set_media_not_present(sdkp); 23388c2ecf20Sopenharmony_ci 23398c2ecf20Sopenharmony_ci /* 23408c2ecf20Sopenharmony_ci * We used to set media_present to 0 here to indicate no media 23418c2ecf20Sopenharmony_ci * in the drive, but some drives fail read capacity even with 23428c2ecf20Sopenharmony_ci * media present, so we can't do that. 23438c2ecf20Sopenharmony_ci */ 23448c2ecf20Sopenharmony_ci sdkp->capacity = 0; /* unknown mapped to zero - as usual */ 23458c2ecf20Sopenharmony_ci} 23468c2ecf20Sopenharmony_ci 23478c2ecf20Sopenharmony_ci#define RC16_LEN 32 23488c2ecf20Sopenharmony_ci#if RC16_LEN > SD_BUF_SIZE 23498c2ecf20Sopenharmony_ci#error RC16_LEN must not be more than SD_BUF_SIZE 23508c2ecf20Sopenharmony_ci#endif 23518c2ecf20Sopenharmony_ci 23528c2ecf20Sopenharmony_ci#define READ_CAPACITY_RETRIES_ON_RESET 10 23538c2ecf20Sopenharmony_ci 23548c2ecf20Sopenharmony_cistatic int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, 23558c2ecf20Sopenharmony_ci unsigned char *buffer) 23568c2ecf20Sopenharmony_ci{ 23578c2ecf20Sopenharmony_ci unsigned char cmd[16]; 23588c2ecf20Sopenharmony_ci struct scsi_sense_hdr sshdr; 23598c2ecf20Sopenharmony_ci int sense_valid = 0; 23608c2ecf20Sopenharmony_ci int the_result; 23618c2ecf20Sopenharmony_ci int retries = 3, reset_retries = READ_CAPACITY_RETRIES_ON_RESET; 23628c2ecf20Sopenharmony_ci unsigned int alignment; 23638c2ecf20Sopenharmony_ci unsigned long long lba; 23648c2ecf20Sopenharmony_ci unsigned sector_size; 23658c2ecf20Sopenharmony_ci 23668c2ecf20Sopenharmony_ci if (sdp->no_read_capacity_16) 23678c2ecf20Sopenharmony_ci return -EINVAL; 23688c2ecf20Sopenharmony_ci 23698c2ecf20Sopenharmony_ci do { 23708c2ecf20Sopenharmony_ci memset(cmd, 0, 16); 23718c2ecf20Sopenharmony_ci cmd[0] = SERVICE_ACTION_IN_16; 23728c2ecf20Sopenharmony_ci cmd[1] = SAI_READ_CAPACITY_16; 23738c2ecf20Sopenharmony_ci cmd[13] = RC16_LEN; 23748c2ecf20Sopenharmony_ci memset(buffer, 0, RC16_LEN); 23758c2ecf20Sopenharmony_ci 23768c2ecf20Sopenharmony_ci the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, 23778c2ecf20Sopenharmony_ci buffer, RC16_LEN, &sshdr, 23788c2ecf20Sopenharmony_ci SD_TIMEOUT, sdkp->max_retries, NULL); 23798c2ecf20Sopenharmony_ci 23808c2ecf20Sopenharmony_ci if (media_not_present(sdkp, &sshdr)) 23818c2ecf20Sopenharmony_ci return -ENODEV; 23828c2ecf20Sopenharmony_ci 23838c2ecf20Sopenharmony_ci if (the_result) { 23848c2ecf20Sopenharmony_ci sense_valid = scsi_sense_valid(&sshdr); 23858c2ecf20Sopenharmony_ci if (sense_valid && 23868c2ecf20Sopenharmony_ci sshdr.sense_key == ILLEGAL_REQUEST && 23878c2ecf20Sopenharmony_ci (sshdr.asc == 0x20 || sshdr.asc == 0x24) && 23888c2ecf20Sopenharmony_ci sshdr.ascq == 0x00) 23898c2ecf20Sopenharmony_ci /* Invalid Command Operation Code or 23908c2ecf20Sopenharmony_ci * Invalid Field in CDB, just retry 23918c2ecf20Sopenharmony_ci * silently with RC10 */ 23928c2ecf20Sopenharmony_ci return -EINVAL; 23938c2ecf20Sopenharmony_ci if (sense_valid && 23948c2ecf20Sopenharmony_ci sshdr.sense_key == UNIT_ATTENTION && 23958c2ecf20Sopenharmony_ci sshdr.asc == 0x29 && sshdr.ascq == 0x00) 23968c2ecf20Sopenharmony_ci /* Device reset might occur several times, 23978c2ecf20Sopenharmony_ci * give it one more chance */ 23988c2ecf20Sopenharmony_ci if (--reset_retries > 0) 23998c2ecf20Sopenharmony_ci continue; 24008c2ecf20Sopenharmony_ci } 24018c2ecf20Sopenharmony_ci retries--; 24028c2ecf20Sopenharmony_ci 24038c2ecf20Sopenharmony_ci } while (the_result && retries); 24048c2ecf20Sopenharmony_ci 24058c2ecf20Sopenharmony_ci if (the_result) { 24068c2ecf20Sopenharmony_ci sd_print_result(sdkp, "Read Capacity(16) failed", the_result); 24078c2ecf20Sopenharmony_ci read_capacity_error(sdkp, sdp, &sshdr, sense_valid, the_result); 24088c2ecf20Sopenharmony_ci return -EINVAL; 24098c2ecf20Sopenharmony_ci } 24108c2ecf20Sopenharmony_ci 24118c2ecf20Sopenharmony_ci sector_size = get_unaligned_be32(&buffer[8]); 24128c2ecf20Sopenharmony_ci lba = get_unaligned_be64(&buffer[0]); 24138c2ecf20Sopenharmony_ci 24148c2ecf20Sopenharmony_ci if (sd_read_protection_type(sdkp, buffer) < 0) { 24158c2ecf20Sopenharmony_ci sdkp->capacity = 0; 24168c2ecf20Sopenharmony_ci return -ENODEV; 24178c2ecf20Sopenharmony_ci } 24188c2ecf20Sopenharmony_ci 24198c2ecf20Sopenharmony_ci /* Logical blocks per physical block exponent */ 24208c2ecf20Sopenharmony_ci sdkp->physical_block_size = (1 << (buffer[13] & 0xf)) * sector_size; 24218c2ecf20Sopenharmony_ci 24228c2ecf20Sopenharmony_ci /* RC basis */ 24238c2ecf20Sopenharmony_ci sdkp->rc_basis = (buffer[12] >> 4) & 0x3; 24248c2ecf20Sopenharmony_ci 24258c2ecf20Sopenharmony_ci /* Lowest aligned logical block */ 24268c2ecf20Sopenharmony_ci alignment = ((buffer[14] & 0x3f) << 8 | buffer[15]) * sector_size; 24278c2ecf20Sopenharmony_ci blk_queue_alignment_offset(sdp->request_queue, alignment); 24288c2ecf20Sopenharmony_ci if (alignment && sdkp->first_scan) 24298c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 24308c2ecf20Sopenharmony_ci "physical block alignment offset: %u\n", alignment); 24318c2ecf20Sopenharmony_ci 24328c2ecf20Sopenharmony_ci if (buffer[14] & 0x80) { /* LBPME */ 24338c2ecf20Sopenharmony_ci sdkp->lbpme = 1; 24348c2ecf20Sopenharmony_ci 24358c2ecf20Sopenharmony_ci if (buffer[14] & 0x40) /* LBPRZ */ 24368c2ecf20Sopenharmony_ci sdkp->lbprz = 1; 24378c2ecf20Sopenharmony_ci 24388c2ecf20Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_WS16); 24398c2ecf20Sopenharmony_ci } 24408c2ecf20Sopenharmony_ci 24418c2ecf20Sopenharmony_ci sdkp->capacity = lba + 1; 24428c2ecf20Sopenharmony_ci return sector_size; 24438c2ecf20Sopenharmony_ci} 24448c2ecf20Sopenharmony_ci 24458c2ecf20Sopenharmony_cistatic int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, 24468c2ecf20Sopenharmony_ci unsigned char *buffer) 24478c2ecf20Sopenharmony_ci{ 24488c2ecf20Sopenharmony_ci unsigned char cmd[16]; 24498c2ecf20Sopenharmony_ci struct scsi_sense_hdr sshdr; 24508c2ecf20Sopenharmony_ci int sense_valid = 0; 24518c2ecf20Sopenharmony_ci int the_result; 24528c2ecf20Sopenharmony_ci int retries = 3, reset_retries = READ_CAPACITY_RETRIES_ON_RESET; 24538c2ecf20Sopenharmony_ci sector_t lba; 24548c2ecf20Sopenharmony_ci unsigned sector_size; 24558c2ecf20Sopenharmony_ci 24568c2ecf20Sopenharmony_ci do { 24578c2ecf20Sopenharmony_ci cmd[0] = READ_CAPACITY; 24588c2ecf20Sopenharmony_ci memset(&cmd[1], 0, 9); 24598c2ecf20Sopenharmony_ci memset(buffer, 0, 8); 24608c2ecf20Sopenharmony_ci 24618c2ecf20Sopenharmony_ci the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, 24628c2ecf20Sopenharmony_ci buffer, 8, &sshdr, 24638c2ecf20Sopenharmony_ci SD_TIMEOUT, sdkp->max_retries, NULL); 24648c2ecf20Sopenharmony_ci 24658c2ecf20Sopenharmony_ci if (media_not_present(sdkp, &sshdr)) 24668c2ecf20Sopenharmony_ci return -ENODEV; 24678c2ecf20Sopenharmony_ci 24688c2ecf20Sopenharmony_ci if (the_result) { 24698c2ecf20Sopenharmony_ci sense_valid = scsi_sense_valid(&sshdr); 24708c2ecf20Sopenharmony_ci if (sense_valid && 24718c2ecf20Sopenharmony_ci sshdr.sense_key == UNIT_ATTENTION && 24728c2ecf20Sopenharmony_ci sshdr.asc == 0x29 && sshdr.ascq == 0x00) 24738c2ecf20Sopenharmony_ci /* Device reset might occur several times, 24748c2ecf20Sopenharmony_ci * give it one more chance */ 24758c2ecf20Sopenharmony_ci if (--reset_retries > 0) 24768c2ecf20Sopenharmony_ci continue; 24778c2ecf20Sopenharmony_ci } 24788c2ecf20Sopenharmony_ci retries--; 24798c2ecf20Sopenharmony_ci 24808c2ecf20Sopenharmony_ci } while (the_result && retries); 24818c2ecf20Sopenharmony_ci 24828c2ecf20Sopenharmony_ci if (the_result) { 24838c2ecf20Sopenharmony_ci sd_print_result(sdkp, "Read Capacity(10) failed", the_result); 24848c2ecf20Sopenharmony_ci read_capacity_error(sdkp, sdp, &sshdr, sense_valid, the_result); 24858c2ecf20Sopenharmony_ci return -EINVAL; 24868c2ecf20Sopenharmony_ci } 24878c2ecf20Sopenharmony_ci 24888c2ecf20Sopenharmony_ci sector_size = get_unaligned_be32(&buffer[4]); 24898c2ecf20Sopenharmony_ci lba = get_unaligned_be32(&buffer[0]); 24908c2ecf20Sopenharmony_ci 24918c2ecf20Sopenharmony_ci if (sdp->no_read_capacity_16 && (lba == 0xffffffff)) { 24928c2ecf20Sopenharmony_ci /* Some buggy (usb cardreader) devices return an lba of 24938c2ecf20Sopenharmony_ci 0xffffffff when the want to report a size of 0 (with 24948c2ecf20Sopenharmony_ci which they really mean no media is present) */ 24958c2ecf20Sopenharmony_ci sdkp->capacity = 0; 24968c2ecf20Sopenharmony_ci sdkp->physical_block_size = sector_size; 24978c2ecf20Sopenharmony_ci return sector_size; 24988c2ecf20Sopenharmony_ci } 24998c2ecf20Sopenharmony_ci 25008c2ecf20Sopenharmony_ci sdkp->capacity = lba + 1; 25018c2ecf20Sopenharmony_ci sdkp->physical_block_size = sector_size; 25028c2ecf20Sopenharmony_ci return sector_size; 25038c2ecf20Sopenharmony_ci} 25048c2ecf20Sopenharmony_ci 25058c2ecf20Sopenharmony_cistatic int sd_try_rc16_first(struct scsi_device *sdp) 25068c2ecf20Sopenharmony_ci{ 25078c2ecf20Sopenharmony_ci if (sdp->host->max_cmd_len < 16) 25088c2ecf20Sopenharmony_ci return 0; 25098c2ecf20Sopenharmony_ci if (sdp->try_rc_10_first) 25108c2ecf20Sopenharmony_ci return 0; 25118c2ecf20Sopenharmony_ci if (sdp->scsi_level > SCSI_SPC_2) 25128c2ecf20Sopenharmony_ci return 1; 25138c2ecf20Sopenharmony_ci if (scsi_device_protection(sdp)) 25148c2ecf20Sopenharmony_ci return 1; 25158c2ecf20Sopenharmony_ci return 0; 25168c2ecf20Sopenharmony_ci} 25178c2ecf20Sopenharmony_ci 25188c2ecf20Sopenharmony_ci/* 25198c2ecf20Sopenharmony_ci * read disk capacity 25208c2ecf20Sopenharmony_ci */ 25218c2ecf20Sopenharmony_cistatic void 25228c2ecf20Sopenharmony_cisd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer) 25238c2ecf20Sopenharmony_ci{ 25248c2ecf20Sopenharmony_ci int sector_size; 25258c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 25268c2ecf20Sopenharmony_ci 25278c2ecf20Sopenharmony_ci if (sd_try_rc16_first(sdp)) { 25288c2ecf20Sopenharmony_ci sector_size = read_capacity_16(sdkp, sdp, buffer); 25298c2ecf20Sopenharmony_ci if (sector_size == -EOVERFLOW) 25308c2ecf20Sopenharmony_ci goto got_data; 25318c2ecf20Sopenharmony_ci if (sector_size == -ENODEV) 25328c2ecf20Sopenharmony_ci return; 25338c2ecf20Sopenharmony_ci if (sector_size < 0) 25348c2ecf20Sopenharmony_ci sector_size = read_capacity_10(sdkp, sdp, buffer); 25358c2ecf20Sopenharmony_ci if (sector_size < 0) 25368c2ecf20Sopenharmony_ci return; 25378c2ecf20Sopenharmony_ci } else { 25388c2ecf20Sopenharmony_ci sector_size = read_capacity_10(sdkp, sdp, buffer); 25398c2ecf20Sopenharmony_ci if (sector_size == -EOVERFLOW) 25408c2ecf20Sopenharmony_ci goto got_data; 25418c2ecf20Sopenharmony_ci if (sector_size < 0) 25428c2ecf20Sopenharmony_ci return; 25438c2ecf20Sopenharmony_ci if ((sizeof(sdkp->capacity) > 4) && 25448c2ecf20Sopenharmony_ci (sdkp->capacity > 0xffffffffULL)) { 25458c2ecf20Sopenharmony_ci int old_sector_size = sector_size; 25468c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Very big device. " 25478c2ecf20Sopenharmony_ci "Trying to use READ CAPACITY(16).\n"); 25488c2ecf20Sopenharmony_ci sector_size = read_capacity_16(sdkp, sdp, buffer); 25498c2ecf20Sopenharmony_ci if (sector_size < 0) { 25508c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 25518c2ecf20Sopenharmony_ci "Using 0xffffffff as device size\n"); 25528c2ecf20Sopenharmony_ci sdkp->capacity = 1 + (sector_t) 0xffffffff; 25538c2ecf20Sopenharmony_ci sector_size = old_sector_size; 25548c2ecf20Sopenharmony_ci goto got_data; 25558c2ecf20Sopenharmony_ci } 25568c2ecf20Sopenharmony_ci /* Remember that READ CAPACITY(16) succeeded */ 25578c2ecf20Sopenharmony_ci sdp->try_rc_10_first = 0; 25588c2ecf20Sopenharmony_ci } 25598c2ecf20Sopenharmony_ci } 25608c2ecf20Sopenharmony_ci 25618c2ecf20Sopenharmony_ci /* Some devices are known to return the total number of blocks, 25628c2ecf20Sopenharmony_ci * not the highest block number. Some devices have versions 25638c2ecf20Sopenharmony_ci * which do this and others which do not. Some devices we might 25648c2ecf20Sopenharmony_ci * suspect of doing this but we don't know for certain. 25658c2ecf20Sopenharmony_ci * 25668c2ecf20Sopenharmony_ci * If we know the reported capacity is wrong, decrement it. If 25678c2ecf20Sopenharmony_ci * we can only guess, then assume the number of blocks is even 25688c2ecf20Sopenharmony_ci * (usually true but not always) and err on the side of lowering 25698c2ecf20Sopenharmony_ci * the capacity. 25708c2ecf20Sopenharmony_ci */ 25718c2ecf20Sopenharmony_ci if (sdp->fix_capacity || 25728c2ecf20Sopenharmony_ci (sdp->guess_capacity && (sdkp->capacity & 0x01))) { 25738c2ecf20Sopenharmony_ci sd_printk(KERN_INFO, sdkp, "Adjusting the sector count " 25748c2ecf20Sopenharmony_ci "from its reported value: %llu\n", 25758c2ecf20Sopenharmony_ci (unsigned long long) sdkp->capacity); 25768c2ecf20Sopenharmony_ci --sdkp->capacity; 25778c2ecf20Sopenharmony_ci } 25788c2ecf20Sopenharmony_ci 25798c2ecf20Sopenharmony_cigot_data: 25808c2ecf20Sopenharmony_ci if (sector_size == 0) { 25818c2ecf20Sopenharmony_ci sector_size = 512; 25828c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Sector size 0 reported, " 25838c2ecf20Sopenharmony_ci "assuming 512.\n"); 25848c2ecf20Sopenharmony_ci } 25858c2ecf20Sopenharmony_ci 25868c2ecf20Sopenharmony_ci if (sector_size != 512 && 25878c2ecf20Sopenharmony_ci sector_size != 1024 && 25888c2ecf20Sopenharmony_ci sector_size != 2048 && 25898c2ecf20Sopenharmony_ci sector_size != 4096) { 25908c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Unsupported sector size %d.\n", 25918c2ecf20Sopenharmony_ci sector_size); 25928c2ecf20Sopenharmony_ci /* 25938c2ecf20Sopenharmony_ci * The user might want to re-format the drive with 25948c2ecf20Sopenharmony_ci * a supported sectorsize. Once this happens, it 25958c2ecf20Sopenharmony_ci * would be relatively trivial to set the thing up. 25968c2ecf20Sopenharmony_ci * For this reason, we leave the thing in the table. 25978c2ecf20Sopenharmony_ci */ 25988c2ecf20Sopenharmony_ci sdkp->capacity = 0; 25998c2ecf20Sopenharmony_ci /* 26008c2ecf20Sopenharmony_ci * set a bogus sector size so the normal read/write 26018c2ecf20Sopenharmony_ci * logic in the block layer will eventually refuse any 26028c2ecf20Sopenharmony_ci * request on this device without tripping over power 26038c2ecf20Sopenharmony_ci * of two sector size assumptions 26048c2ecf20Sopenharmony_ci */ 26058c2ecf20Sopenharmony_ci sector_size = 512; 26068c2ecf20Sopenharmony_ci } 26078c2ecf20Sopenharmony_ci blk_queue_logical_block_size(sdp->request_queue, sector_size); 26088c2ecf20Sopenharmony_ci blk_queue_physical_block_size(sdp->request_queue, 26098c2ecf20Sopenharmony_ci sdkp->physical_block_size); 26108c2ecf20Sopenharmony_ci sdkp->device->sector_size = sector_size; 26118c2ecf20Sopenharmony_ci 26128c2ecf20Sopenharmony_ci if (sdkp->capacity > 0xffffffff) 26138c2ecf20Sopenharmony_ci sdp->use_16_for_rw = 1; 26148c2ecf20Sopenharmony_ci 26158c2ecf20Sopenharmony_ci} 26168c2ecf20Sopenharmony_ci 26178c2ecf20Sopenharmony_ci/* 26188c2ecf20Sopenharmony_ci * Print disk capacity 26198c2ecf20Sopenharmony_ci */ 26208c2ecf20Sopenharmony_cistatic void 26218c2ecf20Sopenharmony_cisd_print_capacity(struct scsi_disk *sdkp, 26228c2ecf20Sopenharmony_ci sector_t old_capacity) 26238c2ecf20Sopenharmony_ci{ 26248c2ecf20Sopenharmony_ci int sector_size = sdkp->device->sector_size; 26258c2ecf20Sopenharmony_ci char cap_str_2[10], cap_str_10[10]; 26268c2ecf20Sopenharmony_ci 26278c2ecf20Sopenharmony_ci if (!sdkp->first_scan && old_capacity == sdkp->capacity) 26288c2ecf20Sopenharmony_ci return; 26298c2ecf20Sopenharmony_ci 26308c2ecf20Sopenharmony_ci string_get_size(sdkp->capacity, sector_size, 26318c2ecf20Sopenharmony_ci STRING_UNITS_2, cap_str_2, sizeof(cap_str_2)); 26328c2ecf20Sopenharmony_ci string_get_size(sdkp->capacity, sector_size, 26338c2ecf20Sopenharmony_ci STRING_UNITS_10, cap_str_10, sizeof(cap_str_10)); 26348c2ecf20Sopenharmony_ci 26358c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 26368c2ecf20Sopenharmony_ci "%llu %d-byte logical blocks: (%s/%s)\n", 26378c2ecf20Sopenharmony_ci (unsigned long long)sdkp->capacity, 26388c2ecf20Sopenharmony_ci sector_size, cap_str_10, cap_str_2); 26398c2ecf20Sopenharmony_ci 26408c2ecf20Sopenharmony_ci if (sdkp->physical_block_size != sector_size) 26418c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 26428c2ecf20Sopenharmony_ci "%u-byte physical blocks\n", 26438c2ecf20Sopenharmony_ci sdkp->physical_block_size); 26448c2ecf20Sopenharmony_ci} 26458c2ecf20Sopenharmony_ci 26468c2ecf20Sopenharmony_ci/* called with buffer of length 512 */ 26478c2ecf20Sopenharmony_cistatic inline int 26488c2ecf20Sopenharmony_cisd_do_mode_sense(struct scsi_disk *sdkp, int dbd, int modepage, 26498c2ecf20Sopenharmony_ci unsigned char *buffer, int len, struct scsi_mode_data *data, 26508c2ecf20Sopenharmony_ci struct scsi_sense_hdr *sshdr) 26518c2ecf20Sopenharmony_ci{ 26528c2ecf20Sopenharmony_ci return scsi_mode_sense(sdkp->device, dbd, modepage, buffer, len, 26538c2ecf20Sopenharmony_ci SD_TIMEOUT, sdkp->max_retries, data, 26548c2ecf20Sopenharmony_ci sshdr); 26558c2ecf20Sopenharmony_ci} 26568c2ecf20Sopenharmony_ci 26578c2ecf20Sopenharmony_ci/* 26588c2ecf20Sopenharmony_ci * read write protect setting, if possible - called only in sd_revalidate_disk() 26598c2ecf20Sopenharmony_ci * called with buffer of length SD_BUF_SIZE 26608c2ecf20Sopenharmony_ci */ 26618c2ecf20Sopenharmony_cistatic void 26628c2ecf20Sopenharmony_cisd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer) 26638c2ecf20Sopenharmony_ci{ 26648c2ecf20Sopenharmony_ci int res; 26658c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 26668c2ecf20Sopenharmony_ci struct scsi_mode_data data; 26678c2ecf20Sopenharmony_ci int old_wp = sdkp->write_prot; 26688c2ecf20Sopenharmony_ci 26698c2ecf20Sopenharmony_ci set_disk_ro(sdkp->disk, 0); 26708c2ecf20Sopenharmony_ci if (sdp->skip_ms_page_3f) { 26718c2ecf20Sopenharmony_ci sd_first_printk(KERN_NOTICE, sdkp, "Assuming Write Enabled\n"); 26728c2ecf20Sopenharmony_ci return; 26738c2ecf20Sopenharmony_ci } 26748c2ecf20Sopenharmony_ci 26758c2ecf20Sopenharmony_ci if (sdp->use_192_bytes_for_3f) { 26768c2ecf20Sopenharmony_ci res = sd_do_mode_sense(sdkp, 0, 0x3F, buffer, 192, &data, NULL); 26778c2ecf20Sopenharmony_ci } else { 26788c2ecf20Sopenharmony_ci /* 26798c2ecf20Sopenharmony_ci * First attempt: ask for all pages (0x3F), but only 4 bytes. 26808c2ecf20Sopenharmony_ci * We have to start carefully: some devices hang if we ask 26818c2ecf20Sopenharmony_ci * for more than is available. 26828c2ecf20Sopenharmony_ci */ 26838c2ecf20Sopenharmony_ci res = sd_do_mode_sense(sdkp, 0, 0x3F, buffer, 4, &data, NULL); 26848c2ecf20Sopenharmony_ci 26858c2ecf20Sopenharmony_ci /* 26868c2ecf20Sopenharmony_ci * Second attempt: ask for page 0 When only page 0 is 26878c2ecf20Sopenharmony_ci * implemented, a request for page 3F may return Sense Key 26888c2ecf20Sopenharmony_ci * 5: Illegal Request, Sense Code 24: Invalid field in 26898c2ecf20Sopenharmony_ci * CDB. 26908c2ecf20Sopenharmony_ci */ 26918c2ecf20Sopenharmony_ci if (res < 0) 26928c2ecf20Sopenharmony_ci res = sd_do_mode_sense(sdkp, 0, 0, buffer, 4, &data, NULL); 26938c2ecf20Sopenharmony_ci 26948c2ecf20Sopenharmony_ci /* 26958c2ecf20Sopenharmony_ci * Third attempt: ask 255 bytes, as we did earlier. 26968c2ecf20Sopenharmony_ci */ 26978c2ecf20Sopenharmony_ci if (res < 0) 26988c2ecf20Sopenharmony_ci res = sd_do_mode_sense(sdkp, 0, 0x3F, buffer, 255, 26998c2ecf20Sopenharmony_ci &data, NULL); 27008c2ecf20Sopenharmony_ci } 27018c2ecf20Sopenharmony_ci 27028c2ecf20Sopenharmony_ci if (res < 0) { 27038c2ecf20Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 27048c2ecf20Sopenharmony_ci "Test WP failed, assume Write Enabled\n"); 27058c2ecf20Sopenharmony_ci } else { 27068c2ecf20Sopenharmony_ci sdkp->write_prot = ((data.device_specific & 0x80) != 0); 27078c2ecf20Sopenharmony_ci set_disk_ro(sdkp->disk, sdkp->write_prot); 27088c2ecf20Sopenharmony_ci if (sdkp->first_scan || old_wp != sdkp->write_prot) { 27098c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n", 27108c2ecf20Sopenharmony_ci sdkp->write_prot ? "on" : "off"); 27118c2ecf20Sopenharmony_ci sd_printk(KERN_DEBUG, sdkp, "Mode Sense: %4ph\n", buffer); 27128c2ecf20Sopenharmony_ci } 27138c2ecf20Sopenharmony_ci } 27148c2ecf20Sopenharmony_ci} 27158c2ecf20Sopenharmony_ci 27168c2ecf20Sopenharmony_ci/* 27178c2ecf20Sopenharmony_ci * sd_read_cache_type - called only from sd_revalidate_disk() 27188c2ecf20Sopenharmony_ci * called with buffer of length SD_BUF_SIZE 27198c2ecf20Sopenharmony_ci */ 27208c2ecf20Sopenharmony_cistatic void 27218c2ecf20Sopenharmony_cisd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) 27228c2ecf20Sopenharmony_ci{ 27238c2ecf20Sopenharmony_ci int len = 0, res; 27248c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 27258c2ecf20Sopenharmony_ci 27268c2ecf20Sopenharmony_ci int dbd; 27278c2ecf20Sopenharmony_ci int modepage; 27288c2ecf20Sopenharmony_ci int first_len; 27298c2ecf20Sopenharmony_ci struct scsi_mode_data data; 27308c2ecf20Sopenharmony_ci struct scsi_sense_hdr sshdr; 27318c2ecf20Sopenharmony_ci int old_wce = sdkp->WCE; 27328c2ecf20Sopenharmony_ci int old_rcd = sdkp->RCD; 27338c2ecf20Sopenharmony_ci int old_dpofua = sdkp->DPOFUA; 27348c2ecf20Sopenharmony_ci 27358c2ecf20Sopenharmony_ci 27368c2ecf20Sopenharmony_ci if (sdkp->cache_override) 27378c2ecf20Sopenharmony_ci return; 27388c2ecf20Sopenharmony_ci 27398c2ecf20Sopenharmony_ci first_len = 4; 27408c2ecf20Sopenharmony_ci if (sdp->skip_ms_page_8) { 27418c2ecf20Sopenharmony_ci if (sdp->type == TYPE_RBC) 27428c2ecf20Sopenharmony_ci goto defaults; 27438c2ecf20Sopenharmony_ci else { 27448c2ecf20Sopenharmony_ci if (sdp->skip_ms_page_3f) 27458c2ecf20Sopenharmony_ci goto defaults; 27468c2ecf20Sopenharmony_ci modepage = 0x3F; 27478c2ecf20Sopenharmony_ci if (sdp->use_192_bytes_for_3f) 27488c2ecf20Sopenharmony_ci first_len = 192; 27498c2ecf20Sopenharmony_ci dbd = 0; 27508c2ecf20Sopenharmony_ci } 27518c2ecf20Sopenharmony_ci } else if (sdp->type == TYPE_RBC) { 27528c2ecf20Sopenharmony_ci modepage = 6; 27538c2ecf20Sopenharmony_ci dbd = 8; 27548c2ecf20Sopenharmony_ci } else { 27558c2ecf20Sopenharmony_ci modepage = 8; 27568c2ecf20Sopenharmony_ci dbd = 0; 27578c2ecf20Sopenharmony_ci } 27588c2ecf20Sopenharmony_ci 27598c2ecf20Sopenharmony_ci /* cautiously ask */ 27608c2ecf20Sopenharmony_ci res = sd_do_mode_sense(sdkp, dbd, modepage, buffer, first_len, 27618c2ecf20Sopenharmony_ci &data, &sshdr); 27628c2ecf20Sopenharmony_ci 27638c2ecf20Sopenharmony_ci if (res < 0) 27648c2ecf20Sopenharmony_ci goto bad_sense; 27658c2ecf20Sopenharmony_ci 27668c2ecf20Sopenharmony_ci if (!data.header_length) { 27678c2ecf20Sopenharmony_ci modepage = 6; 27688c2ecf20Sopenharmony_ci first_len = 0; 27698c2ecf20Sopenharmony_ci sd_first_printk(KERN_ERR, sdkp, 27708c2ecf20Sopenharmony_ci "Missing header in MODE_SENSE response\n"); 27718c2ecf20Sopenharmony_ci } 27728c2ecf20Sopenharmony_ci 27738c2ecf20Sopenharmony_ci /* that went OK, now ask for the proper length */ 27748c2ecf20Sopenharmony_ci len = data.length; 27758c2ecf20Sopenharmony_ci 27768c2ecf20Sopenharmony_ci /* 27778c2ecf20Sopenharmony_ci * We're only interested in the first three bytes, actually. 27788c2ecf20Sopenharmony_ci * But the data cache page is defined for the first 20. 27798c2ecf20Sopenharmony_ci */ 27808c2ecf20Sopenharmony_ci if (len < 3) 27818c2ecf20Sopenharmony_ci goto bad_sense; 27828c2ecf20Sopenharmony_ci else if (len > SD_BUF_SIZE) { 27838c2ecf20Sopenharmony_ci sd_first_printk(KERN_NOTICE, sdkp, "Truncating mode parameter " 27848c2ecf20Sopenharmony_ci "data from %d to %d bytes\n", len, SD_BUF_SIZE); 27858c2ecf20Sopenharmony_ci len = SD_BUF_SIZE; 27868c2ecf20Sopenharmony_ci } 27878c2ecf20Sopenharmony_ci if (modepage == 0x3F && sdp->use_192_bytes_for_3f) 27888c2ecf20Sopenharmony_ci len = 192; 27898c2ecf20Sopenharmony_ci 27908c2ecf20Sopenharmony_ci /* Get the data */ 27918c2ecf20Sopenharmony_ci if (len > first_len) 27928c2ecf20Sopenharmony_ci res = sd_do_mode_sense(sdkp, dbd, modepage, buffer, len, 27938c2ecf20Sopenharmony_ci &data, &sshdr); 27948c2ecf20Sopenharmony_ci 27958c2ecf20Sopenharmony_ci if (!res) { 27968c2ecf20Sopenharmony_ci int offset = data.header_length + data.block_descriptor_length; 27978c2ecf20Sopenharmony_ci 27988c2ecf20Sopenharmony_ci while (offset < len) { 27998c2ecf20Sopenharmony_ci u8 page_code = buffer[offset] & 0x3F; 28008c2ecf20Sopenharmony_ci u8 spf = buffer[offset] & 0x40; 28018c2ecf20Sopenharmony_ci 28028c2ecf20Sopenharmony_ci if (page_code == 8 || page_code == 6) { 28038c2ecf20Sopenharmony_ci /* We're interested only in the first 3 bytes. 28048c2ecf20Sopenharmony_ci */ 28058c2ecf20Sopenharmony_ci if (len - offset <= 2) { 28068c2ecf20Sopenharmony_ci sd_first_printk(KERN_ERR, sdkp, 28078c2ecf20Sopenharmony_ci "Incomplete mode parameter " 28088c2ecf20Sopenharmony_ci "data\n"); 28098c2ecf20Sopenharmony_ci goto defaults; 28108c2ecf20Sopenharmony_ci } else { 28118c2ecf20Sopenharmony_ci modepage = page_code; 28128c2ecf20Sopenharmony_ci goto Page_found; 28138c2ecf20Sopenharmony_ci } 28148c2ecf20Sopenharmony_ci } else { 28158c2ecf20Sopenharmony_ci /* Go to the next page */ 28168c2ecf20Sopenharmony_ci if (spf && len - offset > 3) 28178c2ecf20Sopenharmony_ci offset += 4 + (buffer[offset+2] << 8) + 28188c2ecf20Sopenharmony_ci buffer[offset+3]; 28198c2ecf20Sopenharmony_ci else if (!spf && len - offset > 1) 28208c2ecf20Sopenharmony_ci offset += 2 + buffer[offset+1]; 28218c2ecf20Sopenharmony_ci else { 28228c2ecf20Sopenharmony_ci sd_first_printk(KERN_ERR, sdkp, 28238c2ecf20Sopenharmony_ci "Incomplete mode " 28248c2ecf20Sopenharmony_ci "parameter data\n"); 28258c2ecf20Sopenharmony_ci goto defaults; 28268c2ecf20Sopenharmony_ci } 28278c2ecf20Sopenharmony_ci } 28288c2ecf20Sopenharmony_ci } 28298c2ecf20Sopenharmony_ci 28308c2ecf20Sopenharmony_ci sd_first_printk(KERN_ERR, sdkp, "No Caching mode page found\n"); 28318c2ecf20Sopenharmony_ci goto defaults; 28328c2ecf20Sopenharmony_ci 28338c2ecf20Sopenharmony_ci Page_found: 28348c2ecf20Sopenharmony_ci if (modepage == 8) { 28358c2ecf20Sopenharmony_ci sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); 28368c2ecf20Sopenharmony_ci sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); 28378c2ecf20Sopenharmony_ci } else { 28388c2ecf20Sopenharmony_ci sdkp->WCE = ((buffer[offset + 2] & 0x01) == 0); 28398c2ecf20Sopenharmony_ci sdkp->RCD = 0; 28408c2ecf20Sopenharmony_ci } 28418c2ecf20Sopenharmony_ci 28428c2ecf20Sopenharmony_ci sdkp->DPOFUA = (data.device_specific & 0x10) != 0; 28438c2ecf20Sopenharmony_ci if (sdp->broken_fua) { 28448c2ecf20Sopenharmony_ci sd_first_printk(KERN_NOTICE, sdkp, "Disabling FUA\n"); 28458c2ecf20Sopenharmony_ci sdkp->DPOFUA = 0; 28468c2ecf20Sopenharmony_ci } else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw && 28478c2ecf20Sopenharmony_ci !sdkp->device->use_16_for_rw) { 28488c2ecf20Sopenharmony_ci sd_first_printk(KERN_NOTICE, sdkp, 28498c2ecf20Sopenharmony_ci "Uses READ/WRITE(6), disabling FUA\n"); 28508c2ecf20Sopenharmony_ci sdkp->DPOFUA = 0; 28518c2ecf20Sopenharmony_ci } 28528c2ecf20Sopenharmony_ci 28538c2ecf20Sopenharmony_ci /* No cache flush allowed for write protected devices */ 28548c2ecf20Sopenharmony_ci if (sdkp->WCE && sdkp->write_prot) 28558c2ecf20Sopenharmony_ci sdkp->WCE = 0; 28568c2ecf20Sopenharmony_ci 28578c2ecf20Sopenharmony_ci if (sdkp->first_scan || old_wce != sdkp->WCE || 28588c2ecf20Sopenharmony_ci old_rcd != sdkp->RCD || old_dpofua != sdkp->DPOFUA) 28598c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 28608c2ecf20Sopenharmony_ci "Write cache: %s, read cache: %s, %s\n", 28618c2ecf20Sopenharmony_ci sdkp->WCE ? "enabled" : "disabled", 28628c2ecf20Sopenharmony_ci sdkp->RCD ? "disabled" : "enabled", 28638c2ecf20Sopenharmony_ci sdkp->DPOFUA ? "supports DPO and FUA" 28648c2ecf20Sopenharmony_ci : "doesn't support DPO or FUA"); 28658c2ecf20Sopenharmony_ci 28668c2ecf20Sopenharmony_ci return; 28678c2ecf20Sopenharmony_ci } 28688c2ecf20Sopenharmony_ci 28698c2ecf20Sopenharmony_cibad_sense: 28708c2ecf20Sopenharmony_ci if (scsi_sense_valid(&sshdr) && 28718c2ecf20Sopenharmony_ci sshdr.sense_key == ILLEGAL_REQUEST && 28728c2ecf20Sopenharmony_ci sshdr.asc == 0x24 && sshdr.ascq == 0x0) 28738c2ecf20Sopenharmony_ci /* Invalid field in CDB */ 28748c2ecf20Sopenharmony_ci sd_first_printk(KERN_NOTICE, sdkp, "Cache data unavailable\n"); 28758c2ecf20Sopenharmony_ci else 28768c2ecf20Sopenharmony_ci sd_first_printk(KERN_ERR, sdkp, 28778c2ecf20Sopenharmony_ci "Asking for cache data failed\n"); 28788c2ecf20Sopenharmony_ci 28798c2ecf20Sopenharmony_cidefaults: 28808c2ecf20Sopenharmony_ci if (sdp->wce_default_on) { 28818c2ecf20Sopenharmony_ci sd_first_printk(KERN_NOTICE, sdkp, 28828c2ecf20Sopenharmony_ci "Assuming drive cache: write back\n"); 28838c2ecf20Sopenharmony_ci sdkp->WCE = 1; 28848c2ecf20Sopenharmony_ci } else { 28858c2ecf20Sopenharmony_ci sd_first_printk(KERN_ERR, sdkp, 28868c2ecf20Sopenharmony_ci "Assuming drive cache: write through\n"); 28878c2ecf20Sopenharmony_ci sdkp->WCE = 0; 28888c2ecf20Sopenharmony_ci } 28898c2ecf20Sopenharmony_ci sdkp->RCD = 0; 28908c2ecf20Sopenharmony_ci sdkp->DPOFUA = 0; 28918c2ecf20Sopenharmony_ci} 28928c2ecf20Sopenharmony_ci 28938c2ecf20Sopenharmony_ci/* 28948c2ecf20Sopenharmony_ci * The ATO bit indicates whether the DIF application tag is available 28958c2ecf20Sopenharmony_ci * for use by the operating system. 28968c2ecf20Sopenharmony_ci */ 28978c2ecf20Sopenharmony_cistatic void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) 28988c2ecf20Sopenharmony_ci{ 28998c2ecf20Sopenharmony_ci int res, offset; 29008c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 29018c2ecf20Sopenharmony_ci struct scsi_mode_data data; 29028c2ecf20Sopenharmony_ci struct scsi_sense_hdr sshdr; 29038c2ecf20Sopenharmony_ci 29048c2ecf20Sopenharmony_ci if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC) 29058c2ecf20Sopenharmony_ci return; 29068c2ecf20Sopenharmony_ci 29078c2ecf20Sopenharmony_ci if (sdkp->protection_type == 0) 29088c2ecf20Sopenharmony_ci return; 29098c2ecf20Sopenharmony_ci 29108c2ecf20Sopenharmony_ci res = scsi_mode_sense(sdp, 1, 0x0a, buffer, 36, SD_TIMEOUT, 29118c2ecf20Sopenharmony_ci sdkp->max_retries, &data, &sshdr); 29128c2ecf20Sopenharmony_ci 29138c2ecf20Sopenharmony_ci if (res < 0 || !data.header_length || 29148c2ecf20Sopenharmony_ci data.length < 6) { 29158c2ecf20Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 29168c2ecf20Sopenharmony_ci "getting Control mode page failed, assume no ATO\n"); 29178c2ecf20Sopenharmony_ci 29188c2ecf20Sopenharmony_ci if (scsi_sense_valid(&sshdr)) 29198c2ecf20Sopenharmony_ci sd_print_sense_hdr(sdkp, &sshdr); 29208c2ecf20Sopenharmony_ci 29218c2ecf20Sopenharmony_ci return; 29228c2ecf20Sopenharmony_ci } 29238c2ecf20Sopenharmony_ci 29248c2ecf20Sopenharmony_ci offset = data.header_length + data.block_descriptor_length; 29258c2ecf20Sopenharmony_ci 29268c2ecf20Sopenharmony_ci if ((buffer[offset] & 0x3f) != 0x0a) { 29278c2ecf20Sopenharmony_ci sd_first_printk(KERN_ERR, sdkp, "ATO Got wrong page\n"); 29288c2ecf20Sopenharmony_ci return; 29298c2ecf20Sopenharmony_ci } 29308c2ecf20Sopenharmony_ci 29318c2ecf20Sopenharmony_ci if ((buffer[offset + 5] & 0x80) == 0) 29328c2ecf20Sopenharmony_ci return; 29338c2ecf20Sopenharmony_ci 29348c2ecf20Sopenharmony_ci sdkp->ATO = 1; 29358c2ecf20Sopenharmony_ci 29368c2ecf20Sopenharmony_ci return; 29378c2ecf20Sopenharmony_ci} 29388c2ecf20Sopenharmony_ci 29398c2ecf20Sopenharmony_ci/** 29408c2ecf20Sopenharmony_ci * sd_read_block_limits - Query disk device for preferred I/O sizes. 29418c2ecf20Sopenharmony_ci * @sdkp: disk to query 29428c2ecf20Sopenharmony_ci */ 29438c2ecf20Sopenharmony_cistatic void sd_read_block_limits(struct scsi_disk *sdkp) 29448c2ecf20Sopenharmony_ci{ 29458c2ecf20Sopenharmony_ci unsigned int sector_sz = sdkp->device->sector_size; 29468c2ecf20Sopenharmony_ci const int vpd_len = 64; 29478c2ecf20Sopenharmony_ci unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL); 29488c2ecf20Sopenharmony_ci 29498c2ecf20Sopenharmony_ci if (!buffer || 29508c2ecf20Sopenharmony_ci /* Block Limits VPD */ 29518c2ecf20Sopenharmony_ci scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len)) 29528c2ecf20Sopenharmony_ci goto out; 29538c2ecf20Sopenharmony_ci 29548c2ecf20Sopenharmony_ci blk_queue_io_min(sdkp->disk->queue, 29558c2ecf20Sopenharmony_ci get_unaligned_be16(&buffer[6]) * sector_sz); 29568c2ecf20Sopenharmony_ci 29578c2ecf20Sopenharmony_ci sdkp->max_xfer_blocks = get_unaligned_be32(&buffer[8]); 29588c2ecf20Sopenharmony_ci sdkp->opt_xfer_blocks = get_unaligned_be32(&buffer[12]); 29598c2ecf20Sopenharmony_ci 29608c2ecf20Sopenharmony_ci if (buffer[3] == 0x3c) { 29618c2ecf20Sopenharmony_ci unsigned int lba_count, desc_count; 29628c2ecf20Sopenharmony_ci 29638c2ecf20Sopenharmony_ci sdkp->max_ws_blocks = (u32)get_unaligned_be64(&buffer[36]); 29648c2ecf20Sopenharmony_ci 29658c2ecf20Sopenharmony_ci if (!sdkp->lbpme) 29668c2ecf20Sopenharmony_ci goto out; 29678c2ecf20Sopenharmony_ci 29688c2ecf20Sopenharmony_ci lba_count = get_unaligned_be32(&buffer[20]); 29698c2ecf20Sopenharmony_ci desc_count = get_unaligned_be32(&buffer[24]); 29708c2ecf20Sopenharmony_ci 29718c2ecf20Sopenharmony_ci if (lba_count && desc_count) 29728c2ecf20Sopenharmony_ci sdkp->max_unmap_blocks = lba_count; 29738c2ecf20Sopenharmony_ci 29748c2ecf20Sopenharmony_ci sdkp->unmap_granularity = get_unaligned_be32(&buffer[28]); 29758c2ecf20Sopenharmony_ci 29768c2ecf20Sopenharmony_ci if (buffer[32] & 0x80) 29778c2ecf20Sopenharmony_ci sdkp->unmap_alignment = 29788c2ecf20Sopenharmony_ci get_unaligned_be32(&buffer[32]) & ~(1 << 31); 29798c2ecf20Sopenharmony_ci 29808c2ecf20Sopenharmony_ci if (!sdkp->lbpvpd) { /* LBP VPD page not provided */ 29818c2ecf20Sopenharmony_ci 29828c2ecf20Sopenharmony_ci if (sdkp->max_unmap_blocks) 29838c2ecf20Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_UNMAP); 29848c2ecf20Sopenharmony_ci else 29858c2ecf20Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_WS16); 29868c2ecf20Sopenharmony_ci 29878c2ecf20Sopenharmony_ci } else { /* LBP VPD page tells us what to use */ 29888c2ecf20Sopenharmony_ci if (sdkp->lbpu && sdkp->max_unmap_blocks) 29898c2ecf20Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_UNMAP); 29908c2ecf20Sopenharmony_ci else if (sdkp->lbpws) 29918c2ecf20Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_WS16); 29928c2ecf20Sopenharmony_ci else if (sdkp->lbpws10) 29938c2ecf20Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_WS10); 29948c2ecf20Sopenharmony_ci else 29958c2ecf20Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_DISABLE); 29968c2ecf20Sopenharmony_ci } 29978c2ecf20Sopenharmony_ci } 29988c2ecf20Sopenharmony_ci 29998c2ecf20Sopenharmony_ci out: 30008c2ecf20Sopenharmony_ci kfree(buffer); 30018c2ecf20Sopenharmony_ci} 30028c2ecf20Sopenharmony_ci 30038c2ecf20Sopenharmony_ci/** 30048c2ecf20Sopenharmony_ci * sd_read_block_characteristics - Query block dev. characteristics 30058c2ecf20Sopenharmony_ci * @sdkp: disk to query 30068c2ecf20Sopenharmony_ci */ 30078c2ecf20Sopenharmony_cistatic void sd_read_block_characteristics(struct scsi_disk *sdkp) 30088c2ecf20Sopenharmony_ci{ 30098c2ecf20Sopenharmony_ci struct request_queue *q = sdkp->disk->queue; 30108c2ecf20Sopenharmony_ci unsigned char *buffer; 30118c2ecf20Sopenharmony_ci u16 rot; 30128c2ecf20Sopenharmony_ci const int vpd_len = 64; 30138c2ecf20Sopenharmony_ci 30148c2ecf20Sopenharmony_ci buffer = kmalloc(vpd_len, GFP_KERNEL); 30158c2ecf20Sopenharmony_ci 30168c2ecf20Sopenharmony_ci if (!buffer || 30178c2ecf20Sopenharmony_ci /* Block Device Characteristics VPD */ 30188c2ecf20Sopenharmony_ci scsi_get_vpd_page(sdkp->device, 0xb1, buffer, vpd_len)) 30198c2ecf20Sopenharmony_ci goto out; 30208c2ecf20Sopenharmony_ci 30218c2ecf20Sopenharmony_ci rot = get_unaligned_be16(&buffer[4]); 30228c2ecf20Sopenharmony_ci 30238c2ecf20Sopenharmony_ci if (rot == 1) { 30248c2ecf20Sopenharmony_ci blk_queue_flag_set(QUEUE_FLAG_NONROT, q); 30258c2ecf20Sopenharmony_ci blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q); 30268c2ecf20Sopenharmony_ci } 30278c2ecf20Sopenharmony_ci 30288c2ecf20Sopenharmony_ci if (sdkp->device->type == TYPE_ZBC) { 30298c2ecf20Sopenharmony_ci /* Host-managed */ 30308c2ecf20Sopenharmony_ci blk_queue_set_zoned(sdkp->disk, BLK_ZONED_HM); 30318c2ecf20Sopenharmony_ci } else { 30328c2ecf20Sopenharmony_ci sdkp->zoned = (buffer[8] >> 4) & 3; 30338c2ecf20Sopenharmony_ci if (sdkp->zoned == 1) { 30348c2ecf20Sopenharmony_ci /* Host-aware */ 30358c2ecf20Sopenharmony_ci blk_queue_set_zoned(sdkp->disk, BLK_ZONED_HA); 30368c2ecf20Sopenharmony_ci } else { 30378c2ecf20Sopenharmony_ci /* Regular disk or drive managed disk */ 30388c2ecf20Sopenharmony_ci blk_queue_set_zoned(sdkp->disk, BLK_ZONED_NONE); 30398c2ecf20Sopenharmony_ci } 30408c2ecf20Sopenharmony_ci } 30418c2ecf20Sopenharmony_ci 30428c2ecf20Sopenharmony_ci if (!sdkp->first_scan) 30438c2ecf20Sopenharmony_ci goto out; 30448c2ecf20Sopenharmony_ci 30458c2ecf20Sopenharmony_ci if (blk_queue_is_zoned(q)) { 30468c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Host-%s zoned block device\n", 30478c2ecf20Sopenharmony_ci q->limits.zoned == BLK_ZONED_HM ? "managed" : "aware"); 30488c2ecf20Sopenharmony_ci } else { 30498c2ecf20Sopenharmony_ci if (sdkp->zoned == 1) 30508c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 30518c2ecf20Sopenharmony_ci "Host-aware SMR disk used as regular disk\n"); 30528c2ecf20Sopenharmony_ci else if (sdkp->zoned == 2) 30538c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 30548c2ecf20Sopenharmony_ci "Drive-managed SMR disk\n"); 30558c2ecf20Sopenharmony_ci } 30568c2ecf20Sopenharmony_ci 30578c2ecf20Sopenharmony_ci out: 30588c2ecf20Sopenharmony_ci kfree(buffer); 30598c2ecf20Sopenharmony_ci} 30608c2ecf20Sopenharmony_ci 30618c2ecf20Sopenharmony_ci/** 30628c2ecf20Sopenharmony_ci * sd_read_block_provisioning - Query provisioning VPD page 30638c2ecf20Sopenharmony_ci * @sdkp: disk to query 30648c2ecf20Sopenharmony_ci */ 30658c2ecf20Sopenharmony_cistatic void sd_read_block_provisioning(struct scsi_disk *sdkp) 30668c2ecf20Sopenharmony_ci{ 30678c2ecf20Sopenharmony_ci unsigned char *buffer; 30688c2ecf20Sopenharmony_ci const int vpd_len = 8; 30698c2ecf20Sopenharmony_ci 30708c2ecf20Sopenharmony_ci if (sdkp->lbpme == 0) 30718c2ecf20Sopenharmony_ci return; 30728c2ecf20Sopenharmony_ci 30738c2ecf20Sopenharmony_ci buffer = kmalloc(vpd_len, GFP_KERNEL); 30748c2ecf20Sopenharmony_ci 30758c2ecf20Sopenharmony_ci if (!buffer || scsi_get_vpd_page(sdkp->device, 0xb2, buffer, vpd_len)) 30768c2ecf20Sopenharmony_ci goto out; 30778c2ecf20Sopenharmony_ci 30788c2ecf20Sopenharmony_ci sdkp->lbpvpd = 1; 30798c2ecf20Sopenharmony_ci sdkp->lbpu = (buffer[5] >> 7) & 1; /* UNMAP */ 30808c2ecf20Sopenharmony_ci sdkp->lbpws = (buffer[5] >> 6) & 1; /* WRITE SAME(16) with UNMAP */ 30818c2ecf20Sopenharmony_ci sdkp->lbpws10 = (buffer[5] >> 5) & 1; /* WRITE SAME(10) with UNMAP */ 30828c2ecf20Sopenharmony_ci 30838c2ecf20Sopenharmony_ci out: 30848c2ecf20Sopenharmony_ci kfree(buffer); 30858c2ecf20Sopenharmony_ci} 30868c2ecf20Sopenharmony_ci 30878c2ecf20Sopenharmony_cistatic void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) 30888c2ecf20Sopenharmony_ci{ 30898c2ecf20Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 30908c2ecf20Sopenharmony_ci 30918c2ecf20Sopenharmony_ci if (sdev->host->no_write_same) { 30928c2ecf20Sopenharmony_ci sdev->no_write_same = 1; 30938c2ecf20Sopenharmony_ci 30948c2ecf20Sopenharmony_ci return; 30958c2ecf20Sopenharmony_ci } 30968c2ecf20Sopenharmony_ci 30978c2ecf20Sopenharmony_ci if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) { 30988c2ecf20Sopenharmony_ci /* too large values might cause issues with arcmsr */ 30998c2ecf20Sopenharmony_ci int vpd_buf_len = 64; 31008c2ecf20Sopenharmony_ci 31018c2ecf20Sopenharmony_ci sdev->no_report_opcodes = 1; 31028c2ecf20Sopenharmony_ci 31038c2ecf20Sopenharmony_ci /* Disable WRITE SAME if REPORT SUPPORTED OPERATION 31048c2ecf20Sopenharmony_ci * CODES is unsupported and the device has an ATA 31058c2ecf20Sopenharmony_ci * Information VPD page (SAT). 31068c2ecf20Sopenharmony_ci */ 31078c2ecf20Sopenharmony_ci if (!scsi_get_vpd_page(sdev, 0x89, buffer, vpd_buf_len)) 31088c2ecf20Sopenharmony_ci sdev->no_write_same = 1; 31098c2ecf20Sopenharmony_ci } 31108c2ecf20Sopenharmony_ci 31118c2ecf20Sopenharmony_ci if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16) == 1) 31128c2ecf20Sopenharmony_ci sdkp->ws16 = 1; 31138c2ecf20Sopenharmony_ci 31148c2ecf20Sopenharmony_ci if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME) == 1) 31158c2ecf20Sopenharmony_ci sdkp->ws10 = 1; 31168c2ecf20Sopenharmony_ci} 31178c2ecf20Sopenharmony_ci 31188c2ecf20Sopenharmony_cistatic void sd_read_security(struct scsi_disk *sdkp, unsigned char *buffer) 31198c2ecf20Sopenharmony_ci{ 31208c2ecf20Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 31218c2ecf20Sopenharmony_ci 31228c2ecf20Sopenharmony_ci if (!sdev->security_supported) 31238c2ecf20Sopenharmony_ci return; 31248c2ecf20Sopenharmony_ci 31258c2ecf20Sopenharmony_ci if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, 31268c2ecf20Sopenharmony_ci SECURITY_PROTOCOL_IN) == 1 && 31278c2ecf20Sopenharmony_ci scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, 31288c2ecf20Sopenharmony_ci SECURITY_PROTOCOL_OUT) == 1) 31298c2ecf20Sopenharmony_ci sdkp->security = 1; 31308c2ecf20Sopenharmony_ci} 31318c2ecf20Sopenharmony_ci 31328c2ecf20Sopenharmony_ci/* 31338c2ecf20Sopenharmony_ci * Determine the device's preferred I/O size for reads and writes 31348c2ecf20Sopenharmony_ci * unless the reported value is unreasonably small, large, not a 31358c2ecf20Sopenharmony_ci * multiple of the physical block size, or simply garbage. 31368c2ecf20Sopenharmony_ci */ 31378c2ecf20Sopenharmony_cistatic bool sd_validate_opt_xfer_size(struct scsi_disk *sdkp, 31388c2ecf20Sopenharmony_ci unsigned int dev_max) 31398c2ecf20Sopenharmony_ci{ 31408c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 31418c2ecf20Sopenharmony_ci unsigned int opt_xfer_bytes = 31428c2ecf20Sopenharmony_ci logical_to_bytes(sdp, sdkp->opt_xfer_blocks); 31438c2ecf20Sopenharmony_ci 31448c2ecf20Sopenharmony_ci if (sdkp->opt_xfer_blocks == 0) 31458c2ecf20Sopenharmony_ci return false; 31468c2ecf20Sopenharmony_ci 31478c2ecf20Sopenharmony_ci if (sdkp->opt_xfer_blocks > dev_max) { 31488c2ecf20Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 31498c2ecf20Sopenharmony_ci "Optimal transfer size %u logical blocks " \ 31508c2ecf20Sopenharmony_ci "> dev_max (%u logical blocks)\n", 31518c2ecf20Sopenharmony_ci sdkp->opt_xfer_blocks, dev_max); 31528c2ecf20Sopenharmony_ci return false; 31538c2ecf20Sopenharmony_ci } 31548c2ecf20Sopenharmony_ci 31558c2ecf20Sopenharmony_ci if (sdkp->opt_xfer_blocks > SD_DEF_XFER_BLOCKS) { 31568c2ecf20Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 31578c2ecf20Sopenharmony_ci "Optimal transfer size %u logical blocks " \ 31588c2ecf20Sopenharmony_ci "> sd driver limit (%u logical blocks)\n", 31598c2ecf20Sopenharmony_ci sdkp->opt_xfer_blocks, SD_DEF_XFER_BLOCKS); 31608c2ecf20Sopenharmony_ci return false; 31618c2ecf20Sopenharmony_ci } 31628c2ecf20Sopenharmony_ci 31638c2ecf20Sopenharmony_ci if (opt_xfer_bytes < PAGE_SIZE) { 31648c2ecf20Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 31658c2ecf20Sopenharmony_ci "Optimal transfer size %u bytes < " \ 31668c2ecf20Sopenharmony_ci "PAGE_SIZE (%u bytes)\n", 31678c2ecf20Sopenharmony_ci opt_xfer_bytes, (unsigned int)PAGE_SIZE); 31688c2ecf20Sopenharmony_ci return false; 31698c2ecf20Sopenharmony_ci } 31708c2ecf20Sopenharmony_ci 31718c2ecf20Sopenharmony_ci if (opt_xfer_bytes & (sdkp->physical_block_size - 1)) { 31728c2ecf20Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 31738c2ecf20Sopenharmony_ci "Optimal transfer size %u bytes not a " \ 31748c2ecf20Sopenharmony_ci "multiple of physical block size (%u bytes)\n", 31758c2ecf20Sopenharmony_ci opt_xfer_bytes, sdkp->physical_block_size); 31768c2ecf20Sopenharmony_ci return false; 31778c2ecf20Sopenharmony_ci } 31788c2ecf20Sopenharmony_ci 31798c2ecf20Sopenharmony_ci sd_first_printk(KERN_INFO, sdkp, "Optimal transfer size %u bytes\n", 31808c2ecf20Sopenharmony_ci opt_xfer_bytes); 31818c2ecf20Sopenharmony_ci return true; 31828c2ecf20Sopenharmony_ci} 31838c2ecf20Sopenharmony_ci 31848c2ecf20Sopenharmony_ci/** 31858c2ecf20Sopenharmony_ci * sd_revalidate_disk - called the first time a new disk is seen, 31868c2ecf20Sopenharmony_ci * performs disk spin up, read_capacity, etc. 31878c2ecf20Sopenharmony_ci * @disk: struct gendisk we care about 31888c2ecf20Sopenharmony_ci **/ 31898c2ecf20Sopenharmony_cistatic int sd_revalidate_disk(struct gendisk *disk) 31908c2ecf20Sopenharmony_ci{ 31918c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(disk); 31928c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 31938c2ecf20Sopenharmony_ci struct request_queue *q = sdkp->disk->queue; 31948c2ecf20Sopenharmony_ci sector_t old_capacity = sdkp->capacity; 31958c2ecf20Sopenharmony_ci unsigned char *buffer; 31968c2ecf20Sopenharmony_ci unsigned int dev_max, rw_max; 31978c2ecf20Sopenharmony_ci 31988c2ecf20Sopenharmony_ci SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, 31998c2ecf20Sopenharmony_ci "sd_revalidate_disk\n")); 32008c2ecf20Sopenharmony_ci 32018c2ecf20Sopenharmony_ci /* 32028c2ecf20Sopenharmony_ci * If the device is offline, don't try and read capacity or any 32038c2ecf20Sopenharmony_ci * of the other niceties. 32048c2ecf20Sopenharmony_ci */ 32058c2ecf20Sopenharmony_ci if (!scsi_device_online(sdp)) 32068c2ecf20Sopenharmony_ci goto out; 32078c2ecf20Sopenharmony_ci 32088c2ecf20Sopenharmony_ci buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL); 32098c2ecf20Sopenharmony_ci if (!buffer) { 32108c2ecf20Sopenharmony_ci sd_printk(KERN_WARNING, sdkp, "sd_revalidate_disk: Memory " 32118c2ecf20Sopenharmony_ci "allocation failure.\n"); 32128c2ecf20Sopenharmony_ci goto out; 32138c2ecf20Sopenharmony_ci } 32148c2ecf20Sopenharmony_ci 32158c2ecf20Sopenharmony_ci sd_spinup_disk(sdkp); 32168c2ecf20Sopenharmony_ci 32178c2ecf20Sopenharmony_ci /* 32188c2ecf20Sopenharmony_ci * Without media there is no reason to ask; moreover, some devices 32198c2ecf20Sopenharmony_ci * react badly if we do. 32208c2ecf20Sopenharmony_ci */ 32218c2ecf20Sopenharmony_ci if (sdkp->media_present) { 32228c2ecf20Sopenharmony_ci sd_read_capacity(sdkp, buffer); 32238c2ecf20Sopenharmony_ci 32248c2ecf20Sopenharmony_ci /* 32258c2ecf20Sopenharmony_ci * set the default to rotational. All non-rotational devices 32268c2ecf20Sopenharmony_ci * support the block characteristics VPD page, which will 32278c2ecf20Sopenharmony_ci * cause this to be updated correctly and any device which 32288c2ecf20Sopenharmony_ci * doesn't support it should be treated as rotational. 32298c2ecf20Sopenharmony_ci */ 32308c2ecf20Sopenharmony_ci blk_queue_flag_clear(QUEUE_FLAG_NONROT, q); 32318c2ecf20Sopenharmony_ci blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q); 32328c2ecf20Sopenharmony_ci 32338c2ecf20Sopenharmony_ci if (scsi_device_supports_vpd(sdp)) { 32348c2ecf20Sopenharmony_ci sd_read_block_provisioning(sdkp); 32358c2ecf20Sopenharmony_ci sd_read_block_limits(sdkp); 32368c2ecf20Sopenharmony_ci sd_read_block_characteristics(sdkp); 32378c2ecf20Sopenharmony_ci sd_zbc_read_zones(sdkp, buffer); 32388c2ecf20Sopenharmony_ci } 32398c2ecf20Sopenharmony_ci 32408c2ecf20Sopenharmony_ci sd_print_capacity(sdkp, old_capacity); 32418c2ecf20Sopenharmony_ci 32428c2ecf20Sopenharmony_ci sd_read_write_protect_flag(sdkp, buffer); 32438c2ecf20Sopenharmony_ci sd_read_cache_type(sdkp, buffer); 32448c2ecf20Sopenharmony_ci sd_read_app_tag_own(sdkp, buffer); 32458c2ecf20Sopenharmony_ci sd_read_write_same(sdkp, buffer); 32468c2ecf20Sopenharmony_ci sd_read_security(sdkp, buffer); 32478c2ecf20Sopenharmony_ci } 32488c2ecf20Sopenharmony_ci 32498c2ecf20Sopenharmony_ci /* 32508c2ecf20Sopenharmony_ci * We now have all cache related info, determine how we deal 32518c2ecf20Sopenharmony_ci * with flush requests. 32528c2ecf20Sopenharmony_ci */ 32538c2ecf20Sopenharmony_ci sd_set_flush_flag(sdkp); 32548c2ecf20Sopenharmony_ci 32558c2ecf20Sopenharmony_ci /* Initial block count limit based on CDB TRANSFER LENGTH field size. */ 32568c2ecf20Sopenharmony_ci dev_max = sdp->use_16_for_rw ? SD_MAX_XFER_BLOCKS : SD_DEF_XFER_BLOCKS; 32578c2ecf20Sopenharmony_ci 32588c2ecf20Sopenharmony_ci /* Some devices report a maximum block count for READ/WRITE requests. */ 32598c2ecf20Sopenharmony_ci dev_max = min_not_zero(dev_max, sdkp->max_xfer_blocks); 32608c2ecf20Sopenharmony_ci q->limits.max_dev_sectors = logical_to_sectors(sdp, dev_max); 32618c2ecf20Sopenharmony_ci 32628c2ecf20Sopenharmony_ci if (sd_validate_opt_xfer_size(sdkp, dev_max)) { 32638c2ecf20Sopenharmony_ci q->limits.io_opt = logical_to_bytes(sdp, sdkp->opt_xfer_blocks); 32648c2ecf20Sopenharmony_ci rw_max = logical_to_sectors(sdp, sdkp->opt_xfer_blocks); 32658c2ecf20Sopenharmony_ci } else { 32668c2ecf20Sopenharmony_ci q->limits.io_opt = 0; 32678c2ecf20Sopenharmony_ci rw_max = min_not_zero(logical_to_sectors(sdp, dev_max), 32688c2ecf20Sopenharmony_ci (sector_t)BLK_DEF_MAX_SECTORS); 32698c2ecf20Sopenharmony_ci } 32708c2ecf20Sopenharmony_ci 32718c2ecf20Sopenharmony_ci /* Do not exceed controller limit */ 32728c2ecf20Sopenharmony_ci rw_max = min(rw_max, queue_max_hw_sectors(q)); 32738c2ecf20Sopenharmony_ci 32748c2ecf20Sopenharmony_ci /* 32758c2ecf20Sopenharmony_ci * Only update max_sectors if previously unset or if the current value 32768c2ecf20Sopenharmony_ci * exceeds the capabilities of the hardware. 32778c2ecf20Sopenharmony_ci */ 32788c2ecf20Sopenharmony_ci if (sdkp->first_scan || 32798c2ecf20Sopenharmony_ci q->limits.max_sectors > q->limits.max_dev_sectors || 32808c2ecf20Sopenharmony_ci q->limits.max_sectors > q->limits.max_hw_sectors) 32818c2ecf20Sopenharmony_ci q->limits.max_sectors = rw_max; 32828c2ecf20Sopenharmony_ci 32838c2ecf20Sopenharmony_ci sdkp->first_scan = 0; 32848c2ecf20Sopenharmony_ci 32858c2ecf20Sopenharmony_ci set_capacity_revalidate_and_notify(disk, 32868c2ecf20Sopenharmony_ci logical_to_sectors(sdp, sdkp->capacity), false); 32878c2ecf20Sopenharmony_ci sd_config_write_same(sdkp); 32888c2ecf20Sopenharmony_ci kfree(buffer); 32898c2ecf20Sopenharmony_ci 32908c2ecf20Sopenharmony_ci /* 32918c2ecf20Sopenharmony_ci * For a zoned drive, revalidating the zones can be done only once 32928c2ecf20Sopenharmony_ci * the gendisk capacity is set. So if this fails, set back the gendisk 32938c2ecf20Sopenharmony_ci * capacity to 0. 32948c2ecf20Sopenharmony_ci */ 32958c2ecf20Sopenharmony_ci if (sd_zbc_revalidate_zones(sdkp)) 32968c2ecf20Sopenharmony_ci set_capacity_revalidate_and_notify(disk, 0, false); 32978c2ecf20Sopenharmony_ci 32988c2ecf20Sopenharmony_ci out: 32998c2ecf20Sopenharmony_ci return 0; 33008c2ecf20Sopenharmony_ci} 33018c2ecf20Sopenharmony_ci 33028c2ecf20Sopenharmony_ci/** 33038c2ecf20Sopenharmony_ci * sd_unlock_native_capacity - unlock native capacity 33048c2ecf20Sopenharmony_ci * @disk: struct gendisk to set capacity for 33058c2ecf20Sopenharmony_ci * 33068c2ecf20Sopenharmony_ci * Block layer calls this function if it detects that partitions 33078c2ecf20Sopenharmony_ci * on @disk reach beyond the end of the device. If the SCSI host 33088c2ecf20Sopenharmony_ci * implements ->unlock_native_capacity() method, it's invoked to 33098c2ecf20Sopenharmony_ci * give it a chance to adjust the device capacity. 33108c2ecf20Sopenharmony_ci * 33118c2ecf20Sopenharmony_ci * CONTEXT: 33128c2ecf20Sopenharmony_ci * Defined by block layer. Might sleep. 33138c2ecf20Sopenharmony_ci */ 33148c2ecf20Sopenharmony_cistatic void sd_unlock_native_capacity(struct gendisk *disk) 33158c2ecf20Sopenharmony_ci{ 33168c2ecf20Sopenharmony_ci struct scsi_device *sdev = scsi_disk(disk)->device; 33178c2ecf20Sopenharmony_ci 33188c2ecf20Sopenharmony_ci if (sdev->host->hostt->unlock_native_capacity) 33198c2ecf20Sopenharmony_ci sdev->host->hostt->unlock_native_capacity(sdev); 33208c2ecf20Sopenharmony_ci} 33218c2ecf20Sopenharmony_ci 33228c2ecf20Sopenharmony_ci/** 33238c2ecf20Sopenharmony_ci * sd_format_disk_name - format disk name 33248c2ecf20Sopenharmony_ci * @prefix: name prefix - ie. "sd" for SCSI disks 33258c2ecf20Sopenharmony_ci * @index: index of the disk to format name for 33268c2ecf20Sopenharmony_ci * @buf: output buffer 33278c2ecf20Sopenharmony_ci * @buflen: length of the output buffer 33288c2ecf20Sopenharmony_ci * 33298c2ecf20Sopenharmony_ci * SCSI disk names starts at sda. The 26th device is sdz and the 33308c2ecf20Sopenharmony_ci * 27th is sdaa. The last one for two lettered suffix is sdzz 33318c2ecf20Sopenharmony_ci * which is followed by sdaaa. 33328c2ecf20Sopenharmony_ci * 33338c2ecf20Sopenharmony_ci * This is basically 26 base counting with one extra 'nil' entry 33348c2ecf20Sopenharmony_ci * at the beginning from the second digit on and can be 33358c2ecf20Sopenharmony_ci * determined using similar method as 26 base conversion with the 33368c2ecf20Sopenharmony_ci * index shifted -1 after each digit is computed. 33378c2ecf20Sopenharmony_ci * 33388c2ecf20Sopenharmony_ci * CONTEXT: 33398c2ecf20Sopenharmony_ci * Don't care. 33408c2ecf20Sopenharmony_ci * 33418c2ecf20Sopenharmony_ci * RETURNS: 33428c2ecf20Sopenharmony_ci * 0 on success, -errno on failure. 33438c2ecf20Sopenharmony_ci */ 33448c2ecf20Sopenharmony_cistatic int sd_format_disk_name(char *prefix, int index, char *buf, int buflen) 33458c2ecf20Sopenharmony_ci{ 33468c2ecf20Sopenharmony_ci const int base = 'z' - 'a' + 1; 33478c2ecf20Sopenharmony_ci char *begin = buf + strlen(prefix); 33488c2ecf20Sopenharmony_ci char *end = buf + buflen; 33498c2ecf20Sopenharmony_ci char *p; 33508c2ecf20Sopenharmony_ci int unit; 33518c2ecf20Sopenharmony_ci 33528c2ecf20Sopenharmony_ci p = end - 1; 33538c2ecf20Sopenharmony_ci *p = '\0'; 33548c2ecf20Sopenharmony_ci unit = base; 33558c2ecf20Sopenharmony_ci do { 33568c2ecf20Sopenharmony_ci if (p == begin) 33578c2ecf20Sopenharmony_ci return -EINVAL; 33588c2ecf20Sopenharmony_ci *--p = 'a' + (index % unit); 33598c2ecf20Sopenharmony_ci index = (index / unit) - 1; 33608c2ecf20Sopenharmony_ci } while (index >= 0); 33618c2ecf20Sopenharmony_ci 33628c2ecf20Sopenharmony_ci memmove(begin, p, end - p); 33638c2ecf20Sopenharmony_ci memcpy(buf, prefix, strlen(prefix)); 33648c2ecf20Sopenharmony_ci 33658c2ecf20Sopenharmony_ci return 0; 33668c2ecf20Sopenharmony_ci} 33678c2ecf20Sopenharmony_ci 33688c2ecf20Sopenharmony_ci/** 33698c2ecf20Sopenharmony_ci * sd_probe - called during driver initialization and whenever a 33708c2ecf20Sopenharmony_ci * new scsi device is attached to the system. It is called once 33718c2ecf20Sopenharmony_ci * for each scsi device (not just disks) present. 33728c2ecf20Sopenharmony_ci * @dev: pointer to device object 33738c2ecf20Sopenharmony_ci * 33748c2ecf20Sopenharmony_ci * Returns 0 if successful (or not interested in this scsi device 33758c2ecf20Sopenharmony_ci * (e.g. scanner)); 1 when there is an error. 33768c2ecf20Sopenharmony_ci * 33778c2ecf20Sopenharmony_ci * Note: this function is invoked from the scsi mid-level. 33788c2ecf20Sopenharmony_ci * This function sets up the mapping between a given 33798c2ecf20Sopenharmony_ci * <host,channel,id,lun> (found in sdp) and new device name 33808c2ecf20Sopenharmony_ci * (e.g. /dev/sda). More precisely it is the block device major 33818c2ecf20Sopenharmony_ci * and minor number that is chosen here. 33828c2ecf20Sopenharmony_ci * 33838c2ecf20Sopenharmony_ci * Assume sd_probe is not re-entrant (for time being) 33848c2ecf20Sopenharmony_ci * Also think about sd_probe() and sd_remove() running coincidentally. 33858c2ecf20Sopenharmony_ci **/ 33868c2ecf20Sopenharmony_cistatic int sd_probe(struct device *dev) 33878c2ecf20Sopenharmony_ci{ 33888c2ecf20Sopenharmony_ci struct scsi_device *sdp = to_scsi_device(dev); 33898c2ecf20Sopenharmony_ci struct scsi_disk *sdkp; 33908c2ecf20Sopenharmony_ci struct gendisk *gd; 33918c2ecf20Sopenharmony_ci int index; 33928c2ecf20Sopenharmony_ci int error; 33938c2ecf20Sopenharmony_ci 33948c2ecf20Sopenharmony_ci scsi_autopm_get_device(sdp); 33958c2ecf20Sopenharmony_ci error = -ENODEV; 33968c2ecf20Sopenharmony_ci if (sdp->type != TYPE_DISK && 33978c2ecf20Sopenharmony_ci sdp->type != TYPE_ZBC && 33988c2ecf20Sopenharmony_ci sdp->type != TYPE_MOD && 33998c2ecf20Sopenharmony_ci sdp->type != TYPE_RBC) 34008c2ecf20Sopenharmony_ci goto out; 34018c2ecf20Sopenharmony_ci 34028c2ecf20Sopenharmony_ci#ifndef CONFIG_BLK_DEV_ZONED 34038c2ecf20Sopenharmony_ci if (sdp->type == TYPE_ZBC) 34048c2ecf20Sopenharmony_ci goto out; 34058c2ecf20Sopenharmony_ci#endif 34068c2ecf20Sopenharmony_ci SCSI_LOG_HLQUEUE(3, sdev_printk(KERN_INFO, sdp, 34078c2ecf20Sopenharmony_ci "sd_probe\n")); 34088c2ecf20Sopenharmony_ci 34098c2ecf20Sopenharmony_ci error = -ENOMEM; 34108c2ecf20Sopenharmony_ci sdkp = kzalloc(sizeof(*sdkp), GFP_KERNEL); 34118c2ecf20Sopenharmony_ci if (!sdkp) 34128c2ecf20Sopenharmony_ci goto out; 34138c2ecf20Sopenharmony_ci 34148c2ecf20Sopenharmony_ci gd = alloc_disk(SD_MINORS); 34158c2ecf20Sopenharmony_ci if (!gd) 34168c2ecf20Sopenharmony_ci goto out_free; 34178c2ecf20Sopenharmony_ci 34188c2ecf20Sopenharmony_ci index = ida_alloc(&sd_index_ida, GFP_KERNEL); 34198c2ecf20Sopenharmony_ci if (index < 0) { 34208c2ecf20Sopenharmony_ci sdev_printk(KERN_WARNING, sdp, "sd_probe: memory exhausted.\n"); 34218c2ecf20Sopenharmony_ci goto out_put; 34228c2ecf20Sopenharmony_ci } 34238c2ecf20Sopenharmony_ci 34248c2ecf20Sopenharmony_ci error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN); 34258c2ecf20Sopenharmony_ci if (error) { 34268c2ecf20Sopenharmony_ci sdev_printk(KERN_WARNING, sdp, "SCSI disk (sd) name length exceeded.\n"); 34278c2ecf20Sopenharmony_ci goto out_free_index; 34288c2ecf20Sopenharmony_ci } 34298c2ecf20Sopenharmony_ci 34308c2ecf20Sopenharmony_ci sdkp->device = sdp; 34318c2ecf20Sopenharmony_ci sdkp->driver = &sd_template; 34328c2ecf20Sopenharmony_ci sdkp->disk = gd; 34338c2ecf20Sopenharmony_ci sdkp->index = index; 34348c2ecf20Sopenharmony_ci sdkp->max_retries = SD_MAX_RETRIES; 34358c2ecf20Sopenharmony_ci atomic_set(&sdkp->openers, 0); 34368c2ecf20Sopenharmony_ci atomic_set(&sdkp->device->ioerr_cnt, 0); 34378c2ecf20Sopenharmony_ci 34388c2ecf20Sopenharmony_ci if (!sdp->request_queue->rq_timeout) { 34398c2ecf20Sopenharmony_ci if (sdp->type != TYPE_MOD) 34408c2ecf20Sopenharmony_ci blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT); 34418c2ecf20Sopenharmony_ci else 34428c2ecf20Sopenharmony_ci blk_queue_rq_timeout(sdp->request_queue, 34438c2ecf20Sopenharmony_ci SD_MOD_TIMEOUT); 34448c2ecf20Sopenharmony_ci } 34458c2ecf20Sopenharmony_ci 34468c2ecf20Sopenharmony_ci device_initialize(&sdkp->dev); 34478c2ecf20Sopenharmony_ci sdkp->dev.parent = get_device(dev); 34488c2ecf20Sopenharmony_ci sdkp->dev.class = &sd_disk_class; 34498c2ecf20Sopenharmony_ci dev_set_name(&sdkp->dev, "%s", dev_name(dev)); 34508c2ecf20Sopenharmony_ci 34518c2ecf20Sopenharmony_ci error = device_add(&sdkp->dev); 34528c2ecf20Sopenharmony_ci if (error) { 34538c2ecf20Sopenharmony_ci put_device(&sdkp->dev); 34548c2ecf20Sopenharmony_ci goto out; 34558c2ecf20Sopenharmony_ci } 34568c2ecf20Sopenharmony_ci 34578c2ecf20Sopenharmony_ci dev_set_drvdata(dev, sdkp); 34588c2ecf20Sopenharmony_ci 34598c2ecf20Sopenharmony_ci gd->major = sd_major((index & 0xf0) >> 4); 34608c2ecf20Sopenharmony_ci gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); 34618c2ecf20Sopenharmony_ci 34628c2ecf20Sopenharmony_ci gd->fops = &sd_fops; 34638c2ecf20Sopenharmony_ci gd->private_data = &sdkp->driver; 34648c2ecf20Sopenharmony_ci gd->queue = sdkp->device->request_queue; 34658c2ecf20Sopenharmony_ci 34668c2ecf20Sopenharmony_ci /* defaults, until the device tells us otherwise */ 34678c2ecf20Sopenharmony_ci sdp->sector_size = 512; 34688c2ecf20Sopenharmony_ci sdkp->capacity = 0; 34698c2ecf20Sopenharmony_ci sdkp->media_present = 1; 34708c2ecf20Sopenharmony_ci sdkp->write_prot = 0; 34718c2ecf20Sopenharmony_ci sdkp->cache_override = 0; 34728c2ecf20Sopenharmony_ci sdkp->WCE = 0; 34738c2ecf20Sopenharmony_ci sdkp->RCD = 0; 34748c2ecf20Sopenharmony_ci sdkp->ATO = 0; 34758c2ecf20Sopenharmony_ci sdkp->first_scan = 1; 34768c2ecf20Sopenharmony_ci sdkp->max_medium_access_timeouts = SD_MAX_MEDIUM_TIMEOUTS; 34778c2ecf20Sopenharmony_ci 34788c2ecf20Sopenharmony_ci sd_revalidate_disk(gd); 34798c2ecf20Sopenharmony_ci 34808c2ecf20Sopenharmony_ci gd->flags = GENHD_FL_EXT_DEVT; 34818c2ecf20Sopenharmony_ci if (sdp->removable) { 34828c2ecf20Sopenharmony_ci gd->flags |= GENHD_FL_REMOVABLE; 34838c2ecf20Sopenharmony_ci gd->events |= DISK_EVENT_MEDIA_CHANGE; 34848c2ecf20Sopenharmony_ci gd->event_flags = DISK_EVENT_FLAG_POLL | DISK_EVENT_FLAG_UEVENT; 34858c2ecf20Sopenharmony_ci } 34868c2ecf20Sopenharmony_ci 34878c2ecf20Sopenharmony_ci blk_pm_runtime_init(sdp->request_queue, dev); 34888c2ecf20Sopenharmony_ci if (sdp->rpm_autosuspend) { 34898c2ecf20Sopenharmony_ci pm_runtime_set_autosuspend_delay(dev, 34908c2ecf20Sopenharmony_ci sdp->host->hostt->rpm_autosuspend_delay); 34918c2ecf20Sopenharmony_ci } 34928c2ecf20Sopenharmony_ci device_add_disk(dev, gd, NULL); 34938c2ecf20Sopenharmony_ci blk_delete_region(disk_devt(sdkp->disk), SD_MINORS, sd_default_probe); 34948c2ecf20Sopenharmony_ci if (sdkp->capacity) 34958c2ecf20Sopenharmony_ci sd_dif_config_host(sdkp); 34968c2ecf20Sopenharmony_ci 34978c2ecf20Sopenharmony_ci sd_revalidate_disk(gd); 34988c2ecf20Sopenharmony_ci 34998c2ecf20Sopenharmony_ci if (sdkp->security) { 35008c2ecf20Sopenharmony_ci sdkp->opal_dev = init_opal_dev(sdkp, &sd_sec_submit); 35018c2ecf20Sopenharmony_ci if (sdkp->opal_dev) 35028c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "supports TCG Opal\n"); 35038c2ecf20Sopenharmony_ci } 35048c2ecf20Sopenharmony_ci 35058c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", 35068c2ecf20Sopenharmony_ci sdp->removable ? "removable " : ""); 35078c2ecf20Sopenharmony_ci scsi_autopm_put_device(sdp); 35088c2ecf20Sopenharmony_ci 35098c2ecf20Sopenharmony_ci return 0; 35108c2ecf20Sopenharmony_ci 35118c2ecf20Sopenharmony_ci out_free_index: 35128c2ecf20Sopenharmony_ci ida_free(&sd_index_ida, index); 35138c2ecf20Sopenharmony_ci out_put: 35148c2ecf20Sopenharmony_ci put_disk(gd); 35158c2ecf20Sopenharmony_ci out_free: 35168c2ecf20Sopenharmony_ci kfree(sdkp); 35178c2ecf20Sopenharmony_ci out: 35188c2ecf20Sopenharmony_ci scsi_autopm_put_device(sdp); 35198c2ecf20Sopenharmony_ci return error; 35208c2ecf20Sopenharmony_ci} 35218c2ecf20Sopenharmony_ci 35228c2ecf20Sopenharmony_ci/** 35238c2ecf20Sopenharmony_ci * sd_remove - called whenever a scsi disk (previously recognized by 35248c2ecf20Sopenharmony_ci * sd_probe) is detached from the system. It is called (potentially 35258c2ecf20Sopenharmony_ci * multiple times) during sd module unload. 35268c2ecf20Sopenharmony_ci * @dev: pointer to device object 35278c2ecf20Sopenharmony_ci * 35288c2ecf20Sopenharmony_ci * Note: this function is invoked from the scsi mid-level. 35298c2ecf20Sopenharmony_ci * This function potentially frees up a device name (e.g. /dev/sdc) 35308c2ecf20Sopenharmony_ci * that could be re-used by a subsequent sd_probe(). 35318c2ecf20Sopenharmony_ci * This function is not called when the built-in sd driver is "exit-ed". 35328c2ecf20Sopenharmony_ci **/ 35338c2ecf20Sopenharmony_cistatic int sd_remove(struct device *dev) 35348c2ecf20Sopenharmony_ci{ 35358c2ecf20Sopenharmony_ci struct scsi_disk *sdkp; 35368c2ecf20Sopenharmony_ci dev_t devt; 35378c2ecf20Sopenharmony_ci 35388c2ecf20Sopenharmony_ci sdkp = dev_get_drvdata(dev); 35398c2ecf20Sopenharmony_ci devt = disk_devt(sdkp->disk); 35408c2ecf20Sopenharmony_ci scsi_autopm_get_device(sdkp->device); 35418c2ecf20Sopenharmony_ci 35428c2ecf20Sopenharmony_ci async_synchronize_full_domain(&scsi_sd_pm_domain); 35438c2ecf20Sopenharmony_ci device_del(&sdkp->dev); 35448c2ecf20Sopenharmony_ci del_gendisk(sdkp->disk); 35458c2ecf20Sopenharmony_ci sd_shutdown(dev); 35468c2ecf20Sopenharmony_ci 35478c2ecf20Sopenharmony_ci free_opal_dev(sdkp->opal_dev); 35488c2ecf20Sopenharmony_ci 35498c2ecf20Sopenharmony_ci blk_register_region(devt, SD_MINORS, NULL, 35508c2ecf20Sopenharmony_ci sd_default_probe, NULL, NULL); 35518c2ecf20Sopenharmony_ci 35528c2ecf20Sopenharmony_ci mutex_lock(&sd_ref_mutex); 35538c2ecf20Sopenharmony_ci dev_set_drvdata(dev, NULL); 35548c2ecf20Sopenharmony_ci put_device(&sdkp->dev); 35558c2ecf20Sopenharmony_ci mutex_unlock(&sd_ref_mutex); 35568c2ecf20Sopenharmony_ci 35578c2ecf20Sopenharmony_ci return 0; 35588c2ecf20Sopenharmony_ci} 35598c2ecf20Sopenharmony_ci 35608c2ecf20Sopenharmony_ci/** 35618c2ecf20Sopenharmony_ci * scsi_disk_release - Called to free the scsi_disk structure 35628c2ecf20Sopenharmony_ci * @dev: pointer to embedded class device 35638c2ecf20Sopenharmony_ci * 35648c2ecf20Sopenharmony_ci * sd_ref_mutex must be held entering this routine. Because it is 35658c2ecf20Sopenharmony_ci * called on last put, you should always use the scsi_disk_get() 35668c2ecf20Sopenharmony_ci * scsi_disk_put() helpers which manipulate the semaphore directly 35678c2ecf20Sopenharmony_ci * and never do a direct put_device. 35688c2ecf20Sopenharmony_ci **/ 35698c2ecf20Sopenharmony_cistatic void scsi_disk_release(struct device *dev) 35708c2ecf20Sopenharmony_ci{ 35718c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 35728c2ecf20Sopenharmony_ci struct gendisk *disk = sdkp->disk; 35738c2ecf20Sopenharmony_ci struct request_queue *q = disk->queue; 35748c2ecf20Sopenharmony_ci 35758c2ecf20Sopenharmony_ci ida_free(&sd_index_ida, sdkp->index); 35768c2ecf20Sopenharmony_ci 35778c2ecf20Sopenharmony_ci /* 35788c2ecf20Sopenharmony_ci * Wait until all requests that are in progress have completed. 35798c2ecf20Sopenharmony_ci * This is necessary to avoid that e.g. scsi_end_request() crashes 35808c2ecf20Sopenharmony_ci * due to clearing the disk->private_data pointer. Wait from inside 35818c2ecf20Sopenharmony_ci * scsi_disk_release() instead of from sd_release() to avoid that 35828c2ecf20Sopenharmony_ci * freezing and unfreezing the request queue affects user space I/O 35838c2ecf20Sopenharmony_ci * in case multiple processes open a /dev/sd... node concurrently. 35848c2ecf20Sopenharmony_ci */ 35858c2ecf20Sopenharmony_ci blk_mq_freeze_queue(q); 35868c2ecf20Sopenharmony_ci blk_mq_unfreeze_queue(q); 35878c2ecf20Sopenharmony_ci 35888c2ecf20Sopenharmony_ci disk->private_data = NULL; 35898c2ecf20Sopenharmony_ci put_disk(disk); 35908c2ecf20Sopenharmony_ci put_device(&sdkp->device->sdev_gendev); 35918c2ecf20Sopenharmony_ci 35928c2ecf20Sopenharmony_ci sd_zbc_release_disk(sdkp); 35938c2ecf20Sopenharmony_ci 35948c2ecf20Sopenharmony_ci kfree(sdkp); 35958c2ecf20Sopenharmony_ci} 35968c2ecf20Sopenharmony_ci 35978c2ecf20Sopenharmony_cistatic int sd_start_stop_device(struct scsi_disk *sdkp, int start) 35988c2ecf20Sopenharmony_ci{ 35998c2ecf20Sopenharmony_ci unsigned char cmd[6] = { START_STOP }; /* START_VALID */ 36008c2ecf20Sopenharmony_ci struct scsi_sense_hdr sshdr; 36018c2ecf20Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 36028c2ecf20Sopenharmony_ci int res; 36038c2ecf20Sopenharmony_ci 36048c2ecf20Sopenharmony_ci if (start) 36058c2ecf20Sopenharmony_ci cmd[4] |= 1; /* START */ 36068c2ecf20Sopenharmony_ci 36078c2ecf20Sopenharmony_ci if (sdp->start_stop_pwr_cond) 36088c2ecf20Sopenharmony_ci cmd[4] |= start ? 1 << 4 : 3 << 4; /* Active or Standby */ 36098c2ecf20Sopenharmony_ci 36108c2ecf20Sopenharmony_ci if (!scsi_device_online(sdp)) 36118c2ecf20Sopenharmony_ci return -ENODEV; 36128c2ecf20Sopenharmony_ci 36138c2ecf20Sopenharmony_ci res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr, 36148c2ecf20Sopenharmony_ci SD_TIMEOUT, sdkp->max_retries, 0, RQF_PM, NULL); 36158c2ecf20Sopenharmony_ci if (res) { 36168c2ecf20Sopenharmony_ci sd_print_result(sdkp, "Start/Stop Unit failed", res); 36178c2ecf20Sopenharmony_ci if (driver_byte(res) == DRIVER_SENSE) 36188c2ecf20Sopenharmony_ci sd_print_sense_hdr(sdkp, &sshdr); 36198c2ecf20Sopenharmony_ci if (scsi_sense_valid(&sshdr) && 36208c2ecf20Sopenharmony_ci /* 0x3a is medium not present */ 36218c2ecf20Sopenharmony_ci sshdr.asc == 0x3a) 36228c2ecf20Sopenharmony_ci res = 0; 36238c2ecf20Sopenharmony_ci } 36248c2ecf20Sopenharmony_ci 36258c2ecf20Sopenharmony_ci /* SCSI error codes must not go to the generic layer */ 36268c2ecf20Sopenharmony_ci if (res) 36278c2ecf20Sopenharmony_ci return -EIO; 36288c2ecf20Sopenharmony_ci 36298c2ecf20Sopenharmony_ci return 0; 36308c2ecf20Sopenharmony_ci} 36318c2ecf20Sopenharmony_ci 36328c2ecf20Sopenharmony_ci/* 36338c2ecf20Sopenharmony_ci * Send a SYNCHRONIZE CACHE instruction down to the device through 36348c2ecf20Sopenharmony_ci * the normal SCSI command structure. Wait for the command to 36358c2ecf20Sopenharmony_ci * complete. 36368c2ecf20Sopenharmony_ci */ 36378c2ecf20Sopenharmony_cistatic void sd_shutdown(struct device *dev) 36388c2ecf20Sopenharmony_ci{ 36398c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = dev_get_drvdata(dev); 36408c2ecf20Sopenharmony_ci 36418c2ecf20Sopenharmony_ci if (!sdkp) 36428c2ecf20Sopenharmony_ci return; /* this can happen */ 36438c2ecf20Sopenharmony_ci 36448c2ecf20Sopenharmony_ci if (pm_runtime_suspended(dev)) 36458c2ecf20Sopenharmony_ci return; 36468c2ecf20Sopenharmony_ci 36478c2ecf20Sopenharmony_ci if (sdkp->WCE && sdkp->media_present) { 36488c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); 36498c2ecf20Sopenharmony_ci sd_sync_cache(sdkp, NULL); 36508c2ecf20Sopenharmony_ci } 36518c2ecf20Sopenharmony_ci 36528c2ecf20Sopenharmony_ci if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) { 36538c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); 36548c2ecf20Sopenharmony_ci sd_start_stop_device(sdkp, 0); 36558c2ecf20Sopenharmony_ci } 36568c2ecf20Sopenharmony_ci} 36578c2ecf20Sopenharmony_ci 36588c2ecf20Sopenharmony_cistatic int sd_suspend_common(struct device *dev, bool ignore_stop_errors) 36598c2ecf20Sopenharmony_ci{ 36608c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = dev_get_drvdata(dev); 36618c2ecf20Sopenharmony_ci struct scsi_sense_hdr sshdr; 36628c2ecf20Sopenharmony_ci int ret = 0; 36638c2ecf20Sopenharmony_ci 36648c2ecf20Sopenharmony_ci if (!sdkp) /* E.g.: runtime suspend following sd_remove() */ 36658c2ecf20Sopenharmony_ci return 0; 36668c2ecf20Sopenharmony_ci 36678c2ecf20Sopenharmony_ci if (sdkp->WCE && sdkp->media_present) { 36688c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); 36698c2ecf20Sopenharmony_ci ret = sd_sync_cache(sdkp, &sshdr); 36708c2ecf20Sopenharmony_ci 36718c2ecf20Sopenharmony_ci if (ret) { 36728c2ecf20Sopenharmony_ci /* ignore OFFLINE device */ 36738c2ecf20Sopenharmony_ci if (ret == -ENODEV) 36748c2ecf20Sopenharmony_ci return 0; 36758c2ecf20Sopenharmony_ci 36768c2ecf20Sopenharmony_ci if (!scsi_sense_valid(&sshdr) || 36778c2ecf20Sopenharmony_ci sshdr.sense_key != ILLEGAL_REQUEST) 36788c2ecf20Sopenharmony_ci return ret; 36798c2ecf20Sopenharmony_ci 36808c2ecf20Sopenharmony_ci /* 36818c2ecf20Sopenharmony_ci * sshdr.sense_key == ILLEGAL_REQUEST means this drive 36828c2ecf20Sopenharmony_ci * doesn't support sync. There's not much to do and 36838c2ecf20Sopenharmony_ci * suspend shouldn't fail. 36848c2ecf20Sopenharmony_ci */ 36858c2ecf20Sopenharmony_ci ret = 0; 36868c2ecf20Sopenharmony_ci } 36878c2ecf20Sopenharmony_ci } 36888c2ecf20Sopenharmony_ci 36898c2ecf20Sopenharmony_ci if (sdkp->device->manage_start_stop) { 36908c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); 36918c2ecf20Sopenharmony_ci /* an error is not worth aborting a system sleep */ 36928c2ecf20Sopenharmony_ci ret = sd_start_stop_device(sdkp, 0); 36938c2ecf20Sopenharmony_ci if (ignore_stop_errors) 36948c2ecf20Sopenharmony_ci ret = 0; 36958c2ecf20Sopenharmony_ci } 36968c2ecf20Sopenharmony_ci 36978c2ecf20Sopenharmony_ci return ret; 36988c2ecf20Sopenharmony_ci} 36998c2ecf20Sopenharmony_ci 37008c2ecf20Sopenharmony_cistatic int sd_suspend_system(struct device *dev) 37018c2ecf20Sopenharmony_ci{ 37028c2ecf20Sopenharmony_ci return sd_suspend_common(dev, true); 37038c2ecf20Sopenharmony_ci} 37048c2ecf20Sopenharmony_ci 37058c2ecf20Sopenharmony_cistatic int sd_suspend_runtime(struct device *dev) 37068c2ecf20Sopenharmony_ci{ 37078c2ecf20Sopenharmony_ci return sd_suspend_common(dev, false); 37088c2ecf20Sopenharmony_ci} 37098c2ecf20Sopenharmony_ci 37108c2ecf20Sopenharmony_cistatic int sd_resume(struct device *dev) 37118c2ecf20Sopenharmony_ci{ 37128c2ecf20Sopenharmony_ci struct scsi_disk *sdkp = dev_get_drvdata(dev); 37138c2ecf20Sopenharmony_ci int ret; 37148c2ecf20Sopenharmony_ci 37158c2ecf20Sopenharmony_ci if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ 37168c2ecf20Sopenharmony_ci return 0; 37178c2ecf20Sopenharmony_ci 37188c2ecf20Sopenharmony_ci if (!sdkp->device->manage_start_stop) 37198c2ecf20Sopenharmony_ci return 0; 37208c2ecf20Sopenharmony_ci 37218c2ecf20Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); 37228c2ecf20Sopenharmony_ci ret = sd_start_stop_device(sdkp, 1); 37238c2ecf20Sopenharmony_ci if (!ret) 37248c2ecf20Sopenharmony_ci opal_unlock_from_suspend(sdkp->opal_dev); 37258c2ecf20Sopenharmony_ci return ret; 37268c2ecf20Sopenharmony_ci} 37278c2ecf20Sopenharmony_ci 37288c2ecf20Sopenharmony_ci/** 37298c2ecf20Sopenharmony_ci * init_sd - entry point for this driver (both when built in or when 37308c2ecf20Sopenharmony_ci * a module). 37318c2ecf20Sopenharmony_ci * 37328c2ecf20Sopenharmony_ci * Note: this function registers this driver with the scsi mid-level. 37338c2ecf20Sopenharmony_ci **/ 37348c2ecf20Sopenharmony_cistatic int __init init_sd(void) 37358c2ecf20Sopenharmony_ci{ 37368c2ecf20Sopenharmony_ci int majors = 0, i, err; 37378c2ecf20Sopenharmony_ci 37388c2ecf20Sopenharmony_ci SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n")); 37398c2ecf20Sopenharmony_ci 37408c2ecf20Sopenharmony_ci for (i = 0; i < SD_MAJORS; i++) { 37418c2ecf20Sopenharmony_ci if (register_blkdev(sd_major(i), "sd") != 0) 37428c2ecf20Sopenharmony_ci continue; 37438c2ecf20Sopenharmony_ci majors++; 37448c2ecf20Sopenharmony_ci blk_register_region(sd_major(i), SD_MINORS, NULL, 37458c2ecf20Sopenharmony_ci sd_default_probe, NULL, NULL); 37468c2ecf20Sopenharmony_ci } 37478c2ecf20Sopenharmony_ci 37488c2ecf20Sopenharmony_ci if (!majors) 37498c2ecf20Sopenharmony_ci return -ENODEV; 37508c2ecf20Sopenharmony_ci 37518c2ecf20Sopenharmony_ci err = class_register(&sd_disk_class); 37528c2ecf20Sopenharmony_ci if (err) 37538c2ecf20Sopenharmony_ci goto err_out; 37548c2ecf20Sopenharmony_ci 37558c2ecf20Sopenharmony_ci sd_cdb_cache = kmem_cache_create("sd_ext_cdb", SD_EXT_CDB_SIZE, 37568c2ecf20Sopenharmony_ci 0, 0, NULL); 37578c2ecf20Sopenharmony_ci if (!sd_cdb_cache) { 37588c2ecf20Sopenharmony_ci printk(KERN_ERR "sd: can't init extended cdb cache\n"); 37598c2ecf20Sopenharmony_ci err = -ENOMEM; 37608c2ecf20Sopenharmony_ci goto err_out_class; 37618c2ecf20Sopenharmony_ci } 37628c2ecf20Sopenharmony_ci 37638c2ecf20Sopenharmony_ci sd_cdb_pool = mempool_create_slab_pool(SD_MEMPOOL_SIZE, sd_cdb_cache); 37648c2ecf20Sopenharmony_ci if (!sd_cdb_pool) { 37658c2ecf20Sopenharmony_ci printk(KERN_ERR "sd: can't init extended cdb pool\n"); 37668c2ecf20Sopenharmony_ci err = -ENOMEM; 37678c2ecf20Sopenharmony_ci goto err_out_cache; 37688c2ecf20Sopenharmony_ci } 37698c2ecf20Sopenharmony_ci 37708c2ecf20Sopenharmony_ci sd_page_pool = mempool_create_page_pool(SD_MEMPOOL_SIZE, 0); 37718c2ecf20Sopenharmony_ci if (!sd_page_pool) { 37728c2ecf20Sopenharmony_ci printk(KERN_ERR "sd: can't init discard page pool\n"); 37738c2ecf20Sopenharmony_ci err = -ENOMEM; 37748c2ecf20Sopenharmony_ci goto err_out_ppool; 37758c2ecf20Sopenharmony_ci } 37768c2ecf20Sopenharmony_ci 37778c2ecf20Sopenharmony_ci err = scsi_register_driver(&sd_template.gendrv); 37788c2ecf20Sopenharmony_ci if (err) 37798c2ecf20Sopenharmony_ci goto err_out_driver; 37808c2ecf20Sopenharmony_ci 37818c2ecf20Sopenharmony_ci return 0; 37828c2ecf20Sopenharmony_ci 37838c2ecf20Sopenharmony_cierr_out_driver: 37848c2ecf20Sopenharmony_ci mempool_destroy(sd_page_pool); 37858c2ecf20Sopenharmony_ci 37868c2ecf20Sopenharmony_cierr_out_ppool: 37878c2ecf20Sopenharmony_ci mempool_destroy(sd_cdb_pool); 37888c2ecf20Sopenharmony_ci 37898c2ecf20Sopenharmony_cierr_out_cache: 37908c2ecf20Sopenharmony_ci kmem_cache_destroy(sd_cdb_cache); 37918c2ecf20Sopenharmony_ci 37928c2ecf20Sopenharmony_cierr_out_class: 37938c2ecf20Sopenharmony_ci class_unregister(&sd_disk_class); 37948c2ecf20Sopenharmony_cierr_out: 37958c2ecf20Sopenharmony_ci for (i = 0; i < SD_MAJORS; i++) 37968c2ecf20Sopenharmony_ci unregister_blkdev(sd_major(i), "sd"); 37978c2ecf20Sopenharmony_ci return err; 37988c2ecf20Sopenharmony_ci} 37998c2ecf20Sopenharmony_ci 38008c2ecf20Sopenharmony_ci/** 38018c2ecf20Sopenharmony_ci * exit_sd - exit point for this driver (when it is a module). 38028c2ecf20Sopenharmony_ci * 38038c2ecf20Sopenharmony_ci * Note: this function unregisters this driver from the scsi mid-level. 38048c2ecf20Sopenharmony_ci **/ 38058c2ecf20Sopenharmony_cistatic void __exit exit_sd(void) 38068c2ecf20Sopenharmony_ci{ 38078c2ecf20Sopenharmony_ci int i; 38088c2ecf20Sopenharmony_ci 38098c2ecf20Sopenharmony_ci SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n")); 38108c2ecf20Sopenharmony_ci 38118c2ecf20Sopenharmony_ci scsi_unregister_driver(&sd_template.gendrv); 38128c2ecf20Sopenharmony_ci mempool_destroy(sd_cdb_pool); 38138c2ecf20Sopenharmony_ci mempool_destroy(sd_page_pool); 38148c2ecf20Sopenharmony_ci kmem_cache_destroy(sd_cdb_cache); 38158c2ecf20Sopenharmony_ci 38168c2ecf20Sopenharmony_ci class_unregister(&sd_disk_class); 38178c2ecf20Sopenharmony_ci 38188c2ecf20Sopenharmony_ci for (i = 0; i < SD_MAJORS; i++) { 38198c2ecf20Sopenharmony_ci blk_unregister_region(sd_major(i), SD_MINORS); 38208c2ecf20Sopenharmony_ci unregister_blkdev(sd_major(i), "sd"); 38218c2ecf20Sopenharmony_ci } 38228c2ecf20Sopenharmony_ci} 38238c2ecf20Sopenharmony_ci 38248c2ecf20Sopenharmony_cimodule_init(init_sd); 38258c2ecf20Sopenharmony_cimodule_exit(exit_sd); 38268c2ecf20Sopenharmony_ci 38278c2ecf20Sopenharmony_civoid sd_print_sense_hdr(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr) 38288c2ecf20Sopenharmony_ci{ 38298c2ecf20Sopenharmony_ci scsi_print_sense_hdr(sdkp->device, 38308c2ecf20Sopenharmony_ci sdkp->disk ? sdkp->disk->disk_name : NULL, sshdr); 38318c2ecf20Sopenharmony_ci} 38328c2ecf20Sopenharmony_ci 38338c2ecf20Sopenharmony_civoid sd_print_result(const struct scsi_disk *sdkp, const char *msg, int result) 38348c2ecf20Sopenharmony_ci{ 38358c2ecf20Sopenharmony_ci const char *hb_string = scsi_hostbyte_string(result); 38368c2ecf20Sopenharmony_ci const char *db_string = scsi_driverbyte_string(result); 38378c2ecf20Sopenharmony_ci 38388c2ecf20Sopenharmony_ci if (hb_string || db_string) 38398c2ecf20Sopenharmony_ci sd_printk(KERN_INFO, sdkp, 38408c2ecf20Sopenharmony_ci "%s: Result: hostbyte=%s driverbyte=%s\n", msg, 38418c2ecf20Sopenharmony_ci hb_string ? hb_string : "invalid", 38428c2ecf20Sopenharmony_ci db_string ? db_string : "invalid"); 38438c2ecf20Sopenharmony_ci else 38448c2ecf20Sopenharmony_ci sd_printk(KERN_INFO, sdkp, 38458c2ecf20Sopenharmony_ci "%s: Result: hostbyte=0x%02x driverbyte=0x%02x\n", 38468c2ecf20Sopenharmony_ci msg, host_byte(result), driver_byte(result)); 38478c2ecf20Sopenharmony_ci} 3848