Skip to content

Commit 35e1a5d

Browse files
martinkpetersenJames Bottomley
authored andcommitted
[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>
1 parent c6af404 commit 35e1a5d

File tree

4 files changed

+53
-80
lines changed

4 files changed

+53
-80
lines changed

drivers/scsi/sd.c

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,31 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
370370
mutex_unlock(&sd_ref_mutex);
371371
}
372372

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+
373398
/**
374399
* sd_init_command - build a scsi (read or write) command from
375400
* information in the request structure.
@@ -578,8 +603,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
578603

579604
/* If DIF or DIX is enabled, tell HBA how to handle request */
580605
if (host_dif || scsi_prot_sg_count(SCpnt))
581-
sd_dif_op(SCpnt, host_dif, scsi_prot_sg_count(SCpnt),
582-
sdkp->protection_type);
606+
sd_prot_op(SCpnt, host_dif);
583607

584608
/*
585609
* 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)
12381262
u8 type;
12391263

12401264
if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0)
1241-
type = 0;
1242-
else
1243-
type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
1265+
return;
1266+
1267+
type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
1268+
1269+
if (type == sdkp->protection_type || !sdkp->first_scan)
1270+
return;
12441271

12451272
sdkp->protection_type = type;
12461273

12471274
switch (type) {
1248-
case SD_DIF_TYPE0_PROTECTION:
12491275
case SD_DIF_TYPE1_PROTECTION:
12501276
case SD_DIF_TYPE3_PROTECTION:
12511277
break;
12521278

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-
12591279
default:
1260-
sd_printk(KERN_ERR, sdkp, "formatted with unknown " \
1261-
"protection type %d. Disabling disk!\n", type);
1262-
goto disable;
1280+
sd_printk(KERN_ERR, sdkp, "formatted with unsupported " \
1281+
"protection type %u. Disabling disk!\n", type);
1282+
sdkp->capacity = 0;
1283+
return;
12631284
}
12641285

1265-
return;
1266-
1267-
disable:
1268-
sdkp->capacity = 0;
1286+
if (scsi_host_dif_capable(sdp->host, type))
1287+
sd_printk(KERN_NOTICE, sdkp,
1288+
"Enabling DIF Type %u protection\n", type);
1289+
else
1290+
sd_printk(KERN_NOTICE, sdkp,
1291+
"Disabling DIF Type %u protection\n", type);
12691292
}
12701293

12711294
static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,

drivers/scsi/sd.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,16 +101,12 @@ struct sd_dif_tuple {
101101

102102
#ifdef CONFIG_BLK_DEV_INTEGRITY
103103

104-
extern void sd_dif_op(struct scsi_cmnd *, unsigned int, unsigned int, unsigned int);
105104
extern void sd_dif_config_host(struct scsi_disk *);
106105
extern int sd_dif_prepare(struct request *rq, sector_t, unsigned int);
107106
extern void sd_dif_complete(struct scsi_cmnd *, unsigned int);
108107

109108
#else /* CONFIG_BLK_DEV_INTEGRITY */
110109

111-
static inline void sd_dif_op(struct scsi_cmnd *cmd, unsigned int a, unsigned int b, unsigned int c)
112-
{
113-
}
114110
static inline void sd_dif_config_host(struct scsi_disk *disk)
115111
{
116112
}

drivers/scsi/sd_dif.c

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -320,15 +320,6 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
320320
dif = 0; dix = 1;
321321
}
322322

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-
332323
if (!dix)
333324
return;
334325

@@ -359,50 +350,6 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
359350
}
360351
}
361352

362-
/*
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-
406353
/*
407354
* The virtual start sector is the one that was originally submitted
408355
* by the block layer. Due to partitioning, MD/DM cloning, etc. the

include/scsi/scsi_host.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -798,23 +798,30 @@ static inline unsigned int scsi_host_get_prot(struct Scsi_Host *shost)
798798
static inline unsigned int scsi_host_dif_capable(struct Scsi_Host *shost, unsigned int target_type)
799799
{
800800
switch (target_type) {
801-
case 1: return shost->prot_capabilities & SHOST_DIF_TYPE1_PROTECTION;
802-
case 2: return shost->prot_capabilities & SHOST_DIF_TYPE2_PROTECTION;
803-
case 3: return shost->prot_capabilities & SHOST_DIF_TYPE3_PROTECTION;
801+
case 1:
802+
if (shost->prot_capabilities & SHOST_DIF_TYPE1_PROTECTION)
803+
return target_type;
804+
case 2:
805+
if (shost->prot_capabilities & SHOST_DIF_TYPE2_PROTECTION)
806+
return target_type;
807+
case 3:
808+
if (shost->prot_capabilities & SHOST_DIF_TYPE3_PROTECTION)
809+
return target_type;
804810
}
805811

806812
return 0;
807813
}
808814

809815
static inline unsigned int scsi_host_dix_capable(struct Scsi_Host *shost, unsigned int target_type)
810816
{
817+
#if defined(CONFIG_BLK_DEV_INTEGRITY)
811818
switch (target_type) {
812819
case 0: return shost->prot_capabilities & SHOST_DIX_TYPE0_PROTECTION;
813820
case 1: return shost->prot_capabilities & SHOST_DIX_TYPE1_PROTECTION;
814821
case 2: return shost->prot_capabilities & SHOST_DIX_TYPE2_PROTECTION;
815822
case 3: return shost->prot_capabilities & SHOST_DIX_TYPE3_PROTECTION;
816823
}
817-
824+
#endif
818825
return 0;
819826
}
820827

0 commit comments

Comments
 (0)