1d6e0175cSChristoph Hellwig /* 2d6e0175cSChristoph Hellwig * SCSI Block Commands (SBC) parsing and emulation. 3d6e0175cSChristoph Hellwig * 44c76251eSNicholas Bellinger * (c) Copyright 2002-2013 Datera, Inc. 5d6e0175cSChristoph Hellwig * 6d6e0175cSChristoph Hellwig * Nicholas A. Bellinger <nab@kernel.org> 7d6e0175cSChristoph Hellwig * 8d6e0175cSChristoph Hellwig * This program is free software; you can redistribute it and/or modify 9d6e0175cSChristoph Hellwig * it under the terms of the GNU General Public License as published by 10d6e0175cSChristoph Hellwig * the Free Software Foundation; either version 2 of the License, or 11d6e0175cSChristoph Hellwig * (at your option) any later version. 12d6e0175cSChristoph Hellwig * 13d6e0175cSChristoph Hellwig * This program is distributed in the hope that it will be useful, 14d6e0175cSChristoph Hellwig * but WITHOUT ANY WARRANTY; without even the implied warranty of 15d6e0175cSChristoph Hellwig * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16d6e0175cSChristoph Hellwig * GNU General Public License for more details. 17d6e0175cSChristoph Hellwig * 18d6e0175cSChristoph Hellwig * You should have received a copy of the GNU General Public License 19d6e0175cSChristoph Hellwig * along with this program; if not, write to the Free Software 20d6e0175cSChristoph Hellwig * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21d6e0175cSChristoph Hellwig */ 22d6e0175cSChristoph Hellwig 23d6e0175cSChristoph Hellwig #include <linux/kernel.h> 24d6e0175cSChristoph Hellwig #include <linux/module.h> 25d6e0175cSChristoph Hellwig #include <linux/ratelimit.h> 2641861fa8SNicholas Bellinger #include <linux/crc-t10dif.h> 27d6e0175cSChristoph Hellwig #include <asm/unaligned.h> 28d6e0175cSChristoph Hellwig #include <scsi/scsi.h> 2968ff9b9bSNicholas Bellinger #include <scsi/scsi_tcq.h> 30d6e0175cSChristoph Hellwig 31d6e0175cSChristoph Hellwig #include <target/target_core_base.h> 32d6e0175cSChristoph Hellwig #include <target/target_core_backend.h> 33d6e0175cSChristoph Hellwig #include <target/target_core_fabric.h> 34d6e0175cSChristoph Hellwig 35d6e0175cSChristoph Hellwig #include "target_core_internal.h" 36d6e0175cSChristoph Hellwig #include "target_core_ua.h" 37c66094bfSHannes Reinecke #include "target_core_alua.h" 38d6e0175cSChristoph Hellwig 39de103c93SChristoph Hellwig static sense_reason_t 40de103c93SChristoph Hellwig sbc_emulate_readcapacity(struct se_cmd *cmd) 411fd032eeSChristoph Hellwig { 421fd032eeSChristoph Hellwig struct se_device *dev = cmd->se_dev; 438dc8632aSRoland Dreier unsigned char *cdb = cmd->t_task_cdb; 441fd032eeSChristoph Hellwig unsigned long long blocks_long = dev->transport->get_blocks(dev); 45a50da144SPaolo Bonzini unsigned char *rbuf; 46a50da144SPaolo Bonzini unsigned char buf[8]; 471fd032eeSChristoph Hellwig u32 blocks; 481fd032eeSChristoph Hellwig 498dc8632aSRoland Dreier /* 508dc8632aSRoland Dreier * SBC-2 says: 518dc8632aSRoland Dreier * If the PMI bit is set to zero and the LOGICAL BLOCK 528dc8632aSRoland Dreier * ADDRESS field is not set to zero, the device server shall 538dc8632aSRoland Dreier * terminate the command with CHECK CONDITION status with 548dc8632aSRoland Dreier * the sense key set to ILLEGAL REQUEST and the additional 558dc8632aSRoland Dreier * sense code set to INVALID FIELD IN CDB. 568dc8632aSRoland Dreier * 578dc8632aSRoland Dreier * In SBC-3, these fields are obsolete, but some SCSI 588dc8632aSRoland Dreier * compliance tests actually check this, so we might as well 598dc8632aSRoland Dreier * follow SBC-2. 608dc8632aSRoland Dreier */ 618dc8632aSRoland Dreier if (!(cdb[8] & 1) && !!(cdb[2] | cdb[3] | cdb[4] | cdb[5])) 628dc8632aSRoland Dreier return TCM_INVALID_CDB_FIELD; 638dc8632aSRoland Dreier 641fd032eeSChristoph Hellwig if (blocks_long >= 0x00000000ffffffff) 651fd032eeSChristoph Hellwig blocks = 0xffffffff; 661fd032eeSChristoph Hellwig else 671fd032eeSChristoph Hellwig blocks = (u32)blocks_long; 681fd032eeSChristoph Hellwig 691fd032eeSChristoph Hellwig buf[0] = (blocks >> 24) & 0xff; 701fd032eeSChristoph Hellwig buf[1] = (blocks >> 16) & 0xff; 711fd032eeSChristoph Hellwig buf[2] = (blocks >> 8) & 0xff; 721fd032eeSChristoph Hellwig buf[3] = blocks & 0xff; 730fd97ccfSChristoph Hellwig buf[4] = (dev->dev_attrib.block_size >> 24) & 0xff; 740fd97ccfSChristoph Hellwig buf[5] = (dev->dev_attrib.block_size >> 16) & 0xff; 750fd97ccfSChristoph Hellwig buf[6] = (dev->dev_attrib.block_size >> 8) & 0xff; 760fd97ccfSChristoph Hellwig buf[7] = dev->dev_attrib.block_size & 0xff; 771fd032eeSChristoph Hellwig 78a50da144SPaolo Bonzini rbuf = transport_kmap_data_sg(cmd); 798b4b0dcbSNicholas Bellinger if (rbuf) { 80a50da144SPaolo Bonzini memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); 811fd032eeSChristoph Hellwig transport_kunmap_data_sg(cmd); 828b4b0dcbSNicholas Bellinger } 831fd032eeSChristoph Hellwig 841fd032eeSChristoph Hellwig target_complete_cmd(cmd, GOOD); 851fd032eeSChristoph Hellwig return 0; 861fd032eeSChristoph Hellwig } 871fd032eeSChristoph Hellwig 88de103c93SChristoph Hellwig static sense_reason_t 89de103c93SChristoph Hellwig sbc_emulate_readcapacity_16(struct se_cmd *cmd) 901fd032eeSChristoph Hellwig { 911fd032eeSChristoph Hellwig struct se_device *dev = cmd->se_dev; 92a50da144SPaolo Bonzini unsigned char *rbuf; 93a50da144SPaolo Bonzini unsigned char buf[32]; 941fd032eeSChristoph Hellwig unsigned long long blocks = dev->transport->get_blocks(dev); 951fd032eeSChristoph Hellwig 96a50da144SPaolo Bonzini memset(buf, 0, sizeof(buf)); 971fd032eeSChristoph Hellwig buf[0] = (blocks >> 56) & 0xff; 981fd032eeSChristoph Hellwig buf[1] = (blocks >> 48) & 0xff; 991fd032eeSChristoph Hellwig buf[2] = (blocks >> 40) & 0xff; 1001fd032eeSChristoph Hellwig buf[3] = (blocks >> 32) & 0xff; 1011fd032eeSChristoph Hellwig buf[4] = (blocks >> 24) & 0xff; 1021fd032eeSChristoph Hellwig buf[5] = (blocks >> 16) & 0xff; 1031fd032eeSChristoph Hellwig buf[6] = (blocks >> 8) & 0xff; 1041fd032eeSChristoph Hellwig buf[7] = blocks & 0xff; 1050fd97ccfSChristoph Hellwig buf[8] = (dev->dev_attrib.block_size >> 24) & 0xff; 1060fd97ccfSChristoph Hellwig buf[9] = (dev->dev_attrib.block_size >> 16) & 0xff; 1070fd97ccfSChristoph Hellwig buf[10] = (dev->dev_attrib.block_size >> 8) & 0xff; 1080fd97ccfSChristoph Hellwig buf[11] = dev->dev_attrib.block_size & 0xff; 10956dac14cSNicholas Bellinger /* 11056dac14cSNicholas Bellinger * Set P_TYPE and PROT_EN bits for DIF support 11156dac14cSNicholas Bellinger */ 11256dac14cSNicholas Bellinger if (dev->dev_attrib.pi_prot_type) 11356dac14cSNicholas Bellinger buf[12] = (dev->dev_attrib.pi_prot_type - 1) << 1 | 0x1; 1147f7caf6aSAndy Grover 1157f7caf6aSAndy Grover if (dev->transport->get_lbppbe) 1167f7caf6aSAndy Grover buf[13] = dev->transport->get_lbppbe(dev) & 0x0f; 1177f7caf6aSAndy Grover 1187f7caf6aSAndy Grover if (dev->transport->get_alignment_offset_lbas) { 1197f7caf6aSAndy Grover u16 lalba = dev->transport->get_alignment_offset_lbas(dev); 1207f7caf6aSAndy Grover buf[14] = (lalba >> 8) & 0x3f; 1217f7caf6aSAndy Grover buf[15] = lalba & 0xff; 1227f7caf6aSAndy Grover } 1237f7caf6aSAndy Grover 1241fd032eeSChristoph Hellwig /* 1251fd032eeSChristoph Hellwig * Set Thin Provisioning Enable bit following sbc3r22 in section 1261fd032eeSChristoph Hellwig * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled. 1271fd032eeSChristoph Hellwig */ 1280fd97ccfSChristoph Hellwig if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws) 1297f7caf6aSAndy Grover buf[14] |= 0x80; 1301fd032eeSChristoph Hellwig 131a50da144SPaolo Bonzini rbuf = transport_kmap_data_sg(cmd); 1328b4b0dcbSNicholas Bellinger if (rbuf) { 133a50da144SPaolo Bonzini memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); 1341fd032eeSChristoph Hellwig transport_kunmap_data_sg(cmd); 1358b4b0dcbSNicholas Bellinger } 1361fd032eeSChristoph Hellwig 1371fd032eeSChristoph Hellwig target_complete_cmd(cmd, GOOD); 1381fd032eeSChristoph Hellwig return 0; 1391fd032eeSChristoph Hellwig } 1401fd032eeSChristoph Hellwig 141972b29c8SRoland Dreier sector_t sbc_get_write_same_sectors(struct se_cmd *cmd) 1421fd032eeSChristoph Hellwig { 1431fd032eeSChristoph Hellwig u32 num_blocks; 1441fd032eeSChristoph Hellwig 1451fd032eeSChristoph Hellwig if (cmd->t_task_cdb[0] == WRITE_SAME) 1461fd032eeSChristoph Hellwig num_blocks = get_unaligned_be16(&cmd->t_task_cdb[7]); 1471fd032eeSChristoph Hellwig else if (cmd->t_task_cdb[0] == WRITE_SAME_16) 1481fd032eeSChristoph Hellwig num_blocks = get_unaligned_be32(&cmd->t_task_cdb[10]); 1491fd032eeSChristoph Hellwig else /* WRITE_SAME_32 via VARIABLE_LENGTH_CMD */ 1501fd032eeSChristoph Hellwig num_blocks = get_unaligned_be32(&cmd->t_task_cdb[28]); 1511fd032eeSChristoph Hellwig 1521fd032eeSChristoph Hellwig /* 1531fd032eeSChristoph Hellwig * Use the explicit range when non zero is supplied, otherwise calculate 1541fd032eeSChristoph Hellwig * the remaining range based on ->get_blocks() - starting LBA. 1551fd032eeSChristoph Hellwig */ 1566f974e8cSChristoph Hellwig if (num_blocks) 1576f974e8cSChristoph Hellwig return num_blocks; 1581fd032eeSChristoph Hellwig 1596f974e8cSChristoph Hellwig return cmd->se_dev->transport->get_blocks(cmd->se_dev) - 1606f974e8cSChristoph Hellwig cmd->t_task_lba + 1; 1611fd032eeSChristoph Hellwig } 162972b29c8SRoland Dreier EXPORT_SYMBOL(sbc_get_write_same_sectors); 1631fd032eeSChristoph Hellwig 164de103c93SChristoph Hellwig static sense_reason_t 1651920ed61SNicholas Bellinger sbc_emulate_noop(struct se_cmd *cmd) 1661a1ff38cSBernhard Kohl { 1671a1ff38cSBernhard Kohl target_complete_cmd(cmd, GOOD); 1681a1ff38cSBernhard Kohl return 0; 1691a1ff38cSBernhard Kohl } 1701a1ff38cSBernhard Kohl 171d6e0175cSChristoph Hellwig static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors) 172d6e0175cSChristoph Hellwig { 1730fd97ccfSChristoph Hellwig return cmd->se_dev->dev_attrib.block_size * sectors; 174d6e0175cSChristoph Hellwig } 175d6e0175cSChristoph Hellwig 176d6e0175cSChristoph Hellwig static int sbc_check_valid_sectors(struct se_cmd *cmd) 177d6e0175cSChristoph Hellwig { 178d6e0175cSChristoph Hellwig struct se_device *dev = cmd->se_dev; 179d6e0175cSChristoph Hellwig unsigned long long end_lba; 180d6e0175cSChristoph Hellwig u32 sectors; 181d6e0175cSChristoph Hellwig 1820fd97ccfSChristoph Hellwig sectors = cmd->data_length / dev->dev_attrib.block_size; 183d6e0175cSChristoph Hellwig end_lba = dev->transport->get_blocks(dev) + 1; 184d6e0175cSChristoph Hellwig 185d6e0175cSChristoph Hellwig if (cmd->t_task_lba + sectors > end_lba) { 186d6e0175cSChristoph Hellwig pr_err("target: lba %llu, sectors %u exceeds end lba %llu\n", 187d6e0175cSChristoph Hellwig cmd->t_task_lba, sectors, end_lba); 188d6e0175cSChristoph Hellwig return -EINVAL; 189d6e0175cSChristoph Hellwig } 190d6e0175cSChristoph Hellwig 191d6e0175cSChristoph Hellwig return 0; 192d6e0175cSChristoph Hellwig } 193d6e0175cSChristoph Hellwig 194d6e0175cSChristoph Hellwig static inline u32 transport_get_sectors_6(unsigned char *cdb) 195d6e0175cSChristoph Hellwig { 196d6e0175cSChristoph Hellwig /* 197d6e0175cSChristoph Hellwig * Use 8-bit sector value. SBC-3 says: 198d6e0175cSChristoph Hellwig * 199d6e0175cSChristoph Hellwig * A TRANSFER LENGTH field set to zero specifies that 256 200d6e0175cSChristoph Hellwig * logical blocks shall be written. Any other value 201d6e0175cSChristoph Hellwig * specifies the number of logical blocks that shall be 202d6e0175cSChristoph Hellwig * written. 203d6e0175cSChristoph Hellwig */ 204d6e0175cSChristoph Hellwig return cdb[4] ? : 256; 205d6e0175cSChristoph Hellwig } 206d6e0175cSChristoph Hellwig 207d6e0175cSChristoph Hellwig static inline u32 transport_get_sectors_10(unsigned char *cdb) 208d6e0175cSChristoph Hellwig { 209d6e0175cSChristoph Hellwig return (u32)(cdb[7] << 8) + cdb[8]; 210d6e0175cSChristoph Hellwig } 211d6e0175cSChristoph Hellwig 212d6e0175cSChristoph Hellwig static inline u32 transport_get_sectors_12(unsigned char *cdb) 213d6e0175cSChristoph Hellwig { 214d6e0175cSChristoph Hellwig return (u32)(cdb[6] << 24) + (cdb[7] << 16) + (cdb[8] << 8) + cdb[9]; 215d6e0175cSChristoph Hellwig } 216d6e0175cSChristoph Hellwig 217d6e0175cSChristoph Hellwig static inline u32 transport_get_sectors_16(unsigned char *cdb) 218d6e0175cSChristoph Hellwig { 219d6e0175cSChristoph Hellwig return (u32)(cdb[10] << 24) + (cdb[11] << 16) + 220d6e0175cSChristoph Hellwig (cdb[12] << 8) + cdb[13]; 221d6e0175cSChristoph Hellwig } 222d6e0175cSChristoph Hellwig 223d6e0175cSChristoph Hellwig /* 224d6e0175cSChristoph Hellwig * Used for VARIABLE_LENGTH_CDB WRITE_32 and READ_32 variants 225d6e0175cSChristoph Hellwig */ 226d6e0175cSChristoph Hellwig static inline u32 transport_get_sectors_32(unsigned char *cdb) 227d6e0175cSChristoph Hellwig { 228d6e0175cSChristoph Hellwig return (u32)(cdb[28] << 24) + (cdb[29] << 16) + 229d6e0175cSChristoph Hellwig (cdb[30] << 8) + cdb[31]; 230d6e0175cSChristoph Hellwig 231d6e0175cSChristoph Hellwig } 232d6e0175cSChristoph Hellwig 233d6e0175cSChristoph Hellwig static inline u32 transport_lba_21(unsigned char *cdb) 234d6e0175cSChristoph Hellwig { 235d6e0175cSChristoph Hellwig return ((cdb[1] & 0x1f) << 16) | (cdb[2] << 8) | cdb[3]; 236d6e0175cSChristoph Hellwig } 237d6e0175cSChristoph Hellwig 238d6e0175cSChristoph Hellwig static inline u32 transport_lba_32(unsigned char *cdb) 239d6e0175cSChristoph Hellwig { 240d6e0175cSChristoph Hellwig return (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; 241d6e0175cSChristoph Hellwig } 242d6e0175cSChristoph Hellwig 243d6e0175cSChristoph Hellwig static inline unsigned long long transport_lba_64(unsigned char *cdb) 244d6e0175cSChristoph Hellwig { 245d6e0175cSChristoph Hellwig unsigned int __v1, __v2; 246d6e0175cSChristoph Hellwig 247d6e0175cSChristoph Hellwig __v1 = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; 248d6e0175cSChristoph Hellwig __v2 = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; 249d6e0175cSChristoph Hellwig 250d6e0175cSChristoph Hellwig return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32; 251d6e0175cSChristoph Hellwig } 252d6e0175cSChristoph Hellwig 253d6e0175cSChristoph Hellwig /* 254d6e0175cSChristoph Hellwig * For VARIABLE_LENGTH_CDB w/ 32 byte extended CDBs 255d6e0175cSChristoph Hellwig */ 256d6e0175cSChristoph Hellwig static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) 257d6e0175cSChristoph Hellwig { 258d6e0175cSChristoph Hellwig unsigned int __v1, __v2; 259d6e0175cSChristoph Hellwig 260d6e0175cSChristoph Hellwig __v1 = (cdb[12] << 24) | (cdb[13] << 16) | (cdb[14] << 8) | cdb[15]; 261d6e0175cSChristoph Hellwig __v2 = (cdb[16] << 24) | (cdb[17] << 16) | (cdb[18] << 8) | cdb[19]; 262d6e0175cSChristoph Hellwig 263d6e0175cSChristoph Hellwig return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32; 264d6e0175cSChristoph Hellwig } 265d6e0175cSChristoph Hellwig 266cd063befSNicholas Bellinger static sense_reason_t 267cd063befSNicholas Bellinger sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops) 268d6e0175cSChristoph Hellwig { 269972b29c8SRoland Dreier unsigned int sectors = sbc_get_write_same_sectors(cmd); 270773cbaf7SNicholas Bellinger 271d6e0175cSChristoph Hellwig if ((flags[0] & 0x04) || (flags[0] & 0x02)) { 272d6e0175cSChristoph Hellwig pr_err("WRITE_SAME PBDATA and LBDATA" 273d6e0175cSChristoph Hellwig " bits not supported for Block Discard" 274d6e0175cSChristoph Hellwig " Emulation\n"); 275cd063befSNicholas Bellinger return TCM_UNSUPPORTED_SCSI_OPCODE; 276d6e0175cSChristoph Hellwig } 277773cbaf7SNicholas Bellinger if (sectors > cmd->se_dev->dev_attrib.max_write_same_len) { 278773cbaf7SNicholas Bellinger pr_warn("WRITE_SAME sectors: %u exceeds max_write_same_len: %u\n", 279773cbaf7SNicholas Bellinger sectors, cmd->se_dev->dev_attrib.max_write_same_len); 280773cbaf7SNicholas Bellinger return TCM_INVALID_CDB_FIELD; 281773cbaf7SNicholas Bellinger } 2825cb770bfSRoland Dreier /* We always have ANC_SUP == 0 so setting ANCHOR is always an error */ 2835cb770bfSRoland Dreier if (flags[0] & 0x10) { 2845cb770bfSRoland Dreier pr_warn("WRITE SAME with ANCHOR not supported\n"); 2855cb770bfSRoland Dreier return TCM_INVALID_CDB_FIELD; 2865cb770bfSRoland Dreier } 287d6e0175cSChristoph Hellwig /* 288cd063befSNicholas Bellinger * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting 289cd063befSNicholas Bellinger * translated into block discard requests within backend code. 290d6e0175cSChristoph Hellwig */ 291cd063befSNicholas Bellinger if (flags[0] & 0x08) { 292cd063befSNicholas Bellinger if (!ops->execute_write_same_unmap) 293cd063befSNicholas Bellinger return TCM_UNSUPPORTED_SCSI_OPCODE; 294d6e0175cSChristoph Hellwig 295cd063befSNicholas Bellinger cmd->execute_cmd = ops->execute_write_same_unmap; 296cd063befSNicholas Bellinger return 0; 297cd063befSNicholas Bellinger } 298cd063befSNicholas Bellinger if (!ops->execute_write_same) 299cd063befSNicholas Bellinger return TCM_UNSUPPORTED_SCSI_OPCODE; 300cd063befSNicholas Bellinger 301cd063befSNicholas Bellinger cmd->execute_cmd = ops->execute_write_same; 302d6e0175cSChristoph Hellwig return 0; 303d6e0175cSChristoph Hellwig } 304d6e0175cSChristoph Hellwig 305a6b0133cSNicholas Bellinger static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd) 306d6e0175cSChristoph Hellwig { 307d6e0175cSChristoph Hellwig unsigned char *buf, *addr; 308d6e0175cSChristoph Hellwig struct scatterlist *sg; 309d6e0175cSChristoph Hellwig unsigned int offset; 310a6b0133cSNicholas Bellinger sense_reason_t ret = TCM_NO_SENSE; 311a6b0133cSNicholas Bellinger int i, count; 312d6e0175cSChristoph Hellwig /* 313d6e0175cSChristoph Hellwig * From sbc3r22.pdf section 5.48 XDWRITEREAD (10) command 314d6e0175cSChristoph Hellwig * 315d6e0175cSChristoph Hellwig * 1) read the specified logical block(s); 316d6e0175cSChristoph Hellwig * 2) transfer logical blocks from the data-out buffer; 317d6e0175cSChristoph Hellwig * 3) XOR the logical blocks transferred from the data-out buffer with 318d6e0175cSChristoph Hellwig * the logical blocks read, storing the resulting XOR data in a buffer; 319d6e0175cSChristoph Hellwig * 4) if the DISABLE WRITE bit is set to zero, then write the logical 320d6e0175cSChristoph Hellwig * blocks transferred from the data-out buffer; and 321d6e0175cSChristoph Hellwig * 5) transfer the resulting XOR data to the data-in buffer. 322d6e0175cSChristoph Hellwig */ 323d6e0175cSChristoph Hellwig buf = kmalloc(cmd->data_length, GFP_KERNEL); 324d6e0175cSChristoph Hellwig if (!buf) { 325d6e0175cSChristoph Hellwig pr_err("Unable to allocate xor_callback buf\n"); 326a6b0133cSNicholas Bellinger return TCM_OUT_OF_RESOURCES; 327d6e0175cSChristoph Hellwig } 328d6e0175cSChristoph Hellwig /* 329d6e0175cSChristoph Hellwig * Copy the scatterlist WRITE buffer located at cmd->t_data_sg 330d6e0175cSChristoph Hellwig * into the locally allocated *buf 331d6e0175cSChristoph Hellwig */ 332d6e0175cSChristoph Hellwig sg_copy_to_buffer(cmd->t_data_sg, 333d6e0175cSChristoph Hellwig cmd->t_data_nents, 334d6e0175cSChristoph Hellwig buf, 335d6e0175cSChristoph Hellwig cmd->data_length); 336d6e0175cSChristoph Hellwig 337d6e0175cSChristoph Hellwig /* 338d6e0175cSChristoph Hellwig * Now perform the XOR against the BIDI read memory located at 339d6e0175cSChristoph Hellwig * cmd->t_mem_bidi_list 340d6e0175cSChristoph Hellwig */ 341d6e0175cSChristoph Hellwig 342d6e0175cSChristoph Hellwig offset = 0; 343d6e0175cSChristoph Hellwig for_each_sg(cmd->t_bidi_data_sg, sg, cmd->t_bidi_data_nents, count) { 344d6e0175cSChristoph Hellwig addr = kmap_atomic(sg_page(sg)); 345a6b0133cSNicholas Bellinger if (!addr) { 346a6b0133cSNicholas Bellinger ret = TCM_OUT_OF_RESOURCES; 347d6e0175cSChristoph Hellwig goto out; 348a6b0133cSNicholas Bellinger } 349d6e0175cSChristoph Hellwig 350d6e0175cSChristoph Hellwig for (i = 0; i < sg->length; i++) 351d6e0175cSChristoph Hellwig *(addr + sg->offset + i) ^= *(buf + offset + i); 352d6e0175cSChristoph Hellwig 353d6e0175cSChristoph Hellwig offset += sg->length; 354d6e0175cSChristoph Hellwig kunmap_atomic(addr); 355d6e0175cSChristoph Hellwig } 356d6e0175cSChristoph Hellwig 357d6e0175cSChristoph Hellwig out: 358d6e0175cSChristoph Hellwig kfree(buf); 359a6b0133cSNicholas Bellinger return ret; 360d6e0175cSChristoph Hellwig } 361d6e0175cSChristoph Hellwig 362a82a9538SNicholas Bellinger static sense_reason_t 363a82a9538SNicholas Bellinger sbc_execute_rw(struct se_cmd *cmd) 364a82a9538SNicholas Bellinger { 365a82a9538SNicholas Bellinger return cmd->execute_rw(cmd, cmd->t_data_sg, cmd->t_data_nents, 366a82a9538SNicholas Bellinger cmd->data_direction); 367a82a9538SNicholas Bellinger } 368a82a9538SNicholas Bellinger 36968ff9b9bSNicholas Bellinger static sense_reason_t compare_and_write_post(struct se_cmd *cmd) 37068ff9b9bSNicholas Bellinger { 37168ff9b9bSNicholas Bellinger struct se_device *dev = cmd->se_dev; 37268ff9b9bSNicholas Bellinger 373d8855c15SNicholas Bellinger /* 374d8855c15SNicholas Bellinger * Only set SCF_COMPARE_AND_WRITE_POST to force a response fall-through 375d8855c15SNicholas Bellinger * within target_complete_ok_work() if the command was successfully 376d8855c15SNicholas Bellinger * sent to the backend driver. 377d8855c15SNicholas Bellinger */ 378d8855c15SNicholas Bellinger spin_lock_irq(&cmd->t_state_lock); 379d8855c15SNicholas Bellinger if ((cmd->transport_state & CMD_T_SENT) && !cmd->scsi_status) 38068ff9b9bSNicholas Bellinger cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST; 381d8855c15SNicholas Bellinger spin_unlock_irq(&cmd->t_state_lock); 382d8855c15SNicholas Bellinger 38368ff9b9bSNicholas Bellinger /* 38468ff9b9bSNicholas Bellinger * Unlock ->caw_sem originally obtained during sbc_compare_and_write() 38568ff9b9bSNicholas Bellinger * before the original READ I/O submission. 38668ff9b9bSNicholas Bellinger */ 38768ff9b9bSNicholas Bellinger up(&dev->caw_sem); 38868ff9b9bSNicholas Bellinger 38968ff9b9bSNicholas Bellinger return TCM_NO_SENSE; 39068ff9b9bSNicholas Bellinger } 39168ff9b9bSNicholas Bellinger 39268ff9b9bSNicholas Bellinger static sense_reason_t compare_and_write_callback(struct se_cmd *cmd) 39368ff9b9bSNicholas Bellinger { 39468ff9b9bSNicholas Bellinger struct se_device *dev = cmd->se_dev; 39568ff9b9bSNicholas Bellinger struct scatterlist *write_sg = NULL, *sg; 396db60df88SNicholas Bellinger unsigned char *buf = NULL, *addr; 39768ff9b9bSNicholas Bellinger struct sg_mapping_iter m; 39868ff9b9bSNicholas Bellinger unsigned int offset = 0, len; 39968ff9b9bSNicholas Bellinger unsigned int nlbas = cmd->t_task_nolb; 40068ff9b9bSNicholas Bellinger unsigned int block_size = dev->dev_attrib.block_size; 40168ff9b9bSNicholas Bellinger unsigned int compare_len = (nlbas * block_size); 40268ff9b9bSNicholas Bellinger sense_reason_t ret = TCM_NO_SENSE; 40368ff9b9bSNicholas Bellinger int rc, i; 40468ff9b9bSNicholas Bellinger 405cf6d1f09SNicholas Bellinger /* 406cf6d1f09SNicholas Bellinger * Handle early failure in transport_generic_request_failure(), 407cf6d1f09SNicholas Bellinger * which will not have taken ->caw_mutex yet.. 408cf6d1f09SNicholas Bellinger */ 409cf6d1f09SNicholas Bellinger if (!cmd->t_data_sg || !cmd->t_bidi_data_sg) 410cf6d1f09SNicholas Bellinger return TCM_NO_SENSE; 411db60df88SNicholas Bellinger /* 412db60df88SNicholas Bellinger * Immediately exit + release dev->caw_sem if command has already 413db60df88SNicholas Bellinger * been failed with a non-zero SCSI status. 414db60df88SNicholas Bellinger */ 415db60df88SNicholas Bellinger if (cmd->scsi_status) { 416db60df88SNicholas Bellinger pr_err("compare_and_write_callback: non zero scsi_status:" 417db60df88SNicholas Bellinger " 0x%02x\n", cmd->scsi_status); 418db60df88SNicholas Bellinger goto out; 419db60df88SNicholas Bellinger } 420cf6d1f09SNicholas Bellinger 42168ff9b9bSNicholas Bellinger buf = kzalloc(cmd->data_length, GFP_KERNEL); 42268ff9b9bSNicholas Bellinger if (!buf) { 42368ff9b9bSNicholas Bellinger pr_err("Unable to allocate compare_and_write buf\n"); 424a2890087SNicholas Bellinger ret = TCM_OUT_OF_RESOURCES; 425a2890087SNicholas Bellinger goto out; 42668ff9b9bSNicholas Bellinger } 42768ff9b9bSNicholas Bellinger 42868ff9b9bSNicholas Bellinger write_sg = kzalloc(sizeof(struct scatterlist) * cmd->t_data_nents, 42968ff9b9bSNicholas Bellinger GFP_KERNEL); 43068ff9b9bSNicholas Bellinger if (!write_sg) { 43168ff9b9bSNicholas Bellinger pr_err("Unable to allocate compare_and_write sg\n"); 43268ff9b9bSNicholas Bellinger ret = TCM_OUT_OF_RESOURCES; 43368ff9b9bSNicholas Bellinger goto out; 43468ff9b9bSNicholas Bellinger } 43568ff9b9bSNicholas Bellinger /* 43668ff9b9bSNicholas Bellinger * Setup verify and write data payloads from total NumberLBAs. 43768ff9b9bSNicholas Bellinger */ 43868ff9b9bSNicholas Bellinger rc = sg_copy_to_buffer(cmd->t_data_sg, cmd->t_data_nents, buf, 43968ff9b9bSNicholas Bellinger cmd->data_length); 44068ff9b9bSNicholas Bellinger if (!rc) { 44168ff9b9bSNicholas Bellinger pr_err("sg_copy_to_buffer() failed for compare_and_write\n"); 44268ff9b9bSNicholas Bellinger ret = TCM_OUT_OF_RESOURCES; 44368ff9b9bSNicholas Bellinger goto out; 44468ff9b9bSNicholas Bellinger } 44568ff9b9bSNicholas Bellinger /* 44668ff9b9bSNicholas Bellinger * Compare against SCSI READ payload against verify payload 44768ff9b9bSNicholas Bellinger */ 44868ff9b9bSNicholas Bellinger for_each_sg(cmd->t_bidi_data_sg, sg, cmd->t_bidi_data_nents, i) { 44968ff9b9bSNicholas Bellinger addr = (unsigned char *)kmap_atomic(sg_page(sg)); 45068ff9b9bSNicholas Bellinger if (!addr) { 45168ff9b9bSNicholas Bellinger ret = TCM_OUT_OF_RESOURCES; 45268ff9b9bSNicholas Bellinger goto out; 45368ff9b9bSNicholas Bellinger } 45468ff9b9bSNicholas Bellinger 45568ff9b9bSNicholas Bellinger len = min(sg->length, compare_len); 45668ff9b9bSNicholas Bellinger 45768ff9b9bSNicholas Bellinger if (memcmp(addr, buf + offset, len)) { 45868ff9b9bSNicholas Bellinger pr_warn("Detected MISCOMPARE for addr: %p buf: %p\n", 45968ff9b9bSNicholas Bellinger addr, buf + offset); 46068ff9b9bSNicholas Bellinger kunmap_atomic(addr); 46168ff9b9bSNicholas Bellinger goto miscompare; 46268ff9b9bSNicholas Bellinger } 46368ff9b9bSNicholas Bellinger kunmap_atomic(addr); 46468ff9b9bSNicholas Bellinger 46568ff9b9bSNicholas Bellinger offset += len; 46668ff9b9bSNicholas Bellinger compare_len -= len; 46768ff9b9bSNicholas Bellinger if (!compare_len) 46868ff9b9bSNicholas Bellinger break; 46968ff9b9bSNicholas Bellinger } 47068ff9b9bSNicholas Bellinger 47168ff9b9bSNicholas Bellinger i = 0; 47268ff9b9bSNicholas Bellinger len = cmd->t_task_nolb * block_size; 47368ff9b9bSNicholas Bellinger sg_miter_start(&m, cmd->t_data_sg, cmd->t_data_nents, SG_MITER_TO_SG); 47468ff9b9bSNicholas Bellinger /* 47568ff9b9bSNicholas Bellinger * Currently assumes NoLB=1 and SGLs are PAGE_SIZE.. 47668ff9b9bSNicholas Bellinger */ 47768ff9b9bSNicholas Bellinger while (len) { 47868ff9b9bSNicholas Bellinger sg_miter_next(&m); 47968ff9b9bSNicholas Bellinger 48068ff9b9bSNicholas Bellinger if (block_size < PAGE_SIZE) { 48168ff9b9bSNicholas Bellinger sg_set_page(&write_sg[i], m.page, block_size, 48268ff9b9bSNicholas Bellinger block_size); 48368ff9b9bSNicholas Bellinger } else { 48468ff9b9bSNicholas Bellinger sg_miter_next(&m); 48568ff9b9bSNicholas Bellinger sg_set_page(&write_sg[i], m.page, block_size, 48668ff9b9bSNicholas Bellinger 0); 48768ff9b9bSNicholas Bellinger } 48868ff9b9bSNicholas Bellinger len -= block_size; 48968ff9b9bSNicholas Bellinger i++; 49068ff9b9bSNicholas Bellinger } 49168ff9b9bSNicholas Bellinger sg_miter_stop(&m); 49268ff9b9bSNicholas Bellinger /* 49368ff9b9bSNicholas Bellinger * Save the original SGL + nents values before updating to new 49468ff9b9bSNicholas Bellinger * assignments, to be released in transport_free_pages() -> 49568ff9b9bSNicholas Bellinger * transport_reset_sgl_orig() 49668ff9b9bSNicholas Bellinger */ 49768ff9b9bSNicholas Bellinger cmd->t_data_sg_orig = cmd->t_data_sg; 49868ff9b9bSNicholas Bellinger cmd->t_data_sg = write_sg; 49968ff9b9bSNicholas Bellinger cmd->t_data_nents_orig = cmd->t_data_nents; 50068ff9b9bSNicholas Bellinger cmd->t_data_nents = 1; 50168ff9b9bSNicholas Bellinger 50268ff9b9bSNicholas Bellinger cmd->sam_task_attr = MSG_HEAD_TAG; 50368ff9b9bSNicholas Bellinger cmd->transport_complete_callback = compare_and_write_post; 50468ff9b9bSNicholas Bellinger /* 50568ff9b9bSNicholas Bellinger * Now reset ->execute_cmd() to the normal sbc_execute_rw() handler 50668ff9b9bSNicholas Bellinger * for submitting the adjusted SGL to write instance user-data. 50768ff9b9bSNicholas Bellinger */ 50868ff9b9bSNicholas Bellinger cmd->execute_cmd = sbc_execute_rw; 50968ff9b9bSNicholas Bellinger 51068ff9b9bSNicholas Bellinger spin_lock_irq(&cmd->t_state_lock); 51168ff9b9bSNicholas Bellinger cmd->t_state = TRANSPORT_PROCESSING; 51268ff9b9bSNicholas Bellinger cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT; 51368ff9b9bSNicholas Bellinger spin_unlock_irq(&cmd->t_state_lock); 51468ff9b9bSNicholas Bellinger 51568ff9b9bSNicholas Bellinger __target_execute_cmd(cmd); 51668ff9b9bSNicholas Bellinger 51768ff9b9bSNicholas Bellinger kfree(buf); 51868ff9b9bSNicholas Bellinger return ret; 51968ff9b9bSNicholas Bellinger 52068ff9b9bSNicholas Bellinger miscompare: 52168ff9b9bSNicholas Bellinger pr_warn("Target/%s: Send MISCOMPARE check condition and sense\n", 52268ff9b9bSNicholas Bellinger dev->transport->name); 52368ff9b9bSNicholas Bellinger ret = TCM_MISCOMPARE_VERIFY; 52468ff9b9bSNicholas Bellinger out: 52568ff9b9bSNicholas Bellinger /* 52668ff9b9bSNicholas Bellinger * In the MISCOMPARE or failure case, unlock ->caw_sem obtained in 52768ff9b9bSNicholas Bellinger * sbc_compare_and_write() before the original READ I/O submission. 52868ff9b9bSNicholas Bellinger */ 52968ff9b9bSNicholas Bellinger up(&dev->caw_sem); 53068ff9b9bSNicholas Bellinger kfree(write_sg); 53168ff9b9bSNicholas Bellinger kfree(buf); 53268ff9b9bSNicholas Bellinger return ret; 53368ff9b9bSNicholas Bellinger } 53468ff9b9bSNicholas Bellinger 53568ff9b9bSNicholas Bellinger static sense_reason_t 53668ff9b9bSNicholas Bellinger sbc_compare_and_write(struct se_cmd *cmd) 53768ff9b9bSNicholas Bellinger { 53868ff9b9bSNicholas Bellinger struct se_device *dev = cmd->se_dev; 53968ff9b9bSNicholas Bellinger sense_reason_t ret; 54068ff9b9bSNicholas Bellinger int rc; 54168ff9b9bSNicholas Bellinger /* 54268ff9b9bSNicholas Bellinger * Submit the READ first for COMPARE_AND_WRITE to perform the 54368ff9b9bSNicholas Bellinger * comparision using SGLs at cmd->t_bidi_data_sg.. 54468ff9b9bSNicholas Bellinger */ 54568ff9b9bSNicholas Bellinger rc = down_interruptible(&dev->caw_sem); 54668ff9b9bSNicholas Bellinger if ((rc != 0) || signal_pending(current)) { 54768ff9b9bSNicholas Bellinger cmd->transport_complete_callback = NULL; 54868ff9b9bSNicholas Bellinger return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 54968ff9b9bSNicholas Bellinger } 550b7191253SNicholas Bellinger /* 551b7191253SNicholas Bellinger * Reset cmd->data_length to individual block_size in order to not 552b7191253SNicholas Bellinger * confuse backend drivers that depend on this value matching the 553b7191253SNicholas Bellinger * size of the I/O being submitted. 554b7191253SNicholas Bellinger */ 555b7191253SNicholas Bellinger cmd->data_length = cmd->t_task_nolb * dev->dev_attrib.block_size; 55668ff9b9bSNicholas Bellinger 55768ff9b9bSNicholas Bellinger ret = cmd->execute_rw(cmd, cmd->t_bidi_data_sg, cmd->t_bidi_data_nents, 55868ff9b9bSNicholas Bellinger DMA_FROM_DEVICE); 55968ff9b9bSNicholas Bellinger if (ret) { 56068ff9b9bSNicholas Bellinger cmd->transport_complete_callback = NULL; 56168ff9b9bSNicholas Bellinger up(&dev->caw_sem); 56268ff9b9bSNicholas Bellinger return ret; 56368ff9b9bSNicholas Bellinger } 56468ff9b9bSNicholas Bellinger /* 56568ff9b9bSNicholas Bellinger * Unlock of dev->caw_sem to occur in compare_and_write_callback() 56668ff9b9bSNicholas Bellinger * upon MISCOMPARE, or in compare_and_write_done() upon completion 56768ff9b9bSNicholas Bellinger * of WRITE instance user-data. 56868ff9b9bSNicholas Bellinger */ 56968ff9b9bSNicholas Bellinger return TCM_NO_SENSE; 57068ff9b9bSNicholas Bellinger } 57168ff9b9bSNicholas Bellinger 572499bf77bSNicholas Bellinger static bool 573499bf77bSNicholas Bellinger sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, 574499bf77bSNicholas Bellinger u32 sectors) 575499bf77bSNicholas Bellinger { 576499bf77bSNicholas Bellinger if (!cmd->t_prot_sg || !cmd->t_prot_nents) 577499bf77bSNicholas Bellinger return true; 578499bf77bSNicholas Bellinger 579499bf77bSNicholas Bellinger switch (dev->dev_attrib.pi_prot_type) { 580499bf77bSNicholas Bellinger case TARGET_DIF_TYPE3_PROT: 581499bf77bSNicholas Bellinger if (!(cdb[1] & 0xe0)) 582499bf77bSNicholas Bellinger return true; 583499bf77bSNicholas Bellinger 584499bf77bSNicholas Bellinger cmd->reftag_seed = 0xffffffff; 585499bf77bSNicholas Bellinger break; 586499bf77bSNicholas Bellinger case TARGET_DIF_TYPE2_PROT: 587499bf77bSNicholas Bellinger if (cdb[1] & 0xe0) 588499bf77bSNicholas Bellinger return false; 589499bf77bSNicholas Bellinger 590499bf77bSNicholas Bellinger cmd->reftag_seed = cmd->t_task_lba; 591499bf77bSNicholas Bellinger break; 592499bf77bSNicholas Bellinger case TARGET_DIF_TYPE1_PROT: 593499bf77bSNicholas Bellinger if (!(cdb[1] & 0xe0)) 594499bf77bSNicholas Bellinger return true; 595499bf77bSNicholas Bellinger 596499bf77bSNicholas Bellinger cmd->reftag_seed = cmd->t_task_lba; 597499bf77bSNicholas Bellinger break; 598499bf77bSNicholas Bellinger case TARGET_DIF_TYPE0_PROT: 599499bf77bSNicholas Bellinger default: 600499bf77bSNicholas Bellinger return true; 601499bf77bSNicholas Bellinger } 602499bf77bSNicholas Bellinger 603499bf77bSNicholas Bellinger cmd->prot_type = dev->dev_attrib.pi_prot_type; 604499bf77bSNicholas Bellinger cmd->prot_length = dev->prot_length * sectors; 605499bf77bSNicholas Bellinger cmd->prot_handover = PROT_SEPERATED; 606499bf77bSNicholas Bellinger 607499bf77bSNicholas Bellinger return true; 608499bf77bSNicholas Bellinger } 609499bf77bSNicholas Bellinger 610de103c93SChristoph Hellwig sense_reason_t 611de103c93SChristoph Hellwig sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) 612d6e0175cSChristoph Hellwig { 613d6e0175cSChristoph Hellwig struct se_device *dev = cmd->se_dev; 614d6e0175cSChristoph Hellwig unsigned char *cdb = cmd->t_task_cdb; 6151fd032eeSChristoph Hellwig unsigned int size; 616d6e0175cSChristoph Hellwig u32 sectors = 0; 617de103c93SChristoph Hellwig sense_reason_t ret; 618d6e0175cSChristoph Hellwig 619d6e0175cSChristoph Hellwig switch (cdb[0]) { 620d6e0175cSChristoph Hellwig case READ_6: 621d6e0175cSChristoph Hellwig sectors = transport_get_sectors_6(cdb); 622d6e0175cSChristoph Hellwig cmd->t_task_lba = transport_lba_21(cdb); 623d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 624a82a9538SNicholas Bellinger cmd->execute_rw = ops->execute_rw; 625a82a9538SNicholas Bellinger cmd->execute_cmd = sbc_execute_rw; 626d6e0175cSChristoph Hellwig break; 627d6e0175cSChristoph Hellwig case READ_10: 628d6e0175cSChristoph Hellwig sectors = transport_get_sectors_10(cdb); 629d6e0175cSChristoph Hellwig cmd->t_task_lba = transport_lba_32(cdb); 630499bf77bSNicholas Bellinger 631499bf77bSNicholas Bellinger if (!sbc_check_prot(dev, cmd, cdb, sectors)) 632499bf77bSNicholas Bellinger return TCM_UNSUPPORTED_SCSI_OPCODE; 633499bf77bSNicholas Bellinger 634d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 635a82a9538SNicholas Bellinger cmd->execute_rw = ops->execute_rw; 636a82a9538SNicholas Bellinger cmd->execute_cmd = sbc_execute_rw; 637d6e0175cSChristoph Hellwig break; 638d6e0175cSChristoph Hellwig case READ_12: 639d6e0175cSChristoph Hellwig sectors = transport_get_sectors_12(cdb); 640d6e0175cSChristoph Hellwig cmd->t_task_lba = transport_lba_32(cdb); 641499bf77bSNicholas Bellinger 642499bf77bSNicholas Bellinger if (!sbc_check_prot(dev, cmd, cdb, sectors)) 643499bf77bSNicholas Bellinger return TCM_UNSUPPORTED_SCSI_OPCODE; 644499bf77bSNicholas Bellinger 645d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 646a82a9538SNicholas Bellinger cmd->execute_rw = ops->execute_rw; 647a82a9538SNicholas Bellinger cmd->execute_cmd = sbc_execute_rw; 648d6e0175cSChristoph Hellwig break; 649d6e0175cSChristoph Hellwig case READ_16: 650d6e0175cSChristoph Hellwig sectors = transport_get_sectors_16(cdb); 651d6e0175cSChristoph Hellwig cmd->t_task_lba = transport_lba_64(cdb); 652499bf77bSNicholas Bellinger 653499bf77bSNicholas Bellinger if (!sbc_check_prot(dev, cmd, cdb, sectors)) 654499bf77bSNicholas Bellinger return TCM_UNSUPPORTED_SCSI_OPCODE; 655499bf77bSNicholas Bellinger 656d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 657a82a9538SNicholas Bellinger cmd->execute_rw = ops->execute_rw; 658a82a9538SNicholas Bellinger cmd->execute_cmd = sbc_execute_rw; 659d6e0175cSChristoph Hellwig break; 660d6e0175cSChristoph Hellwig case WRITE_6: 661d6e0175cSChristoph Hellwig sectors = transport_get_sectors_6(cdb); 662d6e0175cSChristoph Hellwig cmd->t_task_lba = transport_lba_21(cdb); 663d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 664a82a9538SNicholas Bellinger cmd->execute_rw = ops->execute_rw; 665a82a9538SNicholas Bellinger cmd->execute_cmd = sbc_execute_rw; 666d6e0175cSChristoph Hellwig break; 667d6e0175cSChristoph Hellwig case WRITE_10: 668d6e0175cSChristoph Hellwig case WRITE_VERIFY: 669d6e0175cSChristoph Hellwig sectors = transport_get_sectors_10(cdb); 670d6e0175cSChristoph Hellwig cmd->t_task_lba = transport_lba_32(cdb); 671499bf77bSNicholas Bellinger 672499bf77bSNicholas Bellinger if (!sbc_check_prot(dev, cmd, cdb, sectors)) 673499bf77bSNicholas Bellinger return TCM_UNSUPPORTED_SCSI_OPCODE; 674499bf77bSNicholas Bellinger 675d6e0175cSChristoph Hellwig if (cdb[1] & 0x8) 676d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_FUA; 677d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 678a82a9538SNicholas Bellinger cmd->execute_rw = ops->execute_rw; 679a82a9538SNicholas Bellinger cmd->execute_cmd = sbc_execute_rw; 680d6e0175cSChristoph Hellwig break; 681d6e0175cSChristoph Hellwig case WRITE_12: 682d6e0175cSChristoph Hellwig sectors = transport_get_sectors_12(cdb); 683d6e0175cSChristoph Hellwig cmd->t_task_lba = transport_lba_32(cdb); 684499bf77bSNicholas Bellinger 685499bf77bSNicholas Bellinger if (!sbc_check_prot(dev, cmd, cdb, sectors)) 686499bf77bSNicholas Bellinger return TCM_UNSUPPORTED_SCSI_OPCODE; 687499bf77bSNicholas Bellinger 688d6e0175cSChristoph Hellwig if (cdb[1] & 0x8) 689d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_FUA; 690d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 691a82a9538SNicholas Bellinger cmd->execute_rw = ops->execute_rw; 692a82a9538SNicholas Bellinger cmd->execute_cmd = sbc_execute_rw; 693d6e0175cSChristoph Hellwig break; 694d6e0175cSChristoph Hellwig case WRITE_16: 695d6e0175cSChristoph Hellwig sectors = transport_get_sectors_16(cdb); 696d6e0175cSChristoph Hellwig cmd->t_task_lba = transport_lba_64(cdb); 697499bf77bSNicholas Bellinger 698499bf77bSNicholas Bellinger if (!sbc_check_prot(dev, cmd, cdb, sectors)) 699499bf77bSNicholas Bellinger return TCM_UNSUPPORTED_SCSI_OPCODE; 700499bf77bSNicholas Bellinger 701d6e0175cSChristoph Hellwig if (cdb[1] & 0x8) 702d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_FUA; 703d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 704a82a9538SNicholas Bellinger cmd->execute_rw = ops->execute_rw; 705a82a9538SNicholas Bellinger cmd->execute_cmd = sbc_execute_rw; 706d6e0175cSChristoph Hellwig break; 707d6e0175cSChristoph Hellwig case XDWRITEREAD_10: 708de103c93SChristoph Hellwig if (cmd->data_direction != DMA_TO_DEVICE || 709d6e0175cSChristoph Hellwig !(cmd->se_cmd_flags & SCF_BIDI)) 710de103c93SChristoph Hellwig return TCM_INVALID_CDB_FIELD; 711d6e0175cSChristoph Hellwig sectors = transport_get_sectors_10(cdb); 712d6e0175cSChristoph Hellwig 713d6e0175cSChristoph Hellwig cmd->t_task_lba = transport_lba_32(cdb); 714d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 715d6e0175cSChristoph Hellwig 716d6e0175cSChristoph Hellwig /* 717d6e0175cSChristoph Hellwig * Setup BIDI XOR callback to be run after I/O completion. 718d6e0175cSChristoph Hellwig */ 719a82a9538SNicholas Bellinger cmd->execute_rw = ops->execute_rw; 720a82a9538SNicholas Bellinger cmd->execute_cmd = sbc_execute_rw; 721d6e0175cSChristoph Hellwig cmd->transport_complete_callback = &xdreadwrite_callback; 722d6e0175cSChristoph Hellwig if (cdb[1] & 0x8) 723d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_FUA; 724d6e0175cSChristoph Hellwig break; 725d6e0175cSChristoph Hellwig case VARIABLE_LENGTH_CMD: 726d6e0175cSChristoph Hellwig { 727d6e0175cSChristoph Hellwig u16 service_action = get_unaligned_be16(&cdb[8]); 728d6e0175cSChristoph Hellwig switch (service_action) { 729d6e0175cSChristoph Hellwig case XDWRITEREAD_32: 730d6e0175cSChristoph Hellwig sectors = transport_get_sectors_32(cdb); 731d6e0175cSChristoph Hellwig 732d6e0175cSChristoph Hellwig /* 733d6e0175cSChristoph Hellwig * Use WRITE_32 and READ_32 opcodes for the emulated 734d6e0175cSChristoph Hellwig * XDWRITE_READ_32 logic. 735d6e0175cSChristoph Hellwig */ 736d6e0175cSChristoph Hellwig cmd->t_task_lba = transport_lba_64_ext(cdb); 737d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 738d6e0175cSChristoph Hellwig 739d6e0175cSChristoph Hellwig /* 740d6e0175cSChristoph Hellwig * Setup BIDI XOR callback to be run during after I/O 741d6e0175cSChristoph Hellwig * completion. 742d6e0175cSChristoph Hellwig */ 743a82a9538SNicholas Bellinger cmd->execute_rw = ops->execute_rw; 744a82a9538SNicholas Bellinger cmd->execute_cmd = sbc_execute_rw; 745d6e0175cSChristoph Hellwig cmd->transport_complete_callback = &xdreadwrite_callback; 746d6e0175cSChristoph Hellwig if (cdb[1] & 0x8) 747d6e0175cSChristoph Hellwig cmd->se_cmd_flags |= SCF_FUA; 748d6e0175cSChristoph Hellwig break; 749d6e0175cSChristoph Hellwig case WRITE_SAME_32: 750d6e0175cSChristoph Hellwig sectors = transport_get_sectors_32(cdb); 751d6e0175cSChristoph Hellwig if (!sectors) { 752d6e0175cSChristoph Hellwig pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not" 753d6e0175cSChristoph Hellwig " supported\n"); 754de103c93SChristoph Hellwig return TCM_INVALID_CDB_FIELD; 755d6e0175cSChristoph Hellwig } 756d6e0175cSChristoph Hellwig 7571fd032eeSChristoph Hellwig size = sbc_get_size(cmd, 1); 758d6e0175cSChristoph Hellwig cmd->t_task_lba = get_unaligned_be64(&cdb[12]); 759d6e0175cSChristoph Hellwig 760cd063befSNicholas Bellinger ret = sbc_setup_write_same(cmd, &cdb[10], ops); 7616b64e1feSDan Carpenter if (ret) 762cd063befSNicholas Bellinger return ret; 763d6e0175cSChristoph Hellwig break; 764d6e0175cSChristoph Hellwig default: 765d6e0175cSChristoph Hellwig pr_err("VARIABLE_LENGTH_CMD service action" 766d6e0175cSChristoph Hellwig " 0x%04x not supported\n", service_action); 767de103c93SChristoph Hellwig return TCM_UNSUPPORTED_SCSI_OPCODE; 768d6e0175cSChristoph Hellwig } 769d6e0175cSChristoph Hellwig break; 770d6e0175cSChristoph Hellwig } 77168ff9b9bSNicholas Bellinger case COMPARE_AND_WRITE: 77268ff9b9bSNicholas Bellinger sectors = cdb[13]; 77368ff9b9bSNicholas Bellinger /* 77468ff9b9bSNicholas Bellinger * Currently enforce COMPARE_AND_WRITE for a single sector 77568ff9b9bSNicholas Bellinger */ 77668ff9b9bSNicholas Bellinger if (sectors > 1) { 77768ff9b9bSNicholas Bellinger pr_err("COMPARE_AND_WRITE contains NoLB: %u greater" 77868ff9b9bSNicholas Bellinger " than 1\n", sectors); 77968ff9b9bSNicholas Bellinger return TCM_INVALID_CDB_FIELD; 78068ff9b9bSNicholas Bellinger } 78168ff9b9bSNicholas Bellinger /* 78268ff9b9bSNicholas Bellinger * Double size because we have two buffers, note that 78368ff9b9bSNicholas Bellinger * zero is not an error.. 78468ff9b9bSNicholas Bellinger */ 78568ff9b9bSNicholas Bellinger size = 2 * sbc_get_size(cmd, sectors); 78668ff9b9bSNicholas Bellinger cmd->t_task_lba = get_unaligned_be64(&cdb[2]); 78768ff9b9bSNicholas Bellinger cmd->t_task_nolb = sectors; 78868ff9b9bSNicholas Bellinger cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB | SCF_COMPARE_AND_WRITE; 78968ff9b9bSNicholas Bellinger cmd->execute_rw = ops->execute_rw; 79068ff9b9bSNicholas Bellinger cmd->execute_cmd = sbc_compare_and_write; 79168ff9b9bSNicholas Bellinger cmd->transport_complete_callback = compare_and_write_callback; 79268ff9b9bSNicholas Bellinger break; 793d6e0175cSChristoph Hellwig case READ_CAPACITY: 7941fd032eeSChristoph Hellwig size = READ_CAP_LEN; 7951fd032eeSChristoph Hellwig cmd->execute_cmd = sbc_emulate_readcapacity; 796d6e0175cSChristoph Hellwig break; 797d6e0175cSChristoph Hellwig case SERVICE_ACTION_IN: 798d6e0175cSChristoph Hellwig switch (cmd->t_task_cdb[1] & 0x1f) { 799d6e0175cSChristoph Hellwig case SAI_READ_CAPACITY_16: 8001fd032eeSChristoph Hellwig cmd->execute_cmd = sbc_emulate_readcapacity_16; 801d6e0175cSChristoph Hellwig break; 802c66094bfSHannes Reinecke case SAI_REPORT_REFERRALS: 803c66094bfSHannes Reinecke cmd->execute_cmd = target_emulate_report_referrals; 804c66094bfSHannes Reinecke break; 805d6e0175cSChristoph Hellwig default: 806d6e0175cSChristoph Hellwig pr_err("Unsupported SA: 0x%02x\n", 807d6e0175cSChristoph Hellwig cmd->t_task_cdb[1] & 0x1f); 808de103c93SChristoph Hellwig return TCM_INVALID_CDB_FIELD; 809d6e0175cSChristoph Hellwig } 8101fd032eeSChristoph Hellwig size = (cdb[10] << 24) | (cdb[11] << 16) | 811d6e0175cSChristoph Hellwig (cdb[12] << 8) | cdb[13]; 812d6e0175cSChristoph Hellwig break; 813d6e0175cSChristoph Hellwig case SYNCHRONIZE_CACHE: 814d6e0175cSChristoph Hellwig case SYNCHRONIZE_CACHE_16: 815882e3f8eSHannes Reinecke if (!ops->execute_sync_cache) { 816882e3f8eSHannes Reinecke size = 0; 817882e3f8eSHannes Reinecke cmd->execute_cmd = sbc_emulate_noop; 818882e3f8eSHannes Reinecke break; 819882e3f8eSHannes Reinecke } 820ad67f0d9SChristoph Hellwig 821d6e0175cSChristoph Hellwig /* 822d6e0175cSChristoph Hellwig * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE 823d6e0175cSChristoph Hellwig */ 824d6e0175cSChristoph Hellwig if (cdb[0] == SYNCHRONIZE_CACHE) { 825d6e0175cSChristoph Hellwig sectors = transport_get_sectors_10(cdb); 826d6e0175cSChristoph Hellwig cmd->t_task_lba = transport_lba_32(cdb); 827d6e0175cSChristoph Hellwig } else { 828d6e0175cSChristoph Hellwig sectors = transport_get_sectors_16(cdb); 829d6e0175cSChristoph Hellwig cmd->t_task_lba = transport_lba_64(cdb); 830d6e0175cSChristoph Hellwig } 831d6e0175cSChristoph Hellwig 8321fd032eeSChristoph Hellwig size = sbc_get_size(cmd, sectors); 833d6e0175cSChristoph Hellwig 834d6e0175cSChristoph Hellwig /* 835d6e0175cSChristoph Hellwig * Check to ensure that LBA + Range does not exceed past end of 836d6e0175cSChristoph Hellwig * device for IBLOCK and FILEIO ->do_sync_cache() backend calls 837d6e0175cSChristoph Hellwig */ 838d6e0175cSChristoph Hellwig if (cmd->t_task_lba || sectors) { 839d6e0175cSChristoph Hellwig if (sbc_check_valid_sectors(cmd) < 0) 84033633676SRoland Dreier return TCM_ADDRESS_OUT_OF_RANGE; 841d6e0175cSChristoph Hellwig } 842ad67f0d9SChristoph Hellwig cmd->execute_cmd = ops->execute_sync_cache; 843d6e0175cSChristoph Hellwig break; 844d6e0175cSChristoph Hellwig case UNMAP: 84514150a6bSChristoph Hellwig if (!ops->execute_unmap) 846de103c93SChristoph Hellwig return TCM_UNSUPPORTED_SCSI_OPCODE; 84714150a6bSChristoph Hellwig 8481fd032eeSChristoph Hellwig size = get_unaligned_be16(&cdb[7]); 84914150a6bSChristoph Hellwig cmd->execute_cmd = ops->execute_unmap; 850d6e0175cSChristoph Hellwig break; 851d6e0175cSChristoph Hellwig case WRITE_SAME_16: 852d6e0175cSChristoph Hellwig sectors = transport_get_sectors_16(cdb); 853d6e0175cSChristoph Hellwig if (!sectors) { 854d6e0175cSChristoph Hellwig pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); 855de103c93SChristoph Hellwig return TCM_INVALID_CDB_FIELD; 856d6e0175cSChristoph Hellwig } 857d6e0175cSChristoph Hellwig 8581fd032eeSChristoph Hellwig size = sbc_get_size(cmd, 1); 859d6e0175cSChristoph Hellwig cmd->t_task_lba = get_unaligned_be64(&cdb[2]); 860d6e0175cSChristoph Hellwig 861cd063befSNicholas Bellinger ret = sbc_setup_write_same(cmd, &cdb[1], ops); 8626b64e1feSDan Carpenter if (ret) 863cd063befSNicholas Bellinger return ret; 864d6e0175cSChristoph Hellwig break; 865d6e0175cSChristoph Hellwig case WRITE_SAME: 866d6e0175cSChristoph Hellwig sectors = transport_get_sectors_10(cdb); 867d6e0175cSChristoph Hellwig if (!sectors) { 868d6e0175cSChristoph Hellwig pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); 869de103c93SChristoph Hellwig return TCM_INVALID_CDB_FIELD; 870d6e0175cSChristoph Hellwig } 871d6e0175cSChristoph Hellwig 8721fd032eeSChristoph Hellwig size = sbc_get_size(cmd, 1); 873d6e0175cSChristoph Hellwig cmd->t_task_lba = get_unaligned_be32(&cdb[2]); 874d6e0175cSChristoph Hellwig 875d6e0175cSChristoph Hellwig /* 876d6e0175cSChristoph Hellwig * Follow sbcr26 with WRITE_SAME (10) and check for the existence 877d6e0175cSChristoph Hellwig * of byte 1 bit 3 UNMAP instead of original reserved field 878d6e0175cSChristoph Hellwig */ 879cd063befSNicholas Bellinger ret = sbc_setup_write_same(cmd, &cdb[1], ops); 8806b64e1feSDan Carpenter if (ret) 881cd063befSNicholas Bellinger return ret; 882d6e0175cSChristoph Hellwig break; 883d6e0175cSChristoph Hellwig case VERIFY: 8841fd032eeSChristoph Hellwig size = 0; 8851920ed61SNicholas Bellinger cmd->execute_cmd = sbc_emulate_noop; 886d6e0175cSChristoph Hellwig break; 8871a1ff38cSBernhard Kohl case REZERO_UNIT: 8881a1ff38cSBernhard Kohl case SEEK_6: 8891a1ff38cSBernhard Kohl case SEEK_10: 8901a1ff38cSBernhard Kohl /* 8911a1ff38cSBernhard Kohl * There are still clients out there which use these old SCSI-2 8921a1ff38cSBernhard Kohl * commands. This mainly happens when running VMs with legacy 8931a1ff38cSBernhard Kohl * guest systems, connected via SCSI command pass-through to 8941a1ff38cSBernhard Kohl * iSCSI targets. Make them happy and return status GOOD. 8951a1ff38cSBernhard Kohl */ 8961a1ff38cSBernhard Kohl size = 0; 8971a1ff38cSBernhard Kohl cmd->execute_cmd = sbc_emulate_noop; 8981a1ff38cSBernhard Kohl break; 899d6e0175cSChristoph Hellwig default: 9001fd032eeSChristoph Hellwig ret = spc_parse_cdb(cmd, &size); 901d6e0175cSChristoph Hellwig if (ret) 902d6e0175cSChristoph Hellwig return ret; 903d6e0175cSChristoph Hellwig } 904d6e0175cSChristoph Hellwig 905d6e0175cSChristoph Hellwig /* reject any command that we don't have a handler for */ 906d6e0175cSChristoph Hellwig if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->execute_cmd) 907de103c93SChristoph Hellwig return TCM_UNSUPPORTED_SCSI_OPCODE; 908d6e0175cSChristoph Hellwig 909d6e0175cSChristoph Hellwig if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { 9101fd032eeSChristoph Hellwig unsigned long long end_lba; 9111fd032eeSChristoph Hellwig 9120fd97ccfSChristoph Hellwig if (sectors > dev->dev_attrib.fabric_max_sectors) { 913d6e0175cSChristoph Hellwig printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" 914d6e0175cSChristoph Hellwig " big sectors %u exceeds fabric_max_sectors:" 915d6e0175cSChristoph Hellwig " %u\n", cdb[0], sectors, 9160fd97ccfSChristoph Hellwig dev->dev_attrib.fabric_max_sectors); 917de103c93SChristoph Hellwig return TCM_INVALID_CDB_FIELD; 918d6e0175cSChristoph Hellwig } 9190fd97ccfSChristoph Hellwig if (sectors > dev->dev_attrib.hw_max_sectors) { 920d6e0175cSChristoph Hellwig printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" 921d6e0175cSChristoph Hellwig " big sectors %u exceeds backend hw_max_sectors:" 922d6e0175cSChristoph Hellwig " %u\n", cdb[0], sectors, 9230fd97ccfSChristoph Hellwig dev->dev_attrib.hw_max_sectors); 924de103c93SChristoph Hellwig return TCM_INVALID_CDB_FIELD; 925d6e0175cSChristoph Hellwig } 926d6e0175cSChristoph Hellwig 9271fd032eeSChristoph Hellwig end_lba = dev->transport->get_blocks(dev) + 1; 9281fd032eeSChristoph Hellwig if (cmd->t_task_lba + sectors > end_lba) { 9291fd032eeSChristoph Hellwig pr_err("cmd exceeds last lba %llu " 9301fd032eeSChristoph Hellwig "(lba %llu, sectors %u)\n", 9311fd032eeSChristoph Hellwig end_lba, cmd->t_task_lba, sectors); 93209ceadc7SRoland Dreier return TCM_ADDRESS_OUT_OF_RANGE; 933d6e0175cSChristoph Hellwig } 934d6e0175cSChristoph Hellwig 93568ff9b9bSNicholas Bellinger if (!(cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE)) 9361fd032eeSChristoph Hellwig size = sbc_get_size(cmd, sectors); 9371fd032eeSChristoph Hellwig } 9381fd032eeSChristoph Hellwig 939de103c93SChristoph Hellwig return target_cmd_size_check(cmd, size); 940d6e0175cSChristoph Hellwig } 941d6e0175cSChristoph Hellwig EXPORT_SYMBOL(sbc_parse_cdb); 9426f23ac8aSChristoph Hellwig 9436f23ac8aSChristoph Hellwig u32 sbc_get_device_type(struct se_device *dev) 9446f23ac8aSChristoph Hellwig { 9456f23ac8aSChristoph Hellwig return TYPE_DISK; 9466f23ac8aSChristoph Hellwig } 9476f23ac8aSChristoph Hellwig EXPORT_SYMBOL(sbc_get_device_type); 94886d71829SAsias He 94986d71829SAsias He sense_reason_t 95086d71829SAsias He sbc_execute_unmap(struct se_cmd *cmd, 95186d71829SAsias He sense_reason_t (*do_unmap_fn)(struct se_cmd *, void *, 95286d71829SAsias He sector_t, sector_t), 95386d71829SAsias He void *priv) 95486d71829SAsias He { 95586d71829SAsias He struct se_device *dev = cmd->se_dev; 95686d71829SAsias He unsigned char *buf, *ptr = NULL; 95786d71829SAsias He sector_t lba; 95886d71829SAsias He int size; 95986d71829SAsias He u32 range; 96086d71829SAsias He sense_reason_t ret = 0; 96186d71829SAsias He int dl, bd_dl; 96286d71829SAsias He 96386d71829SAsias He /* We never set ANC_SUP */ 96486d71829SAsias He if (cmd->t_task_cdb[1]) 96586d71829SAsias He return TCM_INVALID_CDB_FIELD; 96686d71829SAsias He 96786d71829SAsias He if (cmd->data_length == 0) { 96886d71829SAsias He target_complete_cmd(cmd, SAM_STAT_GOOD); 96986d71829SAsias He return 0; 97086d71829SAsias He } 97186d71829SAsias He 97286d71829SAsias He if (cmd->data_length < 8) { 97386d71829SAsias He pr_warn("UNMAP parameter list length %u too small\n", 97486d71829SAsias He cmd->data_length); 97586d71829SAsias He return TCM_PARAMETER_LIST_LENGTH_ERROR; 97686d71829SAsias He } 97786d71829SAsias He 97886d71829SAsias He buf = transport_kmap_data_sg(cmd); 97986d71829SAsias He if (!buf) 98086d71829SAsias He return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 98186d71829SAsias He 98286d71829SAsias He dl = get_unaligned_be16(&buf[0]); 98386d71829SAsias He bd_dl = get_unaligned_be16(&buf[2]); 98486d71829SAsias He 98586d71829SAsias He size = cmd->data_length - 8; 98686d71829SAsias He if (bd_dl > size) 98786d71829SAsias He pr_warn("UNMAP parameter list length %u too small, ignoring bd_dl %u\n", 98886d71829SAsias He cmd->data_length, bd_dl); 98986d71829SAsias He else 99086d71829SAsias He size = bd_dl; 99186d71829SAsias He 99286d71829SAsias He if (size / 16 > dev->dev_attrib.max_unmap_block_desc_count) { 99386d71829SAsias He ret = TCM_INVALID_PARAMETER_LIST; 99486d71829SAsias He goto err; 99586d71829SAsias He } 99686d71829SAsias He 99786d71829SAsias He /* First UNMAP block descriptor starts at 8 byte offset */ 99886d71829SAsias He ptr = &buf[8]; 99986d71829SAsias He pr_debug("UNMAP: Sub: %s Using dl: %u bd_dl: %u size: %u" 100086d71829SAsias He " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr); 100186d71829SAsias He 100286d71829SAsias He while (size >= 16) { 100386d71829SAsias He lba = get_unaligned_be64(&ptr[0]); 100486d71829SAsias He range = get_unaligned_be32(&ptr[8]); 100586d71829SAsias He pr_debug("UNMAP: Using lba: %llu and range: %u\n", 100686d71829SAsias He (unsigned long long)lba, range); 100786d71829SAsias He 100886d71829SAsias He if (range > dev->dev_attrib.max_unmap_lba_count) { 100986d71829SAsias He ret = TCM_INVALID_PARAMETER_LIST; 101086d71829SAsias He goto err; 101186d71829SAsias He } 101286d71829SAsias He 101386d71829SAsias He if (lba + range > dev->transport->get_blocks(dev) + 1) { 101486d71829SAsias He ret = TCM_ADDRESS_OUT_OF_RANGE; 101586d71829SAsias He goto err; 101686d71829SAsias He } 101786d71829SAsias He 101886d71829SAsias He ret = do_unmap_fn(cmd, priv, lba, range); 101986d71829SAsias He if (ret) 102086d71829SAsias He goto err; 102186d71829SAsias He 102286d71829SAsias He ptr += 16; 102386d71829SAsias He size -= 16; 102486d71829SAsias He } 102586d71829SAsias He 102686d71829SAsias He err: 102786d71829SAsias He transport_kunmap_data_sg(cmd); 102886d71829SAsias He if (!ret) 102986d71829SAsias He target_complete_cmd(cmd, GOOD); 103086d71829SAsias He return ret; 103186d71829SAsias He } 103286d71829SAsias He EXPORT_SYMBOL(sbc_execute_unmap); 103341861fa8SNicholas Bellinger 103441861fa8SNicholas Bellinger static sense_reason_t 103541861fa8SNicholas Bellinger sbc_dif_v1_verify(struct se_device *dev, struct se_dif_v1_tuple *sdt, 103641861fa8SNicholas Bellinger const void *p, sector_t sector, unsigned int ei_lba) 103741861fa8SNicholas Bellinger { 103841861fa8SNicholas Bellinger int block_size = dev->dev_attrib.block_size; 103941861fa8SNicholas Bellinger __be16 csum; 104041861fa8SNicholas Bellinger 104141861fa8SNicholas Bellinger csum = cpu_to_be16(crc_t10dif(p, block_size)); 104241861fa8SNicholas Bellinger 104341861fa8SNicholas Bellinger if (sdt->guard_tag != csum) { 104441861fa8SNicholas Bellinger pr_err("DIFv1 checksum failed on sector %llu guard tag 0x%04x" 104541861fa8SNicholas Bellinger " csum 0x%04x\n", (unsigned long long)sector, 104641861fa8SNicholas Bellinger be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum)); 104741861fa8SNicholas Bellinger return TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED; 104841861fa8SNicholas Bellinger } 104941861fa8SNicholas Bellinger 105041861fa8SNicholas Bellinger if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE1_PROT && 105141861fa8SNicholas Bellinger be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) { 105241861fa8SNicholas Bellinger pr_err("DIFv1 Type 1 reference failed on sector: %llu tag: 0x%08x" 105341861fa8SNicholas Bellinger " sector MSB: 0x%08x\n", (unsigned long long)sector, 105441861fa8SNicholas Bellinger be32_to_cpu(sdt->ref_tag), (u32)(sector & 0xffffffff)); 105541861fa8SNicholas Bellinger return TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED; 105641861fa8SNicholas Bellinger } 105741861fa8SNicholas Bellinger 105841861fa8SNicholas Bellinger if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE2_PROT && 105941861fa8SNicholas Bellinger be32_to_cpu(sdt->ref_tag) != ei_lba) { 106041861fa8SNicholas Bellinger pr_err("DIFv1 Type 2 reference failed on sector: %llu tag: 0x%08x" 106141861fa8SNicholas Bellinger " ei_lba: 0x%08x\n", (unsigned long long)sector, 106241861fa8SNicholas Bellinger be32_to_cpu(sdt->ref_tag), ei_lba); 106341861fa8SNicholas Bellinger return TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED; 106441861fa8SNicholas Bellinger } 106541861fa8SNicholas Bellinger 106641861fa8SNicholas Bellinger return 0; 106741861fa8SNicholas Bellinger } 106841861fa8SNicholas Bellinger 106941861fa8SNicholas Bellinger static void 107041861fa8SNicholas Bellinger sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read, 107141861fa8SNicholas Bellinger struct scatterlist *sg, int sg_off) 107241861fa8SNicholas Bellinger { 107341861fa8SNicholas Bellinger struct se_device *dev = cmd->se_dev; 107441861fa8SNicholas Bellinger struct scatterlist *psg; 107541861fa8SNicholas Bellinger void *paddr, *addr; 107641861fa8SNicholas Bellinger unsigned int i, len, left; 107710762e80SNicholas Bellinger unsigned int offset = sg_off; 107841861fa8SNicholas Bellinger 107941861fa8SNicholas Bellinger left = sectors * dev->prot_length; 108041861fa8SNicholas Bellinger 108141861fa8SNicholas Bellinger for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) { 108241861fa8SNicholas Bellinger 108341861fa8SNicholas Bellinger len = min(psg->length, left); 1084d6a65fdcSSagi Grimberg if (offset >= sg->length) { 1085d6a65fdcSSagi Grimberg sg = sg_next(sg); 1086d6a65fdcSSagi Grimberg offset = 0; 1087d6a65fdcSSagi Grimberg } 1088d6a65fdcSSagi Grimberg 108941861fa8SNicholas Bellinger paddr = kmap_atomic(sg_page(psg)) + psg->offset; 109010762e80SNicholas Bellinger addr = kmap_atomic(sg_page(sg)) + sg->offset + offset; 109141861fa8SNicholas Bellinger 109241861fa8SNicholas Bellinger if (read) 109341861fa8SNicholas Bellinger memcpy(paddr, addr, len); 109441861fa8SNicholas Bellinger else 109541861fa8SNicholas Bellinger memcpy(addr, paddr, len); 109641861fa8SNicholas Bellinger 109741861fa8SNicholas Bellinger left -= len; 1098d6a65fdcSSagi Grimberg offset += len; 109941861fa8SNicholas Bellinger kunmap_atomic(paddr); 110041861fa8SNicholas Bellinger kunmap_atomic(addr); 110141861fa8SNicholas Bellinger } 110241861fa8SNicholas Bellinger } 110341861fa8SNicholas Bellinger 110441861fa8SNicholas Bellinger sense_reason_t 110541861fa8SNicholas Bellinger sbc_dif_verify_write(struct se_cmd *cmd, sector_t start, unsigned int sectors, 110641861fa8SNicholas Bellinger unsigned int ei_lba, struct scatterlist *sg, int sg_off) 110741861fa8SNicholas Bellinger { 110841861fa8SNicholas Bellinger struct se_device *dev = cmd->se_dev; 110941861fa8SNicholas Bellinger struct se_dif_v1_tuple *sdt; 111041861fa8SNicholas Bellinger struct scatterlist *dsg, *psg = cmd->t_prot_sg; 111141861fa8SNicholas Bellinger sector_t sector = start; 111241861fa8SNicholas Bellinger void *daddr, *paddr; 111341861fa8SNicholas Bellinger int i, j, offset = 0; 111441861fa8SNicholas Bellinger sense_reason_t rc; 111541861fa8SNicholas Bellinger 111641861fa8SNicholas Bellinger for_each_sg(cmd->t_data_sg, dsg, cmd->t_data_nents, i) { 111741861fa8SNicholas Bellinger daddr = kmap_atomic(sg_page(dsg)) + dsg->offset; 111841861fa8SNicholas Bellinger paddr = kmap_atomic(sg_page(psg)) + psg->offset; 111941861fa8SNicholas Bellinger 112041861fa8SNicholas Bellinger for (j = 0; j < dsg->length; j += dev->dev_attrib.block_size) { 112141861fa8SNicholas Bellinger 112241861fa8SNicholas Bellinger if (offset >= psg->length) { 112341861fa8SNicholas Bellinger kunmap_atomic(paddr); 112441861fa8SNicholas Bellinger psg = sg_next(psg); 112541861fa8SNicholas Bellinger paddr = kmap_atomic(sg_page(psg)) + psg->offset; 112641861fa8SNicholas Bellinger offset = 0; 112741861fa8SNicholas Bellinger } 112841861fa8SNicholas Bellinger 112941861fa8SNicholas Bellinger sdt = paddr + offset; 113041861fa8SNicholas Bellinger 113141861fa8SNicholas Bellinger pr_debug("DIF WRITE sector: %llu guard_tag: 0x%04x" 113241861fa8SNicholas Bellinger " app_tag: 0x%04x ref_tag: %u\n", 113341861fa8SNicholas Bellinger (unsigned long long)sector, sdt->guard_tag, 113441861fa8SNicholas Bellinger sdt->app_tag, be32_to_cpu(sdt->ref_tag)); 113541861fa8SNicholas Bellinger 113641861fa8SNicholas Bellinger rc = sbc_dif_v1_verify(dev, sdt, daddr + j, sector, 113741861fa8SNicholas Bellinger ei_lba); 113841861fa8SNicholas Bellinger if (rc) { 113941861fa8SNicholas Bellinger kunmap_atomic(paddr); 114041861fa8SNicholas Bellinger kunmap_atomic(daddr); 114176736db3SSagi Grimberg cmd->bad_sector = sector; 114241861fa8SNicholas Bellinger return rc; 114341861fa8SNicholas Bellinger } 114441861fa8SNicholas Bellinger 114541861fa8SNicholas Bellinger sector++; 114641861fa8SNicholas Bellinger ei_lba++; 114741861fa8SNicholas Bellinger offset += sizeof(struct se_dif_v1_tuple); 114841861fa8SNicholas Bellinger } 114941861fa8SNicholas Bellinger 115041861fa8SNicholas Bellinger kunmap_atomic(paddr); 115141861fa8SNicholas Bellinger kunmap_atomic(daddr); 115241861fa8SNicholas Bellinger } 115341861fa8SNicholas Bellinger sbc_dif_copy_prot(cmd, sectors, false, sg, sg_off); 115441861fa8SNicholas Bellinger 115541861fa8SNicholas Bellinger return 0; 115641861fa8SNicholas Bellinger } 115741861fa8SNicholas Bellinger EXPORT_SYMBOL(sbc_dif_verify_write); 115841861fa8SNicholas Bellinger 115941861fa8SNicholas Bellinger sense_reason_t 116041861fa8SNicholas Bellinger sbc_dif_verify_read(struct se_cmd *cmd, sector_t start, unsigned int sectors, 116141861fa8SNicholas Bellinger unsigned int ei_lba, struct scatterlist *sg, int sg_off) 116241861fa8SNicholas Bellinger { 116341861fa8SNicholas Bellinger struct se_device *dev = cmd->se_dev; 116441861fa8SNicholas Bellinger struct se_dif_v1_tuple *sdt; 116541861fa8SNicholas Bellinger struct scatterlist *dsg; 116641861fa8SNicholas Bellinger sector_t sector = start; 116741861fa8SNicholas Bellinger void *daddr, *paddr; 116841861fa8SNicholas Bellinger int i, j, offset = sg_off; 116941861fa8SNicholas Bellinger sense_reason_t rc; 117041861fa8SNicholas Bellinger 117141861fa8SNicholas Bellinger for_each_sg(cmd->t_data_sg, dsg, cmd->t_data_nents, i) { 117241861fa8SNicholas Bellinger daddr = kmap_atomic(sg_page(dsg)) + dsg->offset; 117341861fa8SNicholas Bellinger paddr = kmap_atomic(sg_page(sg)) + sg->offset; 117441861fa8SNicholas Bellinger 117541861fa8SNicholas Bellinger for (j = 0; j < dsg->length; j += dev->dev_attrib.block_size) { 117641861fa8SNicholas Bellinger 117741861fa8SNicholas Bellinger if (offset >= sg->length) { 117841861fa8SNicholas Bellinger kunmap_atomic(paddr); 117941861fa8SNicholas Bellinger sg = sg_next(sg); 118041861fa8SNicholas Bellinger paddr = kmap_atomic(sg_page(sg)) + sg->offset; 118141861fa8SNicholas Bellinger offset = 0; 118241861fa8SNicholas Bellinger } 118341861fa8SNicholas Bellinger 118441861fa8SNicholas Bellinger sdt = paddr + offset; 118541861fa8SNicholas Bellinger 118641861fa8SNicholas Bellinger pr_debug("DIF READ sector: %llu guard_tag: 0x%04x" 118741861fa8SNicholas Bellinger " app_tag: 0x%04x ref_tag: %u\n", 118841861fa8SNicholas Bellinger (unsigned long long)sector, sdt->guard_tag, 118941861fa8SNicholas Bellinger sdt->app_tag, be32_to_cpu(sdt->ref_tag)); 119041861fa8SNicholas Bellinger 119141861fa8SNicholas Bellinger if (sdt->app_tag == cpu_to_be16(0xffff)) { 119241861fa8SNicholas Bellinger sector++; 119341861fa8SNicholas Bellinger offset += sizeof(struct se_dif_v1_tuple); 119441861fa8SNicholas Bellinger continue; 119541861fa8SNicholas Bellinger } 119641861fa8SNicholas Bellinger 119741861fa8SNicholas Bellinger rc = sbc_dif_v1_verify(dev, sdt, daddr + j, sector, 119841861fa8SNicholas Bellinger ei_lba); 119941861fa8SNicholas Bellinger if (rc) { 120041861fa8SNicholas Bellinger kunmap_atomic(paddr); 120141861fa8SNicholas Bellinger kunmap_atomic(daddr); 120276736db3SSagi Grimberg cmd->bad_sector = sector; 120341861fa8SNicholas Bellinger return rc; 120441861fa8SNicholas Bellinger } 120541861fa8SNicholas Bellinger 120641861fa8SNicholas Bellinger sector++; 120741861fa8SNicholas Bellinger ei_lba++; 120841861fa8SNicholas Bellinger offset += sizeof(struct se_dif_v1_tuple); 120941861fa8SNicholas Bellinger } 121041861fa8SNicholas Bellinger 121141861fa8SNicholas Bellinger kunmap_atomic(paddr); 121241861fa8SNicholas Bellinger kunmap_atomic(daddr); 121341861fa8SNicholas Bellinger } 121441861fa8SNicholas Bellinger sbc_dif_copy_prot(cmd, sectors, true, sg, sg_off); 121541861fa8SNicholas Bellinger 121641861fa8SNicholas Bellinger return 0; 121741861fa8SNicholas Bellinger } 121841861fa8SNicholas Bellinger EXPORT_SYMBOL(sbc_dif_verify_read); 1219