aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2009-09-18 17:33:00 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-10-02 10:46:39 -0400
commit35e1a5d90b66487d754ef2f2dcbf1007f806d921 (patch)
tree964511498993ed8fe0c1604ab74ac7a3db9361ba /drivers/scsi
parentc6af404215bab0d333accbb497f835d10cb0050c (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/scsi')
-rw-r--r--drivers/scsi/sd.c61
-rw-r--r--drivers/scsi/sd.h4
-rw-r--r--drivers/scsi/sd_dif.c53
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
373static 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,
1267disable: 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
1271static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, 1294static 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
104extern void sd_dif_op(struct scsi_cmnd *, unsigned int, unsigned int, unsigned int);
105extern void sd_dif_config_host(struct scsi_disk *); 104extern void sd_dif_config_host(struct scsi_disk *);
106extern int sd_dif_prepare(struct request *rq, sector_t, unsigned int); 105extern int sd_dif_prepare(struct request *rq, sector_t, unsigned int);
107extern void sd_dif_complete(struct scsi_cmnd *, unsigned int); 106extern 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
111static inline void sd_dif_op(struct scsi_cmnd *cmd, unsigned int a, unsigned int b, unsigned int c)
112{
113}
114static inline void sd_dif_config_host(struct scsi_disk *disk) 110static 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 */
365void 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