linux/drivers/scsi/sd_dif.c
<<
>>
Prefs
   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/blkdev.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 */
  27void 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(sdp->host, type);
  36        dix = scsi_host_dix_capable(sdp->host, type);
  37
  38        if (!dix && scsi_host_dix_capable(sdp->host, 0)) {
  39                dif = 0; dix = 1;
  40        }
  41
  42        if (!dix)
  43                return;
  44
  45        memset(&bi, 0, sizeof(bi));
  46
  47        /* Enable DMA of protection information */
  48        if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) {
  49                if (type == T10_PI_TYPE3_PROTECTION)
  50                        bi.profile = &t10_pi_type3_ip;
  51                else
  52                        bi.profile = &t10_pi_type1_ip;
  53
  54                bi.flags |= BLK_INTEGRITY_IP_CHECKSUM;
  55        } else
  56                if (type == T10_PI_TYPE3_PROTECTION)
  57                        bi.profile = &t10_pi_type3_crc;
  58                else
  59                        bi.profile = &t10_pi_type1_crc;
  60
  61        bi.tuple_size = sizeof(struct t10_pi_tuple);
  62        sd_printk(KERN_NOTICE, sdkp,
  63                  "Enabling DIX %s protection\n", bi.profile->name);
  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                sd_printk(KERN_NOTICE, sdkp, "DIF application tag size %u\n",
  77                          bi.tag_size);
  78        }
  79
  80out:
  81        blk_integrity_register(disk, &bi);
  82}
  83
  84