1 /* 2 * sd_dif.c - SCSI Data Integrity Field 3 * 4 * Copyright (C) 2007, 2008 Oracle Corporation 5 * Written by: Martin K. Petersen <martin.petersen@oracle.com> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License version 9 * 2 as published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; see the file COPYING. If not, write to 18 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 19 * USA. 20 * 21 */ 22 23 #include <linux/blkdev.h> 24 #include <linux/t10-pi.h> 25 26 #include <scsi/scsi.h> 27 #include <scsi/scsi_cmnd.h> 28 #include <scsi/scsi_dbg.h> 29 #include <scsi/scsi_device.h> 30 #include <scsi/scsi_driver.h> 31 #include <scsi/scsi_eh.h> 32 #include <scsi/scsi_host.h> 33 #include <scsi/scsi_ioctl.h> 34 #include <scsi/scsicam.h> 35 36 #include "sd.h" 37 38 /* 39 * Configure exchange of protection information between OS and HBA. 40 */ 41 void sd_dif_config_host(struct scsi_disk *sdkp) 42 { 43 struct scsi_device *sdp = sdkp->device; 44 struct gendisk *disk = sdkp->disk; 45 u8 type = sdkp->protection_type; 46 struct blk_integrity bi; 47 int dif, dix; 48 49 dif = scsi_host_dif_capable(sdp->host, type); 50 dix = scsi_host_dix_capable(sdp->host, type); 51 52 if (!dix && scsi_host_dix_capable(sdp->host, 0)) { 53 dif = 0; dix = 1; 54 } 55 56 if (!dix) 57 return; 58 59 memset(&bi, 0, sizeof(bi)); 60 61 /* Enable DMA of protection information */ 62 if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) { 63 if (type == T10_PI_TYPE3_PROTECTION) 64 bi.profile = &t10_pi_type3_ip; 65 else 66 bi.profile = &t10_pi_type1_ip; 67 68 bi.flags |= BLK_INTEGRITY_IP_CHECKSUM; 69 } else 70 if (type == T10_PI_TYPE3_PROTECTION) 71 bi.profile = &t10_pi_type3_crc; 72 else 73 bi.profile = &t10_pi_type1_crc; 74 75 bi.tuple_size = sizeof(struct t10_pi_tuple); 76 sd_printk(KERN_NOTICE, sdkp, 77 "Enabling DIX %s protection\n", bi.profile->name); 78 79 if (dif && type) { 80 bi.flags |= BLK_INTEGRITY_DEVICE_CAPABLE; 81 82 if (!sdkp->ATO) 83 goto out; 84 85 if (type == T10_PI_TYPE3_PROTECTION) 86 bi.tag_size = sizeof(u16) + sizeof(u32); 87 else 88 bi.tag_size = sizeof(u16); 89 90 sd_printk(KERN_NOTICE, sdkp, "DIF application tag size %u\n", 91 bi.tag_size); 92 } 93 94 out: 95 blk_integrity_register(disk, &bi); 96 } 97 98