diff mbox series

[2/6] sd, sd_zbc: use scsi_cmnd cdb access functions

Message ID 20220408035651.6472-3-dgilbert@interlog.com
State Superseded
Headers show
Series scsi: fix scsi_cmd::cmd_len | expand

Commit Message

Douglas Gilbert April 8, 2022, 3:56 a.m. UTC
Although currently unlikely to be needed, allow the sd driver to
issue SCSI commands whose CDB length is > 32. Remove the
direct access to the scsi_cmnd::cmnd field and use an access
function instead. Use 'cdb' rather than 'cmd' to refer to the
SCSI CDB field.

Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
---
 drivers/scsi/sd.c     | 176 +++++++++++++++++++++++-------------------
 drivers/scsi/sd_zbc.c |  12 +--
 2 files changed, 101 insertions(+), 87 deletions(-)
diff mbox series

Patch

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index a390679cf458..f0fc5789ccbf 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -842,6 +842,7 @@  static blk_status_t sd_setup_unmap_cmnd(struct scsi_cmnd *cmd)
 	u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
 	unsigned int data_len = 24;
 	char *buf;
+	u8 *cdb;
 
 	rq->special_vec.bv_page = mempool_alloc(sd_page_pool, GFP_ATOMIC);
 	if (!rq->special_vec.bv_page)
@@ -851,9 +852,9 @@  static blk_status_t sd_setup_unmap_cmnd(struct scsi_cmnd *cmd)
 	rq->special_vec.bv_len = data_len;
 	rq->rq_flags |= RQF_SPECIAL_PAYLOAD;
 
-	cmd->cmd_len = 10;
-	cmd->cmnd[0] = UNMAP;
-	cmd->cmnd[8] = 24;
+	cdb = scsi_cmnd_set_cdb(cmd, NULL, 10);
+	cdb[0] = UNMAP;
+	cdb[8] = 24;
 
 	buf = bvec_virt(&rq->special_vec);
 	put_unaligned_be16(6 + 16, &buf[0]);
@@ -877,6 +878,7 @@  static blk_status_t sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd,
 	u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq));
 	u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
 	u32 data_len = sdp->sector_size;
+	u8 *cdb;
 
 	rq->special_vec.bv_page = mempool_alloc(sd_page_pool, GFP_ATOMIC);
 	if (!rq->special_vec.bv_page)
@@ -886,12 +888,12 @@  static blk_status_t sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd,
 	rq->special_vec.bv_len = data_len;
 	rq->rq_flags |= RQF_SPECIAL_PAYLOAD;
 
-	cmd->cmd_len = 16;
-	cmd->cmnd[0] = WRITE_SAME_16;
+	cdb = scsi_cmnd_set_cdb(cmd, NULL, 16);
+	cdb[0] = WRITE_SAME_16;
 	if (unmap)
-		cmd->cmnd[1] = 0x8; /* UNMAP */
-	put_unaligned_be64(lba, &cmd->cmnd[2]);
-	put_unaligned_be32(nr_blocks, &cmd->cmnd[10]);
+		cdb[1] = 0x8; /* UNMAP */
+	put_unaligned_be64(lba, &cdb[2]);
+	put_unaligned_be32(nr_blocks, &cdb[10]);
 
 	cmd->allowed = sdkp->max_retries;
 	cmd->transfersize = data_len;
@@ -909,6 +911,7 @@  static blk_status_t sd_setup_write_same10_cmnd(struct scsi_cmnd *cmd,
 	u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq));
 	u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
 	u32 data_len = sdp->sector_size;
+	u8 *cdb;
 
 	rq->special_vec.bv_page = mempool_alloc(sd_page_pool, GFP_ATOMIC);
 	if (!rq->special_vec.bv_page)
