Skip to content

Commit 152e52f

Browse files
damien-lemoalmartinkpetersen
authored andcommitted
scsi: core: Support Service Action in scsi_report_opcode()
The REPORT_SUPPORTED_OPERATION_CODES command allows checking for support of commands that have the same opcode but different service actions, such as READ 32 and WRITE 32. However, the current implementation of scsi_report_opcode() only allows checking an operation code without a service action differentiation. Add the "sa" argument to scsi_report_opcode() to allow passing a service action. If a non-zero service action is specified, the reporting options field value is set to 3 to have the service action field taken into account by the device. If no service action field is specified (zero), the reporting options field is set to 1 as before. Signed-off-by: Damien Le Moal <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Bart Van Assche <[email protected]> Signed-off-by: Niklas Cassel <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin K. Petersen <[email protected]>
1 parent a6cdc35 commit 152e52f

File tree

3 files changed

+27
-16
lines changed

3 files changed

+27
-16
lines changed

drivers/scsi/scsi.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -504,18 +504,22 @@ void scsi_attach_vpd(struct scsi_device *sdev)
504504
}
505505

506506
/**
507-
* scsi_report_opcode - Find out if a given command opcode is supported
507+
* scsi_report_opcode - Find out if a given command is supported
508508
* @sdev: scsi device to query
509509
* @buffer: scratch buffer (must be at least 20 bytes long)
510510
* @len: length of buffer
511-
* @opcode: opcode for command to look up
512-
*
513-
* Uses the REPORT SUPPORTED OPERATION CODES to look up the given
514-
* opcode. Returns -EINVAL if RSOC fails, 0 if the command opcode is
515-
* unsupported and 1 if the device claims to support the command.
511+
* @opcode: opcode for the command to look up
512+
* @sa: service action for the command to look up
513+
*
514+
* Uses the REPORT SUPPORTED OPERATION CODES to check support for the
515+
* command identified with @opcode and @sa. If the command does not
516+
* have a service action, @sa must be 0. Returns -EINVAL if RSOC fails,
517+
* 0 if the command is not supported and 1 if the device claims to
518+
* support the command.
516519
*/
517520
int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
518-
unsigned int len, unsigned char opcode)
521+
unsigned int len, unsigned char opcode,
522+
unsigned short sa)
519523
{
520524
unsigned char cmd[16];
521525
struct scsi_sense_hdr sshdr;
@@ -539,8 +543,14 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
539543
memset(cmd, 0, 16);
540544
cmd[0] = MAINTENANCE_IN;
541545
cmd[1] = MI_REPORT_SUPPORTED_OPERATION_CODES;
542-
cmd[2] = 1; /* One command format */
543-
cmd[3] = opcode;
546+
if (!sa) {
547+
cmd[2] = 1; /* One command format */
548+
cmd[3] = opcode;
549+
} else {
550+
cmd[2] = 3; /* One command format with service action */
551+
cmd[3] = opcode;
552+
put_unaligned_be16(sa, &cmd[4]);
553+
}
544554
put_unaligned_be32(request_len, &cmd[6]);
545555
memset(buffer, 0, len);
546556

drivers/scsi/sd.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3056,7 +3056,7 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
30563056
return;
30573057
}
30583058

3059-
if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) {
3059+
if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY, 0) < 0) {
30603060
struct scsi_vpd *vpd;
30613061

30623062
sdev->no_report_opcodes = 1;
@@ -3072,10 +3072,10 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
30723072
rcu_read_unlock();
30733073
}
30743074

3075-
if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16) == 1)
3075+
if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16, 0) == 1)
30763076
sdkp->ws16 = 1;
30773077

3078-
if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME) == 1)
3078+
if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME, 0) == 1)
30793079
sdkp->ws10 = 1;
30803080
}
30813081

@@ -3087,9 +3087,9 @@ static void sd_read_security(struct scsi_disk *sdkp, unsigned char *buffer)
30873087
return;
30883088

30893089
if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE,
3090-
SECURITY_PROTOCOL_IN) == 1 &&
3090+
SECURITY_PROTOCOL_IN, 0) == 1 &&
30913091
scsi_report_opcode(sdev, buffer, SD_BUF_SIZE,
3092-
SECURITY_PROTOCOL_OUT) == 1)
3092+
SECURITY_PROTOCOL_OUT, 0) == 1)
30933093
sdkp->security = 1;
30943094
}
30953095

include/scsi/scsi_device.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,8 +433,9 @@ extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
433433
int retries, struct scsi_sense_hdr *sshdr);
434434
extern int scsi_get_vpd_page(struct scsi_device *, u8 page, unsigned char *buf,
435435
int buf_len);
436-
extern int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
437-
unsigned int len, unsigned char opcode);
436+
int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
437+
unsigned int len, unsigned char opcode,
438+
unsigned short sa);
438439
extern int scsi_device_set_state(struct scsi_device *sdev,
439440
enum scsi_device_state state);
440441
extern struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type,

0 commit comments

Comments
 (0)