diff options
author | Martin K. Petersen <martin.petersen@oracle.com> | 2009-09-18 17:33:00 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-10-02 10:46:39 -0400 |
commit | 35e1a5d90b66487d754ef2f2dcbf1007f806d921 (patch) | |
tree | 964511498993ed8fe0c1604ab74ac7a3db9361ba /drivers | |
parent | c6af404215bab0d333accbb497f835d10cb0050c (diff) |
[SCSI] sd: Detach DIF from block integrity infrastructure
So far we have only issued DIF commands if CONFIG_BLK_DEV_INTEGRITY is
enabled. However, communication between initiator and target should be
independent of protection information DMA. There are DIF-only host
adapters coming out that will be able to take advantage of this.
Move the relevant DIF bits to sd.c.
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/sd.c | 61 | ||||
-rw-r--r-- | drivers/scsi/sd.h | 4 | ||||
-rw-r--r-- | drivers/scsi/sd_dif.c | 53 |
3 files changed, 42 insertions, 76 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8dd96dcd716c..1e0a0b07dab6 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -370,6 +370,31 @@ static void scsi_disk_put(struct scsi_disk *sdkp) | |||
370 | mutex_unlock(&sd_ref_mutex); | 370 | mutex_unlock(&sd_ref_mutex); |
371 | } | 371 | } |
372 | 372 | ||
373 | static void sd_prot_op(struct scsi_cmnd *scmd, unsigned int dif) | ||
374 | { | ||
375 | unsigned int prot_op = SCSI_PROT_NORMAL; | ||
376 | unsigned int dix = scsi_prot_sg_count(scmd); | ||
377 | |||
378 | if (scmd->sc_data_direction == DMA_FROM_DEVICE) { | ||
379 | if (dif && dix) | ||
380 | prot_op = SCSI_PROT_READ_PASS; | ||
381 | else if (dif && !dix) | ||
382 | prot_op = SCSI_PROT_READ_STRIP; | ||
383 | else if (!dif && dix) | ||
384 | prot_op = SCSI_PROT_READ_INSERT; | ||
385 | } else { | ||
386 | if (dif && dix) | ||
387 | prot_op = SCSI_PROT_WRITE_PASS; | ||
388 | else if (dif && !dix) | ||
389 | prot_op = SCSI_PROT_WRITE_INSERT; | ||
390 | else if (!dif && dix) | ||
391 | prot_op = SCSI_PROT_WRITE_STRIP; | ||
392 | } | ||
393 | |||
394 | scsi_set_prot_op(scmd, prot_op); | ||
395 | scsi_set_prot_type(scmd, dif); | ||
396 | } | ||
397 | |||
373 | /** | 398 | /** |
374 | * sd_init_command - build a scsi (read or write) command from | 399 | * sd_init_command - build a scsi (read or write) command from |
375 | * information in the request structure. | 400 | * information in the request structure. |
@@ -578,8 +603,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
578 | 603 | ||
579 | /* If DIF or DIX is enabled, tell HBA how to handle request */ | 604 | /* If DIF or DIX is enabled, tell HBA how to handle request */ |
580 | if (host_dif || scsi_prot_sg_count(SCpnt)) | 605 | if (host_dif || scsi_prot_sg_count(SCpnt)) |
581 | sd_dif_op(SCpnt, host_dif, scsi_prot_sg_count(SCpnt), | 606 | sd_prot_op(SCpnt, host_dif); |
582 | sdkp->protection_type); | ||
583 | 607 | ||
584 | /* | 608 | /* |
585 | * We shouldn't disconnect in the middle of a sector, so with a dumb | 609 | * We shouldn't disconnect in the middle of a sector, so with a dumb |
@@ -1238,34 +1262,33 @@ void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
1238 | u8 type; | 1262 | u8 type; |
1239 | 1263 | ||
1240 | if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) | 1264 | if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) |
1241 | type = 0; | 1265 | return; |
1242 | else | 1266 | |
1243 | type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ | 1267 | type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ |
1268 | |||
1269 | if (type == sdkp->protection_type || !sdkp->first_scan) | ||
1270 | return; | ||
1244 | 1271 | ||
1245 | sdkp->protection_type = type; | 1272 | sdkp->protection_type = type; |
1246 | 1273 | ||
1247 | switch (type) { | 1274 | switch (type) { |
1248 | case SD_DIF_TYPE0_PROTECTION: | ||
1249 | case SD_DIF_TYPE1_PROTECTION: | 1275 | case SD_DIF_TYPE1_PROTECTION: |
1250 | case SD_DIF_TYPE3_PROTECTION: | 1276 | case SD_DIF_TYPE3_PROTECTION: |
1251 | break; | 1277 | break; |
1252 | 1278 | ||
1253 | case SD_DIF_TYPE2_PROTECTION: | ||
1254 | sd_printk(KERN_ERR, sdkp, "formatted with DIF Type 2 " \ | ||
1255 | "protection which is currently unsupported. " \ | ||
1256 | "Disabling disk!\n"); | ||
1257 | goto disable; | ||
1258 | |||
1259 | default: | 1279 | default: |
1260 | sd_printk(KERN_ERR, sdkp, "formatted with unknown " \ | 1280 | sd_printk(KERN_ERR, sdkp, "formatted with unsupported " \ |
1261 | "protection type %d. Disabling disk!\n", type); | 1281 | "protection type %u. Disabling disk!\n", type); |
1262 | goto disable; | 1282 | sdkp->capacity = 0; |
1283 | return; | ||
1263 | } | 1284 | } |
1264 | 1285 | ||
1265 | return; | 1286 | if (scsi_host_dif_capable(sdp->host, type)) |
1266 | 1287 | sd_printk(KERN_NOTICE, sdkp, | |
1267 | disable: | 1288 | "Enabling DIF Type %u protection\n", type); |
1268 | sdkp->capacity = 0; | 1289 | else |
1290 | sd_printk(KERN_NOTICE, sdkp, | ||
1291 | "Disabling DIF Type %u protection\n", type); | ||
1269 | } | 1292 | } |
1270 | 1293 | ||
1271 | static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, | 1294 | static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, |
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 8474b5bad3fe..ce1f5f899fe3 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h | |||
@@ -101,16 +101,12 @@ struct sd_dif_tuple { | |||
101 | 101 | ||
102 | #ifdef CONFIG_BLK_DEV_INTEGRITY | 102 | #ifdef CONFIG_BLK_DEV_INTEGRITY |
103 | 103 | ||
104 | extern void sd_dif_op(struct scsi_cmnd *, unsigned int, unsigned int, unsigned int); | ||
105 | extern void sd_dif_config_host(struct scsi_disk *); | 104 | extern void sd_dif_config_host(struct scsi_disk *); |
106 | extern int sd_dif_prepare(struct request *rq, sector_t, unsigned int); | 105 | extern int sd_dif_prepare(struct request *rq, sector_t, unsigned int); |
107 | extern void sd_dif_complete(struct scsi_cmnd *, unsigned int); | 106 | extern void sd_dif_complete(struct scsi_cmnd *, unsigned int); |
108 | 107 | ||
109 | #else /* CONFIG_BLK_DEV_INTEGRITY */ | 108 | #else /* CONFIG_BLK_DEV_INTEGRITY */ |
110 | 109 | ||
111 | static inline void sd_dif_op(struct scsi_cmnd *cmd, unsigned int a, unsigned int b, unsigned int c) | ||
112 | { | ||
113 | } | ||
114 | static inline void sd_dif_config_host(struct scsi_disk *disk) | 110 | static inline void sd_dif_config_host(struct scsi_disk *disk) |
115 | { | 111 | { |
116 | } | 112 | } |
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c index 84224dd21acf..88da97745710 100644 --- a/drivers/scsi/sd_dif.c +++ b/drivers/scsi/sd_dif.c | |||
@@ -320,15 +320,6 @@ void sd_dif_config_host(struct scsi_disk *sdkp) | |||
320 | dif = 0; dix = 1; | 320 | dif = 0; dix = 1; |
321 | } | 321 | } |
322 | 322 | ||
323 | if (type) { | ||
324 | if (dif) | ||
325 | sd_printk(KERN_NOTICE, sdkp, | ||
326 | "Enabling DIF Type %d protection\n", type); | ||
327 | else | ||
328 | sd_printk(KERN_NOTICE, sdkp, | ||
329 | "Disabling DIF Type %d protection\n", type); | ||
330 | } | ||
331 | |||
332 | if (!dix) | 323 | if (!dix) |
333 | return; | 324 | return; |
334 | 325 | ||
@@ -360,50 +351,6 @@ void sd_dif_config_host(struct scsi_disk *sdkp) | |||
360 | } | 351 | } |
361 | 352 | ||
362 | /* | 353 | /* |
363 | * DIF DMA operation magic decoder ring. | ||
364 | */ | ||
365 | void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix, unsigned int type) | ||
366 | { | ||
367 | int prot_op; | ||
368 | |||
369 | prot_op = SCSI_PROT_NORMAL; | ||
370 | |||
371 | BUG_ON(dif && (scmd->cmnd[0] == READ_6 || scmd->cmnd[0] == WRITE_6)); | ||
372 | |||
373 | switch (scmd->cmnd[0]) { | ||
374 | case READ_6: | ||
375 | case READ_10: | ||
376 | case READ_12: | ||
377 | case READ_16: | ||
378 | if (dif && dix) | ||
379 | prot_op = SCSI_PROT_READ_PASS; | ||
380 | else if (dif && !dix) | ||
381 | prot_op = SCSI_PROT_READ_STRIP; | ||
382 | else if (!dif && dix) | ||
383 | prot_op = SCSI_PROT_READ_INSERT; | ||
384 | |||
385 | break; | ||
386 | |||
387 | case WRITE_6: | ||
388 | case WRITE_10: | ||
389 | case WRITE_12: | ||
390 | case WRITE_16: | ||
391 | if (dif && dix) | ||
392 | prot_op = SCSI_PROT_WRITE_PASS; | ||
393 | else if (dif && !dix) | ||
394 | prot_op = SCSI_PROT_WRITE_INSERT; | ||
395 | else if (!dif && dix) | ||
396 | prot_op = SCSI_PROT_WRITE_STRIP; | ||
397 | |||
398 | break; | ||
399 | } | ||
400 | |||
401 | scsi_set_prot_op(scmd, prot_op); | ||
402 | if (dif) | ||
403 | scsi_set_prot_type(scmd, type); | ||
404 | } | ||
405 | |||
406 | /* | ||
407 | * The virtual start sector is the one that was originally submitted | 354 | * The virtual start sector is the one that was originally submitted |
408 | * by the block layer. Due to partitioning, MD/DM cloning, etc. the | 355 | * by the block layer. Due to partitioning, MD/DM cloning, etc. the |
409 | * actual physical start sector is likely to be different. Remap | 356 | * actual physical start sector is likely to be different. Remap |