Commit | Line | Data |
---|---|---|
af55ff67 MP |
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> | |
2341c2f8 | 24 | #include <linux/t10-pi.h> |
af55ff67 MP |
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 | ||
af55ff67 MP |
36 | #include "sd.h" |
37 | ||
af55ff67 MP |
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; | |
0f8087ec | 46 | struct blk_integrity bi; |
9e06688e | 47 | int dif, dix; |
af55ff67 | 48 | |
9e06688e MP |
49 | dif = scsi_host_dif_capable(sdp->host, type); |
50 | dix = scsi_host_dix_capable(sdp->host, type); | |
af55ff67 | 51 | |
9e06688e MP |
52 | if (!dix && scsi_host_dix_capable(sdp->host, 0)) { |
53 | dif = 0; dix = 1; | |
54 | } | |
af55ff67 | 55 | |
9e06688e | 56 | if (!dix) |
af55ff67 | 57 | return; |
af55ff67 | 58 | |
0f8087ec MP |
59 | memset(&bi, 0, sizeof(bi)); |
60 | ||
af55ff67 | 61 | /* Enable DMA of protection information */ |
aae7df50 | 62 | if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) { |
8475c811 | 63 | if (type == T10_PI_TYPE3_PROTECTION) |
0f8087ec | 64 | bi.profile = &t10_pi_type3_ip; |
af55ff67 | 65 | else |
0f8087ec | 66 | bi.profile = &t10_pi_type1_ip; |
aae7df50 | 67 | |
0f8087ec | 68 | bi.flags |= BLK_INTEGRITY_IP_CHECKSUM; |
aae7df50 | 69 | } else |
8475c811 | 70 | if (type == T10_PI_TYPE3_PROTECTION) |
0f8087ec | 71 | bi.profile = &t10_pi_type3_crc; |
af55ff67 | 72 | else |
0f8087ec | 73 | bi.profile = &t10_pi_type1_crc; |
af55ff67 | 74 | |
0f8087ec | 75 | bi.tuple_size = sizeof(struct t10_pi_tuple); |
cbdc1445 | 76 | sd_printk(KERN_NOTICE, sdkp, |
0f8087ec | 77 | "Enabling DIX %s protection\n", bi.profile->name); |
af55ff67 | 78 | |
3aec2f41 | 79 | if (dif && type) { |
0f8087ec | 80 | bi.flags |= BLK_INTEGRITY_DEVICE_CAPABLE; |
3aec2f41 | 81 | |
e557990e | 82 | if (!sdkp->ATO) |
0f8087ec | 83 | goto out; |
3aec2f41 | 84 | |
8475c811 | 85 | if (type == T10_PI_TYPE3_PROTECTION) |
0f8087ec | 86 | bi.tag_size = sizeof(u16) + sizeof(u32); |
af55ff67 | 87 | else |
0f8087ec | 88 | bi.tag_size = sizeof(u16); |
af55ff67 | 89 | |
cbdc1445 | 90 | sd_printk(KERN_NOTICE, sdkp, "DIF application tag size %u\n", |
0f8087ec | 91 | bi.tag_size); |
af55ff67 | 92 | } |
0f8087ec MP |
93 | |
94 | out: | |
95 | blk_integrity_register(disk, &bi); | |
af55ff67 MP |
96 | } |
97 |