1*a98c5b19SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2af55ff67SMartin K. Petersen /* 3af55ff67SMartin K. Petersen * sd_dif.c - SCSI Data Integrity Field 4af55ff67SMartin K. Petersen * 5af55ff67SMartin K. Petersen * Copyright (C) 2007, 2008 Oracle Corporation 6af55ff67SMartin K. Petersen * Written by: Martin K. Petersen <martin.petersen@oracle.com> 7af55ff67SMartin K. Petersen */ 8af55ff67SMartin K. Petersen 9af55ff67SMartin K. Petersen #include <linux/blkdev.h> 102341c2f8SMartin K. Petersen #include <linux/t10-pi.h> 11af55ff67SMartin K. Petersen 12af55ff67SMartin K. Petersen #include <scsi/scsi.h> 13af55ff67SMartin K. Petersen #include <scsi/scsi_cmnd.h> 14af55ff67SMartin K. Petersen #include <scsi/scsi_dbg.h> 15af55ff67SMartin K. Petersen #include <scsi/scsi_device.h> 16af55ff67SMartin K. Petersen #include <scsi/scsi_driver.h> 17af55ff67SMartin K. Petersen #include <scsi/scsi_eh.h> 18af55ff67SMartin K. Petersen #include <scsi/scsi_host.h> 19af55ff67SMartin K. Petersen #include <scsi/scsi_ioctl.h> 20af55ff67SMartin K. Petersen #include <scsi/scsicam.h> 21af55ff67SMartin K. Petersen 22af55ff67SMartin K. Petersen #include "sd.h" 23af55ff67SMartin K. Petersen 24af55ff67SMartin K. Petersen /* 25af55ff67SMartin K. Petersen * Configure exchange of protection information between OS and HBA. 26af55ff67SMartin K. Petersen */ 27af55ff67SMartin K. Petersen void sd_dif_config_host(struct scsi_disk *sdkp) 28af55ff67SMartin K. Petersen { 29af55ff67SMartin K. Petersen struct scsi_device *sdp = sdkp->device; 30af55ff67SMartin K. Petersen struct gendisk *disk = sdkp->disk; 31af55ff67SMartin K. Petersen u8 type = sdkp->protection_type; 320f8087ecSMartin K. Petersen struct blk_integrity bi; 339e06688eSMartin K. Petersen int dif, dix; 34af55ff67SMartin K. Petersen 359e06688eSMartin K. Petersen dif = scsi_host_dif_capable(sdp->host, type); 369e06688eSMartin K. Petersen dix = scsi_host_dix_capable(sdp->host, type); 37af55ff67SMartin K. Petersen 389e06688eSMartin K. Petersen if (!dix && scsi_host_dix_capable(sdp->host, 0)) { 399e06688eSMartin K. Petersen dif = 0; dix = 1; 40af55ff67SMartin K. Petersen } 41af55ff67SMartin K. Petersen 429e06688eSMartin K. Petersen if (!dix) 439e06688eSMartin K. Petersen return; 449e06688eSMartin K. Petersen 450f8087ecSMartin K. Petersen memset(&bi, 0, sizeof(bi)); 460f8087ecSMartin K. Petersen 47af55ff67SMartin K. Petersen /* Enable DMA of protection information */ 48aae7df50SMartin K. Petersen if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) { 498475c811SChristoph Hellwig if (type == T10_PI_TYPE3_PROTECTION) 500f8087ecSMartin K. Petersen bi.profile = &t10_pi_type3_ip; 51af55ff67SMartin K. Petersen else 520f8087ecSMartin K. Petersen bi.profile = &t10_pi_type1_ip; 53aae7df50SMartin K. Petersen 540f8087ecSMartin K. Petersen bi.flags |= BLK_INTEGRITY_IP_CHECKSUM; 55aae7df50SMartin K. Petersen } else 568475c811SChristoph Hellwig if (type == T10_PI_TYPE3_PROTECTION) 570f8087ecSMartin K. Petersen bi.profile = &t10_pi_type3_crc; 58af55ff67SMartin K. Petersen else 590f8087ecSMartin K. Petersen bi.profile = &t10_pi_type1_crc; 60af55ff67SMartin K. Petersen 610f8087ecSMartin K. Petersen bi.tuple_size = sizeof(struct t10_pi_tuple); 62cbdc1445SMartin K. Petersen sd_printk(KERN_NOTICE, sdkp, 630f8087ecSMartin K. Petersen "Enabling DIX %s protection\n", bi.profile->name); 64af55ff67SMartin K. Petersen 653aec2f41SMartin K. Petersen if (dif && type) { 660f8087ecSMartin K. Petersen bi.flags |= BLK_INTEGRITY_DEVICE_CAPABLE; 673aec2f41SMartin K. Petersen 68e557990eSMartin K. Petersen if (!sdkp->ATO) 690f8087ecSMartin K. Petersen goto out; 703aec2f41SMartin K. Petersen 718475c811SChristoph Hellwig if (type == T10_PI_TYPE3_PROTECTION) 720f8087ecSMartin K. Petersen bi.tag_size = sizeof(u16) + sizeof(u32); 73af55ff67SMartin K. Petersen else 740f8087ecSMartin K. Petersen bi.tag_size = sizeof(u16); 75af55ff67SMartin K. Petersen 76cbdc1445SMartin K. Petersen sd_printk(KERN_NOTICE, sdkp, "DIF application tag size %u\n", 770f8087ecSMartin K. Petersen bi.tag_size); 78af55ff67SMartin K. Petersen } 790f8087ecSMartin K. Petersen 800f8087ecSMartin K. Petersen out: 810f8087ecSMartin K. Petersen blk_integrity_register(disk, &bi); 82af55ff67SMartin K. Petersen } 83af55ff67SMartin K. Petersen 84