static inline int qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts) { struct scsi_cmnd *cmd = GET_CMD_SP(sp); uint8_t guard = scsi_host_get_guard(cmd->device->host); /* We only support T10 DIF right now */ if (guard != SHOST_DIX_GUARD_CRC) { ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3007, "Unsupported guard: %d for cmd=%p.\n", guard, cmd); return 0; } /* We always use DIFF Bundling for best performance */ *fw_prot_opts = 0; /* Translate SCSI opcode to a protection opcode */ switch (scsi_get_prot_op(cmd)) { case SCSI_PROT_READ_STRIP: *fw_prot_opts |= PO_MODE_DIF_REMOVE; break; case SCSI_PROT_WRITE_INSERT: *fw_prot_opts |= PO_MODE_DIF_INSERT; break; case SCSI_PROT_READ_INSERT: *fw_prot_opts |= PO_MODE_DIF_INSERT; break; case SCSI_PROT_WRITE_STRIP: *fw_prot_opts |= PO_MODE_DIF_REMOVE; break; case SCSI_PROT_READ_PASS: *fw_prot_opts |= PO_MODE_DIF_PASS; break; case SCSI_PROT_WRITE_PASS: *fw_prot_opts |= PO_MODE_DIF_PASS; break; default: /* Normal Request */ *fw_prot_opts |= PO_MODE_DIF_PASS; break; } return scsi_prot_sg_count(cmd); }
/* * Configure exchange of protection information between OS and HBA. */ void sd_dif_config_host(struct scsi_disk *sdkp) { struct scsi_device *sdp = sdkp->device; struct gendisk *disk = sdkp->disk; u8 type = sdkp->protection_type; int dif, dix; dif = scsi_host_dif_capable(sdp->host, type); dix = scsi_host_dix_capable(sdp->host, type); if (!dix && scsi_host_dix_capable(sdp->host, 0)) { dif = 0; dix = 1; } if (!dix) return; /* Enable DMA of protection information */ if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) if (type == SD_DIF_TYPE3_PROTECTION) blk_integrity_register(disk, &dif_type3_integrity_ip); else blk_integrity_register(disk, &dif_type1_integrity_ip); else if (type == SD_DIF_TYPE3_PROTECTION) blk_integrity_register(disk, &dif_type3_integrity_crc); else blk_integrity_register(disk, &dif_type1_integrity_crc); sd_printk(KERN_NOTICE, sdkp, "Enabling DIX %s protection\n", disk->integrity->name); /* Signal to block layer that we support sector tagging */ if (dif && type && sdkp->ATO) { if (type == SD_DIF_TYPE3_PROTECTION) disk->integrity->tag_size = sizeof(u16) + sizeof(u32); else disk->integrity->tag_size = sizeof(u16); sd_printk(KERN_NOTICE, sdkp, "DIF application tag size %u\n", disk->integrity->tag_size); } }