2019-06-01 11:08:25 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2008-07-17 12:28:35 +04:00
/*
* sd_dif . c - SCSI Data Integrity Field
*
* Copyright ( C ) 2007 , 2008 Oracle Corporation
* Written by : Martin K . Petersen < martin . petersen @ oracle . com >
*/
# include <linux/blkdev.h>
2014-09-27 03:20:07 +04:00
# include <linux/t10-pi.h>
2008-07-17 12:28:35 +04:00
# include <scsi/scsi.h>
# include <scsi/scsi_cmnd.h>
# include <scsi/scsi_dbg.h>
# include <scsi/scsi_device.h>
# include <scsi/scsi_driver.h>
# include <scsi/scsi_eh.h>
# include <scsi/scsi_host.h>
# include <scsi/scsi_ioctl.h>
# include <scsi/scsicam.h>
# include "sd.h"
/*
* Configure exchange of protection information between OS and HBA .
*/
void sd_dif_config_host ( struct scsi_disk * sdkp )
{
struct scsi_device * sdp = sdkp - > device ;
struct gendisk * disk = sdkp - > disk ;
u8 type = sdkp - > protection_type ;
2015-10-21 20:19:33 +03:00
struct blk_integrity bi ;
2008-09-20 02:47:21 +04:00
int dif , dix ;
2008-07-17 12:28:35 +04:00
2008-09-20 02:47:21 +04:00
dif = scsi_host_dif_capable ( sdp - > host , type ) ;
dix = scsi_host_dix_capable ( sdp - > host , type ) ;
2008-07-17 12:28:35 +04:00
2008-09-20 02:47:21 +04:00
if ( ! dix & & scsi_host_dix_capable ( sdp - > host , 0 ) ) {
dif = 0 ; dix = 1 ;
}
2008-07-17 12:28:35 +04:00
2008-09-20 02:47:21 +04:00
if ( ! dix )
2008-07-17 12:28:35 +04:00
return ;
2015-10-21 20:19:33 +03:00
memset ( & bi , 0 , sizeof ( bi ) ) ;
2008-07-17 12:28:35 +04:00
/* Enable DMA of protection information */
2014-09-27 03:20:05 +04:00
if ( scsi_host_get_guard ( sdkp - > device - > host ) & SHOST_DIX_GUARD_IP ) {
2016-09-11 20:35:41 +03:00
if ( type = = T10_PI_TYPE3_PROTECTION )
2015-10-21 20:19:33 +03:00
bi . profile = & t10_pi_type3_ip ;
2008-07-17 12:28:35 +04:00
else
2015-10-21 20:19:33 +03:00
bi . profile = & t10_pi_type1_ip ;
2014-09-27 03:20:05 +04:00
2015-10-21 20:19:33 +03:00
bi . flags | = BLK_INTEGRITY_IP_CHECKSUM ;
2014-09-27 03:20:05 +04:00
} else
2016-09-11 20:35:41 +03:00
if ( type = = T10_PI_TYPE3_PROTECTION )
2015-10-21 20:19:33 +03:00
bi . profile = & t10_pi_type3_crc ;
2008-07-17 12:28:35 +04:00
else
2015-10-21 20:19:33 +03:00
bi . profile = & t10_pi_type1_crc ;
2008-07-17 12:28:35 +04:00
2015-10-21 20:19:33 +03:00
bi . tuple_size = sizeof ( struct t10_pi_tuple ) ;
2008-10-01 09:37:21 +04:00
sd_printk ( KERN_NOTICE , sdkp ,
2015-10-21 20:19:33 +03:00
" Enabling DIX %s protection \n " , bi . profile - > name ) ;
2008-07-17 12:28:35 +04:00
2014-09-27 03:20:03 +04:00
if ( dif & & type ) {
2015-10-21 20:19:33 +03:00
bi . flags | = BLK_INTEGRITY_DEVICE_CAPABLE ;
2014-09-27 03:20:03 +04:00
2015-04-15 00:11:03 +03:00
if ( ! sdkp - > ATO )
2015-10-21 20:19:33 +03:00
goto out ;
2014-09-27 03:20:03 +04:00
2016-09-11 20:35:41 +03:00
if ( type = = T10_PI_TYPE3_PROTECTION )
2015-10-21 20:19:33 +03:00
bi . tag_size = sizeof ( u16 ) + sizeof ( u32 ) ;
2008-07-17 12:28:35 +04:00
else
2015-10-21 20:19:33 +03:00
bi . tag_size = sizeof ( u16 ) ;
2008-07-17 12:28:35 +04:00
2008-10-01 09:37:21 +04:00
sd_printk ( KERN_NOTICE , sdkp , " DIF application tag size %u \n " ,
2015-10-21 20:19:33 +03:00
bi . tag_size ) ;
2008-07-17 12:28:35 +04:00
}
2015-10-21 20:19:33 +03:00
out :
blk_integrity_register ( disk , & bi ) ;
2008-07-17 12:28:35 +04:00
}