aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/libata-scsi.c1
-rw-r--r--drivers/firewire/sbp2.c1
-rw-r--r--drivers/scsi/scsi.c45
-rw-r--r--drivers/usb/storage/scsiglue.c3
-rw-r--r--include/scsi/scsi_device.h3
5 files changed, 53 insertions, 0 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index e3bda074fa12..7c2dead60518 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1052,6 +1052,7 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)
1052{ 1052{
1053 sdev->use_10_for_rw = 1; 1053 sdev->use_10_for_rw = 1;
1054 sdev->use_10_for_ms = 1; 1054 sdev->use_10_for_ms = 1;
1055 sdev->no_report_opcodes = 1;
1055 1056
1056 /* Schedule policy is determined by ->qc_defer() callback and 1057 /* Schedule policy is determined by ->qc_defer() callback and
1057 * it needs to see every deferred qc. Set dev_blocked to 1 to 1058 * it needs to see every deferred qc. Set dev_blocked to 1 to
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index 1162d6b3bf85..f82e9d4295d0 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -1546,6 +1546,7 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
1546 struct sbp2_logical_unit *lu = sdev->hostdata; 1546 struct sbp2_logical_unit *lu = sdev->hostdata;
1547 1547
1548 sdev->use_10_for_rw = 1; 1548 sdev->use_10_for_rw = 1;
1549 sdev->no_report_opcodes = 1;
1549 1550
1550 if (sbp2_param_exclusive_login) 1551 if (sbp2_param_exclusive_login)
1551 sdev->manage_start_stop = 1; 1552 sdev->manage_start_stop = 1;
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 2936b447cae9..2c0d0ec8150b 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -55,6 +55,7 @@
55#include <linux/cpu.h> 55#include <linux/cpu.h>
56#include <linux/mutex.h> 56#include <linux/mutex.h>
57#include <linux/async.h> 57#include <linux/async.h>
58#include <asm/unaligned.h>
58 59
59#include <scsi/scsi.h> 60#include <scsi/scsi.h>
60#include <scsi/scsi_cmnd.h> 61#include <scsi/scsi_cmnd.h>
@@ -1062,6 +1063,50 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf,
1062EXPORT_SYMBOL_GPL(scsi_get_vpd_page); 1063EXPORT_SYMBOL_GPL(scsi_get_vpd_page);
1063 1064
1064/** 1065/**
1066 * scsi_report_opcode - Find out if a given command opcode is supported
1067 * @sdev: scsi device to query
1068 * @buffer: scratch buffer (must be at least 20 bytes long)
1069 * @len: length of buffer
1070 * @opcode: opcode for command to look up
1071 *
1072 * Uses the REPORT SUPPORTED OPERATION CODES to look up the given
1073 * opcode. Returns 0 if RSOC fails or if the command opcode is
1074 * unsupported. Returns 1 if the device claims to support the command.
1075 */
1076int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
1077 unsigned int len, unsigned char opcode)
1078{
1079 unsigned char cmd[16];
1080 struct scsi_sense_hdr sshdr;
1081 int result;
1082
1083 if (sdev->no_report_opcodes || sdev->scsi_level < SCSI_SPC_3)
1084 return 0;
1085
1086 memset(cmd, 0, 16);
1087 cmd[0] = MAINTENANCE_IN;
1088 cmd[1] = MI_REPORT_SUPPORTED_OPERATION_CODES;
1089 cmd[2] = 1; /* One command format */
1090 cmd[3] = opcode;
1091 put_unaligned_be32(len, &cmd[6]);
1092 memset(buffer, 0, len);
1093
1094 result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len,
1095 &sshdr, 30 * HZ, 3, NULL);
1096
1097 if (result && scsi_sense_valid(&sshdr) &&
1098 sshdr.sense_key == ILLEGAL_REQUEST &&
1099 (sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00)
1100 return 0;
1101
1102 if ((buffer[1] & 3) == 3) /* Command supported */
1103 return 1;
1104
1105 return 0;
1106}
1107EXPORT_SYMBOL(scsi_report_opcode);
1108
1109/**
1065 * scsi_device_get - get an additional reference to a scsi_device 1110 * scsi_device_get - get an additional reference to a scsi_device
1066 * @sdev: device to get a reference to 1111 * @sdev: device to get a reference to
1067 * 1112 *
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index a3d54366afcc..6ab376a7c501 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -186,6 +186,9 @@ static int slave_configure(struct scsi_device *sdev)
186 /* Some devices don't handle VPD pages correctly */ 186 /* Some devices don't handle VPD pages correctly */
187 sdev->skip_vpd_pages = 1; 187 sdev->skip_vpd_pages = 1;
188 188
189 /* Do not attempt to use REPORT SUPPORTED OPERATION CODES */
190 sdev->no_report_opcodes = 1;
191
189 /* Some disks return the total number of blocks in response 192 /* Some disks return the total number of blocks in response
190 * to READ CAPACITY rather than the highest block number. 193 * to READ CAPACITY rather than the highest block number.
191 * If this device makes that mistake, tell the sd driver. */ 194 * If this device makes that mistake, tell the sd driver. */
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 88fae8d20154..379d465e8070 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -135,6 +135,7 @@ struct scsi_device {
135 * because we did a bus reset. */ 135 * because we did a bus reset. */
136 unsigned use_10_for_rw:1; /* first try 10-byte read / write */ 136 unsigned use_10_for_rw:1; /* first try 10-byte read / write */
137 unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */ 137 unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
138 unsigned no_report_opcodes:1; /* no REPORT SUPPORTED OPERATION CODES */
138 unsigned skip_ms_page_8:1; /* do not use MODE SENSE page 0x08 */ 139 unsigned skip_ms_page_8:1; /* do not use MODE SENSE page 0x08 */
139 unsigned skip_ms_page_3f:1; /* do not use MODE SENSE page 0x3f */ 140 unsigned skip_ms_page_3f:1; /* do not use MODE SENSE page 0x3f */
140 unsigned skip_vpd_pages:1; /* do not read VPD pages */ 141 unsigned skip_vpd_pages:1; /* do not read VPD pages */
@@ -362,6 +363,8 @@ extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
362 int retries, struct scsi_sense_hdr *sshdr); 363 int retries, struct scsi_sense_hdr *sshdr);
363extern int scsi_get_vpd_page(struct scsi_device *, u8 page, unsigned char *buf, 364extern int scsi_get_vpd_page(struct scsi_device *, u8 page, unsigned char *buf,
364 int buf_len); 365 int buf_len);
366extern int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
367 unsigned int len, unsigned char opcode);
365extern int scsi_device_set_state(struct scsi_device *sdev, 368extern int scsi_device_set_state(struct scsi_device *sdev,
366 enum scsi_device_state state); 369 enum scsi_device_state state);
367extern struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type, 370extern struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type,