diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/scsi/scsi.h | 3 | ||||
-rw-r--r-- | include/scsi/scsi_cmnd.h | 86 | ||||
-rw-r--r-- | include/scsi/scsi_device.h | 17 | ||||
-rw-r--r-- | include/scsi/scsi_dh.h | 11 | ||||
-rw-r--r-- | include/scsi/scsi_eh.h | 2 | ||||
-rw-r--r-- | include/scsi/scsi_host.h | 86 |
6 files changed, 202 insertions, 3 deletions
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 00137a7769ee..5c40cc537d4c 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h | |||
@@ -106,6 +106,7 @@ | |||
106 | #define VARIABLE_LENGTH_CMD 0x7f | 106 | #define VARIABLE_LENGTH_CMD 0x7f |
107 | #define REPORT_LUNS 0xa0 | 107 | #define REPORT_LUNS 0xa0 |
108 | #define MAINTENANCE_IN 0xa3 | 108 | #define MAINTENANCE_IN 0xa3 |
109 | #define MAINTENANCE_OUT 0xa4 | ||
109 | #define MOVE_MEDIUM 0xa5 | 110 | #define MOVE_MEDIUM 0xa5 |
110 | #define EXCHANGE_MEDIUM 0xa6 | 111 | #define EXCHANGE_MEDIUM 0xa6 |
111 | #define READ_12 0xa8 | 112 | #define READ_12 0xa8 |
@@ -125,6 +126,8 @@ | |||
125 | #define SAI_READ_CAPACITY_16 0x10 | 126 | #define SAI_READ_CAPACITY_16 0x10 |
126 | /* values for maintenance in */ | 127 | /* values for maintenance in */ |
127 | #define MI_REPORT_TARGET_PGS 0x0a | 128 | #define MI_REPORT_TARGET_PGS 0x0a |
129 | /* values for maintenance out */ | ||
130 | #define MO_SET_TARGET_PGS 0x0a | ||
128 | 131 | ||
129 | /* Values for T10/04-262r7 */ | 132 | /* Values for T10/04-262r7 */ |
130 | #define ATA_16 0x85 /* 16-byte pass-thru */ | 133 | #define ATA_16 0x85 /* 16-byte pass-thru */ |
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 66c944849d6b..f9f6e793575c 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h | |||
@@ -77,6 +77,9 @@ struct scsi_cmnd { | |||
77 | int allowed; | 77 | int allowed; |
78 | int timeout_per_command; | 78 | int timeout_per_command; |
79 | 79 | ||
80 | unsigned char prot_op; | ||
81 | unsigned char prot_type; | ||
82 | |||
80 | unsigned short cmd_len; | 83 | unsigned short cmd_len; |
81 | enum dma_data_direction sc_data_direction; | 84 | enum dma_data_direction sc_data_direction; |
82 | 85 | ||
@@ -87,6 +90,8 @@ struct scsi_cmnd { | |||
87 | 90 | ||
88 | /* These elements define the operation we ultimately want to perform */ | 91 | /* These elements define the operation we ultimately want to perform */ |
89 | struct scsi_data_buffer sdb; | 92 | struct scsi_data_buffer sdb; |
93 | struct scsi_data_buffer *prot_sdb; | ||
94 | |||
90 | unsigned underflow; /* Return error if less than | 95 | unsigned underflow; /* Return error if less than |
91 | this amount is transferred */ | 96 | this amount is transferred */ |
92 | 97 | ||
@@ -208,4 +213,85 @@ static inline int scsi_sg_copy_to_buffer(struct scsi_cmnd *cmd, | |||
208 | buf, buflen); | 213 | buf, buflen); |
209 | } | 214 | } |
210 | 215 | ||
216 | /* | ||
217 | * The operations below are hints that tell the controller driver how | ||
218 | * to handle I/Os with DIF or similar types of protection information. | ||
219 | */ | ||
220 | enum scsi_prot_operations { | ||
221 | /* Normal I/O */ | ||
222 | SCSI_PROT_NORMAL = 0, | ||
223 | |||
224 | /* OS-HBA: Protected, HBA-Target: Unprotected */ | ||
225 | SCSI_PROT_READ_INSERT, | ||
226 | SCSI_PROT_WRITE_STRIP, | ||
227 | |||
228 | /* OS-HBA: Unprotected, HBA-Target: Protected */ | ||
229 | SCSI_PROT_READ_STRIP, | ||
230 | SCSI_PROT_WRITE_INSERT, | ||
231 | |||
232 | /* OS-HBA: Protected, HBA-Target: Protected */ | ||
233 | SCSI_PROT_READ_PASS, | ||
234 | SCSI_PROT_WRITE_PASS, | ||
235 | |||
236 | /* OS-HBA: Protected, HBA-Target: Protected, checksum conversion */ | ||
237 | SCSI_PROT_READ_CONVERT, | ||
238 | SCSI_PROT_WRITE_CONVERT, | ||
239 | }; | ||
240 | |||
241 | static inline void scsi_set_prot_op(struct scsi_cmnd *scmd, unsigned char op) | ||
242 | { | ||
243 | scmd->prot_op = op; | ||
244 | } | ||
245 | |||
246 | static inline unsigned char scsi_get_prot_op(struct scsi_cmnd *scmd) | ||
247 | { | ||
248 | return scmd->prot_op; | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * The controller usually does not know anything about the target it | ||
253 | * is communicating with. However, when DIX is enabled the controller | ||
254 | * must be know target type so it can verify the protection | ||
255 | * information passed along with the I/O. | ||
256 | */ | ||
257 | enum scsi_prot_target_type { | ||
258 | SCSI_PROT_DIF_TYPE0 = 0, | ||
259 | SCSI_PROT_DIF_TYPE1, | ||
260 | SCSI_PROT_DIF_TYPE2, | ||
261 | SCSI_PROT_DIF_TYPE3, | ||
262 | }; | ||
263 | |||
264 | static inline void scsi_set_prot_type(struct scsi_cmnd *scmd, unsigned char type) | ||
265 | { | ||
266 | scmd->prot_type = type; | ||
267 | } | ||
268 | |||
269 | static inline unsigned char scsi_get_prot_type(struct scsi_cmnd *scmd) | ||
270 | { | ||
271 | return scmd->prot_type; | ||
272 | } | ||
273 | |||
274 | static inline sector_t scsi_get_lba(struct scsi_cmnd *scmd) | ||
275 | { | ||
276 | return scmd->request->sector; | ||
277 | } | ||
278 | |||
279 | static inline unsigned scsi_prot_sg_count(struct scsi_cmnd *cmd) | ||
280 | { | ||
281 | return cmd->prot_sdb ? cmd->prot_sdb->table.nents : 0; | ||
282 | } | ||
283 | |||
284 | static inline struct scatterlist *scsi_prot_sglist(struct scsi_cmnd *cmd) | ||
285 | { | ||
286 | return cmd->prot_sdb ? cmd->prot_sdb->table.sgl : NULL; | ||
287 | } | ||
288 | |||
289 | static inline struct scsi_data_buffer *scsi_prot(struct scsi_cmnd *cmd) | ||
290 | { | ||
291 | return cmd->prot_sdb; | ||
292 | } | ||
293 | |||
294 | #define scsi_for_each_prot_sg(cmd, sg, nseg, __i) \ | ||
295 | for_each_sg(scsi_prot_sglist(cmd), sg, nseg, __i) | ||
296 | |||
211 | #endif /* _SCSI_SCSI_CMND_H */ | 297 | #endif /* _SCSI_SCSI_CMND_H */ |
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 6467f78b191f..291d56a19167 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h | |||
@@ -140,7 +140,8 @@ struct scsi_device { | |||
140 | unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */ | 140 | unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */ |
141 | unsigned guess_capacity:1; /* READ_CAPACITY might be too high by 1 */ | 141 | unsigned guess_capacity:1; /* READ_CAPACITY might be too high by 1 */ |
142 | unsigned retry_hwerror:1; /* Retry HARDWARE_ERROR */ | 142 | unsigned retry_hwerror:1; /* Retry HARDWARE_ERROR */ |
143 | unsigned last_sector_bug:1; /* Always read last sector in a 1 sector read */ | 143 | unsigned last_sector_bug:1; /* do not use multisector accesses on |
144 | SD_LAST_BUGGY_SECTORS */ | ||
144 | 145 | ||
145 | DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ | 146 | DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ |
146 | struct list_head event_list; /* asserted events */ | 147 | struct list_head event_list; /* asserted events */ |
@@ -167,15 +168,22 @@ struct scsi_device { | |||
167 | unsigned long sdev_data[0]; | 168 | unsigned long sdev_data[0]; |
168 | } __attribute__((aligned(sizeof(unsigned long)))); | 169 | } __attribute__((aligned(sizeof(unsigned long)))); |
169 | 170 | ||
171 | struct scsi_dh_devlist { | ||
172 | char *vendor; | ||
173 | char *model; | ||
174 | }; | ||
175 | |||
170 | struct scsi_device_handler { | 176 | struct scsi_device_handler { |
171 | /* Used by the infrastructure */ | 177 | /* Used by the infrastructure */ |
172 | struct list_head list; /* list of scsi_device_handlers */ | 178 | struct list_head list; /* list of scsi_device_handlers */ |
173 | struct notifier_block nb; | ||
174 | 179 | ||
175 | /* Filled by the hardware handler */ | 180 | /* Filled by the hardware handler */ |
176 | struct module *module; | 181 | struct module *module; |
177 | const char *name; | 182 | const char *name; |
183 | const struct scsi_dh_devlist *devlist; | ||
178 | int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *); | 184 | int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *); |
185 | int (*attach)(struct scsi_device *); | ||
186 | void (*detach)(struct scsi_device *); | ||
179 | int (*activate)(struct scsi_device *); | 187 | int (*activate)(struct scsi_device *); |
180 | int (*prep_fn)(struct scsi_device *, struct request *); | 188 | int (*prep_fn)(struct scsi_device *, struct request *); |
181 | }; | 189 | }; |
@@ -416,6 +424,11 @@ static inline int scsi_device_enclosure(struct scsi_device *sdev) | |||
416 | return sdev->inquiry[6] & (1<<6); | 424 | return sdev->inquiry[6] & (1<<6); |
417 | } | 425 | } |
418 | 426 | ||
427 | static inline int scsi_device_protection(struct scsi_device *sdev) | ||
428 | { | ||
429 | return sdev->inquiry[5] & (1<<0); | ||
430 | } | ||
431 | |||
419 | #define MODULE_ALIAS_SCSI_DEVICE(type) \ | 432 | #define MODULE_ALIAS_SCSI_DEVICE(type) \ |
420 | MODULE_ALIAS("scsi:t-" __stringify(type) "*") | 433 | MODULE_ALIAS("scsi:t-" __stringify(type) "*") |
421 | #define SCSI_DEVICE_MODALIAS_FMT "scsi:t-0x%02x" | 434 | #define SCSI_DEVICE_MODALIAS_FMT "scsi:t-0x%02x" |
diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h index 3ad2303d1a16..33efce20c26c 100644 --- a/include/scsi/scsi_dh.h +++ b/include/scsi/scsi_dh.h | |||
@@ -32,6 +32,7 @@ enum { | |||
32 | */ | 32 | */ |
33 | SCSI_DH_DEV_FAILED, /* generic device error */ | 33 | SCSI_DH_DEV_FAILED, /* generic device error */ |
34 | SCSI_DH_DEV_TEMP_BUSY, | 34 | SCSI_DH_DEV_TEMP_BUSY, |
35 | SCSI_DH_DEV_UNSUPP, /* device handler not supported */ | ||
35 | SCSI_DH_DEVICE_MAX, /* max device blkerr definition */ | 36 | SCSI_DH_DEVICE_MAX, /* max device blkerr definition */ |
36 | 37 | ||
37 | /* | 38 | /* |
@@ -57,6 +58,8 @@ enum { | |||
57 | #if defined(CONFIG_SCSI_DH) || defined(CONFIG_SCSI_DH_MODULE) | 58 | #if defined(CONFIG_SCSI_DH) || defined(CONFIG_SCSI_DH_MODULE) |
58 | extern int scsi_dh_activate(struct request_queue *); | 59 | extern int scsi_dh_activate(struct request_queue *); |
59 | extern int scsi_dh_handler_exist(const char *); | 60 | extern int scsi_dh_handler_exist(const char *); |
61 | extern int scsi_dh_attach(struct request_queue *, const char *); | ||
62 | extern void scsi_dh_detach(struct request_queue *); | ||
60 | #else | 63 | #else |
61 | static inline int scsi_dh_activate(struct request_queue *req) | 64 | static inline int scsi_dh_activate(struct request_queue *req) |
62 | { | 65 | { |
@@ -66,4 +69,12 @@ static inline int scsi_dh_handler_exist(const char *name) | |||
66 | { | 69 | { |
67 | return 0; | 70 | return 0; |
68 | } | 71 | } |
72 | static inline int scsi_dh_attach(struct request_queue *req, const char *name) | ||
73 | { | ||
74 | return SCSI_DH_NOSYS; | ||
75 | } | ||
76 | static inline void scsi_dh_detach(struct request_queue *q) | ||
77 | { | ||
78 | return; | ||
79 | } | ||
69 | #endif | 80 | #endif |
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 2a9add21267d..06a8790893ef 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h | |||
@@ -74,7 +74,9 @@ struct scsi_eh_save { | |||
74 | /* saved state */ | 74 | /* saved state */ |
75 | int result; | 75 | int result; |
76 | enum dma_data_direction data_direction; | 76 | enum dma_data_direction data_direction; |
77 | unsigned underflow; | ||
77 | unsigned char cmd_len; | 78 | unsigned char cmd_len; |
79 | unsigned char prot_op; | ||
78 | unsigned char *cmnd; | 80 | unsigned char *cmnd; |
79 | struct scsi_data_buffer sdb; | 81 | struct scsi_data_buffer sdb; |
80 | struct request *next_rq; | 82 | struct request *next_rq; |
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index a594bac4a77d..44a55d1bf530 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h | |||
@@ -547,7 +547,7 @@ struct Scsi_Host { | |||
547 | unsigned int host_failed; /* commands that failed. */ | 547 | unsigned int host_failed; /* commands that failed. */ |
548 | unsigned int host_eh_scheduled; /* EH scheduled without command */ | 548 | unsigned int host_eh_scheduled; /* EH scheduled without command */ |
549 | 549 | ||
550 | unsigned short host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ | 550 | unsigned int host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ |
551 | int resetting; /* if set, it means that last_reset is a valid value */ | 551 | int resetting; /* if set, it means that last_reset is a valid value */ |
552 | unsigned long last_reset; | 552 | unsigned long last_reset; |
553 | 553 | ||
@@ -636,6 +636,10 @@ struct Scsi_Host { | |||
636 | */ | 636 | */ |
637 | unsigned int max_host_blocked; | 637 | unsigned int max_host_blocked; |
638 | 638 | ||
639 | /* Protection Information */ | ||
640 | unsigned int prot_capabilities; | ||
641 | unsigned char prot_guard_type; | ||
642 | |||
639 | /* | 643 | /* |
640 | * q used for scsi_tgt msgs, async events or any other requests that | 644 | * q used for scsi_tgt msgs, async events or any other requests that |
641 | * need to be processed in userspace | 645 | * need to be processed in userspace |
@@ -756,6 +760,86 @@ extern struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, | |||
756 | extern void scsi_free_host_dev(struct scsi_device *); | 760 | extern void scsi_free_host_dev(struct scsi_device *); |
757 | extern struct scsi_device *scsi_get_host_dev(struct Scsi_Host *); | 761 | extern struct scsi_device *scsi_get_host_dev(struct Scsi_Host *); |
758 | 762 | ||
763 | /* | ||
764 | * DIF defines the exchange of protection information between | ||
765 | * initiator and SBC block device. | ||
766 | * | ||
767 | * DIX defines the exchange of protection information between OS and | ||
768 | * initiator. | ||
769 | */ | ||
770 | enum scsi_host_prot_capabilities { | ||
771 | SHOST_DIF_TYPE1_PROTECTION = 1 << 0, /* T10 DIF Type 1 */ | ||
772 | SHOST_DIF_TYPE2_PROTECTION = 1 << 1, /* T10 DIF Type 2 */ | ||
773 | SHOST_DIF_TYPE3_PROTECTION = 1 << 2, /* T10 DIF Type 3 */ | ||
774 | |||
775 | SHOST_DIX_TYPE0_PROTECTION = 1 << 3, /* DIX between OS and HBA only */ | ||
776 | SHOST_DIX_TYPE1_PROTECTION = 1 << 4, /* DIX with DIF Type 1 */ | ||
777 | SHOST_DIX_TYPE2_PROTECTION = 1 << 5, /* DIX with DIF Type 2 */ | ||
778 | SHOST_DIX_TYPE3_PROTECTION = 1 << 6, /* DIX with DIF Type 3 */ | ||
779 | }; | ||
780 | |||
781 | /* | ||
782 | * SCSI hosts which support the Data Integrity Extensions must | ||
783 | * indicate their capabilities by setting the prot_capabilities using | ||
784 | * this call. | ||
785 | */ | ||
786 | static inline void scsi_host_set_prot(struct Scsi_Host *shost, unsigned int mask) | ||
787 | { | ||
788 | shost->prot_capabilities = mask; | ||
789 | } | ||
790 | |||
791 | static inline unsigned int scsi_host_get_prot(struct Scsi_Host *shost) | ||
792 | { | ||
793 | return shost->prot_capabilities; | ||
794 | } | ||
795 | |||
796 | static inline unsigned int scsi_host_dif_capable(struct Scsi_Host *shost, unsigned int target_type) | ||
797 | { | ||
798 | switch (target_type) { | ||
799 | case 1: return shost->prot_capabilities & SHOST_DIF_TYPE1_PROTECTION; | ||
800 | case 2: return shost->prot_capabilities & SHOST_DIF_TYPE2_PROTECTION; | ||
801 | case 3: return shost->prot_capabilities & SHOST_DIF_TYPE3_PROTECTION; | ||
802 | } | ||
803 | |||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | static inline unsigned int scsi_host_dix_capable(struct Scsi_Host *shost, unsigned int target_type) | ||
808 | { | ||
809 | switch (target_type) { | ||
810 | case 0: return shost->prot_capabilities & SHOST_DIX_TYPE0_PROTECTION; | ||
811 | case 1: return shost->prot_capabilities & SHOST_DIX_TYPE1_PROTECTION; | ||
812 | case 2: return shost->prot_capabilities & SHOST_DIX_TYPE2_PROTECTION; | ||
813 | case 3: return shost->prot_capabilities & SHOST_DIX_TYPE3_PROTECTION; | ||
814 | } | ||
815 | |||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | /* | ||
820 | * All DIX-capable initiators must support the T10-mandated CRC | ||
821 | * checksum. Controllers can optionally implement the IP checksum | ||
822 | * scheme which has much lower impact on system performance. Note | ||
823 | * that the main rationale for the checksum is to match integrity | ||
824 | * metadata with data. Detecting bit errors are a job for ECC memory | ||
825 | * and buses. | ||
826 | */ | ||
827 | |||
828 | enum scsi_host_guard_type { | ||
829 | SHOST_DIX_GUARD_CRC = 1 << 0, | ||
830 | SHOST_DIX_GUARD_IP = 1 << 1, | ||
831 | }; | ||
832 | |||
833 | static inline void scsi_host_set_guard(struct Scsi_Host *shost, unsigned char type) | ||
834 | { | ||
835 | shost->prot_guard_type = type; | ||
836 | } | ||
837 | |||
838 | static inline unsigned char scsi_host_get_guard(struct Scsi_Host *shost) | ||
839 | { | ||
840 | return shost->prot_guard_type; | ||
841 | } | ||
842 | |||
759 | /* legacy interfaces */ | 843 | /* legacy interfaces */ |
760 | extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int); | 844 | extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int); |
761 | extern void scsi_unregister(struct Scsi_Host *); | 845 | extern void scsi_unregister(struct Scsi_Host *); |