@@ -918,12 +921,12 @@  static blk_status_t sd_setup_write_same10_cmnd(struct scsi_cmnd *cmd,
 	rq->special_vec.bv_len = data_len;
 	rq->rq_flags |= RQF_SPECIAL_PAYLOAD;
 
-	cmd->cmd_len = 10;
-	cmd->cmnd[0] = WRITE_SAME;
+	cdb = scsi_cmnd_set_cdb(cmd, NULL, 10);
+	cdb[0] = WRITE_SAME;
 	if (unmap)
-		cmd->cmnd[1] = 0x8; /* UNMAP */
-	put_unaligned_be32(lba, &cmd->cmnd[2]);
-	put_unaligned_be16(nr_blocks, &cmd->cmnd[7]);
+		cdb[1] = 0x8; /* UNMAP */
+	put_unaligned_be32(lba, &cdb[2]);
+	put_unaligned_be16(nr_blocks, &cdb[7]);
 
 	cmd->allowed = sdkp->max_retries;
 	cmd->transfersize = data_len;
@@ -1024,12 +1027,13 @@  static blk_status_t sd_setup_flush_cmnd(struct scsi_cmnd *cmd)
 {
 	struct request *rq = scsi_cmd_to_rq(cmd);
 	struct scsi_disk *sdkp = scsi_disk(rq->q->disk);
+	u8 *cdb;
 
 	/* flush requests don't perform I/O, zero the S/G table */
 	memset(&cmd->sdb, 0, sizeof(cmd->sdb));
 
-	cmd->cmnd[0] = SYNCHRONIZE_CACHE;
-	cmd->cmd_len = 10;
+	cdb = scsi_cmnd_set_cdb(cmd, NULL, 10);
+	cdb[0] = SYNCHRONIZE_CACHE;
 	cmd->transfersize = 0;
 	cmd->allowed = sdkp->max_retries;
 
@@ -1041,14 +1045,16 @@  static blk_status_t sd_setup_rw32_cmnd(struct scsi_cmnd *cmd, bool write,
 				       sector_t lba, unsigned int nr_blocks,
 				       unsigned char flags)
 {
-	cmd->cmd_len = SD_EXT_CDB_SIZE;
-	cmd->cmnd[0]  = VARIABLE_LENGTH_CMD;
-	cmd->cmnd[7]  = 0x18; /* Additional CDB len */
-	cmd->cmnd[9]  = write ? WRITE_32 : READ_32;
-	cmd->cmnd[10] = flags;
-	put_unaligned_be64(lba, &cmd->cmnd[12]);
-	put_unaligned_be32(lba, &cmd->cmnd[20]); /* Expected Indirect LBA */
-	put_unaligned_be32(nr_blocks, &cmd->cmnd[28]);
+	u8 *cdb;
+
+	cdb = scsi_cmnd_set_cdb(cmd, NULL, SD_EXT_CDB_SIZE);
+	cdb[0]  = VARIABLE_LENGTH_CMD;
+	cdb[7]  = 0x18; /* Additional CDB len */
+	cdb[9]  = write ? WRITE_32 : READ_32;
+	cdb[10] = flags;
+	put_unaligned_be64(lba, &cdb[12]);
+	put_unaligned_be32(lba, &cdb[20]); /* Expected Indirect LBA */
+	put_unaligned_be32(nr_blocks, &cdb[28]);
 
 	return BLK_STS_OK;
 }
@@ -1057,13 +1063,15 @@  static blk_status_t sd_setup_rw16_cmnd(struct scsi_cmnd *cmd, bool write,
 				       sector_t lba, unsigned int nr_blocks,
 				       unsigned char flags)
 {
-	cmd->cmd_len  = 16;
-	cmd->cmnd[0]  = write ? WRITE_16 : READ_16;
-	cmd->cmnd[1]  = flags;
-	cmd->cmnd[14] = 0;
-	cmd->cmnd[15] = 0;
-	put_unaligned_be64(lba, &cmd->cmnd[2]);
-	put_unaligned_be32(nr_blocks, &cmd->cmnd[10]);
+	u8 *cdb;
+
+	cdb = scsi_cmnd_set_cdb(cmd, NULL, 16);
+	cdb[0]  = write ? WRITE_16 : READ_16;
+	cdb[1]  = flags;
+	cdb[14] = 0;
+	cdb[15] = 0;
+	put_unaligned_be64(lba, &cdb[2]);
+	put_unaligned_be32(nr_blocks, &cdb[10]);
 
 	return BLK_STS_OK;
 }
@@ -1072,13 +1080,15 @@  static blk_status_t sd_setup_rw10_cmnd(struct scsi_cmnd *cmd, bool write,
 				       sector_t lba, unsigned int nr_blocks,
 				       unsigned char flags)
 {
-	cmd->cmd_len = 10;
-	cmd->cmnd[0] = write ? WRITE_10 : READ_10;
-	cmd->cmnd[1] = flags;
-	cmd->cmnd[6] = 0;
-	cmd->cmnd[9] = 0;
-	put_unaligned_be32(lba, &cmd->cmnd[2]);
-	put_unaligned_be16(nr_blocks, &cmd->cmnd[7]);
+	u8 *cdb;
+
+	cdb = scsi_cmnd_set_cdb(cmd, NULL, 10);
+	cdb[0] = write ? WRITE_10 : READ_10;
+	cdb[1] = flags;
+	cdb[6] = 0;
+	cdb[9] = 0;
+	put_unaligned_be32(lba, &cdb[2]);
+	put_unaligned_be16(nr_blocks, &cdb[7]);
 
 	return BLK_STS_OK;
 }
@@ -1087,6 +1097,8 @@  static blk_status_t sd_setup_rw6_cmnd(struct scsi_cmnd *cmd, bool write,
 				      sector_t lba, unsigned int nr_blocks,
 				      unsigned char flags)
 {
+	u8 *cdb;
+
 	/* Avoid that 0 blocks gets translated into 256 blocks. */
 	if (WARN_ON_ONCE(nr_blocks == 0))
 		return BLK_STS_IOERR;
@@ -1101,13 +1113,13 @@  static blk_status_t sd_setup_rw6_cmnd(struct scsi_cmnd *cmd, bool write,
 		return BLK_STS_IOERR;
 	}
 
-	cmd->cmd_len = 6;
-	cmd->cmnd[0] = write ? WRITE_6 : READ_6;
-	cmd->cmnd[1] = (lba >> 16) & 0x1f;
-	cmd->cmnd[2] = (lba >> 8) & 0xff;
-	cmd->cmnd[3] = lba & 0xff;
-	cmd->cmnd[4] = nr_blocks;
-	cmd->cmnd[5] = 0;
+	cdb = scsi_cmnd_set_cdb(cmd, NULL, 6);
+	cdb[0] = write ? WRITE_6 : READ_6;
+	cdb[1] = (lba >> 16) & 0x1f;
+	cdb[2] = (lba >> 8) & 0xff;
+	cdb[3] = lba & 0xff;
+	cdb[4] = nr_blocks;
+	cdb[5] = 0;
 
 	return BLK_STS_OK;
 }
@@ -1589,14 +1601,14 @@  static int sd_sync_cache(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr)
 		sshdr = &my_sshdr;
 
 	for (retries = 3; retries > 0; --retries) {
-		unsigned char cmd[10] = { 0 };
+		unsigned char cdb[10] = { 0 };
 
-		cmd[0] = SYNCHRONIZE_CACHE;
+		cdb[0] = SYNCHRONIZE_CACHE;
 		/*
 		 * Leave the rest of the command zero to indicate
 		 * flush everything.
 		 */
-		res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, sshdr,
+		res = scsi_execute(sdp, cdb, DMA_NONE, NULL, 0, NULL, sshdr,
 				timeout, sdkp->max_retries, 0, RQF_PM, NULL);
 		if (res == 0)
 			break;
@@ -1710,19 +1722,19 @@  static int sd_pr_command(struct block_device *bdev, u8 sa,
 	struct scsi_device *sdev = sdkp->device;
 	struct scsi_sense_hdr sshdr;
 	int result;
-	u8 cmd[16] = { 0, };
+	u8 cdb[16] = { 0, };
 	u8 data[24] = { 0, };
 
-	cmd[0] = PERSISTENT_RESERVE_OUT;
-	cmd[1] = sa;
-	cmd[2] = type;
-	put_unaligned_be32(sizeof(data), &cmd[5]);
+	cdb[0] = PERSISTENT_RESERVE_OUT;
+	cdb[1] = sa;
+	cdb[2] = type;
+	put_unaligned_be32(sizeof(data), &cdb[5]);
 
 	put_unaligned_be64(key, &data[0]);
 	put_unaligned_be64(sa_key, &data[8]);
 	data[20] = flags;
 
-	result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, &data, sizeof(data),
+	result = scsi_execute_req(sdev, cdb, DMA_TO_DEVICE, &data, sizeof(data),
 			&sshdr, SD_TIMEOUT, sdkp->max_retries, NULL);
 
 	if (scsi_status_is_check_condition(result) &&
@@ -1931,6 +1943,7 @@  static int sd_done(struct scsi_cmnd *SCpnt)
 	struct scsi_sense_hdr sshdr;
 	struct request *req = scsi_cmd_to_rq(SCpnt);
 	struct scsi_disk *sdkp = scsi_disk(req->q->disk);
+	const u8 *cdb;
 	int sense_valid = 0;
 	int sense_deferred = 0;
 
@@ -1979,6 +1992,7 @@  static int sd_done(struct scsi_cmnd *SCpnt)
 	    (!sense_valid || sense_deferred))
 		goto out;
 
+	cdb = scsi_cmnd_get_cdb(SCpnt);
 	switch (sshdr.sense_key) {
 	case HARDWARE_ERROR:
 	case MEDIUM_ERROR:
@@ -2006,13 +2020,13 @@  static int sd_done(struct scsi_cmnd *SCpnt)
 			break;
 		case 0x20:	/* INVALID COMMAND OPCODE */
 		case 0x24:	/* INVALID FIELD IN CDB */
-			switch (SCpnt->cmnd[0]) {
+			switch (cdb[0]) {
 			case UNMAP:
 				sd_config_discard(sdkp, SD_LBP_DISABLE);
 				break;
 			case WRITE_SAME_16:
 			case WRITE_SAME:
-				if (SCpnt->cmnd[1] & 8) { /* UNMAP */
+				if (cdb[1] & 8) { /* UNMAP */
 					sd_config_discard(sdkp, SD_LBP_DISABLE);
 				} else {
 					sdkp->device->no_write_same = 1;
@@ -2044,7 +2058,7 @@  static int sd_done(struct scsi_cmnd *SCpnt)
 static void
 sd_spinup_disk(struct scsi_disk *sdkp)
 {
-	unsigned char cmd[10];
+	u8 cdb[10];
 	unsigned long spintime_expire = 0;
 	int retries, spintime;
 	unsigned int the_result;
@@ -2061,10 +2075,10 @@  sd_spinup_disk(struct scsi_disk *sdkp)
 		do {
 			bool media_was_present = sdkp->media_present;
 
-			cmd[0] = TEST_UNIT_READY;
-			memset((void *) &cmd[1], 0, 9);
+			cdb[0] = TEST_UNIT_READY;
+			memset((void *) &cdb[1], 0, 9);
 
-			the_result = scsi_execute_req(sdkp->device, cmd,
+			the_result = scsi_execute_req(sdkp->device, cdb,
 						      DMA_NONE, NULL, 0,
 						      &sshdr, SD_TIMEOUT,
 						      sdkp->max_retries, NULL);
@@ -2118,13 +2132,13 @@  sd_spinup_disk(struct scsi_disk *sdkp)
 			 */
 			if (!spintime) {
 				sd_printk(KERN_NOTICE, sdkp, "Spinning up disk...");
-				cmd[0] = START_STOP;
-				cmd[1] = 1;	/* Return immediately */
-				memset((void *) &cmd[2], 0, 8);
-				cmd[4] = 1;	/* Start spin cycle */
+				cdb[0] = START_STOP;
+				cdb[1] = 1;	/* Return immediately */
+				memset((void *) &cdb[2], 0, 8);
+				cdb[4] = 1;	/* Start spin cycle */
 				if (sdkp->device->start_stop_pwr_cond)
-					cmd[4] |= 1 << 4;
-				scsi_execute_req(sdkp->device, cmd, DMA_NONE,
+					cdb[4] |= 1 << 4;
+				scsi_execute_req(sdkp->device, cdb, DMA_NONE,
 						 NULL, 0, &sshdr,
 						 SD_TIMEOUT, sdkp->max_retries,
 						 NULL);
@@ -2247,7 +2261,7 @@  static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
 static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
 						unsigned char *buffer)
 {
-	unsigned char cmd[16];
+	u8 cdb[16];
 	struct scsi_sense_hdr sshdr;
 	int sense_valid = 0;
 	int the_result;
@@ -2260,13 +2274,13 @@  static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
 		return -EINVAL;
 
 	do {
-		memset(cmd, 0, 16);
-		cmd[0] = SERVICE_ACTION_IN_16;
-		cmd[1] = SAI_READ_CAPACITY_16;
-		cmd[13] = RC16_LEN;
+		memset(cdb, 0, 16);
+		cdb[0] = SERVICE_ACTION_IN_16;
+		cdb[1] = SAI_READ_CAPACITY_16;
+		cdb[13] = RC16_LEN;
 		memset(buffer, 0, RC16_LEN);
 
-		the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
+		the_result = scsi_execute_req(sdp, cdb, DMA_FROM_DEVICE,
 					buffer, RC16_LEN, &sshdr,
 					SD_TIMEOUT, sdkp->max_retries, NULL);
 
@@ -2338,7 +2352,7 @@  static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
 static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
 						unsigned char *buffer)
 {
-	unsigned char cmd[16];
+	unsigned char cdb[16];
 	struct scsi_sense_hdr sshdr;
 	int sense_valid = 0;
 	int the_result;
@@ -2347,11 +2361,11 @@  static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
 	unsigned sector_size;
 
 	do {
-		cmd[0] = READ_CAPACITY;
-		memset(&cmd[1], 0, 9);
+		cdb[0] = READ_CAPACITY;
+		memset(&cdb[1], 0, 9);
 		memset(buffer, 0, 8);
 
-		the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
+		the_result = scsi_execute_req(sdp, cdb, DMA_FROM_DEVICE,
 					buffer, 8, &sshdr,
 					SD_TIMEOUT, sdkp->max_retries, NULL);
 
@@ -3546,21 +3560,21 @@  static void scsi_disk_release(struct device *dev)
 
 static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
 {
-	unsigned char cmd[6] = { START_STOP };	/* START_VALID */
+	u8 cdb[6] = { START_STOP };	/* START_VALID */
 	struct scsi_sense_hdr sshdr;
 	struct scsi_device *sdp = sdkp->device;
 	int res;
 
 	if (start)
-		cmd[4] |= 1;	/* START */
+		cdb[4] |= 1;	/* START */
 
 	if (sdp->start_stop_pwr_cond)
-		cmd[4] |= start ? 1 << 4 : 3 << 4;	/* Active or Standby */
+		cdb[4] |= start ? 1 << 4 : 3 << 4;	/* Active or Standby */
 
 	if (!scsi_device_online(sdp))
 		return -ENODEV;
 
-	res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr,
+	res = scsi_execute(sdp, cdb, DMA_NONE, NULL, 0, NULL, &sshdr,
 			SD_TIMEOUT, sdkp->max_retries, 0, RQF_PM, NULL);
 	if (res) {
 		sd_print_result(sdkp, "Start/Stop Unit failed", res);
@@ -3700,9 +3714,9 @@  static int sd_resume_runtime(struct device *dev)
 
 	if (sdp->ignore_media_change) {
 		/* clear the device's sense data */
-		static const u8 cmd[10] = { REQUEST_SENSE };
+		static const u8 cdb[10] = { REQUEST_SENSE };
 
-		if (scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL,
+		if (scsi_execute(sdp, cdb, DMA_NONE, NULL, 0, NULL,
 				 NULL, sdp->request_queue->rq_timeout, 1, 0,
 				 RQF_PM, NULL))
 			sd_printk(KERN_NOTICE, sdkp,
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index 7f466280993b..5567e6af5b49 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -389,6 +389,7 @@  blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
 	struct request *rq = scsi_cmd_to_rq(cmd);
 	sector_t sector = blk_rq_pos(rq);
 	struct scsi_disk *sdkp = scsi_disk(rq->q->disk);
+	u8 *cdb;
 	sector_t block = sectors_to_logical(sdkp->device, sector);
 	blk_status_t ret;
 
@@ -396,14 +397,13 @@  blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
 	if (ret != BLK_STS_OK)
 		return ret;
 
-	cmd->cmd_len = 16;
-	memset(cmd->cmnd, 0, cmd->cmd_len);
-	cmd->cmnd[0] = ZBC_OUT;
-	cmd->cmnd[1] = op;
+	cdb = scsi_cmnd_set_cdb(cmd, NULL, 16);
+	cdb[0] = ZBC_OUT;
+	cdb[1] = op;
 	if (all)
-		cmd->cmnd[14] = 0x1;
+		cdb[14] = 0x1;
 	else
-		put_unaligned_be64(block, &cmd->cmnd[2]);
+		put_unaligned_be64(block, &cdb[2]);
 
 	rq->timeout = SD_TIMEOUT;
 	cmd->sc_data_direction = DMA_NONE;