1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * sd_dif.c - SCSI Data Integrity Field |
4 | * |
5 | * Copyright (C) 2007, 2008 Oracle Corporation |
6 | * Written by: Martin K. Petersen <martin.petersen@oracle.com> |
7 | */ |
8 | |
9 | #include <linux/blk-integrity.h> |
10 | #include <linux/t10-pi.h> |
11 | |
12 | #include <scsi/scsi.h> |
13 | #include <scsi/scsi_cmnd.h> |
14 | #include <scsi/scsi_dbg.h> |
15 | #include <scsi/scsi_device.h> |
16 | #include <scsi/scsi_driver.h> |
17 | #include <scsi/scsi_eh.h> |
18 | #include <scsi/scsi_host.h> |
19 | #include <scsi/scsi_ioctl.h> |
20 | #include <scsi/scsicam.h> |
21 | |
22 | #include "sd.h" |
23 | |
24 | /* |
25 | * Configure exchange of protection information between OS and HBA. |
26 | */ |
27 | void sd_dif_config_host(struct scsi_disk *sdkp) |
28 | { |
29 | struct scsi_device *sdp = sdkp->device; |
30 | struct gendisk *disk = sdkp->disk; |
31 | u8 type = sdkp->protection_type; |
32 | struct blk_integrity bi; |
33 | int dif, dix; |
34 | |
35 | dif = scsi_host_dif_capable(shost: sdp->host, target_type: type); |
36 | dix = scsi_host_dix_capable(shost: sdp->host, target_type: type); |
37 | |
38 | if (!dix && scsi_host_dix_capable(shost: sdp->host, target_type: 0)) { |
39 | dif = 0; dix = 1; |
40 | } |
41 | |
42 | if (!dix) { |
43 | blk_integrity_unregister(disk); |
44 | return; |
45 | } |
46 | |
47 | memset(&bi, 0, sizeof(bi)); |
48 | |
49 | /* Enable DMA of protection information */ |
50 | if (scsi_host_get_guard(shost: sdkp->device->host) & SHOST_DIX_GUARD_IP) { |
51 | if (type == T10_PI_TYPE3_PROTECTION) |
52 | bi.profile = &t10_pi_type3_ip; |
53 | else |
54 | bi.profile = &t10_pi_type1_ip; |
55 | |
56 | bi.flags |= BLK_INTEGRITY_IP_CHECKSUM; |
57 | } else |
58 | if (type == T10_PI_TYPE3_PROTECTION) |
59 | bi.profile = &t10_pi_type3_crc; |
60 | else |
61 | bi.profile = &t10_pi_type1_crc; |
62 | |
63 | bi.tuple_size = sizeof(struct t10_pi_tuple); |
64 | |
65 | if (dif && type) { |
66 | bi.flags |= BLK_INTEGRITY_DEVICE_CAPABLE; |
67 | |
68 | if (!sdkp->ATO) |
69 | goto out; |
70 | |
71 | if (type == T10_PI_TYPE3_PROTECTION) |
72 | bi.tag_size = sizeof(u16) + sizeof(u32); |
73 | else |
74 | bi.tag_size = sizeof(u16); |
75 | } |
76 | |
77 | sd_first_printk(KERN_NOTICE, sdkp, |
78 | "Enabling DIX %s, application tag size %u bytes\n" , |
79 | bi.profile->name, bi.tag_size); |
80 | out: |
81 | blk_integrity_register(disk, &bi); |
82 | } |
83 | |
84 | |