18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _SCSI_DISK_H
38c2ecf20Sopenharmony_ci#define _SCSI_DISK_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci/*
68c2ecf20Sopenharmony_ci * More than enough for everybody ;)  The huge number of majors
78c2ecf20Sopenharmony_ci * is a leftover from 16bit dev_t days, we don't really need that
88c2ecf20Sopenharmony_ci * much numberspace.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci#define SD_MAJORS	16
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci/*
138c2ecf20Sopenharmony_ci * Time out in seconds for disks and Magneto-opticals (which are slower).
148c2ecf20Sopenharmony_ci */
158c2ecf20Sopenharmony_ci#define SD_TIMEOUT		(30 * HZ)
168c2ecf20Sopenharmony_ci#define SD_MOD_TIMEOUT		(75 * HZ)
178c2ecf20Sopenharmony_ci/*
188c2ecf20Sopenharmony_ci * Flush timeout is a multiplier over the standard device timeout which is
198c2ecf20Sopenharmony_ci * user modifiable via sysfs but initially set to SD_TIMEOUT
208c2ecf20Sopenharmony_ci */
218c2ecf20Sopenharmony_ci#define SD_FLUSH_TIMEOUT_MULTIPLIER	2
228c2ecf20Sopenharmony_ci#define SD_WRITE_SAME_TIMEOUT	(120 * HZ)
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci/*
258c2ecf20Sopenharmony_ci * Number of allowed retries
268c2ecf20Sopenharmony_ci */
278c2ecf20Sopenharmony_ci#define SD_MAX_RETRIES		5
288c2ecf20Sopenharmony_ci#define SD_PASSTHROUGH_RETRIES	1
298c2ecf20Sopenharmony_ci#define SD_MAX_MEDIUM_TIMEOUTS	2
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/*
328c2ecf20Sopenharmony_ci * Size of the initial data buffer for mode and read capacity data
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_ci#define SD_BUF_SIZE		512
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/*
378c2ecf20Sopenharmony_ci * Number of sectors at the end of the device to avoid multi-sector
388c2ecf20Sopenharmony_ci * accesses to in the case of last_sector_bug
398c2ecf20Sopenharmony_ci */
408c2ecf20Sopenharmony_ci#define SD_LAST_BUGGY_SECTORS	8
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cienum {
438c2ecf20Sopenharmony_ci	SD_EXT_CDB_SIZE = 32,	/* Extended CDB size */
448c2ecf20Sopenharmony_ci	SD_MEMPOOL_SIZE = 2,	/* CDB pool size */
458c2ecf20Sopenharmony_ci};
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cienum {
488c2ecf20Sopenharmony_ci	SD_DEF_XFER_BLOCKS = 0xffff,
498c2ecf20Sopenharmony_ci	SD_MAX_XFER_BLOCKS = 0xffffffff,
508c2ecf20Sopenharmony_ci	SD_MAX_WS10_BLOCKS = 0xffff,
518c2ecf20Sopenharmony_ci	SD_MAX_WS16_BLOCKS = 0x7fffff,
528c2ecf20Sopenharmony_ci};
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cienum {
558c2ecf20Sopenharmony_ci	SD_LBP_FULL = 0,	/* Full logical block provisioning */
568c2ecf20Sopenharmony_ci	SD_LBP_UNMAP,		/* Use UNMAP command */
578c2ecf20Sopenharmony_ci	SD_LBP_WS16,		/* Use WRITE SAME(16) with UNMAP bit */
588c2ecf20Sopenharmony_ci	SD_LBP_WS10,		/* Use WRITE SAME(10) with UNMAP bit */
598c2ecf20Sopenharmony_ci	SD_LBP_ZERO,		/* Use WRITE SAME(10) with zero payload */
608c2ecf20Sopenharmony_ci	SD_LBP_DISABLE,		/* Discard disabled due to failed cmd */
618c2ecf20Sopenharmony_ci};
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cienum {
648c2ecf20Sopenharmony_ci	SD_ZERO_WRITE = 0,	/* Use WRITE(10/16) command */
658c2ecf20Sopenharmony_ci	SD_ZERO_WS,		/* Use WRITE SAME(10/16) command */
668c2ecf20Sopenharmony_ci	SD_ZERO_WS16_UNMAP,	/* Use WRITE SAME(16) with UNMAP */
678c2ecf20Sopenharmony_ci	SD_ZERO_WS10_UNMAP,	/* Use WRITE SAME(10) with UNMAP */
688c2ecf20Sopenharmony_ci};
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistruct scsi_disk {
718c2ecf20Sopenharmony_ci	struct scsi_driver *driver;	/* always &sd_template */
728c2ecf20Sopenharmony_ci	struct scsi_device *device;
738c2ecf20Sopenharmony_ci	struct device	dev;
748c2ecf20Sopenharmony_ci	struct gendisk	*disk;
758c2ecf20Sopenharmony_ci	struct opal_dev *opal_dev;
768c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED
778c2ecf20Sopenharmony_ci	u32		nr_zones;
788c2ecf20Sopenharmony_ci	u32		rev_nr_zones;
798c2ecf20Sopenharmony_ci	u32		zone_blocks;
808c2ecf20Sopenharmony_ci	u32		rev_zone_blocks;
818c2ecf20Sopenharmony_ci	u32		zones_optimal_open;
828c2ecf20Sopenharmony_ci	u32		zones_optimal_nonseq;
838c2ecf20Sopenharmony_ci	u32		zones_max_open;
848c2ecf20Sopenharmony_ci	u32		*zones_wp_offset;
858c2ecf20Sopenharmony_ci	spinlock_t	zones_wp_offset_lock;
868c2ecf20Sopenharmony_ci	u32		*rev_wp_offset;
878c2ecf20Sopenharmony_ci	struct mutex	rev_mutex;
888c2ecf20Sopenharmony_ci	struct work_struct zone_wp_offset_work;
898c2ecf20Sopenharmony_ci	char		*zone_wp_update_buf;
908c2ecf20Sopenharmony_ci#endif
918c2ecf20Sopenharmony_ci	atomic_t	openers;
928c2ecf20Sopenharmony_ci	sector_t	capacity;	/* size in logical blocks */
938c2ecf20Sopenharmony_ci	int		max_retries;
948c2ecf20Sopenharmony_ci	u32		max_xfer_blocks;
958c2ecf20Sopenharmony_ci	u32		opt_xfer_blocks;
968c2ecf20Sopenharmony_ci	u32		max_ws_blocks;
978c2ecf20Sopenharmony_ci	u32		max_unmap_blocks;
988c2ecf20Sopenharmony_ci	u32		unmap_granularity;
998c2ecf20Sopenharmony_ci	u32		unmap_alignment;
1008c2ecf20Sopenharmony_ci	u32		index;
1018c2ecf20Sopenharmony_ci	unsigned int	physical_block_size;
1028c2ecf20Sopenharmony_ci	unsigned int	max_medium_access_timeouts;
1038c2ecf20Sopenharmony_ci	unsigned int	medium_access_timed_out;
1048c2ecf20Sopenharmony_ci	u8		media_present;
1058c2ecf20Sopenharmony_ci	u8		write_prot;
1068c2ecf20Sopenharmony_ci	u8		protection_type;/* Data Integrity Field */
1078c2ecf20Sopenharmony_ci	u8		provisioning_mode;
1088c2ecf20Sopenharmony_ci	u8		zeroing_mode;
1098c2ecf20Sopenharmony_ci	unsigned	ATO : 1;	/* state of disk ATO bit */
1108c2ecf20Sopenharmony_ci	unsigned	cache_override : 1; /* temp override of WCE,RCD */
1118c2ecf20Sopenharmony_ci	unsigned	WCE : 1;	/* state of disk WCE bit */
1128c2ecf20Sopenharmony_ci	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
1138c2ecf20Sopenharmony_ci	unsigned	DPOFUA : 1;	/* state of disk DPOFUA bit */
1148c2ecf20Sopenharmony_ci	unsigned	first_scan : 1;
1158c2ecf20Sopenharmony_ci	unsigned	lbpme : 1;
1168c2ecf20Sopenharmony_ci	unsigned	lbprz : 1;
1178c2ecf20Sopenharmony_ci	unsigned	lbpu : 1;
1188c2ecf20Sopenharmony_ci	unsigned	lbpws : 1;
1198c2ecf20Sopenharmony_ci	unsigned	lbpws10 : 1;
1208c2ecf20Sopenharmony_ci	unsigned	lbpvpd : 1;
1218c2ecf20Sopenharmony_ci	unsigned	ws10 : 1;
1228c2ecf20Sopenharmony_ci	unsigned	ws16 : 1;
1238c2ecf20Sopenharmony_ci	unsigned	rc_basis: 2;
1248c2ecf20Sopenharmony_ci	unsigned	zoned: 2;
1258c2ecf20Sopenharmony_ci	unsigned	urswrz : 1;
1268c2ecf20Sopenharmony_ci	unsigned	security : 1;
1278c2ecf20Sopenharmony_ci	unsigned	ignore_medium_access_errors : 1;
1288c2ecf20Sopenharmony_ci};
1298c2ecf20Sopenharmony_ci#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_cistatic inline struct scsi_disk *scsi_disk(struct gendisk *disk)
1328c2ecf20Sopenharmony_ci{
1338c2ecf20Sopenharmony_ci	return container_of(disk->private_data, struct scsi_disk, driver);
1348c2ecf20Sopenharmony_ci}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci#define sd_printk(prefix, sdsk, fmt, a...)				\
1378c2ecf20Sopenharmony_ci        (sdsk)->disk ?							\
1388c2ecf20Sopenharmony_ci	      sdev_prefix_printk(prefix, (sdsk)->device,		\
1398c2ecf20Sopenharmony_ci				 (sdsk)->disk->disk_name, fmt, ##a) :	\
1408c2ecf20Sopenharmony_ci	      sdev_printk(prefix, (sdsk)->device, fmt, ##a)
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci#define sd_first_printk(prefix, sdsk, fmt, a...)			\
1438c2ecf20Sopenharmony_ci	do {								\
1448c2ecf20Sopenharmony_ci		if ((sdsk)->first_scan)					\
1458c2ecf20Sopenharmony_ci			sd_printk(prefix, sdsk, fmt, ##a);		\
1468c2ecf20Sopenharmony_ci	} while (0)
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_cistatic inline int scsi_medium_access_command(struct scsi_cmnd *scmd)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	switch (scmd->cmnd[0]) {
1518c2ecf20Sopenharmony_ci	case READ_6:
1528c2ecf20Sopenharmony_ci	case READ_10:
1538c2ecf20Sopenharmony_ci	case READ_12:
1548c2ecf20Sopenharmony_ci	case READ_16:
1558c2ecf20Sopenharmony_ci	case SYNCHRONIZE_CACHE:
1568c2ecf20Sopenharmony_ci	case VERIFY:
1578c2ecf20Sopenharmony_ci	case VERIFY_12:
1588c2ecf20Sopenharmony_ci	case VERIFY_16:
1598c2ecf20Sopenharmony_ci	case WRITE_6:
1608c2ecf20Sopenharmony_ci	case WRITE_10:
1618c2ecf20Sopenharmony_ci	case WRITE_12:
1628c2ecf20Sopenharmony_ci	case WRITE_16:
1638c2ecf20Sopenharmony_ci	case WRITE_SAME:
1648c2ecf20Sopenharmony_ci	case WRITE_SAME_16:
1658c2ecf20Sopenharmony_ci	case UNMAP:
1668c2ecf20Sopenharmony_ci		return 1;
1678c2ecf20Sopenharmony_ci	case VARIABLE_LENGTH_CMD:
1688c2ecf20Sopenharmony_ci		switch (scmd->cmnd[9]) {
1698c2ecf20Sopenharmony_ci		case READ_32:
1708c2ecf20Sopenharmony_ci		case VERIFY_32:
1718c2ecf20Sopenharmony_ci		case WRITE_32:
1728c2ecf20Sopenharmony_ci		case WRITE_SAME_32:
1738c2ecf20Sopenharmony_ci			return 1;
1748c2ecf20Sopenharmony_ci		}
1758c2ecf20Sopenharmony_ci	}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	return 0;
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cistatic inline sector_t logical_to_sectors(struct scsi_device *sdev, sector_t blocks)
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci	return blocks << (ilog2(sdev->sector_size) - 9);
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_cistatic inline unsigned int logical_to_bytes(struct scsi_device *sdev, sector_t blocks)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	return blocks * sdev->sector_size;
1888c2ecf20Sopenharmony_ci}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic inline sector_t bytes_to_logical(struct scsi_device *sdev, unsigned int bytes)
1918c2ecf20Sopenharmony_ci{
1928c2ecf20Sopenharmony_ci	return bytes >> ilog2(sdev->sector_size);
1938c2ecf20Sopenharmony_ci}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_cistatic inline sector_t sectors_to_logical(struct scsi_device *sdev, sector_t sector)
1968c2ecf20Sopenharmony_ci{
1978c2ecf20Sopenharmony_ci	return sector >> (ilog2(sdev->sector_size) - 9);
1988c2ecf20Sopenharmony_ci}
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_DEV_INTEGRITY
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ciextern void sd_dif_config_host(struct scsi_disk *);
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci#else /* CONFIG_BLK_DEV_INTEGRITY */
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_cistatic inline void sd_dif_config_host(struct scsi_disk *disk)
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci#endif /* CONFIG_BLK_DEV_INTEGRITY */
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_cistatic inline int sd_is_zoned(struct scsi_disk *sdkp)
2138c2ecf20Sopenharmony_ci{
2148c2ecf20Sopenharmony_ci	return sdkp->zoned == 1 || sdkp->device->type == TYPE_ZBC;
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_civoid sd_zbc_release_disk(struct scsi_disk *sdkp);
2208c2ecf20Sopenharmony_ciint sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buffer);
2218c2ecf20Sopenharmony_ciint sd_zbc_revalidate_zones(struct scsi_disk *sdkp);
2228c2ecf20Sopenharmony_ciblk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
2238c2ecf20Sopenharmony_ci					 unsigned char op, bool all);
2248c2ecf20Sopenharmony_ciunsigned int sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes,
2258c2ecf20Sopenharmony_ci			     struct scsi_sense_hdr *sshdr);
2268c2ecf20Sopenharmony_ciint sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
2278c2ecf20Sopenharmony_ci		unsigned int nr_zones, report_zones_cb cb, void *data);
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ciblk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
2308c2ecf20Sopenharmony_ci				        unsigned int nr_blocks);
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci#else /* CONFIG_BLK_DEV_ZONED */
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_cistatic inline void sd_zbc_release_disk(struct scsi_disk *sdkp) {}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_cistatic inline int sd_zbc_read_zones(struct scsi_disk *sdkp,
2378c2ecf20Sopenharmony_ci				    unsigned char *buf)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	return 0;
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_cistatic inline int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
2438c2ecf20Sopenharmony_ci{
2448c2ecf20Sopenharmony_ci	return 0;
2458c2ecf20Sopenharmony_ci}
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_cistatic inline blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
2488c2ecf20Sopenharmony_ci						       unsigned char op,
2498c2ecf20Sopenharmony_ci						       bool all)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	return BLK_STS_TARGET;
2528c2ecf20Sopenharmony_ci}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_cistatic inline unsigned int sd_zbc_complete(struct scsi_cmnd *cmd,
2558c2ecf20Sopenharmony_ci			unsigned int good_bytes, struct scsi_sense_hdr *sshdr)
2568c2ecf20Sopenharmony_ci{
2578c2ecf20Sopenharmony_ci	return good_bytes;
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cistatic inline blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd,
2618c2ecf20Sopenharmony_ci						      sector_t *lba,
2628c2ecf20Sopenharmony_ci						      unsigned int nr_blocks)
2638c2ecf20Sopenharmony_ci{
2648c2ecf20Sopenharmony_ci	return BLK_STS_TARGET;
2658c2ecf20Sopenharmony_ci}
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci#define sd_zbc_report_zones NULL
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci#endif /* CONFIG_BLK_DEV_ZONED */
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_civoid sd_print_sense_hdr(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr);
2728c2ecf20Sopenharmony_civoid sd_print_result(const struct scsi_disk *sdkp, const char *msg, int result);
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci#endif /* _SCSI_DISK_H */
275