162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * sd.c Copyright (C) 1992 Drew Eckhardt 462306a36Sopenharmony_ci * Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Linux scsi disk driver 762306a36Sopenharmony_ci * Initial versions: Drew Eckhardt 862306a36Sopenharmony_ci * Subsequent revisions: Eric Youngdale 962306a36Sopenharmony_ci * Modification history: 1062306a36Sopenharmony_ci * - Drew Eckhardt <drew@colorado.edu> original 1162306a36Sopenharmony_ci * - Eric Youngdale <eric@andante.org> add scatter-gather, multiple 1262306a36Sopenharmony_ci * outstanding request, and other enhancements. 1362306a36Sopenharmony_ci * Support loadable low-level scsi drivers. 1462306a36Sopenharmony_ci * - Jirka Hanika <geo@ff.cuni.cz> support more scsi disks using 1562306a36Sopenharmony_ci * eight major numbers. 1662306a36Sopenharmony_ci * - Richard Gooch <rgooch@atnf.csiro.au> support devfs. 1762306a36Sopenharmony_ci * - Torben Mathiasen <tmm@image.dk> Resource allocation fixes in 1862306a36Sopenharmony_ci * sd_init and cleanups. 1962306a36Sopenharmony_ci * - Alex Davis <letmein@erols.com> Fix problem where partition info 2062306a36Sopenharmony_ci * not being read in sd_open. Fix problem where removable media 2162306a36Sopenharmony_ci * could be ejected after sd_open. 2262306a36Sopenharmony_ci * - Douglas Gilbert <dgilbert@interlog.com> cleanup for lk 2.5.x 2362306a36Sopenharmony_ci * - Badari Pulavarty <pbadari@us.ibm.com>, Matthew Wilcox 2462306a36Sopenharmony_ci * <willy@debian.org>, Kurt Garloff <garloff@suse.de>: 2562306a36Sopenharmony_ci * Support 32k/1M disks. 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * Logging policy (needs CONFIG_SCSI_LOGGING defined): 2862306a36Sopenharmony_ci * - setting up transfer: SCSI_LOG_HLQUEUE levels 1 and 2 2962306a36Sopenharmony_ci * - end of transfer (bh + scsi_lib): SCSI_LOG_HLCOMPLETE level 1 3062306a36Sopenharmony_ci * - entering sd_ioctl: SCSI_LOG_IOCTL level 1 3162306a36Sopenharmony_ci * - entering other commands: SCSI_LOG_HLQUEUE level 3 3262306a36Sopenharmony_ci * Note: when the logging level is set by the user, it must be greater 3362306a36Sopenharmony_ci * than the level indicated above to trigger output. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include <linux/module.h> 3762306a36Sopenharmony_ci#include <linux/fs.h> 3862306a36Sopenharmony_ci#include <linux/kernel.h> 3962306a36Sopenharmony_ci#include <linux/mm.h> 4062306a36Sopenharmony_ci#include <linux/bio.h> 4162306a36Sopenharmony_ci#include <linux/hdreg.h> 4262306a36Sopenharmony_ci#include <linux/errno.h> 4362306a36Sopenharmony_ci#include <linux/idr.h> 4462306a36Sopenharmony_ci#include <linux/interrupt.h> 4562306a36Sopenharmony_ci#include <linux/init.h> 4662306a36Sopenharmony_ci#include <linux/blkdev.h> 4762306a36Sopenharmony_ci#include <linux/blkpg.h> 4862306a36Sopenharmony_ci#include <linux/blk-pm.h> 4962306a36Sopenharmony_ci#include <linux/delay.h> 5062306a36Sopenharmony_ci#include <linux/major.h> 5162306a36Sopenharmony_ci#include <linux/mutex.h> 5262306a36Sopenharmony_ci#include <linux/string_helpers.h> 5362306a36Sopenharmony_ci#include <linux/slab.h> 5462306a36Sopenharmony_ci#include <linux/sed-opal.h> 5562306a36Sopenharmony_ci#include <linux/pm_runtime.h> 5662306a36Sopenharmony_ci#include <linux/pr.h> 5762306a36Sopenharmony_ci#include <linux/t10-pi.h> 5862306a36Sopenharmony_ci#include <linux/uaccess.h> 5962306a36Sopenharmony_ci#include <asm/unaligned.h> 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#include <scsi/scsi.h> 6262306a36Sopenharmony_ci#include <scsi/scsi_cmnd.h> 6362306a36Sopenharmony_ci#include <scsi/scsi_dbg.h> 6462306a36Sopenharmony_ci#include <scsi/scsi_device.h> 6562306a36Sopenharmony_ci#include <scsi/scsi_driver.h> 6662306a36Sopenharmony_ci#include <scsi/scsi_eh.h> 6762306a36Sopenharmony_ci#include <scsi/scsi_host.h> 6862306a36Sopenharmony_ci#include <scsi/scsi_ioctl.h> 6962306a36Sopenharmony_ci#include <scsi/scsicam.h> 7062306a36Sopenharmony_ci#include <scsi/scsi_common.h> 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci#include "sd.h" 7362306a36Sopenharmony_ci#include "scsi_priv.h" 7462306a36Sopenharmony_ci#include "scsi_logging.h" 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ciMODULE_AUTHOR("Eric Youngdale"); 7762306a36Sopenharmony_ciMODULE_DESCRIPTION("SCSI disk (sd) driver"); 7862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK0_MAJOR); 8162306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK1_MAJOR); 8262306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK2_MAJOR); 8362306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK3_MAJOR); 8462306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK4_MAJOR); 8562306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK5_MAJOR); 8662306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK6_MAJOR); 8762306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK7_MAJOR); 8862306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK8_MAJOR); 8962306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK9_MAJOR); 9062306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK10_MAJOR); 9162306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK11_MAJOR); 9262306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK12_MAJOR); 9362306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK13_MAJOR); 9462306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK14_MAJOR); 9562306a36Sopenharmony_ciMODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK15_MAJOR); 9662306a36Sopenharmony_ciMODULE_ALIAS_SCSI_DEVICE(TYPE_DISK); 9762306a36Sopenharmony_ciMODULE_ALIAS_SCSI_DEVICE(TYPE_MOD); 9862306a36Sopenharmony_ciMODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); 9962306a36Sopenharmony_ciMODULE_ALIAS_SCSI_DEVICE(TYPE_ZBC); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci#define SD_MINORS 16 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic void sd_config_discard(struct scsi_disk *, unsigned int); 10462306a36Sopenharmony_cistatic void sd_config_write_same(struct scsi_disk *); 10562306a36Sopenharmony_cistatic int sd_revalidate_disk(struct gendisk *); 10662306a36Sopenharmony_cistatic void sd_unlock_native_capacity(struct gendisk *disk); 10762306a36Sopenharmony_cistatic void sd_shutdown(struct device *); 10862306a36Sopenharmony_cistatic void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); 10962306a36Sopenharmony_cistatic void scsi_disk_release(struct device *cdev); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic DEFINE_IDA(sd_index_ida); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistatic mempool_t *sd_page_pool; 11462306a36Sopenharmony_cistatic struct lock_class_key sd_bio_compl_lkclass; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistatic const char *sd_cache_types[] = { 11762306a36Sopenharmony_ci "write through", "none", "write back", 11862306a36Sopenharmony_ci "write back, no read (daft)" 11962306a36Sopenharmony_ci}; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistatic void sd_set_flush_flag(struct scsi_disk *sdkp) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci bool wc = false, fua = false; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci if (sdkp->WCE) { 12662306a36Sopenharmony_ci wc = true; 12762306a36Sopenharmony_ci if (sdkp->DPOFUA) 12862306a36Sopenharmony_ci fua = true; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci blk_queue_write_cache(sdkp->disk->queue, wc, fua); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic ssize_t 13562306a36Sopenharmony_cicache_type_store(struct device *dev, struct device_attribute *attr, 13662306a36Sopenharmony_ci const char *buf, size_t count) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci int ct, rcd, wce, sp; 13962306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 14062306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 14162306a36Sopenharmony_ci char buffer[64]; 14262306a36Sopenharmony_ci char *buffer_data; 14362306a36Sopenharmony_ci struct scsi_mode_data data; 14462306a36Sopenharmony_ci struct scsi_sense_hdr sshdr; 14562306a36Sopenharmony_ci static const char temp[] = "temporary "; 14662306a36Sopenharmony_ci int len; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC) 14962306a36Sopenharmony_ci /* no cache control on RBC devices; theoretically they 15062306a36Sopenharmony_ci * can do it, but there's probably so many exceptions 15162306a36Sopenharmony_ci * it's not worth the risk */ 15262306a36Sopenharmony_ci return -EINVAL; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci if (strncmp(buf, temp, sizeof(temp) - 1) == 0) { 15562306a36Sopenharmony_ci buf += sizeof(temp) - 1; 15662306a36Sopenharmony_ci sdkp->cache_override = 1; 15762306a36Sopenharmony_ci } else { 15862306a36Sopenharmony_ci sdkp->cache_override = 0; 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci ct = sysfs_match_string(sd_cache_types, buf); 16262306a36Sopenharmony_ci if (ct < 0) 16362306a36Sopenharmony_ci return -EINVAL; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci rcd = ct & 0x01 ? 1 : 0; 16662306a36Sopenharmony_ci wce = (ct & 0x02) && !sdkp->write_prot ? 1 : 0; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci if (sdkp->cache_override) { 16962306a36Sopenharmony_ci sdkp->WCE = wce; 17062306a36Sopenharmony_ci sdkp->RCD = rcd; 17162306a36Sopenharmony_ci sd_set_flush_flag(sdkp); 17262306a36Sopenharmony_ci return count; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci if (scsi_mode_sense(sdp, 0x08, 8, 0, buffer, sizeof(buffer), SD_TIMEOUT, 17662306a36Sopenharmony_ci sdkp->max_retries, &data, NULL)) 17762306a36Sopenharmony_ci return -EINVAL; 17862306a36Sopenharmony_ci len = min_t(size_t, sizeof(buffer), data.length - data.header_length - 17962306a36Sopenharmony_ci data.block_descriptor_length); 18062306a36Sopenharmony_ci buffer_data = buffer + data.header_length + 18162306a36Sopenharmony_ci data.block_descriptor_length; 18262306a36Sopenharmony_ci buffer_data[2] &= ~0x05; 18362306a36Sopenharmony_ci buffer_data[2] |= wce << 2 | rcd; 18462306a36Sopenharmony_ci sp = buffer_data[0] & 0x80 ? 1 : 0; 18562306a36Sopenharmony_ci buffer_data[0] &= ~0x80; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci /* 18862306a36Sopenharmony_ci * Ensure WP, DPOFUA, and RESERVED fields are cleared in 18962306a36Sopenharmony_ci * received mode parameter buffer before doing MODE SELECT. 19062306a36Sopenharmony_ci */ 19162306a36Sopenharmony_ci data.device_specific = 0; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (scsi_mode_select(sdp, 1, sp, buffer_data, len, SD_TIMEOUT, 19462306a36Sopenharmony_ci sdkp->max_retries, &data, &sshdr)) { 19562306a36Sopenharmony_ci if (scsi_sense_valid(&sshdr)) 19662306a36Sopenharmony_ci sd_print_sense_hdr(sdkp, &sshdr); 19762306a36Sopenharmony_ci return -EINVAL; 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci sd_revalidate_disk(sdkp->disk); 20062306a36Sopenharmony_ci return count; 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic ssize_t 20462306a36Sopenharmony_cimanage_start_stop_show(struct device *dev, 20562306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 20862306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci return sysfs_emit(buf, "%u\n", 21162306a36Sopenharmony_ci sdp->manage_system_start_stop && 21262306a36Sopenharmony_ci sdp->manage_runtime_start_stop && 21362306a36Sopenharmony_ci sdp->manage_shutdown); 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_cistatic DEVICE_ATTR_RO(manage_start_stop); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic ssize_t 21862306a36Sopenharmony_cimanage_system_start_stop_show(struct device *dev, 21962306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 22262306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci return sysfs_emit(buf, "%u\n", sdp->manage_system_start_stop); 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic ssize_t 22862306a36Sopenharmony_cimanage_system_start_stop_store(struct device *dev, 22962306a36Sopenharmony_ci struct device_attribute *attr, 23062306a36Sopenharmony_ci const char *buf, size_t count) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 23362306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 23462306a36Sopenharmony_ci bool v; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 23762306a36Sopenharmony_ci return -EACCES; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci if (kstrtobool(buf, &v)) 24062306a36Sopenharmony_ci return -EINVAL; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci sdp->manage_system_start_stop = v; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci return count; 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_cistatic DEVICE_ATTR_RW(manage_system_start_stop); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic ssize_t 24962306a36Sopenharmony_cimanage_runtime_start_stop_show(struct device *dev, 25062306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 25362306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci return sysfs_emit(buf, "%u\n", sdp->manage_runtime_start_stop); 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic ssize_t 25962306a36Sopenharmony_cimanage_runtime_start_stop_store(struct device *dev, 26062306a36Sopenharmony_ci struct device_attribute *attr, 26162306a36Sopenharmony_ci const char *buf, size_t count) 26262306a36Sopenharmony_ci{ 26362306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 26462306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 26562306a36Sopenharmony_ci bool v; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 26862306a36Sopenharmony_ci return -EACCES; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci if (kstrtobool(buf, &v)) 27162306a36Sopenharmony_ci return -EINVAL; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci sdp->manage_runtime_start_stop = v; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci return count; 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_cistatic DEVICE_ATTR_RW(manage_runtime_start_stop); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistatic ssize_t manage_shutdown_show(struct device *dev, 28062306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 28362306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci return sysfs_emit(buf, "%u\n", sdp->manage_shutdown); 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_cistatic ssize_t manage_shutdown_store(struct device *dev, 28962306a36Sopenharmony_ci struct device_attribute *attr, 29062306a36Sopenharmony_ci const char *buf, size_t count) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 29362306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 29462306a36Sopenharmony_ci bool v; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 29762306a36Sopenharmony_ci return -EACCES; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci if (kstrtobool(buf, &v)) 30062306a36Sopenharmony_ci return -EINVAL; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci sdp->manage_shutdown = v; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci return count; 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_cistatic DEVICE_ATTR_RW(manage_shutdown); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistatic ssize_t 30962306a36Sopenharmony_ciallow_restart_show(struct device *dev, struct device_attribute *attr, char *buf) 31062306a36Sopenharmony_ci{ 31162306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci return sprintf(buf, "%u\n", sdkp->device->allow_restart); 31462306a36Sopenharmony_ci} 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_cistatic ssize_t 31762306a36Sopenharmony_ciallow_restart_store(struct device *dev, struct device_attribute *attr, 31862306a36Sopenharmony_ci const char *buf, size_t count) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci bool v; 32162306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 32262306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 32562306a36Sopenharmony_ci return -EACCES; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC) 32862306a36Sopenharmony_ci return -EINVAL; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci if (kstrtobool(buf, &v)) 33162306a36Sopenharmony_ci return -EINVAL; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci sdp->allow_restart = v; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci return count; 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_cistatic DEVICE_ATTR_RW(allow_restart); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_cistatic ssize_t 34062306a36Sopenharmony_cicache_type_show(struct device *dev, struct device_attribute *attr, char *buf) 34162306a36Sopenharmony_ci{ 34262306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 34362306a36Sopenharmony_ci int ct = sdkp->RCD + 2*sdkp->WCE; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci return sprintf(buf, "%s\n", sd_cache_types[ct]); 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_cistatic DEVICE_ATTR_RW(cache_type); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_cistatic ssize_t 35062306a36Sopenharmony_ciFUA_show(struct device *dev, struct device_attribute *attr, char *buf) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci return sprintf(buf, "%u\n", sdkp->DPOFUA); 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_cistatic DEVICE_ATTR_RO(FUA); 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cistatic ssize_t 35962306a36Sopenharmony_ciprotection_type_show(struct device *dev, struct device_attribute *attr, 36062306a36Sopenharmony_ci char *buf) 36162306a36Sopenharmony_ci{ 36262306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci return sprintf(buf, "%u\n", sdkp->protection_type); 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic ssize_t 36862306a36Sopenharmony_ciprotection_type_store(struct device *dev, struct device_attribute *attr, 36962306a36Sopenharmony_ci const char *buf, size_t count) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 37262306a36Sopenharmony_ci unsigned int val; 37362306a36Sopenharmony_ci int err; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 37662306a36Sopenharmony_ci return -EACCES; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci err = kstrtouint(buf, 10, &val); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci if (err) 38162306a36Sopenharmony_ci return err; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci if (val <= T10_PI_TYPE3_PROTECTION) 38462306a36Sopenharmony_ci sdkp->protection_type = val; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci return count; 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_cistatic DEVICE_ATTR_RW(protection_type); 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cistatic ssize_t 39162306a36Sopenharmony_ciprotection_mode_show(struct device *dev, struct device_attribute *attr, 39262306a36Sopenharmony_ci char *buf) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 39562306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 39662306a36Sopenharmony_ci unsigned int dif, dix; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type); 39962306a36Sopenharmony_ci dix = scsi_host_dix_capable(sdp->host, sdkp->protection_type); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci if (!dix && scsi_host_dix_capable(sdp->host, T10_PI_TYPE0_PROTECTION)) { 40262306a36Sopenharmony_ci dif = 0; 40362306a36Sopenharmony_ci dix = 1; 40462306a36Sopenharmony_ci } 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci if (!dif && !dix) 40762306a36Sopenharmony_ci return sprintf(buf, "none\n"); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci return sprintf(buf, "%s%u\n", dix ? "dix" : "dif", dif); 41062306a36Sopenharmony_ci} 41162306a36Sopenharmony_cistatic DEVICE_ATTR_RO(protection_mode); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_cistatic ssize_t 41462306a36Sopenharmony_ciapp_tag_own_show(struct device *dev, struct device_attribute *attr, char *buf) 41562306a36Sopenharmony_ci{ 41662306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci return sprintf(buf, "%u\n", sdkp->ATO); 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_cistatic DEVICE_ATTR_RO(app_tag_own); 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_cistatic ssize_t 42362306a36Sopenharmony_cithin_provisioning_show(struct device *dev, struct device_attribute *attr, 42462306a36Sopenharmony_ci char *buf) 42562306a36Sopenharmony_ci{ 42662306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci return sprintf(buf, "%u\n", sdkp->lbpme); 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_cistatic DEVICE_ATTR_RO(thin_provisioning); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci/* sysfs_match_string() requires dense arrays */ 43362306a36Sopenharmony_cistatic const char *lbp_mode[] = { 43462306a36Sopenharmony_ci [SD_LBP_FULL] = "full", 43562306a36Sopenharmony_ci [SD_LBP_UNMAP] = "unmap", 43662306a36Sopenharmony_ci [SD_LBP_WS16] = "writesame_16", 43762306a36Sopenharmony_ci [SD_LBP_WS10] = "writesame_10", 43862306a36Sopenharmony_ci [SD_LBP_ZERO] = "writesame_zero", 43962306a36Sopenharmony_ci [SD_LBP_DISABLE] = "disabled", 44062306a36Sopenharmony_ci}; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic ssize_t 44362306a36Sopenharmony_ciprovisioning_mode_show(struct device *dev, struct device_attribute *attr, 44462306a36Sopenharmony_ci char *buf) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci return sprintf(buf, "%s\n", lbp_mode[sdkp->provisioning_mode]); 44962306a36Sopenharmony_ci} 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_cistatic ssize_t 45262306a36Sopenharmony_ciprovisioning_mode_store(struct device *dev, struct device_attribute *attr, 45362306a36Sopenharmony_ci const char *buf, size_t count) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 45662306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 45762306a36Sopenharmony_ci int mode; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 46062306a36Sopenharmony_ci return -EACCES; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci if (sd_is_zoned(sdkp)) { 46362306a36Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_DISABLE); 46462306a36Sopenharmony_ci return count; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci if (sdp->type != TYPE_DISK) 46862306a36Sopenharmony_ci return -EINVAL; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci mode = sysfs_match_string(lbp_mode, buf); 47162306a36Sopenharmony_ci if (mode < 0) 47262306a36Sopenharmony_ci return -EINVAL; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci sd_config_discard(sdkp, mode); 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci return count; 47762306a36Sopenharmony_ci} 47862306a36Sopenharmony_cistatic DEVICE_ATTR_RW(provisioning_mode); 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci/* sysfs_match_string() requires dense arrays */ 48162306a36Sopenharmony_cistatic const char *zeroing_mode[] = { 48262306a36Sopenharmony_ci [SD_ZERO_WRITE] = "write", 48362306a36Sopenharmony_ci [SD_ZERO_WS] = "writesame", 48462306a36Sopenharmony_ci [SD_ZERO_WS16_UNMAP] = "writesame_16_unmap", 48562306a36Sopenharmony_ci [SD_ZERO_WS10_UNMAP] = "writesame_10_unmap", 48662306a36Sopenharmony_ci}; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_cistatic ssize_t 48962306a36Sopenharmony_cizeroing_mode_show(struct device *dev, struct device_attribute *attr, 49062306a36Sopenharmony_ci char *buf) 49162306a36Sopenharmony_ci{ 49262306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci return sprintf(buf, "%s\n", zeroing_mode[sdkp->zeroing_mode]); 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_cistatic ssize_t 49862306a36Sopenharmony_cizeroing_mode_store(struct device *dev, struct device_attribute *attr, 49962306a36Sopenharmony_ci const char *buf, size_t count) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 50262306a36Sopenharmony_ci int mode; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 50562306a36Sopenharmony_ci return -EACCES; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci mode = sysfs_match_string(zeroing_mode, buf); 50862306a36Sopenharmony_ci if (mode < 0) 50962306a36Sopenharmony_ci return -EINVAL; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci sdkp->zeroing_mode = mode; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci return count; 51462306a36Sopenharmony_ci} 51562306a36Sopenharmony_cistatic DEVICE_ATTR_RW(zeroing_mode); 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistatic ssize_t 51862306a36Sopenharmony_cimax_medium_access_timeouts_show(struct device *dev, 51962306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 52062306a36Sopenharmony_ci{ 52162306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci return sprintf(buf, "%u\n", sdkp->max_medium_access_timeouts); 52462306a36Sopenharmony_ci} 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_cistatic ssize_t 52762306a36Sopenharmony_cimax_medium_access_timeouts_store(struct device *dev, 52862306a36Sopenharmony_ci struct device_attribute *attr, const char *buf, 52962306a36Sopenharmony_ci size_t count) 53062306a36Sopenharmony_ci{ 53162306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 53262306a36Sopenharmony_ci int err; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 53562306a36Sopenharmony_ci return -EACCES; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci err = kstrtouint(buf, 10, &sdkp->max_medium_access_timeouts); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci return err ? err : count; 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_cistatic DEVICE_ATTR_RW(max_medium_access_timeouts); 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_cistatic ssize_t 54462306a36Sopenharmony_cimax_write_same_blocks_show(struct device *dev, struct device_attribute *attr, 54562306a36Sopenharmony_ci char *buf) 54662306a36Sopenharmony_ci{ 54762306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci return sprintf(buf, "%u\n", sdkp->max_ws_blocks); 55062306a36Sopenharmony_ci} 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_cistatic ssize_t 55362306a36Sopenharmony_cimax_write_same_blocks_store(struct device *dev, struct device_attribute *attr, 55462306a36Sopenharmony_ci const char *buf, size_t count) 55562306a36Sopenharmony_ci{ 55662306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 55762306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 55862306a36Sopenharmony_ci unsigned long max; 55962306a36Sopenharmony_ci int err; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 56262306a36Sopenharmony_ci return -EACCES; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC) 56562306a36Sopenharmony_ci return -EINVAL; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci err = kstrtoul(buf, 10, &max); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci if (err) 57062306a36Sopenharmony_ci return err; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci if (max == 0) 57362306a36Sopenharmony_ci sdp->no_write_same = 1; 57462306a36Sopenharmony_ci else if (max <= SD_MAX_WS16_BLOCKS) { 57562306a36Sopenharmony_ci sdp->no_write_same = 0; 57662306a36Sopenharmony_ci sdkp->max_ws_blocks = max; 57762306a36Sopenharmony_ci } 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci sd_config_write_same(sdkp); 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci return count; 58262306a36Sopenharmony_ci} 58362306a36Sopenharmony_cistatic DEVICE_ATTR_RW(max_write_same_blocks); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_cistatic ssize_t 58662306a36Sopenharmony_cizoned_cap_show(struct device *dev, struct device_attribute *attr, char *buf) 58762306a36Sopenharmony_ci{ 58862306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci if (sdkp->device->type == TYPE_ZBC) 59162306a36Sopenharmony_ci return sprintf(buf, "host-managed\n"); 59262306a36Sopenharmony_ci if (sdkp->zoned == 1) 59362306a36Sopenharmony_ci return sprintf(buf, "host-aware\n"); 59462306a36Sopenharmony_ci if (sdkp->zoned == 2) 59562306a36Sopenharmony_ci return sprintf(buf, "drive-managed\n"); 59662306a36Sopenharmony_ci return sprintf(buf, "none\n"); 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_cistatic DEVICE_ATTR_RO(zoned_cap); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_cistatic ssize_t 60162306a36Sopenharmony_cimax_retries_store(struct device *dev, struct device_attribute *attr, 60262306a36Sopenharmony_ci const char *buf, size_t count) 60362306a36Sopenharmony_ci{ 60462306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 60562306a36Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 60662306a36Sopenharmony_ci int retries, err; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci err = kstrtoint(buf, 10, &retries); 60962306a36Sopenharmony_ci if (err) 61062306a36Sopenharmony_ci return err; 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci if (retries == SCSI_CMD_RETRIES_NO_LIMIT || retries <= SD_MAX_RETRIES) { 61362306a36Sopenharmony_ci sdkp->max_retries = retries; 61462306a36Sopenharmony_ci return count; 61562306a36Sopenharmony_ci } 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci sdev_printk(KERN_ERR, sdev, "max_retries must be between -1 and %d\n", 61862306a36Sopenharmony_ci SD_MAX_RETRIES); 61962306a36Sopenharmony_ci return -EINVAL; 62062306a36Sopenharmony_ci} 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_cistatic ssize_t 62362306a36Sopenharmony_cimax_retries_show(struct device *dev, struct device_attribute *attr, 62462306a36Sopenharmony_ci char *buf) 62562306a36Sopenharmony_ci{ 62662306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci return sprintf(buf, "%d\n", sdkp->max_retries); 62962306a36Sopenharmony_ci} 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_cistatic DEVICE_ATTR_RW(max_retries); 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cistatic struct attribute *sd_disk_attrs[] = { 63462306a36Sopenharmony_ci &dev_attr_cache_type.attr, 63562306a36Sopenharmony_ci &dev_attr_FUA.attr, 63662306a36Sopenharmony_ci &dev_attr_allow_restart.attr, 63762306a36Sopenharmony_ci &dev_attr_manage_start_stop.attr, 63862306a36Sopenharmony_ci &dev_attr_manage_system_start_stop.attr, 63962306a36Sopenharmony_ci &dev_attr_manage_runtime_start_stop.attr, 64062306a36Sopenharmony_ci &dev_attr_manage_shutdown.attr, 64162306a36Sopenharmony_ci &dev_attr_protection_type.attr, 64262306a36Sopenharmony_ci &dev_attr_protection_mode.attr, 64362306a36Sopenharmony_ci &dev_attr_app_tag_own.attr, 64462306a36Sopenharmony_ci &dev_attr_thin_provisioning.attr, 64562306a36Sopenharmony_ci &dev_attr_provisioning_mode.attr, 64662306a36Sopenharmony_ci &dev_attr_zeroing_mode.attr, 64762306a36Sopenharmony_ci &dev_attr_max_write_same_blocks.attr, 64862306a36Sopenharmony_ci &dev_attr_max_medium_access_timeouts.attr, 64962306a36Sopenharmony_ci &dev_attr_zoned_cap.attr, 65062306a36Sopenharmony_ci &dev_attr_max_retries.attr, 65162306a36Sopenharmony_ci NULL, 65262306a36Sopenharmony_ci}; 65362306a36Sopenharmony_ciATTRIBUTE_GROUPS(sd_disk); 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_cistatic struct class sd_disk_class = { 65662306a36Sopenharmony_ci .name = "scsi_disk", 65762306a36Sopenharmony_ci .dev_release = scsi_disk_release, 65862306a36Sopenharmony_ci .dev_groups = sd_disk_groups, 65962306a36Sopenharmony_ci}; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci/* 66262306a36Sopenharmony_ci * Don't request a new module, as that could deadlock in multipath 66362306a36Sopenharmony_ci * environment. 66462306a36Sopenharmony_ci */ 66562306a36Sopenharmony_cistatic void sd_default_probe(dev_t devt) 66662306a36Sopenharmony_ci{ 66762306a36Sopenharmony_ci} 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci/* 67062306a36Sopenharmony_ci * Device no to disk mapping: 67162306a36Sopenharmony_ci * 67262306a36Sopenharmony_ci * major disc2 disc p1 67362306a36Sopenharmony_ci * |............|.............|....|....| <- dev_t 67462306a36Sopenharmony_ci * 31 20 19 8 7 4 3 0 67562306a36Sopenharmony_ci * 67662306a36Sopenharmony_ci * Inside a major, we have 16k disks, however mapped non- 67762306a36Sopenharmony_ci * contiguously. The first 16 disks are for major0, the next 67862306a36Sopenharmony_ci * ones with major1, ... Disk 256 is for major0 again, disk 272 67962306a36Sopenharmony_ci * for major1, ... 68062306a36Sopenharmony_ci * As we stay compatible with our numbering scheme, we can reuse 68162306a36Sopenharmony_ci * the well-know SCSI majors 8, 65--71, 136--143. 68262306a36Sopenharmony_ci */ 68362306a36Sopenharmony_cistatic int sd_major(int major_idx) 68462306a36Sopenharmony_ci{ 68562306a36Sopenharmony_ci switch (major_idx) { 68662306a36Sopenharmony_ci case 0: 68762306a36Sopenharmony_ci return SCSI_DISK0_MAJOR; 68862306a36Sopenharmony_ci case 1 ... 7: 68962306a36Sopenharmony_ci return SCSI_DISK1_MAJOR + major_idx - 1; 69062306a36Sopenharmony_ci case 8 ... 15: 69162306a36Sopenharmony_ci return SCSI_DISK8_MAJOR + major_idx - 8; 69262306a36Sopenharmony_ci default: 69362306a36Sopenharmony_ci BUG(); 69462306a36Sopenharmony_ci return 0; /* shut up gcc */ 69562306a36Sopenharmony_ci } 69662306a36Sopenharmony_ci} 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci#ifdef CONFIG_BLK_SED_OPAL 69962306a36Sopenharmony_cistatic int sd_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, 70062306a36Sopenharmony_ci size_t len, bool send) 70162306a36Sopenharmony_ci{ 70262306a36Sopenharmony_ci struct scsi_disk *sdkp = data; 70362306a36Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 70462306a36Sopenharmony_ci u8 cdb[12] = { 0, }; 70562306a36Sopenharmony_ci const struct scsi_exec_args exec_args = { 70662306a36Sopenharmony_ci .req_flags = BLK_MQ_REQ_PM, 70762306a36Sopenharmony_ci }; 70862306a36Sopenharmony_ci int ret; 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci cdb[0] = send ? SECURITY_PROTOCOL_OUT : SECURITY_PROTOCOL_IN; 71162306a36Sopenharmony_ci cdb[1] = secp; 71262306a36Sopenharmony_ci put_unaligned_be16(spsp, &cdb[2]); 71362306a36Sopenharmony_ci put_unaligned_be32(len, &cdb[6]); 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci ret = scsi_execute_cmd(sdev, cdb, send ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 71662306a36Sopenharmony_ci buffer, len, SD_TIMEOUT, sdkp->max_retries, 71762306a36Sopenharmony_ci &exec_args); 71862306a36Sopenharmony_ci return ret <= 0 ? ret : -EIO; 71962306a36Sopenharmony_ci} 72062306a36Sopenharmony_ci#endif /* CONFIG_BLK_SED_OPAL */ 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci/* 72362306a36Sopenharmony_ci * Look up the DIX operation based on whether the command is read or 72462306a36Sopenharmony_ci * write and whether dix and dif are enabled. 72562306a36Sopenharmony_ci */ 72662306a36Sopenharmony_cistatic unsigned int sd_prot_op(bool write, bool dix, bool dif) 72762306a36Sopenharmony_ci{ 72862306a36Sopenharmony_ci /* Lookup table: bit 2 (write), bit 1 (dix), bit 0 (dif) */ 72962306a36Sopenharmony_ci static const unsigned int ops[] = { /* wrt dix dif */ 73062306a36Sopenharmony_ci SCSI_PROT_NORMAL, /* 0 0 0 */ 73162306a36Sopenharmony_ci SCSI_PROT_READ_STRIP, /* 0 0 1 */ 73262306a36Sopenharmony_ci SCSI_PROT_READ_INSERT, /* 0 1 0 */ 73362306a36Sopenharmony_ci SCSI_PROT_READ_PASS, /* 0 1 1 */ 73462306a36Sopenharmony_ci SCSI_PROT_NORMAL, /* 1 0 0 */ 73562306a36Sopenharmony_ci SCSI_PROT_WRITE_INSERT, /* 1 0 1 */ 73662306a36Sopenharmony_ci SCSI_PROT_WRITE_STRIP, /* 1 1 0 */ 73762306a36Sopenharmony_ci SCSI_PROT_WRITE_PASS, /* 1 1 1 */ 73862306a36Sopenharmony_ci }; 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci return ops[write << 2 | dix << 1 | dif]; 74162306a36Sopenharmony_ci} 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci/* 74462306a36Sopenharmony_ci * Returns a mask of the protection flags that are valid for a given DIX 74562306a36Sopenharmony_ci * operation. 74662306a36Sopenharmony_ci */ 74762306a36Sopenharmony_cistatic unsigned int sd_prot_flag_mask(unsigned int prot_op) 74862306a36Sopenharmony_ci{ 74962306a36Sopenharmony_ci static const unsigned int flag_mask[] = { 75062306a36Sopenharmony_ci [SCSI_PROT_NORMAL] = 0, 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci [SCSI_PROT_READ_STRIP] = SCSI_PROT_TRANSFER_PI | 75362306a36Sopenharmony_ci SCSI_PROT_GUARD_CHECK | 75462306a36Sopenharmony_ci SCSI_PROT_REF_CHECK | 75562306a36Sopenharmony_ci SCSI_PROT_REF_INCREMENT, 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci [SCSI_PROT_READ_INSERT] = SCSI_PROT_REF_INCREMENT | 75862306a36Sopenharmony_ci SCSI_PROT_IP_CHECKSUM, 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci [SCSI_PROT_READ_PASS] = SCSI_PROT_TRANSFER_PI | 76162306a36Sopenharmony_ci SCSI_PROT_GUARD_CHECK | 76262306a36Sopenharmony_ci SCSI_PROT_REF_CHECK | 76362306a36Sopenharmony_ci SCSI_PROT_REF_INCREMENT | 76462306a36Sopenharmony_ci SCSI_PROT_IP_CHECKSUM, 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci [SCSI_PROT_WRITE_INSERT] = SCSI_PROT_TRANSFER_PI | 76762306a36Sopenharmony_ci SCSI_PROT_REF_INCREMENT, 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci [SCSI_PROT_WRITE_STRIP] = SCSI_PROT_GUARD_CHECK | 77062306a36Sopenharmony_ci SCSI_PROT_REF_CHECK | 77162306a36Sopenharmony_ci SCSI_PROT_REF_INCREMENT | 77262306a36Sopenharmony_ci SCSI_PROT_IP_CHECKSUM, 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci [SCSI_PROT_WRITE_PASS] = SCSI_PROT_TRANSFER_PI | 77562306a36Sopenharmony_ci SCSI_PROT_GUARD_CHECK | 77662306a36Sopenharmony_ci SCSI_PROT_REF_CHECK | 77762306a36Sopenharmony_ci SCSI_PROT_REF_INCREMENT | 77862306a36Sopenharmony_ci SCSI_PROT_IP_CHECKSUM, 77962306a36Sopenharmony_ci }; 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci return flag_mask[prot_op]; 78262306a36Sopenharmony_ci} 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_cistatic unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd, 78562306a36Sopenharmony_ci unsigned int dix, unsigned int dif) 78662306a36Sopenharmony_ci{ 78762306a36Sopenharmony_ci struct request *rq = scsi_cmd_to_rq(scmd); 78862306a36Sopenharmony_ci struct bio *bio = rq->bio; 78962306a36Sopenharmony_ci unsigned int prot_op = sd_prot_op(rq_data_dir(rq), dix, dif); 79062306a36Sopenharmony_ci unsigned int protect = 0; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci if (dix) { /* DIX Type 0, 1, 2, 3 */ 79362306a36Sopenharmony_ci if (bio_integrity_flagged(bio, BIP_IP_CHECKSUM)) 79462306a36Sopenharmony_ci scmd->prot_flags |= SCSI_PROT_IP_CHECKSUM; 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci if (bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false) 79762306a36Sopenharmony_ci scmd->prot_flags |= SCSI_PROT_GUARD_CHECK; 79862306a36Sopenharmony_ci } 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci if (dif != T10_PI_TYPE3_PROTECTION) { /* DIX/DIF Type 0, 1, 2 */ 80162306a36Sopenharmony_ci scmd->prot_flags |= SCSI_PROT_REF_INCREMENT; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci if (bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false) 80462306a36Sopenharmony_ci scmd->prot_flags |= SCSI_PROT_REF_CHECK; 80562306a36Sopenharmony_ci } 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci if (dif) { /* DIX/DIF Type 1, 2, 3 */ 80862306a36Sopenharmony_ci scmd->prot_flags |= SCSI_PROT_TRANSFER_PI; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci if (bio_integrity_flagged(bio, BIP_DISK_NOCHECK)) 81162306a36Sopenharmony_ci protect = 3 << 5; /* Disable target PI checking */ 81262306a36Sopenharmony_ci else 81362306a36Sopenharmony_ci protect = 1 << 5; /* Enable target PI checking */ 81462306a36Sopenharmony_ci } 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci scsi_set_prot_op(scmd, prot_op); 81762306a36Sopenharmony_ci scsi_set_prot_type(scmd, dif); 81862306a36Sopenharmony_ci scmd->prot_flags &= sd_prot_flag_mask(prot_op); 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci return protect; 82162306a36Sopenharmony_ci} 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_cistatic void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) 82462306a36Sopenharmony_ci{ 82562306a36Sopenharmony_ci struct request_queue *q = sdkp->disk->queue; 82662306a36Sopenharmony_ci unsigned int logical_block_size = sdkp->device->sector_size; 82762306a36Sopenharmony_ci unsigned int max_blocks = 0; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci q->limits.discard_alignment = 83062306a36Sopenharmony_ci sdkp->unmap_alignment * logical_block_size; 83162306a36Sopenharmony_ci q->limits.discard_granularity = 83262306a36Sopenharmony_ci max(sdkp->physical_block_size, 83362306a36Sopenharmony_ci sdkp->unmap_granularity * logical_block_size); 83462306a36Sopenharmony_ci sdkp->provisioning_mode = mode; 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci switch (mode) { 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci case SD_LBP_FULL: 83962306a36Sopenharmony_ci case SD_LBP_DISABLE: 84062306a36Sopenharmony_ci blk_queue_max_discard_sectors(q, 0); 84162306a36Sopenharmony_ci return; 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci case SD_LBP_UNMAP: 84462306a36Sopenharmony_ci max_blocks = min_not_zero(sdkp->max_unmap_blocks, 84562306a36Sopenharmony_ci (u32)SD_MAX_WS16_BLOCKS); 84662306a36Sopenharmony_ci break; 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci case SD_LBP_WS16: 84962306a36Sopenharmony_ci if (sdkp->device->unmap_limit_for_ws) 85062306a36Sopenharmony_ci max_blocks = sdkp->max_unmap_blocks; 85162306a36Sopenharmony_ci else 85262306a36Sopenharmony_ci max_blocks = sdkp->max_ws_blocks; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci max_blocks = min_not_zero(max_blocks, (u32)SD_MAX_WS16_BLOCKS); 85562306a36Sopenharmony_ci break; 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci case SD_LBP_WS10: 85862306a36Sopenharmony_ci if (sdkp->device->unmap_limit_for_ws) 85962306a36Sopenharmony_ci max_blocks = sdkp->max_unmap_blocks; 86062306a36Sopenharmony_ci else 86162306a36Sopenharmony_ci max_blocks = sdkp->max_ws_blocks; 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci max_blocks = min_not_zero(max_blocks, (u32)SD_MAX_WS10_BLOCKS); 86462306a36Sopenharmony_ci break; 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci case SD_LBP_ZERO: 86762306a36Sopenharmony_ci max_blocks = min_not_zero(sdkp->max_ws_blocks, 86862306a36Sopenharmony_ci (u32)SD_MAX_WS10_BLOCKS); 86962306a36Sopenharmony_ci break; 87062306a36Sopenharmony_ci } 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci blk_queue_max_discard_sectors(q, max_blocks * (logical_block_size >> 9)); 87362306a36Sopenharmony_ci} 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_cistatic void *sd_set_special_bvec(struct request *rq, unsigned int data_len) 87662306a36Sopenharmony_ci{ 87762306a36Sopenharmony_ci struct page *page; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci page = mempool_alloc(sd_page_pool, GFP_ATOMIC); 88062306a36Sopenharmony_ci if (!page) 88162306a36Sopenharmony_ci return NULL; 88262306a36Sopenharmony_ci clear_highpage(page); 88362306a36Sopenharmony_ci bvec_set_page(&rq->special_vec, page, data_len, 0); 88462306a36Sopenharmony_ci rq->rq_flags |= RQF_SPECIAL_PAYLOAD; 88562306a36Sopenharmony_ci return bvec_virt(&rq->special_vec); 88662306a36Sopenharmony_ci} 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_cistatic blk_status_t sd_setup_unmap_cmnd(struct scsi_cmnd *cmd) 88962306a36Sopenharmony_ci{ 89062306a36Sopenharmony_ci struct scsi_device *sdp = cmd->device; 89162306a36Sopenharmony_ci struct request *rq = scsi_cmd_to_rq(cmd); 89262306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(rq->q->disk); 89362306a36Sopenharmony_ci u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq)); 89462306a36Sopenharmony_ci u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); 89562306a36Sopenharmony_ci unsigned int data_len = 24; 89662306a36Sopenharmony_ci char *buf; 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci buf = sd_set_special_bvec(rq, data_len); 89962306a36Sopenharmony_ci if (!buf) 90062306a36Sopenharmony_ci return BLK_STS_RESOURCE; 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci cmd->cmd_len = 10; 90362306a36Sopenharmony_ci cmd->cmnd[0] = UNMAP; 90462306a36Sopenharmony_ci cmd->cmnd[8] = 24; 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci put_unaligned_be16(6 + 16, &buf[0]); 90762306a36Sopenharmony_ci put_unaligned_be16(16, &buf[2]); 90862306a36Sopenharmony_ci put_unaligned_be64(lba, &buf[8]); 90962306a36Sopenharmony_ci put_unaligned_be32(nr_blocks, &buf[16]); 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci cmd->allowed = sdkp->max_retries; 91262306a36Sopenharmony_ci cmd->transfersize = data_len; 91362306a36Sopenharmony_ci rq->timeout = SD_TIMEOUT; 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci return scsi_alloc_sgtables(cmd); 91662306a36Sopenharmony_ci} 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_cistatic blk_status_t sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd, 91962306a36Sopenharmony_ci bool unmap) 92062306a36Sopenharmony_ci{ 92162306a36Sopenharmony_ci struct scsi_device *sdp = cmd->device; 92262306a36Sopenharmony_ci struct request *rq = scsi_cmd_to_rq(cmd); 92362306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(rq->q->disk); 92462306a36Sopenharmony_ci u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq)); 92562306a36Sopenharmony_ci u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); 92662306a36Sopenharmony_ci u32 data_len = sdp->sector_size; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci if (!sd_set_special_bvec(rq, data_len)) 92962306a36Sopenharmony_ci return BLK_STS_RESOURCE; 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci cmd->cmd_len = 16; 93262306a36Sopenharmony_ci cmd->cmnd[0] = WRITE_SAME_16; 93362306a36Sopenharmony_ci if (unmap) 93462306a36Sopenharmony_ci cmd->cmnd[1] = 0x8; /* UNMAP */ 93562306a36Sopenharmony_ci put_unaligned_be64(lba, &cmd->cmnd[2]); 93662306a36Sopenharmony_ci put_unaligned_be32(nr_blocks, &cmd->cmnd[10]); 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci cmd->allowed = sdkp->max_retries; 93962306a36Sopenharmony_ci cmd->transfersize = data_len; 94062306a36Sopenharmony_ci rq->timeout = unmap ? SD_TIMEOUT : SD_WRITE_SAME_TIMEOUT; 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci return scsi_alloc_sgtables(cmd); 94362306a36Sopenharmony_ci} 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_cistatic blk_status_t sd_setup_write_same10_cmnd(struct scsi_cmnd *cmd, 94662306a36Sopenharmony_ci bool unmap) 94762306a36Sopenharmony_ci{ 94862306a36Sopenharmony_ci struct scsi_device *sdp = cmd->device; 94962306a36Sopenharmony_ci struct request *rq = scsi_cmd_to_rq(cmd); 95062306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(rq->q->disk); 95162306a36Sopenharmony_ci u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq)); 95262306a36Sopenharmony_ci u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); 95362306a36Sopenharmony_ci u32 data_len = sdp->sector_size; 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci if (!sd_set_special_bvec(rq, data_len)) 95662306a36Sopenharmony_ci return BLK_STS_RESOURCE; 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci cmd->cmd_len = 10; 95962306a36Sopenharmony_ci cmd->cmnd[0] = WRITE_SAME; 96062306a36Sopenharmony_ci if (unmap) 96162306a36Sopenharmony_ci cmd->cmnd[1] = 0x8; /* UNMAP */ 96262306a36Sopenharmony_ci put_unaligned_be32(lba, &cmd->cmnd[2]); 96362306a36Sopenharmony_ci put_unaligned_be16(nr_blocks, &cmd->cmnd[7]); 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci cmd->allowed = sdkp->max_retries; 96662306a36Sopenharmony_ci cmd->transfersize = data_len; 96762306a36Sopenharmony_ci rq->timeout = unmap ? SD_TIMEOUT : SD_WRITE_SAME_TIMEOUT; 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci return scsi_alloc_sgtables(cmd); 97062306a36Sopenharmony_ci} 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_cistatic blk_status_t sd_setup_write_zeroes_cmnd(struct scsi_cmnd *cmd) 97362306a36Sopenharmony_ci{ 97462306a36Sopenharmony_ci struct request *rq = scsi_cmd_to_rq(cmd); 97562306a36Sopenharmony_ci struct scsi_device *sdp = cmd->device; 97662306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(rq->q->disk); 97762306a36Sopenharmony_ci u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq)); 97862306a36Sopenharmony_ci u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci if (!(rq->cmd_flags & REQ_NOUNMAP)) { 98162306a36Sopenharmony_ci switch (sdkp->zeroing_mode) { 98262306a36Sopenharmony_ci case SD_ZERO_WS16_UNMAP: 98362306a36Sopenharmony_ci return sd_setup_write_same16_cmnd(cmd, true); 98462306a36Sopenharmony_ci case SD_ZERO_WS10_UNMAP: 98562306a36Sopenharmony_ci return sd_setup_write_same10_cmnd(cmd, true); 98662306a36Sopenharmony_ci } 98762306a36Sopenharmony_ci } 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci if (sdp->no_write_same) { 99062306a36Sopenharmony_ci rq->rq_flags |= RQF_QUIET; 99162306a36Sopenharmony_ci return BLK_STS_TARGET; 99262306a36Sopenharmony_ci } 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci if (sdkp->ws16 || lba > 0xffffffff || nr_blocks > 0xffff) 99562306a36Sopenharmony_ci return sd_setup_write_same16_cmnd(cmd, false); 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci return sd_setup_write_same10_cmnd(cmd, false); 99862306a36Sopenharmony_ci} 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_cistatic void sd_config_write_same(struct scsi_disk *sdkp) 100162306a36Sopenharmony_ci{ 100262306a36Sopenharmony_ci struct request_queue *q = sdkp->disk->queue; 100362306a36Sopenharmony_ci unsigned int logical_block_size = sdkp->device->sector_size; 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci if (sdkp->device->no_write_same) { 100662306a36Sopenharmony_ci sdkp->max_ws_blocks = 0; 100762306a36Sopenharmony_ci goto out; 100862306a36Sopenharmony_ci } 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci /* Some devices can not handle block counts above 0xffff despite 101162306a36Sopenharmony_ci * supporting WRITE SAME(16). Consequently we default to 64k 101262306a36Sopenharmony_ci * blocks per I/O unless the device explicitly advertises a 101362306a36Sopenharmony_ci * bigger limit. 101462306a36Sopenharmony_ci */ 101562306a36Sopenharmony_ci if (sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS) 101662306a36Sopenharmony_ci sdkp->max_ws_blocks = min_not_zero(sdkp->max_ws_blocks, 101762306a36Sopenharmony_ci (u32)SD_MAX_WS16_BLOCKS); 101862306a36Sopenharmony_ci else if (sdkp->ws16 || sdkp->ws10 || sdkp->device->no_report_opcodes) 101962306a36Sopenharmony_ci sdkp->max_ws_blocks = min_not_zero(sdkp->max_ws_blocks, 102062306a36Sopenharmony_ci (u32)SD_MAX_WS10_BLOCKS); 102162306a36Sopenharmony_ci else { 102262306a36Sopenharmony_ci sdkp->device->no_write_same = 1; 102362306a36Sopenharmony_ci sdkp->max_ws_blocks = 0; 102462306a36Sopenharmony_ci } 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci if (sdkp->lbprz && sdkp->lbpws) 102762306a36Sopenharmony_ci sdkp->zeroing_mode = SD_ZERO_WS16_UNMAP; 102862306a36Sopenharmony_ci else if (sdkp->lbprz && sdkp->lbpws10) 102962306a36Sopenharmony_ci sdkp->zeroing_mode = SD_ZERO_WS10_UNMAP; 103062306a36Sopenharmony_ci else if (sdkp->max_ws_blocks) 103162306a36Sopenharmony_ci sdkp->zeroing_mode = SD_ZERO_WS; 103262306a36Sopenharmony_ci else 103362306a36Sopenharmony_ci sdkp->zeroing_mode = SD_ZERO_WRITE; 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci if (sdkp->max_ws_blocks && 103662306a36Sopenharmony_ci sdkp->physical_block_size > logical_block_size) { 103762306a36Sopenharmony_ci /* 103862306a36Sopenharmony_ci * Reporting a maximum number of blocks that is not aligned 103962306a36Sopenharmony_ci * on the device physical size would cause a large write same 104062306a36Sopenharmony_ci * request to be split into physically unaligned chunks by 104162306a36Sopenharmony_ci * __blkdev_issue_write_zeroes() even if the caller of this 104262306a36Sopenharmony_ci * functions took care to align the large request. So make sure 104362306a36Sopenharmony_ci * the maximum reported is aligned to the device physical block 104462306a36Sopenharmony_ci * size. This is only an optional optimization for regular 104562306a36Sopenharmony_ci * disks, but this is mandatory to avoid failure of large write 104662306a36Sopenharmony_ci * same requests directed at sequential write required zones of 104762306a36Sopenharmony_ci * host-managed ZBC disks. 104862306a36Sopenharmony_ci */ 104962306a36Sopenharmony_ci sdkp->max_ws_blocks = 105062306a36Sopenharmony_ci round_down(sdkp->max_ws_blocks, 105162306a36Sopenharmony_ci bytes_to_logical(sdkp->device, 105262306a36Sopenharmony_ci sdkp->physical_block_size)); 105362306a36Sopenharmony_ci } 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ciout: 105662306a36Sopenharmony_ci blk_queue_max_write_zeroes_sectors(q, sdkp->max_ws_blocks * 105762306a36Sopenharmony_ci (logical_block_size >> 9)); 105862306a36Sopenharmony_ci} 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_cistatic blk_status_t sd_setup_flush_cmnd(struct scsi_cmnd *cmd) 106162306a36Sopenharmony_ci{ 106262306a36Sopenharmony_ci struct request *rq = scsi_cmd_to_rq(cmd); 106362306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(rq->q->disk); 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci /* flush requests don't perform I/O, zero the S/G table */ 106662306a36Sopenharmony_ci memset(&cmd->sdb, 0, sizeof(cmd->sdb)); 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci if (cmd->device->use_16_for_sync) { 106962306a36Sopenharmony_ci cmd->cmnd[0] = SYNCHRONIZE_CACHE_16; 107062306a36Sopenharmony_ci cmd->cmd_len = 16; 107162306a36Sopenharmony_ci } else { 107262306a36Sopenharmony_ci cmd->cmnd[0] = SYNCHRONIZE_CACHE; 107362306a36Sopenharmony_ci cmd->cmd_len = 10; 107462306a36Sopenharmony_ci } 107562306a36Sopenharmony_ci cmd->transfersize = 0; 107662306a36Sopenharmony_ci cmd->allowed = sdkp->max_retries; 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci rq->timeout = rq->q->rq_timeout * SD_FLUSH_TIMEOUT_MULTIPLIER; 107962306a36Sopenharmony_ci return BLK_STS_OK; 108062306a36Sopenharmony_ci} 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_cistatic blk_status_t sd_setup_rw32_cmnd(struct scsi_cmnd *cmd, bool write, 108362306a36Sopenharmony_ci sector_t lba, unsigned int nr_blocks, 108462306a36Sopenharmony_ci unsigned char flags, unsigned int dld) 108562306a36Sopenharmony_ci{ 108662306a36Sopenharmony_ci cmd->cmd_len = SD_EXT_CDB_SIZE; 108762306a36Sopenharmony_ci cmd->cmnd[0] = VARIABLE_LENGTH_CMD; 108862306a36Sopenharmony_ci cmd->cmnd[7] = 0x18; /* Additional CDB len */ 108962306a36Sopenharmony_ci cmd->cmnd[9] = write ? WRITE_32 : READ_32; 109062306a36Sopenharmony_ci cmd->cmnd[10] = flags; 109162306a36Sopenharmony_ci cmd->cmnd[11] = dld & 0x07; 109262306a36Sopenharmony_ci put_unaligned_be64(lba, &cmd->cmnd[12]); 109362306a36Sopenharmony_ci put_unaligned_be32(lba, &cmd->cmnd[20]); /* Expected Indirect LBA */ 109462306a36Sopenharmony_ci put_unaligned_be32(nr_blocks, &cmd->cmnd[28]); 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci return BLK_STS_OK; 109762306a36Sopenharmony_ci} 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_cistatic blk_status_t sd_setup_rw16_cmnd(struct scsi_cmnd *cmd, bool write, 110062306a36Sopenharmony_ci sector_t lba, unsigned int nr_blocks, 110162306a36Sopenharmony_ci unsigned char flags, unsigned int dld) 110262306a36Sopenharmony_ci{ 110362306a36Sopenharmony_ci cmd->cmd_len = 16; 110462306a36Sopenharmony_ci cmd->cmnd[0] = write ? WRITE_16 : READ_16; 110562306a36Sopenharmony_ci cmd->cmnd[1] = flags | ((dld >> 2) & 0x01); 110662306a36Sopenharmony_ci cmd->cmnd[14] = (dld & 0x03) << 6; 110762306a36Sopenharmony_ci cmd->cmnd[15] = 0; 110862306a36Sopenharmony_ci put_unaligned_be64(lba, &cmd->cmnd[2]); 110962306a36Sopenharmony_ci put_unaligned_be32(nr_blocks, &cmd->cmnd[10]); 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci return BLK_STS_OK; 111262306a36Sopenharmony_ci} 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_cistatic blk_status_t sd_setup_rw10_cmnd(struct scsi_cmnd *cmd, bool write, 111562306a36Sopenharmony_ci sector_t lba, unsigned int nr_blocks, 111662306a36Sopenharmony_ci unsigned char flags) 111762306a36Sopenharmony_ci{ 111862306a36Sopenharmony_ci cmd->cmd_len = 10; 111962306a36Sopenharmony_ci cmd->cmnd[0] = write ? WRITE_10 : READ_10; 112062306a36Sopenharmony_ci cmd->cmnd[1] = flags; 112162306a36Sopenharmony_ci cmd->cmnd[6] = 0; 112262306a36Sopenharmony_ci cmd->cmnd[9] = 0; 112362306a36Sopenharmony_ci put_unaligned_be32(lba, &cmd->cmnd[2]); 112462306a36Sopenharmony_ci put_unaligned_be16(nr_blocks, &cmd->cmnd[7]); 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci return BLK_STS_OK; 112762306a36Sopenharmony_ci} 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_cistatic blk_status_t sd_setup_rw6_cmnd(struct scsi_cmnd *cmd, bool write, 113062306a36Sopenharmony_ci sector_t lba, unsigned int nr_blocks, 113162306a36Sopenharmony_ci unsigned char flags) 113262306a36Sopenharmony_ci{ 113362306a36Sopenharmony_ci /* Avoid that 0 blocks gets translated into 256 blocks. */ 113462306a36Sopenharmony_ci if (WARN_ON_ONCE(nr_blocks == 0)) 113562306a36Sopenharmony_ci return BLK_STS_IOERR; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci if (unlikely(flags & 0x8)) { 113862306a36Sopenharmony_ci /* 113962306a36Sopenharmony_ci * This happens only if this drive failed 10byte rw 114062306a36Sopenharmony_ci * command with ILLEGAL_REQUEST during operation and 114162306a36Sopenharmony_ci * thus turned off use_10_for_rw. 114262306a36Sopenharmony_ci */ 114362306a36Sopenharmony_ci scmd_printk(KERN_ERR, cmd, "FUA write on READ/WRITE(6) drive\n"); 114462306a36Sopenharmony_ci return BLK_STS_IOERR; 114562306a36Sopenharmony_ci } 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci cmd->cmd_len = 6; 114862306a36Sopenharmony_ci cmd->cmnd[0] = write ? WRITE_6 : READ_6; 114962306a36Sopenharmony_ci cmd->cmnd[1] = (lba >> 16) & 0x1f; 115062306a36Sopenharmony_ci cmd->cmnd[2] = (lba >> 8) & 0xff; 115162306a36Sopenharmony_ci cmd->cmnd[3] = lba & 0xff; 115262306a36Sopenharmony_ci cmd->cmnd[4] = nr_blocks; 115362306a36Sopenharmony_ci cmd->cmnd[5] = 0; 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci return BLK_STS_OK; 115662306a36Sopenharmony_ci} 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci/* 115962306a36Sopenharmony_ci * Check if a command has a duration limit set. If it does, and the target 116062306a36Sopenharmony_ci * device supports CDL and the feature is enabled, return the limit 116162306a36Sopenharmony_ci * descriptor index to use. Return 0 (no limit) otherwise. 116262306a36Sopenharmony_ci */ 116362306a36Sopenharmony_cistatic int sd_cdl_dld(struct scsi_disk *sdkp, struct scsi_cmnd *scmd) 116462306a36Sopenharmony_ci{ 116562306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 116662306a36Sopenharmony_ci int hint; 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci if (!sdp->cdl_supported || !sdp->cdl_enable) 116962306a36Sopenharmony_ci return 0; 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci /* 117262306a36Sopenharmony_ci * Use "no limit" if the request ioprio does not specify a duration 117362306a36Sopenharmony_ci * limit hint. 117462306a36Sopenharmony_ci */ 117562306a36Sopenharmony_ci hint = IOPRIO_PRIO_HINT(req_get_ioprio(scsi_cmd_to_rq(scmd))); 117662306a36Sopenharmony_ci if (hint < IOPRIO_HINT_DEV_DURATION_LIMIT_1 || 117762306a36Sopenharmony_ci hint > IOPRIO_HINT_DEV_DURATION_LIMIT_7) 117862306a36Sopenharmony_ci return 0; 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci return (hint - IOPRIO_HINT_DEV_DURATION_LIMIT_1) + 1; 118162306a36Sopenharmony_ci} 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_cistatic blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) 118462306a36Sopenharmony_ci{ 118562306a36Sopenharmony_ci struct request *rq = scsi_cmd_to_rq(cmd); 118662306a36Sopenharmony_ci struct scsi_device *sdp = cmd->device; 118762306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(rq->q->disk); 118862306a36Sopenharmony_ci sector_t lba = sectors_to_logical(sdp, blk_rq_pos(rq)); 118962306a36Sopenharmony_ci sector_t threshold; 119062306a36Sopenharmony_ci unsigned int nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); 119162306a36Sopenharmony_ci unsigned int mask = logical_to_sectors(sdp, 1) - 1; 119262306a36Sopenharmony_ci bool write = rq_data_dir(rq) == WRITE; 119362306a36Sopenharmony_ci unsigned char protect, fua; 119462306a36Sopenharmony_ci unsigned int dld; 119562306a36Sopenharmony_ci blk_status_t ret; 119662306a36Sopenharmony_ci unsigned int dif; 119762306a36Sopenharmony_ci bool dix; 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_ci ret = scsi_alloc_sgtables(cmd); 120062306a36Sopenharmony_ci if (ret != BLK_STS_OK) 120162306a36Sopenharmony_ci return ret; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci ret = BLK_STS_IOERR; 120462306a36Sopenharmony_ci if (!scsi_device_online(sdp) || sdp->changed) { 120562306a36Sopenharmony_ci scmd_printk(KERN_ERR, cmd, "device offline or changed\n"); 120662306a36Sopenharmony_ci goto fail; 120762306a36Sopenharmony_ci } 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci if (blk_rq_pos(rq) + blk_rq_sectors(rq) > get_capacity(rq->q->disk)) { 121062306a36Sopenharmony_ci scmd_printk(KERN_ERR, cmd, "access beyond end of device\n"); 121162306a36Sopenharmony_ci goto fail; 121262306a36Sopenharmony_ci } 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci if ((blk_rq_pos(rq) & mask) || (blk_rq_sectors(rq) & mask)) { 121562306a36Sopenharmony_ci scmd_printk(KERN_ERR, cmd, "request not aligned to the logical block size\n"); 121662306a36Sopenharmony_ci goto fail; 121762306a36Sopenharmony_ci } 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci /* 122062306a36Sopenharmony_ci * Some SD card readers can't handle accesses which touch the 122162306a36Sopenharmony_ci * last one or two logical blocks. Split accesses as needed. 122262306a36Sopenharmony_ci */ 122362306a36Sopenharmony_ci threshold = sdkp->capacity - SD_LAST_BUGGY_SECTORS; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci if (unlikely(sdp->last_sector_bug && lba + nr_blocks > threshold)) { 122662306a36Sopenharmony_ci if (lba < threshold) { 122762306a36Sopenharmony_ci /* Access up to the threshold but not beyond */ 122862306a36Sopenharmony_ci nr_blocks = threshold - lba; 122962306a36Sopenharmony_ci } else { 123062306a36Sopenharmony_ci /* Access only a single logical block */ 123162306a36Sopenharmony_ci nr_blocks = 1; 123262306a36Sopenharmony_ci } 123362306a36Sopenharmony_ci } 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci if (req_op(rq) == REQ_OP_ZONE_APPEND) { 123662306a36Sopenharmony_ci ret = sd_zbc_prepare_zone_append(cmd, &lba, nr_blocks); 123762306a36Sopenharmony_ci if (ret) 123862306a36Sopenharmony_ci goto fail; 123962306a36Sopenharmony_ci } 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci fua = rq->cmd_flags & REQ_FUA ? 0x8 : 0; 124262306a36Sopenharmony_ci dix = scsi_prot_sg_count(cmd); 124362306a36Sopenharmony_ci dif = scsi_host_dif_capable(cmd->device->host, sdkp->protection_type); 124462306a36Sopenharmony_ci dld = sd_cdl_dld(sdkp, cmd); 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci if (dif || dix) 124762306a36Sopenharmony_ci protect = sd_setup_protect_cmnd(cmd, dix, dif); 124862306a36Sopenharmony_ci else 124962306a36Sopenharmony_ci protect = 0; 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci if (protect && sdkp->protection_type == T10_PI_TYPE2_PROTECTION) { 125262306a36Sopenharmony_ci ret = sd_setup_rw32_cmnd(cmd, write, lba, nr_blocks, 125362306a36Sopenharmony_ci protect | fua, dld); 125462306a36Sopenharmony_ci } else if (sdp->use_16_for_rw || (nr_blocks > 0xffff)) { 125562306a36Sopenharmony_ci ret = sd_setup_rw16_cmnd(cmd, write, lba, nr_blocks, 125662306a36Sopenharmony_ci protect | fua, dld); 125762306a36Sopenharmony_ci } else if ((nr_blocks > 0xff) || (lba > 0x1fffff) || 125862306a36Sopenharmony_ci sdp->use_10_for_rw || protect) { 125962306a36Sopenharmony_ci ret = sd_setup_rw10_cmnd(cmd, write, lba, nr_blocks, 126062306a36Sopenharmony_ci protect | fua); 126162306a36Sopenharmony_ci } else { 126262306a36Sopenharmony_ci ret = sd_setup_rw6_cmnd(cmd, write, lba, nr_blocks, 126362306a36Sopenharmony_ci protect | fua); 126462306a36Sopenharmony_ci } 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci if (unlikely(ret != BLK_STS_OK)) 126762306a36Sopenharmony_ci goto fail; 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci /* 127062306a36Sopenharmony_ci * We shouldn't disconnect in the middle of a sector, so with a dumb 127162306a36Sopenharmony_ci * host adapter, it's safe to assume that we can at least transfer 127262306a36Sopenharmony_ci * this many bytes between each connect / disconnect. 127362306a36Sopenharmony_ci */ 127462306a36Sopenharmony_ci cmd->transfersize = sdp->sector_size; 127562306a36Sopenharmony_ci cmd->underflow = nr_blocks << 9; 127662306a36Sopenharmony_ci cmd->allowed = sdkp->max_retries; 127762306a36Sopenharmony_ci cmd->sdb.length = nr_blocks * sdp->sector_size; 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci SCSI_LOG_HLQUEUE(1, 128062306a36Sopenharmony_ci scmd_printk(KERN_INFO, cmd, 128162306a36Sopenharmony_ci "%s: block=%llu, count=%d\n", __func__, 128262306a36Sopenharmony_ci (unsigned long long)blk_rq_pos(rq), 128362306a36Sopenharmony_ci blk_rq_sectors(rq))); 128462306a36Sopenharmony_ci SCSI_LOG_HLQUEUE(2, 128562306a36Sopenharmony_ci scmd_printk(KERN_INFO, cmd, 128662306a36Sopenharmony_ci "%s %d/%u 512 byte blocks.\n", 128762306a36Sopenharmony_ci write ? "writing" : "reading", nr_blocks, 128862306a36Sopenharmony_ci blk_rq_sectors(rq))); 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci /* 129162306a36Sopenharmony_ci * This indicates that the command is ready from our end to be queued. 129262306a36Sopenharmony_ci */ 129362306a36Sopenharmony_ci return BLK_STS_OK; 129462306a36Sopenharmony_cifail: 129562306a36Sopenharmony_ci scsi_free_sgtables(cmd); 129662306a36Sopenharmony_ci return ret; 129762306a36Sopenharmony_ci} 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_cistatic blk_status_t sd_init_command(struct scsi_cmnd *cmd) 130062306a36Sopenharmony_ci{ 130162306a36Sopenharmony_ci struct request *rq = scsi_cmd_to_rq(cmd); 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci switch (req_op(rq)) { 130462306a36Sopenharmony_ci case REQ_OP_DISCARD: 130562306a36Sopenharmony_ci switch (scsi_disk(rq->q->disk)->provisioning_mode) { 130662306a36Sopenharmony_ci case SD_LBP_UNMAP: 130762306a36Sopenharmony_ci return sd_setup_unmap_cmnd(cmd); 130862306a36Sopenharmony_ci case SD_LBP_WS16: 130962306a36Sopenharmony_ci return sd_setup_write_same16_cmnd(cmd, true); 131062306a36Sopenharmony_ci case SD_LBP_WS10: 131162306a36Sopenharmony_ci return sd_setup_write_same10_cmnd(cmd, true); 131262306a36Sopenharmony_ci case SD_LBP_ZERO: 131362306a36Sopenharmony_ci return sd_setup_write_same10_cmnd(cmd, false); 131462306a36Sopenharmony_ci default: 131562306a36Sopenharmony_ci return BLK_STS_TARGET; 131662306a36Sopenharmony_ci } 131762306a36Sopenharmony_ci case REQ_OP_WRITE_ZEROES: 131862306a36Sopenharmony_ci return sd_setup_write_zeroes_cmnd(cmd); 131962306a36Sopenharmony_ci case REQ_OP_FLUSH: 132062306a36Sopenharmony_ci return sd_setup_flush_cmnd(cmd); 132162306a36Sopenharmony_ci case REQ_OP_READ: 132262306a36Sopenharmony_ci case REQ_OP_WRITE: 132362306a36Sopenharmony_ci case REQ_OP_ZONE_APPEND: 132462306a36Sopenharmony_ci return sd_setup_read_write_cmnd(cmd); 132562306a36Sopenharmony_ci case REQ_OP_ZONE_RESET: 132662306a36Sopenharmony_ci return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_RESET_WRITE_POINTER, 132762306a36Sopenharmony_ci false); 132862306a36Sopenharmony_ci case REQ_OP_ZONE_RESET_ALL: 132962306a36Sopenharmony_ci return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_RESET_WRITE_POINTER, 133062306a36Sopenharmony_ci true); 133162306a36Sopenharmony_ci case REQ_OP_ZONE_OPEN: 133262306a36Sopenharmony_ci return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_OPEN_ZONE, false); 133362306a36Sopenharmony_ci case REQ_OP_ZONE_CLOSE: 133462306a36Sopenharmony_ci return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_CLOSE_ZONE, false); 133562306a36Sopenharmony_ci case REQ_OP_ZONE_FINISH: 133662306a36Sopenharmony_ci return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_FINISH_ZONE, false); 133762306a36Sopenharmony_ci default: 133862306a36Sopenharmony_ci WARN_ON_ONCE(1); 133962306a36Sopenharmony_ci return BLK_STS_NOTSUPP; 134062306a36Sopenharmony_ci } 134162306a36Sopenharmony_ci} 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_cistatic void sd_uninit_command(struct scsi_cmnd *SCpnt) 134462306a36Sopenharmony_ci{ 134562306a36Sopenharmony_ci struct request *rq = scsi_cmd_to_rq(SCpnt); 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci if (rq->rq_flags & RQF_SPECIAL_PAYLOAD) 134862306a36Sopenharmony_ci mempool_free(rq->special_vec.bv_page, sd_page_pool); 134962306a36Sopenharmony_ci} 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_cistatic bool sd_need_revalidate(struct gendisk *disk, struct scsi_disk *sdkp) 135262306a36Sopenharmony_ci{ 135362306a36Sopenharmony_ci if (sdkp->device->removable || sdkp->write_prot) { 135462306a36Sopenharmony_ci if (disk_check_media_change(disk)) 135562306a36Sopenharmony_ci return true; 135662306a36Sopenharmony_ci } 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci /* 135962306a36Sopenharmony_ci * Force a full rescan after ioctl(BLKRRPART). While the disk state has 136062306a36Sopenharmony_ci * nothing to do with partitions, BLKRRPART is used to force a full 136162306a36Sopenharmony_ci * revalidate after things like a format for historical reasons. 136262306a36Sopenharmony_ci */ 136362306a36Sopenharmony_ci return test_bit(GD_NEED_PART_SCAN, &disk->state); 136462306a36Sopenharmony_ci} 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci/** 136762306a36Sopenharmony_ci * sd_open - open a scsi disk device 136862306a36Sopenharmony_ci * @disk: disk to open 136962306a36Sopenharmony_ci * @mode: open mode 137062306a36Sopenharmony_ci * 137162306a36Sopenharmony_ci * Returns 0 if successful. Returns a negated errno value in case 137262306a36Sopenharmony_ci * of error. 137362306a36Sopenharmony_ci * 137462306a36Sopenharmony_ci * Note: This can be called from a user context (e.g. fsck(1) ) 137562306a36Sopenharmony_ci * or from within the kernel (e.g. as a result of a mount(1) ). 137662306a36Sopenharmony_ci * In the latter case @inode and @filp carry an abridged amount 137762306a36Sopenharmony_ci * of information as noted above. 137862306a36Sopenharmony_ci * 137962306a36Sopenharmony_ci * Locking: called with disk->open_mutex held. 138062306a36Sopenharmony_ci **/ 138162306a36Sopenharmony_cistatic int sd_open(struct gendisk *disk, blk_mode_t mode) 138262306a36Sopenharmony_ci{ 138362306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(disk); 138462306a36Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 138562306a36Sopenharmony_ci int retval; 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_ci if (scsi_device_get(sdev)) 138862306a36Sopenharmony_ci return -ENXIO; 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_open\n")); 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_ci /* 139362306a36Sopenharmony_ci * If the device is in error recovery, wait until it is done. 139462306a36Sopenharmony_ci * If the device is offline, then disallow any access to it. 139562306a36Sopenharmony_ci */ 139662306a36Sopenharmony_ci retval = -ENXIO; 139762306a36Sopenharmony_ci if (!scsi_block_when_processing_errors(sdev)) 139862306a36Sopenharmony_ci goto error_out; 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci if (sd_need_revalidate(disk, sdkp)) 140162306a36Sopenharmony_ci sd_revalidate_disk(disk); 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci /* 140462306a36Sopenharmony_ci * If the drive is empty, just let the open fail. 140562306a36Sopenharmony_ci */ 140662306a36Sopenharmony_ci retval = -ENOMEDIUM; 140762306a36Sopenharmony_ci if (sdev->removable && !sdkp->media_present && 140862306a36Sopenharmony_ci !(mode & BLK_OPEN_NDELAY)) 140962306a36Sopenharmony_ci goto error_out; 141062306a36Sopenharmony_ci 141162306a36Sopenharmony_ci /* 141262306a36Sopenharmony_ci * If the device has the write protect tab set, have the open fail 141362306a36Sopenharmony_ci * if the user expects to be able to write to the thing. 141462306a36Sopenharmony_ci */ 141562306a36Sopenharmony_ci retval = -EROFS; 141662306a36Sopenharmony_ci if (sdkp->write_prot && (mode & BLK_OPEN_WRITE)) 141762306a36Sopenharmony_ci goto error_out; 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci /* 142062306a36Sopenharmony_ci * It is possible that the disk changing stuff resulted in 142162306a36Sopenharmony_ci * the device being taken offline. If this is the case, 142262306a36Sopenharmony_ci * report this to the user, and don't pretend that the 142362306a36Sopenharmony_ci * open actually succeeded. 142462306a36Sopenharmony_ci */ 142562306a36Sopenharmony_ci retval = -ENXIO; 142662306a36Sopenharmony_ci if (!scsi_device_online(sdev)) 142762306a36Sopenharmony_ci goto error_out; 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci if ((atomic_inc_return(&sdkp->openers) == 1) && sdev->removable) { 143062306a36Sopenharmony_ci if (scsi_block_when_processing_errors(sdev)) 143162306a36Sopenharmony_ci scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); 143262306a36Sopenharmony_ci } 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci return 0; 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_cierror_out: 143762306a36Sopenharmony_ci scsi_device_put(sdev); 143862306a36Sopenharmony_ci return retval; 143962306a36Sopenharmony_ci} 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci/** 144262306a36Sopenharmony_ci * sd_release - invoked when the (last) close(2) is called on this 144362306a36Sopenharmony_ci * scsi disk. 144462306a36Sopenharmony_ci * @disk: disk to release 144562306a36Sopenharmony_ci * 144662306a36Sopenharmony_ci * Returns 0. 144762306a36Sopenharmony_ci * 144862306a36Sopenharmony_ci * Note: may block (uninterruptible) if error recovery is underway 144962306a36Sopenharmony_ci * on this disk. 145062306a36Sopenharmony_ci * 145162306a36Sopenharmony_ci * Locking: called with disk->open_mutex held. 145262306a36Sopenharmony_ci **/ 145362306a36Sopenharmony_cistatic void sd_release(struct gendisk *disk) 145462306a36Sopenharmony_ci{ 145562306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(disk); 145662306a36Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_ci SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n")); 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci if (atomic_dec_return(&sdkp->openers) == 0 && sdev->removable) { 146162306a36Sopenharmony_ci if (scsi_block_when_processing_errors(sdev)) 146262306a36Sopenharmony_ci scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); 146362306a36Sopenharmony_ci } 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_ci scsi_device_put(sdev); 146662306a36Sopenharmony_ci} 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_cistatic int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) 146962306a36Sopenharmony_ci{ 147062306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); 147162306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 147262306a36Sopenharmony_ci struct Scsi_Host *host = sdp->host; 147362306a36Sopenharmony_ci sector_t capacity = logical_to_sectors(sdp, sdkp->capacity); 147462306a36Sopenharmony_ci int diskinfo[4]; 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci /* default to most commonly used values */ 147762306a36Sopenharmony_ci diskinfo[0] = 0x40; /* 1 << 6 */ 147862306a36Sopenharmony_ci diskinfo[1] = 0x20; /* 1 << 5 */ 147962306a36Sopenharmony_ci diskinfo[2] = capacity >> 11; 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci /* override with calculated, extended default, or driver values */ 148262306a36Sopenharmony_ci if (host->hostt->bios_param) 148362306a36Sopenharmony_ci host->hostt->bios_param(sdp, bdev, capacity, diskinfo); 148462306a36Sopenharmony_ci else 148562306a36Sopenharmony_ci scsicam_bios_param(bdev, capacity, diskinfo); 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci geo->heads = diskinfo[0]; 148862306a36Sopenharmony_ci geo->sectors = diskinfo[1]; 148962306a36Sopenharmony_ci geo->cylinders = diskinfo[2]; 149062306a36Sopenharmony_ci return 0; 149162306a36Sopenharmony_ci} 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci/** 149462306a36Sopenharmony_ci * sd_ioctl - process an ioctl 149562306a36Sopenharmony_ci * @bdev: target block device 149662306a36Sopenharmony_ci * @mode: open mode 149762306a36Sopenharmony_ci * @cmd: ioctl command number 149862306a36Sopenharmony_ci * @arg: this is third argument given to ioctl(2) system call. 149962306a36Sopenharmony_ci * Often contains a pointer. 150062306a36Sopenharmony_ci * 150162306a36Sopenharmony_ci * Returns 0 if successful (some ioctls return positive numbers on 150262306a36Sopenharmony_ci * success as well). Returns a negated errno value in case of error. 150362306a36Sopenharmony_ci * 150462306a36Sopenharmony_ci * Note: most ioctls are forward onto the block subsystem or further 150562306a36Sopenharmony_ci * down in the scsi subsystem. 150662306a36Sopenharmony_ci **/ 150762306a36Sopenharmony_cistatic int sd_ioctl(struct block_device *bdev, blk_mode_t mode, 150862306a36Sopenharmony_ci unsigned int cmd, unsigned long arg) 150962306a36Sopenharmony_ci{ 151062306a36Sopenharmony_ci struct gendisk *disk = bdev->bd_disk; 151162306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(disk); 151262306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 151362306a36Sopenharmony_ci void __user *p = (void __user *)arg; 151462306a36Sopenharmony_ci int error; 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, " 151762306a36Sopenharmony_ci "cmd=0x%x\n", disk->disk_name, cmd)); 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci if (bdev_is_partition(bdev) && !capable(CAP_SYS_RAWIO)) 152062306a36Sopenharmony_ci return -ENOIOCTLCMD; 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci /* 152362306a36Sopenharmony_ci * If we are in the middle of error recovery, don't let anyone 152462306a36Sopenharmony_ci * else try and use this device. Also, if error recovery fails, it 152562306a36Sopenharmony_ci * may try and take the device offline, in which case all further 152662306a36Sopenharmony_ci * access to the device is prohibited. 152762306a36Sopenharmony_ci */ 152862306a36Sopenharmony_ci error = scsi_ioctl_block_when_processing_errors(sdp, cmd, 152962306a36Sopenharmony_ci (mode & BLK_OPEN_NDELAY)); 153062306a36Sopenharmony_ci if (error) 153162306a36Sopenharmony_ci return error; 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_ci if (is_sed_ioctl(cmd)) 153462306a36Sopenharmony_ci return sed_ioctl(sdkp->opal_dev, cmd, p); 153562306a36Sopenharmony_ci return scsi_ioctl(sdp, mode & BLK_OPEN_WRITE, cmd, p); 153662306a36Sopenharmony_ci} 153762306a36Sopenharmony_ci 153862306a36Sopenharmony_cistatic void set_media_not_present(struct scsi_disk *sdkp) 153962306a36Sopenharmony_ci{ 154062306a36Sopenharmony_ci if (sdkp->media_present) 154162306a36Sopenharmony_ci sdkp->device->changed = 1; 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci if (sdkp->device->removable) { 154462306a36Sopenharmony_ci sdkp->media_present = 0; 154562306a36Sopenharmony_ci sdkp->capacity = 0; 154662306a36Sopenharmony_ci } 154762306a36Sopenharmony_ci} 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_cistatic int media_not_present(struct scsi_disk *sdkp, 155062306a36Sopenharmony_ci struct scsi_sense_hdr *sshdr) 155162306a36Sopenharmony_ci{ 155262306a36Sopenharmony_ci if (!scsi_sense_valid(sshdr)) 155362306a36Sopenharmony_ci return 0; 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci /* not invoked for commands that could return deferred errors */ 155662306a36Sopenharmony_ci switch (sshdr->sense_key) { 155762306a36Sopenharmony_ci case UNIT_ATTENTION: 155862306a36Sopenharmony_ci case NOT_READY: 155962306a36Sopenharmony_ci /* medium not present */ 156062306a36Sopenharmony_ci if (sshdr->asc == 0x3A) { 156162306a36Sopenharmony_ci set_media_not_present(sdkp); 156262306a36Sopenharmony_ci return 1; 156362306a36Sopenharmony_ci } 156462306a36Sopenharmony_ci } 156562306a36Sopenharmony_ci return 0; 156662306a36Sopenharmony_ci} 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_ci/** 156962306a36Sopenharmony_ci * sd_check_events - check media events 157062306a36Sopenharmony_ci * @disk: kernel device descriptor 157162306a36Sopenharmony_ci * @clearing: disk events currently being cleared 157262306a36Sopenharmony_ci * 157362306a36Sopenharmony_ci * Returns mask of DISK_EVENT_*. 157462306a36Sopenharmony_ci * 157562306a36Sopenharmony_ci * Note: this function is invoked from the block subsystem. 157662306a36Sopenharmony_ci **/ 157762306a36Sopenharmony_cistatic unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing) 157862306a36Sopenharmony_ci{ 157962306a36Sopenharmony_ci struct scsi_disk *sdkp = disk->private_data; 158062306a36Sopenharmony_ci struct scsi_device *sdp; 158162306a36Sopenharmony_ci int retval; 158262306a36Sopenharmony_ci bool disk_changed; 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_ci if (!sdkp) 158562306a36Sopenharmony_ci return 0; 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_ci sdp = sdkp->device; 158862306a36Sopenharmony_ci SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_check_events\n")); 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_ci /* 159162306a36Sopenharmony_ci * If the device is offline, don't send any commands - just pretend as 159262306a36Sopenharmony_ci * if the command failed. If the device ever comes back online, we 159362306a36Sopenharmony_ci * can deal with it then. It is only because of unrecoverable errors 159462306a36Sopenharmony_ci * that we would ever take a device offline in the first place. 159562306a36Sopenharmony_ci */ 159662306a36Sopenharmony_ci if (!scsi_device_online(sdp)) { 159762306a36Sopenharmony_ci set_media_not_present(sdkp); 159862306a36Sopenharmony_ci goto out; 159962306a36Sopenharmony_ci } 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_ci /* 160262306a36Sopenharmony_ci * Using TEST_UNIT_READY enables differentiation between drive with 160362306a36Sopenharmony_ci * no cartridge loaded - NOT READY, drive with changed cartridge - 160462306a36Sopenharmony_ci * UNIT ATTENTION, or with same cartridge - GOOD STATUS. 160562306a36Sopenharmony_ci * 160662306a36Sopenharmony_ci * Drives that auto spin down. eg iomega jaz 1G, will be started 160762306a36Sopenharmony_ci * by sd_spinup_disk() from sd_revalidate_disk(), which happens whenever 160862306a36Sopenharmony_ci * sd_revalidate() is called. 160962306a36Sopenharmony_ci */ 161062306a36Sopenharmony_ci if (scsi_block_when_processing_errors(sdp)) { 161162306a36Sopenharmony_ci struct scsi_sense_hdr sshdr = { 0, }; 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_ci retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, sdkp->max_retries, 161462306a36Sopenharmony_ci &sshdr); 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci /* failed to execute TUR, assume media not present */ 161762306a36Sopenharmony_ci if (retval < 0 || host_byte(retval)) { 161862306a36Sopenharmony_ci set_media_not_present(sdkp); 161962306a36Sopenharmony_ci goto out; 162062306a36Sopenharmony_ci } 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci if (media_not_present(sdkp, &sshdr)) 162362306a36Sopenharmony_ci goto out; 162462306a36Sopenharmony_ci } 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_ci /* 162762306a36Sopenharmony_ci * For removable scsi disk we have to recognise the presence 162862306a36Sopenharmony_ci * of a disk in the drive. 162962306a36Sopenharmony_ci */ 163062306a36Sopenharmony_ci if (!sdkp->media_present) 163162306a36Sopenharmony_ci sdp->changed = 1; 163262306a36Sopenharmony_ci sdkp->media_present = 1; 163362306a36Sopenharmony_ciout: 163462306a36Sopenharmony_ci /* 163562306a36Sopenharmony_ci * sdp->changed is set under the following conditions: 163662306a36Sopenharmony_ci * 163762306a36Sopenharmony_ci * Medium present state has changed in either direction. 163862306a36Sopenharmony_ci * Device has indicated UNIT_ATTENTION. 163962306a36Sopenharmony_ci */ 164062306a36Sopenharmony_ci disk_changed = sdp->changed; 164162306a36Sopenharmony_ci sdp->changed = 0; 164262306a36Sopenharmony_ci return disk_changed ? DISK_EVENT_MEDIA_CHANGE : 0; 164362306a36Sopenharmony_ci} 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_cistatic int sd_sync_cache(struct scsi_disk *sdkp) 164662306a36Sopenharmony_ci{ 164762306a36Sopenharmony_ci int retries, res; 164862306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 164962306a36Sopenharmony_ci const int timeout = sdp->request_queue->rq_timeout 165062306a36Sopenharmony_ci * SD_FLUSH_TIMEOUT_MULTIPLIER; 165162306a36Sopenharmony_ci struct scsi_sense_hdr sshdr; 165262306a36Sopenharmony_ci const struct scsi_exec_args exec_args = { 165362306a36Sopenharmony_ci .req_flags = BLK_MQ_REQ_PM, 165462306a36Sopenharmony_ci .sshdr = &sshdr, 165562306a36Sopenharmony_ci }; 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci if (!scsi_device_online(sdp)) 165862306a36Sopenharmony_ci return -ENODEV; 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci for (retries = 3; retries > 0; --retries) { 166162306a36Sopenharmony_ci unsigned char cmd[16] = { 0 }; 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci if (sdp->use_16_for_sync) 166462306a36Sopenharmony_ci cmd[0] = SYNCHRONIZE_CACHE_16; 166562306a36Sopenharmony_ci else 166662306a36Sopenharmony_ci cmd[0] = SYNCHRONIZE_CACHE; 166762306a36Sopenharmony_ci /* 166862306a36Sopenharmony_ci * Leave the rest of the command zero to indicate 166962306a36Sopenharmony_ci * flush everything. 167062306a36Sopenharmony_ci */ 167162306a36Sopenharmony_ci res = scsi_execute_cmd(sdp, cmd, REQ_OP_DRV_IN, NULL, 0, 167262306a36Sopenharmony_ci timeout, sdkp->max_retries, &exec_args); 167362306a36Sopenharmony_ci if (res == 0) 167462306a36Sopenharmony_ci break; 167562306a36Sopenharmony_ci } 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci if (res) { 167862306a36Sopenharmony_ci sd_print_result(sdkp, "Synchronize Cache(10) failed", res); 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_ci if (res < 0) 168162306a36Sopenharmony_ci return res; 168262306a36Sopenharmony_ci 168362306a36Sopenharmony_ci if (scsi_status_is_check_condition(res) && 168462306a36Sopenharmony_ci scsi_sense_valid(&sshdr)) { 168562306a36Sopenharmony_ci sd_print_sense_hdr(sdkp, &sshdr); 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci /* we need to evaluate the error return */ 168862306a36Sopenharmony_ci if (sshdr.asc == 0x3a || /* medium not present */ 168962306a36Sopenharmony_ci sshdr.asc == 0x20 || /* invalid command */ 169062306a36Sopenharmony_ci (sshdr.asc == 0x74 && sshdr.ascq == 0x71)) /* drive is password locked */ 169162306a36Sopenharmony_ci /* this is no error here */ 169262306a36Sopenharmony_ci return 0; 169362306a36Sopenharmony_ci /* 169462306a36Sopenharmony_ci * This drive doesn't support sync and there's not much 169562306a36Sopenharmony_ci * we can do because this is called during shutdown 169662306a36Sopenharmony_ci * or suspend so just return success so those operations 169762306a36Sopenharmony_ci * can proceed. 169862306a36Sopenharmony_ci */ 169962306a36Sopenharmony_ci if (sshdr.sense_key == ILLEGAL_REQUEST) 170062306a36Sopenharmony_ci return 0; 170162306a36Sopenharmony_ci } 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_ci switch (host_byte(res)) { 170462306a36Sopenharmony_ci /* ignore errors due to racing a disconnection */ 170562306a36Sopenharmony_ci case DID_BAD_TARGET: 170662306a36Sopenharmony_ci case DID_NO_CONNECT: 170762306a36Sopenharmony_ci return 0; 170862306a36Sopenharmony_ci /* signal the upper layer it might try again */ 170962306a36Sopenharmony_ci case DID_BUS_BUSY: 171062306a36Sopenharmony_ci case DID_IMM_RETRY: 171162306a36Sopenharmony_ci case DID_REQUEUE: 171262306a36Sopenharmony_ci case DID_SOFT_ERROR: 171362306a36Sopenharmony_ci return -EBUSY; 171462306a36Sopenharmony_ci default: 171562306a36Sopenharmony_ci return -EIO; 171662306a36Sopenharmony_ci } 171762306a36Sopenharmony_ci } 171862306a36Sopenharmony_ci return 0; 171962306a36Sopenharmony_ci} 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_cistatic void sd_rescan(struct device *dev) 172262306a36Sopenharmony_ci{ 172362306a36Sopenharmony_ci struct scsi_disk *sdkp = dev_get_drvdata(dev); 172462306a36Sopenharmony_ci 172562306a36Sopenharmony_ci sd_revalidate_disk(sdkp->disk); 172662306a36Sopenharmony_ci} 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_cistatic int sd_get_unique_id(struct gendisk *disk, u8 id[16], 172962306a36Sopenharmony_ci enum blk_unique_id type) 173062306a36Sopenharmony_ci{ 173162306a36Sopenharmony_ci struct scsi_device *sdev = scsi_disk(disk)->device; 173262306a36Sopenharmony_ci const struct scsi_vpd *vpd; 173362306a36Sopenharmony_ci const unsigned char *d; 173462306a36Sopenharmony_ci int ret = -ENXIO, len; 173562306a36Sopenharmony_ci 173662306a36Sopenharmony_ci rcu_read_lock(); 173762306a36Sopenharmony_ci vpd = rcu_dereference(sdev->vpd_pg83); 173862306a36Sopenharmony_ci if (!vpd) 173962306a36Sopenharmony_ci goto out_unlock; 174062306a36Sopenharmony_ci 174162306a36Sopenharmony_ci ret = -EINVAL; 174262306a36Sopenharmony_ci for (d = vpd->data + 4; d < vpd->data + vpd->len; d += d[3] + 4) { 174362306a36Sopenharmony_ci /* we only care about designators with LU association */ 174462306a36Sopenharmony_ci if (((d[1] >> 4) & 0x3) != 0x00) 174562306a36Sopenharmony_ci continue; 174662306a36Sopenharmony_ci if ((d[1] & 0xf) != type) 174762306a36Sopenharmony_ci continue; 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_ci /* 175062306a36Sopenharmony_ci * Only exit early if a 16-byte descriptor was found. Otherwise 175162306a36Sopenharmony_ci * keep looking as one with more entropy might still show up. 175262306a36Sopenharmony_ci */ 175362306a36Sopenharmony_ci len = d[3]; 175462306a36Sopenharmony_ci if (len != 8 && len != 12 && len != 16) 175562306a36Sopenharmony_ci continue; 175662306a36Sopenharmony_ci ret = len; 175762306a36Sopenharmony_ci memcpy(id, d + 4, len); 175862306a36Sopenharmony_ci if (len == 16) 175962306a36Sopenharmony_ci break; 176062306a36Sopenharmony_ci } 176162306a36Sopenharmony_ciout_unlock: 176262306a36Sopenharmony_ci rcu_read_unlock(); 176362306a36Sopenharmony_ci return ret; 176462306a36Sopenharmony_ci} 176562306a36Sopenharmony_ci 176662306a36Sopenharmony_cistatic int sd_scsi_to_pr_err(struct scsi_sense_hdr *sshdr, int result) 176762306a36Sopenharmony_ci{ 176862306a36Sopenharmony_ci switch (host_byte(result)) { 176962306a36Sopenharmony_ci case DID_TRANSPORT_MARGINAL: 177062306a36Sopenharmony_ci case DID_TRANSPORT_DISRUPTED: 177162306a36Sopenharmony_ci case DID_BUS_BUSY: 177262306a36Sopenharmony_ci return PR_STS_RETRY_PATH_FAILURE; 177362306a36Sopenharmony_ci case DID_NO_CONNECT: 177462306a36Sopenharmony_ci return PR_STS_PATH_FAILED; 177562306a36Sopenharmony_ci case DID_TRANSPORT_FAILFAST: 177662306a36Sopenharmony_ci return PR_STS_PATH_FAST_FAILED; 177762306a36Sopenharmony_ci } 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci switch (status_byte(result)) { 178062306a36Sopenharmony_ci case SAM_STAT_RESERVATION_CONFLICT: 178162306a36Sopenharmony_ci return PR_STS_RESERVATION_CONFLICT; 178262306a36Sopenharmony_ci case SAM_STAT_CHECK_CONDITION: 178362306a36Sopenharmony_ci if (!scsi_sense_valid(sshdr)) 178462306a36Sopenharmony_ci return PR_STS_IOERR; 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci if (sshdr->sense_key == ILLEGAL_REQUEST && 178762306a36Sopenharmony_ci (sshdr->asc == 0x26 || sshdr->asc == 0x24)) 178862306a36Sopenharmony_ci return -EINVAL; 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci fallthrough; 179162306a36Sopenharmony_ci default: 179262306a36Sopenharmony_ci return PR_STS_IOERR; 179362306a36Sopenharmony_ci } 179462306a36Sopenharmony_ci} 179562306a36Sopenharmony_ci 179662306a36Sopenharmony_cistatic int sd_pr_in_command(struct block_device *bdev, u8 sa, 179762306a36Sopenharmony_ci unsigned char *data, int data_len) 179862306a36Sopenharmony_ci{ 179962306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); 180062306a36Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 180162306a36Sopenharmony_ci struct scsi_sense_hdr sshdr; 180262306a36Sopenharmony_ci u8 cmd[10] = { PERSISTENT_RESERVE_IN, sa }; 180362306a36Sopenharmony_ci const struct scsi_exec_args exec_args = { 180462306a36Sopenharmony_ci .sshdr = &sshdr, 180562306a36Sopenharmony_ci }; 180662306a36Sopenharmony_ci int result; 180762306a36Sopenharmony_ci 180862306a36Sopenharmony_ci put_unaligned_be16(data_len, &cmd[7]); 180962306a36Sopenharmony_ci 181062306a36Sopenharmony_ci result = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_IN, data, data_len, 181162306a36Sopenharmony_ci SD_TIMEOUT, sdkp->max_retries, &exec_args); 181262306a36Sopenharmony_ci if (scsi_status_is_check_condition(result) && 181362306a36Sopenharmony_ci scsi_sense_valid(&sshdr)) { 181462306a36Sopenharmony_ci sdev_printk(KERN_INFO, sdev, "PR command failed: %d\n", result); 181562306a36Sopenharmony_ci scsi_print_sense_hdr(sdev, NULL, &sshdr); 181662306a36Sopenharmony_ci } 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci if (result <= 0) 181962306a36Sopenharmony_ci return result; 182062306a36Sopenharmony_ci 182162306a36Sopenharmony_ci return sd_scsi_to_pr_err(&sshdr, result); 182262306a36Sopenharmony_ci} 182362306a36Sopenharmony_ci 182462306a36Sopenharmony_cistatic int sd_pr_read_keys(struct block_device *bdev, struct pr_keys *keys_info) 182562306a36Sopenharmony_ci{ 182662306a36Sopenharmony_ci int result, i, data_offset, num_copy_keys; 182762306a36Sopenharmony_ci u32 num_keys = keys_info->num_keys; 182862306a36Sopenharmony_ci int data_len = num_keys * 8 + 8; 182962306a36Sopenharmony_ci u8 *data; 183062306a36Sopenharmony_ci 183162306a36Sopenharmony_ci data = kzalloc(data_len, GFP_KERNEL); 183262306a36Sopenharmony_ci if (!data) 183362306a36Sopenharmony_ci return -ENOMEM; 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci result = sd_pr_in_command(bdev, READ_KEYS, data, data_len); 183662306a36Sopenharmony_ci if (result) 183762306a36Sopenharmony_ci goto free_data; 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci keys_info->generation = get_unaligned_be32(&data[0]); 184062306a36Sopenharmony_ci keys_info->num_keys = get_unaligned_be32(&data[4]) / 8; 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_ci data_offset = 8; 184362306a36Sopenharmony_ci num_copy_keys = min(num_keys, keys_info->num_keys); 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci for (i = 0; i < num_copy_keys; i++) { 184662306a36Sopenharmony_ci keys_info->keys[i] = get_unaligned_be64(&data[data_offset]); 184762306a36Sopenharmony_ci data_offset += 8; 184862306a36Sopenharmony_ci } 184962306a36Sopenharmony_ci 185062306a36Sopenharmony_cifree_data: 185162306a36Sopenharmony_ci kfree(data); 185262306a36Sopenharmony_ci return result; 185362306a36Sopenharmony_ci} 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_cistatic int sd_pr_read_reservation(struct block_device *bdev, 185662306a36Sopenharmony_ci struct pr_held_reservation *rsv) 185762306a36Sopenharmony_ci{ 185862306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); 185962306a36Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 186062306a36Sopenharmony_ci u8 data[24] = { }; 186162306a36Sopenharmony_ci int result, len; 186262306a36Sopenharmony_ci 186362306a36Sopenharmony_ci result = sd_pr_in_command(bdev, READ_RESERVATION, data, sizeof(data)); 186462306a36Sopenharmony_ci if (result) 186562306a36Sopenharmony_ci return result; 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_ci len = get_unaligned_be32(&data[4]); 186862306a36Sopenharmony_ci if (!len) 186962306a36Sopenharmony_ci return 0; 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci /* Make sure we have at least the key and type */ 187262306a36Sopenharmony_ci if (len < 14) { 187362306a36Sopenharmony_ci sdev_printk(KERN_INFO, sdev, 187462306a36Sopenharmony_ci "READ RESERVATION failed due to short return buffer of %d bytes\n", 187562306a36Sopenharmony_ci len); 187662306a36Sopenharmony_ci return -EINVAL; 187762306a36Sopenharmony_ci } 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_ci rsv->generation = get_unaligned_be32(&data[0]); 188062306a36Sopenharmony_ci rsv->key = get_unaligned_be64(&data[8]); 188162306a36Sopenharmony_ci rsv->type = scsi_pr_type_to_block(data[21] & 0x0f); 188262306a36Sopenharmony_ci return 0; 188362306a36Sopenharmony_ci} 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_cistatic int sd_pr_out_command(struct block_device *bdev, u8 sa, u64 key, 188662306a36Sopenharmony_ci u64 sa_key, enum scsi_pr_type type, u8 flags) 188762306a36Sopenharmony_ci{ 188862306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); 188962306a36Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 189062306a36Sopenharmony_ci struct scsi_sense_hdr sshdr; 189162306a36Sopenharmony_ci const struct scsi_exec_args exec_args = { 189262306a36Sopenharmony_ci .sshdr = &sshdr, 189362306a36Sopenharmony_ci }; 189462306a36Sopenharmony_ci int result; 189562306a36Sopenharmony_ci u8 cmd[16] = { 0, }; 189662306a36Sopenharmony_ci u8 data[24] = { 0, }; 189762306a36Sopenharmony_ci 189862306a36Sopenharmony_ci cmd[0] = PERSISTENT_RESERVE_OUT; 189962306a36Sopenharmony_ci cmd[1] = sa; 190062306a36Sopenharmony_ci cmd[2] = type; 190162306a36Sopenharmony_ci put_unaligned_be32(sizeof(data), &cmd[5]); 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_ci put_unaligned_be64(key, &data[0]); 190462306a36Sopenharmony_ci put_unaligned_be64(sa_key, &data[8]); 190562306a36Sopenharmony_ci data[20] = flags; 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci result = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_OUT, &data, 190862306a36Sopenharmony_ci sizeof(data), SD_TIMEOUT, sdkp->max_retries, 190962306a36Sopenharmony_ci &exec_args); 191062306a36Sopenharmony_ci 191162306a36Sopenharmony_ci if (scsi_status_is_check_condition(result) && 191262306a36Sopenharmony_ci scsi_sense_valid(&sshdr)) { 191362306a36Sopenharmony_ci sdev_printk(KERN_INFO, sdev, "PR command failed: %d\n", result); 191462306a36Sopenharmony_ci scsi_print_sense_hdr(sdev, NULL, &sshdr); 191562306a36Sopenharmony_ci } 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_ci if (result <= 0) 191862306a36Sopenharmony_ci return result; 191962306a36Sopenharmony_ci 192062306a36Sopenharmony_ci return sd_scsi_to_pr_err(&sshdr, result); 192162306a36Sopenharmony_ci} 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_cistatic int sd_pr_register(struct block_device *bdev, u64 old_key, u64 new_key, 192462306a36Sopenharmony_ci u32 flags) 192562306a36Sopenharmony_ci{ 192662306a36Sopenharmony_ci if (flags & ~PR_FL_IGNORE_KEY) 192762306a36Sopenharmony_ci return -EOPNOTSUPP; 192862306a36Sopenharmony_ci return sd_pr_out_command(bdev, (flags & PR_FL_IGNORE_KEY) ? 0x06 : 0x00, 192962306a36Sopenharmony_ci old_key, new_key, 0, 193062306a36Sopenharmony_ci (1 << 0) /* APTPL */); 193162306a36Sopenharmony_ci} 193262306a36Sopenharmony_ci 193362306a36Sopenharmony_cistatic int sd_pr_reserve(struct block_device *bdev, u64 key, enum pr_type type, 193462306a36Sopenharmony_ci u32 flags) 193562306a36Sopenharmony_ci{ 193662306a36Sopenharmony_ci if (flags) 193762306a36Sopenharmony_ci return -EOPNOTSUPP; 193862306a36Sopenharmony_ci return sd_pr_out_command(bdev, 0x01, key, 0, 193962306a36Sopenharmony_ci block_pr_type_to_scsi(type), 0); 194062306a36Sopenharmony_ci} 194162306a36Sopenharmony_ci 194262306a36Sopenharmony_cistatic int sd_pr_release(struct block_device *bdev, u64 key, enum pr_type type) 194362306a36Sopenharmony_ci{ 194462306a36Sopenharmony_ci return sd_pr_out_command(bdev, 0x02, key, 0, 194562306a36Sopenharmony_ci block_pr_type_to_scsi(type), 0); 194662306a36Sopenharmony_ci} 194762306a36Sopenharmony_ci 194862306a36Sopenharmony_cistatic int sd_pr_preempt(struct block_device *bdev, u64 old_key, u64 new_key, 194962306a36Sopenharmony_ci enum pr_type type, bool abort) 195062306a36Sopenharmony_ci{ 195162306a36Sopenharmony_ci return sd_pr_out_command(bdev, abort ? 0x05 : 0x04, old_key, new_key, 195262306a36Sopenharmony_ci block_pr_type_to_scsi(type), 0); 195362306a36Sopenharmony_ci} 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_cistatic int sd_pr_clear(struct block_device *bdev, u64 key) 195662306a36Sopenharmony_ci{ 195762306a36Sopenharmony_ci return sd_pr_out_command(bdev, 0x03, key, 0, 0, 0); 195862306a36Sopenharmony_ci} 195962306a36Sopenharmony_ci 196062306a36Sopenharmony_cistatic const struct pr_ops sd_pr_ops = { 196162306a36Sopenharmony_ci .pr_register = sd_pr_register, 196262306a36Sopenharmony_ci .pr_reserve = sd_pr_reserve, 196362306a36Sopenharmony_ci .pr_release = sd_pr_release, 196462306a36Sopenharmony_ci .pr_preempt = sd_pr_preempt, 196562306a36Sopenharmony_ci .pr_clear = sd_pr_clear, 196662306a36Sopenharmony_ci .pr_read_keys = sd_pr_read_keys, 196762306a36Sopenharmony_ci .pr_read_reservation = sd_pr_read_reservation, 196862306a36Sopenharmony_ci}; 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_cistatic void scsi_disk_free_disk(struct gendisk *disk) 197162306a36Sopenharmony_ci{ 197262306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(disk); 197362306a36Sopenharmony_ci 197462306a36Sopenharmony_ci put_device(&sdkp->disk_dev); 197562306a36Sopenharmony_ci} 197662306a36Sopenharmony_ci 197762306a36Sopenharmony_cistatic const struct block_device_operations sd_fops = { 197862306a36Sopenharmony_ci .owner = THIS_MODULE, 197962306a36Sopenharmony_ci .open = sd_open, 198062306a36Sopenharmony_ci .release = sd_release, 198162306a36Sopenharmony_ci .ioctl = sd_ioctl, 198262306a36Sopenharmony_ci .getgeo = sd_getgeo, 198362306a36Sopenharmony_ci .compat_ioctl = blkdev_compat_ptr_ioctl, 198462306a36Sopenharmony_ci .check_events = sd_check_events, 198562306a36Sopenharmony_ci .unlock_native_capacity = sd_unlock_native_capacity, 198662306a36Sopenharmony_ci .report_zones = sd_zbc_report_zones, 198762306a36Sopenharmony_ci .get_unique_id = sd_get_unique_id, 198862306a36Sopenharmony_ci .free_disk = scsi_disk_free_disk, 198962306a36Sopenharmony_ci .pr_ops = &sd_pr_ops, 199062306a36Sopenharmony_ci}; 199162306a36Sopenharmony_ci 199262306a36Sopenharmony_ci/** 199362306a36Sopenharmony_ci * sd_eh_reset - reset error handling callback 199462306a36Sopenharmony_ci * @scmd: sd-issued command that has failed 199562306a36Sopenharmony_ci * 199662306a36Sopenharmony_ci * This function is called by the SCSI midlayer before starting 199762306a36Sopenharmony_ci * SCSI EH. When counting medium access failures we have to be 199862306a36Sopenharmony_ci * careful to register it only only once per device and SCSI EH run; 199962306a36Sopenharmony_ci * there might be several timed out commands which will cause the 200062306a36Sopenharmony_ci * 'max_medium_access_timeouts' counter to trigger after the first 200162306a36Sopenharmony_ci * SCSI EH run already and set the device to offline. 200262306a36Sopenharmony_ci * So this function resets the internal counter before starting SCSI EH. 200362306a36Sopenharmony_ci **/ 200462306a36Sopenharmony_cistatic void sd_eh_reset(struct scsi_cmnd *scmd) 200562306a36Sopenharmony_ci{ 200662306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(scsi_cmd_to_rq(scmd)->q->disk); 200762306a36Sopenharmony_ci 200862306a36Sopenharmony_ci /* New SCSI EH run, reset gate variable */ 200962306a36Sopenharmony_ci sdkp->ignore_medium_access_errors = false; 201062306a36Sopenharmony_ci} 201162306a36Sopenharmony_ci 201262306a36Sopenharmony_ci/** 201362306a36Sopenharmony_ci * sd_eh_action - error handling callback 201462306a36Sopenharmony_ci * @scmd: sd-issued command that has failed 201562306a36Sopenharmony_ci * @eh_disp: The recovery disposition suggested by the midlayer 201662306a36Sopenharmony_ci * 201762306a36Sopenharmony_ci * This function is called by the SCSI midlayer upon completion of an 201862306a36Sopenharmony_ci * error test command (currently TEST UNIT READY). The result of sending 201962306a36Sopenharmony_ci * the eh command is passed in eh_disp. We're looking for devices that 202062306a36Sopenharmony_ci * fail medium access commands but are OK with non access commands like 202162306a36Sopenharmony_ci * test unit ready (so wrongly see the device as having a successful 202262306a36Sopenharmony_ci * recovery) 202362306a36Sopenharmony_ci **/ 202462306a36Sopenharmony_cistatic int sd_eh_action(struct scsi_cmnd *scmd, int eh_disp) 202562306a36Sopenharmony_ci{ 202662306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(scsi_cmd_to_rq(scmd)->q->disk); 202762306a36Sopenharmony_ci struct scsi_device *sdev = scmd->device; 202862306a36Sopenharmony_ci 202962306a36Sopenharmony_ci if (!scsi_device_online(sdev) || 203062306a36Sopenharmony_ci !scsi_medium_access_command(scmd) || 203162306a36Sopenharmony_ci host_byte(scmd->result) != DID_TIME_OUT || 203262306a36Sopenharmony_ci eh_disp != SUCCESS) 203362306a36Sopenharmony_ci return eh_disp; 203462306a36Sopenharmony_ci 203562306a36Sopenharmony_ci /* 203662306a36Sopenharmony_ci * The device has timed out executing a medium access command. 203762306a36Sopenharmony_ci * However, the TEST UNIT READY command sent during error 203862306a36Sopenharmony_ci * handling completed successfully. Either the device is in the 203962306a36Sopenharmony_ci * process of recovering or has it suffered an internal failure 204062306a36Sopenharmony_ci * that prevents access to the storage medium. 204162306a36Sopenharmony_ci */ 204262306a36Sopenharmony_ci if (!sdkp->ignore_medium_access_errors) { 204362306a36Sopenharmony_ci sdkp->medium_access_timed_out++; 204462306a36Sopenharmony_ci sdkp->ignore_medium_access_errors = true; 204562306a36Sopenharmony_ci } 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_ci /* 204862306a36Sopenharmony_ci * If the device keeps failing read/write commands but TEST UNIT 204962306a36Sopenharmony_ci * READY always completes successfully we assume that medium 205062306a36Sopenharmony_ci * access is no longer possible and take the device offline. 205162306a36Sopenharmony_ci */ 205262306a36Sopenharmony_ci if (sdkp->medium_access_timed_out >= sdkp->max_medium_access_timeouts) { 205362306a36Sopenharmony_ci scmd_printk(KERN_ERR, scmd, 205462306a36Sopenharmony_ci "Medium access timeout failure. Offlining disk!\n"); 205562306a36Sopenharmony_ci mutex_lock(&sdev->state_mutex); 205662306a36Sopenharmony_ci scsi_device_set_state(sdev, SDEV_OFFLINE); 205762306a36Sopenharmony_ci mutex_unlock(&sdev->state_mutex); 205862306a36Sopenharmony_ci 205962306a36Sopenharmony_ci return SUCCESS; 206062306a36Sopenharmony_ci } 206162306a36Sopenharmony_ci 206262306a36Sopenharmony_ci return eh_disp; 206362306a36Sopenharmony_ci} 206462306a36Sopenharmony_ci 206562306a36Sopenharmony_cistatic unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) 206662306a36Sopenharmony_ci{ 206762306a36Sopenharmony_ci struct request *req = scsi_cmd_to_rq(scmd); 206862306a36Sopenharmony_ci struct scsi_device *sdev = scmd->device; 206962306a36Sopenharmony_ci unsigned int transferred, good_bytes; 207062306a36Sopenharmony_ci u64 start_lba, end_lba, bad_lba; 207162306a36Sopenharmony_ci 207262306a36Sopenharmony_ci /* 207362306a36Sopenharmony_ci * Some commands have a payload smaller than the device logical 207462306a36Sopenharmony_ci * block size (e.g. INQUIRY on a 4K disk). 207562306a36Sopenharmony_ci */ 207662306a36Sopenharmony_ci if (scsi_bufflen(scmd) <= sdev->sector_size) 207762306a36Sopenharmony_ci return 0; 207862306a36Sopenharmony_ci 207962306a36Sopenharmony_ci /* Check if we have a 'bad_lba' information */ 208062306a36Sopenharmony_ci if (!scsi_get_sense_info_fld(scmd->sense_buffer, 208162306a36Sopenharmony_ci SCSI_SENSE_BUFFERSIZE, 208262306a36Sopenharmony_ci &bad_lba)) 208362306a36Sopenharmony_ci return 0; 208462306a36Sopenharmony_ci 208562306a36Sopenharmony_ci /* 208662306a36Sopenharmony_ci * If the bad lba was reported incorrectly, we have no idea where 208762306a36Sopenharmony_ci * the error is. 208862306a36Sopenharmony_ci */ 208962306a36Sopenharmony_ci start_lba = sectors_to_logical(sdev, blk_rq_pos(req)); 209062306a36Sopenharmony_ci end_lba = start_lba + bytes_to_logical(sdev, scsi_bufflen(scmd)); 209162306a36Sopenharmony_ci if (bad_lba < start_lba || bad_lba >= end_lba) 209262306a36Sopenharmony_ci return 0; 209362306a36Sopenharmony_ci 209462306a36Sopenharmony_ci /* 209562306a36Sopenharmony_ci * resid is optional but mostly filled in. When it's unused, 209662306a36Sopenharmony_ci * its value is zero, so we assume the whole buffer transferred 209762306a36Sopenharmony_ci */ 209862306a36Sopenharmony_ci transferred = scsi_bufflen(scmd) - scsi_get_resid(scmd); 209962306a36Sopenharmony_ci 210062306a36Sopenharmony_ci /* This computation should always be done in terms of the 210162306a36Sopenharmony_ci * resolution of the device's medium. 210262306a36Sopenharmony_ci */ 210362306a36Sopenharmony_ci good_bytes = logical_to_bytes(sdev, bad_lba - start_lba); 210462306a36Sopenharmony_ci 210562306a36Sopenharmony_ci return min(good_bytes, transferred); 210662306a36Sopenharmony_ci} 210762306a36Sopenharmony_ci 210862306a36Sopenharmony_ci/** 210962306a36Sopenharmony_ci * sd_done - bottom half handler: called when the lower level 211062306a36Sopenharmony_ci * driver has completed (successfully or otherwise) a scsi command. 211162306a36Sopenharmony_ci * @SCpnt: mid-level's per command structure. 211262306a36Sopenharmony_ci * 211362306a36Sopenharmony_ci * Note: potentially run from within an ISR. Must not block. 211462306a36Sopenharmony_ci **/ 211562306a36Sopenharmony_cistatic int sd_done(struct scsi_cmnd *SCpnt) 211662306a36Sopenharmony_ci{ 211762306a36Sopenharmony_ci int result = SCpnt->result; 211862306a36Sopenharmony_ci unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt); 211962306a36Sopenharmony_ci unsigned int sector_size = SCpnt->device->sector_size; 212062306a36Sopenharmony_ci unsigned int resid; 212162306a36Sopenharmony_ci struct scsi_sense_hdr sshdr; 212262306a36Sopenharmony_ci struct request *req = scsi_cmd_to_rq(SCpnt); 212362306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(req->q->disk); 212462306a36Sopenharmony_ci int sense_valid = 0; 212562306a36Sopenharmony_ci int sense_deferred = 0; 212662306a36Sopenharmony_ci 212762306a36Sopenharmony_ci switch (req_op(req)) { 212862306a36Sopenharmony_ci case REQ_OP_DISCARD: 212962306a36Sopenharmony_ci case REQ_OP_WRITE_ZEROES: 213062306a36Sopenharmony_ci case REQ_OP_ZONE_RESET: 213162306a36Sopenharmony_ci case REQ_OP_ZONE_RESET_ALL: 213262306a36Sopenharmony_ci case REQ_OP_ZONE_OPEN: 213362306a36Sopenharmony_ci case REQ_OP_ZONE_CLOSE: 213462306a36Sopenharmony_ci case REQ_OP_ZONE_FINISH: 213562306a36Sopenharmony_ci if (!result) { 213662306a36Sopenharmony_ci good_bytes = blk_rq_bytes(req); 213762306a36Sopenharmony_ci scsi_set_resid(SCpnt, 0); 213862306a36Sopenharmony_ci } else { 213962306a36Sopenharmony_ci good_bytes = 0; 214062306a36Sopenharmony_ci scsi_set_resid(SCpnt, blk_rq_bytes(req)); 214162306a36Sopenharmony_ci } 214262306a36Sopenharmony_ci break; 214362306a36Sopenharmony_ci default: 214462306a36Sopenharmony_ci /* 214562306a36Sopenharmony_ci * In case of bogus fw or device, we could end up having 214662306a36Sopenharmony_ci * an unaligned partial completion. Check this here and force 214762306a36Sopenharmony_ci * alignment. 214862306a36Sopenharmony_ci */ 214962306a36Sopenharmony_ci resid = scsi_get_resid(SCpnt); 215062306a36Sopenharmony_ci if (resid & (sector_size - 1)) { 215162306a36Sopenharmony_ci sd_printk(KERN_INFO, sdkp, 215262306a36Sopenharmony_ci "Unaligned partial completion (resid=%u, sector_sz=%u)\n", 215362306a36Sopenharmony_ci resid, sector_size); 215462306a36Sopenharmony_ci scsi_print_command(SCpnt); 215562306a36Sopenharmony_ci resid = min(scsi_bufflen(SCpnt), 215662306a36Sopenharmony_ci round_up(resid, sector_size)); 215762306a36Sopenharmony_ci scsi_set_resid(SCpnt, resid); 215862306a36Sopenharmony_ci } 215962306a36Sopenharmony_ci } 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_ci if (result) { 216262306a36Sopenharmony_ci sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr); 216362306a36Sopenharmony_ci if (sense_valid) 216462306a36Sopenharmony_ci sense_deferred = scsi_sense_is_deferred(&sshdr); 216562306a36Sopenharmony_ci } 216662306a36Sopenharmony_ci sdkp->medium_access_timed_out = 0; 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci if (!scsi_status_is_check_condition(result) && 216962306a36Sopenharmony_ci (!sense_valid || sense_deferred)) 217062306a36Sopenharmony_ci goto out; 217162306a36Sopenharmony_ci 217262306a36Sopenharmony_ci switch (sshdr.sense_key) { 217362306a36Sopenharmony_ci case HARDWARE_ERROR: 217462306a36Sopenharmony_ci case MEDIUM_ERROR: 217562306a36Sopenharmony_ci good_bytes = sd_completed_bytes(SCpnt); 217662306a36Sopenharmony_ci break; 217762306a36Sopenharmony_ci case RECOVERED_ERROR: 217862306a36Sopenharmony_ci good_bytes = scsi_bufflen(SCpnt); 217962306a36Sopenharmony_ci break; 218062306a36Sopenharmony_ci case NO_SENSE: 218162306a36Sopenharmony_ci /* This indicates a false check condition, so ignore it. An 218262306a36Sopenharmony_ci * unknown amount of data was transferred so treat it as an 218362306a36Sopenharmony_ci * error. 218462306a36Sopenharmony_ci */ 218562306a36Sopenharmony_ci SCpnt->result = 0; 218662306a36Sopenharmony_ci memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); 218762306a36Sopenharmony_ci break; 218862306a36Sopenharmony_ci case ABORTED_COMMAND: 218962306a36Sopenharmony_ci if (sshdr.asc == 0x10) /* DIF: Target detected corruption */ 219062306a36Sopenharmony_ci good_bytes = sd_completed_bytes(SCpnt); 219162306a36Sopenharmony_ci break; 219262306a36Sopenharmony_ci case ILLEGAL_REQUEST: 219362306a36Sopenharmony_ci switch (sshdr.asc) { 219462306a36Sopenharmony_ci case 0x10: /* DIX: Host detected corruption */ 219562306a36Sopenharmony_ci good_bytes = sd_completed_bytes(SCpnt); 219662306a36Sopenharmony_ci break; 219762306a36Sopenharmony_ci case 0x20: /* INVALID COMMAND OPCODE */ 219862306a36Sopenharmony_ci case 0x24: /* INVALID FIELD IN CDB */ 219962306a36Sopenharmony_ci switch (SCpnt->cmnd[0]) { 220062306a36Sopenharmony_ci case UNMAP: 220162306a36Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_DISABLE); 220262306a36Sopenharmony_ci break; 220362306a36Sopenharmony_ci case WRITE_SAME_16: 220462306a36Sopenharmony_ci case WRITE_SAME: 220562306a36Sopenharmony_ci if (SCpnt->cmnd[1] & 8) { /* UNMAP */ 220662306a36Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_DISABLE); 220762306a36Sopenharmony_ci } else { 220862306a36Sopenharmony_ci sdkp->device->no_write_same = 1; 220962306a36Sopenharmony_ci sd_config_write_same(sdkp); 221062306a36Sopenharmony_ci req->rq_flags |= RQF_QUIET; 221162306a36Sopenharmony_ci } 221262306a36Sopenharmony_ci break; 221362306a36Sopenharmony_ci } 221462306a36Sopenharmony_ci } 221562306a36Sopenharmony_ci break; 221662306a36Sopenharmony_ci default: 221762306a36Sopenharmony_ci break; 221862306a36Sopenharmony_ci } 221962306a36Sopenharmony_ci 222062306a36Sopenharmony_ci out: 222162306a36Sopenharmony_ci if (sd_is_zoned(sdkp)) 222262306a36Sopenharmony_ci good_bytes = sd_zbc_complete(SCpnt, good_bytes, &sshdr); 222362306a36Sopenharmony_ci 222462306a36Sopenharmony_ci SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt, 222562306a36Sopenharmony_ci "sd_done: completed %d of %d bytes\n", 222662306a36Sopenharmony_ci good_bytes, scsi_bufflen(SCpnt))); 222762306a36Sopenharmony_ci 222862306a36Sopenharmony_ci return good_bytes; 222962306a36Sopenharmony_ci} 223062306a36Sopenharmony_ci 223162306a36Sopenharmony_ci/* 223262306a36Sopenharmony_ci * spinup disk - called only in sd_revalidate_disk() 223362306a36Sopenharmony_ci */ 223462306a36Sopenharmony_cistatic void 223562306a36Sopenharmony_cisd_spinup_disk(struct scsi_disk *sdkp) 223662306a36Sopenharmony_ci{ 223762306a36Sopenharmony_ci unsigned char cmd[10]; 223862306a36Sopenharmony_ci unsigned long spintime_expire = 0; 223962306a36Sopenharmony_ci int retries, spintime; 224062306a36Sopenharmony_ci unsigned int the_result; 224162306a36Sopenharmony_ci struct scsi_sense_hdr sshdr; 224262306a36Sopenharmony_ci const struct scsi_exec_args exec_args = { 224362306a36Sopenharmony_ci .sshdr = &sshdr, 224462306a36Sopenharmony_ci }; 224562306a36Sopenharmony_ci int sense_valid = 0; 224662306a36Sopenharmony_ci 224762306a36Sopenharmony_ci spintime = 0; 224862306a36Sopenharmony_ci 224962306a36Sopenharmony_ci /* Spin up drives, as required. Only do this at boot time */ 225062306a36Sopenharmony_ci /* Spinup needs to be done for module loads too. */ 225162306a36Sopenharmony_ci do { 225262306a36Sopenharmony_ci retries = 0; 225362306a36Sopenharmony_ci 225462306a36Sopenharmony_ci do { 225562306a36Sopenharmony_ci bool media_was_present = sdkp->media_present; 225662306a36Sopenharmony_ci 225762306a36Sopenharmony_ci cmd[0] = TEST_UNIT_READY; 225862306a36Sopenharmony_ci memset((void *) &cmd[1], 0, 9); 225962306a36Sopenharmony_ci 226062306a36Sopenharmony_ci the_result = scsi_execute_cmd(sdkp->device, cmd, 226162306a36Sopenharmony_ci REQ_OP_DRV_IN, NULL, 0, 226262306a36Sopenharmony_ci SD_TIMEOUT, 226362306a36Sopenharmony_ci sdkp->max_retries, 226462306a36Sopenharmony_ci &exec_args); 226562306a36Sopenharmony_ci 226662306a36Sopenharmony_ci /* 226762306a36Sopenharmony_ci * If the drive has indicated to us that it 226862306a36Sopenharmony_ci * doesn't have any media in it, don't bother 226962306a36Sopenharmony_ci * with any more polling. 227062306a36Sopenharmony_ci */ 227162306a36Sopenharmony_ci if (media_not_present(sdkp, &sshdr)) { 227262306a36Sopenharmony_ci if (media_was_present) 227362306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Media removed, stopped polling\n"); 227462306a36Sopenharmony_ci return; 227562306a36Sopenharmony_ci } 227662306a36Sopenharmony_ci 227762306a36Sopenharmony_ci if (the_result) 227862306a36Sopenharmony_ci sense_valid = scsi_sense_valid(&sshdr); 227962306a36Sopenharmony_ci retries++; 228062306a36Sopenharmony_ci } while (retries < 3 && 228162306a36Sopenharmony_ci (!scsi_status_is_good(the_result) || 228262306a36Sopenharmony_ci (scsi_status_is_check_condition(the_result) && 228362306a36Sopenharmony_ci sense_valid && sshdr.sense_key == UNIT_ATTENTION))); 228462306a36Sopenharmony_ci 228562306a36Sopenharmony_ci if (!scsi_status_is_check_condition(the_result)) { 228662306a36Sopenharmony_ci /* no sense, TUR either succeeded or failed 228762306a36Sopenharmony_ci * with a status error */ 228862306a36Sopenharmony_ci if(!spintime && !scsi_status_is_good(the_result)) { 228962306a36Sopenharmony_ci sd_print_result(sdkp, "Test Unit Ready failed", 229062306a36Sopenharmony_ci the_result); 229162306a36Sopenharmony_ci } 229262306a36Sopenharmony_ci break; 229362306a36Sopenharmony_ci } 229462306a36Sopenharmony_ci 229562306a36Sopenharmony_ci /* 229662306a36Sopenharmony_ci * The device does not want the automatic start to be issued. 229762306a36Sopenharmony_ci */ 229862306a36Sopenharmony_ci if (sdkp->device->no_start_on_add) 229962306a36Sopenharmony_ci break; 230062306a36Sopenharmony_ci 230162306a36Sopenharmony_ci if (sense_valid && sshdr.sense_key == NOT_READY) { 230262306a36Sopenharmony_ci if (sshdr.asc == 4 && sshdr.ascq == 3) 230362306a36Sopenharmony_ci break; /* manual intervention required */ 230462306a36Sopenharmony_ci if (sshdr.asc == 4 && sshdr.ascq == 0xb) 230562306a36Sopenharmony_ci break; /* standby */ 230662306a36Sopenharmony_ci if (sshdr.asc == 4 && sshdr.ascq == 0xc) 230762306a36Sopenharmony_ci break; /* unavailable */ 230862306a36Sopenharmony_ci if (sshdr.asc == 4 && sshdr.ascq == 0x1b) 230962306a36Sopenharmony_ci break; /* sanitize in progress */ 231062306a36Sopenharmony_ci /* 231162306a36Sopenharmony_ci * Issue command to spin up drive when not ready 231262306a36Sopenharmony_ci */ 231362306a36Sopenharmony_ci if (!spintime) { 231462306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Spinning up disk..."); 231562306a36Sopenharmony_ci cmd[0] = START_STOP; 231662306a36Sopenharmony_ci cmd[1] = 1; /* Return immediately */ 231762306a36Sopenharmony_ci memset((void *) &cmd[2], 0, 8); 231862306a36Sopenharmony_ci cmd[4] = 1; /* Start spin cycle */ 231962306a36Sopenharmony_ci if (sdkp->device->start_stop_pwr_cond) 232062306a36Sopenharmony_ci cmd[4] |= 1 << 4; 232162306a36Sopenharmony_ci scsi_execute_cmd(sdkp->device, cmd, 232262306a36Sopenharmony_ci REQ_OP_DRV_IN, NULL, 0, 232362306a36Sopenharmony_ci SD_TIMEOUT, sdkp->max_retries, 232462306a36Sopenharmony_ci &exec_args); 232562306a36Sopenharmony_ci spintime_expire = jiffies + 100 * HZ; 232662306a36Sopenharmony_ci spintime = 1; 232762306a36Sopenharmony_ci } 232862306a36Sopenharmony_ci /* Wait 1 second for next try */ 232962306a36Sopenharmony_ci msleep(1000); 233062306a36Sopenharmony_ci printk(KERN_CONT "."); 233162306a36Sopenharmony_ci 233262306a36Sopenharmony_ci /* 233362306a36Sopenharmony_ci * Wait for USB flash devices with slow firmware. 233462306a36Sopenharmony_ci * Yes, this sense key/ASC combination shouldn't 233562306a36Sopenharmony_ci * occur here. It's characteristic of these devices. 233662306a36Sopenharmony_ci */ 233762306a36Sopenharmony_ci } else if (sense_valid && 233862306a36Sopenharmony_ci sshdr.sense_key == UNIT_ATTENTION && 233962306a36Sopenharmony_ci sshdr.asc == 0x28) { 234062306a36Sopenharmony_ci if (!spintime) { 234162306a36Sopenharmony_ci spintime_expire = jiffies + 5 * HZ; 234262306a36Sopenharmony_ci spintime = 1; 234362306a36Sopenharmony_ci } 234462306a36Sopenharmony_ci /* Wait 1 second for next try */ 234562306a36Sopenharmony_ci msleep(1000); 234662306a36Sopenharmony_ci } else { 234762306a36Sopenharmony_ci /* we don't understand the sense code, so it's 234862306a36Sopenharmony_ci * probably pointless to loop */ 234962306a36Sopenharmony_ci if(!spintime) { 235062306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Unit Not Ready\n"); 235162306a36Sopenharmony_ci sd_print_sense_hdr(sdkp, &sshdr); 235262306a36Sopenharmony_ci } 235362306a36Sopenharmony_ci break; 235462306a36Sopenharmony_ci } 235562306a36Sopenharmony_ci 235662306a36Sopenharmony_ci } while (spintime && time_before_eq(jiffies, spintime_expire)); 235762306a36Sopenharmony_ci 235862306a36Sopenharmony_ci if (spintime) { 235962306a36Sopenharmony_ci if (scsi_status_is_good(the_result)) 236062306a36Sopenharmony_ci printk(KERN_CONT "ready\n"); 236162306a36Sopenharmony_ci else 236262306a36Sopenharmony_ci printk(KERN_CONT "not responding...\n"); 236362306a36Sopenharmony_ci } 236462306a36Sopenharmony_ci} 236562306a36Sopenharmony_ci 236662306a36Sopenharmony_ci/* 236762306a36Sopenharmony_ci * Determine whether disk supports Data Integrity Field. 236862306a36Sopenharmony_ci */ 236962306a36Sopenharmony_cistatic int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) 237062306a36Sopenharmony_ci{ 237162306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 237262306a36Sopenharmony_ci u8 type; 237362306a36Sopenharmony_ci 237462306a36Sopenharmony_ci if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) { 237562306a36Sopenharmony_ci sdkp->protection_type = 0; 237662306a36Sopenharmony_ci return 0; 237762306a36Sopenharmony_ci } 237862306a36Sopenharmony_ci 237962306a36Sopenharmony_ci type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ 238062306a36Sopenharmony_ci 238162306a36Sopenharmony_ci if (type > T10_PI_TYPE3_PROTECTION) { 238262306a36Sopenharmony_ci sd_printk(KERN_ERR, sdkp, "formatted with unsupported" \ 238362306a36Sopenharmony_ci " protection type %u. Disabling disk!\n", 238462306a36Sopenharmony_ci type); 238562306a36Sopenharmony_ci sdkp->protection_type = 0; 238662306a36Sopenharmony_ci return -ENODEV; 238762306a36Sopenharmony_ci } 238862306a36Sopenharmony_ci 238962306a36Sopenharmony_ci sdkp->protection_type = type; 239062306a36Sopenharmony_ci 239162306a36Sopenharmony_ci return 0; 239262306a36Sopenharmony_ci} 239362306a36Sopenharmony_ci 239462306a36Sopenharmony_cistatic void sd_config_protection(struct scsi_disk *sdkp) 239562306a36Sopenharmony_ci{ 239662306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 239762306a36Sopenharmony_ci 239862306a36Sopenharmony_ci sd_dif_config_host(sdkp); 239962306a36Sopenharmony_ci 240062306a36Sopenharmony_ci if (!sdkp->protection_type) 240162306a36Sopenharmony_ci return; 240262306a36Sopenharmony_ci 240362306a36Sopenharmony_ci if (!scsi_host_dif_capable(sdp->host, sdkp->protection_type)) { 240462306a36Sopenharmony_ci sd_first_printk(KERN_NOTICE, sdkp, 240562306a36Sopenharmony_ci "Disabling DIF Type %u protection\n", 240662306a36Sopenharmony_ci sdkp->protection_type); 240762306a36Sopenharmony_ci sdkp->protection_type = 0; 240862306a36Sopenharmony_ci } 240962306a36Sopenharmony_ci 241062306a36Sopenharmony_ci sd_first_printk(KERN_NOTICE, sdkp, "Enabling DIF Type %u protection\n", 241162306a36Sopenharmony_ci sdkp->protection_type); 241262306a36Sopenharmony_ci} 241362306a36Sopenharmony_ci 241462306a36Sopenharmony_cistatic void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, 241562306a36Sopenharmony_ci struct scsi_sense_hdr *sshdr, int sense_valid, 241662306a36Sopenharmony_ci int the_result) 241762306a36Sopenharmony_ci{ 241862306a36Sopenharmony_ci if (sense_valid) 241962306a36Sopenharmony_ci sd_print_sense_hdr(sdkp, sshdr); 242062306a36Sopenharmony_ci else 242162306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Sense not available.\n"); 242262306a36Sopenharmony_ci 242362306a36Sopenharmony_ci /* 242462306a36Sopenharmony_ci * Set dirty bit for removable devices if not ready - 242562306a36Sopenharmony_ci * sometimes drives will not report this properly. 242662306a36Sopenharmony_ci */ 242762306a36Sopenharmony_ci if (sdp->removable && 242862306a36Sopenharmony_ci sense_valid && sshdr->sense_key == NOT_READY) 242962306a36Sopenharmony_ci set_media_not_present(sdkp); 243062306a36Sopenharmony_ci 243162306a36Sopenharmony_ci /* 243262306a36Sopenharmony_ci * We used to set media_present to 0 here to indicate no media 243362306a36Sopenharmony_ci * in the drive, but some drives fail read capacity even with 243462306a36Sopenharmony_ci * media present, so we can't do that. 243562306a36Sopenharmony_ci */ 243662306a36Sopenharmony_ci sdkp->capacity = 0; /* unknown mapped to zero - as usual */ 243762306a36Sopenharmony_ci} 243862306a36Sopenharmony_ci 243962306a36Sopenharmony_ci#define RC16_LEN 32 244062306a36Sopenharmony_ci#if RC16_LEN > SD_BUF_SIZE 244162306a36Sopenharmony_ci#error RC16_LEN must not be more than SD_BUF_SIZE 244262306a36Sopenharmony_ci#endif 244362306a36Sopenharmony_ci 244462306a36Sopenharmony_ci#define READ_CAPACITY_RETRIES_ON_RESET 10 244562306a36Sopenharmony_ci 244662306a36Sopenharmony_cistatic int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, 244762306a36Sopenharmony_ci unsigned char *buffer) 244862306a36Sopenharmony_ci{ 244962306a36Sopenharmony_ci unsigned char cmd[16]; 245062306a36Sopenharmony_ci struct scsi_sense_hdr sshdr; 245162306a36Sopenharmony_ci const struct scsi_exec_args exec_args = { 245262306a36Sopenharmony_ci .sshdr = &sshdr, 245362306a36Sopenharmony_ci }; 245462306a36Sopenharmony_ci int sense_valid = 0; 245562306a36Sopenharmony_ci int the_result; 245662306a36Sopenharmony_ci int retries = 3, reset_retries = READ_CAPACITY_RETRIES_ON_RESET; 245762306a36Sopenharmony_ci unsigned int alignment; 245862306a36Sopenharmony_ci unsigned long long lba; 245962306a36Sopenharmony_ci unsigned sector_size; 246062306a36Sopenharmony_ci 246162306a36Sopenharmony_ci if (sdp->no_read_capacity_16) 246262306a36Sopenharmony_ci return -EINVAL; 246362306a36Sopenharmony_ci 246462306a36Sopenharmony_ci do { 246562306a36Sopenharmony_ci memset(cmd, 0, 16); 246662306a36Sopenharmony_ci cmd[0] = SERVICE_ACTION_IN_16; 246762306a36Sopenharmony_ci cmd[1] = SAI_READ_CAPACITY_16; 246862306a36Sopenharmony_ci cmd[13] = RC16_LEN; 246962306a36Sopenharmony_ci memset(buffer, 0, RC16_LEN); 247062306a36Sopenharmony_ci 247162306a36Sopenharmony_ci the_result = scsi_execute_cmd(sdp, cmd, REQ_OP_DRV_IN, 247262306a36Sopenharmony_ci buffer, RC16_LEN, SD_TIMEOUT, 247362306a36Sopenharmony_ci sdkp->max_retries, &exec_args); 247462306a36Sopenharmony_ci 247562306a36Sopenharmony_ci if (media_not_present(sdkp, &sshdr)) 247662306a36Sopenharmony_ci return -ENODEV; 247762306a36Sopenharmony_ci 247862306a36Sopenharmony_ci if (the_result > 0) { 247962306a36Sopenharmony_ci sense_valid = scsi_sense_valid(&sshdr); 248062306a36Sopenharmony_ci if (sense_valid && 248162306a36Sopenharmony_ci sshdr.sense_key == ILLEGAL_REQUEST && 248262306a36Sopenharmony_ci (sshdr.asc == 0x20 || sshdr.asc == 0x24) && 248362306a36Sopenharmony_ci sshdr.ascq == 0x00) 248462306a36Sopenharmony_ci /* Invalid Command Operation Code or 248562306a36Sopenharmony_ci * Invalid Field in CDB, just retry 248662306a36Sopenharmony_ci * silently with RC10 */ 248762306a36Sopenharmony_ci return -EINVAL; 248862306a36Sopenharmony_ci if (sense_valid && 248962306a36Sopenharmony_ci sshdr.sense_key == UNIT_ATTENTION && 249062306a36Sopenharmony_ci sshdr.asc == 0x29 && sshdr.ascq == 0x00) 249162306a36Sopenharmony_ci /* Device reset might occur several times, 249262306a36Sopenharmony_ci * give it one more chance */ 249362306a36Sopenharmony_ci if (--reset_retries > 0) 249462306a36Sopenharmony_ci continue; 249562306a36Sopenharmony_ci } 249662306a36Sopenharmony_ci retries--; 249762306a36Sopenharmony_ci 249862306a36Sopenharmony_ci } while (the_result && retries); 249962306a36Sopenharmony_ci 250062306a36Sopenharmony_ci if (the_result) { 250162306a36Sopenharmony_ci sd_print_result(sdkp, "Read Capacity(16) failed", the_result); 250262306a36Sopenharmony_ci read_capacity_error(sdkp, sdp, &sshdr, sense_valid, the_result); 250362306a36Sopenharmony_ci return -EINVAL; 250462306a36Sopenharmony_ci } 250562306a36Sopenharmony_ci 250662306a36Sopenharmony_ci sector_size = get_unaligned_be32(&buffer[8]); 250762306a36Sopenharmony_ci lba = get_unaligned_be64(&buffer[0]); 250862306a36Sopenharmony_ci 250962306a36Sopenharmony_ci if (sd_read_protection_type(sdkp, buffer) < 0) { 251062306a36Sopenharmony_ci sdkp->capacity = 0; 251162306a36Sopenharmony_ci return -ENODEV; 251262306a36Sopenharmony_ci } 251362306a36Sopenharmony_ci 251462306a36Sopenharmony_ci /* Logical blocks per physical block exponent */ 251562306a36Sopenharmony_ci sdkp->physical_block_size = (1 << (buffer[13] & 0xf)) * sector_size; 251662306a36Sopenharmony_ci 251762306a36Sopenharmony_ci /* RC basis */ 251862306a36Sopenharmony_ci sdkp->rc_basis = (buffer[12] >> 4) & 0x3; 251962306a36Sopenharmony_ci 252062306a36Sopenharmony_ci /* Lowest aligned logical block */ 252162306a36Sopenharmony_ci alignment = ((buffer[14] & 0x3f) << 8 | buffer[15]) * sector_size; 252262306a36Sopenharmony_ci blk_queue_alignment_offset(sdp->request_queue, alignment); 252362306a36Sopenharmony_ci if (alignment && sdkp->first_scan) 252462306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 252562306a36Sopenharmony_ci "physical block alignment offset: %u\n", alignment); 252662306a36Sopenharmony_ci 252762306a36Sopenharmony_ci if (buffer[14] & 0x80) { /* LBPME */ 252862306a36Sopenharmony_ci sdkp->lbpme = 1; 252962306a36Sopenharmony_ci 253062306a36Sopenharmony_ci if (buffer[14] & 0x40) /* LBPRZ */ 253162306a36Sopenharmony_ci sdkp->lbprz = 1; 253262306a36Sopenharmony_ci 253362306a36Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_WS16); 253462306a36Sopenharmony_ci } 253562306a36Sopenharmony_ci 253662306a36Sopenharmony_ci sdkp->capacity = lba + 1; 253762306a36Sopenharmony_ci return sector_size; 253862306a36Sopenharmony_ci} 253962306a36Sopenharmony_ci 254062306a36Sopenharmony_cistatic int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, 254162306a36Sopenharmony_ci unsigned char *buffer) 254262306a36Sopenharmony_ci{ 254362306a36Sopenharmony_ci unsigned char cmd[16]; 254462306a36Sopenharmony_ci struct scsi_sense_hdr sshdr; 254562306a36Sopenharmony_ci const struct scsi_exec_args exec_args = { 254662306a36Sopenharmony_ci .sshdr = &sshdr, 254762306a36Sopenharmony_ci }; 254862306a36Sopenharmony_ci int sense_valid = 0; 254962306a36Sopenharmony_ci int the_result; 255062306a36Sopenharmony_ci int retries = 3, reset_retries = READ_CAPACITY_RETRIES_ON_RESET; 255162306a36Sopenharmony_ci sector_t lba; 255262306a36Sopenharmony_ci unsigned sector_size; 255362306a36Sopenharmony_ci 255462306a36Sopenharmony_ci do { 255562306a36Sopenharmony_ci cmd[0] = READ_CAPACITY; 255662306a36Sopenharmony_ci memset(&cmd[1], 0, 9); 255762306a36Sopenharmony_ci memset(buffer, 0, 8); 255862306a36Sopenharmony_ci 255962306a36Sopenharmony_ci the_result = scsi_execute_cmd(sdp, cmd, REQ_OP_DRV_IN, buffer, 256062306a36Sopenharmony_ci 8, SD_TIMEOUT, sdkp->max_retries, 256162306a36Sopenharmony_ci &exec_args); 256262306a36Sopenharmony_ci 256362306a36Sopenharmony_ci if (media_not_present(sdkp, &sshdr)) 256462306a36Sopenharmony_ci return -ENODEV; 256562306a36Sopenharmony_ci 256662306a36Sopenharmony_ci if (the_result > 0) { 256762306a36Sopenharmony_ci sense_valid = scsi_sense_valid(&sshdr); 256862306a36Sopenharmony_ci if (sense_valid && 256962306a36Sopenharmony_ci sshdr.sense_key == UNIT_ATTENTION && 257062306a36Sopenharmony_ci sshdr.asc == 0x29 && sshdr.ascq == 0x00) 257162306a36Sopenharmony_ci /* Device reset might occur several times, 257262306a36Sopenharmony_ci * give it one more chance */ 257362306a36Sopenharmony_ci if (--reset_retries > 0) 257462306a36Sopenharmony_ci continue; 257562306a36Sopenharmony_ci } 257662306a36Sopenharmony_ci retries--; 257762306a36Sopenharmony_ci 257862306a36Sopenharmony_ci } while (the_result && retries); 257962306a36Sopenharmony_ci 258062306a36Sopenharmony_ci if (the_result) { 258162306a36Sopenharmony_ci sd_print_result(sdkp, "Read Capacity(10) failed", the_result); 258262306a36Sopenharmony_ci read_capacity_error(sdkp, sdp, &sshdr, sense_valid, the_result); 258362306a36Sopenharmony_ci return -EINVAL; 258462306a36Sopenharmony_ci } 258562306a36Sopenharmony_ci 258662306a36Sopenharmony_ci sector_size = get_unaligned_be32(&buffer[4]); 258762306a36Sopenharmony_ci lba = get_unaligned_be32(&buffer[0]); 258862306a36Sopenharmony_ci 258962306a36Sopenharmony_ci if (sdp->no_read_capacity_16 && (lba == 0xffffffff)) { 259062306a36Sopenharmony_ci /* Some buggy (usb cardreader) devices return an lba of 259162306a36Sopenharmony_ci 0xffffffff when the want to report a size of 0 (with 259262306a36Sopenharmony_ci which they really mean no media is present) */ 259362306a36Sopenharmony_ci sdkp->capacity = 0; 259462306a36Sopenharmony_ci sdkp->physical_block_size = sector_size; 259562306a36Sopenharmony_ci return sector_size; 259662306a36Sopenharmony_ci } 259762306a36Sopenharmony_ci 259862306a36Sopenharmony_ci sdkp->capacity = lba + 1; 259962306a36Sopenharmony_ci sdkp->physical_block_size = sector_size; 260062306a36Sopenharmony_ci return sector_size; 260162306a36Sopenharmony_ci} 260262306a36Sopenharmony_ci 260362306a36Sopenharmony_cistatic int sd_try_rc16_first(struct scsi_device *sdp) 260462306a36Sopenharmony_ci{ 260562306a36Sopenharmony_ci if (sdp->host->max_cmd_len < 16) 260662306a36Sopenharmony_ci return 0; 260762306a36Sopenharmony_ci if (sdp->try_rc_10_first) 260862306a36Sopenharmony_ci return 0; 260962306a36Sopenharmony_ci if (sdp->scsi_level > SCSI_SPC_2) 261062306a36Sopenharmony_ci return 1; 261162306a36Sopenharmony_ci if (scsi_device_protection(sdp)) 261262306a36Sopenharmony_ci return 1; 261362306a36Sopenharmony_ci return 0; 261462306a36Sopenharmony_ci} 261562306a36Sopenharmony_ci 261662306a36Sopenharmony_ci/* 261762306a36Sopenharmony_ci * read disk capacity 261862306a36Sopenharmony_ci */ 261962306a36Sopenharmony_cistatic void 262062306a36Sopenharmony_cisd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer) 262162306a36Sopenharmony_ci{ 262262306a36Sopenharmony_ci int sector_size; 262362306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 262462306a36Sopenharmony_ci 262562306a36Sopenharmony_ci if (sd_try_rc16_first(sdp)) { 262662306a36Sopenharmony_ci sector_size = read_capacity_16(sdkp, sdp, buffer); 262762306a36Sopenharmony_ci if (sector_size == -EOVERFLOW) 262862306a36Sopenharmony_ci goto got_data; 262962306a36Sopenharmony_ci if (sector_size == -ENODEV) 263062306a36Sopenharmony_ci return; 263162306a36Sopenharmony_ci if (sector_size < 0) 263262306a36Sopenharmony_ci sector_size = read_capacity_10(sdkp, sdp, buffer); 263362306a36Sopenharmony_ci if (sector_size < 0) 263462306a36Sopenharmony_ci return; 263562306a36Sopenharmony_ci } else { 263662306a36Sopenharmony_ci sector_size = read_capacity_10(sdkp, sdp, buffer); 263762306a36Sopenharmony_ci if (sector_size == -EOVERFLOW) 263862306a36Sopenharmony_ci goto got_data; 263962306a36Sopenharmony_ci if (sector_size < 0) 264062306a36Sopenharmony_ci return; 264162306a36Sopenharmony_ci if ((sizeof(sdkp->capacity) > 4) && 264262306a36Sopenharmony_ci (sdkp->capacity > 0xffffffffULL)) { 264362306a36Sopenharmony_ci int old_sector_size = sector_size; 264462306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Very big device. " 264562306a36Sopenharmony_ci "Trying to use READ CAPACITY(16).\n"); 264662306a36Sopenharmony_ci sector_size = read_capacity_16(sdkp, sdp, buffer); 264762306a36Sopenharmony_ci if (sector_size < 0) { 264862306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 264962306a36Sopenharmony_ci "Using 0xffffffff as device size\n"); 265062306a36Sopenharmony_ci sdkp->capacity = 1 + (sector_t) 0xffffffff; 265162306a36Sopenharmony_ci sector_size = old_sector_size; 265262306a36Sopenharmony_ci goto got_data; 265362306a36Sopenharmony_ci } 265462306a36Sopenharmony_ci /* Remember that READ CAPACITY(16) succeeded */ 265562306a36Sopenharmony_ci sdp->try_rc_10_first = 0; 265662306a36Sopenharmony_ci } 265762306a36Sopenharmony_ci } 265862306a36Sopenharmony_ci 265962306a36Sopenharmony_ci /* Some devices are known to return the total number of blocks, 266062306a36Sopenharmony_ci * not the highest block number. Some devices have versions 266162306a36Sopenharmony_ci * which do this and others which do not. Some devices we might 266262306a36Sopenharmony_ci * suspect of doing this but we don't know for certain. 266362306a36Sopenharmony_ci * 266462306a36Sopenharmony_ci * If we know the reported capacity is wrong, decrement it. If 266562306a36Sopenharmony_ci * we can only guess, then assume the number of blocks is even 266662306a36Sopenharmony_ci * (usually true but not always) and err on the side of lowering 266762306a36Sopenharmony_ci * the capacity. 266862306a36Sopenharmony_ci */ 266962306a36Sopenharmony_ci if (sdp->fix_capacity || 267062306a36Sopenharmony_ci (sdp->guess_capacity && (sdkp->capacity & 0x01))) { 267162306a36Sopenharmony_ci sd_printk(KERN_INFO, sdkp, "Adjusting the sector count " 267262306a36Sopenharmony_ci "from its reported value: %llu\n", 267362306a36Sopenharmony_ci (unsigned long long) sdkp->capacity); 267462306a36Sopenharmony_ci --sdkp->capacity; 267562306a36Sopenharmony_ci } 267662306a36Sopenharmony_ci 267762306a36Sopenharmony_cigot_data: 267862306a36Sopenharmony_ci if (sector_size == 0) { 267962306a36Sopenharmony_ci sector_size = 512; 268062306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Sector size 0 reported, " 268162306a36Sopenharmony_ci "assuming 512.\n"); 268262306a36Sopenharmony_ci } 268362306a36Sopenharmony_ci 268462306a36Sopenharmony_ci if (sector_size != 512 && 268562306a36Sopenharmony_ci sector_size != 1024 && 268662306a36Sopenharmony_ci sector_size != 2048 && 268762306a36Sopenharmony_ci sector_size != 4096) { 268862306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Unsupported sector size %d.\n", 268962306a36Sopenharmony_ci sector_size); 269062306a36Sopenharmony_ci /* 269162306a36Sopenharmony_ci * The user might want to re-format the drive with 269262306a36Sopenharmony_ci * a supported sectorsize. Once this happens, it 269362306a36Sopenharmony_ci * would be relatively trivial to set the thing up. 269462306a36Sopenharmony_ci * For this reason, we leave the thing in the table. 269562306a36Sopenharmony_ci */ 269662306a36Sopenharmony_ci sdkp->capacity = 0; 269762306a36Sopenharmony_ci /* 269862306a36Sopenharmony_ci * set a bogus sector size so the normal read/write 269962306a36Sopenharmony_ci * logic in the block layer will eventually refuse any 270062306a36Sopenharmony_ci * request on this device without tripping over power 270162306a36Sopenharmony_ci * of two sector size assumptions 270262306a36Sopenharmony_ci */ 270362306a36Sopenharmony_ci sector_size = 512; 270462306a36Sopenharmony_ci } 270562306a36Sopenharmony_ci blk_queue_logical_block_size(sdp->request_queue, sector_size); 270662306a36Sopenharmony_ci blk_queue_physical_block_size(sdp->request_queue, 270762306a36Sopenharmony_ci sdkp->physical_block_size); 270862306a36Sopenharmony_ci sdkp->device->sector_size = sector_size; 270962306a36Sopenharmony_ci 271062306a36Sopenharmony_ci if (sdkp->capacity > 0xffffffff) 271162306a36Sopenharmony_ci sdp->use_16_for_rw = 1; 271262306a36Sopenharmony_ci 271362306a36Sopenharmony_ci} 271462306a36Sopenharmony_ci 271562306a36Sopenharmony_ci/* 271662306a36Sopenharmony_ci * Print disk capacity 271762306a36Sopenharmony_ci */ 271862306a36Sopenharmony_cistatic void 271962306a36Sopenharmony_cisd_print_capacity(struct scsi_disk *sdkp, 272062306a36Sopenharmony_ci sector_t old_capacity) 272162306a36Sopenharmony_ci{ 272262306a36Sopenharmony_ci int sector_size = sdkp->device->sector_size; 272362306a36Sopenharmony_ci char cap_str_2[10], cap_str_10[10]; 272462306a36Sopenharmony_ci 272562306a36Sopenharmony_ci if (!sdkp->first_scan && old_capacity == sdkp->capacity) 272662306a36Sopenharmony_ci return; 272762306a36Sopenharmony_ci 272862306a36Sopenharmony_ci string_get_size(sdkp->capacity, sector_size, 272962306a36Sopenharmony_ci STRING_UNITS_2, cap_str_2, sizeof(cap_str_2)); 273062306a36Sopenharmony_ci string_get_size(sdkp->capacity, sector_size, 273162306a36Sopenharmony_ci STRING_UNITS_10, cap_str_10, sizeof(cap_str_10)); 273262306a36Sopenharmony_ci 273362306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 273462306a36Sopenharmony_ci "%llu %d-byte logical blocks: (%s/%s)\n", 273562306a36Sopenharmony_ci (unsigned long long)sdkp->capacity, 273662306a36Sopenharmony_ci sector_size, cap_str_10, cap_str_2); 273762306a36Sopenharmony_ci 273862306a36Sopenharmony_ci if (sdkp->physical_block_size != sector_size) 273962306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 274062306a36Sopenharmony_ci "%u-byte physical blocks\n", 274162306a36Sopenharmony_ci sdkp->physical_block_size); 274262306a36Sopenharmony_ci} 274362306a36Sopenharmony_ci 274462306a36Sopenharmony_ci/* called with buffer of length 512 */ 274562306a36Sopenharmony_cistatic inline int 274662306a36Sopenharmony_cisd_do_mode_sense(struct scsi_disk *sdkp, int dbd, int modepage, 274762306a36Sopenharmony_ci unsigned char *buffer, int len, struct scsi_mode_data *data, 274862306a36Sopenharmony_ci struct scsi_sense_hdr *sshdr) 274962306a36Sopenharmony_ci{ 275062306a36Sopenharmony_ci /* 275162306a36Sopenharmony_ci * If we must use MODE SENSE(10), make sure that the buffer length 275262306a36Sopenharmony_ci * is at least 8 bytes so that the mode sense header fits. 275362306a36Sopenharmony_ci */ 275462306a36Sopenharmony_ci if (sdkp->device->use_10_for_ms && len < 8) 275562306a36Sopenharmony_ci len = 8; 275662306a36Sopenharmony_ci 275762306a36Sopenharmony_ci return scsi_mode_sense(sdkp->device, dbd, modepage, 0, buffer, len, 275862306a36Sopenharmony_ci SD_TIMEOUT, sdkp->max_retries, data, sshdr); 275962306a36Sopenharmony_ci} 276062306a36Sopenharmony_ci 276162306a36Sopenharmony_ci/* 276262306a36Sopenharmony_ci * read write protect setting, if possible - called only in sd_revalidate_disk() 276362306a36Sopenharmony_ci * called with buffer of length SD_BUF_SIZE 276462306a36Sopenharmony_ci */ 276562306a36Sopenharmony_cistatic void 276662306a36Sopenharmony_cisd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer) 276762306a36Sopenharmony_ci{ 276862306a36Sopenharmony_ci int res; 276962306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 277062306a36Sopenharmony_ci struct scsi_mode_data data; 277162306a36Sopenharmony_ci int old_wp = sdkp->write_prot; 277262306a36Sopenharmony_ci 277362306a36Sopenharmony_ci set_disk_ro(sdkp->disk, 0); 277462306a36Sopenharmony_ci if (sdp->skip_ms_page_3f) { 277562306a36Sopenharmony_ci sd_first_printk(KERN_NOTICE, sdkp, "Assuming Write Enabled\n"); 277662306a36Sopenharmony_ci return; 277762306a36Sopenharmony_ci } 277862306a36Sopenharmony_ci 277962306a36Sopenharmony_ci if (sdp->use_192_bytes_for_3f) { 278062306a36Sopenharmony_ci res = sd_do_mode_sense(sdkp, 0, 0x3F, buffer, 192, &data, NULL); 278162306a36Sopenharmony_ci } else { 278262306a36Sopenharmony_ci /* 278362306a36Sopenharmony_ci * First attempt: ask for all pages (0x3F), but only 4 bytes. 278462306a36Sopenharmony_ci * We have to start carefully: some devices hang if we ask 278562306a36Sopenharmony_ci * for more than is available. 278662306a36Sopenharmony_ci */ 278762306a36Sopenharmony_ci res = sd_do_mode_sense(sdkp, 0, 0x3F, buffer, 4, &data, NULL); 278862306a36Sopenharmony_ci 278962306a36Sopenharmony_ci /* 279062306a36Sopenharmony_ci * Second attempt: ask for page 0 When only page 0 is 279162306a36Sopenharmony_ci * implemented, a request for page 3F may return Sense Key 279262306a36Sopenharmony_ci * 5: Illegal Request, Sense Code 24: Invalid field in 279362306a36Sopenharmony_ci * CDB. 279462306a36Sopenharmony_ci */ 279562306a36Sopenharmony_ci if (res < 0) 279662306a36Sopenharmony_ci res = sd_do_mode_sense(sdkp, 0, 0, buffer, 4, &data, NULL); 279762306a36Sopenharmony_ci 279862306a36Sopenharmony_ci /* 279962306a36Sopenharmony_ci * Third attempt: ask 255 bytes, as we did earlier. 280062306a36Sopenharmony_ci */ 280162306a36Sopenharmony_ci if (res < 0) 280262306a36Sopenharmony_ci res = sd_do_mode_sense(sdkp, 0, 0x3F, buffer, 255, 280362306a36Sopenharmony_ci &data, NULL); 280462306a36Sopenharmony_ci } 280562306a36Sopenharmony_ci 280662306a36Sopenharmony_ci if (res < 0) { 280762306a36Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 280862306a36Sopenharmony_ci "Test WP failed, assume Write Enabled\n"); 280962306a36Sopenharmony_ci } else { 281062306a36Sopenharmony_ci sdkp->write_prot = ((data.device_specific & 0x80) != 0); 281162306a36Sopenharmony_ci set_disk_ro(sdkp->disk, sdkp->write_prot); 281262306a36Sopenharmony_ci if (sdkp->first_scan || old_wp != sdkp->write_prot) { 281362306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n", 281462306a36Sopenharmony_ci sdkp->write_prot ? "on" : "off"); 281562306a36Sopenharmony_ci sd_printk(KERN_DEBUG, sdkp, "Mode Sense: %4ph\n", buffer); 281662306a36Sopenharmony_ci } 281762306a36Sopenharmony_ci } 281862306a36Sopenharmony_ci} 281962306a36Sopenharmony_ci 282062306a36Sopenharmony_ci/* 282162306a36Sopenharmony_ci * sd_read_cache_type - called only from sd_revalidate_disk() 282262306a36Sopenharmony_ci * called with buffer of length SD_BUF_SIZE 282362306a36Sopenharmony_ci */ 282462306a36Sopenharmony_cistatic void 282562306a36Sopenharmony_cisd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) 282662306a36Sopenharmony_ci{ 282762306a36Sopenharmony_ci int len = 0, res; 282862306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 282962306a36Sopenharmony_ci 283062306a36Sopenharmony_ci int dbd; 283162306a36Sopenharmony_ci int modepage; 283262306a36Sopenharmony_ci int first_len; 283362306a36Sopenharmony_ci struct scsi_mode_data data; 283462306a36Sopenharmony_ci struct scsi_sense_hdr sshdr; 283562306a36Sopenharmony_ci int old_wce = sdkp->WCE; 283662306a36Sopenharmony_ci int old_rcd = sdkp->RCD; 283762306a36Sopenharmony_ci int old_dpofua = sdkp->DPOFUA; 283862306a36Sopenharmony_ci 283962306a36Sopenharmony_ci 284062306a36Sopenharmony_ci if (sdkp->cache_override) 284162306a36Sopenharmony_ci return; 284262306a36Sopenharmony_ci 284362306a36Sopenharmony_ci first_len = 4; 284462306a36Sopenharmony_ci if (sdp->skip_ms_page_8) { 284562306a36Sopenharmony_ci if (sdp->type == TYPE_RBC) 284662306a36Sopenharmony_ci goto defaults; 284762306a36Sopenharmony_ci else { 284862306a36Sopenharmony_ci if (sdp->skip_ms_page_3f) 284962306a36Sopenharmony_ci goto defaults; 285062306a36Sopenharmony_ci modepage = 0x3F; 285162306a36Sopenharmony_ci if (sdp->use_192_bytes_for_3f) 285262306a36Sopenharmony_ci first_len = 192; 285362306a36Sopenharmony_ci dbd = 0; 285462306a36Sopenharmony_ci } 285562306a36Sopenharmony_ci } else if (sdp->type == TYPE_RBC) { 285662306a36Sopenharmony_ci modepage = 6; 285762306a36Sopenharmony_ci dbd = 8; 285862306a36Sopenharmony_ci } else { 285962306a36Sopenharmony_ci modepage = 8; 286062306a36Sopenharmony_ci dbd = 0; 286162306a36Sopenharmony_ci } 286262306a36Sopenharmony_ci 286362306a36Sopenharmony_ci /* cautiously ask */ 286462306a36Sopenharmony_ci res = sd_do_mode_sense(sdkp, dbd, modepage, buffer, first_len, 286562306a36Sopenharmony_ci &data, &sshdr); 286662306a36Sopenharmony_ci 286762306a36Sopenharmony_ci if (res < 0) 286862306a36Sopenharmony_ci goto bad_sense; 286962306a36Sopenharmony_ci 287062306a36Sopenharmony_ci if (!data.header_length) { 287162306a36Sopenharmony_ci modepage = 6; 287262306a36Sopenharmony_ci first_len = 0; 287362306a36Sopenharmony_ci sd_first_printk(KERN_ERR, sdkp, 287462306a36Sopenharmony_ci "Missing header in MODE_SENSE response\n"); 287562306a36Sopenharmony_ci } 287662306a36Sopenharmony_ci 287762306a36Sopenharmony_ci /* that went OK, now ask for the proper length */ 287862306a36Sopenharmony_ci len = data.length; 287962306a36Sopenharmony_ci 288062306a36Sopenharmony_ci /* 288162306a36Sopenharmony_ci * We're only interested in the first three bytes, actually. 288262306a36Sopenharmony_ci * But the data cache page is defined for the first 20. 288362306a36Sopenharmony_ci */ 288462306a36Sopenharmony_ci if (len < 3) 288562306a36Sopenharmony_ci goto bad_sense; 288662306a36Sopenharmony_ci else if (len > SD_BUF_SIZE) { 288762306a36Sopenharmony_ci sd_first_printk(KERN_NOTICE, sdkp, "Truncating mode parameter " 288862306a36Sopenharmony_ci "data from %d to %d bytes\n", len, SD_BUF_SIZE); 288962306a36Sopenharmony_ci len = SD_BUF_SIZE; 289062306a36Sopenharmony_ci } 289162306a36Sopenharmony_ci if (modepage == 0x3F && sdp->use_192_bytes_for_3f) 289262306a36Sopenharmony_ci len = 192; 289362306a36Sopenharmony_ci 289462306a36Sopenharmony_ci /* Get the data */ 289562306a36Sopenharmony_ci if (len > first_len) 289662306a36Sopenharmony_ci res = sd_do_mode_sense(sdkp, dbd, modepage, buffer, len, 289762306a36Sopenharmony_ci &data, &sshdr); 289862306a36Sopenharmony_ci 289962306a36Sopenharmony_ci if (!res) { 290062306a36Sopenharmony_ci int offset = data.header_length + data.block_descriptor_length; 290162306a36Sopenharmony_ci 290262306a36Sopenharmony_ci while (offset < len) { 290362306a36Sopenharmony_ci u8 page_code = buffer[offset] & 0x3F; 290462306a36Sopenharmony_ci u8 spf = buffer[offset] & 0x40; 290562306a36Sopenharmony_ci 290662306a36Sopenharmony_ci if (page_code == 8 || page_code == 6) { 290762306a36Sopenharmony_ci /* We're interested only in the first 3 bytes. 290862306a36Sopenharmony_ci */ 290962306a36Sopenharmony_ci if (len - offset <= 2) { 291062306a36Sopenharmony_ci sd_first_printk(KERN_ERR, sdkp, 291162306a36Sopenharmony_ci "Incomplete mode parameter " 291262306a36Sopenharmony_ci "data\n"); 291362306a36Sopenharmony_ci goto defaults; 291462306a36Sopenharmony_ci } else { 291562306a36Sopenharmony_ci modepage = page_code; 291662306a36Sopenharmony_ci goto Page_found; 291762306a36Sopenharmony_ci } 291862306a36Sopenharmony_ci } else { 291962306a36Sopenharmony_ci /* Go to the next page */ 292062306a36Sopenharmony_ci if (spf && len - offset > 3) 292162306a36Sopenharmony_ci offset += 4 + (buffer[offset+2] << 8) + 292262306a36Sopenharmony_ci buffer[offset+3]; 292362306a36Sopenharmony_ci else if (!spf && len - offset > 1) 292462306a36Sopenharmony_ci offset += 2 + buffer[offset+1]; 292562306a36Sopenharmony_ci else { 292662306a36Sopenharmony_ci sd_first_printk(KERN_ERR, sdkp, 292762306a36Sopenharmony_ci "Incomplete mode " 292862306a36Sopenharmony_ci "parameter data\n"); 292962306a36Sopenharmony_ci goto defaults; 293062306a36Sopenharmony_ci } 293162306a36Sopenharmony_ci } 293262306a36Sopenharmony_ci } 293362306a36Sopenharmony_ci 293462306a36Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 293562306a36Sopenharmony_ci "No Caching mode page found\n"); 293662306a36Sopenharmony_ci goto defaults; 293762306a36Sopenharmony_ci 293862306a36Sopenharmony_ci Page_found: 293962306a36Sopenharmony_ci if (modepage == 8) { 294062306a36Sopenharmony_ci sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); 294162306a36Sopenharmony_ci sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); 294262306a36Sopenharmony_ci } else { 294362306a36Sopenharmony_ci sdkp->WCE = ((buffer[offset + 2] & 0x01) == 0); 294462306a36Sopenharmony_ci sdkp->RCD = 0; 294562306a36Sopenharmony_ci } 294662306a36Sopenharmony_ci 294762306a36Sopenharmony_ci sdkp->DPOFUA = (data.device_specific & 0x10) != 0; 294862306a36Sopenharmony_ci if (sdp->broken_fua) { 294962306a36Sopenharmony_ci sd_first_printk(KERN_NOTICE, sdkp, "Disabling FUA\n"); 295062306a36Sopenharmony_ci sdkp->DPOFUA = 0; 295162306a36Sopenharmony_ci } else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw && 295262306a36Sopenharmony_ci !sdkp->device->use_16_for_rw) { 295362306a36Sopenharmony_ci sd_first_printk(KERN_NOTICE, sdkp, 295462306a36Sopenharmony_ci "Uses READ/WRITE(6), disabling FUA\n"); 295562306a36Sopenharmony_ci sdkp->DPOFUA = 0; 295662306a36Sopenharmony_ci } 295762306a36Sopenharmony_ci 295862306a36Sopenharmony_ci /* No cache flush allowed for write protected devices */ 295962306a36Sopenharmony_ci if (sdkp->WCE && sdkp->write_prot) 296062306a36Sopenharmony_ci sdkp->WCE = 0; 296162306a36Sopenharmony_ci 296262306a36Sopenharmony_ci if (sdkp->first_scan || old_wce != sdkp->WCE || 296362306a36Sopenharmony_ci old_rcd != sdkp->RCD || old_dpofua != sdkp->DPOFUA) 296462306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 296562306a36Sopenharmony_ci "Write cache: %s, read cache: %s, %s\n", 296662306a36Sopenharmony_ci sdkp->WCE ? "enabled" : "disabled", 296762306a36Sopenharmony_ci sdkp->RCD ? "disabled" : "enabled", 296862306a36Sopenharmony_ci sdkp->DPOFUA ? "supports DPO and FUA" 296962306a36Sopenharmony_ci : "doesn't support DPO or FUA"); 297062306a36Sopenharmony_ci 297162306a36Sopenharmony_ci return; 297262306a36Sopenharmony_ci } 297362306a36Sopenharmony_ci 297462306a36Sopenharmony_cibad_sense: 297562306a36Sopenharmony_ci if (scsi_sense_valid(&sshdr) && 297662306a36Sopenharmony_ci sshdr.sense_key == ILLEGAL_REQUEST && 297762306a36Sopenharmony_ci sshdr.asc == 0x24 && sshdr.ascq == 0x0) 297862306a36Sopenharmony_ci /* Invalid field in CDB */ 297962306a36Sopenharmony_ci sd_first_printk(KERN_NOTICE, sdkp, "Cache data unavailable\n"); 298062306a36Sopenharmony_ci else 298162306a36Sopenharmony_ci sd_first_printk(KERN_ERR, sdkp, 298262306a36Sopenharmony_ci "Asking for cache data failed\n"); 298362306a36Sopenharmony_ci 298462306a36Sopenharmony_cidefaults: 298562306a36Sopenharmony_ci if (sdp->wce_default_on) { 298662306a36Sopenharmony_ci sd_first_printk(KERN_NOTICE, sdkp, 298762306a36Sopenharmony_ci "Assuming drive cache: write back\n"); 298862306a36Sopenharmony_ci sdkp->WCE = 1; 298962306a36Sopenharmony_ci } else { 299062306a36Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 299162306a36Sopenharmony_ci "Assuming drive cache: write through\n"); 299262306a36Sopenharmony_ci sdkp->WCE = 0; 299362306a36Sopenharmony_ci } 299462306a36Sopenharmony_ci sdkp->RCD = 0; 299562306a36Sopenharmony_ci sdkp->DPOFUA = 0; 299662306a36Sopenharmony_ci} 299762306a36Sopenharmony_ci 299862306a36Sopenharmony_ci/* 299962306a36Sopenharmony_ci * The ATO bit indicates whether the DIF application tag is available 300062306a36Sopenharmony_ci * for use by the operating system. 300162306a36Sopenharmony_ci */ 300262306a36Sopenharmony_cistatic void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) 300362306a36Sopenharmony_ci{ 300462306a36Sopenharmony_ci int res, offset; 300562306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 300662306a36Sopenharmony_ci struct scsi_mode_data data; 300762306a36Sopenharmony_ci struct scsi_sense_hdr sshdr; 300862306a36Sopenharmony_ci 300962306a36Sopenharmony_ci if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC) 301062306a36Sopenharmony_ci return; 301162306a36Sopenharmony_ci 301262306a36Sopenharmony_ci if (sdkp->protection_type == 0) 301362306a36Sopenharmony_ci return; 301462306a36Sopenharmony_ci 301562306a36Sopenharmony_ci res = scsi_mode_sense(sdp, 1, 0x0a, 0, buffer, 36, SD_TIMEOUT, 301662306a36Sopenharmony_ci sdkp->max_retries, &data, &sshdr); 301762306a36Sopenharmony_ci 301862306a36Sopenharmony_ci if (res < 0 || !data.header_length || 301962306a36Sopenharmony_ci data.length < 6) { 302062306a36Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 302162306a36Sopenharmony_ci "getting Control mode page failed, assume no ATO\n"); 302262306a36Sopenharmony_ci 302362306a36Sopenharmony_ci if (scsi_sense_valid(&sshdr)) 302462306a36Sopenharmony_ci sd_print_sense_hdr(sdkp, &sshdr); 302562306a36Sopenharmony_ci 302662306a36Sopenharmony_ci return; 302762306a36Sopenharmony_ci } 302862306a36Sopenharmony_ci 302962306a36Sopenharmony_ci offset = data.header_length + data.block_descriptor_length; 303062306a36Sopenharmony_ci 303162306a36Sopenharmony_ci if ((buffer[offset] & 0x3f) != 0x0a) { 303262306a36Sopenharmony_ci sd_first_printk(KERN_ERR, sdkp, "ATO Got wrong page\n"); 303362306a36Sopenharmony_ci return; 303462306a36Sopenharmony_ci } 303562306a36Sopenharmony_ci 303662306a36Sopenharmony_ci if ((buffer[offset + 5] & 0x80) == 0) 303762306a36Sopenharmony_ci return; 303862306a36Sopenharmony_ci 303962306a36Sopenharmony_ci sdkp->ATO = 1; 304062306a36Sopenharmony_ci 304162306a36Sopenharmony_ci return; 304262306a36Sopenharmony_ci} 304362306a36Sopenharmony_ci 304462306a36Sopenharmony_ci/** 304562306a36Sopenharmony_ci * sd_read_block_limits - Query disk device for preferred I/O sizes. 304662306a36Sopenharmony_ci * @sdkp: disk to query 304762306a36Sopenharmony_ci */ 304862306a36Sopenharmony_cistatic void sd_read_block_limits(struct scsi_disk *sdkp) 304962306a36Sopenharmony_ci{ 305062306a36Sopenharmony_ci struct scsi_vpd *vpd; 305162306a36Sopenharmony_ci 305262306a36Sopenharmony_ci rcu_read_lock(); 305362306a36Sopenharmony_ci 305462306a36Sopenharmony_ci vpd = rcu_dereference(sdkp->device->vpd_pgb0); 305562306a36Sopenharmony_ci if (!vpd || vpd->len < 16) 305662306a36Sopenharmony_ci goto out; 305762306a36Sopenharmony_ci 305862306a36Sopenharmony_ci sdkp->min_xfer_blocks = get_unaligned_be16(&vpd->data[6]); 305962306a36Sopenharmony_ci sdkp->max_xfer_blocks = get_unaligned_be32(&vpd->data[8]); 306062306a36Sopenharmony_ci sdkp->opt_xfer_blocks = get_unaligned_be32(&vpd->data[12]); 306162306a36Sopenharmony_ci 306262306a36Sopenharmony_ci if (vpd->len >= 64) { 306362306a36Sopenharmony_ci unsigned int lba_count, desc_count; 306462306a36Sopenharmony_ci 306562306a36Sopenharmony_ci sdkp->max_ws_blocks = (u32)get_unaligned_be64(&vpd->data[36]); 306662306a36Sopenharmony_ci 306762306a36Sopenharmony_ci if (!sdkp->lbpme) 306862306a36Sopenharmony_ci goto out; 306962306a36Sopenharmony_ci 307062306a36Sopenharmony_ci lba_count = get_unaligned_be32(&vpd->data[20]); 307162306a36Sopenharmony_ci desc_count = get_unaligned_be32(&vpd->data[24]); 307262306a36Sopenharmony_ci 307362306a36Sopenharmony_ci if (lba_count && desc_count) 307462306a36Sopenharmony_ci sdkp->max_unmap_blocks = lba_count; 307562306a36Sopenharmony_ci 307662306a36Sopenharmony_ci sdkp->unmap_granularity = get_unaligned_be32(&vpd->data[28]); 307762306a36Sopenharmony_ci 307862306a36Sopenharmony_ci if (vpd->data[32] & 0x80) 307962306a36Sopenharmony_ci sdkp->unmap_alignment = 308062306a36Sopenharmony_ci get_unaligned_be32(&vpd->data[32]) & ~(1 << 31); 308162306a36Sopenharmony_ci 308262306a36Sopenharmony_ci if (!sdkp->lbpvpd) { /* LBP VPD page not provided */ 308362306a36Sopenharmony_ci 308462306a36Sopenharmony_ci if (sdkp->max_unmap_blocks) 308562306a36Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_UNMAP); 308662306a36Sopenharmony_ci else 308762306a36Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_WS16); 308862306a36Sopenharmony_ci 308962306a36Sopenharmony_ci } else { /* LBP VPD page tells us what to use */ 309062306a36Sopenharmony_ci if (sdkp->lbpu && sdkp->max_unmap_blocks) 309162306a36Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_UNMAP); 309262306a36Sopenharmony_ci else if (sdkp->lbpws) 309362306a36Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_WS16); 309462306a36Sopenharmony_ci else if (sdkp->lbpws10) 309562306a36Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_WS10); 309662306a36Sopenharmony_ci else 309762306a36Sopenharmony_ci sd_config_discard(sdkp, SD_LBP_DISABLE); 309862306a36Sopenharmony_ci } 309962306a36Sopenharmony_ci } 310062306a36Sopenharmony_ci 310162306a36Sopenharmony_ci out: 310262306a36Sopenharmony_ci rcu_read_unlock(); 310362306a36Sopenharmony_ci} 310462306a36Sopenharmony_ci 310562306a36Sopenharmony_ci/** 310662306a36Sopenharmony_ci * sd_read_block_characteristics - Query block dev. characteristics 310762306a36Sopenharmony_ci * @sdkp: disk to query 310862306a36Sopenharmony_ci */ 310962306a36Sopenharmony_cistatic void sd_read_block_characteristics(struct scsi_disk *sdkp) 311062306a36Sopenharmony_ci{ 311162306a36Sopenharmony_ci struct request_queue *q = sdkp->disk->queue; 311262306a36Sopenharmony_ci struct scsi_vpd *vpd; 311362306a36Sopenharmony_ci u16 rot; 311462306a36Sopenharmony_ci u8 zoned; 311562306a36Sopenharmony_ci 311662306a36Sopenharmony_ci rcu_read_lock(); 311762306a36Sopenharmony_ci vpd = rcu_dereference(sdkp->device->vpd_pgb1); 311862306a36Sopenharmony_ci 311962306a36Sopenharmony_ci if (!vpd || vpd->len < 8) { 312062306a36Sopenharmony_ci rcu_read_unlock(); 312162306a36Sopenharmony_ci return; 312262306a36Sopenharmony_ci } 312362306a36Sopenharmony_ci 312462306a36Sopenharmony_ci rot = get_unaligned_be16(&vpd->data[4]); 312562306a36Sopenharmony_ci zoned = (vpd->data[8] >> 4) & 3; 312662306a36Sopenharmony_ci rcu_read_unlock(); 312762306a36Sopenharmony_ci 312862306a36Sopenharmony_ci if (rot == 1) { 312962306a36Sopenharmony_ci blk_queue_flag_set(QUEUE_FLAG_NONROT, q); 313062306a36Sopenharmony_ci blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q); 313162306a36Sopenharmony_ci } 313262306a36Sopenharmony_ci 313362306a36Sopenharmony_ci if (sdkp->device->type == TYPE_ZBC) { 313462306a36Sopenharmony_ci /* 313562306a36Sopenharmony_ci * Host-managed: Per ZBC and ZAC specifications, writes in 313662306a36Sopenharmony_ci * sequential write required zones of host-managed devices must 313762306a36Sopenharmony_ci * be aligned to the device physical block size. 313862306a36Sopenharmony_ci */ 313962306a36Sopenharmony_ci disk_set_zoned(sdkp->disk, BLK_ZONED_HM); 314062306a36Sopenharmony_ci blk_queue_zone_write_granularity(q, sdkp->physical_block_size); 314162306a36Sopenharmony_ci } else { 314262306a36Sopenharmony_ci sdkp->zoned = zoned; 314362306a36Sopenharmony_ci if (sdkp->zoned == 1) { 314462306a36Sopenharmony_ci /* Host-aware */ 314562306a36Sopenharmony_ci disk_set_zoned(sdkp->disk, BLK_ZONED_HA); 314662306a36Sopenharmony_ci } else { 314762306a36Sopenharmony_ci /* Regular disk or drive managed disk */ 314862306a36Sopenharmony_ci disk_set_zoned(sdkp->disk, BLK_ZONED_NONE); 314962306a36Sopenharmony_ci } 315062306a36Sopenharmony_ci } 315162306a36Sopenharmony_ci 315262306a36Sopenharmony_ci if (!sdkp->first_scan) 315362306a36Sopenharmony_ci return; 315462306a36Sopenharmony_ci 315562306a36Sopenharmony_ci if (blk_queue_is_zoned(q)) { 315662306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Host-%s zoned block device\n", 315762306a36Sopenharmony_ci q->limits.zoned == BLK_ZONED_HM ? "managed" : "aware"); 315862306a36Sopenharmony_ci } else { 315962306a36Sopenharmony_ci if (sdkp->zoned == 1) 316062306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 316162306a36Sopenharmony_ci "Host-aware SMR disk used as regular disk\n"); 316262306a36Sopenharmony_ci else if (sdkp->zoned == 2) 316362306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 316462306a36Sopenharmony_ci "Drive-managed SMR disk\n"); 316562306a36Sopenharmony_ci } 316662306a36Sopenharmony_ci} 316762306a36Sopenharmony_ci 316862306a36Sopenharmony_ci/** 316962306a36Sopenharmony_ci * sd_read_block_provisioning - Query provisioning VPD page 317062306a36Sopenharmony_ci * @sdkp: disk to query 317162306a36Sopenharmony_ci */ 317262306a36Sopenharmony_cistatic void sd_read_block_provisioning(struct scsi_disk *sdkp) 317362306a36Sopenharmony_ci{ 317462306a36Sopenharmony_ci struct scsi_vpd *vpd; 317562306a36Sopenharmony_ci 317662306a36Sopenharmony_ci if (sdkp->lbpme == 0) 317762306a36Sopenharmony_ci return; 317862306a36Sopenharmony_ci 317962306a36Sopenharmony_ci rcu_read_lock(); 318062306a36Sopenharmony_ci vpd = rcu_dereference(sdkp->device->vpd_pgb2); 318162306a36Sopenharmony_ci 318262306a36Sopenharmony_ci if (!vpd || vpd->len < 8) { 318362306a36Sopenharmony_ci rcu_read_unlock(); 318462306a36Sopenharmony_ci return; 318562306a36Sopenharmony_ci } 318662306a36Sopenharmony_ci 318762306a36Sopenharmony_ci sdkp->lbpvpd = 1; 318862306a36Sopenharmony_ci sdkp->lbpu = (vpd->data[5] >> 7) & 1; /* UNMAP */ 318962306a36Sopenharmony_ci sdkp->lbpws = (vpd->data[5] >> 6) & 1; /* WRITE SAME(16) w/ UNMAP */ 319062306a36Sopenharmony_ci sdkp->lbpws10 = (vpd->data[5] >> 5) & 1; /* WRITE SAME(10) w/ UNMAP */ 319162306a36Sopenharmony_ci rcu_read_unlock(); 319262306a36Sopenharmony_ci} 319362306a36Sopenharmony_ci 319462306a36Sopenharmony_cistatic void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) 319562306a36Sopenharmony_ci{ 319662306a36Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 319762306a36Sopenharmony_ci 319862306a36Sopenharmony_ci if (sdev->host->no_write_same) { 319962306a36Sopenharmony_ci sdev->no_write_same = 1; 320062306a36Sopenharmony_ci 320162306a36Sopenharmony_ci return; 320262306a36Sopenharmony_ci } 320362306a36Sopenharmony_ci 320462306a36Sopenharmony_ci if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY, 0) < 0) { 320562306a36Sopenharmony_ci struct scsi_vpd *vpd; 320662306a36Sopenharmony_ci 320762306a36Sopenharmony_ci sdev->no_report_opcodes = 1; 320862306a36Sopenharmony_ci 320962306a36Sopenharmony_ci /* Disable WRITE SAME if REPORT SUPPORTED OPERATION 321062306a36Sopenharmony_ci * CODES is unsupported and the device has an ATA 321162306a36Sopenharmony_ci * Information VPD page (SAT). 321262306a36Sopenharmony_ci */ 321362306a36Sopenharmony_ci rcu_read_lock(); 321462306a36Sopenharmony_ci vpd = rcu_dereference(sdev->vpd_pg89); 321562306a36Sopenharmony_ci if (vpd) 321662306a36Sopenharmony_ci sdev->no_write_same = 1; 321762306a36Sopenharmony_ci rcu_read_unlock(); 321862306a36Sopenharmony_ci } 321962306a36Sopenharmony_ci 322062306a36Sopenharmony_ci if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16, 0) == 1) 322162306a36Sopenharmony_ci sdkp->ws16 = 1; 322262306a36Sopenharmony_ci 322362306a36Sopenharmony_ci if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME, 0) == 1) 322462306a36Sopenharmony_ci sdkp->ws10 = 1; 322562306a36Sopenharmony_ci} 322662306a36Sopenharmony_ci 322762306a36Sopenharmony_cistatic void sd_read_security(struct scsi_disk *sdkp, unsigned char *buffer) 322862306a36Sopenharmony_ci{ 322962306a36Sopenharmony_ci struct scsi_device *sdev = sdkp->device; 323062306a36Sopenharmony_ci 323162306a36Sopenharmony_ci if (!sdev->security_supported) 323262306a36Sopenharmony_ci return; 323362306a36Sopenharmony_ci 323462306a36Sopenharmony_ci if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, 323562306a36Sopenharmony_ci SECURITY_PROTOCOL_IN, 0) == 1 && 323662306a36Sopenharmony_ci scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, 323762306a36Sopenharmony_ci SECURITY_PROTOCOL_OUT, 0) == 1) 323862306a36Sopenharmony_ci sdkp->security = 1; 323962306a36Sopenharmony_ci} 324062306a36Sopenharmony_ci 324162306a36Sopenharmony_cistatic inline sector_t sd64_to_sectors(struct scsi_disk *sdkp, u8 *buf) 324262306a36Sopenharmony_ci{ 324362306a36Sopenharmony_ci return logical_to_sectors(sdkp->device, get_unaligned_be64(buf)); 324462306a36Sopenharmony_ci} 324562306a36Sopenharmony_ci 324662306a36Sopenharmony_ci/** 324762306a36Sopenharmony_ci * sd_read_cpr - Query concurrent positioning ranges 324862306a36Sopenharmony_ci * @sdkp: disk to query 324962306a36Sopenharmony_ci */ 325062306a36Sopenharmony_cistatic void sd_read_cpr(struct scsi_disk *sdkp) 325162306a36Sopenharmony_ci{ 325262306a36Sopenharmony_ci struct blk_independent_access_ranges *iars = NULL; 325362306a36Sopenharmony_ci unsigned char *buffer = NULL; 325462306a36Sopenharmony_ci unsigned int nr_cpr = 0; 325562306a36Sopenharmony_ci int i, vpd_len, buf_len = SD_BUF_SIZE; 325662306a36Sopenharmony_ci u8 *desc; 325762306a36Sopenharmony_ci 325862306a36Sopenharmony_ci /* 325962306a36Sopenharmony_ci * We need to have the capacity set first for the block layer to be 326062306a36Sopenharmony_ci * able to check the ranges. 326162306a36Sopenharmony_ci */ 326262306a36Sopenharmony_ci if (sdkp->first_scan) 326362306a36Sopenharmony_ci return; 326462306a36Sopenharmony_ci 326562306a36Sopenharmony_ci if (!sdkp->capacity) 326662306a36Sopenharmony_ci goto out; 326762306a36Sopenharmony_ci 326862306a36Sopenharmony_ci /* 326962306a36Sopenharmony_ci * Concurrent Positioning Ranges VPD: there can be at most 256 ranges, 327062306a36Sopenharmony_ci * leading to a maximum page size of 64 + 256*32 bytes. 327162306a36Sopenharmony_ci */ 327262306a36Sopenharmony_ci buf_len = 64 + 256*32; 327362306a36Sopenharmony_ci buffer = kmalloc(buf_len, GFP_KERNEL); 327462306a36Sopenharmony_ci if (!buffer || scsi_get_vpd_page(sdkp->device, 0xb9, buffer, buf_len)) 327562306a36Sopenharmony_ci goto out; 327662306a36Sopenharmony_ci 327762306a36Sopenharmony_ci /* We must have at least a 64B header and one 32B range descriptor */ 327862306a36Sopenharmony_ci vpd_len = get_unaligned_be16(&buffer[2]) + 4; 327962306a36Sopenharmony_ci if (vpd_len > buf_len || vpd_len < 64 + 32 || (vpd_len & 31)) { 328062306a36Sopenharmony_ci sd_printk(KERN_ERR, sdkp, 328162306a36Sopenharmony_ci "Invalid Concurrent Positioning Ranges VPD page\n"); 328262306a36Sopenharmony_ci goto out; 328362306a36Sopenharmony_ci } 328462306a36Sopenharmony_ci 328562306a36Sopenharmony_ci nr_cpr = (vpd_len - 64) / 32; 328662306a36Sopenharmony_ci if (nr_cpr == 1) { 328762306a36Sopenharmony_ci nr_cpr = 0; 328862306a36Sopenharmony_ci goto out; 328962306a36Sopenharmony_ci } 329062306a36Sopenharmony_ci 329162306a36Sopenharmony_ci iars = disk_alloc_independent_access_ranges(sdkp->disk, nr_cpr); 329262306a36Sopenharmony_ci if (!iars) { 329362306a36Sopenharmony_ci nr_cpr = 0; 329462306a36Sopenharmony_ci goto out; 329562306a36Sopenharmony_ci } 329662306a36Sopenharmony_ci 329762306a36Sopenharmony_ci desc = &buffer[64]; 329862306a36Sopenharmony_ci for (i = 0; i < nr_cpr; i++, desc += 32) { 329962306a36Sopenharmony_ci if (desc[0] != i) { 330062306a36Sopenharmony_ci sd_printk(KERN_ERR, sdkp, 330162306a36Sopenharmony_ci "Invalid Concurrent Positioning Range number\n"); 330262306a36Sopenharmony_ci nr_cpr = 0; 330362306a36Sopenharmony_ci break; 330462306a36Sopenharmony_ci } 330562306a36Sopenharmony_ci 330662306a36Sopenharmony_ci iars->ia_range[i].sector = sd64_to_sectors(sdkp, desc + 8); 330762306a36Sopenharmony_ci iars->ia_range[i].nr_sectors = sd64_to_sectors(sdkp, desc + 16); 330862306a36Sopenharmony_ci } 330962306a36Sopenharmony_ci 331062306a36Sopenharmony_ciout: 331162306a36Sopenharmony_ci disk_set_independent_access_ranges(sdkp->disk, iars); 331262306a36Sopenharmony_ci if (nr_cpr && sdkp->nr_actuators != nr_cpr) { 331362306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 331462306a36Sopenharmony_ci "%u concurrent positioning ranges\n", nr_cpr); 331562306a36Sopenharmony_ci sdkp->nr_actuators = nr_cpr; 331662306a36Sopenharmony_ci } 331762306a36Sopenharmony_ci 331862306a36Sopenharmony_ci kfree(buffer); 331962306a36Sopenharmony_ci} 332062306a36Sopenharmony_ci 332162306a36Sopenharmony_cistatic bool sd_validate_min_xfer_size(struct scsi_disk *sdkp) 332262306a36Sopenharmony_ci{ 332362306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 332462306a36Sopenharmony_ci unsigned int min_xfer_bytes = 332562306a36Sopenharmony_ci logical_to_bytes(sdp, sdkp->min_xfer_blocks); 332662306a36Sopenharmony_ci 332762306a36Sopenharmony_ci if (sdkp->min_xfer_blocks == 0) 332862306a36Sopenharmony_ci return false; 332962306a36Sopenharmony_ci 333062306a36Sopenharmony_ci if (min_xfer_bytes & (sdkp->physical_block_size - 1)) { 333162306a36Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 333262306a36Sopenharmony_ci "Preferred minimum I/O size %u bytes not a " \ 333362306a36Sopenharmony_ci "multiple of physical block size (%u bytes)\n", 333462306a36Sopenharmony_ci min_xfer_bytes, sdkp->physical_block_size); 333562306a36Sopenharmony_ci sdkp->min_xfer_blocks = 0; 333662306a36Sopenharmony_ci return false; 333762306a36Sopenharmony_ci } 333862306a36Sopenharmony_ci 333962306a36Sopenharmony_ci sd_first_printk(KERN_INFO, sdkp, "Preferred minimum I/O size %u bytes\n", 334062306a36Sopenharmony_ci min_xfer_bytes); 334162306a36Sopenharmony_ci return true; 334262306a36Sopenharmony_ci} 334362306a36Sopenharmony_ci 334462306a36Sopenharmony_ci/* 334562306a36Sopenharmony_ci * Determine the device's preferred I/O size for reads and writes 334662306a36Sopenharmony_ci * unless the reported value is unreasonably small, large, not a 334762306a36Sopenharmony_ci * multiple of the physical block size, or simply garbage. 334862306a36Sopenharmony_ci */ 334962306a36Sopenharmony_cistatic bool sd_validate_opt_xfer_size(struct scsi_disk *sdkp, 335062306a36Sopenharmony_ci unsigned int dev_max) 335162306a36Sopenharmony_ci{ 335262306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 335362306a36Sopenharmony_ci unsigned int opt_xfer_bytes = 335462306a36Sopenharmony_ci logical_to_bytes(sdp, sdkp->opt_xfer_blocks); 335562306a36Sopenharmony_ci unsigned int min_xfer_bytes = 335662306a36Sopenharmony_ci logical_to_bytes(sdp, sdkp->min_xfer_blocks); 335762306a36Sopenharmony_ci 335862306a36Sopenharmony_ci if (sdkp->opt_xfer_blocks == 0) 335962306a36Sopenharmony_ci return false; 336062306a36Sopenharmony_ci 336162306a36Sopenharmony_ci if (sdkp->opt_xfer_blocks > dev_max) { 336262306a36Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 336362306a36Sopenharmony_ci "Optimal transfer size %u logical blocks " \ 336462306a36Sopenharmony_ci "> dev_max (%u logical blocks)\n", 336562306a36Sopenharmony_ci sdkp->opt_xfer_blocks, dev_max); 336662306a36Sopenharmony_ci return false; 336762306a36Sopenharmony_ci } 336862306a36Sopenharmony_ci 336962306a36Sopenharmony_ci if (sdkp->opt_xfer_blocks > SD_DEF_XFER_BLOCKS) { 337062306a36Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 337162306a36Sopenharmony_ci "Optimal transfer size %u logical blocks " \ 337262306a36Sopenharmony_ci "> sd driver limit (%u logical blocks)\n", 337362306a36Sopenharmony_ci sdkp->opt_xfer_blocks, SD_DEF_XFER_BLOCKS); 337462306a36Sopenharmony_ci return false; 337562306a36Sopenharmony_ci } 337662306a36Sopenharmony_ci 337762306a36Sopenharmony_ci if (opt_xfer_bytes < PAGE_SIZE) { 337862306a36Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 337962306a36Sopenharmony_ci "Optimal transfer size %u bytes < " \ 338062306a36Sopenharmony_ci "PAGE_SIZE (%u bytes)\n", 338162306a36Sopenharmony_ci opt_xfer_bytes, (unsigned int)PAGE_SIZE); 338262306a36Sopenharmony_ci return false; 338362306a36Sopenharmony_ci } 338462306a36Sopenharmony_ci 338562306a36Sopenharmony_ci if (min_xfer_bytes && opt_xfer_bytes % min_xfer_bytes) { 338662306a36Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 338762306a36Sopenharmony_ci "Optimal transfer size %u bytes not a " \ 338862306a36Sopenharmony_ci "multiple of preferred minimum block " \ 338962306a36Sopenharmony_ci "size (%u bytes)\n", 339062306a36Sopenharmony_ci opt_xfer_bytes, min_xfer_bytes); 339162306a36Sopenharmony_ci return false; 339262306a36Sopenharmony_ci } 339362306a36Sopenharmony_ci 339462306a36Sopenharmony_ci if (opt_xfer_bytes & (sdkp->physical_block_size - 1)) { 339562306a36Sopenharmony_ci sd_first_printk(KERN_WARNING, sdkp, 339662306a36Sopenharmony_ci "Optimal transfer size %u bytes not a " \ 339762306a36Sopenharmony_ci "multiple of physical block size (%u bytes)\n", 339862306a36Sopenharmony_ci opt_xfer_bytes, sdkp->physical_block_size); 339962306a36Sopenharmony_ci return false; 340062306a36Sopenharmony_ci } 340162306a36Sopenharmony_ci 340262306a36Sopenharmony_ci sd_first_printk(KERN_INFO, sdkp, "Optimal transfer size %u bytes\n", 340362306a36Sopenharmony_ci opt_xfer_bytes); 340462306a36Sopenharmony_ci return true; 340562306a36Sopenharmony_ci} 340662306a36Sopenharmony_ci 340762306a36Sopenharmony_cistatic void sd_read_block_zero(struct scsi_disk *sdkp) 340862306a36Sopenharmony_ci{ 340962306a36Sopenharmony_ci unsigned int buf_len = sdkp->device->sector_size; 341062306a36Sopenharmony_ci char *buffer, cmd[10] = { }; 341162306a36Sopenharmony_ci 341262306a36Sopenharmony_ci buffer = kmalloc(buf_len, GFP_KERNEL); 341362306a36Sopenharmony_ci if (!buffer) 341462306a36Sopenharmony_ci return; 341562306a36Sopenharmony_ci 341662306a36Sopenharmony_ci cmd[0] = READ_10; 341762306a36Sopenharmony_ci put_unaligned_be32(0, &cmd[2]); /* Logical block address 0 */ 341862306a36Sopenharmony_ci put_unaligned_be16(1, &cmd[7]); /* Transfer 1 logical block */ 341962306a36Sopenharmony_ci 342062306a36Sopenharmony_ci scsi_execute_cmd(sdkp->device, cmd, REQ_OP_DRV_IN, buffer, buf_len, 342162306a36Sopenharmony_ci SD_TIMEOUT, sdkp->max_retries, NULL); 342262306a36Sopenharmony_ci kfree(buffer); 342362306a36Sopenharmony_ci} 342462306a36Sopenharmony_ci 342562306a36Sopenharmony_ci/** 342662306a36Sopenharmony_ci * sd_revalidate_disk - called the first time a new disk is seen, 342762306a36Sopenharmony_ci * performs disk spin up, read_capacity, etc. 342862306a36Sopenharmony_ci * @disk: struct gendisk we care about 342962306a36Sopenharmony_ci **/ 343062306a36Sopenharmony_cistatic int sd_revalidate_disk(struct gendisk *disk) 343162306a36Sopenharmony_ci{ 343262306a36Sopenharmony_ci struct scsi_disk *sdkp = scsi_disk(disk); 343362306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 343462306a36Sopenharmony_ci struct request_queue *q = sdkp->disk->queue; 343562306a36Sopenharmony_ci sector_t old_capacity = sdkp->capacity; 343662306a36Sopenharmony_ci unsigned char *buffer; 343762306a36Sopenharmony_ci unsigned int dev_max, rw_max; 343862306a36Sopenharmony_ci 343962306a36Sopenharmony_ci SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, 344062306a36Sopenharmony_ci "sd_revalidate_disk\n")); 344162306a36Sopenharmony_ci 344262306a36Sopenharmony_ci /* 344362306a36Sopenharmony_ci * If the device is offline, don't try and read capacity or any 344462306a36Sopenharmony_ci * of the other niceties. 344562306a36Sopenharmony_ci */ 344662306a36Sopenharmony_ci if (!scsi_device_online(sdp)) 344762306a36Sopenharmony_ci goto out; 344862306a36Sopenharmony_ci 344962306a36Sopenharmony_ci buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL); 345062306a36Sopenharmony_ci if (!buffer) { 345162306a36Sopenharmony_ci sd_printk(KERN_WARNING, sdkp, "sd_revalidate_disk: Memory " 345262306a36Sopenharmony_ci "allocation failure.\n"); 345362306a36Sopenharmony_ci goto out; 345462306a36Sopenharmony_ci } 345562306a36Sopenharmony_ci 345662306a36Sopenharmony_ci sd_spinup_disk(sdkp); 345762306a36Sopenharmony_ci 345862306a36Sopenharmony_ci /* 345962306a36Sopenharmony_ci * Without media there is no reason to ask; moreover, some devices 346062306a36Sopenharmony_ci * react badly if we do. 346162306a36Sopenharmony_ci */ 346262306a36Sopenharmony_ci if (sdkp->media_present) { 346362306a36Sopenharmony_ci sd_read_capacity(sdkp, buffer); 346462306a36Sopenharmony_ci /* 346562306a36Sopenharmony_ci * Some USB/UAS devices return generic values for mode pages 346662306a36Sopenharmony_ci * until the media has been accessed. Trigger a READ operation 346762306a36Sopenharmony_ci * to force the device to populate mode pages. 346862306a36Sopenharmony_ci */ 346962306a36Sopenharmony_ci if (sdp->read_before_ms) 347062306a36Sopenharmony_ci sd_read_block_zero(sdkp); 347162306a36Sopenharmony_ci /* 347262306a36Sopenharmony_ci * set the default to rotational. All non-rotational devices 347362306a36Sopenharmony_ci * support the block characteristics VPD page, which will 347462306a36Sopenharmony_ci * cause this to be updated correctly and any device which 347562306a36Sopenharmony_ci * doesn't support it should be treated as rotational. 347662306a36Sopenharmony_ci */ 347762306a36Sopenharmony_ci blk_queue_flag_clear(QUEUE_FLAG_NONROT, q); 347862306a36Sopenharmony_ci blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q); 347962306a36Sopenharmony_ci 348062306a36Sopenharmony_ci if (scsi_device_supports_vpd(sdp)) { 348162306a36Sopenharmony_ci sd_read_block_provisioning(sdkp); 348262306a36Sopenharmony_ci sd_read_block_limits(sdkp); 348362306a36Sopenharmony_ci sd_read_block_characteristics(sdkp); 348462306a36Sopenharmony_ci sd_zbc_read_zones(sdkp, buffer); 348562306a36Sopenharmony_ci sd_read_cpr(sdkp); 348662306a36Sopenharmony_ci } 348762306a36Sopenharmony_ci 348862306a36Sopenharmony_ci sd_print_capacity(sdkp, old_capacity); 348962306a36Sopenharmony_ci 349062306a36Sopenharmony_ci sd_read_write_protect_flag(sdkp, buffer); 349162306a36Sopenharmony_ci sd_read_cache_type(sdkp, buffer); 349262306a36Sopenharmony_ci sd_read_app_tag_own(sdkp, buffer); 349362306a36Sopenharmony_ci sd_read_write_same(sdkp, buffer); 349462306a36Sopenharmony_ci sd_read_security(sdkp, buffer); 349562306a36Sopenharmony_ci sd_config_protection(sdkp); 349662306a36Sopenharmony_ci } 349762306a36Sopenharmony_ci 349862306a36Sopenharmony_ci /* 349962306a36Sopenharmony_ci * We now have all cache related info, determine how we deal 350062306a36Sopenharmony_ci * with flush requests. 350162306a36Sopenharmony_ci */ 350262306a36Sopenharmony_ci sd_set_flush_flag(sdkp); 350362306a36Sopenharmony_ci 350462306a36Sopenharmony_ci /* Initial block count limit based on CDB TRANSFER LENGTH field size. */ 350562306a36Sopenharmony_ci dev_max = sdp->use_16_for_rw ? SD_MAX_XFER_BLOCKS : SD_DEF_XFER_BLOCKS; 350662306a36Sopenharmony_ci 350762306a36Sopenharmony_ci /* Some devices report a maximum block count for READ/WRITE requests. */ 350862306a36Sopenharmony_ci dev_max = min_not_zero(dev_max, sdkp->max_xfer_blocks); 350962306a36Sopenharmony_ci q->limits.max_dev_sectors = logical_to_sectors(sdp, dev_max); 351062306a36Sopenharmony_ci 351162306a36Sopenharmony_ci if (sd_validate_min_xfer_size(sdkp)) 351262306a36Sopenharmony_ci blk_queue_io_min(sdkp->disk->queue, 351362306a36Sopenharmony_ci logical_to_bytes(sdp, sdkp->min_xfer_blocks)); 351462306a36Sopenharmony_ci else 351562306a36Sopenharmony_ci blk_queue_io_min(sdkp->disk->queue, 0); 351662306a36Sopenharmony_ci 351762306a36Sopenharmony_ci if (sd_validate_opt_xfer_size(sdkp, dev_max)) { 351862306a36Sopenharmony_ci q->limits.io_opt = logical_to_bytes(sdp, sdkp->opt_xfer_blocks); 351962306a36Sopenharmony_ci rw_max = logical_to_sectors(sdp, sdkp->opt_xfer_blocks); 352062306a36Sopenharmony_ci } else { 352162306a36Sopenharmony_ci q->limits.io_opt = 0; 352262306a36Sopenharmony_ci rw_max = min_not_zero(logical_to_sectors(sdp, dev_max), 352362306a36Sopenharmony_ci (sector_t)BLK_DEF_MAX_SECTORS); 352462306a36Sopenharmony_ci } 352562306a36Sopenharmony_ci 352662306a36Sopenharmony_ci /* 352762306a36Sopenharmony_ci * Limit default to SCSI host optimal sector limit if set. There may be 352862306a36Sopenharmony_ci * an impact on performance for when the size of a request exceeds this 352962306a36Sopenharmony_ci * host limit. 353062306a36Sopenharmony_ci */ 353162306a36Sopenharmony_ci rw_max = min_not_zero(rw_max, sdp->host->opt_sectors); 353262306a36Sopenharmony_ci 353362306a36Sopenharmony_ci /* Do not exceed controller limit */ 353462306a36Sopenharmony_ci rw_max = min(rw_max, queue_max_hw_sectors(q)); 353562306a36Sopenharmony_ci 353662306a36Sopenharmony_ci /* 353762306a36Sopenharmony_ci * Only update max_sectors if previously unset or if the current value 353862306a36Sopenharmony_ci * exceeds the capabilities of the hardware. 353962306a36Sopenharmony_ci */ 354062306a36Sopenharmony_ci if (sdkp->first_scan || 354162306a36Sopenharmony_ci q->limits.max_sectors > q->limits.max_dev_sectors || 354262306a36Sopenharmony_ci q->limits.max_sectors > q->limits.max_hw_sectors) 354362306a36Sopenharmony_ci q->limits.max_sectors = rw_max; 354462306a36Sopenharmony_ci 354562306a36Sopenharmony_ci sdkp->first_scan = 0; 354662306a36Sopenharmony_ci 354762306a36Sopenharmony_ci set_capacity_and_notify(disk, logical_to_sectors(sdp, sdkp->capacity)); 354862306a36Sopenharmony_ci sd_config_write_same(sdkp); 354962306a36Sopenharmony_ci kfree(buffer); 355062306a36Sopenharmony_ci 355162306a36Sopenharmony_ci /* 355262306a36Sopenharmony_ci * For a zoned drive, revalidating the zones can be done only once 355362306a36Sopenharmony_ci * the gendisk capacity is set. So if this fails, set back the gendisk 355462306a36Sopenharmony_ci * capacity to 0. 355562306a36Sopenharmony_ci */ 355662306a36Sopenharmony_ci if (sd_zbc_revalidate_zones(sdkp)) 355762306a36Sopenharmony_ci set_capacity_and_notify(disk, 0); 355862306a36Sopenharmony_ci 355962306a36Sopenharmony_ci out: 356062306a36Sopenharmony_ci return 0; 356162306a36Sopenharmony_ci} 356262306a36Sopenharmony_ci 356362306a36Sopenharmony_ci/** 356462306a36Sopenharmony_ci * sd_unlock_native_capacity - unlock native capacity 356562306a36Sopenharmony_ci * @disk: struct gendisk to set capacity for 356662306a36Sopenharmony_ci * 356762306a36Sopenharmony_ci * Block layer calls this function if it detects that partitions 356862306a36Sopenharmony_ci * on @disk reach beyond the end of the device. If the SCSI host 356962306a36Sopenharmony_ci * implements ->unlock_native_capacity() method, it's invoked to 357062306a36Sopenharmony_ci * give it a chance to adjust the device capacity. 357162306a36Sopenharmony_ci * 357262306a36Sopenharmony_ci * CONTEXT: 357362306a36Sopenharmony_ci * Defined by block layer. Might sleep. 357462306a36Sopenharmony_ci */ 357562306a36Sopenharmony_cistatic void sd_unlock_native_capacity(struct gendisk *disk) 357662306a36Sopenharmony_ci{ 357762306a36Sopenharmony_ci struct scsi_device *sdev = scsi_disk(disk)->device; 357862306a36Sopenharmony_ci 357962306a36Sopenharmony_ci if (sdev->host->hostt->unlock_native_capacity) 358062306a36Sopenharmony_ci sdev->host->hostt->unlock_native_capacity(sdev); 358162306a36Sopenharmony_ci} 358262306a36Sopenharmony_ci 358362306a36Sopenharmony_ci/** 358462306a36Sopenharmony_ci * sd_format_disk_name - format disk name 358562306a36Sopenharmony_ci * @prefix: name prefix - ie. "sd" for SCSI disks 358662306a36Sopenharmony_ci * @index: index of the disk to format name for 358762306a36Sopenharmony_ci * @buf: output buffer 358862306a36Sopenharmony_ci * @buflen: length of the output buffer 358962306a36Sopenharmony_ci * 359062306a36Sopenharmony_ci * SCSI disk names starts at sda. The 26th device is sdz and the 359162306a36Sopenharmony_ci * 27th is sdaa. The last one for two lettered suffix is sdzz 359262306a36Sopenharmony_ci * which is followed by sdaaa. 359362306a36Sopenharmony_ci * 359462306a36Sopenharmony_ci * This is basically 26 base counting with one extra 'nil' entry 359562306a36Sopenharmony_ci * at the beginning from the second digit on and can be 359662306a36Sopenharmony_ci * determined using similar method as 26 base conversion with the 359762306a36Sopenharmony_ci * index shifted -1 after each digit is computed. 359862306a36Sopenharmony_ci * 359962306a36Sopenharmony_ci * CONTEXT: 360062306a36Sopenharmony_ci * Don't care. 360162306a36Sopenharmony_ci * 360262306a36Sopenharmony_ci * RETURNS: 360362306a36Sopenharmony_ci * 0 on success, -errno on failure. 360462306a36Sopenharmony_ci */ 360562306a36Sopenharmony_cistatic int sd_format_disk_name(char *prefix, int index, char *buf, int buflen) 360662306a36Sopenharmony_ci{ 360762306a36Sopenharmony_ci const int base = 'z' - 'a' + 1; 360862306a36Sopenharmony_ci char *begin = buf + strlen(prefix); 360962306a36Sopenharmony_ci char *end = buf + buflen; 361062306a36Sopenharmony_ci char *p; 361162306a36Sopenharmony_ci int unit; 361262306a36Sopenharmony_ci 361362306a36Sopenharmony_ci p = end - 1; 361462306a36Sopenharmony_ci *p = '\0'; 361562306a36Sopenharmony_ci unit = base; 361662306a36Sopenharmony_ci do { 361762306a36Sopenharmony_ci if (p == begin) 361862306a36Sopenharmony_ci return -EINVAL; 361962306a36Sopenharmony_ci *--p = 'a' + (index % unit); 362062306a36Sopenharmony_ci index = (index / unit) - 1; 362162306a36Sopenharmony_ci } while (index >= 0); 362262306a36Sopenharmony_ci 362362306a36Sopenharmony_ci memmove(begin, p, end - p); 362462306a36Sopenharmony_ci memcpy(buf, prefix, strlen(prefix)); 362562306a36Sopenharmony_ci 362662306a36Sopenharmony_ci return 0; 362762306a36Sopenharmony_ci} 362862306a36Sopenharmony_ci 362962306a36Sopenharmony_ci/** 363062306a36Sopenharmony_ci * sd_probe - called during driver initialization and whenever a 363162306a36Sopenharmony_ci * new scsi device is attached to the system. It is called once 363262306a36Sopenharmony_ci * for each scsi device (not just disks) present. 363362306a36Sopenharmony_ci * @dev: pointer to device object 363462306a36Sopenharmony_ci * 363562306a36Sopenharmony_ci * Returns 0 if successful (or not interested in this scsi device 363662306a36Sopenharmony_ci * (e.g. scanner)); 1 when there is an error. 363762306a36Sopenharmony_ci * 363862306a36Sopenharmony_ci * Note: this function is invoked from the scsi mid-level. 363962306a36Sopenharmony_ci * This function sets up the mapping between a given 364062306a36Sopenharmony_ci * <host,channel,id,lun> (found in sdp) and new device name 364162306a36Sopenharmony_ci * (e.g. /dev/sda). More precisely it is the block device major 364262306a36Sopenharmony_ci * and minor number that is chosen here. 364362306a36Sopenharmony_ci * 364462306a36Sopenharmony_ci * Assume sd_probe is not re-entrant (for time being) 364562306a36Sopenharmony_ci * Also think about sd_probe() and sd_remove() running coincidentally. 364662306a36Sopenharmony_ci **/ 364762306a36Sopenharmony_cistatic int sd_probe(struct device *dev) 364862306a36Sopenharmony_ci{ 364962306a36Sopenharmony_ci struct scsi_device *sdp = to_scsi_device(dev); 365062306a36Sopenharmony_ci struct scsi_disk *sdkp; 365162306a36Sopenharmony_ci struct gendisk *gd; 365262306a36Sopenharmony_ci int index; 365362306a36Sopenharmony_ci int error; 365462306a36Sopenharmony_ci 365562306a36Sopenharmony_ci scsi_autopm_get_device(sdp); 365662306a36Sopenharmony_ci error = -ENODEV; 365762306a36Sopenharmony_ci if (sdp->type != TYPE_DISK && 365862306a36Sopenharmony_ci sdp->type != TYPE_ZBC && 365962306a36Sopenharmony_ci sdp->type != TYPE_MOD && 366062306a36Sopenharmony_ci sdp->type != TYPE_RBC) 366162306a36Sopenharmony_ci goto out; 366262306a36Sopenharmony_ci 366362306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_BLK_DEV_ZONED) && sdp->type == TYPE_ZBC) { 366462306a36Sopenharmony_ci sdev_printk(KERN_WARNING, sdp, 366562306a36Sopenharmony_ci "Unsupported ZBC host-managed device.\n"); 366662306a36Sopenharmony_ci goto out; 366762306a36Sopenharmony_ci } 366862306a36Sopenharmony_ci 366962306a36Sopenharmony_ci SCSI_LOG_HLQUEUE(3, sdev_printk(KERN_INFO, sdp, 367062306a36Sopenharmony_ci "sd_probe\n")); 367162306a36Sopenharmony_ci 367262306a36Sopenharmony_ci error = -ENOMEM; 367362306a36Sopenharmony_ci sdkp = kzalloc(sizeof(*sdkp), GFP_KERNEL); 367462306a36Sopenharmony_ci if (!sdkp) 367562306a36Sopenharmony_ci goto out; 367662306a36Sopenharmony_ci 367762306a36Sopenharmony_ci gd = blk_mq_alloc_disk_for_queue(sdp->request_queue, 367862306a36Sopenharmony_ci &sd_bio_compl_lkclass); 367962306a36Sopenharmony_ci if (!gd) 368062306a36Sopenharmony_ci goto out_free; 368162306a36Sopenharmony_ci 368262306a36Sopenharmony_ci index = ida_alloc(&sd_index_ida, GFP_KERNEL); 368362306a36Sopenharmony_ci if (index < 0) { 368462306a36Sopenharmony_ci sdev_printk(KERN_WARNING, sdp, "sd_probe: memory exhausted.\n"); 368562306a36Sopenharmony_ci goto out_put; 368662306a36Sopenharmony_ci } 368762306a36Sopenharmony_ci 368862306a36Sopenharmony_ci error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN); 368962306a36Sopenharmony_ci if (error) { 369062306a36Sopenharmony_ci sdev_printk(KERN_WARNING, sdp, "SCSI disk (sd) name length exceeded.\n"); 369162306a36Sopenharmony_ci goto out_free_index; 369262306a36Sopenharmony_ci } 369362306a36Sopenharmony_ci 369462306a36Sopenharmony_ci sdkp->device = sdp; 369562306a36Sopenharmony_ci sdkp->disk = gd; 369662306a36Sopenharmony_ci sdkp->index = index; 369762306a36Sopenharmony_ci sdkp->max_retries = SD_MAX_RETRIES; 369862306a36Sopenharmony_ci atomic_set(&sdkp->openers, 0); 369962306a36Sopenharmony_ci atomic_set(&sdkp->device->ioerr_cnt, 0); 370062306a36Sopenharmony_ci 370162306a36Sopenharmony_ci if (!sdp->request_queue->rq_timeout) { 370262306a36Sopenharmony_ci if (sdp->type != TYPE_MOD) 370362306a36Sopenharmony_ci blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT); 370462306a36Sopenharmony_ci else 370562306a36Sopenharmony_ci blk_queue_rq_timeout(sdp->request_queue, 370662306a36Sopenharmony_ci SD_MOD_TIMEOUT); 370762306a36Sopenharmony_ci } 370862306a36Sopenharmony_ci 370962306a36Sopenharmony_ci device_initialize(&sdkp->disk_dev); 371062306a36Sopenharmony_ci sdkp->disk_dev.parent = get_device(dev); 371162306a36Sopenharmony_ci sdkp->disk_dev.class = &sd_disk_class; 371262306a36Sopenharmony_ci dev_set_name(&sdkp->disk_dev, "%s", dev_name(dev)); 371362306a36Sopenharmony_ci 371462306a36Sopenharmony_ci error = device_add(&sdkp->disk_dev); 371562306a36Sopenharmony_ci if (error) { 371662306a36Sopenharmony_ci put_device(&sdkp->disk_dev); 371762306a36Sopenharmony_ci goto out; 371862306a36Sopenharmony_ci } 371962306a36Sopenharmony_ci 372062306a36Sopenharmony_ci dev_set_drvdata(dev, sdkp); 372162306a36Sopenharmony_ci 372262306a36Sopenharmony_ci gd->major = sd_major((index & 0xf0) >> 4); 372362306a36Sopenharmony_ci gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); 372462306a36Sopenharmony_ci gd->minors = SD_MINORS; 372562306a36Sopenharmony_ci 372662306a36Sopenharmony_ci gd->fops = &sd_fops; 372762306a36Sopenharmony_ci gd->private_data = sdkp; 372862306a36Sopenharmony_ci 372962306a36Sopenharmony_ci /* defaults, until the device tells us otherwise */ 373062306a36Sopenharmony_ci sdp->sector_size = 512; 373162306a36Sopenharmony_ci sdkp->capacity = 0; 373262306a36Sopenharmony_ci sdkp->media_present = 1; 373362306a36Sopenharmony_ci sdkp->write_prot = 0; 373462306a36Sopenharmony_ci sdkp->cache_override = 0; 373562306a36Sopenharmony_ci sdkp->WCE = 0; 373662306a36Sopenharmony_ci sdkp->RCD = 0; 373762306a36Sopenharmony_ci sdkp->ATO = 0; 373862306a36Sopenharmony_ci sdkp->first_scan = 1; 373962306a36Sopenharmony_ci sdkp->max_medium_access_timeouts = SD_MAX_MEDIUM_TIMEOUTS; 374062306a36Sopenharmony_ci 374162306a36Sopenharmony_ci sd_revalidate_disk(gd); 374262306a36Sopenharmony_ci 374362306a36Sopenharmony_ci if (sdp->removable) { 374462306a36Sopenharmony_ci gd->flags |= GENHD_FL_REMOVABLE; 374562306a36Sopenharmony_ci gd->events |= DISK_EVENT_MEDIA_CHANGE; 374662306a36Sopenharmony_ci gd->event_flags = DISK_EVENT_FLAG_POLL | DISK_EVENT_FLAG_UEVENT; 374762306a36Sopenharmony_ci } 374862306a36Sopenharmony_ci 374962306a36Sopenharmony_ci blk_pm_runtime_init(sdp->request_queue, dev); 375062306a36Sopenharmony_ci if (sdp->rpm_autosuspend) { 375162306a36Sopenharmony_ci pm_runtime_set_autosuspend_delay(dev, 375262306a36Sopenharmony_ci sdp->host->hostt->rpm_autosuspend_delay); 375362306a36Sopenharmony_ci } 375462306a36Sopenharmony_ci 375562306a36Sopenharmony_ci error = device_add_disk(dev, gd, NULL); 375662306a36Sopenharmony_ci if (error) { 375762306a36Sopenharmony_ci put_device(&sdkp->disk_dev); 375862306a36Sopenharmony_ci put_disk(gd); 375962306a36Sopenharmony_ci goto out; 376062306a36Sopenharmony_ci } 376162306a36Sopenharmony_ci 376262306a36Sopenharmony_ci if (sdkp->security) { 376362306a36Sopenharmony_ci sdkp->opal_dev = init_opal_dev(sdkp, &sd_sec_submit); 376462306a36Sopenharmony_ci if (sdkp->opal_dev) 376562306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "supports TCG Opal\n"); 376662306a36Sopenharmony_ci } 376762306a36Sopenharmony_ci 376862306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", 376962306a36Sopenharmony_ci sdp->removable ? "removable " : ""); 377062306a36Sopenharmony_ci scsi_autopm_put_device(sdp); 377162306a36Sopenharmony_ci 377262306a36Sopenharmony_ci return 0; 377362306a36Sopenharmony_ci 377462306a36Sopenharmony_ci out_free_index: 377562306a36Sopenharmony_ci ida_free(&sd_index_ida, index); 377662306a36Sopenharmony_ci out_put: 377762306a36Sopenharmony_ci put_disk(gd); 377862306a36Sopenharmony_ci out_free: 377962306a36Sopenharmony_ci kfree(sdkp); 378062306a36Sopenharmony_ci out: 378162306a36Sopenharmony_ci scsi_autopm_put_device(sdp); 378262306a36Sopenharmony_ci return error; 378362306a36Sopenharmony_ci} 378462306a36Sopenharmony_ci 378562306a36Sopenharmony_ci/** 378662306a36Sopenharmony_ci * sd_remove - called whenever a scsi disk (previously recognized by 378762306a36Sopenharmony_ci * sd_probe) is detached from the system. It is called (potentially 378862306a36Sopenharmony_ci * multiple times) during sd module unload. 378962306a36Sopenharmony_ci * @dev: pointer to device object 379062306a36Sopenharmony_ci * 379162306a36Sopenharmony_ci * Note: this function is invoked from the scsi mid-level. 379262306a36Sopenharmony_ci * This function potentially frees up a device name (e.g. /dev/sdc) 379362306a36Sopenharmony_ci * that could be re-used by a subsequent sd_probe(). 379462306a36Sopenharmony_ci * This function is not called when the built-in sd driver is "exit-ed". 379562306a36Sopenharmony_ci **/ 379662306a36Sopenharmony_cistatic int sd_remove(struct device *dev) 379762306a36Sopenharmony_ci{ 379862306a36Sopenharmony_ci struct scsi_disk *sdkp = dev_get_drvdata(dev); 379962306a36Sopenharmony_ci 380062306a36Sopenharmony_ci scsi_autopm_get_device(sdkp->device); 380162306a36Sopenharmony_ci 380262306a36Sopenharmony_ci device_del(&sdkp->disk_dev); 380362306a36Sopenharmony_ci del_gendisk(sdkp->disk); 380462306a36Sopenharmony_ci if (!sdkp->suspended) 380562306a36Sopenharmony_ci sd_shutdown(dev); 380662306a36Sopenharmony_ci 380762306a36Sopenharmony_ci put_disk(sdkp->disk); 380862306a36Sopenharmony_ci return 0; 380962306a36Sopenharmony_ci} 381062306a36Sopenharmony_ci 381162306a36Sopenharmony_cistatic void scsi_disk_release(struct device *dev) 381262306a36Sopenharmony_ci{ 381362306a36Sopenharmony_ci struct scsi_disk *sdkp = to_scsi_disk(dev); 381462306a36Sopenharmony_ci 381562306a36Sopenharmony_ci ida_free(&sd_index_ida, sdkp->index); 381662306a36Sopenharmony_ci sd_zbc_free_zone_info(sdkp); 381762306a36Sopenharmony_ci put_device(&sdkp->device->sdev_gendev); 381862306a36Sopenharmony_ci free_opal_dev(sdkp->opal_dev); 381962306a36Sopenharmony_ci 382062306a36Sopenharmony_ci kfree(sdkp); 382162306a36Sopenharmony_ci} 382262306a36Sopenharmony_ci 382362306a36Sopenharmony_cistatic int sd_start_stop_device(struct scsi_disk *sdkp, int start) 382462306a36Sopenharmony_ci{ 382562306a36Sopenharmony_ci unsigned char cmd[6] = { START_STOP }; /* START_VALID */ 382662306a36Sopenharmony_ci struct scsi_sense_hdr sshdr; 382762306a36Sopenharmony_ci const struct scsi_exec_args exec_args = { 382862306a36Sopenharmony_ci .sshdr = &sshdr, 382962306a36Sopenharmony_ci .req_flags = BLK_MQ_REQ_PM, 383062306a36Sopenharmony_ci }; 383162306a36Sopenharmony_ci struct scsi_device *sdp = sdkp->device; 383262306a36Sopenharmony_ci int res; 383362306a36Sopenharmony_ci 383462306a36Sopenharmony_ci if (start) 383562306a36Sopenharmony_ci cmd[4] |= 1; /* START */ 383662306a36Sopenharmony_ci 383762306a36Sopenharmony_ci if (sdp->start_stop_pwr_cond) 383862306a36Sopenharmony_ci cmd[4] |= start ? 1 << 4 : 3 << 4; /* Active or Standby */ 383962306a36Sopenharmony_ci 384062306a36Sopenharmony_ci if (!scsi_device_online(sdp)) 384162306a36Sopenharmony_ci return -ENODEV; 384262306a36Sopenharmony_ci 384362306a36Sopenharmony_ci res = scsi_execute_cmd(sdp, cmd, REQ_OP_DRV_IN, NULL, 0, SD_TIMEOUT, 384462306a36Sopenharmony_ci sdkp->max_retries, &exec_args); 384562306a36Sopenharmony_ci if (res) { 384662306a36Sopenharmony_ci sd_print_result(sdkp, "Start/Stop Unit failed", res); 384762306a36Sopenharmony_ci if (res > 0 && scsi_sense_valid(&sshdr)) { 384862306a36Sopenharmony_ci sd_print_sense_hdr(sdkp, &sshdr); 384962306a36Sopenharmony_ci /* 0x3a is medium not present */ 385062306a36Sopenharmony_ci if (sshdr.asc == 0x3a) 385162306a36Sopenharmony_ci res = 0; 385262306a36Sopenharmony_ci } 385362306a36Sopenharmony_ci } 385462306a36Sopenharmony_ci 385562306a36Sopenharmony_ci /* SCSI error codes must not go to the generic layer */ 385662306a36Sopenharmony_ci if (res) 385762306a36Sopenharmony_ci return -EIO; 385862306a36Sopenharmony_ci 385962306a36Sopenharmony_ci return 0; 386062306a36Sopenharmony_ci} 386162306a36Sopenharmony_ci 386262306a36Sopenharmony_ci/* 386362306a36Sopenharmony_ci * Send a SYNCHRONIZE CACHE instruction down to the device through 386462306a36Sopenharmony_ci * the normal SCSI command structure. Wait for the command to 386562306a36Sopenharmony_ci * complete. 386662306a36Sopenharmony_ci */ 386762306a36Sopenharmony_cistatic void sd_shutdown(struct device *dev) 386862306a36Sopenharmony_ci{ 386962306a36Sopenharmony_ci struct scsi_disk *sdkp = dev_get_drvdata(dev); 387062306a36Sopenharmony_ci 387162306a36Sopenharmony_ci if (!sdkp) 387262306a36Sopenharmony_ci return; /* this can happen */ 387362306a36Sopenharmony_ci 387462306a36Sopenharmony_ci if (pm_runtime_suspended(dev)) 387562306a36Sopenharmony_ci return; 387662306a36Sopenharmony_ci 387762306a36Sopenharmony_ci if (sdkp->WCE && sdkp->media_present) { 387862306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); 387962306a36Sopenharmony_ci sd_sync_cache(sdkp); 388062306a36Sopenharmony_ci } 388162306a36Sopenharmony_ci 388262306a36Sopenharmony_ci if ((system_state != SYSTEM_RESTART && 388362306a36Sopenharmony_ci sdkp->device->manage_system_start_stop) || 388462306a36Sopenharmony_ci (system_state == SYSTEM_POWER_OFF && 388562306a36Sopenharmony_ci sdkp->device->manage_shutdown)) { 388662306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); 388762306a36Sopenharmony_ci sd_start_stop_device(sdkp, 0); 388862306a36Sopenharmony_ci } 388962306a36Sopenharmony_ci} 389062306a36Sopenharmony_ci 389162306a36Sopenharmony_cistatic inline bool sd_do_start_stop(struct scsi_device *sdev, bool runtime) 389262306a36Sopenharmony_ci{ 389362306a36Sopenharmony_ci return (sdev->manage_system_start_stop && !runtime) || 389462306a36Sopenharmony_ci (sdev->manage_runtime_start_stop && runtime); 389562306a36Sopenharmony_ci} 389662306a36Sopenharmony_ci 389762306a36Sopenharmony_cistatic int sd_suspend_common(struct device *dev, bool runtime) 389862306a36Sopenharmony_ci{ 389962306a36Sopenharmony_ci struct scsi_disk *sdkp = dev_get_drvdata(dev); 390062306a36Sopenharmony_ci int ret = 0; 390162306a36Sopenharmony_ci 390262306a36Sopenharmony_ci if (!sdkp) /* E.g.: runtime suspend following sd_remove() */ 390362306a36Sopenharmony_ci return 0; 390462306a36Sopenharmony_ci 390562306a36Sopenharmony_ci if (sdkp->WCE && sdkp->media_present) { 390662306a36Sopenharmony_ci if (!sdkp->device->silence_suspend) 390762306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); 390862306a36Sopenharmony_ci ret = sd_sync_cache(sdkp); 390962306a36Sopenharmony_ci /* ignore OFFLINE device */ 391062306a36Sopenharmony_ci if (ret == -ENODEV) 391162306a36Sopenharmony_ci return 0; 391262306a36Sopenharmony_ci 391362306a36Sopenharmony_ci if (ret) 391462306a36Sopenharmony_ci return ret; 391562306a36Sopenharmony_ci } 391662306a36Sopenharmony_ci 391762306a36Sopenharmony_ci if (sd_do_start_stop(sdkp->device, runtime)) { 391862306a36Sopenharmony_ci if (!sdkp->device->silence_suspend) 391962306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); 392062306a36Sopenharmony_ci /* an error is not worth aborting a system sleep */ 392162306a36Sopenharmony_ci ret = sd_start_stop_device(sdkp, 0); 392262306a36Sopenharmony_ci if (!runtime) 392362306a36Sopenharmony_ci ret = 0; 392462306a36Sopenharmony_ci } 392562306a36Sopenharmony_ci 392662306a36Sopenharmony_ci if (!ret) 392762306a36Sopenharmony_ci sdkp->suspended = true; 392862306a36Sopenharmony_ci 392962306a36Sopenharmony_ci return ret; 393062306a36Sopenharmony_ci} 393162306a36Sopenharmony_ci 393262306a36Sopenharmony_cistatic int sd_suspend_system(struct device *dev) 393362306a36Sopenharmony_ci{ 393462306a36Sopenharmony_ci if (pm_runtime_suspended(dev)) 393562306a36Sopenharmony_ci return 0; 393662306a36Sopenharmony_ci 393762306a36Sopenharmony_ci return sd_suspend_common(dev, false); 393862306a36Sopenharmony_ci} 393962306a36Sopenharmony_ci 394062306a36Sopenharmony_cistatic int sd_suspend_runtime(struct device *dev) 394162306a36Sopenharmony_ci{ 394262306a36Sopenharmony_ci return sd_suspend_common(dev, true); 394362306a36Sopenharmony_ci} 394462306a36Sopenharmony_ci 394562306a36Sopenharmony_cistatic int sd_resume(struct device *dev, bool runtime) 394662306a36Sopenharmony_ci{ 394762306a36Sopenharmony_ci struct scsi_disk *sdkp = dev_get_drvdata(dev); 394862306a36Sopenharmony_ci int ret = 0; 394962306a36Sopenharmony_ci 395062306a36Sopenharmony_ci if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ 395162306a36Sopenharmony_ci return 0; 395262306a36Sopenharmony_ci 395362306a36Sopenharmony_ci if (!sd_do_start_stop(sdkp->device, runtime)) { 395462306a36Sopenharmony_ci sdkp->suspended = false; 395562306a36Sopenharmony_ci return 0; 395662306a36Sopenharmony_ci } 395762306a36Sopenharmony_ci 395862306a36Sopenharmony_ci if (!sdkp->device->no_start_on_resume) { 395962306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); 396062306a36Sopenharmony_ci ret = sd_start_stop_device(sdkp, 1); 396162306a36Sopenharmony_ci } 396262306a36Sopenharmony_ci 396362306a36Sopenharmony_ci if (!ret) { 396462306a36Sopenharmony_ci opal_unlock_from_suspend(sdkp->opal_dev); 396562306a36Sopenharmony_ci sdkp->suspended = false; 396662306a36Sopenharmony_ci } 396762306a36Sopenharmony_ci 396862306a36Sopenharmony_ci return ret; 396962306a36Sopenharmony_ci} 397062306a36Sopenharmony_ci 397162306a36Sopenharmony_cistatic int sd_resume_system(struct device *dev) 397262306a36Sopenharmony_ci{ 397362306a36Sopenharmony_ci if (pm_runtime_suspended(dev)) { 397462306a36Sopenharmony_ci struct scsi_disk *sdkp = dev_get_drvdata(dev); 397562306a36Sopenharmony_ci struct scsi_device *sdp = sdkp ? sdkp->device : NULL; 397662306a36Sopenharmony_ci 397762306a36Sopenharmony_ci if (sdp && sdp->force_runtime_start_on_system_start) 397862306a36Sopenharmony_ci pm_request_resume(dev); 397962306a36Sopenharmony_ci 398062306a36Sopenharmony_ci return 0; 398162306a36Sopenharmony_ci } 398262306a36Sopenharmony_ci 398362306a36Sopenharmony_ci return sd_resume(dev, false); 398462306a36Sopenharmony_ci} 398562306a36Sopenharmony_ci 398662306a36Sopenharmony_cistatic int sd_resume_runtime(struct device *dev) 398762306a36Sopenharmony_ci{ 398862306a36Sopenharmony_ci struct scsi_disk *sdkp = dev_get_drvdata(dev); 398962306a36Sopenharmony_ci struct scsi_device *sdp; 399062306a36Sopenharmony_ci 399162306a36Sopenharmony_ci if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ 399262306a36Sopenharmony_ci return 0; 399362306a36Sopenharmony_ci 399462306a36Sopenharmony_ci sdp = sdkp->device; 399562306a36Sopenharmony_ci 399662306a36Sopenharmony_ci if (sdp->ignore_media_change) { 399762306a36Sopenharmony_ci /* clear the device's sense data */ 399862306a36Sopenharmony_ci static const u8 cmd[10] = { REQUEST_SENSE }; 399962306a36Sopenharmony_ci const struct scsi_exec_args exec_args = { 400062306a36Sopenharmony_ci .req_flags = BLK_MQ_REQ_PM, 400162306a36Sopenharmony_ci }; 400262306a36Sopenharmony_ci 400362306a36Sopenharmony_ci if (scsi_execute_cmd(sdp, cmd, REQ_OP_DRV_IN, NULL, 0, 400462306a36Sopenharmony_ci sdp->request_queue->rq_timeout, 1, 400562306a36Sopenharmony_ci &exec_args)) 400662306a36Sopenharmony_ci sd_printk(KERN_NOTICE, sdkp, 400762306a36Sopenharmony_ci "Failed to clear sense data\n"); 400862306a36Sopenharmony_ci } 400962306a36Sopenharmony_ci 401062306a36Sopenharmony_ci return sd_resume(dev, true); 401162306a36Sopenharmony_ci} 401262306a36Sopenharmony_ci 401362306a36Sopenharmony_cistatic const struct dev_pm_ops sd_pm_ops = { 401462306a36Sopenharmony_ci .suspend = sd_suspend_system, 401562306a36Sopenharmony_ci .resume = sd_resume_system, 401662306a36Sopenharmony_ci .poweroff = sd_suspend_system, 401762306a36Sopenharmony_ci .restore = sd_resume_system, 401862306a36Sopenharmony_ci .runtime_suspend = sd_suspend_runtime, 401962306a36Sopenharmony_ci .runtime_resume = sd_resume_runtime, 402062306a36Sopenharmony_ci}; 402162306a36Sopenharmony_ci 402262306a36Sopenharmony_cistatic struct scsi_driver sd_template = { 402362306a36Sopenharmony_ci .gendrv = { 402462306a36Sopenharmony_ci .name = "sd", 402562306a36Sopenharmony_ci .owner = THIS_MODULE, 402662306a36Sopenharmony_ci .probe = sd_probe, 402762306a36Sopenharmony_ci .probe_type = PROBE_PREFER_ASYNCHRONOUS, 402862306a36Sopenharmony_ci .remove = sd_remove, 402962306a36Sopenharmony_ci .shutdown = sd_shutdown, 403062306a36Sopenharmony_ci .pm = &sd_pm_ops, 403162306a36Sopenharmony_ci }, 403262306a36Sopenharmony_ci .rescan = sd_rescan, 403362306a36Sopenharmony_ci .init_command = sd_init_command, 403462306a36Sopenharmony_ci .uninit_command = sd_uninit_command, 403562306a36Sopenharmony_ci .done = sd_done, 403662306a36Sopenharmony_ci .eh_action = sd_eh_action, 403762306a36Sopenharmony_ci .eh_reset = sd_eh_reset, 403862306a36Sopenharmony_ci}; 403962306a36Sopenharmony_ci 404062306a36Sopenharmony_ci/** 404162306a36Sopenharmony_ci * init_sd - entry point for this driver (both when built in or when 404262306a36Sopenharmony_ci * a module). 404362306a36Sopenharmony_ci * 404462306a36Sopenharmony_ci * Note: this function registers this driver with the scsi mid-level. 404562306a36Sopenharmony_ci **/ 404662306a36Sopenharmony_cistatic int __init init_sd(void) 404762306a36Sopenharmony_ci{ 404862306a36Sopenharmony_ci int majors = 0, i, err; 404962306a36Sopenharmony_ci 405062306a36Sopenharmony_ci SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n")); 405162306a36Sopenharmony_ci 405262306a36Sopenharmony_ci for (i = 0; i < SD_MAJORS; i++) { 405362306a36Sopenharmony_ci if (__register_blkdev(sd_major(i), "sd", sd_default_probe)) 405462306a36Sopenharmony_ci continue; 405562306a36Sopenharmony_ci majors++; 405662306a36Sopenharmony_ci } 405762306a36Sopenharmony_ci 405862306a36Sopenharmony_ci if (!majors) 405962306a36Sopenharmony_ci return -ENODEV; 406062306a36Sopenharmony_ci 406162306a36Sopenharmony_ci err = class_register(&sd_disk_class); 406262306a36Sopenharmony_ci if (err) 406362306a36Sopenharmony_ci goto err_out; 406462306a36Sopenharmony_ci 406562306a36Sopenharmony_ci sd_page_pool = mempool_create_page_pool(SD_MEMPOOL_SIZE, 0); 406662306a36Sopenharmony_ci if (!sd_page_pool) { 406762306a36Sopenharmony_ci printk(KERN_ERR "sd: can't init discard page pool\n"); 406862306a36Sopenharmony_ci err = -ENOMEM; 406962306a36Sopenharmony_ci goto err_out_class; 407062306a36Sopenharmony_ci } 407162306a36Sopenharmony_ci 407262306a36Sopenharmony_ci err = scsi_register_driver(&sd_template.gendrv); 407362306a36Sopenharmony_ci if (err) 407462306a36Sopenharmony_ci goto err_out_driver; 407562306a36Sopenharmony_ci 407662306a36Sopenharmony_ci return 0; 407762306a36Sopenharmony_ci 407862306a36Sopenharmony_cierr_out_driver: 407962306a36Sopenharmony_ci mempool_destroy(sd_page_pool); 408062306a36Sopenharmony_cierr_out_class: 408162306a36Sopenharmony_ci class_unregister(&sd_disk_class); 408262306a36Sopenharmony_cierr_out: 408362306a36Sopenharmony_ci for (i = 0; i < SD_MAJORS; i++) 408462306a36Sopenharmony_ci unregister_blkdev(sd_major(i), "sd"); 408562306a36Sopenharmony_ci return err; 408662306a36Sopenharmony_ci} 408762306a36Sopenharmony_ci 408862306a36Sopenharmony_ci/** 408962306a36Sopenharmony_ci * exit_sd - exit point for this driver (when it is a module). 409062306a36Sopenharmony_ci * 409162306a36Sopenharmony_ci * Note: this function unregisters this driver from the scsi mid-level. 409262306a36Sopenharmony_ci **/ 409362306a36Sopenharmony_cistatic void __exit exit_sd(void) 409462306a36Sopenharmony_ci{ 409562306a36Sopenharmony_ci int i; 409662306a36Sopenharmony_ci 409762306a36Sopenharmony_ci SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n")); 409862306a36Sopenharmony_ci 409962306a36Sopenharmony_ci scsi_unregister_driver(&sd_template.gendrv); 410062306a36Sopenharmony_ci mempool_destroy(sd_page_pool); 410162306a36Sopenharmony_ci 410262306a36Sopenharmony_ci class_unregister(&sd_disk_class); 410362306a36Sopenharmony_ci 410462306a36Sopenharmony_ci for (i = 0; i < SD_MAJORS; i++) 410562306a36Sopenharmony_ci unregister_blkdev(sd_major(i), "sd"); 410662306a36Sopenharmony_ci} 410762306a36Sopenharmony_ci 410862306a36Sopenharmony_cimodule_init(init_sd); 410962306a36Sopenharmony_cimodule_exit(exit_sd); 411062306a36Sopenharmony_ci 411162306a36Sopenharmony_civoid sd_print_sense_hdr(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr) 411262306a36Sopenharmony_ci{ 411362306a36Sopenharmony_ci scsi_print_sense_hdr(sdkp->device, 411462306a36Sopenharmony_ci sdkp->disk ? sdkp->disk->disk_name : NULL, sshdr); 411562306a36Sopenharmony_ci} 411662306a36Sopenharmony_ci 411762306a36Sopenharmony_civoid sd_print_result(const struct scsi_disk *sdkp, const char *msg, int result) 411862306a36Sopenharmony_ci{ 411962306a36Sopenharmony_ci const char *hb_string = scsi_hostbyte_string(result); 412062306a36Sopenharmony_ci 412162306a36Sopenharmony_ci if (hb_string) 412262306a36Sopenharmony_ci sd_printk(KERN_INFO, sdkp, 412362306a36Sopenharmony_ci "%s: Result: hostbyte=%s driverbyte=%s\n", msg, 412462306a36Sopenharmony_ci hb_string ? hb_string : "invalid", 412562306a36Sopenharmony_ci "DRIVER_OK"); 412662306a36Sopenharmony_ci else 412762306a36Sopenharmony_ci sd_printk(KERN_INFO, sdkp, 412862306a36Sopenharmony_ci "%s: Result: hostbyte=0x%02x driverbyte=%s\n", 412962306a36Sopenharmony_ci msg, host_byte(result), "DRIVER_OK"); 413062306a36Sopenharmony_ci} 4131